diff options
author | Bjørn Mork <bjorn@mork.no> | 2019-06-03 22:53:44 +0200 |
---|---|---|
committer | Bjørn Mork <bjorn@mork.no> | 2019-06-03 22:54:59 +0200 |
commit | d89b7c37ca5fc790f9ac02dfebb808fb16406ae3 (patch) | |
tree | 347dbf4847255f1709894f94407c7193499a5eb7 | |
parent | 6263515f4bf93f12769bb30b6d59a484f90f5e27 (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.xml | 44 | ||||
-rw-r--r-- | Defogger/Makefile | 4 | ||||
-rw-r--r-- | Defogger/res/layout/activity_configurenetwork.xml | 41 | ||||
-rw-r--r-- | Defogger/res/layout/activity_ipcam.xml | 14 | ||||
-rw-r--r-- | Defogger/res/layout/item_net.xml | 24 | ||||
-rw-r--r-- | Defogger/src/no/mork/android/defogger/ConfigureNetworkActivity.java | 127 | ||||
-rw-r--r-- | Defogger/src/no/mork/android/defogger/IpCamActivity.java | 204 | ||||
-rw-r--r-- | Defogger/src/no/mork/android/defogger/MainActivity.java | 1 | ||||
-rw-r--r-- | Defogger/src/no/mork/android/defogger/ScannerActivity.java | 2 | ||||
-rw-r--r-- | Defogger/src/no/mork/android/defogger/Util.java | 48 |
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); + } +} |