npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@neukolabs/neuko-js-device-sdk

v0.0.1

Published

Neuko device SDK for NodeJS hardware

Downloads

6

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:

  1. information
  2. 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 is null, a random ID will be created
    • brokerEndpoint - Endpoint to IoT platform. OMIT protocol value. e.g. iot.endpoint.com
    • tlsOptions
      • ca - Certificate Authority
      • key - Private key certificate
      • cert - Public certificate
    • recycleClients - If this is null, 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 identifier
  • stateName - State's name with changes
  • payload
    • 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 context
  • stateName - State name to be watched
  • listener - Function callback to be invoked
  • filterAttribbute - 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

  1. context - the context when registered
  2. data - 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 calling synchronizeState().

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 watched
  • state - 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 watched
  • state - 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.

  1. simple.js - A simple skeleton to show on how the Device class can be use directly as an object.
  2. extends.js - Using inheritence that extend Device functionality to your class.