summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjørn Mork <bjorn@mork.no>2019-06-03 22:53:44 +0200
committerBjørn Mork <bjorn@mork.no>2019-06-03 22:54:59 +0200
commitd89b7c37ca5fc790f9ac02dfebb808fb16406ae3 (patch)
tree347dbf4847255f1709894f94407c7193499a5eb7
parent6263515f4bf93f12769bb30b6d59a484f90f5e27 (diff)
network config wip - failing to restore state in ipcam activity
Signed-off-by: Bjørn Mork <bjorn@mork.no>
-rw-r--r--Defogger/AndroidManifest.xml44
-rw-r--r--Defogger/Makefile4
-rw-r--r--Defogger/res/layout/activity_configurenetwork.xml41
-rw-r--r--Defogger/res/layout/activity_ipcam.xml14
-rw-r--r--Defogger/res/layout/item_net.xml24
-rw-r--r--Defogger/src/no/mork/android/defogger/ConfigureNetworkActivity.java127
-rw-r--r--Defogger/src/no/mork/android/defogger/IpCamActivity.java204
-rw-r--r--Defogger/src/no/mork/android/defogger/MainActivity.java1
-rw-r--r--Defogger/src/no/mork/android/defogger/ScannerActivity.java2
-rw-r--r--Defogger/src/no/mork/android/defogger/Util.java48
10 files changed, 340 insertions, 169 deletions
diff --git a/Defogger/AndroidManifest.xml b/Defogger/AndroidManifest.xml
index 074e909..d977486 100644
--- a/Defogger/AndroidManifest.xml
+++ b/Defogger/AndroidManifest.xml
@@ -1,38 +1,38 @@
<?xml version='1.0'?>
-<manifest xmlns:a='http://schemas.android.com/apk/res/android'
+<manifest xmlns:android='http://schemas.android.com/apk/res/android'
package='no.mork.android.defogger'
- a:versionCode='0'
- a:versionName='0'>
+ android:versionCode='0'
+ android:versionName='0'>
<!-- API level 18 required for EC signing key support
API level 21 required for BluetoothLeScanner -->
- <uses-sdk a:minSdkVersion="21" />
+ <uses-sdk android:minSdkVersion="21" />
- <uses-permission a:name="android.permission.BLUETOOTH"/>
+ <uses-permission android:name="android.permission.BLUETOOTH"/>
<!-- BT admin required for scanning -->
- <uses-permission a:name="android.permission.BLUETOOTH_ADMIN"/>
+ <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<!-- An app must hold ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission in order to get BT scan results. -->
- <uses-permission a:name="android.permission.ACCESS_COARSE_LOCATION"/>
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
- <uses-feature a:name="android.hardware.bluetooth_le" a:required="true"/>
-
- <application a:label="Defogger">
- <activity a:name=".MainActivity">
+ <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
+
+ <application android:label="Defogger">
+ <activity android:name="no.mork.android.defogger.MainActivity">
<intent-filter>
- <category a:name="android.intent.category.LAUNCHER"/>
- <action a:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ <action android:name="android.intent.action.MAIN"/>
</intent-filter>
</activity>
-
<activity
- a:name=".ScannerActivity"
- a:parentActivityName=".MainActivity" />
-
+ android:name="no.mork.android.defogger.ScannerActivity"
+ android:parentActivityName="no.mork.android.defogger.MainActivity" />
<activity
- a:name=".IpCamActivity"
- a:parentActivityName=".MainActivity"
- a:windowSoftInputMode="stateHidden|adjustResize" />
-
+ android:name="no.mork.android.defogger.IpCamActivity"
+ android:parentActivityName="no.mork.android.defogger.MainActivity"
+ android:windowSoftInputMode="stateHidden|adjustResize" />
+ <activity
+ android:name="no.mork.android.defogger.ConfigureNetworkActivity"
+ android:parentActivityName="no.mork.android.defogger.IpCamActivity"
+ android:windowSoftInputMode="stateHidden|adjustResize" />
</application>
-
</manifest>
diff --git a/Defogger/Makefile b/Defogger/Makefile
index 5c24b36..4467cc7 100644
--- a/Defogger/Makefile
+++ b/Defogger/Makefile
@@ -21,9 +21,7 @@ RES=$(addprefix res/,$(RESOURCES))
## Temp disabled while we have some non-building classess....
#CLASSES=obj/no/mork/android/defogger/R.class $(patsubst src/%.java,obj/%.class,$(wildcard src/no/mork/android/defogger/util/*.java) $(wildcard src/no/mork/android/defogger/*.java))
CLASSES=obj/no/mork/android/defogger/R.class $(patsubst src/%.java,obj/%.class,\
- src/no/mork/android/defogger/MainActivity.java \
- src/no/mork/android/defogger/ScannerActivity.java \
- src/no/mork/android/defogger/IpCamActivity.java \
+ $(wildcard src/no/mork/android/defogger/*.java) \
$(wildcard src/com/google/zxing/integration/android/*.java))
all: defogger.apk
diff --git a/Defogger/res/layout/activity_configurenetwork.xml b/Defogger/res/layout/activity_configurenetwork.xml
new file mode 100644
index 0000000..6158fff
--- /dev/null
+++ b/Defogger/res/layout/activity_configurenetwork.xml
@@ -0,0 +1,41 @@
+<LinearLayout 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:orientation="vertical" >
+ <TextView
+ android:id="@+id/netstatus"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:layout_centerVertical="true" />
+ <Button
+ android:id="@+id/finish"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:onClick="doFinish"
+ android:text="Finished"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Password:" />
+ <EditText
+ android:id="@+id/password"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:inputType="text"
+ android:imeOptions="actionNone" />
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Enter SSID or select from list:" />
+ <EditText
+ android:id="@+id/ssid"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:inputType="text"
+ android:imeOptions="actionNone" />
+ <ListView
+ android:id="@+id/networks"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+</LinearLayout>
diff --git a/Defogger/res/layout/activity_ipcam.xml b/Defogger/res/layout/activity_ipcam.xml
index faa8226..b53e206 100644
--- a/Defogger/res/layout/activity_ipcam.xml
+++ b/Defogger/res/layout/activity_ipcam.xml
@@ -26,7 +26,7 @@
android:id="@+id/wificonfig"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:onClick="getWifiConfig"
+ android:onClick="doWifiConfig"
android:text="@string/wificonfig"/>
<TextView
@@ -81,16 +81,4 @@
android:imeOptions="actionDone"
android:imeActionLabel="Run" />
- <Button
- android:id="@+id/setup"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:onClick="getWifiLink"
- android:text="@string/setup"/>
-
- <ListView
- android:id="@+id/networks"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
-
</LinearLayout>
diff --git a/Defogger/res/layout/item_net.xml b/Defogger/res/layout/item_net.xml
index f3f8eb8..b399c43 100644
--- a/Defogger/res/layout/item_net.xml
+++ b/Defogger/res/layout/item_net.xml
@@ -1,29 +1,9 @@
-<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
- <TableRow
- android:layout_width="match_parent"
- android:layout_height="match_parent">
<TextView
android:id="@+id/ssid"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
- <TextView
- android:id="@+id/channel"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content" />
- <TextView
- android:id="@+id/key_mgmt"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content" />
- <TextView
- android:id="@+id/proto"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content" />
- <TextView
- android:id="@+id/rssi"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content" />
- </TableRow>
-</TableLayout>
+</LinearLayout>
diff --git a/Defogger/src/no/mork/android/defogger/ConfigureNetworkActivity.java b/Defogger/src/no/mork/android/defogger/ConfigureNetworkActivity.java
new file mode 100644
index 0000000..7613fa9
--- /dev/null
+++ b/Defogger/src/no/mork/android/defogger/ConfigureNetworkActivity.java
@@ -0,0 +1,127 @@
+/*
+ * SPDX-License-Identifier: GPL-3.0-only
+ * Copyright (c) 2019 Bjørn Mork <bjorn@mork.no>
+ */
+
+package no.mork.android.defogger;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.ParcelUuid;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.view.inputmethod.EditorInfo;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class ConfigureNetworkActivity extends Activity {
+ private static String msg = "Defogger Network Config: ";
+ private ArrayAdapter<String> networklist;
+ private String selected = null;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_configurenetwork);
+
+ // Get the Intent that started this activity and extract parameters
+ Intent intent = getIntent();
+ String[] networks = intent.getStringArrayExtra("networks");
+ if (networks == null)
+ networks = new String[0];
+
+ networklist = new ArrayAdapter<String> (this, R.layout.item_net, networks) {
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ // Check if an existing view is being reused, otherwise inflate the view
+ if (convertView == null) {
+ convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_net, parent, false);
+ }
+
+ //L=I=aaaa7,M=0,C=4,S=4,E=2,P=100
+ // Get the data item for this position
+ String txt = getItem(position);
+ TextView ssid = (TextView) convertView.findViewById(R.id.ssid);
+ ssid.setText(txt.substring(4).split(",", 1)[0]);
+
+ // react when selecting item
+ convertView.setOnClickListener(new OnClickListener() {
+ private String ret = getItem(position).substring(2);
+
+ @Override
+ public void onClick(View v) {
+ Log.d(msg, "onClick() will return " + ret);
+ selected = ret;
+ }
+ });
+
+ return convertView;
+ }
+ };
+
+ ListView listView = (ListView) findViewById(R.id.networks);
+ listView.setAdapter(networklist);
+ intent.putExtra("netconf", "");
+ setResult(RESULT_CANCELED, intent);
+ }
+
+ public void returnConfigResult(String config) {
+ Log.d(msg, "returnConfigResult()");
+ Intent intent = new Intent();
+ if (config != null) {
+ intent.putExtra("netconf", config);
+ setResult(RESULT_OK, intent);
+ } else {
+ intent.putExtra("netconf", "");
+ setResult(RESULT_CANCELED, intent);
+ }
+ finish();
+ }
+
+ public void doFinish(View v) {
+ // cfg = "M=" + net["M"] + ";I=" + essid + ";S=" + net["S"] + ";E=" + net["E"] + ";K=" + passwd
+ // L=I=Telenor_Guest,M=0,C=11,S=0,E=0,P=74
+ // L=I=Telenor_employee,M=0,C=11,S=4,E=2,P=74
+ if (selected == null)
+ returnConfigResult(null);
+
+ Map<String,String> kv = Util.splitKV(selected, ".");
+ EditText edit = (EditText) findViewById(R.id.password);
+ String password = edit.getText().toString();
+ String ret = null;
+ String ssid = kv.get("I"); // FIXME: allow entering SSID in edit field
+ if (password == null)
+ password = "";
+
+ /* assume open network if password is empty? */
+ if (password.length() == 0 && (!kv.get("S").equals("0") || !kv.get("E").equals("0")))
+ returnConfigResult(null);
+ else
+ ret = "M=0;I=" + ssid + ";S=" + kv.get("S") + ";E=" + kv.get("E") + ";K=" + password;
+
+ returnConfigResult(ret);
+ }
+
+ private class NetAdapter extends ArrayAdapter {
+ private int resource;
+
+ public NetAdapter(Context context, int resource, String[] networks) {
+ super(context, resource, networks);
+ this.resource = resource;
+ }
+
+ }
+}
diff --git a/Defogger/src/no/mork/android/defogger/IpCamActivity.java b/Defogger/src/no/mork/android/defogger/IpCamActivity.java
index 7d5ba21..3b0c774 100644
--- a/Defogger/src/no/mork/android/defogger/IpCamActivity.java
+++ b/Defogger/src/no/mork/android/defogger/IpCamActivity.java
@@ -50,6 +50,8 @@ import java.util.UUID;
public class IpCamActivity extends Activity {
private static String msg = "Defogger IPCamActivity: ";
+ private static final int REQUEST_GET_NETWORK = 0x10;
+
private BluetoothGatt mGatt;
private BluetoothGattService ipcamService;
private BluetoothDevice device;
@@ -63,6 +65,8 @@ public class IpCamActivity extends Activity {
private boolean locked = true;
private boolean wifilink = false;
+ private String[] networks;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -71,9 +75,9 @@ public class IpCamActivity extends Activity {
// Get the Intent that started this activity and extract parameters
Intent intent = getIntent();
pincode = intent.getStringExtra("pincode");
- device = intent.getExtras().getParcelable("btdevice");
- if (pincode == null || device == null)
- finish();
+ Bundle b = intent.getExtras();
+ if (b != null)
+ device = b.getParcelable("btdevice");
EditText cmd = (EditText) findViewById(R.id.command);
cmd.setOnEditorActionListener(new OnEditorActionListener() {
@@ -91,39 +95,54 @@ public class IpCamActivity extends Activity {
@Override
protected void onResume() {
+ Log.d(msg, "onResume()");
super.onResume();
connectDevice(device);
}
- // utilities
- private Map<String,String> splitKV(String kv, String splitter)
- {
- Map<String,String> ret = new HashMap();
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ Log.d(msg, "onSaveInstanceState()");
+ outState.putParcelable("btdevice", device);
+ outState.putString("pincode", pincode);
+ }
+
+ @Override
+ public void onRestoreInstanceState(Bundle savedInstanceState) {
+ // Always call the superclass so it can restore the view hierarchy
+ super.onRestoreInstanceState(savedInstanceState);
+ Log.d(msg, "onRestoreInstanceState()");
- for (String s : kv.split(splitter)) {
- String[] foo = s.split("=");
- ret.put(foo[0], foo[1]);
- }
- return ret;
+ // Restore state members from saved instance
+ device = savedInstanceState.getParcelable("btdevice");
+ pincode = savedInstanceState.getString("pincode");
}
- private String calculateKey(String in) {
- MessageDigest md5Hash = null;
- try {
- md5Hash = MessageDigest.getInstance("MD5");
- } catch (NoSuchAlgorithmException e) {
- Log.d(msg, "Exception while encrypting to md5");
+ @Override
+ protected void onActivityResult(int req, int res, Intent intent) {
+ super.onActivityResult(req, res, intent);
+ Log.d(msg, "activity returned result");
+ switch (req) {
+ case REQUEST_GET_NETWORK:
+ if (res == RESULT_OK)
+ handleConfigureNetworkResult(intent.getStringExtra("netconf"));
+ else
+ setStatus("Network configuration was cancelled");
+ break;
+ default:
+ Log.d(msg, "unknown activity result returned???");
}
- byte[] bytes = in.getBytes(StandardCharsets.UTF_8);
- md5Hash.update(bytes, 0, bytes.length);
- String ret = Base64.encodeToString(md5Hash.digest(), Base64.DEFAULT);
- return ret.substring(0, 16);
}
- private UUID UUIDfromInt(long uuid) {
- return new UUID(uuid << 32 | 0x1000 , 0x800000805f9b34fbL);
+ /* offload network selection and password input to another activity */
+ public void startConfigureNetworkActivity(String[] networks) {
+ Intent intent = new Intent(this, ConfigureNetworkActivity.class);
+ intent.putExtra("networks", networks);
+ startActivityForResult(intent, REQUEST_GET_NETWORK);
}
-
+
+
// GATT callbacks
private class GattClientCallback extends BluetoothGattCallback {
private String multimsg;
@@ -149,7 +168,7 @@ public class IpCamActivity extends Activity {
}
// get the IPCam service
// ipcamService = gatt.getService(UUID.fromString("0000d001-0000-1000-8000-00805f9b34fb"));
- ipcamService = gatt.getService(UUIDfromInt(0xd001));
+ ipcamService = gatt.getService(Util.UUIDfromInt(0xd001));
if (ipcamService == null) {
disconnectDevice(gatt.getDevice().getName() + " does not support the IPCam GATT service");
return;
@@ -163,7 +182,7 @@ public class IpCamActivity extends Activity {
public void onCharacteristicRead (BluetoothGatt gatt, BluetoothGattCharacteristic c, int status) {
int code = (int)(c.getUuid().getMostSignificantBits() >> 32);
String val = c.getStringValue(0);
- Map<String,String> kv = splitKV(val, ";");
+ Map<String,String> kv = Util.splitKV(val, ";");
Log.d(msg, c.getUuid().toString() + " returned " + val);
@@ -176,7 +195,7 @@ public class IpCamActivity extends Activity {
}
setStatus("Unlocking " + gatt.getDevice().getName() + " usin pincode " + pincode);
- String key = calculateKey(gatt.getDevice().getName() + pincode + kv.get("C"));
+ String key = Util.calculateKey(gatt.getDevice().getName() + pincode + kv.get("C"));
doUnlock(key);
break;
case 0xa100:
@@ -188,7 +207,7 @@ public class IpCamActivity extends Activity {
if (!kv.get("N").equals(kv.get("P")))
readChar(0xa100);
else
- selectNetwork(multimsg.split("&"));
+ networks = multimsg.split("&");
break;
case 0xa101: // wificonfig
displayWifiConfig(kv);
@@ -210,14 +229,14 @@ public class IpCamActivity extends Activity {
}
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic c) {
- Map<String,String> kv = splitKV(c.getStringValue(0), ";");
+ Map<String,String> kv = Util.splitKV(c.getStringValue(0), ";");
Log.d(msg, String.format("UUID %#06x mode=", Integer.parseInt(kv.get("C"))) + kv.get("A") + " state=" + kv.get("R"));
}
public void onCharacteristicWrite (BluetoothGatt gatt, BluetoothGattCharacteristic c, int status) {
int code = (int)(c.getUuid().getMostSignificantBits() >> 32);
String val = c.getStringValue(0);
- Map<String,String> kv = splitKV(val, ";");
+ Map<String,String> kv = Util.splitKV(val, ";");
Log.d(msg, "Write to " + c.getUuid().toString() + " status=" + status + ", value is now: " + val);
@@ -313,58 +332,9 @@ public class IpCamActivity extends Activity {
});
}
- private class NetAdapter extends ArrayAdapter<String> {
- private int resource;
-
- public NetAdapter(Context context, int resource, String[] networks) {
- super(context, resource, networks);
- this.resource = resource;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- //L=I=aaaa7,M=0,C=4,S=4,E=2,P=100
- // Get the data item for this position
- Map<String,String> net = splitKV(getItem(position).substring(2), ",");
-
- // Check if an existing view is being reused, otherwise inflate the view
- if (convertView == null) {
- convertView = LayoutInflater.from(getContext()).inflate(resource, parent, false);
- }
-
- // Lookup view for data population
- TextView ssid = (TextView) convertView.findViewById(R.id.ssid);
- TextView channel = (TextView) convertView.findViewById(R.id.channel);
- TextView key_mgmt = (TextView) convertView.findViewById(R.id.key_mgmt);
- TextView proto = (TextView) convertView.findViewById(R.id.proto);
- TextView rssi = (TextView) convertView.findViewById(R.id.rssi);
-
- // Populate the data into the template view using the data object
- ssid.setText(net.get("I"));
- channel.setText(net.get("C"));
- key_mgmt.setText(net.get("S"));
- proto.setText(net.get("E"));
- rssi.setText(net.get("P"));
-
- // Return the completed view to render on screen
- return convertView;
- }
- }
-
- private void selectNetwork(String[] networks) {
- Context ctx = this;
- Log.d(msg, "displayWifiConfig()");
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- ArrayAdapter<String> itemsAdapter = new NetAdapter(ctx, R.layout.item_net, networks);
- ListView listView = (ListView) findViewById(R.id.networks);
- listView.setAdapter(itemsAdapter);
- }
- });
- }
-
private void connectDevice(BluetoothDevice device) {
+ if (device == null)
+ return;
Log.d(msg, "connectDevice() " + device.getAddress());
// create queues
@@ -400,17 +370,7 @@ public class IpCamActivity extends Activity {
finish();
}
- // camera specific code
- private void setLocked(boolean lock) {
- if (lock == locked)
- return;
-
- locked = lock;
- setStatus(mGatt.getDevice().getName() + " is " + (lock ? "locked" : "unlocked"));
- if (locked)
- return;
-
- /* collect current config after unlocking */
+ private void getCurrentConfig() {
View v = new View(this);
getWifiLink(v);
getWifiConfig(v);
@@ -419,11 +379,23 @@ public class IpCamActivity extends Activity {
doWifiScan(v);
}
+ // camera specific code
+ private void setLocked(boolean lock) {
+ if (lock == locked)
+ return;
+ locked = lock;
+ setStatus(mGatt.getDevice().getName() + " is " + (lock ? "locked" : "unlocked"));
+
+ /* autocollect current config after unlocking */
+ if (!locked)
+ getCurrentConfig();
+ }
+
private void notifications(boolean enable) {
if (!connected || !enable)
return;
Log.d(msg, "notifications()");
- BluetoothGattCharacteristic c = ipcamService.getCharacteristic(UUIDfromInt(0xa000));
+ BluetoothGattCharacteristic c = ipcamService.getCharacteristic(Util.UUIDfromInt(0xa000));
if (!mGatt.setCharacteristicNotification(c, enable))
Log.d(msg, "failed to enable notifications");
@@ -432,7 +404,7 @@ public class IpCamActivity extends Activity {
* ref: https://stackoverflow.com/questions/27068673/subscribe-to-a-ble-gatt-notification-android
* 0x2902 org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
*/
- BluetoothGattDescriptor descriptor = c.getDescriptor(UUIDfromInt(0x2902));
+ BluetoothGattDescriptor descriptor = c.getDescriptor(Util.UUIDfromInt(0x2902));
descriptor.setValue(enable ? BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE : BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
mGatt.writeDescriptor(descriptor);
}
@@ -442,7 +414,7 @@ public class IpCamActivity extends Activity {
Log.d(msg, "getLock() already unlocked");
return;
}
- BluetoothGattCharacteristic c = ipcamService.getCharacteristic(UUIDfromInt(0xa001));
+ BluetoothGattCharacteristic c = ipcamService.getCharacteristic(Util.UUIDfromInt(0xa001));
mGatt.readCharacteristic(c);
}
@@ -450,7 +422,7 @@ public class IpCamActivity extends Activity {
if (!connected)
return;
Log.d(msg, "doUnlock(), key is " + key);
- BluetoothGattCharacteristic c = ipcamService.getCharacteristic(UUIDfromInt(0xa001));
+ BluetoothGattCharacteristic c = ipcamService.getCharacteristic(Util.UUIDfromInt(0xa001));
c.setValue("M=0;K=" + key);
mGatt.writeCharacteristic(c);
}
@@ -468,7 +440,7 @@ public class IpCamActivity extends Activity {
private void readChar(int num) {
if (!connected)
return;
- BluetoothGattCharacteristic c = ipcamService.getCharacteristic(UUIDfromInt(num));
+ BluetoothGattCharacteristic c = ipcamService.getCharacteristic(Util.UUIDfromInt(num));
if (locked) {
Log.d(msg, "camera is locked");
readQ.offer(c);
@@ -483,7 +455,7 @@ public class IpCamActivity extends Activity {
private void writeChar(int num, String val) {
if (!connected)
return;
- BluetoothGattCharacteristic c = ipcamService.getCharacteristic(UUIDfromInt(num));
+ BluetoothGattCharacteristic c = ipcamService.getCharacteristic(Util.UUIDfromInt(num));
c.setValue(val);
if (locked) {
Log.d(msg, "camera is locked");
@@ -495,10 +467,15 @@ public class IpCamActivity extends Activity {
writeQ.offer(c);
}
+ /* WiFi scan is required for network configuration */
public void doWifiScan(View view) {
readChar(0xa100);
}
+ public void doWifiConfig(View view) {
+ startConfigureNetworkActivity(networks);
+ }
+
public void getWifiConfig(View view) {
readChar(0xa101);
}
@@ -542,22 +519,33 @@ public class IpCamActivity extends Activity {
runCommand("tdb set SecureFW _TrustLevel_byte=0");
}
- /*
- private void setWifi(String essid, String passwd) {
- if (wifiScanResults == null) {
- doWifiScan(gatt);
+ private void handleConfigureNetworkResult(String netconf) {
+ /* Validate result from ConfigureNetwork activity */
+ if (netconf == null) {
+ setStatus("Network configuration was cancelled");
return;
}
-
- writeChar(0xa101, "P=;N=" + pincode);
+
+ /* sanity check result */
+ Map<String,String> kv = Util.splitKV(netconf, ";");
+ if (!kv.containsKey("M") || !kv.containsKey("I") || !kv.containsKey("S") || !kv.containsKey("E") || !kv.containsKey("K")) {
+ setStatus("Network configuration failure - data missing");
+ return;
+ }
+
+ /* OK, go */
+ writeChar(0xa101, netconf); // configure wifi
+ writeChar(0xa102, "C=1"); // connect
+
+ /* refresh current settings for display */
+ getCurrentConfig();
}
- */
-
+
+ /* does this work? */
private void setInitialPassword() {
queuedSetPassword("P=;N=" + pincode);
}
-
/*
* writing a series of values to this characteristic is not the
* same as writing the last value only, which is how a
diff --git a/Defogger/src/no/mork/android/defogger/MainActivity.java b/Defogger/src/no/mork/android/defogger/MainActivity.java
index 34cc562..d90413a 100644
--- a/Defogger/src/no/mork/android/defogger/MainActivity.java
+++ b/Defogger/src/no/mork/android/defogger/MainActivity.java
@@ -40,6 +40,7 @@ public class MainActivity extends Activity {
@Override
protected void onResume() {
+ Log.d(msg, "onResume()");
super.onResume();
getBluetoothAdapter();
}
diff --git a/Defogger/src/no/mork/android/defogger/ScannerActivity.java b/Defogger/src/no/mork/android/defogger/ScannerActivity.java
index f9ae304..310e8dd 100644
--- a/Defogger/src/no/mork/android/defogger/ScannerActivity.java
+++ b/Defogger/src/no/mork/android/defogger/ScannerActivity.java
@@ -81,7 +81,7 @@ public class ScannerActivity extends Activity implements Runnable {
TextView txt = (TextView) convertView.findViewById(R.id.scanitem);
txt.setText(device.getAddress() + " - " + device.getName());
- // react when selecting iteam
+ // react when selecting item
convertView.setOnClickListener(new OnClickListener() {
private BluetoothDevice ret = device;
diff --git a/Defogger/src/no/mork/android/defogger/Util.java b/Defogger/src/no/mork/android/defogger/Util.java
new file mode 100644
index 0000000..1492843
--- /dev/null
+++ b/Defogger/src/no/mork/android/defogger/Util.java
@@ -0,0 +1,48 @@
+/*
+ * SPDX-License-Identifier: GPL-3.0-only
+ * Copyright (c) 2019 Bjørn Mork <bjorn@mork.no>
+ */
+
+package no.mork.android.defogger;
+
+import android.util.Base64;
+import android.util.Log;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+public class Util {
+ private static String msg = "Defogger Util: ";
+
+ public static Map<String,String> splitKV(String kv, String splitter)
+ {
+ Map<String,String> ret = new HashMap();
+
+ for (String s : kv.split(splitter)) {
+ String[] foo = s.split("=");
+ ret.put(foo[0], foo[1]);
+ }
+ return ret;
+ }
+
+ public static String calculateKey(String in) {
+ MessageDigest md5Hash = null;
+ try {
+ md5Hash = MessageDigest.getInstance("MD5");
+ } catch (NoSuchAlgorithmException e) {
+ Log.d(msg, "Exception while encrypting to md5");
+ }
+ byte[] bytes = in.getBytes(StandardCharsets.UTF_8);
+ md5Hash.update(bytes, 0, bytes.length);
+ String ret = Base64.encodeToString(md5Hash.digest(), Base64.DEFAULT);
+ return ret.substring(0, 16);
+ }
+
+ public static UUID UUIDfromInt(long uuid) {
+ return new UUID(uuid << 32 | 0x1000 , 0x800000805f9b34fbL);
+ }
+}