@neukolabs/neuko-js-device-sdk
v0.0.1
Published
Neuko device SDK for NodeJS hardware
Downloads
4
Readme
js-device-sdk
This device SDK will be a starting point to build Neuko SDK for device.
The main idea in using the SDK is based on state management as what we have in React. You may think of this as a react-redux but for IoT device.
Every device typically works by watching, executing and updating its own state. For instance, if you take a Raspberry PI, the each of the pin on the board can be represented as the state. For example,
{
"digital_input": {
"pin1": true,
"pin2": false
}
}
Or lets use Maevi Smart Plug. We can define the plug state as below:
{
"information": {
"ieee": "123",
"ep": 1,
"netDeviceStatus": 256,
"name": "Room 1 General Socket"
},
"electricity": {
"switchgear": "on",
"consumption": {
"active_power": 1.3,
"cumulative_energy": 12.9,
"active_power_unit": "kW",
"cumulative_energy_unit": "kWh"
}
}
}
With above state definition, this SDK will group the state into 2 states:
- information
- electricity
Following the methods exposed by the Device class, you can actually update, watch and execute the state when there is a request to change or being changed between actual device and cloud.
This SDK exposed Device class in which you can use ES2015 inheritance style or creating new instance as object.
Installation
Should be (I don't know yet)
yarn add https://github.com/neukolabs/js-device-sdk
Usage ES2015
const { Device } = require("js-device-sdk"); // maybe. Aku xpernah try pon cmni
class SmartPlug extends Device {
constructor(deviceId, deviceAttributes, connectionOptions) {
super(deviceId, deviceAttributes, connectionOptions)
}
...
}
Usage as Object
const { Device } = require("js-device-sdk"); // maybe. Aku xpernah try pon cmni
let smartPlug = new Device(deviceId, deviceAttributes, connectionOptions);
ConnectionOptions
ConnectionOptions defines parameters required to connect to MQTT Broker and HTTP Server.
ConnectionnOptions
deviceId
- Unique identifier for device in context. If this isnull
, a random ID will be createdbrokerEndpoint
- Endpoint to IoT platform. OMIT protocol value. e.g.iot.endpoint.com
tlsOptions
ca
- Certificate Authoritykey
- Private key certificatecert
- Public certificate
recycleClients
- If this isnull
, new clients will be created and populated. If you provide value, the connection will be reused instead of new connection
example
const ConnectionOptions = require("../clients/connection-options");
const connectionOptios = new ConnectionOptions(
"js-device-sdk-test-demojs",
"a3ubgz3tzfk7uk-ats.iot.ap-southeast-1.amazonaws.com",
{
ca: fs.readFileSync(CA_PATH),
key: fs.readFileSync(KEY_PATH),
cert: fs.readFileSync(CERT_PATH)
}
)
let myDevice = new MyDevice(deviceId, deviceAttributes, connectionOptios);
Device State
Device's state defined with state's name and its value. The value MUST NOT EXCEED 5 tiers.
Format
{
"StateName1": {
"Key1": Value
"Key2": [],
"Key3": {
"Key31": {
"Key32": {
"Key33": {
"Key34": {
"Key35": Value
}
}
}
}
}
},
...
}
Example
Sample below shows 2 different states.
{
"electricity": {
"switchgear": "on",
"consumption": {
"power": 1.2,
"energy": 33.2,
"power_unit": "kW",
"energy_unit": "kWh"
}
},
"information": {
"firmware_version": "version1.2.3",
"link_status": true
}
}
Device State Changed Request Payload
Payload provided when state changed request.
deviceId
- Device unique identifierstateName
- State's name with changespayload
state
- An object with state attribute's name and value
Example
{
"deviceId": "device_id",
"stateName": "state_name",
"payload": {
"state": {
"key1": false
}
}
}
or
{
"deviceId": "device_id",
"stateName": "state_name",
"payload": {
"state": {
"key1.key2": 123
}
}
}
Device Methods
initialize()
Initializing the object class and set the default state to the cloud.
let device = new Device(...args);
device.initialize({
stateA: {
attrA: false
},
stateB: {
attr1: 44122
}
})
registerStateChangedFunction(context, stateName, listener, filterAttribute)
This function register the listener to be invoked when any watched state changed.
Parameters
context
- Caller contextstateName
- State name to be watchedlistener
- Function callback to be invokedfilterAttribbute
- Optional. You can watch towards specific attribute in the state using dot path. If you omit this parameter, any attribute changed will invoke the listener.
Notes
The listener function will be passed with 2 arguments
context
- the context when registereddata
- object with below information
The data
has a structure in such
{
"deviceId": "<deviceId",
"stateName": "stateName",
"changeState": {
"path.to.attribute": "value"
}
}
Example
e.g One of the state named plug
{
"plug": {
"pin_d01": true,
"digital_input": {
"pin_d32": false
}
}
}
And you want to watch pin_d32, so
function onPinD32Changed(context, data) {
// ... do something
}
// register the function
device.registerStateChangedFunction(this, "plug", this.onPinD32Changed, "digital_input.pin_d32");
synchronizeState()
This function will synchronize the state as per request by executing the function registered to the state or/and attribute.
:warning Make sure you have registered functions (using
registerStateChangedFunction()
) to be invoked when state changed request before callingsynchronizeState()
.
Example
// above code already initialize and register several function
// sync the state cloud vs actual
await device.synchronizeState();
updateOrCreateState(stateName, state)
This will update or create a new state with state value if not existed yet. You can update whole state's attributes or partial attribute.
This method usually being called when the actual device changed its state and your function being invoked because of that, in which, you want to state at the cloud.
Notes. This function handles the interval to update the cloud. Which means, although you may update at fast interval, it will be the one that actually decide to update the cloud or not. If the state is being configured (at cloud level) to be stored as timestream data such as power data, it will automatically handles for you.
Also it will publish at certain topic when there is client watches the device. (Still in development)
Parameters
stateName
- State name to be watchedstate
- JSON object of the state. You can pass full object or partial object. They will be merged in the cloud.
Example
await device.updateOrCreateState("plug", {
"pin_d01": false
})
stateChangeRequestCompleted(stateName, newState)
This function needs to be called when the actual device already fullfilled the state request changed.
Parameters
stateName
- State name to be watchedstate
- JSON object of the state. You can pass full object or partial object. They will be merged in the cloud.
Example
async function onPinD32Changed(context, data) {
// ... do something to the actual device
// once success update the cloud
super.stateChangeRequestCompleted(data.stateName, {
"digital_input": {
"pin_d32": true // new value from false
}
})
}
Usage Example
Refer to example
folder. There are 2 examples.
simple.js
- A simple skeleton to show on how the Device class can be use directly as an object.extends.js
- Using inheritence that extend Device functionality to your class.