Device : IoT device operation
This module is the EdgerOS Device service module. Applications can use this module to operate any IoT device connected to this EdgerOS machine. This module is available in EdgerOS 1.6.0 and later.
EdgerOS supports various types of IoT devices. The supported protocols include: MQTT, MQTT-SN, CoAP, SDDC, Zigbee Home Automation, etc. SDDC devices and Zigbee Home Automation devices can be directly operated use Device
module. MQTT, MQTT-SN, CoAP devices can obtain related device resources and description through this module, and directly use MQTT
and CoAP
modules to operate the device.
Any IoT device connected to EdgerOS includes a devid
. This devid
is the globally unique identifier of the device. The App that operates this device must first have the operation permission of the corresponding device devid
before it can obtain the complete information of the device and operate the device.
This module is the asynchronous mode of the Device
module. User can use the following code to import the Device
module.
var Device = require('async/device');
Support
The following shows Device
module APIs available for each permissions.
User Mode | Privilege Mode | |
---|---|---|
Device | ● | ● |
Device.count | ● | ● |
Device.list | ● | ● |
Device.info | ● | ● |
Device.named | ● | ● |
device.request | ● | ● |
device.release | ● | ● |
device.address | ● | ● |
device.send | ● | ● |
device.transmit | ● | ● |
Device.Connector | ● | ● |
connector.write | ● | ● |
connector.end | ● | ● |
connector.close | ● | ● |
connector.toJSON | ● | ● |
Device Class
new Device()
- Returns: {Object} Device object.
Create a device object.
Example
var device = new Device();
async Device.count(join)
join
{Boolean} Whether to list only devices that have joined the network.- Returns: {Integer} Device count.
Get all device count currently discovered by the system. When join
is true
, only get device count that have been discovered and joined.
Example
async function getCount() {
console.log(await Device.count(true));
}
async Device.list(join)
join
{Boolean} Whether to list only devices that have joined the network.- Returns: {Array} devid and alias object list.
List all devices currently discovered by the system. When join
is true
, only list devices that have been discovered and joined.
Example
async function showDevs() {
var list = await Device.list(true);
for (var item of list) {
console.log(item.alias, item.devid);
}
}
async Device.info(devid)
devid
{String} Device ID.- Returns: {Object} Device information.
Get detailed information for the specified device. The device information includes two parts, report
: basic information reported by the device, and server
: device server information. If this device contains server information, such as a CoAP server, it can only be obtained after device.request()
succeeds, otherwise only the basic device information can be obtained.
The return object contains the following members:
join
{Boolean} Whether the device has joined the network. Only devices that have been confirmed to join the network can operate.alias
{String} Device alias name.report
{Object} Basic information reported by the devicename
{String} Name of the current machine. Typically:'Printer'
,'Patch panel'
,'Air conditioning'
...type
{String} The type of the machine. Typically:'monitor'
,'edger'
,'device'
.excl
{Boolean} This device is App exclusive.desc
{String} Device description information.model
{String} Device model.vendor
{String} Device manufacturer.version
{Array} Device software version, optional.
server
{Object} Server information.coap
{Array} All CoAP server object information in this device.port
{Integer} CoAP server port.
addr
{String} If it is a network device, it indicates the IP address of the target device. For example, a CoAP device can use this IP address to access the device with the specified device service.probe
{Boolean} Only the ZigBee device contains this member, indicating whether this device is allowed to be probed. Ifprobe
istrue
, it means that EdgerOS can automatically sense the online and offline status of this device.
Example
async function showDevs() {
var list = await Device.list(true);
for (var item of list) {
var info = await Device.info(item.devid);
console.log(item.alias, 'information:', JSON.stringify(info));
}
}
async Device.named()
- Returns: {Array} All devices have been aliased.
Get a list of all devices in the system that have been aliased, regardless of whether the device is online.
Example
async function showDevs() {
var list = await Device.named();
for (var item of list) {
console.log(item.alias, item.devid);
}
}
Device Object
async device.request(devid)
devid
{String} Device ID.- Returns: {Boolean} Whether the operation was successful.
Request control of specified device. First you need to use permission.device()
to check if you have permission to access this device.
When this device is an exclusive device and is being used by other app, you cannot get the operation permission.
Example
var permission = require('permission');
var device = new Device();
async function test(devid) {
try {
var suc = await device.request(devid);
} catch (error) {
if (permission.isDenied(error)) {
console.log('No permission');
} else {
console.error(error);
}
}
}
Example
if (device.devid) {
device.send(...);
}
async device.release([removeAllListeners])
removeAllListeners
{Boolean} Whether to remove the previously installed event listener after the release is successful. default: false.
Release the previously requested device. When the operation of the device is completed, the device should be released immediately.
Example
async function test(devid) {
var device = new Device();
await device.request(devid);
await device.release();
}
async device.address()
- Returns: {String} Device net address.
Sometimes we need to use some special protocols to access the device, such as CoAP, etc. We can use this function to get the network address of the requested device.
Example
async function test(devid) {
var device = new Device();
await device.request(devid);
console.log(await device.address());
await device.release();
}
async device.send(msg[, retries[, urgent[, mark]]])
msg
{Object} Message to send.retries
{Integer} Number of automatic retries. default: 2.urgent
{Boolean} Whether it is an urgent message. default: false.mark
{Boolean} Whether to mark the current app tag in the data packet. default: true.
Send a message to the specified device. When retries
is 0, it means non-reliable sending. When retries
> 0, the device will delay retrying when device not confirm (depends on the implementation of the relevant link protocol).
Example
device.send({ hello: 'hello' }).then(() => console.log('send!'), console.error);
If you need to send an urgent message, you can set urgent
to true
, preempt the current sending sequence, and immediately transmit the urgent message. Not all IoT connections support urgent messages. If the communication link does not support, this message will be transmitted as a normal message.
When the target device can be shared and used by multiple apps, the mark
function will indicate the ID of the App in the data packet sent to the device. Using this information, the current App can establish a session with the target device, so that the target device can send data directly to the current App, other apps can’t received. EdgerOS 1.5.8 and later versions support mark
.
device.transmit(msg[, retries[, urgent[, mark]]])
msg
{Object} Message to send.retries
{Integer} Number of automatic retries. default: 2.urgent
{Boolean} Whether it is an urgent message. default: false.mark
{Boolean} Whether to mark the current app tag in the data packet. default: true.
Same as device.send
, but don't care about the result, used for some non-critical data transmission.
Example
device.transmit({ hello: 'hello' });
Device Class Events
Device
class and device
objects both inherit from EventEmitter
, The following events are thrown in some specific situations.
found
A new device was found. Only privileged app can receive this event.
Example
Device.on('found', function(devid, info) {
console.log('A new device was found:', devid, 'report:', info.report);
});
join
The discovered device has successfully joined the network and can request.
Example
Device.on('join', function(devid, info) {
console.log('Device join in:', devid, 'report:', info.report);
});
update
Device information changes, such as IP address or server status.
Example
Device.on('update', function(devid, info) {
console.log('Device update:', devid, 'report:', info.report);
});
lost
The device is lost. The lost device can no longer be operated.
Example
Device.on('lost', function(devid) {
console.log('Device lost:', devid);
});
alias
The specified device alias is modified.
Example
Device.on('alias', function(devid, info) {
console.log('Device alias modified:', devid, 'alias:', info.alias);
});
refuse
Discovered device refuses to join the network.
Example
Device.on('refuse', function(devid) {
console.warn('Device refuse join network:', devid);
});
Device Object Events
message
Received a message from a device.
Example
device.on('message', function(msg) {
console.log('received a message:', msg);
});
lost
This device is lost. The lost device can no longer be operated.
Example
device.on('lost', function() {
// This device lost
});
Device.Connector Class
Many devices need to perform batch data network transmission. EdgerOS provides the Device.Connector
class specifically for this operation. This class can receive and send data. At the same time, it supports encrypted data transmission. Device.Connector
only supports network devices. Device.Connector
class inherits from Stream.Duplex
class (For details: Stream), developers can use stream operations to communicate with the device in both directions
new Device.Connector(device[, cipher[, timeout]])
device
{Object} Device object.cipher
{Boolean} Whether to use encrypted transmission. default: false.timeout
{Integer} Maximum quiet time, no data transmission after checking this time, the current connection will be closed. default: 6000ms.- Returns: {Object}
Device.Connector
object.
Create a Device.Connector
object for batch data transfer with the device. If cipher
is true
, the data transmission will use a random key for encrypted transmission.
Example
var device = new Device();
device.request(devid).then(() => {
var connector = new Device.Connector(device);
// ...
}).catch(console.error);
Device.Connector Object
connector.close()
Close the current object, this object can no longer be used for any data transfer.
connector.write(data[, encoding][, callback])
data
{String | Buffer} Data to write.encoding
{String} Only used when data is string. default: utf8.callback
{Function} Optional callback for when the socket is finished.error
{Error} Specify the error when writing an error.
- Returns: {Boolean} Whether this operation was successful.
Send data to the device. Before sending data, you must ensure that the Device.Connector
object has been linked with the device.
Like Writable
stream object, if the return value is false
, indicating that there is too much data in the sending buffer, and it is recommended that the remaining data continue to be sent in the drain
event.
Example
var chunk = Buffer.from(...);
connector.write(chunk);
connector.end([data[, encoding][, callback]])
data
{String | Buffer} Data to write. default: no data to send.encoding
{String} Only used when data is string. default: 'utf8'.callback
{Function} Optional callback for when the socket is finished.error
{Error} Specify the error when writing an error.
To end data transmission, the Device.Connector
object must call this function to end data transmission after sending data to the device.
Example
connector.write('hello', 'utf-8');
connector.end();
// Or:
connector.end('hello', 'utf-8');
connector.toJSON()
- Returns: {String} This connector network parameters.
This function can cooperate with the device.send()
operation to inform the device of connector
related transmission parameters, and the device actively connects to the current connector
for data communication according to this parameter.
Example
var device = new Device();
device.request(devid).then(() => {
var connector = new Device.Connector(device);
// connector.toJSON() will return: {"port":...,"token":"..."}
// Or {"port":...}
device.send({ cmd: 'get_picture', connector: connector });
var chunks = [];
connector.on('data', function(chunk) {
chunks.push(chunk);
});
connector.on('close', function() {
// Closed!
});
connector.on('error', function(error) {
// Error!
connector.close();
});
}).catch(console.error);
- Send data
var device = new Device();
var chunk = fs.readFile('./pic.jpg');
device.request(devid).then(() => {
var connector = new Device.Connector(device);
// connector.toJSON() will return: {"port":...,"token":"..."}
// Or {"port":...}
device.send({ cmd: 'put_picture', connector: connector, size: chunk.length });
connector.on('connect', function() {
connector.end(chunk);
}
connector.on('close', function() {
// Closed!
});
connector.on('error', function(error) {
// Error!
connector.close();
});
}).catch(console.error);
Device.Connector Object Events
connect
When a device is connected, this event will be generated. Only after this event occurs, data can be sent and receive.
timeout
This event will be generated when the connector has no device connection for a long time. The connection will be closed automatically.
drain
Emitted when the write buffer becomes empty. Can be used to throttle uploads.
error
error
{Error} Indicate an error. When a communication error occurs, this event will be generated and indicate an error. This event callback must be installed to handle this event.
data
chunk
{String} | {Buffer} Received data. This event will be generated when data from the device is received.
finish
When the data transmission is completed, this event will be generated.
close
When the connector
connection is closed, this event will be generated, and the connector
object can no longer be used.
Device.Connector Writable & Readable
The Device.Connector
object can support duplex communication with the device. When sending data, it can be used as a Writable object for readable.pipe()
operations.
Example
var device = new Device();
var readable = fs.createReadStream('./pic.jpg');
device.request(devid).then(() => {
var connector = new Device.Connector(device);
// connector.toJSON() will return: {"port":...,"token":"..."}
// Or {"port":...}
device.send({ cmd: 'put_picture', connector: connector, size: fs.size('./pic.jpg') });
connector.on('connect', function() {
readable.pipe(connector);
}
connector.on('close', function() {
// Closed!
});
connector.on('error', function(error) {
// Error!
connector.close();
});
}).catch(console.error);