Hello! Welcome to my blog on using Xamarin's tools to develop mobile apps.
I'm going to start with a project that provides a UI to my SmartThings devices. SmartThings sells a local hub device that is connected to your router providing connectivity between your Z-Wave or Zigbee devices and the SmartThings cloud. The devices are things like sensors for doors being opened, temperature, moisture, and also actuators which do things like switches and alarms.
The SmartThings cloud provides an online IDE in which you can write your own SmartApps. They are written in a language called Groovy which provides a Domain Specific Language for handling your devices events and invoking their actions.
So my first Xamarin post doesn't have any C#, it's Groovy!
But please don't be put off by this! This series of posts will show how to create a tiled interface (like the Windows 8 Start Menu) with each tile data bound to a device. I will be using the SmartApp as a source for the data to show in the tiles, and operations to call when interacting with the tiles. However you can easily use other web services to provide a UI to interact with them.
SmartApp
So let's start with the Groovy SmartApp. I have followed the tutorial here to create a SmartApp called REST Endpoints which responds to REST requests for sensor data and to perform actions.
The SmartApp script can be found in my SmartThings repository https://github.com/JasonBSteele/SmartThings where the README explains how to install it, get authorisation, and to call its endpoints.
I won't go through the SmartApp in detail but hopefully just enough for you to see how it wires up my devices to a REST interface. The snippet below handles the REST requests for switch devices. The path specifies the pattern to match against the URL and the action maps the HTTP verb to the function to call.
path("/switches") {
action: [
GET: "listSwitches"
]
}
path("/switches/:id") {
action: [
GET: "showSwitch"
]
}
path("/switches/:id/:command") {
action: [
GET: "updateSwitch"
]
}
Both listSwitches and showSwitch call deviceToJson with the attribute name of the value of a switch, which is switch. A JSON response is built in deviceMap which is of type Map (similar to a C# Dictionary). You will notice below that the return keyword is optional.
private deviceToJson(device, attributeName) {
if (!device)
null
def s = device.currentState(attributeName)
def deviceMap = [id: device.id, name: device.displayName, unitTime: s?.date?.time]
deviceMap[attributeName] = s?.value
deviceMap
}
The JSON response for a single switch looks like this:
{
"id":"be7c0195-ef58-4b16-969b-91299c1e0c82",
"name":"My Switch",
"unitTime":1425247415223,
"switch":"on"
}
The remaining function updateSwitch calls updateToggle which finds the specific device in the switches collection and executes it's on or off command.
private void updateToggle(devices) {
log.debug "updateToggle request: params: ${params}, devices: $devices.id"
def command = params.command
if (command)
{
def device = devices.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
}
else {
if(command == "toggle") {
if(device.currentValue('switch') == "on")
device.off();
else
device.on();
}
else {
//else 'on' or 'off'
device."$command"()
}
}
}
}
You may have noticed that the HTTP verb GET invokes updateSwitch. For proper REST I should really use a PUT to change state but I have client applicatons for which it was easier to use a GET so decided, for now, to relax this convention.
Conclusion
We now have a web service for our Xamarin client to connect to. The next post will start with creating the app and it's main page.
No comments:
Post a Comment