JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 17
  • Score
    100M100P100Q12425F
  • License MIT

A Smart Object Class that helps you create IPSO Smart Objects in your JavaScript applications

Package Exports

  • smartobject

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (smartobject) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

smartobject

NPM

Build Status npm npm

Table of Contents

  1. Overview
  2. Installation
  3. Usage
  4. Resources Planning
  5. APIs

1. Overview

smartobject is a Smart Object Class that helps you create IPSO Smart Objects in your JavaScript applications. If you'd like use IPSO data model in your projects or products, you can use smartobject as the base class to abstract your hardware, sensor modules, or gadgets into plugins (node.js packages) for users convenience.

IPSO defines a hierarchical data model to describe real-world gadgets, such as temperature sensors and light switches. IPSO uses Object to tell what kind of a gadget is, and uses Object Instance to tell which one a gadget is. An Object is like a class, and Object Instance is the entity of an Object. Each Object Instance has an unique Object Instance Id to identify itself from other gadgets with the same class. The Resources are used to describe what attributes may a gadget have, for example, a temperature sensor may have attributes such as sensorValue, unit, minMeaValue, .etc.

[Note]: The italics, such Object, Object Id, Object Instance, and Object Instance Id, are used to distinguish the IPSO Objects from the JavaScript objects.

2. Installation

$ npm install smartobject --save

3. Usage

Here is a quick example to show you how to create your Smart Object with only few steps:

// Step 1: Import the SmartObject Class
var SmartObject = require('smartobject');

// Step 2: New a SmartObject instance to have all your IPSO Objects in it
var so = new SmartObject();

// Step 3: Initialize a 'temperature' Object Instance in your smart object 'so'.  
//         - 'temperature' is the IPSO Object Identifier (oid).
//         - 0 is the Object Instance Id (iid).
//         - { sensorValue, units } contains all Resources (attributes) this sensor has.  
//         - sensorValue and units are the Resource Id (rid)

so.init('temperature', 0, {
    sensorValue: 31,
    units : 'Celsius'
});


// Init more temperature sensors (each with an unique iid)
so.init('temperature', 1, {
    sensorValue: 28,
    units : 'Celsius'
});

so.init('temperature', 2, {
    sensorValue: 72.6,
    units : 'Fahrenheit'
});

// Init other gadgets
so.init('magnetometer', 0, {
    xValue: 18,
    yValue: 21,
    zValue: 231
});

so.init('dIn', 0, { dInState: 1 });
so.init('dIn', 1, { dInState: 0 });
so.init('dIn', 6, { dInState: 0 });
so.init('dIn', 7, { dInState: 1 });

4. Resources Planning

Imagine that you have to read the temperature value from which sensor with one-wire interface, and you'd like to export this sensor to an IPSO smart object, but how to? And how do you update the temperature value to your smart object, polling it regularly? How do you do with the access control? Which Resource is readable? Which is writable? And which is remotely executable?

The great benefit of using smartobject in your application is that you almost need not to tackle the allocation of Resources by yourself. It provides a scheme to help you with management of reading/writing your hardware or executing a procedure on the machine. All you have to do is to plan and define your Resources well, and then use smartobject methods to access them.

Please refer to Resources Planning Tutorial for more details.

Here are the code templates of many IPSO-defined devices, such as temperature sensor, humidity sensor, and light control. Each template gives the code snippet of how to initialize an Object Instance with its oid and iid, and lists every Resource the Object Instance may have.

5. APIs


SmartObject Class

Exposed by require('smartobject').

new SmartObject()

Create a new instance of SmartObject class. This document will use so to indicate this kind of instance. A so can hold many IPSO Objects in it.

Arguments:

  1. none

Returns:

  • (Object): so

Examples:

var SmartObject = require('smartobject');

var so = new SmartObject();

init(oid, iid, resrcs[, opt])

Initialize an Object Instance in so. oid is the IPSO Object Id to indicate what kind of your gadget is, for example, 'temperature'. iid is the Object Instance Id to tell a Instance from the others. resrcs is an object that wraps all the Resources up.

  • Simply speaking, oid is like a namespace to manage all the same kind of IPSO Object Instances. For example, our so has a 'temperature' namespace, and there are 3 temperature sensors(Object Instances) within this namespace.
  • You can initialize an Object Instance with an empty resrcs = {}, and then use set() method to add Resources one by one to the Instance. In my experience, initialize an Object Instance with all Resources at once is more elegant, for example, you can manage all your Resources in a separated module, and export the whole thing to your main app to do the initialization).
  • Be careful, invoking init() upon an existing Instance will firstly remove all the Resources it has and then put the new Resources into it. Thus, it is better to initialize your Instance only once throughout your code.
  • Resources Planning Tutorial will show you the how-tos about initializing your Resources and exporting your hardware to IPSO Resources.

Arguments:

  1. oid (String | Number): IPSO Object Id. oid indicates what kind of your gadget is, for example, 'temperature' apparently tells it's a temperature sensor. oid also accepts a numeric id defined by IPSO, for example, you can give it a number of 3303, and so will internally turn it into its string version, say 'temperature', as a key.
  2. iid (String | Number): Object Instance Id, which tells different Instances. For example, if you have 3 temperature sensors on your machine, then you can assign an unique iid to each of them to distinguish one from the others. It would be nice to use numbers, i.e., 0, 1, 2, 3, as the iid to strictly meet the IPSO definition. But strings are also accepted, e.g., 'sen01', 'sen02', 'sen03', it is just like a handle to help you distinguish different Instances within the same Object class.
  3. resrcs (Object): IPSO Resources, which is an object with rid-value pairs to describe the Resources. Each key in resrcs is a Resource Id, which can be a string or a number. And each value can be a primitive, an data object, or an object with specific methods, i.e. read(), write(), exec(). Resources Planning Tutorial will give you some hints.
  4. opt (Object): An option object, default is { ipsoOnly: false } if not given. If it is given with { ipsoOnly: true }, then oid must be an IPSO-defined Object Id, iid must be a number, and Resource Ids within resrcs must all be IPSO-defined Resource Ids, or init() will throw Errors.

Returns:

  • (Object): The initialized Object Instance.

Examples:

var so = new SmartObject();

so.init('temperature', 0, {
    sensorValue: 31,
    units : 'Celsius'
});

so.init('temperature', 1, {
    sensorValue: 75,
    units : 'Fahrenheit'
});

so.init('temperature', 18, {
    sensorValue: 301,
    units : 'Kelvin'
});

// Dump the whole Smart Object
so.dump(function (err, data) {
    if (!err)
        console.log(data);
    // {
    //     temperature: {
    //         '0': {
    //             sensorValue: 31,
    //             units : 'Celsius'
    //         },
    //         '1': {
    //             sensorValue: 75,
    //             units : 'Fahrenheit'
    //         },
    //         '18': {
    //             sensorValue: 301,
    //             units : 'Kelvin'
    //         }
    //     }
    // }
});

// Dump the 'temperature' Object
so.dump('temperature', function (err, data) {
    if (!err)
        console.log(data);
    // {
    //     '0': {
    //         sensorValue: 31,
    //         units : 'Celsius'
    //     },
    //     '1': {
    //         sensorValue: 75,
    //         units : 'Fahrenheit'
    //     },
    //     '18': {
    //         sensorValue: 301,
    //         units : 'Kelvin'
    //     }
    // }
});

// Dump the 'temperature' sensor (Object Instance) with iid = 18
so.dump('temperature', 18, function (err, data) {
    if (!err)
        console.log(data);
    // {
    //     sensorValue: 301,
    //     units : 'Kelvin'
    // }
});

objectList()

Returns the list of Objects and Object Instances with their identifiers. If an Id is an IPSO-defined one, it will be turned into a numeric one. When you're using LWM2M interface, you may need this method to generate the Object List for registering.

Arguments:

  1. none

Returns:

  • (Array): Returns an array that contains all the identifiers, each element is in the form of { oid: 3301, iid: [ 0, 1, 2, 3 ] }.

Examples:

var so = new SmartObject();

so.init('temperature', 0, {
    sensorValue: 31,
    units : 'Celsius'
});

so.init('temperature', 18, {
    sensorValue: 301,
    units : 'Kelvin'
});

so.init('illuminance', 0, {
    sensorValue: 128.6
});

so.initResrc('presence', 6, {
    dInState: 0
});

so.initResrc('myGadget', 'gad72', {
    myResource: 'hello_world'
});

so.objectList();
// [
//     { oid: 3303, iid: [ 0, 18 ] },
//     { oid: 3301, iid: [ 0 ] },
//     { oid: 3302, iid: [ 6 ] },
//     { oid: 'myGadget', iid: [ 'gad72' ] }    // not IPSO-defined
// ]

has(oid[, iid[, rid]])

To see if so has the specified Object, Object Instance, or Resource.

Arguments:

  1. oid (String | Number): Object Id of the target.
  2. iid (String | Number): Object Instance Id of the target.
  3. rid (String | Number): Resource Id of the target.

Returns:

  • (Boolean): Returns true if target exists, otherwise false.

Examples:

// Checks if so has the 'humidity' Object
so.has('humidity');                       // true

// Checks if so has the 'foo' Object Instance with iid = 0
so.has('foo', 0);                         // false

// Checks if so has the 'sensorValue' Resource in temperature sensor 8
so.has('temperature', 8, 'sensorValue');  // true

get(oid, iid, rid)

Synchronously get the specified Resource.

  • At client-side (machine), the get() method is usually used to get the raw Resource which may be an object with read/write/exec callbacks. If you like to read the exact value of a Resource, you should use the read() method. Since reading something from somewhere may require some special and asynchronous operations, such as reading data from a wire, and reading from a database.
  • At server-side (data center), the Resource values are simple data pieces requested from machines. Thus, use get() to get the stored value of a Resource on the server is no problem.

Arguments:

  1. oid (String | Number): Object Id of the target.
  2. iid (String | Number): Object Instance Id of the target.
  3. rid (String | Number): Resource Id of the target.

Returns:

  • (Depends): Returns the Resource value, or undefined if Resource does not exist.

Examples:

so.get('temperature', 2, 'sensorValue');  // 26.4

// If the Resource is an object with read/write/exec method(s)
so.get('temperature', 1, 'sensorValue');
// {
//     read: function (cb) {
//              ...
//     }
// }

// If you do like read the exact value from the temperature sensor,
// please use read()
so.read('temperature', 1, 'sensorValue', function (err, data) {
    if (!err)
        console.log(data);  // 18.4
});

set(oid, iid, rid, value)

Synchronously set a value to the specified Resource.

  • At client-side (machine), the set() method is usually used to initialize a Resource, but not write a value to a Resource. If you like to write a value to the Resource, you should use the write() method. Since writing something to somewhere may require some special and asynchronous operations, such as writing data to a wire, and writing data to a database.
  • At server-side (data center), use set() to store the value of a Resource on the server is no problem. For example, when your request of reading a Resource from a remote machine is responded back, you can use set() to store that Resource value on the server.

Arguments:

  1. oid (String | Number): Object Id of the target.
  2. iid (String | Number): Object Instance Id of the target.
  3. rid (String | Number): Resource Id of the target.
  4. value (Primitives | Object): Resource data or an object with read/write/exec method(s). This method will throw if value is given with a function.

Returns:

  • (Boolean): Returns true if set successfully, else returns false if the Object Instance does not exist (Resource cannot be set).

Examples:

so.set('dIn', 0, 'dInState', 1);    // true
so.set('dOut', 1, 'dOutState', 0);  // true

so.set('dOut', 2, 'dOutState', function (cb) {
    gpioA3.read(function (state) {  // assume gpioA3 is a handle to your hardware
        cb(null, state);
    });
});  // true

read(oid, iid, rid, callback[, opt])

Asynchronously read the specified Resource value.

Arguments:

  1. oid (String | Number): Object Id of the target.
  2. iid (String | Number): Object Instance Id of the target.
  3. rid (String | Number): Resource Id of the target.
  4. callback (Function): function (err, data) { ... }. Will be called when reading is done or any error occurs, where data is the Resource value. (When an error occurs, so will pass you a string like '_notfound_' with data, you can use it as a hint to choose a status code to respond back to the requester.)
  5. opt (Object): An option used to read Resources in restrict mode, default is { restrict: false }. If it is given with { restrict: true }, this method will follow the access control specification defined by IPSO. This option may be set to true to respond to a remote read request (access from outside world should be under control).
  • This table show you what results may the callback receive:
err data Description
Error object '_notfound_' Resource not found.
Error object '_unreadable_' Resource is unreadable.
Error object '_exec_' Resource is unreadable (Because it is an executable Resource).
null Depends Resource is successfully read.

Returns:

  • (none)

Examples:

so.read('temperature', 1, 'sensorValue', function (err, data) {
    if (!err)
        console.log(data);  // 18.4
});

so.read('actuation', 0, 'dimmer', function (err, data) {
    if (!err)
        console.log(data);  // 62
});

so.read('illuminance', 1, 'maxMeaValue', function (err, data) {
    if (err) {
        console.log(err);   //  Error: 'Resource is unreadable.'
        console.log(data);  // '_unreadable_'
    }
});

so.read('accelerometer', 2, 'minRangeValue', function (err, data) {
    if (err) {
        console.log(err);   //  Error: 'Resource not found.'
        console.log(data);  // '_notfound_'
    }
});

so.read('barometer', 6, 'resetMinMaxMeaValues', function (err, data) {
    if (err) {
        console.log(err);   //  Error: 'Resource is unreadable.'
        console.log(data);  // '_exec_'
    }
});

write(oid, iid, rid, value, callback[, opt])

Asynchronously write a value to the specified Resource.

Arguments:

  1. oid (String | Number): Object Id of the target.
  2. iid (String | Number): Object Instance Id of the target.
  3. rid (String | Number): Resource Id of the target.
  4. value (Depends): The value to write to the specified Resource.
  5. callback (Function): function (err, data) { ... }. Will be called when writing is done or any error occurs, where data is the Resource value written. (When an error occurs, so will pass you a string like '_notfound_' with data, you can use it as a hint to choose a status code to respond back to the requester.)
  6. opt (Object): An option used to write Resources in restrict mode.
  • This table show you what results may the callback receive:
err data Description
Error object '_notfound_' Resource not found.
Error object '_unwritable_' Resource is unwritable.
Error object '_exec_' Resource is unwritable (Becasue it is an executable Resource).
null Depends Resource is successfully write.

Returns:

  • (none)

Examples:

so.write('actuation', 0, 'onOff', 1, function (err, data) {
    if (!err)
        console.log(data);  // 1
});

so.write('temperature', 1, 'sensorValue', 26, function (err, data) {
    if (err) {
        console.log(err);   // Error: 'Resource is unwritable.'
        console.log(data);  // _unwritable_
    }
});

so.write('presence', 3, 'busyToClearDelay', function (err, data) {
    if (err) {
        console.log(err);   //  Error: 'Resource not found.'
        console.log(data);  // '_notfound_'
    }
});

so.write('barometer', 6, 'resetMinMaxMeaValues', function (err, data) {
    if (err) {
        console.log(err);   //  Error: 'Resource is unwritable.'
        console.log(data);  // '_exec_'
    }
});

exec(oid, iid, rid, args, callback)

Execute the specified Resource. The executable Resource is a procedure you've defined, for example, blinking a led for N times when the Resource is invoked.

Arguments:

  1. oid (String | Number): Object Id of the target.
  2. iid (String | Number): Object Instance Id of the target.
  3. rid (String | Number): Resource Id of the target.
  4. args (Array): The parameters required by the procedure.
  5. callback (Function): function (err, data) { ... }. Will be called when execution is performed or any error occurs, where data is anything your procedure like to return back. For example, when a blinking led procedure starts, you may like return an object { status: 'ok', led: 6, times: 10, speed: 5 } to the callback to tell something about this execution.
  • This table show you what results may the callback receive:
err data Description
Error object '_notfound_' Resource not found.
Error object '_unexecutable_' Resource is unexecutable.
Error object '_badarg_' Input arguments is not an array.
null Depends Resource is successfully executed, data depends on your will.

Returns:

  • (none)

Examples:

// Assume we have initialized an Object Instance like this:
so.init('foo_object', 0, {
    foo: 60,
    bar: 'hello',
    blink: {
        exec: function (args, cb) {
            var ledPin = args[0],
                times = args[1];

            myHardwareController.blinkLed(ledPin, times, function (err) {
                if (err)
                    cb(err);
                else
                    cb(null, { status: 'success', led: ledPin, times: times });
            });
        }
    }
});

// Excute the blink Resource on it
so.exec('foo_object', 0, 'blink', [ 3, 10 ], function (err, data) {
    if (!err)
        console.log(data);  // { status: 'success', led: 3, times: 10 }
});

// Excute a Resource that doesn't exist
so.exec('foo_object', 0, 'show', [], function (err, data) {
    if (err) {
        console.log(err);   // Error: 'Resource not found.'
        console.log(data);  // '_notfound_'
    }
});

dump([oid[, iid],] callback[, opt])

Asynchronously dump data from so. This dumping method uses the asynchronous read() under the hood.

  • Given with oid, iid, and a callback to dump data of an Object Instance.
  • Given with oid and a callback to dump data of an Object.
  • Given with only a callback to dump data of whole Smart Object.

Arguments:

  1. oid (String | Number): Object Id of the target.
  2. iid (String | Number): Object Instance Id of the target.
  3. callback (Function): function (err, data) { }.
  4. opt (Object): An option used to dump Resources in restrict mode.

Returns:

  • (none)

Examples:

// Dump Object Instance: 'temperature' sensor with iid = 18
so.dump('temperature', 18, function (err, data) {
    if (!err)
        console.log(data);
    // {
    //     sensorValue: 301,
    //     units : 'Kelvin'
    // }
});

// Dump Object: all 'temperature' sensors
so.dump('temperature', function (err, data) {
    if (!err)
        console.log(data);
    // {
    //     '0': {
    //         sensorValue: 31,
    //         units : 'Celsius'
    //     },
    //     '1': {
    //         sensorValue: 75,
    //         units : 'Fahrenheit'
    //     },
    //     '18': {
    //         sensorValue: 301,
    //         units : 'Kelvin'
    //     }
    // }
});

// Dump whole Smart Object
so.dump(function (err, data) {
    if (!err)
        console.log(data);
    // {
    //     temperature: {
    //         '0': {
    //             sensorValue: 31,
    //             units : 'Celsius'
    //         },
    //         '1': {
    //             sensorValue: 75,
    //             units : 'Fahrenheit'
    //         },
    //         '18': {
    //             sensorValue: 301,
    //             units : 'Kelvin'
    //         }
    //     }
    // }
});

dumpSync([oid[, iid]])

Synchronously dump data from so. This dumping method uses the synchronous get() under the hood. This method should only be used at server-side (since at server-side, all stored Objects are simply data pieces).

  • Given with both oid and iid to dump data of an Object Instance.
  • Given with only oid to dump data of an Object.
  • Given with no ids to dump data of whole Smart Object.

Arguments:

  1. oid (String | Number): Object Id of the target.
  2. iid (String | Number): Object Instance Id of the target.

Returns:

  • (Object): The dumped data, can be from an Object Instance, an Object, or whole Smart Object.

Examples:

// These examples are assuming that we are at server-side.
var myDevice = myController.find('0x12AE3B4D77886644'); // find the device
var so = myDevice.getSmartObject();                     // get the smart object on the device

// Dump Object Instance: 'temperature' sensor with iid = 18
so.dumpSync('temperature', 18);
// {
//     sensorValue: 301,
//     units : 'Kelvin'
// }

// Dump Object: all 'temperature' sensors
so.dumpSync('temperature');
// {
//     '0': {
//         sensorValue: 31,
//         units : 'Celsius'
//     },
//     '1': {
//         sensorValue: 75,
//         units : 'Fahrenheit'
//     },
//     '18': {
//         sensorValue: 301,
//         units : 'Kelvin'
//     }
// }

// Dump whole Smart Object
so.dumpSync();
// {
//     temperature: {
//         '0': {
//             sensorValue: 31,
//             units : 'Celsius'
//         },
//         '1': {
//             sensorValue: 75,
//             units : 'Fahrenheit'
//         },
//         '18': {
//             sensorValue: 301,
//             units : 'Kelvin'
//         }
//     }
// }

isReadable(oid, iid, rid)

To see if a Resource is readable.

Arguments:

  1. oid (String | Number): Object Id of the target.
  2. iid (String | Number): Object Instance Id of the target.
  3. rid (String | Number): Resource Id of the target.

Returns:

  • (Boolean): Returns true if the Resource is readable, otherwise false.

Examples:

so.isReadable('temperature', 8, 'sensorValue');     // true

isWritable(oid, iid, rid)

To see if a Resource is writable.

Arguments:

  1. oid (String | Number): Object Id of the target.
  2. iid (String | Number): Object Instance Id of the target.
  3. rid (String | Number): Resource Id of the target.

Returns:

  • (Boolean): Returns true if the Resource is writable, otherwise false.

Examples:

so.isWritable('temperature', 8, 'sensorValue');     // false

isExecutable(oid, iid, rid)

To see if a Resource is executable.

Arguments:

  1. oid (String | Number): Object Id of the target.
  2. iid (String | Number): Object Instance Id of the target.
  3. rid (String | Number): Resource Id of the target.

Returns:

  • (Boolean): Returns true if the Resource is executable, otherwise false.

Examples:

so.isExecutable('temperature', 8, 'sensorValue');   // false