source added
authorebelcrom <ebelcrom@gmail.com>
Sun, 28 Jan 2018 22:10:04 +0000 (23:10 +0100)
committerebelcrom <ebelcrom@gmail.com>
Sun, 28 Jan 2018 22:10:04 +0000 (23:10 +0100)
49 files changed:
.classpath [new file with mode: 0644]
.project [new file with mode: 0644]
.settings/org.eclipse.jdt.core.prefs [new file with mode: 0644]
AndroidManifest.xml [new file with mode: 0644]
bin/jarlist.cache [new file with mode: 0644]
external/switch.sh [new file with mode: 0644]
ic_launcher-web.png [new file with mode: 0644]
libs/android-support-v13.jar [new file with mode: 0644]
libs/android-support-v4.jar [new file with mode: 0644]
libs/jsch-0.1.54.jar [new file with mode: 0644]
proguard-project.txt [new file with mode: 0644]
project.properties [new file with mode: 0644]
res/drawable-hdpi/ic_action_name.png [new file with mode: 0644]
res/drawable-hdpi/ic_launcher.png [new file with mode: 0644]
res/drawable-mdpi/ic_action_name.png [new file with mode: 0644]
res/drawable-mdpi/ic_launcher.png [new file with mode: 0644]
res/drawable-xhdpi/ic_ab_back_holo_dark_am_act.png [new file with mode: 0644]
res/drawable-xhdpi/ic_ab_back_holo_dark_am_inact.png [new file with mode: 0644]
res/drawable-xhdpi/ic_ab_forward_holo_dark_am_act.png [new file with mode: 0644]
res/drawable-xhdpi/ic_ab_forward_holo_dark_am_inact.png [new file with mode: 0644]
res/drawable-xhdpi/ic_action_name.png [new file with mode: 0644]
res/drawable-xhdpi/ic_launcher.png [new file with mode: 0644]
res/drawable-xxhdpi/ic_action_name.png [new file with mode: 0644]
res/drawable-xxhdpi/ic_launcher.png [new file with mode: 0644]
res/drawable-xxhdpi/stat_notify_sync_act.png [new file with mode: 0644]
res/drawable-xxhdpi/stat_notify_sync_inact.png [new file with mode: 0644]
res/drawable/selector_back.xml [new file with mode: 0644]
res/drawable/selector_forward.xml [new file with mode: 0644]
res/drawable/selector_sync.xml [new file with mode: 0644]
res/layout/activity_main.xml [new file with mode: 0644]
res/layout/fragment_connection.xml [new file with mode: 0644]
res/layout/fragment_log.xml [new file with mode: 0644]
res/layout/fragment_main.xml [new file with mode: 0644]
res/layout/fragment_switch.xml [new file with mode: 0644]
res/menu/main.xml [new file with mode: 0644]
res/values-v11/styles.xml [new file with mode: 0644]
res/values-v14/styles.xml [new file with mode: 0644]
res/values-w820dp/dimens.xml [new file with mode: 0644]
res/values/dimens.xml [new file with mode: 0644]
res/values/strings.xml [new file with mode: 0644]
res/values/styles.xml [new file with mode: 0644]
res/xml/fragment_preference.xml [new file with mode: 0644]
src/org/duckdns/binomiant/ipremoteswitch/ConnectionFragment.java [new file with mode: 0644]
src/org/duckdns/binomiant/ipremoteswitch/LogFragment.java [new file with mode: 0644]
src/org/duckdns/binomiant/ipremoteswitch/MainActivity.java [new file with mode: 0644]
src/org/duckdns/binomiant/ipremoteswitch/SettingsActivity.java [new file with mode: 0644]
src/org/duckdns/binomiant/ipremoteswitch/SettingsData.java [new file with mode: 0644]
src/org/duckdns/binomiant/ipremoteswitch/SettingsFragment.java [new file with mode: 0644]
src/org/duckdns/binomiant/ipremoteswitch/SwitchFragment.java [new file with mode: 0644]

diff --git a/.classpath b/.classpath
new file mode 100644 (file)
index 0000000..7bc01d9
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+       <classpathentry kind="src" path="src"/>
+       <classpathentry kind="src" path="gen"/>
+       <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+       <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+       <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
+       <classpathentry kind="output" path="bin/classes"/>
+</classpath>
diff --git a/.project b/.project
new file mode 100644 (file)
index 0000000..a69828d
--- /dev/null
+++ b/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>IPRemoteSwitch</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>com.android.ide.eclipse.adt.ApkBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+       </natures>
+</projectDescription>
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
new file mode 100644 (file)
index 0000000..7341ab1
--- /dev/null
@@ -0,0 +1,11 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.7
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
new file mode 100644 (file)
index 0000000..b8f343d
--- /dev/null
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest package="org.duckdns.binomiant.ipremoteswitch"
+    android:versionCode="1"
+    android:versionName="1.0" xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <uses-sdk
+        android:minSdkVersion="22"
+        android:targetSdkVersion="22" />
+
+    <uses-permission android:name="android.permission.INTERNET"/>
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@android:style/Theme.Material" >
+        <activity
+            android:name=".MainActivity"
+            android:screenOrientation="portrait"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+                <activity
+            android:name=".PrefActivity"
+            android:label="@string/action_about" >
+        </activity>
+               <activity
+                   android:name=".SettingsActivity"
+                   android:label="@string/action_settings">
+               </activity>
+    </application>
+
+</manifest>
diff --git a/bin/jarlist.cache b/bin/jarlist.cache
new file mode 100644 (file)
index 0000000..0565465
--- /dev/null
@@ -0,0 +1,3 @@
+# cache for current jar dependency. DO NOT EDIT.
+# format is <lastModified> <length> <SHA-1> <path>
+# Encoding is UTF-8
diff --git a/external/switch.sh b/external/switch.sh
new file mode 100644 (file)
index 0000000..7ced8bb
--- /dev/null
@@ -0,0 +1,172 @@
+#!/bin/bash
+#
+# Arguments: <on|off|status>
+# Returns:   1 for ON, 2 for off, 0 for tests and -1/255 on errors
+#
+
+# settings
+PING_INTERVAL=1
+SWITCH_COUNT=60
+ACK_COUNT=3
+
+GPIO_PIN=18
+cmd=
+host=
+state=
+
+CMD_ON=on
+CMD_OFF=off
+CMD_STAT=status
+
+ARGS=2
+TOOL_DIR=/home/pi
+SWITCH_LOCK=/tmp/.switch.lock
+
+ERROR=-1
+ON=1
+OFF=2
+
+# put output to log file for debugging purposes
+set -x
+exec &> /tmp/switch.log
+
+# loggs error and exits
+# param1 is the message
+# param2 is a flag for lock file deletion
+error()
+{
+    logger "error: $1"
+    if [ -z $2 ]; then
+        rm -f $SWITCH_LOCK
+    fi
+    exit $ERROR
+}
+
+# cleans up on exit
+cleanup()
+{
+    rm -f $SWITCH_LOCK
+}
+
+# setup GPIO interface
+gpio_init()
+{
+    # set direction, pull etc.
+    echo $GPIO_PIN > /sys/class/gpio/export
+    sleep 1
+    echo out > /sys/class/gpio/gpio$GPIO_PIN/direction
+    echo 1 > /sys/class/gpio/gpio$GPIO_PIN/active_low
+}
+
+# simulates a push button action via GPIO
+gpio_push()
+{
+    # set signal
+    echo 1 > /sys/class/gpio/gpio$GPIO_PIN/value
+    # wait a second
+    sleep 1
+    # set signal back
+    echo 0 > /sys/class/gpio/gpio$GPIO_PIN/value
+}
+
+# exits with actual state
+# param1 is a exit flag
+status()
+{
+    ping -i $PING_INTERVAL -c $ACK_COUNT $host &>/dev/null
+    local res=$?
+    case $res in
+        0)
+            state=$ON
+            ;;
+        *)
+            state=$OFF
+            ;;
+    esac
+    if ! [ -z $1 ]; then
+        cleanup
+        exit $state
+    fi
+}
+
+# turns the machine on
+turn_on()
+{
+    status
+    if [ "$state" == "$OFF" ]; then
+        gpio_init
+        gpio_push
+        local counter=$(($SWITCH_COUNT/$ACK_COUNT))
+        while [ $counter -gt 0 ]; do
+            status
+            if [ "$state" == "$ON" ]; then
+                cleanup
+                exit $state
+            fi
+            let "counter-=1"
+        done
+    fi
+    cleanup
+    exit $state
+}
+
+# turns the machine on
+turn_off()
+{
+    status
+    if [ "$state" == "$ON" ]; then
+        gpio_init
+        gpio_push
+        local counter=$(($SWITCH_COUNT/$ACK_COUNT))
+        while [ $counter -gt 0 ]; do
+            status
+            if [ "$state" == "$OFF" ]; then
+                cleanup
+                exit $state
+            fi
+            let "counter-=1"
+        done
+    fi
+    cleanup
+    exit $state
+}
+
+# handles signals
+sig_handler()
+{
+    cleanup
+    exit
+}
+
+# test arguments
+if [ $# -ne $ARGS ]; then
+    error "invalid argument count $#" 0
+fi
+
+# test on parallel execution
+if [ -e $SWITCH_LOCK ]; then
+    error "lockfile exists" 0
+else
+    touch $SWITCH_LOCK
+fi
+
+# trap for signals
+trap 'sig_handler' SIGINT EXIT
+
+# execution
+cmd=$1
+host=$2
+case $cmd in
+    $CMD_ON)
+        turn_on
+        ;;
+    $CMD_OFF)
+        turn_off
+        ;;
+    $CMD_STAT)
+        status 1
+        ;;
+    *)
+        error "command $cmd not recognised"
+        ;;
+esac
diff --git a/ic_launcher-web.png b/ic_launcher-web.png
new file mode 100644 (file)
index 0000000..a18cbb4
Binary files /dev/null and b/ic_launcher-web.png differ
diff --git a/libs/android-support-v13.jar b/libs/android-support-v13.jar
new file mode 100644 (file)
index 0000000..a1b123a
Binary files /dev/null and b/libs/android-support-v13.jar differ
diff --git a/libs/android-support-v4.jar b/libs/android-support-v4.jar
new file mode 100644 (file)
index 0000000..2ff47f4
Binary files /dev/null and b/libs/android-support-v4.jar differ
diff --git a/libs/jsch-0.1.54.jar b/libs/jsch-0.1.54.jar
new file mode 100644 (file)
index 0000000..1372c8e
Binary files /dev/null and b/libs/jsch-0.1.54.jar differ
diff --git a/proguard-project.txt b/proguard-project.txt
new file mode 100644 (file)
index 0000000..f2fe155
--- /dev/null
@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
diff --git a/project.properties b/project.properties
new file mode 100644 (file)
index 0000000..00cf62b
--- /dev/null
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-22
diff --git a/res/drawable-hdpi/ic_action_name.png b/res/drawable-hdpi/ic_action_name.png
new file mode 100644 (file)
index 0000000..24dc464
Binary files /dev/null and b/res/drawable-hdpi/ic_action_name.png differ
diff --git a/res/drawable-hdpi/ic_launcher.png b/res/drawable-hdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..617cef6
Binary files /dev/null and b/res/drawable-hdpi/ic_launcher.png differ
diff --git a/res/drawable-mdpi/ic_action_name.png b/res/drawable-mdpi/ic_action_name.png
new file mode 100644 (file)
index 0000000..df3ada7
Binary files /dev/null and b/res/drawable-mdpi/ic_action_name.png differ
diff --git a/res/drawable-mdpi/ic_launcher.png b/res/drawable-mdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..200460c
Binary files /dev/null and b/res/drawable-mdpi/ic_launcher.png differ
diff --git a/res/drawable-xhdpi/ic_ab_back_holo_dark_am_act.png b/res/drawable-xhdpi/ic_ab_back_holo_dark_am_act.png
new file mode 100644 (file)
index 0000000..4ffe73e
Binary files /dev/null and b/res/drawable-xhdpi/ic_ab_back_holo_dark_am_act.png differ
diff --git a/res/drawable-xhdpi/ic_ab_back_holo_dark_am_inact.png b/res/drawable-xhdpi/ic_ab_back_holo_dark_am_inact.png
new file mode 100644 (file)
index 0000000..6a47b91
Binary files /dev/null and b/res/drawable-xhdpi/ic_ab_back_holo_dark_am_inact.png differ
diff --git a/res/drawable-xhdpi/ic_ab_forward_holo_dark_am_act.png b/res/drawable-xhdpi/ic_ab_forward_holo_dark_am_act.png
new file mode 100644 (file)
index 0000000..29e482b
Binary files /dev/null and b/res/drawable-xhdpi/ic_ab_forward_holo_dark_am_act.png differ
diff --git a/res/drawable-xhdpi/ic_ab_forward_holo_dark_am_inact.png b/res/drawable-xhdpi/ic_ab_forward_holo_dark_am_inact.png
new file mode 100644 (file)
index 0000000..420f0b1
Binary files /dev/null and b/res/drawable-xhdpi/ic_ab_forward_holo_dark_am_inact.png differ
diff --git a/res/drawable-xhdpi/ic_action_name.png b/res/drawable-xhdpi/ic_action_name.png
new file mode 100644 (file)
index 0000000..a1db2b1
Binary files /dev/null and b/res/drawable-xhdpi/ic_action_name.png differ
diff --git a/res/drawable-xhdpi/ic_launcher.png b/res/drawable-xhdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..d42259a
Binary files /dev/null and b/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/res/drawable-xxhdpi/ic_action_name.png b/res/drawable-xxhdpi/ic_action_name.png
new file mode 100644 (file)
index 0000000..94a69f7
Binary files /dev/null and b/res/drawable-xxhdpi/ic_action_name.png differ
diff --git a/res/drawable-xxhdpi/ic_launcher.png b/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644 (file)
index 0000000..c26c01c
Binary files /dev/null and b/res/drawable-xxhdpi/ic_launcher.png differ
diff --git a/res/drawable-xxhdpi/stat_notify_sync_act.png b/res/drawable-xxhdpi/stat_notify_sync_act.png
new file mode 100644 (file)
index 0000000..7dfaec3
Binary files /dev/null and b/res/drawable-xxhdpi/stat_notify_sync_act.png differ
diff --git a/res/drawable-xxhdpi/stat_notify_sync_inact.png b/res/drawable-xxhdpi/stat_notify_sync_inact.png
new file mode 100644 (file)
index 0000000..8b7e34d
Binary files /dev/null and b/res/drawable-xxhdpi/stat_notify_sync_inact.png differ
diff --git a/res/drawable/selector_back.xml b/res/drawable/selector_back.xml
new file mode 100644 (file)
index 0000000..0ffcbb9
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:state_enabled="false"
+        android:drawable="@drawable/ic_ab_back_holo_dark_am_inact" />
+
+    <item android:state_enabled="true"
+        android:drawable="@drawable/ic_ab_back_holo_dark_am_act" /> 
+
+</selector>
\ No newline at end of file
diff --git a/res/drawable/selector_forward.xml b/res/drawable/selector_forward.xml
new file mode 100644 (file)
index 0000000..f84ce3e
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:state_enabled="false"
+        android:drawable="@drawable/ic_ab_forward_holo_dark_am_inact" />
+
+    <item android:state_enabled="true"
+        android:drawable="@drawable/ic_ab_forward_holo_dark_am_act" /> 
+
+</selector>
\ No newline at end of file
diff --git a/res/drawable/selector_sync.xml b/res/drawable/selector_sync.xml
new file mode 100644 (file)
index 0000000..d7c1996
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:state_enabled="false"
+        android:drawable="@drawable/stat_notify_sync_inact" />
+
+    <item android:state_enabled="true"
+        android:drawable="@drawable/stat_notify_sync_act" /> 
+
+</selector>
\ No newline at end of file
diff --git a/res/layout/activity_main.xml b/res/layout/activity_main.xml
new file mode 100644 (file)
index 0000000..a4a3e3b
--- /dev/null
@@ -0,0 +1,6 @@
+<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/pager"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context="com.example.tabs.MainActivity" />
diff --git a/res/layout/fragment_connection.xml b/res/layout/fragment_connection.xml
new file mode 100644 (file)
index 0000000..71f4810
--- /dev/null
@@ -0,0 +1,72 @@
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:fillViewport="true"
+    tools:context=".ConnectionFragment">
+
+       <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+           android:paddingBottom="@dimen/activity_vertical_margin"
+           android:paddingLeft="@dimen/activity_horizontal_margin"
+           android:paddingRight="@dimen/activity_horizontal_margin"
+           android:paddingTop="@dimen/activity_vertical_margin">
+
+           <TextView
+               android:id="@+id/tabConnectionIntro"
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:layout_marginTop="16dp"
+               android:text="@string/tab_connection_intro"
+               android:textAppearance="?android:attr/textAppearanceMedium" />
+       
+           <Button
+               android:id="@+id/buttonConnectionAction"
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:layout_below="@+id/tabConnectionIntro"
+               android:layout_centerHorizontal="true"
+               android:layout_marginTop="16dp"
+               android:text="@string/tab_button_connect" />
+       
+           <TextView
+               android:id="@+id/textConnectionStatus"
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:layout_alignLeft="@+id/tabConnectionIntro"
+               android:layout_below="@+id/buttonConnectionAction"
+               android:layout_marginTop="16dp"
+               android:text="@string/tab_status_text"
+               android:textAppearance="?android:attr/textAppearanceMedium" />
+       
+           <ProgressBar
+               android:id="@+id/progressConnection"
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:layout_alignLeft="@+id/textConnectionStatus"
+               android:layout_below="@+id/textConnectionStatus"
+               android:layout_marginTop="16dp" />
+       
+           <TextView
+               android:id="@+id/connectionMessage"
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:layout_alignTop="@+id/progressConnection"
+               android:layout_toRightOf="@+id/textConnectionStatus"
+               android:text="@string/tab_status_disconnected"
+               android:textAppearance="?android:attr/textAppearanceMedium" />
+
+           <ImageButton
+               android:id="@+id/toSwitch"
+               android:layout_width="wrap_content"
+               android:layout_height="wrap_content"
+               android:layout_alignParentRight="true"
+               android:layout_alignParentTop="true"
+               android:layout_marginTop="250dp"
+               android:minWidth="48dp"
+               android:src="@drawable/selector_forward" />
+
+       </RelativeLayout>
+
+</ScrollView>
\ No newline at end of file
diff --git a/res/layout/fragment_log.xml b/res/layout/fragment_log.xml
new file mode 100644 (file)
index 0000000..4601c7b
--- /dev/null
@@ -0,0 +1,35 @@
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:fillViewport="true"
+    android:id="@+id/log_fragment"
+    tools:context=".LogFragment" >
+
+       <RelativeLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+           android:paddingBottom="@dimen/activity_vertical_margin"
+           android:paddingLeft="@dimen/activity_horizontal_margin"
+           android:paddingRight="@dimen/activity_horizontal_margin"
+           android:paddingTop="@dimen/activity_vertical_margin" >
+
+               <TextView
+                   android:id="@+id/logView"
+                   android:layout_width="wrap_content"
+                   android:layout_height="wrap_content"
+                   android:layout_alignParentLeft="true"
+                   android:layout_alignParentTop="true" />
+       
+       </RelativeLayout>
+
+</ScrollView>
+
+<!-- <fragment xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/log_fragment"
+    android:name="com.example.tabs.LogFragment"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    xmlns:tools="http://schemas.android.com/tools"
+    tools:layout="@layout/log"/>
+ -->
\ No newline at end of file
diff --git a/res/layout/fragment_main.xml b/res/layout/fragment_main.xml
new file mode 100644 (file)
index 0000000..4ed07e0
--- /dev/null
@@ -0,0 +1,16 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingBottom="@dimen/activity_vertical_margin"
+    android:paddingLeft="@dimen/activity_horizontal_margin"
+    android:paddingRight="@dimen/activity_horizontal_margin"
+    android:paddingTop="@dimen/activity_vertical_margin"
+    tools:context="net.ddns.ebelcrom.ipremoteswitch.MainActivity$PlaceholderFragment" >
+
+    <TextView
+        android:id="@+id/section_label"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+</RelativeLayout>
diff --git a/res/layout/fragment_switch.xml b/res/layout/fragment_switch.xml
new file mode 100644 (file)
index 0000000..6cd70c8
--- /dev/null
@@ -0,0 +1,84 @@
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:fillViewport="true"
+    tools:context=".SwitchFragment" >
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingBottom="@dimen/activity_vertical_margin"
+        android:paddingLeft="@dimen/activity_horizontal_margin"
+        android:paddingRight="@dimen/activity_horizontal_margin"
+        android:paddingTop="@dimen/activity_vertical_margin" >
+
+        <TextView
+            android:id="@+id/tabSwitchIntro"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="16dp"
+            android:text="@string/tab_switch_intro"
+            android:textAppearance="?android:attr/textAppearanceMedium" />
+
+        <ToggleButton
+            android:id="@+id/buttonSwitchAction"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@+id/tabSwitchIntro"
+            android:layout_centerHorizontal="true"
+            android:layout_marginTop="16dp"
+            android:text="@string/tab_button_connect"
+            android:textOff="@string/tab_off"
+            android:textOn="@string/tab_on" />
+
+        <TextView
+            android:id="@+id/textSwitchStatus"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignLeft="@+id/tabSwitchIntro"
+            android:layout_below="@+id/buttonSwitchAction"
+            android:layout_marginTop="16dp"
+            android:text="@string/tab_status_text"
+            android:textAppearance="?android:attr/textAppearanceMedium" />
+
+        <ProgressBar
+            android:id="@+id/progressSwitch"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignLeft="@+id/textSwitchStatus"
+            android:layout_below="@+id/textSwitchStatus"
+            android:layout_marginTop="16dp" />
+
+        <TextView
+            android:id="@+id/switchMessage"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignTop="@+id/progressSwitch"
+            android:layout_toRightOf="@+id/textSwitchStatus"
+            android:maxWidth="200dp"
+            android:text="@string/tab_stop_failure"
+            android:textAppearance="?android:attr/textAppearanceMedium" />
+
+        <ImageButton
+            android:id="@+id/toConnection"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentLeft="true"
+            android:layout_alignParentTop="true"
+            android:layout_marginTop="250dp"
+            android:minWidth="48dp"
+            android:src="@drawable/selector_back" />
+
+        <ImageButton
+            android:id="@+id/buttonRefresh"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentRight="true"
+            android:layout_below="@+id/textSwitchStatus"
+            android:layout_marginTop="16dp"
+            android:minWidth="48dp"
+            android:src="@drawable/selector_sync" />
+    </RelativeLayout>
+
+</ScrollView>
\ No newline at end of file
diff --git a/res/menu/main.xml b/res/menu/main.xml
new file mode 100644 (file)
index 0000000..8397c34
--- /dev/null
@@ -0,0 +1,17 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    tools:context="com.example.tabs.MainActivity" >
+
+    <item
+        android:id="@+id/action_settings"
+        android:orderInCategory="100"
+        android:showAsAction="never"
+        android:title="@string/action_settings"/>
+
+    <item
+        android:id="@+id/action_about"
+        android:orderInCategory="200"
+        android:showAsAction="never"
+        android:title="@string/action_about"/>
+    
+</menu>
diff --git a/res/values-v11/styles.xml b/res/values-v11/styles.xml
new file mode 100644 (file)
index 0000000..3c02242
--- /dev/null
@@ -0,0 +1,11 @@
+<resources>
+
+    <!--
+        Base application theme for API 11+. This theme completely replaces
+        AppBaseTheme from res/values/styles.xml on API 11+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+        <!-- API 11 theme customizations can go here. -->
+    </style>
+
+</resources>
diff --git a/res/values-v14/styles.xml b/res/values-v14/styles.xml
new file mode 100644 (file)
index 0000000..a91fd03
--- /dev/null
@@ -0,0 +1,12 @@
+<resources>
+
+    <!--
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+        <!-- API 14 theme customizations can go here. -->
+    </style>
+
+</resources>
diff --git a/res/values-w820dp/dimens.xml b/res/values-w820dp/dimens.xml
new file mode 100644 (file)
index 0000000..f3e7020
--- /dev/null
@@ -0,0 +1,10 @@
+<resources>
+
+    <!--
+         Example customization of dimensions originally defined in res/values/dimens.xml
+         (such as screen margins) for screens with more than 820dp of available width. This
+         would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively).
+    -->
+    <dimen name="activity_horizontal_margin">64dp</dimen>
+
+</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
new file mode 100644 (file)
index 0000000..55c1e59
--- /dev/null
@@ -0,0 +1,7 @@
+<resources>
+
+    <!-- Default screen margins, per the Android Design guidelines. -->
+    <dimen name="activity_horizontal_margin">16dp</dimen>
+    <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
new file mode 100644 (file)
index 0000000..263f33f
--- /dev/null
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <string name="app_name">IPRemoteSwitch</string>
+
+    <!-- App actions -->
+    <string name="action_about">About</string>
+    <string name="action_settings">Settings</string>
+
+    <!-- Preferences -->
+    <string name="pref_gatew_sect">Gateway</string>
+    <string name="pref_gatew_title">Gateway WAN address</string>
+    <string name="pref_gatew_descr">WAN IP address or DNS name of your internet gateway
+        e.g. DSL router</string>
+    <string name="pref_gatew_default">example.com</string>
+    <string name="pref_gatew_port_title">Gateway WAN port</string>
+    <string name="pref_gatew_port_descr">WAN port of your internet gateway e.g. DSL
+        router</string>
+    <string name="pref_gatew_port_default">22</string>
+    <string name="pref_pc_sect">Remote PC</string>
+    <string name="pref_pc_title">Remote PC LAN address</string>
+    <string name="pref_pc_descr">LAN IP address or DNS name of your PC to be switched
+        remotely</string>
+    <string name="pref_pc_default">192.168.0.100</string>
+    <string name="pref_switch_sect">IP switch</string>
+    <string name="pref_usern_title">IP Switch username</string>
+    <string name="pref_usern_descr">Username of your IP switch account</string>
+    <string name="pref_usern_default">user</string>
+    <string name="pref_passwd_title">IP Switch password</string>
+    <string name="pref_passwd_descr">********</string>
+    <string name="pref_passwd_default">pass</string>
+
+    <!-- Connection tab -->
+    <string name="tab_connection">Connection</string>
+    <string name="tab_connection_intro">Connect to or disconnect from remote IP switch.</string>
+    <string name="tab_button_connect">Connect</string>
+    <string name="tab_button_disconnect">Disconnect</string>
+    <string name="tab_status_connecting">Connecting&#8230;</string>
+    <string name="tab_status_connected">Connected.</string>
+    <string name="tab_connection_failure">Connection failure. See log for more
+        information.</string>
+    <string name="tab_disconnection_failure">Disconnection failure. See log for more
+        information.</string>
+    <string name="tab_status_disconnecting">Disconnecting&#8230;</string>
+    <string name="tab_status_disconnected">Disconnected.</string>
+
+    <!-- Switch tab -->
+    <string name="tab_switch">Switch</string>
+    <string name="tab_switch_intro">Turn on/off remote PC.</string>
+    <string name="tab_status_starting">Starting&#8230;</string>
+    <string name="tab_status_started">Started.</string>
+    <string name="tab_start_failure">Start failure. See log for more information.</string>
+    <string name="tab_status_stopping">Stopping&#8230;</string>
+    <string name="tab_status_stopped">Stopped.</string>
+    <string name="tab_stop_failure">Stop failure. See log for more information.</string>
+    <string name="tab_refreshing">Refreshing&#8230;</string>
+    <string name="tab_refresh_failure">Refresh failure. See log for more information.</string>
+    <string name="tab_status_unknown">Unknown. Refresh status.</string>
+    <string name="tab_on">ON</string>
+    <string name="tab_off">OFF</string>
+
+    <!-- Log tab -->
+    <string name="tab_log">Log</string>
+    <string name="tab_status_text">Status:</string>
+    <string name="tab_unknown_text">Unknown</string>
+
+</resources>
\ No newline at end of file
diff --git a/res/values/styles.xml b/res/values/styles.xml
new file mode 100644 (file)
index 0000000..6ce89c7
--- /dev/null
@@ -0,0 +1,20 @@
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Light">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+
+</resources>
diff --git a/res/xml/fragment_preference.xml b/res/xml/fragment_preference.xml
new file mode 100644 (file)
index 0000000..8ffd6ef
--- /dev/null
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen
+    xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <PreferenceCategory
+        android:title="@string/pref_gatew_sect"
+        android:key="gateway_settings">
+        
+           <EditTextPreference
+               android:defaultValue="@string/pref_gatew_default"
+               android:key="gateway_address"
+               android:title="@string/pref_gatew_title"
+               android:summary="@string/pref_gatew_descr"/>
+
+           <EditTextPreference
+               android:defaultValue="@string/pref_gatew_port_default"
+               android:key="gateway_port"
+               android:inputType="number"
+               android:title="@string/pref_gatew_port_title"
+               android:summary="@string/pref_gatew_port_descr"/>
+
+    </PreferenceCategory>
+
+    <PreferenceCategory
+        android:title="@string/pref_pc_sect"
+        android:key="pc_settings">
+        
+           <EditTextPreference
+               android:defaultValue="@string/pref_pc_default"
+               android:key="pc_address"
+               android:title="@string/pref_pc_title"
+               android:summary="@string/pref_pc_descr"/>
+
+    </PreferenceCategory>
+
+    <PreferenceCategory
+        android:title="@string/pref_switch_sect"
+        android:key="switch_settings">
+        
+           <EditTextPreference
+               android:defaultValue="@string/pref_usern_default"
+               android:key="switch_username"
+               android:title="@string/pref_usern_title"
+               android:summary="@string/pref_usern_descr"/>
+       
+           <EditTextPreference
+               android:defaultValue="@string/pref_passwd_default"
+               android:key="switch_password"
+               android:inputType="textPassword"
+               android:title="@string/pref_passwd_title"
+               android:summary="@string/pref_passwd_descr"/>
+
+    </PreferenceCategory>
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/src/org/duckdns/binomiant/ipremoteswitch/ConnectionFragment.java b/src/org/duckdns/binomiant/ipremoteswitch/ConnectionFragment.java
new file mode 100644 (file)
index 0000000..95f977f
--- /dev/null
@@ -0,0 +1,263 @@
+package org.duckdns.binomiant.ipremoteswitch;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Properties;
+
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.JSchException;
+import com.jcraft.jsch.Session;
+
+import android.app.ActionBar;
+import android.app.Fragment;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.ImageButton;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+public class ConnectionFragment extends Fragment {
+
+       private static final String ARG_SECTION_NUMBER = "section_number";
+
+       private static ConnectionFragment instance;
+
+       private View rootView;
+
+       private enum State {
+               DISCONNECTED, CONNECTING, CONNECTING_FAILURE, CONNECTED, DISCONNECTING,
+               DISCONNECTING_FAILURE
+       };
+
+       private State state;
+
+       private Session session;
+
+       private class Task extends AsyncTask<SettingsData, Integer, Session> {
+               private Context context;
+               private View view;
+               private JSch jsch;
+
+               public Task(Context context, View view) {
+                       this.context = context;
+                       this.view = view;
+                       jsch = new JSch();
+               }
+
+               @Override
+               protected void onPreExecute() {
+                       Button button = (Button) view.findViewById(R.id.buttonConnectionAction);
+                       button.setEnabled(false);
+               }
+
+               @Override
+               protected Session doInBackground(SettingsData... params) {
+                       try {
+                               publishProgress(0);
+                               if (State.DISCONNECTED == state) {
+                                       /* set state */
+                                       state = State.CONNECTING;
+                                       /* log */
+                                       ((MainActivity) context).log("Connecting to "
+                                                       + params[0].gatewayAddress + ":" + params[0].gatewayPort);
+                                       /* open session */
+                                       InetAddress address = InetAddress.getByName(params[0].gatewayAddress);
+                                       session = jsch.getSession(params[0].username,
+                                                       address.getHostAddress(), params[0].gatewayPort);
+                                       session.setPassword(params[0].password);
+                                       /* avoid asking for key confirmation */
+                                       Properties prop = new Properties();
+                                       prop.put("StrictHostKeyChecking", "no");
+                                       session.setConfig(prop);
+                                       session.connect();
+                                       /* set state */
+                                       state = State.CONNECTED;
+                                       /* update switch fragment */
+                                       ((MainActivity) context).enableSwitch(true, session);
+                                       /* log */
+                                       ((MainActivity) context).log("Connected");
+                                       return session;
+                               } else if (State.CONNECTED == state) {
+                                       /* set state */
+                                       state = State.DISCONNECTING;
+                                       /* log */
+                                       ((MainActivity) context).log("Disconnecting from "
+                                                       + params[0].gatewayAddress + ":" + params[0].gatewayPort);
+                                       session.disconnect();
+                                       /* set state */
+                                       state = State.DISCONNECTED;
+                                       /* update switch fragment */
+                                       ((MainActivity) context).enableSwitch(false, session);
+                                       /* log */
+                                       ((MainActivity) context).log("Disconnected");
+                                       return session = null;
+                               }
+                       } catch (UnknownHostException | JSchException e) {
+                               if (State.CONNECTING == state) {
+                                       /* set state */
+                                       state = State.CONNECTING_FAILURE;
+                                       /* log */
+                                       ((MainActivity) context)
+                                                       .log("Connection failure: " + e.getLocalizedMessage());
+                               } else if (State.DISCONNECTING == state) {
+                                       /* set state */
+                                       state = State.DISCONNECTING_FAILURE;
+                                       /* log */
+                                       ((MainActivity) context)
+                                                       .log("Disconnection failure: " + e.getLocalizedMessage());
+                               }
+                       } finally {
+                               publishProgress(100);
+                       }
+                       return null;
+               }
+
+               @Override
+               protected void onProgressUpdate(Integer... values) {
+                       updateView();
+                       if (100 == values[0]) {
+                               if (State.CONNECTING_FAILURE == state) {
+                                       state = State.DISCONNECTED;
+                               }
+                               if (State.DISCONNECTING_FAILURE == state) {
+                                       state = State.CONNECTED;
+                               }
+                       }
+               }
+
+               @Override
+               protected void onPostExecute(Session result) {
+                       if (null != result) {
+                               ImageButton toSwitch = (ImageButton) view.findViewById(R.id.toSwitch);
+                               toSwitch.setEnabled(true);
+                       } else if (null == result) {
+                               ImageButton toSwitch = (ImageButton) view.findViewById(R.id.toSwitch);
+                               toSwitch.setEnabled(false);
+                       }
+               }
+       }
+
+       private Task task;
+
+       public static ConnectionFragment newInstance(int sectionNumber) {
+               if (null == instance) {
+                       instance = new ConnectionFragment();
+                       Bundle args = new Bundle();
+                       args.putInt(ARG_SECTION_NUMBER, sectionNumber);
+                       instance.setArguments(args);
+               }
+               return instance;
+       }
+
+       public ConnectionFragment() {
+               state = State.DISCONNECTED;
+       }
+
+       public Session getSession() {
+               return session;
+       }
+
+       @Override
+       public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                       Bundle savedInstanceState) {
+               if (null == rootView) {
+                       rootView = inflater.inflate(R.layout.fragment_connection, container, false);
+               }
+               return rootView;
+       }
+
+       public void updateView() {
+               Button button = (Button) rootView.findViewById(R.id.buttonConnectionAction);
+               ProgressBar progress = (ProgressBar) rootView
+                               .findViewById(R.id.progressConnection);
+               TextView status = (TextView) rootView.findViewById(R.id.connectionMessage);
+               ImageButton toSwitch = (ImageButton) rootView.findViewById(R.id.toSwitch);
+
+               if (State.CONNECTING == state || State.DISCONNECTING == state) {
+                       progress.setVisibility(ProgressBar.VISIBLE);
+                       button.setEnabled(false);
+                       if (State.CONNECTING == state) {
+                               button.setText(R.string.tab_button_connect);
+                               status.setText(R.string.tab_status_connecting);
+                       } else {
+                               button.setText(R.string.tab_button_disconnect);
+                               status.setText(R.string.tab_status_disconnecting);
+                       }
+                       toSwitch.setEnabled(false);
+               } else {
+                       progress.setVisibility(ProgressBar.INVISIBLE);
+                       button.setEnabled(true);
+                       switch (state) {
+                       case CONNECTED:
+                               button.setText(R.string.tab_button_disconnect);
+                               status.setText(R.string.tab_status_connected);
+                               toSwitch.setEnabled(true);
+                               break;
+                       case CONNECTING_FAILURE:
+                               button.setText(R.string.tab_button_connect);
+                               status.setText(R.string.tab_connection_failure);
+                               toSwitch.setEnabled(false);
+                               break;
+                       case DISCONNECTED:
+                               button.setText(R.string.tab_button_connect);
+                               status.setText(R.string.tab_status_disconnected);
+                               toSwitch.setEnabled(false);
+                               break;
+                       case DISCONNECTING_FAILURE:
+                               button.setText(R.string.tab_button_disconnect);
+                               status.setText(R.string.tab_disconnection_failure);
+                               toSwitch.setEnabled(false);
+                       }
+               }
+       }
+
+       @Override
+       public void onViewCreated(View view, Bundle savedInstanceState) {
+               super.onViewCreated(view, savedInstanceState);
+
+               ImageButton toSwitch = (ImageButton) view.findViewById(R.id.toSwitch);
+               toSwitch.setOnClickListener(new OnClickListener() {
+                       @Override
+                       public void onClick(View view) {
+                               ActionBar actionBar = getActivity().getActionBar();
+                               actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
+                               int pos = actionBar.getSelectedNavigationIndex();
+                               actionBar.setSelectedNavigationItem(pos + 1);
+                       }
+               });
+               toSwitch.setEnabled(false);
+
+               Button button = (Button) view.findViewById(R.id.buttonConnectionAction);
+               button.setOnClickListener(new OnClickListener() {
+                       @Override
+                       public void onClick(View view) {
+                               SharedPreferences preferences = PreferenceManager
+                                               .getDefaultSharedPreferences(getActivity());
+                               SettingsData settingsData = new SettingsData(
+                                               preferences.getString("gateway_address",
+                                                               getString(R.string.pref_gatew_default)),
+                                               Integer.valueOf(preferences.getString("gateway_port",
+                                                               getString(R.string.pref_gatew_port_default))).intValue(),
+                                               preferences.getString("pc_address",
+                                                               getString(R.string.pref_pc_default)),
+                                               preferences.getString("switch_username",
+                                                               getString(R.string.pref_usern_default)),
+                                               preferences.getString("switch_password",
+                                                               getString(R.string.pref_passwd_default)));
+
+                               task = new Task(getActivity(), rootView);
+                               task.execute(settingsData);
+                       }
+               });
+
+               updateView();
+       }
+}
diff --git a/src/org/duckdns/binomiant/ipremoteswitch/LogFragment.java b/src/org/duckdns/binomiant/ipremoteswitch/LogFragment.java
new file mode 100644 (file)
index 0000000..5196558
--- /dev/null
@@ -0,0 +1,79 @@
+package org.duckdns.binomiant.ipremoteswitch;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+public class LogFragment extends Fragment {
+
+       private static final String ARG_SECTION_NUMBER = "section_number";
+
+       private static LogFragment instance;
+       private View rootView;
+       private StringBuffer logBuffer;
+
+       private Handler messageHandler = new Handler() {
+               public void handleMessage(Message msg) {
+                       super.handleMessage(msg);
+                       String aResponse = msg.getData().getString("log");
+                       TextView logView = (TextView) rootView.findViewById(R.id.logView);
+                       logView.append(aResponse);
+               }
+       };
+
+       public static LogFragment newInstance(int sectionNumber) {
+               if (null == instance) {
+                       instance = new LogFragment();
+                       Bundle args = new Bundle();
+                       args.putInt(ARG_SECTION_NUMBER, sectionNumber);
+                       instance.setArguments(args);
+               }
+               return instance;
+       }
+
+       public LogFragment() {
+               logBuffer = new StringBuffer();
+       }
+
+       @Override
+       public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                       Bundle savedInstanceState) {
+               if (null == rootView) {
+                       rootView = inflater.inflate(R.layout.fragment_log, container, false);
+               }
+               return rootView;
+       }
+
+       @Override
+       public void onViewCreated(View view, Bundle savedInstanceState) {
+               if (logBuffer.length() > 0) {
+                       TextView logView = (TextView) rootView.findViewById(R.id.logView);
+                       logView.append(logBuffer.toString());
+                       logBuffer.delete(0, logBuffer.length());
+               }
+       }
+
+       public void log(String message) {
+               Date timestamp = new Date();
+               SimpleDateFormat dateFormat = new SimpleDateFormat("[HH:mm:ss.SSS] ");
+               String entry = dateFormat.format(timestamp) + message + "\n";
+
+               if (null != rootView) {
+                       Message msgObj = Message.obtain();
+                       Bundle b = new Bundle();
+                       b.putString("log", entry);
+                       msgObj.setData(b);
+                       messageHandler.sendMessage(msgObj);
+               } else {
+                       logBuffer.append(entry);
+               }
+       }
+}
diff --git a/src/org/duckdns/binomiant/ipremoteswitch/MainActivity.java b/src/org/duckdns/binomiant/ipremoteswitch/MainActivity.java
new file mode 100644 (file)
index 0000000..88666a2
--- /dev/null
@@ -0,0 +1,172 @@
+package org.duckdns.binomiant.ipremoteswitch;
+
+import java.util.Locale;
+
+import com.jcraft.jsch.Session;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.ActionBar;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.support.v13.app.FragmentPagerAdapter;
+import android.os.Bundle;
+import android.support.v4.view.ViewPager;
+import android.view.Menu;
+import android.view.MenuItem;
+
+@SuppressWarnings("deprecation")
+public class MainActivity extends Activity implements ActionBar.TabListener {
+
+       private static final int ABOUT_DIALOG = 1;
+
+       private SectionsPagerAdapter mSectionsPagerAdapter;
+
+       private ViewPager mViewPager;
+
+       private LogFragment mLogFragment;
+       private ConnectionFragment mConnectionFragment;
+       private SwitchFragment mSwitchFragment;
+
+       @Override
+       protected void onCreate(Bundle savedInstanceState) {
+               super.onCreate(savedInstanceState);
+               setContentView(R.layout.activity_main);
+
+               mConnectionFragment = ConnectionFragment.newInstance(1);
+               mSwitchFragment = SwitchFragment.newInstance(2);
+               mLogFragment = LogFragment.newInstance(3);
+
+               final ActionBar actionBar = getActionBar();
+               actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
+
+               mSectionsPagerAdapter = new SectionsPagerAdapter(getFragmentManager());
+
+               mViewPager = (ViewPager) findViewById(R.id.pager);
+               mViewPager.setAdapter(mSectionsPagerAdapter);
+
+               mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
+                       @Override
+                       public void onPageSelected(int position) {
+                               actionBar.setSelectedNavigationItem(position);
+                       }
+               });
+
+               for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
+                       actionBar.addTab(actionBar.newTab()
+                                       .setText(mSectionsPagerAdapter.getPageTitle(i)).setTabListener(this));
+               }
+       }
+
+       @Override
+       public boolean onCreateOptionsMenu(Menu menu) {
+               getMenuInflater().inflate(R.menu.main, menu);
+               return true;
+       }
+
+       @Override
+       public boolean onOptionsItemSelected(MenuItem item) {
+               int id = item.getItemId();
+               if (id == R.id.action_settings) {
+                       startActivity(new Intent(this, SettingsActivity.class));
+                       return true;
+               }
+               if (id == R.id.action_about) {
+                       showDialog(ABOUT_DIALOG);
+                       return true;
+               }
+               return super.onOptionsItemSelected(item);
+       }
+
+       @Override
+       public void onTabSelected(ActionBar.Tab tab,
+                       FragmentTransaction fragmentTransaction) {
+               mViewPager.setCurrentItem(tab.getPosition());
+       }
+
+       @Override
+       public void onTabUnselected(ActionBar.Tab tab,
+                       FragmentTransaction fragmentTransaction) {
+       }
+
+       @Override
+       public void onTabReselected(ActionBar.Tab tab,
+                       FragmentTransaction fragmentTransaction) {
+       }
+
+       public class SectionsPagerAdapter extends FragmentPagerAdapter {
+
+               public SectionsPagerAdapter(FragmentManager fm) {
+                       super(fm);
+               }
+
+               @Override
+               public Fragment getItem(int position) {
+                       Fragment fragment = null;
+                       switch (position) {
+                               case 0:
+                                       fragment = ConnectionFragment.newInstance(position + 1);
+                                       break;
+                               case 1:
+                                       fragment = SwitchFragment.newInstance(position + 1);
+                                       break;
+                               case 2:
+                                       fragment = LogFragment.newInstance(position + 1);
+                                       break;
+                       }
+                       return fragment;
+               }
+
+               @Override
+               public int getCount() {
+                       return 3;
+               }
+
+               @Override
+               public CharSequence getPageTitle(int position) {
+                       Locale l = Locale.getDefault();
+                       switch (position) {
+                               case 0:
+                                       return getString(R.string.tab_connection).toUpperCase(l);
+                               case 1:
+                                       return getString(R.string.tab_switch).toUpperCase(l);
+                               case 2:
+                                       return getString(R.string.tab_log).toUpperCase(l);
+                       }
+                       return null;
+               }
+       }
+
+       public Dialog onCreateDialog(int id) {
+               Dialog dialog = null;
+
+               switch (id) {
+                       case ABOUT_DIALOG:
+                               AlertDialog.Builder builder = new AlertDialog.Builder(this);
+                               builder.setTitle("About");
+                               builder.setMessage("IPRemoteSwitch v1.0\n©2016 ebelcrom");
+                               builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
+                                       public void onClick(DialogInterface dialog, int id) {
+                                               dialog.dismiss();
+                                       }
+                               });
+                               builder.setCancelable(false);
+                               dialog = builder.create();
+                               break;
+               }
+               return dialog;
+       }
+
+       public void log(String message) {
+               mLogFragment.log(message);
+       }
+
+       public void enableSwitch(boolean enable, Session session) {
+               mSwitchFragment.enableSwitch(enable, session);
+       }
+
+}
diff --git a/src/org/duckdns/binomiant/ipremoteswitch/SettingsActivity.java b/src/org/duckdns/binomiant/ipremoteswitch/SettingsActivity.java
new file mode 100644 (file)
index 0000000..89851f9
--- /dev/null
@@ -0,0 +1,46 @@
+package org.duckdns.binomiant.ipremoteswitch;
+
+import java.util.List;
+
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceManager;
+
+public class SettingsActivity extends PreferenceActivity {
+    private static Preference.OnPreferenceChangeListener bindSummaryListener = new Preference.OnPreferenceChangeListener() {
+       @Override
+       public boolean onPreferenceChange(Preference preference, Object value) {
+           /* set summary text to preference value */
+           String stringValue = value.toString();
+           preference.setSummary(stringValue);
+           return true;
+       }
+    };
+
+    @Override
+    public void onBuildHeaders(List<Header> target) {
+       /* set content of this activity to the preference fragment */
+       getFragmentManager().beginTransaction()
+               .replace(android.R.id.content, new SettingsFragment()).commit();
+    }
+
+    @Override
+    protected boolean isValidFragment(String fragmentName) {
+       /* return the only preferences fragment available */
+       return SettingsFragment.class.getName().equals(fragmentName);
+    }
+
+    public void bindSummary(Preference preference) {
+       /* set a listener for changes on values except password */
+       if (!"switch_password".equals(preference.getKey())) {
+           preference.setOnPreferenceChangeListener(bindSummaryListener);
+       }
+
+       /* trigger listener immediately once except password */
+       if (!"switch_password".equals(preference.getKey())) {
+           bindSummaryListener.onPreferenceChange(preference,
+                   PreferenceManager.getDefaultSharedPreferences(preference.getContext())
+                           .getString(preference.getKey(), ""));
+       }
+    }
+}
diff --git a/src/org/duckdns/binomiant/ipremoteswitch/SettingsData.java b/src/org/duckdns/binomiant/ipremoteswitch/SettingsData.java
new file mode 100644 (file)
index 0000000..5b9a6a5
--- /dev/null
@@ -0,0 +1,18 @@
+package org.duckdns.binomiant.ipremoteswitch;
+
+public class SettingsData {
+       public String gatewayAddress;
+       public int gatewayPort;
+       public String pcAddress;
+       public String username;
+       public String password;
+
+       public SettingsData(String gatewayAddress, int gatewayPort, String pcAddress,
+                       String username, String password) {
+               this.gatewayAddress = gatewayAddress;
+               this.gatewayPort = gatewayPort;
+               this.pcAddress = pcAddress;
+               this.username = username;
+               this.password = password;
+       }
+}
diff --git a/src/org/duckdns/binomiant/ipremoteswitch/SettingsFragment.java b/src/org/duckdns/binomiant/ipremoteswitch/SettingsFragment.java
new file mode 100644 (file)
index 0000000..3976ee7
--- /dev/null
@@ -0,0 +1,25 @@
+package org.duckdns.binomiant.ipremoteswitch;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.preference.PreferenceFragment;
+
+public class SettingsFragment extends PreferenceFragment {
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+       super.onCreate(savedInstanceState);
+       /* create preferences from resource */
+       addPreferencesFromResource(R.xml.fragment_preference);
+       /* bind summary to values */
+       Activity superActivity = getActivity();
+       SettingsActivity activity;
+       if (superActivity instanceof SettingsActivity) {
+           activity = (SettingsActivity) superActivity;
+           activity.bindSummary(findPreference("gateway_address"));
+           activity.bindSummary(findPreference("gateway_port"));
+           activity.bindSummary(findPreference("pc_address"));
+           activity.bindSummary(findPreference("switch_username"));
+           activity.bindSummary(findPreference("switch_password"));
+       }
+    }
+}
diff --git a/src/org/duckdns/binomiant/ipremoteswitch/SwitchFragment.java b/src/org/duckdns/binomiant/ipremoteswitch/SwitchFragment.java
new file mode 100644 (file)
index 0000000..b01feb0
--- /dev/null
@@ -0,0 +1,455 @@
+package org.duckdns.binomiant.ipremoteswitch;
+
+import com.jcraft.jsch.ChannelExec;
+import com.jcraft.jsch.JSchException;
+import com.jcraft.jsch.Session;
+
+import android.app.ActionBar;
+import android.app.Fragment;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.preference.PreferenceManager;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.View.OnClickListener;
+import android.widget.ImageButton;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+import android.widget.ToggleButton;
+
+public class SwitchFragment extends Fragment {
+       private static final String ARG_SECTION_NUMBER = "section_number";
+
+       private static SwitchFragment instance;
+
+       private View rootView;
+
+       private enum State {
+               INACTIVE, OFF, SWITCHING_ON, SWITCHING_ON_FAILURE, ON, SWITCHING_OFF,
+               SWITCHING_OFF_FAILURE, REFRESHING, REFRESHING_FAILURE, UNKNOWN
+       };
+
+       private State state;
+
+       private Session session;
+
+       private final static String CMD_SCRIPT = "/home/pi/switch.sh ";
+       private final static String CMD_STATUS = "status ";
+       private final static String CMD_ON = "on ";
+       private final static String CMD_OFF = "off ";
+
+       private final static int RESULT_UNKNOWN = -2;
+       private final static int RESULT_ERROR = -1;
+       private final static int RESULT_ON = 1;
+       private final static int RESULT_OFF = 2;
+
+       private Handler messageHandler = new Handler() {
+               public void handleMessage(Message msg) {
+                       super.handleMessage(msg);
+                       updateView();
+               }
+       };
+
+       private class Task extends AsyncTask<SettingsData, Void, Void> {
+               private Context context;
+
+               public Task(Context context, View view) {
+                       this.context = context;
+               }
+
+               @Override
+               protected void onPreExecute() {
+                       /* set state */
+                       if (State.OFF == state) {
+                               state = State.SWITCHING_ON;
+                       } else {
+                               state = State.SWITCHING_OFF;
+                       }
+                       updateView();
+               }
+
+               @Override
+               protected Void doInBackground(SettingsData... params) {
+                       int result = RESULT_UNKNOWN;
+                       try {
+                               if (State.SWITCHING_ON == state) {
+                                       /* log */
+                                       ((MainActivity) context).log("Switching on " + params[0].pcAddress);
+                                       /* set channel params */
+                                       ChannelExec channel = (ChannelExec) session.openChannel("exec");
+                                       channel.setCommand(CMD_SCRIPT + CMD_ON + params[0].pcAddress);
+                                       channel.setInputStream(null);
+                                       channel.setOutputStream(null);
+                                       channel.setErrStream(null);
+                                       /* send command */
+                                       channel.connect();
+                                       /* wait on command termination */
+                                       while (true) {
+                                               if (channel.isClosed()) {
+                                                       result = channel.getExitStatus();
+                                                       break;
+                                               }
+                                               try {
+                                                       Thread.sleep(1000);
+                                               } catch (InterruptedException e) {
+                                                       /* do nothing */
+                                               }
+                                       }
+                                       /* close channel */
+                                       channel.disconnect();
+                                       /* set state */
+                                       switch (result) {
+                                               case RESULT_ON:
+                                                       state = State.ON;
+                                                       /* log */
+                                                       ((MainActivity) context)
+                                                                       .log("Switched on " + params[0].pcAddress);
+                                                       break;
+                                               case RESULT_OFF:
+                                               case RESULT_ERROR:
+                                                       state = State.SWITCHING_ON_FAILURE;
+                                                       /* log */
+                                                       ((MainActivity) context).log(
+                                                                       "Switching on " + params[0].pcAddress + " failed");
+                                                       break;
+                                       }
+                               } else if (State.SWITCHING_OFF == state) {
+                                       /* log */
+                                       ((MainActivity) context).log("Switching off " + params[0].pcAddress);
+                                       /* set channel params */
+                                       ChannelExec channel = (ChannelExec) session.openChannel("exec");
+                                       channel.setCommand(CMD_SCRIPT + CMD_OFF + params[0].pcAddress);
+                                       channel.setInputStream(null);
+                                       channel.setOutputStream(null);
+                                       channel.setErrStream(null);
+                                       /* send command */
+                                       channel.connect();
+                                       /* wait on command termination */
+                                       while (true) {
+                                               if (channel.isClosed()) {
+                                                       result = channel.getExitStatus();
+                                                       break;
+                                               }
+                                               try {
+                                                       Thread.sleep(1000);
+                                               } catch (InterruptedException e) {
+                                                       /* do nothing */
+                                               }
+                                       }
+                                       /* close channel */
+                                       channel.disconnect();
+                                       /* set state */
+                                       switch (result) {
+                                               case RESULT_OFF:
+                                                       state = State.OFF;
+                                                       /* log */
+                                                       ((MainActivity) context)
+                                                                       .log("Switched off " + params[0].pcAddress);
+                                                       break;
+                                               case RESULT_ON:
+                                               case RESULT_ERROR:
+                                                       state = State.SWITCHING_OFF_FAILURE;
+                                                       /* log */
+                                                       ((MainActivity) context).log(
+                                                                       "Switching off " + params[0].pcAddress + " failed");
+                                                       break;
+                                       }
+                               }
+                       } catch (JSchException e) {
+                               if (State.SWITCHING_ON == state) {
+                                       /* set state */
+                                       state = State.SWITCHING_ON_FAILURE;
+                                       /* log */
+                                       ((MainActivity) context)
+                                                       .log("Switching on failure: " + e.getLocalizedMessage());
+                               } else if (State.SWITCHING_OFF == state) {
+                                       /* set state */
+                                       state = State.SWITCHING_OFF_FAILURE;
+                                       /* log */
+                                       ((MainActivity) context)
+                                                       .log("Switching off failure: " + e.getLocalizedMessage());
+                               }
+                       }
+                       return null;
+               }
+
+               @Override
+               protected void onPostExecute(Void result) {
+                       updateView();
+                       if (State.SWITCHING_ON_FAILURE == state) {
+                               /* set state */
+                               state = State.OFF;
+                       }
+                       if (State.SWITCHING_OFF_FAILURE == state) {
+                               /* set state */
+                               state = State.ON;
+                       }
+               }
+       }
+
+       private Task task;
+
+       private class RefreshTask extends AsyncTask<SettingsData, Void, Void> {
+               private Context context;
+
+               public RefreshTask(Context context, View view) {
+                       this.context = context;
+               }
+
+               @Override
+               protected void onPreExecute() {
+                       /* set state */
+                       state = State.REFRESHING;
+                       updateView();
+               }
+
+               @Override
+               protected Void doInBackground(SettingsData... params) {
+                       int result = RESULT_UNKNOWN;
+                       try {
+                               /* log */
+                               ((MainActivity) context).log("Refresh state of " + params[0].pcAddress);
+                               /* set channel params */
+                               ChannelExec channel = (ChannelExec) session.openChannel("exec");
+                               channel.setCommand(CMD_SCRIPT + CMD_STATUS + params[0].pcAddress);
+                               channel.setInputStream(null);
+                               channel.setOutputStream(null);
+                               channel.setErrStream(null);
+                               /* send command */
+                               channel.connect();
+                               /* wait on command termination */
+                               while (true) {
+                                       if (channel.isClosed()) {
+                                               result = channel.getExitStatus();
+                                               break;
+                                       }
+                                       try {
+                                               Thread.sleep(1000);
+                                       } catch (InterruptedException e) {
+                                               /* do nothing */
+                                       }
+                               }
+                               /* close channel */
+                               channel.disconnect();
+                               /* set state */
+                               switch (result) {
+                                       case RESULT_OFF:
+                                               state = State.OFF;
+                                               /* log */
+                                               ((MainActivity) context)
+                                                               .log("State of is off");
+                                               break;
+                                       case RESULT_ON:
+                                               state = State.ON;
+                                               /* log */
+                                               ((MainActivity) context)
+                                                               .log("State of is on");
+                                               break;
+                                       case RESULT_ERROR:
+                                               state = State.REFRESHING_FAILURE;
+                                               /* log */
+                                               ((MainActivity) context)
+                                                               .log("State of unknown");
+                                               break;
+                               }
+                       } catch (JSchException e) {
+                               /* log */
+                               ((MainActivity) context)
+                                               .log("Refreshing failure: " + e.getLocalizedMessage());
+                       }
+                       return null;
+               }
+
+               @Override
+               protected void onPostExecute(Void result) {
+                       updateView();
+                       if (State.SWITCHING_ON_FAILURE == state) {
+                               /* set state */
+                               state = State.OFF;
+                       }
+                       if (State.SWITCHING_OFF_FAILURE == state) {
+                               /* set state */
+                               state = State.ON;
+                       }
+               }
+       }
+
+       private RefreshTask refreshTask;
+
+       public static SwitchFragment newInstance(int sectionNumber) {
+               if (null == instance) {
+                       instance = new SwitchFragment();
+                       Bundle args = new Bundle();
+                       args.putInt(ARG_SECTION_NUMBER, sectionNumber);
+                       instance.setArguments(args);
+               }
+               return instance;
+       }
+
+       public SwitchFragment() {
+               state = State.INACTIVE;
+       }
+
+       @Override
+       public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                       Bundle savedInstanceState) {
+               if (null == rootView) {
+                       rootView = inflater.inflate(R.layout.fragment_switch, container, false);
+               }
+               return rootView;
+       }
+
+       public void updateView() {
+               ToggleButton button = (ToggleButton) rootView
+                               .findViewById(R.id.buttonSwitchAction);
+               ProgressBar progress = (ProgressBar) rootView.findViewById(R.id.progressSwitch);
+               TextView status = (TextView) rootView.findViewById(R.id.switchMessage);
+               ImageButton toConnection = (ImageButton) rootView.findViewById(R.id.toConnection);
+               ImageButton buttonRefresh = (ImageButton) rootView
+                               .findViewById(R.id.buttonRefresh);
+
+               if (State.SWITCHING_ON == state || State.SWITCHING_OFF == state) {
+                       progress.setVisibility(ProgressBar.VISIBLE);
+                       button.setEnabled(false);
+                       toConnection.setEnabled(true);
+                       buttonRefresh.setEnabled(false);
+                       if (State.SWITCHING_ON == state) {
+                               button.setChecked(true);
+                               status.setText(R.string.tab_status_starting);
+                       } else {
+                               button.setChecked(false);
+                               status.setText(R.string.tab_status_stopping);
+                       }
+               } else if (State.INACTIVE == state) {
+                       progress.setVisibility(ProgressBar.INVISIBLE);
+                       button.setEnabled(false);
+                       button.setChecked(false);
+                       status.setText(R.string.tab_status_unknown);
+                       toConnection.setEnabled(false);
+                       buttonRefresh.setEnabled(false);
+               } else if (State.UNKNOWN == state) {
+                       progress.setVisibility(ProgressBar.INVISIBLE);
+                       button.setEnabled(false);
+                       button.setChecked(false);
+                       status.setText(R.string.tab_status_unknown);
+                       toConnection.setEnabled(true);
+                       buttonRefresh.setEnabled(true);
+               } else if (State.REFRESHING == state) {
+                       progress.setVisibility(ProgressBar.VISIBLE);
+                       button.setEnabled(false);
+                       button.setChecked(false);
+                       status.setText(R.string.tab_refreshing);
+                       toConnection.setEnabled(true);
+                       buttonRefresh.setEnabled(false);
+               } else {
+                       progress.setVisibility(ProgressBar.INVISIBLE);
+                       button.setEnabled(true);
+                       toConnection.setEnabled(true);
+                       buttonRefresh.setEnabled(true);
+                       switch (state) {
+                               case ON:
+                                       button.setChecked(true);
+                                       status.setText(R.string.tab_status_started);
+                                       break;
+                               case SWITCHING_ON_FAILURE:
+                                       button.setChecked(false);
+                                       status.setText(R.string.tab_start_failure);
+                                       break;
+                               case OFF:
+                                       button.setChecked(false);
+                                       status.setText(R.string.tab_status_stopped);
+                                       break;
+                               case SWITCHING_OFF_FAILURE:
+                                       button.setChecked(true);
+                                       status.setText(R.string.tab_stop_failure);
+                                       break;
+                               case REFRESHING_FAILURE:
+                                       status.setText(R.string.tab_refresh_failure);
+                       }
+               }
+       }
+
+       @Override
+       public void onViewCreated(View view, Bundle savedInstanceState) {
+               super.onViewCreated(view, savedInstanceState);
+
+               ImageButton toConnection = (ImageButton) view.findViewById(R.id.toConnection);
+               toConnection.setOnClickListener(new OnClickListener() {
+                       @Override
+                       public void onClick(View view) {
+                               ActionBar actionBar = getActivity().getActionBar();
+                               actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
+                               int pos = actionBar.getSelectedNavigationIndex();
+                               actionBar.setSelectedNavigationItem(pos - 1);
+                       }
+               });
+
+               ToggleButton button = (ToggleButton) view.findViewById(R.id.buttonSwitchAction);
+               button.setOnClickListener(new OnClickListener() {
+                       @Override
+                       public void onClick(View view) {
+                               SharedPreferences preferences = PreferenceManager
+                                               .getDefaultSharedPreferences(getActivity());
+                               SettingsData settingsData = new SettingsData(
+                                               preferences.getString("gateway_address",
+                                                               getString(R.string.pref_gatew_default)),
+                                               Integer.valueOf(preferences.getString("gateway_port",
+                                                               getString(R.string.pref_gatew_port_default))).intValue(),
+                                               preferences.getString("pc_address",
+                                                               getString(R.string.pref_pc_default)),
+                                               preferences.getString("switch_username",
+                                                               getString(R.string.pref_usern_default)),
+                                               preferences.getString("switch_password",
+                                                               getString(R.string.pref_passwd_default)));
+
+                               task = new Task(getActivity(), rootView);
+                               task.execute(settingsData);
+                       }
+               });
+
+               ImageButton refreshButton = (ImageButton) view.findViewById(R.id.buttonRefresh);
+               refreshButton.setOnClickListener(new OnClickListener() {
+                       @Override
+                       public void onClick(View view) {
+                               SharedPreferences preferences = PreferenceManager
+                                               .getDefaultSharedPreferences(getActivity());
+                               SettingsData settingsData = new SettingsData(
+                                               preferences.getString("gateway_address",
+                                                               getString(R.string.pref_gatew_default)),
+                                               Integer.valueOf(preferences.getString("gateway_port",
+                                                               getString(R.string.pref_gatew_port_default))).intValue(),
+                                               preferences.getString("pc_address",
+                                                               getString(R.string.pref_pc_default)),
+                                               preferences.getString("switch_username",
+                                                               getString(R.string.pref_usern_default)),
+                                               preferences.getString("switch_password",
+                                                               getString(R.string.pref_passwd_default)));
+
+                               refreshTask = new RefreshTask(getActivity(), rootView);
+                               refreshTask.execute(settingsData);
+                       }
+               });
+
+               updateView();
+       }
+
+       public void enableSwitch(boolean enable, Session session) {
+               this.session = session;
+               if (enable)
+                       state = State.UNKNOWN;
+               else
+                       state = State.INACTIVE;
+
+               if (null != rootView) {
+                       Message msgObj = Message.obtain();
+                       Bundle b = new Bundle();
+                       messageHandler.sendMessage(msgObj);
+               }
+       }
+
+}