This project demonstrates access to hardware peripherals from the Brillo operating system to create a Weave-enabled jack-o-lantern or other generic demo device.
Before you proceed, make sure that you have set up your device for audio playback and GPIO. For example, on the Qualcomm Dragonboard, you will need connect a speaker to audio expansion pins 1 (-) and 2 (+) and a 1.8v LED to the GND (LS_GPIO pin 1) and the GPIO_A pin (LS_GPIO pin 23).
First, you will need to build the sources as described in Building and Running.
The sources for sound playback are shared across the test app and daemon in order to allow testing right after flashing the firmware. To test the app using the test executable run:
adb root
adb shell
# jacksmart-test s
If you have connected a speaker to your device, sound should play.
Now that you verified your peripherals are working, configure the device from the Weave developer console. After you have created the project, product, and model, replace the Client ID, secret, and API key in weaved.conf.
Now that you have configured the application / device, build and provision
again and try accessing the device through the Weave service. Add the device
using the Weave Android app. When prompted for the conformation code, use the
embed code set in weaved.conf, 0000
.
After the device has been registered, you can turn on the GPIO pins by sending
the custom command _lights._set
; the message payload is:
{
"name": "_lights._set",
"parameters": {"_light": 1,"_on":true},
"deviceId" : "your-device-id"
}
You can also trigger the service through the Google Cloud Devices interface,
to hear a sound by sending the custom command _playsound._set
; the message
payload is:
{
"name": "_playsound._set",
"parameters": {"_on":true},
"deviceId" : "your-device-id"
}
Note that you can also run adb logcat | grep -i jack
on a machine connected
to your Brillo device and you will see INFO messages for the commands coming,
for example:
I /system/bin/jacksmart: [INFO:jacksmart.cc(165)] Command: _lights._set
I /system/bin/jacksmart: [INFO:jacksmart.cc(170)] Setting Light: 1 to on
-
Install the BDK by following these instructions
-
Set the BDK path:
export BDK_PATH=<BDK install dir>
-
Create the project folder using the BDK:
${BDK_PATH}/tools/bdk/brunch/brunch product create ~/products/jacksmart dragonboard
-
Copy the jacksmart brillo sources into the product folder
cp -r <path-to>/jacksmart/brillo/* ./jacksmart/
-
Configure the product
. envsetup.sh m -j32
-
Boot your device into fastboot mode by holding down the volume key while powering on or calling
adb reboot bootloader
. Check the device is in fastboot mode with:fastboot devices
-
Flash the firmware to your device:
provision
-
Reboot your device:
fastboot reboot
Although the test configuration is exciting on its own, you can take your working sample and can build it out into a prototype for your device.
For our demo device, we wanted to build a jack-o-lantern so we acquired a plastic pumpkin that included a bright light inside of it. We then upgraded our test configuration by connecting a relay to the GPIO pins and wiring this to our light. Now, instead of triggering an LED on the board, we are able to turn on and off a more exciting light inside of the pumpkin.
After adding a light that is controlled via the GPIO pins, we upgraded the speaker to instead use the line-out and an external speaker.
The sample is provided with the intention of being extended to different configurations. For example, you could add colored lights to the hardware pumpkin, could use the message loop to add a proximity sensor, or can make your own remix of the pieces that creates an alarm or jukebox. To get you started, let's take a look at adding a device already built into the sample.
Before jumping into the sources, it's helpful to understand what you typically will be changing and what you generally don't need to change. The following overview shows you the project structure for the JackSmart pumpkin demo:
├── AndroidProducts.mk - Boilerplate build file generated by brunch
├── config - Files generated by brunch
│ ├── bdk
│ │ ├── buildtype
│ │ ├── java
│ │ └── version
│ ├── brand
│ ├── brillo
│ │ ├── crash_server
│ │ ├── product_id
│ │ └── product_version
│ ├── copy_files - Contains list of files copied to firmware
│ ├── device
│ ├── manufacturer
│ ├── name
│ └── packages
├── configurations - Example configurations for this demo
│ └── audio
│ ├── audio_policy.conf.headphones
│ ├── audio_policy.conf.speaker
│ └── README
├── envsetup.sh - Generated by brunch, sets up the build environment
├── extras.mk - Contains additional rules for Android's make
├── jacksmart_kernel.config - Contains kernel changes for this app
├── jacksmart.mk - This app's makefile
├── README - This file
├── sepolicy - Security policy and exceptions
│ ├── file_contexts
│ └── jacksmart.te
├── src - The sample source folder, contains the test app and Weave service
│ └── jacksmart
│ ├── Android.mk - Local make rules for this app's modules
│ ├── etc - file structure for Weave traits
│ │ └── weaved
| │ └── traits
| | └── sputnik.json
│ ├── include - Shared includes local to this app
│ │ └── peripherals - Basic shared includes for peripheral types
│ │ ├── gpio - Contains GPIO peripheral implementations
│ │ │ ├── gpio.cc
│ │ │ └── gpio.h
│ │ ├── i2c - Contains I2C peripheral implementations
│ │ │ ├── facehelper.cc
│ │ │ └── facehelper.h
│ │ ├── sound - Contains sound wrappers
│ │ │ ├── alsasound.cc
│ │ │ ├── alsasound.h
│ │ │ ├── sound.cc
│ │ │ └── sound.h
│ │ └── spi - Contains SPI wrappers
│ │ ├── apa102.cc
│ │ ├── apa102.h
│ │ ├── spi.cc
│ │ └── spi.h
│ ├── jacksmart.cc - The Weave service
│ ├── jacksmart.rc - The service startup settings
│ ├── prebuilts - Local prebuilts that are copied to the device
│ │ ├── 2553.mp3
│ │ ├── boot.mp3
│ │ ├── out.wav
│ │ └── testmixer.sh
│ └── testsmart.cc - The test application
└── weaved.conf - The Weave service configuration file
Most of the changes you would want to make are going to be in the src/
folder where the binary sources for the test app and service are. If you want
to iteratively develop features on a device, you typically will do the
following:
- Test feature from command line (if possible)
- Add feature to test app that runs on Brillo
- Add feature to Weave service
Continue to the next section to jump into getting started on adding an SPI peripheral to the sample app.
You can start by adding an additional device to the sample. For example, the SPI peripheral sources include an implementation for driving APA102 LED lights. To get started with the hardware, you will need a logic level converter and some APA102 lights (sold through Adafruit as "Dotstar").
Add a logic level converter to a breadboard and connect APA 102 LEDs to the appropriate pins with the voltage logic set to 5v. In short, setup consists of connecting across the voltage logic converter between the Dragonboard and APA102 as:
Dragonboard side
- CLK (pin 8 on dragonboard) -> Low voltage 1 on logic level converter
- MOSI (pin 14 on dragonboard) -> Low voltage 2 on logic level converter
- GND (pin 40 on dragonboard) -> Low ground on logic level converter
- 1.8V (Pin 35 on dragonboard) -> Low input voltage on logic level converter
APA102 side
- 5V (pin 37 on dragonboard) -> High Voltage pin on logic level converter
- GND (pin 39 on dragonboard) -> High ground on logic level converter
- 5V shared on logic level -> Dotstar +
- GND shared on logic level converter -> Dotstar -
- CLK on APA102 -> High voltage 1 on logic level converter
- SD on APA102 -> High voltage 2 on logic level converter
After you have connected everything, test that SPI is working by running the SPI example build in to the test app:
jacksmart-test S
If your peripheral is correctly configured, the LED lights should turn on and off.
Now that you have a test that works, add a command to the Weave service that can be triggered over the Weave API.
To do this, you could:
- Add the command to your Weave command definitions in
src/jacksmart/etc/weaved/commands/jacksmart.json
- Add the associated state to your Weave states definitions in
src/jacksmart/etc/weaved/states/jacksmart.json
- Add a command callback to
src/jacksmart/jacksmart.cc
similar to those defined forOnPlaySound
andOnLightSet
. - Add the command handler to
Daemon::OnInit
as well as any initialization. - Add the method implementation for your command.