Device listens to telemetry state changed

Device listens to telemetry state changed

This guide describes the concept and syntax when a device listens to the changes of telemetry state from its Virtual Twin.

Below telemetry state schema with a state name of smart_plug_state will be used throughout this guide.

  "electricity": {
    "power": 0,
    "votage": 0
  "switch": {
    "toggle": false,
    "led": {
      "front": false,
      "back": true

Code below shows several examples when listening to changes and invoke functions associated to the changes.

import { 
} from "@neukolabs/device-sdk-js";
import { readFileSync, writeFileSync, unlinkSync, existsSync } from 'fs';
import path from 'path';

class deviceIdentifier extends DeviceIdentifierStore {
    // ... some content inside

class deviceCertificate extends CertificateStore {
    // ... some content inside

class deviceConnection extends ConnectionStore {
    // ... some content inside

// Example 1
// this function will be invoked whenever any attribute in the telemetry state changed
async function logAttributeChanged(data) {
    console.log(`${data.deviceIdentifier} ${data.stateName} ${data.attributeTree}, ${data.value}`);
    return true;

// Example 2
// this function will be invoked a "swtich.toggle" changed
async function onChangedSwitchToggle(data) {
    if (data.value) {
    } else {
    return true;

// Example 3
// this function will be invoked a "switch.led.*" changed
async function onLedChangedRequest(data) {
    // data.attributeTree will have value like switch.led.front or switch.led.back
    const location = data.attributeTree.replace("switch.led.", "");
    some_hardware_function_to_switch_led(location, data.value);
    return true;

async function main() {
    const device: Device = new Device();
    device.identifierStore = new deviceIdentifier();
    device.connectionStore = new deviceConnection();
    device.certificateStore = new deviceCertificate();

    // register listeners
    device.useEffects(this, "smart_plug_state", "*", logAttributeChanged); // example 1
    device.useEffects(this, "smart_plug_state", "switch.toggle", onChangedSwitchToggle); // example 2
    device.useEffects(this, "smart_plug_state", "switch.led.front", onLedChangedRequest); // example 3
    device.useEffects(this, "smart_plug_state", "switch.led.back", onLedChangedRequest); // example 3

    // start the device
    await device.start();

async function exit() {
    // stop the device 
    await device.stop();


import sys
import asyncio
import concurrent.futures
from neuko.device.identifierStore import DeviceIdentifierStore
from neuko.connection.certificateStore import CertificateStore
from neuko.connection.connectionStore import ConnectionStore
from neuko.device.model import DeviceIdentifier, TelemetricStateChangeParameter
from neuko.device.device import Device, DeviceState

class deviceIdentifier(DeviceIdentifierStore):
    # ... some content here

class deviceCertificate(CertificateStore):
    # ... some content here

class deviceConnection(ConnectionStore):
    # ... some content here

class MyDevice:
    def __init__(self) -> None:
        self.device = None
        self.RUNNING = False
        self._ready = False

    # Example 1 - this function will be invoked in another thread whenever any attribute in the telemetry state changed
    def logAttributeChanged(self, params: TelemetricStateChangeParameter):
        print(f'{params.deviceIdentifier}, {params.stateName}, {params.attributeTree}, {params.value}')
        return true

    # Example 2 - this function will be invoked in another thread whenever a "swtich.toggle" changed
    def onChangedSwitchToggle(self, params: TelemetricStateChangeParameter):
        return true

    # Example 3 - this function will be invoked in another thread whenever a "switch.led.*" changed
    def onLedChangedRequest(self, params: TelemetricStateChangeParameter):
        location = params.attributeTree.replace("switch.led.", "")
        some_hard_function_to_switch_led(location, params.value)
        return true

    def init(self):
        self.device = Device(deviceIdentifier(), deviceConnection(), deviceCertificate())

        self.useEffect(self, self.logAttributeChanged, "smart_plug_state", "*") # example 1
        self.useEffect(self, self.onChangedSwitchToggle, "smart_plug_state", "switch.toggle") # example 2
        self.useEffect(self, self.onLedChangedRequest, "smart_plug_state", "switch.led.front") # example 3
        self.useEffect(self, self.onLedChangedRequest, "smart_plug_state", "switch.led.back") # example 3


    async def start(self):
        self.RUNNING = True
        while self.RUNNING:
            if (self._ready == False):
                if (self.gateway.state == DeviceState.READY):
                    self._ready = True
            await asyncio.sleep(1)

    async def stop(self):
        self.RUNNING = False
        await self.gateway.stop()

async def forever():
    mydevice = MyDevice()
    await mydevice.start()

def main():
    loop = asyncio.new_event_loop()

if __name__ == "__main__":


Telemetry state lifecycles

When an active device connected to the platform, Neuko Device SDK requests the latest telemetry state from its Virtual Twin and copy it into local variable.

Once it has copied, it will invoked each of the listeners registered using useEffect() function. As the result, you should know that this can be used to initialize the device at the time of connecting.

Scroll to Top