Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Android Things - Solid Foundations

554 views

Published on

Android Things is Googles latest foray into the Internet of Things. Android Things lets you build professional, mass-market products on a trusted platform, without previous knowledge of embedded system design. IoT devices need testing too.

We will talk about how to architect your Android Things applications to enable testing and explore best practices to keep your codebase clean and your IoT devices solid.

The second half of the talk will be a deeper dive into controlling Android Things peripherals. We'll explain what are user drivers, how they work, how to use them, and most importantly: how you can create and test a new driver from scratch that can be used from Android Things to interact with new peripherals.

Published in: Technology
  • Be the first to comment

Android Things - Solid Foundations

  1. 1. solid foundations Paul Blundell Xavi Rigau
  2. 2. Cameras Gateways HVAC Control Smart Meters Point of Sale Inventory Control Interactive Ads Vending Machines Security Systems Smart Doorbells Routers Energy Monitors Asset Tracking Fleet Management Driver Assist Predictive Service Ideal for powerful, intelligent devices on the edge that need to be secure.
  3. 3. IoT Developer Console Automatic Security Updates Signed Images Verified Boot
  4. 4. SoM Architecture Google Managed BSP
  5. 5. Displays are Optional Consider Alternate UI
  6. 6. Supported protocols
  7. 7. Peripheral I/O Communicate your Android Things device with external hardware components (usually called peripherals) Various protocols can be used (depends on hardware) General-Purpose Input/Output GPIO Pulse Width Modulation PWM Inter-Integrated Circuit I2C Universal Asynchronous Receiver-Transmitter UART Serial Peripheral Interface SPI
  8. 8. Peripheral I/O Communicate your Android Things device with external hardware components (usually called peripherals) Various protocols can be used (depends on hardware) General-Purpose Input/Output GPIO Pulse Width Modulation PWM Inter-Integrated Circuit I2C Universal Asynchronous Receiver-Transmitter UART Serial Peripheral Interface SPI Native Peripheral Input/Output NPIO
  9. 9. General-Purpose Input/Output GPIO
  10. 10. Pulse Width Modulation PWM
  11. 11. Serial Peripheral Interface SPI
  12. 12. Inter-Integrated Circuit I2C
  13. 13. Universal Asynchronous Receiver-Transmitter UART
  14. 14. Code example: use SPI for an LED strip
  15. 15. public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } }
  16. 16. public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); PeripheralManagerService service = new PeripheralManagerService(); } }
  17. 17. public class MainActivity extends Activity { private static final String SPI_PORT = "SPI1"; private SpiDevice device; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); PeripheralManagerService service = new PeripheralManagerService(); try { device = service.openSpiDevice(SPI_PORT); } catch (IOException e) { throw new IllegalStateException(SPI_PORT + " bus cannot be opened.", e); } } }
  18. 18. public class MainActivity extends Activity { ... @Override protected void onDestroy() { super.onDestroy(); try { device.close(); } catch (IOException e) { Log.e("TUT", SPI_PORT + " bus cannot be closed, you may experience errors on next launch.", e); } } }
  19. 19. public class MainActivity extends Activity { ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... try { device.setMode(SpiDevice.MODE0); device.setFrequency(1_000_000); device.setBitsPerWord(8); } catch (IOException e) { throw new IllegalStateException(SPI_PORT + " bus cannot be configured.", e); } } }
  20. 20. public class MainActivity extends Activity { ... private Handler ledToggleHandler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... ledToggleHandler = new Handler(Looper.getMainLooper()); } }
  21. 21. public class MainActivity extends Activity { ... private Handler ledToggleHandler; @Override protected void onStart() { super.onStart(); ledToggleHandler.post(toggleLed); } @Override protected void onStop() { ledToggleHandler.removeCallbacks(toggleLed); super.onStop(); } }
  22. 22. public class MainActivity extends Activity { ... private int colourValue; ... private final Runnable toggleLed = new Runnable() { @Override public void run() { try { colourValue = (colourValue == 0 ? 123 : 0); device.write(new byte[]{colourValue, colourValue, colourValue}, 3); } catch (IOException e) { throw new IllegalStateException(LED_PIN + " cannot be read/written.", e); } ledToggleHandler.postDelayed(this, TimeUnit.SECONDS.toMillis(1)); } }; }
  23. 23. Drivers
  24. 24. Driver Libraries Input Drivers User Drivers
  25. 25. Read or write from/to a peripheral Reusable components Abstract protocol details Driver Libraries
  26. 26. Ws2801 ledstrip = Ws2801.create("SPI1", Ws2801.Mode.RGB); ledstrip.write(new int[]{Color.rgb(123, 123, 123)});
  27. 27. Input Drivers Framework redirects events to the Android event queue Register an input driver Use Services instead of Activities
  28. 28. BarActivityFooService
  29. 29. InputDriver inputDriver = InputDriver.builder(InputDevice.SOURCE_CLASS_BUTTON) .setName("HelloInputDriver") .setVersion(1) .setKeys(new int[]{ KeyEvent.KEYCODE_T, KeyEvent.KEYCODE_H, KeyEvent.KEYCODE_I, KeyEvent.KEYCODE_N, KeyEvent.KEYCODE_G, KeyEvent.KEYCODE_S }).build(); UserDriverManager driverManager = UserDriverManager.getManager(); driverManager.registerInputDriver(inputDriver); KeyEvent[] events = new KeyEvent[]{new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_T)}; inputDriver.emit(events);
  30. 30. Peripherals naming convention
  31. 31. Active peripherals Passive peripherals
  32. 32. Output peripherals Input peripherals
  33. 33. Input peripherals / Sensors “A sensor detects or measures a physical property and responds to it.”
  34. 34. Output peripherals / Actuators “An actuator is responsible for moving or controlling a mechanism or system, or presenting data to the outside world.”
  35. 35. /** * HC-SR501 */ class PirMotionSensor implements MotionSensor { … /** * PS-1240 */ class PiezoSoundActuator implements SoundActuator { ...
  36. 36. Clarity when searching classes Clarity when reading code
  37. 37. Better team discussions
  38. 38. Package structure convention
  39. 39. Grouping by type - activities - MainActivity - BasketActivity - CheckoutActivity - services - LoginService - MoneyService - utils - LoginUtils - HttpUtils - peripherals - BarcodeScanningSensor - PriceInputSensor - HelpAlertSensor - FingerprintSensor - PriceDisplayActuator - MoneyDrawActuator - models - Money - Username - Basket - Receipt - Barcode - Price
  40. 40. Grouping by protocol - activities - MainActivity - BasketActivity - CheckoutActivity - services - LoginService - MoneyService - utils - LoginUtils - HttpUtils - gpio - BarcodeScanningSensor - PriceInputSensor - HelpAlertSensor - i2c - FingerprintSensor - pwm - PriceDisplayActuator - MoneyDrawActuator - models - Money - Username - Basket - Receipt - Barcode - Price
  41. 41. Increased package tackle index Tidy, everything in its place and a place for everything Don’t always remember the protocol Context switching between packages
  42. 42. Grouping by domain concepts - login - MainActivity - LoginUtils - FingerprintSensor - LoginService - Username - shopping - basket - BasketActivity - PriceInputSensor - Basket - checkout - CheckoutActivity - MoneyService - BarcodeScanningSensor - HelpAlertSensor - MoneyDrawActuator - Barcode - receipt - PriceDisplayActuator - Receipt - Money - Price - HttpUtils
  43. 43. Needs to be taught (DDD) Easier to remember where to look All code in the same place Less chance of conflicting changes
  44. 44. Peripherals MVP convention
  45. 45. Model business logic Presenter co-ordination View user interface
  46. 46. Sensor “A sensor detects or measures a physical property and responds to it.”Model business logic
  47. 47. Actuator “An actuator is responsible for moving or controlling a mechanism or system, or presenting data to the outside world.” View user interface
  48. 48. Faster debugging and problem analysis Clean code, more maintainable A clear separation of concerns Faster development through agreed standards Clarity in discussions around class responsibilities
  49. 49. Driver testing
  50. 50. Mock framework classes Test driver behaviour Extract collaborator classes
  51. 51. Test driver behaviour public class LightStripActuatorTest { @Mock Ws2801 driver; private LightStripActuator actuator; @Test public void driverGoesRedWhenError() throws Exception { actuator.showError(); verify(driver).write({Color.RED}); } }
  52. 52. Rely on mocks public class Ws2801Test { @Mock SpiDevice device; private Ws2801 driver; @Test public void configures1MHzClockFrequencyWhenCreated() throws Exception { driver = new Ws2801(device, Direction.NORMAL); verify(device).setFrequency(1_000_000); } @Test public void writesToSpiDeviceWhenWriting() throws Exception { int[] anyColors = {Color.RED, Color.DKGRAY, Color.GREEN, Color.WHITE, Color.YELLOW}; driver.write(anyColors); verify(device).write(any(byte[].class), anyInt()); } }
  53. 53. Test collaborators easily public class ColorUnpackerTest { @Test public void orderedBytesWhenModeIsRBG() { Ws2801.Mode mode = Ws2801.Mode.RBG; byte[] result = ColorUnpacker.getOrderedRgbBytes(mode, R, G, B); assertBytesOrder(result, R, B, G); } @Test public void orderedBytesWhenModeIsBGR() { Ws2801.Mode mode = Ws2801.Mode.BGR; byte[] result = ColorUnpacker.getOrderedRgbBytes(mode, R, G, B); assertBytesOrder(result, B, G, R); } }
  54. 54. Tips & Tricks
  55. 55. Always match .openSomething() with .close() Set a static IP address or use Android.local
  56. 56. On app crash need to redeploy or adb shell am start Only 1 app active at a time https://goo.gl/kLtvM7
  57. 57. Each board has different pin/bus address names Threading, 3 choices
  58. 58. Thanks! Paul Blundell Xavi Rigau @blundell_apps @xrigau
  59. 59. Questions? user drivers PWM UART GPIO I2C SPI input output sensorsactuators MVP DDD Paul Blundell Xavi Rigau @blundell_apps @xrigau

×