From 76b17543bee2c38995fca07e21d5b271eddb7369 Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Sat, 6 Dec 2014 19:25:51 +0100 Subject: o Moving out the executor so it becomes its own class. o Adding seek bars to each gauge. Sending updates to the device. --- .../no/topi/fiken/display/BtActionExecutor.java | 171 +++++++++++++ .../java/no/topi/fiken/display/BtCallback.java | 49 ++++ .../topi/fiken/display/DefaultDisplayService.java | 265 +++++++-------------- .../topi/fiken/display/DisplayControlActivity.java | 58 ++++- .../java/no/topi/fiken/display/DisplayService.java | 9 +- .../no/topi/fiken/display/FikenStatusPanel.java | 68 ++++++ .../topi/fiken/display/NotOverriddenException.java | 4 + .../main/res/layout/activity_display_control.xml | 4 +- app/src/main/res/layout/fragment_gauge.xml | 24 ++ 9 files changed, 459 insertions(+), 193 deletions(-) create mode 100644 app/src/main/java/no/topi/fiken/display/BtActionExecutor.java create mode 100644 app/src/main/java/no/topi/fiken/display/BtCallback.java create mode 100644 app/src/main/java/no/topi/fiken/display/FikenStatusPanel.java create mode 100644 app/src/main/java/no/topi/fiken/display/NotOverriddenException.java create mode 100644 app/src/main/res/layout/fragment_gauge.xml diff --git a/app/src/main/java/no/topi/fiken/display/BtActionExecutor.java b/app/src/main/java/no/topi/fiken/display/BtActionExecutor.java new file mode 100644 index 0000000..022bbc7 --- /dev/null +++ b/app/src/main/java/no/topi/fiken/display/BtActionExecutor.java @@ -0,0 +1,171 @@ +package no.topi.fiken.display; + +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCallback; +import android.bluetooth.BluetoothGattCharacteristic; +import android.bluetooth.BluetoothGattDescriptor; +import android.util.Log; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.List; +import java.util.Queue; + +class BtActionExecutor { + private final static String TAG = BtActionExecutor.class.getSimpleName(); + Queue actions = new ArrayDeque(); + Queue fallbackActions = new ArrayDeque(); + private final Runnable disconnect; + List remoteRssi = new ArrayList(); + + BtActionExecutor(Runnable disconnect) { + this.disconnect = disconnect; + } + + public static final BtCallback waitForIt = new BtCallback("Wait for it") { + @Override + public boolean onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { + Log.w(TAG, "wait for it...!"); + return true; + } + }; + + public synchronized BtActionExecutor onSuccess(BtCallback btCallback) { + actions.add(btCallback); + return this; + } + + public synchronized BtActionExecutor addFallback(BtCallback btCallback) { + fallbackActions.add(btCallback); + return this; + } + + public synchronized BtActionExecutor onRemoteRssi(BluetoothGattCallback callback) { + remoteRssi.add(callback); + return this; + } + + public void onEvent(String key, String values, BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, BluetoothGattDescriptor descriptor, int status, int newState) { + if (status != BluetoothGatt.GATT_SUCCESS) { + Log.w(TAG, "Operation failed: " + key + ", " + values); + return; + } + + Log.i(TAG, "Bt action completed successfully: callback=" + key); + + BtCallback btCallback; + synchronized (this) { + if (actions.isEmpty()) { + Log.d(TAG, "All Bluetooth actions are done"); + + for (BtCallback callback = fallbackActions.poll(); callback != null; callback = fallbackActions.poll()) { + try { + callCallback(key, gatt, characteristic, descriptor, newState, callback); + } catch (NotOverriddenException e) { + return; + } + } + + return; + } + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + // ignore + } + btCallback = actions.remove(); + Log.i(TAG, "Executing bt action: " + btCallback.name); + } + + boolean ok; + + try { + ok = callCallback(key, gatt, characteristic, descriptor, newState, btCallback); + } catch (NotOverriddenException e) { + Log.w(TAG, "Unexpected callback by listener: " + key); + disconnect.run(); + return; + } + + if (!ok) { + Log.w(TAG, "Error performing Bluetooth action."); + disconnect.run(); + } + } + + private Boolean callCallback(String key, BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, BluetoothGattDescriptor descriptor, int newState, BtCallback btCallback) { + if (key.equals("onConnectionStateChange")) { + return btCallback.onConnectionStateChange(gatt, newState); + } else if (key.equals("onServicesDiscovered")) { + return btCallback.onServicesDiscovered(gatt); + } else if (key.equals("onCharacteristicRead")) { + return btCallback.onCharacteristicRead(gatt, characteristic); + } else if (key.equals("onCharacteristicWrite")) { + return btCallback.onCharacteristicWrite(gatt, characteristic); + } else if (key.equals("onCharacteristicChanged")) { + return btCallback.onCharacteristicChanged(gatt, characteristic); + } else if (key.equals("onDescriptorRead")) { + return btCallback.onDescriptorRead(gatt, descriptor); + } else if (key.equals("onDescriptorWrite")) { + return btCallback.onDescriptorWrite(gatt, descriptor); + } else if (key.equals("onReliableWriteCompleted")) { + return btCallback.onReliableWriteCompleted(gatt); + } + + Log.w(TAG, "Unknown callback: " + key); + return null; + } + + public BluetoothGattCallback asCallback() { + return new BluetoothGattCallback() { + + @Override + public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { + onEvent("onConnectionStateChange", "status=" + status + ", newState=" + newState, gatt, null, null, status, newState); + } + + @Override + public void onServicesDiscovered(BluetoothGatt gatt, int status) { + onEvent("onServicesDiscovered", "status=" + status, gatt, null, null, status, 9); + } + + @Override + public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { + onEvent("onCharacteristicRead", "status=" + status + ", characteristic=" + characteristic.getUuid(), gatt, characteristic, null, status, 0); + } + + @Override + public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { + onEvent("onCharacteristicWrite", "status=" + status + ", characteristic=" + characteristic.getUuid(), gatt, characteristic, null, status, 0); + } + + @Override + public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { + onEvent("onCharacteristicChanged", "characteristic=" + characteristic.getUuid(), gatt, characteristic, null, BluetoothGatt.GATT_SUCCESS, 0); + } + + @Override + public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { + onEvent("onDescriptorRead", "status=" + status + ", descriptor=" + descriptor.getUuid(), gatt, null, descriptor, status, 0); + } + + @Override + public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { + onEvent("onDescriptorWrite", "status=" + status + ", descriptor=" + descriptor.getUuid(), gatt, null, descriptor, status, 0); + } + + @Override + public void onReliableWriteCompleted(BluetoothGatt gatt, int status) { + onEvent("onReliableWriteCompleted", "status=" + status, gatt, null, null, status, 0); + } + + @Override + public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) { + for (BluetoothGattCallback callback : remoteRssi) { + callback.onReadRemoteRssi(gatt, rssi, status); + } + } + }; + } +} diff --git a/app/src/main/java/no/topi/fiken/display/BtCallback.java b/app/src/main/java/no/topi/fiken/display/BtCallback.java new file mode 100644 index 0000000..f637bd9 --- /dev/null +++ b/app/src/main/java/no/topi/fiken/display/BtCallback.java @@ -0,0 +1,49 @@ +package no.topi.fiken.display; + +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCharacteristic; +import android.bluetooth.BluetoothGattDescriptor; + +class BtCallback { + public final String name; + + BtCallback(String name) { + this.name = name; + } + + public boolean onConnectionStateChange(BluetoothGatt gatt, int newState) { + throw new NotOverriddenException(); + } + + public boolean onServicesDiscovered(BluetoothGatt gatt) { + throw new NotOverriddenException(); + } + + public boolean onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { + throw new NotOverriddenException(); + } + + public boolean onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { + throw new NotOverriddenException(); + } + + public boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { + throw new NotOverriddenException(); + } + + public boolean onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor) { + throw new NotOverriddenException(); + } + + public boolean onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor) { + throw new NotOverriddenException(); + } + + public boolean onReliableWriteCompleted(BluetoothGatt gatt) { + throw new NotOverriddenException(); + } + + public boolean onReadRemoteRssi(BluetoothGatt gatt, int rssi) { + throw new NotOverriddenException(); + } +} diff --git a/app/src/main/java/no/topi/fiken/display/DefaultDisplayService.java b/app/src/main/java/no/topi/fiken/display/DefaultDisplayService.java index 53b00fc..9a4cbf0 100644 --- a/app/src/main/java/no/topi/fiken/display/DefaultDisplayService.java +++ b/app/src/main/java/no/topi/fiken/display/DefaultDisplayService.java @@ -16,14 +16,11 @@ import android.os.IBinder; import android.util.Log; import android.widget.Toast; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.List; -import java.util.Queue; +import java.util.concurrent.atomic.AtomicInteger; public class DefaultDisplayService extends Service implements DisplayService { - private final Context context = DefaultDisplayService.this; private final static String TAG = DefaultDisplayService.class.getSimpleName(); + private final Context context = DefaultDisplayService.this; private final IBinder binder = new LocalBinder(this); @@ -37,6 +34,8 @@ public class DefaultDisplayService extends Service implements DisplayService { BluetoothGattService displayService; BluetoothGattCharacteristic gaugeCtrl; BluetoothGattCharacteristic gaugeData; + + FikenStatusPanel fikenStatusPanel = new FikenStatusPanel(); } private Handler handler; @@ -113,9 +112,14 @@ public class DefaultDisplayService extends Service implements DisplayService { state = new State(); BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); - BtActionExecutor executor = new BtActionExecutor(); + final BtActionExecutor executor = new BtActionExecutor(new Runnable() { + @Override + public void run() { + disconnect(); + } + }); - executor.onSuccess(new BtCallback() { + executor.onSuccess(new BtCallback("Connect") { @Override public boolean onConnectionStateChange(BluetoothGatt gatt, int newState) { boolean ok = gatt.discoverServices(); @@ -131,12 +135,24 @@ public class DefaultDisplayService extends Service implements DisplayService { return true; } - }).onSuccess(new BtCallback() { + }).onSuccess(new BtCallback("Service discovered") { @Override public boolean onServicesDiscovered(BluetoothGatt gatt) { Log.i(TAG, "Services discovered"); state.displayService = gatt.getService(Constants.TRYGVIS_IO_FIKEN_STATUS_PANEL_UUID); + + if (state.displayService == null) { + Log.e(TAG, "Could not find display service on device."); + + Intent intent = IntentAction.DEVICE_UPDATE.intent(); + intent.putExtra(IntentExtra.DEVICE_ADDRESS.name(), address); + intent.putExtra(IntentExtra.DEVICE_IS_DISPLAY.name(), state.displayService != null); + sendBroadcast(intent); + + return false; + } + state.gaugeCtrl = state.displayService.getCharacteristic(Constants.TRYGVIS_IO_GAUGE_CTRL_UUID); state.gaugeData = state.displayService.getCharacteristic(Constants.TRYGVIS_IO_GAUGE_DATA_UUID); @@ -152,42 +168,55 @@ public class DefaultDisplayService extends Service implements DisplayService { gatt.setCharacteristicNotification(state.gaugeCtrl, true); return gatt.writeDescriptor(ccg); } - }).onSuccess(new BtCallback() { + }).onSuccess(new BtCallback("Get gauge count") { @Override public boolean onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor) { - state.gaugeCtrl.setValue(new byte[]{0x01}); - gatt.writeCharacteristic(state.gaugeCtrl); - - return true; + state.gaugeCtrl.setValue(FikenStatusPanel.getGaugeCountReq()); + return gatt.writeCharacteristic(state.gaugeCtrl); } - }).onSuccess(new BtCallback() { + }).onSuccess(new BtCallback("data written") { @Override public boolean onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { Log.w(TAG, "wait for it...!"); return true; } - }).onSuccess(new BtCallback() { + }).onSuccess(new BtCallback("Got gauge count") { @Override public boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { byte[] value = state.gaugeCtrl.getValue(); - Log.w(TAG, "gauge bytes: " + toHexString(value)); - - if (value.length != 2) { - Log.w(TAG, "Bad response, expected value.length to be 2, was " + value.length); - return false; - } - - int gaugeCount = (int) value[1]; - - Log.d(TAG, "Gauge count=" + gaugeCount); + state.fikenStatusPanel.update(value); + int gaugeCount = state.fikenStatusPanel.gaugeCount(); Intent intent = IntentAction.DEVICE_UPDATE.intent(); intent.putExtra(IntentExtra.DEVICE_ADDRESS.name(), address); intent.putExtra(IntentExtra.GAUGE_COUNT.name(), gaugeCount); sendBroadcast(intent); - return true; + final AtomicInteger i = new AtomicInteger(0); + + executor.addFallback(updateGaugeValue); + executor.onSuccess(BtActionExecutor.waitForIt); + executor.onSuccess(new BtCallback("Get gauge value") { + @Override + public boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { + updateGaugeValue.onCharacteristicChanged(gatt, characteristic); + + int next = i.incrementAndGet(); + + if (next == state.fikenStatusPanel.gaugeCount()) { + return true; + } + + executor.onSuccess(BtActionExecutor.waitForIt); + executor.onSuccess(this); + state.gaugeCtrl.setValue(FikenStatusPanel.getGaugeValueReq((byte) next)); + return gatt.writeCharacteristic(state.gaugeCtrl); + } + }); + + state.gaugeCtrl.setValue(FikenStatusPanel.getGaugeValueReq((byte) 0)); + return gatt.writeCharacteristic(state.gaugeCtrl); } }); @@ -211,164 +240,6 @@ public class DefaultDisplayService extends Service implements DisplayService { } } - private static class BtCallback { - public boolean onConnectionStateChange(BluetoothGatt gatt, int newState) { - throw new NotOverriddenException(); - } - - public boolean onServicesDiscovered(BluetoothGatt gatt) { - throw new NotOverriddenException(); - } - - public boolean onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { - throw new NotOverriddenException(); - } - - public boolean onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { - throw new NotOverriddenException(); - } - - public boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { - throw new NotOverriddenException(); - } - - public boolean onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor) { - throw new NotOverriddenException(); - } - - public boolean onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor) { - throw new NotOverriddenException(); - } - - public boolean onReliableWriteCompleted(BluetoothGatt gatt) { - throw new NotOverriddenException(); - } - - public boolean onReadRemoteRssi(BluetoothGatt gatt, int rssi) { - throw new NotOverriddenException(); - } - } - - private static class NotOverriddenException extends RuntimeException { - } - - private class BtActionExecutor { - Queue actions = new ArrayDeque(); - List remoteRssi = new ArrayList(); - - - public BtActionExecutor onSuccess(BtCallback btCallback) { - actions.add(btCallback); - return this; - } - - public BtActionExecutor onRemoteRssi(BluetoothGattCallback callback) { - remoteRssi.add(callback); - return this; - } - - public void onEvent(String key, BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, BluetoothGattDescriptor descriptor, int status, int newState) { - if (status != BluetoothGatt.GATT_SUCCESS) { - Log.w(TAG, "Operation failed: " + key); - } - - Log.i(TAG, "Bt action completed successfully: callback=" + key); - - if (!actions.isEmpty()) { - BtCallback btCallback = actions.remove(); - Log.i(TAG, "Executing bt action"); - - boolean ok; - - try { - if (key.equals("onConnectionStateChange")) { - ok = btCallback.onConnectionStateChange(gatt, newState); - } else if (key.equals("onServicesDiscovered")) { - ok = btCallback.onServicesDiscovered(gatt); - } else if (key.equals("onCharacteristicRead")) { - ok = btCallback.onCharacteristicRead(gatt, characteristic); - } else if (key.equals("onCharacteristicWrite")) { - ok = btCallback.onCharacteristicWrite(gatt, characteristic); - } else if (key.equals("onCharacteristicChanged")) { - ok = btCallback.onCharacteristicChanged(gatt, characteristic); - } else if (key.equals("onDescriptorRead")) { - ok = btCallback.onDescriptorRead(gatt, descriptor); - } else if (key.equals("onDescriptorWrite")) { - ok = btCallback.onDescriptorWrite(gatt, descriptor); - } else if (key.equals("onReliableWriteCompleted")) { - ok = btCallback.onReliableWriteCompleted(gatt); - } else { - Log.w(TAG, "Unknown callback: " + key); - return; - } - } catch (NotOverriddenException e) { - Log.w(TAG, "Unexpected callback by listener: " + key); - disconnect(); - return; - } - - if (!ok) { - Log.w(TAG, "Error performing Bluetooth action."); - disconnect(); - } - } else { - Log.d(TAG, "All Bluetooth actions are done"); - } - } - - public BluetoothGattCallback asCallback() { - return new BluetoothGattCallback() { - - @Override - public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { - onEvent("onConnectionStateChange", gatt, null, null, status, newState); - } - - @Override - public void onServicesDiscovered(BluetoothGatt gatt, int status) { - onEvent("onServicesDiscovered", gatt, null, null, status, 9); - } - - @Override - public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { - onEvent("onCharacteristicRead", gatt, characteristic, null, status, 0); - } - - @Override - public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { - onEvent("onCharacteristicWrite", gatt, characteristic, null, status, 0); - } - - @Override - public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { - onEvent("onCharacteristicChanged", gatt, characteristic, null, BluetoothGatt.GATT_SUCCESS, 0); - } - - @Override - public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { - onEvent("onDescriptorRead", gatt, null, descriptor, status, 0); - } - - @Override - public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { - onEvent("onDescriptorWrite", gatt, null, descriptor, status, 0); - } - - @Override - public void onReliableWriteCompleted(BluetoothGatt gatt, int status) { - onEvent("onReliableWriteCompleted", gatt, null, null, status, 0); - } - - @Override - public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) { - for (BluetoothGattCallback callback : remoteRssi) { - callback.onReadRemoteRssi(gatt, rssi, status); - } - } - }; - } - } - @Override public void disconnect() { if (serviceState != ServiceState.CONNECTED) { @@ -421,6 +292,17 @@ public class DefaultDisplayService extends Service implements DisplayService { serviceState = ServiceState.IDLE; } + @Override + public FikenStatusPanel getStatusPanel() { + return state != null ? state.fikenStatusPanel : null; + } + + @Override + public void setGauge(int gauge, int value) { + state.gaugeCtrl.setValue(FikenStatusPanel.setGaugeValueReq((byte) gauge, (byte) value)); + state.gatt.writeCharacteristic(state.gaugeCtrl); + } + private BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) { @@ -444,4 +326,19 @@ public class DefaultDisplayService extends Service implements DisplayService { return s.toString(); } + + private final BtCallback updateGaugeValue = new BtCallback("Update gauge value") { + @Override + public boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { + if (state != null) { + state.fikenStatusPanel.update(state.gaugeCtrl.getValue()); + + Intent intent = IntentAction.DEVICE_UPDATE.intent(); + intent.putExtra(IntentExtra.DEVICE_ADDRESS.name(), gatt.getDevice().getAddress()); + intent.putExtra(IntentExtra.GAUGE_VALUE_CHANGED.name(), 0); + sendBroadcast(intent); + } + return true; + } + }; } diff --git a/app/src/main/java/no/topi/fiken/display/DisplayControlActivity.java b/app/src/main/java/no/topi/fiken/display/DisplayControlActivity.java index 1a537d9..8cd16ec 100644 --- a/app/src/main/java/no/topi/fiken/display/DisplayControlActivity.java +++ b/app/src/main/java/no/topi/fiken/display/DisplayControlActivity.java @@ -12,6 +12,7 @@ import android.view.Menu; import android.view.View; import android.widget.Button; import android.widget.LinearLayout; +import android.widget.SeekBar; import android.widget.TextView; import static java.lang.String.valueOf; @@ -28,7 +29,6 @@ public class DisplayControlActivity extends Activity { private TextView deviceNameView; private TextView deviceRssiView; - private TextView gaugeCountView; private LinearLayout gaugesLayout; @Override @@ -46,7 +46,6 @@ public class DisplayControlActivity extends Activity { deviceNameView = (TextView) findViewById(R.id.device_name); deviceRssiView = (TextView) findViewById(R.id.device_rssi); - gaugeCountView = (TextView) findViewById(R.id.gauge_count); gaugesLayout = (LinearLayout) findViewById(R.id.gauges); Button disconnectButton = (Button) findViewById(R.id.button_disconnect); @@ -63,7 +62,6 @@ public class DisplayControlActivity extends Activity { private void updateValues() { deviceNameView.setText(deviceInfo.name != null ? deviceInfo.name : getText(R.string.name_unknown)); deviceRssiView.setText(getText(R.string.rssi) + ": " + (deviceInfo.rssi != 0 ? valueOf(deviceInfo.rssi) : "")); - gaugeCountView.setText(getText(R.string.gauge_count) + ": " + (deviceInfo.gaugeCount)); } @Override @@ -135,7 +133,59 @@ public class DisplayControlActivity extends Activity { finish(); } } - updateValues(); + if (intent.hasExtra(IntentExtra.GAUGE_COUNT.name())) { + int count = intent.getIntExtra(IntentExtra.GAUGE_COUNT.name(), 0); + + if (gaugesLayout.getChildCount() == 0) { + for (int i = 0; i < count; i++) { + final int gauge = i; + View gaugeView = getLayoutInflater().inflate(R.layout.fragment_gauge, null); + + final TextView title = (TextView) gaugeView.findViewById(R.id.gauge_title); + title.setText("Gauge " + (i + 1)); + + SeekBar value = (SeekBar) gaugeView.findViewById(R.id.gauge_seek_bar); + value.setMax(255); + value.setProgress(0); + value.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + int value = seekBar.getProgress(); + title.setText("Value: " + value); + displayService.setGauge(gauge, value); + } + }); + gaugesLayout.addView(gaugeView); + } + } + } + if (intent.hasExtra(IntentExtra.GAUGE_VALUE_CHANGED.name())) { + for (int gauge = 0; gauge < gaugesLayout.getChildCount(); gauge++) { + FikenStatusPanel statusPanel = displayService.getStatusPanel(); + Integer gaugeValue = statusPanel.get(gauge); + if (gaugeValue != null) { + View gaugeView = gaugesLayout.getChildAt(gauge); + SeekBar seekBar = (SeekBar) gaugeView.findViewById(R.id.gauge_seek_bar); + if (seekBar != null) { + seekBar.setProgress(gaugeValue); + } + + TextView title = (TextView) gaugeView.findViewById(R.id.gauge_title); + if (title != null) { + title.setText("Gauge " + gaugeValue); + } + } + } + updateValues(); + } } }); } diff --git a/app/src/main/java/no/topi/fiken/display/DisplayService.java b/app/src/main/java/no/topi/fiken/display/DisplayService.java index 666a750..34e6ff9 100644 --- a/app/src/main/java/no/topi/fiken/display/DisplayService.java +++ b/app/src/main/java/no/topi/fiken/display/DisplayService.java @@ -14,6 +14,7 @@ public interface DisplayService { SCANNING, CONNECTED, GAUGE_COUNT, + GAUGE_VALUE_CHANGED, } public static enum IntentAction { @@ -62,10 +63,13 @@ public interface DisplayService { public void disconnect(); + FikenStatusPanel getStatusPanel(); + + void setGauge(int gauge, int value); + class DeviceInfo { final String address; int rssi = 0; - int gaugeCount = 0; Boolean isDisplay = null; String name; @@ -99,9 +103,6 @@ public interface DisplayService { if (intent.hasExtra(IntentExtra.DEVICE_NAME.name())) { name = intent.getStringExtra(IntentExtra.DEVICE_NAME.name()); } - if (intent.hasExtra(IntentExtra.GAUGE_COUNT.name())) { - gaugeCount = intent.getIntExtra(IntentExtra.GAUGE_COUNT.name(), 0); - } } } } diff --git a/app/src/main/java/no/topi/fiken/display/FikenStatusPanel.java b/app/src/main/java/no/topi/fiken/display/FikenStatusPanel.java new file mode 100644 index 0000000..fb7f5e1 --- /dev/null +++ b/app/src/main/java/no/topi/fiken/display/FikenStatusPanel.java @@ -0,0 +1,68 @@ +package no.topi.fiken.display; + +import android.util.Log; + +import static no.topi.fiken.display.DefaultDisplayService.toHexString; + +public class FikenStatusPanel { + private final static String TAG = DefaultDisplayService.class.getSimpleName(); + + public static final byte + FSP_CMD_GET_GAUGE_COUNT = (byte) 0x01, + FSP_CMD_SET_GAUGE = (byte) 0x02, + FSP_CMD_GET_GAUGE = (byte) 0x03, + FSP_CMD_FAIL = (byte) 0xff; + + private Integer[] gauges; + + public int gaugeCount() { + return gauges != null ? gauges.length : 0; + } + + public Integer get(int gauge) { + return gauges[gauge]; + } + + public void update(byte[] data) { + Log.d(TAG, "data=" + toHexString(data)); + byte len = data[0]; + byte code = data[1]; + + switch (code) { + case FSP_CMD_GET_GAUGE_COUNT: + byte count = data[2]; + gauges = new Integer[count]; + Log.d(TAG, "Gauge count=" + count); + break; + case FSP_CMD_GET_GAUGE: + byte gauge = data[2]; + byte value = data[3]; + Log.d(TAG, "Gauge #" + gauge + ", value=" + value); + if (gauge < gauges.length) { + gauges[gauge] = 0xff & value; + } + break; + case FSP_CMD_FAIL: + Log.e(TAG, "FSP_CMD_FAIL"); + break; + case FSP_CMD_SET_GAUGE: + // ignored + break; + default: + Log.w(TAG, "Unknown code: " + code); + break; + } + } + + public static byte[] getGaugeCountReq() { + return new byte[]{FSP_CMD_GET_GAUGE_COUNT}; + } + + public static byte[] getGaugeValueReq(byte gauge) { + return new byte[]{FSP_CMD_GET_GAUGE, gauge}; + } + + public static byte[] setGaugeValueReq(byte gauge, byte value) { + return new byte[]{FSP_CMD_SET_GAUGE, gauge, value}; + } +} diff --git a/app/src/main/java/no/topi/fiken/display/NotOverriddenException.java b/app/src/main/java/no/topi/fiken/display/NotOverriddenException.java new file mode 100644 index 0000000..7247de8 --- /dev/null +++ b/app/src/main/java/no/topi/fiken/display/NotOverriddenException.java @@ -0,0 +1,4 @@ +package no.topi.fiken.display; + +class NotOverriddenException extends RuntimeException { +} diff --git a/app/src/main/res/layout/activity_display_control.xml b/app/src/main/res/layout/activity_display_control.xml index 7b19429..1ee86a0 100644 --- a/app/src/main/res/layout/activity_display_control.xml +++ b/app/src/main/res/layout/activity_display_control.xml @@ -22,18 +22,20 @@ android:textSize="12sp" android:layout_below="@+id/device_name"/> +