Building IoT Applications
Any application built on the Appivo-platform can have IoT-functionality – meaning you can have devices connected to your application that contribute functionality. Examples of this could be a device monitoring the temperature of a room, controlling a doorlock or displaying information on a TV. An application may even have several kinds of devices connected to it and these different device may need to run different code. That’s why an appivo-application can have several deviceprofiles. A deviceprofile is the collection of code required for a certain type of device when being connected to your application.
The deviceprofile contains a set of event-handlers as the programming model for a device is strictly event-based. The platform emits a few fundamental events – such as App.Start and App.Stop – as you might guess these events are emitted when the application starts and stops, on the device that is. Typically you will initialize datastructures and features when the app starts and then clean everything up when it stops.
Devices can also have timers that emit “tick”-events according to a schedule that you determine, this way you can for instance collect data from a sensor at a regular interval. The device may also “listen” for messages being received on messaging-topics – this allows the device to interact with the part of your application running in the cloud, as well as other devices of course.
Devices may also make use of various plugins, there are plugins for interfacing with hardware components such as I²C, SPI and GPIO – but that’s not all, there is also a plugin for controlling an embedded chrome-browser which can be used to open up web-based user-interfaces that are also part of your application. This makes it very easy to build a digital signage system that can be used with a regular TV.
The DeviceContext API
The DeviceContext is the main interface when interacting with the device. Through it you can get access to hardware-features and general functionality. Notice that when interacting with the database this API is asynchronous and related methods return a Promise. This section of the document provides a description of the DeviceContext API:
Method | Arguments | Description |
---|---|---|
log | message (string) | Logs a message to the application log at INFO-level |
log | level (string – TRACE, DEBUG, INFO, WARN, ERROR) message (string) | Logs a message to the application log at the specified level |
setData | key (string) value (anything) scope (optional string – GLOBAL, APP, PROFILE, LOCAL) | Stores a key/value-pair on the device within the specified scope. GLOBAL means that the key is available in any app running on the device, APP means it is available in any device-profile belonging to this app, PROFILE means it is available only within the current device-profile and LOCAL is the same as PROFILE but not persistent (i.e. will not survive and app-restart or device-reboot). |
getData | key (string) | Gets the value of the given key |
clearData | key (string) | Removes the value for the given key |
sleep | milliseconds (integer) nanoseconds (optional integer) | Sleeps for the given amount of time |
getAppliance | Gets a record that describes the local appliance | |
getMilliTime | Gets the time in ms since 1970-01-01 | |
getModule | module (string) | Gets a handle to the module with the given name |
getUser | Gets the current user | |
createRecord | model (model/string) data (map/object) attribute-data | Create a Record of the given model with the provided values. Does NOT write it to the database. |
create | record (record/object) | Returns a promise which will resolve to newly created Record upon success |
udate | record | Returns a promise which will resolve to the updated Record upon success |
get | model (string/object) model or name of model ID (string/ID) ID of record to get | Returns a promise which will resolve to the requested Record |
delete | model (string/object) model or name of model) ID (string/ID) ID of record to get | Returns a promise which will resolve to true if record was successfully deleted |
query | query (string) query in ASQL or #query-name params (object/map) query-parameters | Returns a promise which will resolve to the queried Records in the form of an array |
publish | topic (string) topic to publish message to message (map/object) message-payload headers (map/object) optional headers | Publishes a message to the given topic |
Examples
1. Creating a record and storing it in the database.
Note: in this example my SensorValue-model has a relationship to the appliance, so I populate the “appliance_id”-attribute with the appliance-ID.
var sensorData = 7;
var appliance = context.getAppliance();
var record = context.createRecord("SensorValue", {
"appliance_id": appliance.id,
"Value": sensorData
});
context.create(record);
2. Getting a record from the database
context.get("Sensor", sensorId).then(function(record) {
context.log("Got record from database " + record.id);
});
3. Executing a query
context.query("#MyQuery", {
"threshold": 100
}).then(function(records) {
for (var i = 0; i < records.length; i++) {
var record = records[i];
context.log("Got record " + i + " with id " + record.id);
}
});
4. Publish a message
context.publish("#mytopic", {
value: 10,
status: "OPEN"
});
5. Storing data locally
var counter = compute();
context.setData("counter", counter, "APP");
And retrieving it at a later time:
var counter = context.getData("counter");
The GPIO Module
Method | Arguments | Description |
---|---|---|
getPin | pinName (string) – A provisioned GPIO pin (e.g. “GPIO 0”) | Gets the instance of the GPIO pin |
provisionPin | options (object) –{ pin: string – GPIO pin name (e.g. “GPIO 0”), mode: string – INPUT, OUTPUT, INPUT_OUTPUT } | Provisions and returns a GPIO pin, if the pin has already been provisioned, it will just be returned. |
setValue | pinName (string) – A provisioned GPIO pin (e.g. “GPIO 0”) value (boolean) | Sets the value of the specified pin (no operation on input pin) |
getValue | pinName (string) – A provisioned GPIO pin (e.g. “GPIO 0”) | Returns a boolean representing the current state of the specified pin |
Examples
//Make GPIO pin 0 blink
context.getModule("gpio").getPin("GPIO 0").blink(500);
GPIO Pin
Method | Arguments | Description |
---|---|---|
setValue | value (boolean) | Sets the value of the pin (no operator for input pin) |
getValue | Gets the value of the pin |
GPIO Input Pin
Inherits all methods from GPIO Pin
Method | Arguments | Description |
---|---|---|
isHigh | Returns true if the input pin state is high | |
isLow | Returns true if the input pin state is low | |
addListener | listener (function) – receives 1 argument with methods getState and getEdge | Adds a state listener to the pin. Returns the pin itself |
GPIO Output Pin
Inherits all methods from GPIO Pin
Method | Arguments | Description |
---|---|---|
blink | delay (number) duration (optional number) | Toggles the pin back and forth between high and low staying in one state for delay ms and running for duration (infinite if not specified) |
pulse | delay (number) | Pulses the pin high for delay ms |
pulseLow | delay (number) | Pulses the pin low for delay ms |
addListener | listener (function) – receives 1 argument with methods getState and getEdge | Adds a state listener to the pin. Returns the pin itself |
toggle | Toggles the pins state (pin.state = !pin.state) | |
high | Sets the pin high | |
low | Sets the pin low | |
stop | Stops any ongoing pulse or blinking. Is called by all methods except getValue internally to make behaviour predictable |
GPIO Input/Output Pin
Inherits all methods from GPIO Pin
Method | Arguments | Description |
---|---|---|
stop | Stops any ongoing pulse or blinking | |
setModeInput | Calls stop and sets the pin to input mode | |
setModeOutput | Calls stop and sets the pin to output mode | |
getMode | Returns the current mode of the pin (“INPUT”, “OUTPUT”) | |
getValue | Calls setModeInput then returns the current state of the pin. | |
setValue | Calls setModeOutput then set the current state of the pin. | |
isHigh | Calls setModeInput then returns if the pin state is high. | |
isLow | Calls setModeInput then returns if the pin state is low. | |
addListener | listener (function) – receives 1 argument with methods getState and getEdge | Adds a state listener to the pin. Returns the pin itself |
pulse | delay (number) | Calls setModeOutput then pulses the pin high for delay ms |
toggle | Calls setModeOutput then toggles the pins state (pin.state = !pin.state) | |
high | Calls setModeOutput then sets the pin high | |
low | Calls setModeOutput then sets the pin low | |
stop | Stops any ongoing pulse or blinking. Is called by all methods except getValue internally to make behaviour predictable |
The I2C Module
Method | Arguments | Description |
---|---|---|
getDevice | bus (number) address (number) | Gets the i2c device with the specified address on the bus (on raspberry pi the only available bus i 1) |
Examples
// Get the i2c module
var i2c = context.getModule("i2c");
// Get the device on bus 1, address 0x29
var device = i2c.getDevice(1, 0x29);
// Write 0x30 to the internal register address 0x8A
device.write(0x8A, 0x30);
I2C Device
Method | Arguments | Description |
---|---|---|
read | address (optional number) size (optional number) | Reads from the internal register(s) on the i2c device. Returns a number if size is not defined and an array if it is. |
write | address (optional number) data (number | array<number>) | Write to the internal register(s) on the i2c device. |
close | Release the device reference |
The SPI Module
Method | Arguments | Description |
---|---|---|
getDevice | cs (number) channel (number) | Gets the spi device with the specified cs connection on the channel (for most devices channel is not needed so can just be 0) |
Examples
// Get the SPI-module
var spi = context.getModule("spi");
// Get the device on CS 0
var device = spi.getDevice(0, 0);
//Write 0x0A, 0x0B, 0xC to the device using CS 0 and store the result (2 bytes)
var bytes = device.write([0x0A, 0x0B, 0x0C]);
//assemble the 2 bytes into a single 16-bit unsigned integer (assuming big endian byte order)
var uInt16 = bytes[0] << 8 | bytes[1];
SPI Device
Method | Arguments | Description |
---|---|---|
write | data (array<number>) | Writes bytes to the spi device and returns the response. |
write | data (string) charset (string) | Writes a string to the device and returns the response |