Android Things Musings about Android Things & IoT

Controlling your office lights with Android Things

Controlling your office lights with Android Things - Logo

I love the Philips Hue light bulbs and have them in a few places around my house. Being able to turn the lights on or off using my mobile phone or even voice commands is great!

I’m also a big fan of changing the colours based on my mood or what I’m actually working on but opening the app to change the presets can really kill my concentration. I wish there were buttons I could quickly press to get the colours to change…

Let’s build an Android Things app that changes the light bulb colours by the press of a button using the Philips Hue API.

Our tools

The list of materials above along with links is just my suggestion to get you going quickly (all links are Amazon Prime & have my affiliate ID). Feel free to order anywhere you prefer.

Credentials

To talk to Hue’s API, we first need to get our credentials. This Getting Started guide will take you through all the necessary steps.

Once you’ve completed it use the Clip API debugger shown on the link above, make a GET request to list all your light bulbs. We want to control our office light bulb remember?

http://<bridge ip address>/api/<authorised user code>/lights

JSON Light Bulb information

The ID of the light bulb you want to control is the root node of that item as highlighted in pink above. So if i wanted to turn of my light I would make a PUT request to http://<bridge ip address>/api/<authorised user code>/lights/<ID>/state passing this JSON payload: {"on":false}

Give that a go and if you’ve got it all working we can now move to our circuit.

Light bulb animation

Controls

Our circuit is very simple as it only consists of a few buttons that are directly connected to the PI’s GPIO and a few resistors.

Breadboard representation

Every resistor is connected to V+ and the other leg of the button is connected to GND. On the other side, we connect the leg directly opposite to the resistor to BCM26, BCM19, BCM13 and BCM6 respectively.

In the diagram I’m using wires of different colours to represent the colours each one of my buttons will change the light bulb to.

We should write some code to control these buttons though.

Building the APP

In android studio create a new Android project with an empty activity called “Hue Controller” with Kotlin support and make sure you set the SDK to 24 or above.

New Android Things project

Open the application level build.gradle and add the following dependencies to the project.

dependencies {
    ...
    compile 'com.squareup.retrofit2:retrofit:2.3.0'
    compile 'com.squareup.okhttp3:logging-interceptor:3.8.0'

    provided 'com.google.android.things:androidthings:0.4-devpreview'
    compile 'com.google.android.things.contrib:driver-button:0.3'
}

We will be using Retrofit to make HTTP requests to the Hue API along with Android Things and the button driver. Gradle will then ask to sync the project, so let it do its thing.

In AndroidManifest.xml add the Internet permission and a new Intent-Filter to make sure our application is launched at boot.

   <uses-permission android:name="android.permission.INTERNET" />

    <application
        ...
            <!-- Launch activity automatically on boot -->
            <intent-filter>
                <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>
    </application>

We can start really coding our application by opening MainActivity.kt and adding references to our buttons at the top of the class.

class MainActivity : Activity() {
    lateinit var redButton: Button
    lateinit var greenButton: Button
    lateinit var blueButton: Button
    lateinit var greyButton: Button

You should resolve the Button dependency using com.google.android.things.contrib.driver.button.Button as we’re dealing with hardware buttons here.

In the onCreate initialise the four buttons as follows:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    redButton = Button("BCM26", Button.LogicState.PRESSED_WHEN_LOW)
    greenButton = Button("BCM19", Button.LogicState.PRESSED_WHEN_LOW)
    blueButton = Button("BCM13", Button.LogicState.PRESSED_WHEN_LOW)
    greyButton = Button("BCM6", Button.LogicState.PRESSED_WHEN_LOW)

For each of the buttons create an event listener that will be called every time one of the buttons is pressed.

    redButton.setOnButtonEventListener( { _, _ -> Log.d("BUTTON", "Red pressed!") })
    greenButton.setOnButtonEventListener( { _, _ -> Log.d("BUTTON", "Green pressed!") })
    blueButton.setOnButtonEventListener( { _, _ -> Log.d("BUTTON", "Blue pressed!") })
    greyButton.setOnButtonEventListener( { _, _ -> Log.d("BUTTON", "Grey pressed!") })

Let’s make sure we connected everything up correctly by running the application and pushing each one of the buttons. You should end up with logs that looks similar to this:

06-04 16:51:49.987 3932-3932/rocks.androidthings.huecontroller D/BUTTON: Red pressed!
06-04 16:51:55.987 3932-3932/rocks.androidthings.huecontroller D/BUTTON: Green pressed!
06-04 16:52:03.987 3932-3932/rocks.androidthings.huecontroller D/BUTTON: Blue pressed!
06-04 16:52:07.987 3932-3932/rocks.androidthings.huecontroller D/BUTTON: Grey pressed!

If all your buttons worked, we should now be able to code the second part of this app, which is where we start interacting with the Hue API.

Create a new Kotlin interface called Hue.kt alongside MainActivity.kt and add the following code to it.

import retrofit2.Call
import retrofit2.http.Body
import retrofit2.http.PUT
import okhttp3.RequestBody
import okhttp3.ResponseBody

interface Hue {
    @PUT("/api/<authorised user code>/lights/<ID>/state")
    fun ControlLight(@Body params: RequestBody): Call<ResponseBody>
}

Make sure you replace the contents of <authorised user code> and <ID> with the details you got earlier in the Credentials section.

Now create a new Kotlin class called RestApi.kt and initialise Retrofit

import okhttp3.MediaType
import okhttp3.OkHttpClient
import okhttp3.RequestBody
import okhttp3.ResponseBody
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Call
import retrofit2.Retrofit

class RestApi {
    private val hueApi: Hue
    init {
        val logging = HttpLoggingInterceptor()
        logging.level = HttpLoggingInterceptor.Level.BODY
        val httpClient = OkHttpClient.Builder().addInterceptor(logging).build()

        val retrofit = Retrofit.Builder()
                .baseUrl("<bridge ip address>")
                .client(httpClient)
                .build()

        hueApi = retrofit.create(Hue::class.java)
    }
}

Make sure you replace <bridge ip address> with the IP address for your Hue bridge. We’re also adding some logging so we can see that the requests are made correctly. This will be helpful later on in case something goes wrong.

Still inside the RestApi.kt class, add methods to be invoked by each one of the buttons and one method to convert a string into a valid RequestBody.

fun makeRed(): Call<ResponseBody> = hueApi.ControlLight(convertRequestBody("""{"on":true, "hue":0}"""))

fun  makeGreen(): Call<ResponseBody> = hueApi.ControlLight(convertRequestBody("""{"on":true, "hue":25500}"""))

fun  makeBlue(): Call<ResponseBody> = hueApi.ControlLight(convertRequestBody("""{"on":true, "hue":46920}"""))

fun turnOff(): Call<ResponseBody> = hueApi.ControlLight(convertRequestBody("""{"on":false}"""))

private fun convertRequestBody(body: String): RequestBody = RequestBody.create(MediaType.parse("text/plain"), body)

The first three methods set a different colour to our lights, while turnOff just turns the lights off. You can see some of the other colours in this page.

Let’s go back to our MainActivity.kt and change it so pressing the buttons call the methods we just defined above.

In each one of the event listeners, we’re now going to make a request to our API for each one of the colours we’re using.

// Event Listener
redButton.setOnButtonEventListener( { _, _ -> val call = hueApi.makeRed(); call.enqueue(callbackHue) })
greenButton.setOnButtonEventListener( { _, _ -> val call = hueApi.makeGreen(); call.enqueue(callbackHue) })
blueButton.setOnButtonEventListener( { _, _ -> val call = hueApi.makeBlue(); call.enqueue(callbackHue) })
greyButton.setOnButtonEventListener( { _, _ -> val call = hueApi.turnOff(); call.enqueue(callbackHue) })

They now return a callback which will tell us whether the request was successful or not. We’ve defined that in a variable called callbackHue which we define as follows.

private val callbackHue: Callback<ResponseBody> = object : Callback<ResponseBody> {
    override fun onResponse(call: Call<ResponseBody>, response: retrofit2.Response<ResponseBody>) {
        Log.d(TAG, response?.body().toString())
    }

    override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
        Log.d("ERROR", "Failure " + t.message)
    }
}

You can choose to do anything you want with the response, but for brevity we’re only logging the response or the error.

Run the app again and and press one of the coloured buttons and you should see that your lights change to that colour. When you want to turn the lights off, just press the grey button and the lights will go off.

Let there be lights…

Being able to control your lights using buttons connected directly to the Pi is great, but now that you know how to use the Hue API with it, you could build an application that will change the light colours depending on other things.

Have a look a the high five machine for example. Wouldn’t it be nice to also change the colours when you get a new follower? Or turn it red when you lose one?

I would love to hear what you do with it. Ping me on Twitter @marcos_placona to tell me more!

You can download the entire code for this post here.