Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Londroind - Thingyfy your home with Android Things and Firebase

Londroind - Thingyfy your home with Android Things and Firebase

Slides for the Talk done at Londroid January 2018

James Coggan

February 07, 2018
Tweet

More Decks by James Coggan

Other Decks in Technology

Transcript

  1. James Coggan, MyDrive Solutions Connect your Phone and Home with

    Firebase and Android Things We are hiring! https://www.mydrivesolutions.com/jobs
  2. A little bit about me.. James Coggan Android tech lead

    https://jamescoggan.com @mad_team
  3. Android vs Android Things • Main app started automatically •

    Android Things support Library • Permissions are free (reboot required for dangerous ones) • Google play services: ◦ Firebase ▪ Realtime database ▪ Cloud messaging ▪ Etc ◦ Google cloud platform ◦ Google cloud IoT ◦ ...
  4. Android vs Android Things • AdMob • Android Pay •

    Full screen display (no status bar, notifications or navigation buttons) • Sign-In • System apps (Calendar, Telephony, Settings..) • Display is optional
  5. Why Android Things? • Kotlin :) • OS and Framework

    Maintained by Google • OTA updates • Android community • Android libraries • Reusable code/infrastructure
  6. Why Android Things? A bundle is a zip file that

    contains the following: • bootanimation.zip: Boot animation located in the root directory • <user-space driver>.apk:User-space driver as a service (action=BOOT_COMPLETED) • <main>.apk: (Required) The apk for the main entry point (action=MAIN, category=IOT_LAUNCHER) • <sub>.apk:One of any number of apks that is launched by the main apk
  7. Update policy • POLICY_CHECKS_ONLY - Only check for an available

    update. • POLICY_APPLY_ONLY - Download and apply an available update. • POLICY_APPLY_AND_REBOOT - Download and apply an available update. Reboot the device automatically. This is the default policy.
  8. Getting started // Things manifest file <activity android:name=".MainActivity"> <intent-filter> <!--

    Launch activity as default from Android Studio --> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
  9. Getting started <activity android:name=".MainActivity"> <intent-filter> <!-- Launch activity as default

    from Android Studio --> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter> <!-- Launch activity automatically on boot --> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.IOT_LAUNCHER" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
  10. Supported I/Os • General Purpose Input/Output (GPIO): Binary • Pulse

    Width Modulation (PWM): Servo motors, DC motors • Inter-Integrated Circuit(I2C) • Serial Peripheral Interface (SPI) • Universal Asynchronous Receiver Transmitter (UART)
  11. val gpioForLED: String // Pin 31 get() { return when

    (Build.DEVICE) { DEVICE_RPI3 -> "BCM6" DEVICE_IMX6UL_PICO -> "GPIO4_IO22" DEVICE_IMX7D_PICO -> "GPIO2_IO02" else -> throw IllegalStateException("Unknown Build.DEVICE " + Build.DEVICE) } }
  12. val gpioForButton: String // Pin 40 get() { return when

    (Build.DEVICE) { DEVICE_RPI3 -> "BCM21" DEVICE_IMX6UL_PICO -> "GPIO2_IO03" DEVICE_IMX7D_PICO -> "GPIO6_IO14" else -> throw IllegalStateException("Unknown Build.DEVICE " + Build.DEVICE) } }
  13. val pinName = gpioForLED val pioService = PeripheralManagerService() ledGpio =

    pioService.openGpio(pinName) ledGpio?.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW) ledGpio?.setActiveType(Gpio.ACTIVE_HIGH) ledGpio?.value = false
  14. val service = PeripheralManagerService() val pinName = gpioForButton switchGpio =

    service.openGpio(pinName) switchGpio?.setDirection(Gpio.DIRECTION_IN) switchGpio?.setEdgeTriggerType(Gpio.EDGE_BOTH) switchGpio?.registerGpioCallback(object : GpioCallback() { override fun onGpioEdge(gpio: Gpio?): Boolean { setLed(gpio?.value ?: false) return true } ... }
  15. @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); PeripheralManagerService service =

    new PeripheralManagerService(); try { bus = service.openI2cDevice(I2C_ADDRESS, BMP280_TEMPERATURE_SENSOR_SLAVE); calibrationData[0] = bus.readRegWord(REGISTER_TEMPERATURE_CALIBRATION_1); calibrationData[1] = bus.readRegWord(REGISTER_TEMPERATURE_CALIBRATION_2); calibrationData[2] = bus.readRegWord(REGISTER_TEMPERATURE_CALIBRATION_3); …. private static int readSample(byte[] data) { // msb[7:0] lsb[7:0] xlsb[7:4] int msb = data[0] & 0xff; int lsb = data[1] & 0xff; int xlsb = data[2] & 0xf0; // Convert to 20bit integer return (msb << 16 | lsb << 8 | xlsb) >> 4; } } https://github.com/blundell/androidthings-i2c-input
  16. override fun onStart() { super.onStart() ... val ledGpio = RainbowHat.openLedGreen()

    ledGpio?.value = true } override fun onStop() { super.onStop() ... ledGpio?.close() }
  17. private var sensor: Bmx280? = null override fun onStart() {

    super.onStart() ... sensor = RainbowHat.openSensor() sensor?.setTemperatureOversampling(Bmx280.OVERSAMPLING_1X) sensor?.setPressureOversampling(Bmx280.OVERSAMPLING_1X) val temperature = sensor?.readTemperature() ?: 0f val pressure = sensor?.readPressure() ?: 0f val value = TemperatureAndPressure(temperature, pressure) saveTemperatureAndPressure(value) } override fun onStop() { super.onStop() ... sensor?.close() }
  18. Setting up Firebase https://console.firebase.google.com • Create a new Firebase project

    • Add a new Android app to the project with your package name: ie: com.jamescoggan.thingspresentation • Enable anonymous login on (temporarily)
  19. • Setup a database // Database { "home" : {

    "light" : false, "pressure" : 0, "temperature" : 0 } }
  20. // Base build.gradle for all modules buildscript { ... dependencies

    { classpath "com.google.gms:google-services:$googleServicesClassVersion" } }
  21. // mobile & things build.gradle dependencies { ... implementation "com.google.firebase:firebase-core:$playServicesVersion"

    implementation "com.google.firebase:firebase-database:$playServicesVersion" implementation "com.google.firebase:firebase-auth:$playServicesVersion" implementation "android.arch.lifecycle:extensions:$androidArchComponentsVersion" } apply plugin: "com.google.gms.google-services"
  22. // MainActivity.kt (Both modules - mobile and things) companion object

    { private val HOME = "home" } override fun onCreate(savedInstanceState: Bundle?) { val firebaseAuth = FirebaseAuth.getInstance() val reference = FirebaseDatabase .getInstance() .reference .child(HOME) ... }
  23. // Mobile Activity companion object { val LIGHT = "light"

    } override fun onCreate(savedInstanceState: Bundle?) { ... toggleButton.setOnCheckedChangeListener({ _, state: Boolean -> databaseReference.child(LIGHT).setValue(state) }) }
  24. // Things Activity companion object { val PRESSURE = "pressure"

    val TEMPERATURE = "temperature" } private val temperatureAndPressureListener = object : Sensor.OnStateChangeListener<TemperatureAndPressure> { override fun onStateChanged(state: TemperatureAndPressure) { reference.child(TEMPERATURE).setValue(temperature) reference.child(PRESSURE).setValue(pressure) } }
  25. class HomeInformationLiveData(val dbReference : DatabaseReference) : LiveData<HomeInformation>() { override fun

    onActive() { dbReference.addValueEventListener(valueEventListener) } override fun onInactive() { dbReference.removeEventListener(valueEventListener) } }
  26. val valueEventListener = object : ValueEventListener { override fun onDataChange(snapshot:

    DataSnapshot) { val newValue = snapshot.getValue(HomeInformation::class.java) value = newValue } override fun onCancelled(error: DatabaseError) { handleError(error) } }
  27. // Things Activity private val lightsDataObserver = Observer<HomeInformation> { homeInformation

    -> setLed(homeInformation?.light ?: false) } // Mobile Activity private val lightsDataObserver = Observer<HomeInformation> { homeInformation -> pressureText.text =homeInformation?.pressure ?: 0f temperatureText.text = homeInformation?.temperature ?: 0f) }
  28. // Activity override fun onCreate(savedInstanceState: Bundle?) { val liveData =

    HomeInformationLiveData(databaseReference) firebaseAuth.signInAnonymously() .addOnCompleteListener { task -> if (task.isSuccessful) { liveData.observe(this, lightsDataObserver) } } override fun onStop() { super.onStop() lightsLiveData.removeObserver { lightsDataObserver } }
  29. Nearby • Pub/Sub • Send messages, files or stream data

    • No need for server • Peer to peer • Wifi or BLE
  30. https://github.com/jamescoggan/thingspresentationn • Common code in shared module • Nearby •

    RainbowHat: ◦ Sensors ◦ Led ◦ Button • Philips Hue (in progress)
  31. Android Things Workshops 21 February 6pm 28 February 6pm We’ll

    be giving away a JetBrains subscription & some Android Things kits at the office @GDGLondon