cylon
cylon copied to clipboard
Adding devices on runtime.
I am using Cylon for my Smart Devices framework, I am using MQTT for this purpose. I've defined a driver for my AirConditionar let's say. I have an ESP8026 chip in each AC which may use the different driver, but let's stick to one for now and I am using MQTT for communication.
I've added MQTT device with a topic devices/events on which every device will send data. I am using this device inside ESP's custom driver.
Now I want to add more devices dynamically to this robot in my MQTT's onConnect event on broker side. How can I do that?
This is the way I am defining my driver
Cylon.robot({
connections: {
server: { adaptor: 'mqtt', host: 'mqtt://localhost:1883' }
},
devices: {
deviceAdapter: { driver: 'mqtt', topic: 'device/event', adaptor: 'server' },
ultron: { driver: 'orient-ultron', deviceId: '5CCF7F095FE9', topic: 'device/5CCF7F095FE9/command' }
},
work: function(my) {
my.ultron.initDriver(null, () => {
console.log('driver bootstraped');
});
my.deviceAdapter.on('message', function (data) {
debug(data);
my.ultron.setState(data);
sendCommand();
});
my.ultron.on('state', function (data) {
debug('inside state event', data.toString());
});
function sendCommand() {
my.ultron.thermostatDrySetpoint(30);
}
}
}).start();
and this is the way I've defined my driver.
class Driver extends Cylon.Driver {
constructor(opts, cb) {
super(opts);
this.setupCommands(Commands);
this.deviceId = opts.deviceId || null;
this.topic = opts.topic;
this.commands = Commands;
this.protobuf = {};
this.state = {};
this.initDriver(cb);
debug(this.deviceId);
}
start(callback) {
const events = ['state', 'measurement', 'alert', 'log', 'ack'];
events.forEach(function(e) {
this.defineDriverEvent(e);
}.bind(this));
if (this.robot.devices.deviceAdapter) {
this.connection.robot.devices.deviceAdapter.on('message', function(data) {
// TODO modify event based on type of data received
debug('Got data inside driver throught adapter', data.toString());
this.emit('state', data);
}.bind(this));
}
callback()
}
halt(callback) { callback() }
/**
* Send standby command to OrientUltron
* This capability is used to set standby mode of a device.
* @param {String} value true | false
*/
standby(value) {
const action = this.protobuf.message.lookup('standby').name;
this.sendToDevice(action, value || false);
}
/**
* Send refresh command to OrientUltron
* This capability is used to request all latest state values from a device.
*/
refresh() {
const action = this.protobuf.message.lookup('refresh').name;
this.sendToDevice(action, true);
}
/**
* This is the thermostat's setpoint value, when the thermostat mode is set to Auto. The value will be fixed on 24.
*/
thermostatAutoSetpoint() {
const action = this.protobuf.message.lookup('thermostatAutoSetpoint').name;
this.sendToDevice(action, 24);
}
/**
* This is the thermostat's setpoint value, when the thermostat mode is set to Cool. The default value will be 24. The values ranges from 16 to 32.
* @param {Number} value 16-32
*/
thermostatCoolingSetpoint(value) {
const action = this.protobuf.message.lookup('thermostatCoolingSetpoint').name;
this.sendToDevice(action, value || 24);
}
/**
* This is the thermostat's setpoint value, when the thermostat mode is set to Dry. The default value will be 24. The values ranges from 16 to 32.
* @param {Number} value 16-32
*/
thermostatDrySetpoint(value) {
const action = this.protobuf.message.lookup('thermostatDrySetpoint').name;
this.sendToDevice(action, value);
}
/**
* This is the thermostat's fan mode (speed). e.g. "4 = high", "3 = mid", "2 = low", "1 = auto". The default value will be "auto".
* @param {Number} value 4 | 3 | 2 | 1
*/
thermostatFanMode(value) {
const action = this.protobuf.message.lookup('thermostatFanMode').name;
this.sendToDevice(action, value);
}
/**
* This is the thermostat's setpoint value, when the thermostat mode is set to Heat.
* @param {Number} value
*/
thermostatHeatingSetpoint(value) {
const action = this.protobuf.message.lookup('thermostatHeatingSetpoint').name;
this.sendToDevice(action, value);
}
/**
* This is the thermostat's fan mode. e.g. "1 = auto", "2 = cool", "3 = dry", "4 = heat", "5 = fan"
* @param {Number} value 1 | 2 | 3 | 4 | 5
*/
thermostatMode(value) {
const action = this.protobuf.message.lookup('thermostatMode').name;
this.sendToDevice(action, value);
}
/**
* Controls Vertical air flow direction of a device.
* Send air flow change command to OrientUltron
*/
verticalAirFlowDirection() {
const action = this.protobuf.message.lookup('verticalAirFlowDirection').name;
this.sendToDevice(action, true);
}
/**
* Controls horizontal air flow direction of a device.
* Send air flow change command to OrientUltron
*/
horizontalAirFlowDirection() {
const action = this.protobuf.message.lookup('horizontalAirFlowDirection').name;
this.sendToDevice(action, true);
}
setState(state) {
if (this.protobuf.message) {
this.state = this.protobuf.decode(state);
debug(this.state);
} else {
debug('state not updated');
}
}
initDriver(filePath, cb) {
if (!this.protobuf.message) {
const path = filePath || './';
this.protobuf = new ProtocolBuffer('format', path, 'ACDriver', 'ACActions', () => {
debug('protobuf loaded');
if (cb) cb(this);
});
} else {
debug('protobuf already loaded');
}
}
sendToDevice(key, value) {
this.state[key] = value;
this.connection.publish(this.topic, this.protobuf.encode(this.state));
}
}
module.exports = Driver;
Hello, I'm doing a dynamic driver configuration from electron UI & IPC by using require. I think you can re-implement this code using Socket.io or MQTT. But probably you need to setup a different HTTP / MQTT port from the cylon-api-mqtt / http module. :
electron IPC Code:
ipc.on('device', (event, arg) => {
console.log("ipc called");
const DeviceServer = new DeviceHttpServer(arg);
DeviceServer.start();
});
Dynamic Server Code:
import http from "http";
class DeviceHttpServer{
constructor(device){
this.device = device;
console.log("DeviceHttpServer object created");
}
start(){
require( __dirname +"/" + this.device);
}
}
export default DeviceHttpServer;
cylon module code called by require:
import Cylon from "cylon";
Cylon.api("http", {
host: '127.0.0.1',
port: '3001',
ssl: false,
auth: false
});
Cylon.robot({
name: "hoge",
connections: {
bebop: { adaptor: 'hoge' }
},
devices: {
drone: { driver : 'hoge' }
},
work: function(my){
}
}).start();