842 lines
29 KiB
JavaScript
842 lines
29 KiB
JavaScript
/** @module xcf/driver/DriverBase */
|
|
define([
|
|
"dcl/dcl",
|
|
'xdojo/has',
|
|
'xide/types',
|
|
'xide/utils',
|
|
'xide/mixins/EventedMixin',
|
|
'dojo/has!host-node?nxapp/utils/_console'
|
|
], function (dcl, has, types, utils, EventedMixin, _console) {
|
|
|
|
//////////////////////////////////////////////////////////
|
|
//
|
|
// Constants
|
|
//
|
|
var isServer = has('host-node'); // We are running server-side ?
|
|
var isIDE = has('xcf-ui'); // We are running client-side and in the IDE?
|
|
var _debug = false;
|
|
var MAX_BUFFER_COUNT = 1024;
|
|
|
|
// Switch to pretty & colored console when running server side
|
|
var console = typeof window !== 'undefined' ? window.console : console;
|
|
if (_console && _console.error && _console.warn) {
|
|
console = _console;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////
|
|
//
|
|
// Helpers
|
|
//
|
|
|
|
/**
|
|
*
|
|
* @param buffer {integer[]}
|
|
* @returns {string}
|
|
*/
|
|
function toString(buffer) {
|
|
var result = "";
|
|
for (var i = 0; i < buffer.length; i++) {
|
|
result += String.fromCharCode(buffer[i]);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Compare 2 buffers
|
|
* @param arr1 {integer[]}
|
|
* @param arr2 {integer[]}
|
|
* @returns {boolean}
|
|
*/
|
|
function isEqual(arr1, arr2) {
|
|
var isArray = Array.isArray;
|
|
if (!isArray(arr1) || !isArray(arr2) || arr1.length !== arr2.length) {
|
|
return false;
|
|
}
|
|
var l = arr1.length;
|
|
for (var i = 0; i < l; i += 1) {
|
|
if (arr1[i] !== arr2[i]) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////
|
|
//
|
|
// Implementation
|
|
//
|
|
|
|
/**
|
|
* Driver Base Class
|
|
*
|
|
* @class module:xcf/driver/DriverBase
|
|
*/
|
|
var Module = dcl(EventedMixin.dcl, {
|
|
declaredClass: 'system_drivers/DriverBase',
|
|
/**
|
|
* The information about the device in this structure:
|
|
* @example
|
|
* {
|
|
* driver:"Marantz/MyMarantz.js",
|
|
* host:"102.123.23.23"
|
|
* port:23,
|
|
* protocol:"tcp"
|
|
* scope:"system_drivers"
|
|
* }
|
|
*
|
|
* @type {object}
|
|
*/
|
|
options: null,
|
|
/**
|
|
* The information about the driver it self
|
|
* @example
|
|
* {
|
|
* name:"My Marantz",
|
|
* path:"Marantz/My Marantz.meta.json"
|
|
* }
|
|
*
|
|
* @private
|
|
* @type {object}
|
|
*/
|
|
storeItem: null,
|
|
/**
|
|
* The xBlox scope object for this driver. It contains all commands, variables and settings. You can blocks
|
|
* through here
|
|
* @private
|
|
* @access private
|
|
*/
|
|
blockScope: null,
|
|
/**
|
|
* Our delegate is in charge to send messages
|
|
* @private
|
|
* @access private
|
|
*/
|
|
delegate: null,
|
|
/**
|
|
* @type {string}
|
|
* @default \r
|
|
*/
|
|
lineBreak: '\r',
|
|
// (optional, but recommended) name your class:
|
|
// constructor is a method named ... 'constructor'
|
|
constructor: function (name) { },
|
|
/**
|
|
* sendSettings contains the constants for receiving and sending data to a device
|
|
* its being set at initialization time and has this structure:
|
|
* @example
|
|
{
|
|
constants:{
|
|
end:'\r',
|
|
start:'',
|
|
},
|
|
send:{
|
|
interval:500,
|
|
mode:true|false, //true=onReply | false=Interval
|
|
onReply:'\n',
|
|
timeout:500
|
|
}
|
|
}
|
|
* @type {object}
|
|
*/
|
|
sendSettings: null,
|
|
/**
|
|
* responseSettings contains the constants for receiving data from a device
|
|
* its being set at initialization time and has this structure:
|
|
* @example
|
|
{
|
|
start:false,
|
|
startString:''
|
|
cTypeByte:false, //construction type 'Per Byte'
|
|
cTypePacket:false, //construction type 'Per Packet'
|
|
cTypeDelimiter:true, //construction type 'Per Delimiter'
|
|
cTypeCount:false, //construction type 'Per Count'
|
|
delimiter:'', //the delimiter
|
|
count:10 //packet count
|
|
}
|
|
* @type {object}
|
|
*/
|
|
responseSettings: null,
|
|
/**
|
|
* currently outgoing message queue
|
|
* @private
|
|
* @type {message[]}
|
|
*/
|
|
outgoing: null,
|
|
/**
|
|
* currently incoming message queue
|
|
* @private
|
|
* @type {message[]}
|
|
*/
|
|
incoming: null,
|
|
/**
|
|
* incoming message string
|
|
* @private
|
|
* @type {string|null}
|
|
*/
|
|
incomingBuf: null,
|
|
|
|
bytesIncomeBuf: null,
|
|
// reference to a Javascript timer object, used for sending outgoing messages. private!
|
|
/**
|
|
* @private
|
|
*/
|
|
queueTimer: null,
|
|
/**
|
|
* private!in case processOutgoing is busy
|
|
* @private
|
|
*/
|
|
busy: false,
|
|
|
|
_lastInterval: null,
|
|
_onReplyTimeout: null,
|
|
onReplyStatus: false,
|
|
/**
|
|
* Method to add a logging message.
|
|
*
|
|
* @param level {string} This can be error, warning, info, trace or custom
|
|
* @param type {string} An additional string, by default this is set to "Device"
|
|
* @param message {string} The message it self
|
|
* @param data {object} An optional object/data you want to include
|
|
*
|
|
* @example
|
|
*
|
|
// for instance you want to log any incoming message in a custom way, you need to overwrite 'sendMessage' in
|
|
// your base class like this:
|
|
|
|
onMessage: function (data) {
|
|
|
|
this.log('info', 'my marantz', 'Marantz Driver Message: ' + data.message, {
|
|
some: 'extra',
|
|
message: data
|
|
});
|
|
|
|
this.inherited(arguments); //important, call BaseDriver::onMessage!
|
|
}
|
|
*
|
|
*/
|
|
log: function (level, type, message, data) {
|
|
return this.inherited(arguments);
|
|
},
|
|
/**
|
|
* Callback when we got changed by an external editor or the IDE.
|
|
*/
|
|
onReloaded: function (evt) {
|
|
},
|
|
/***
|
|
* Unescape string from line breaks
|
|
* @param str
|
|
* @returns {*}
|
|
*/
|
|
unescape: function (str) {
|
|
|
|
str = utils.convertAllEscapes(str, "none");
|
|
try {
|
|
if (str) {
|
|
//return JSON.parse('"' + str + '"');
|
|
}
|
|
} catch (e) {
|
|
console.error('-bad');
|
|
}
|
|
var _a2 = str.length;
|
|
return str;
|
|
},
|
|
complete: function (str, _end) {
|
|
var end = JSON.parse('"' + _end + '"');
|
|
var out = "" + str;
|
|
for (var i = 0; i < end.length; i++) {
|
|
var hex = end.charCodeAt(i);
|
|
hex = String.fromCharCode(hex);
|
|
out += hex;
|
|
}
|
|
out = utils.convertAllEscapes(out, "none");
|
|
return out;
|
|
},
|
|
completeBegin: function (str, _start) {
|
|
var end = JSON.parse('"' + _start + '"');
|
|
var begin = "";
|
|
|
|
var out = "" + str;
|
|
|
|
for (var i = 0; i < end.length; i++) {
|
|
var hex = end.charCodeAt(i);
|
|
hex = String.fromCharCode(hex);
|
|
begin += hex;
|
|
}
|
|
return utils.convertAllEscapes(begin, "none") + out;
|
|
},
|
|
/**
|
|
* Surround command with 'start' and 'end' constant, specified in the command settings
|
|
* of the driver.
|
|
* @param msg
|
|
* @param toBuffer {boolean} Return a buffer, serialized with commas : '01,02,03'
|
|
* @returns {*|string|String}
|
|
*/
|
|
prepareMessage: function (msg, toBuffer) {
|
|
var _m = "" + msg;
|
|
// add 'start'
|
|
if (this.sendSettings.constants.start) {
|
|
_m = "" + this.completeBegin("" + msg, this.sendSettings.constants.start);
|
|
}
|
|
// add 'end'
|
|
if (this.sendSettings.constants.end) {
|
|
_m = this.complete(_m, this.sendSettings.constants.end);
|
|
}
|
|
return toBuffer !== false ? utils.stringToBufferStr(_m) : _m;
|
|
},
|
|
|
|
/***
|
|
* Process outgoing sends last message from this.outgoing
|
|
* @param force
|
|
*/
|
|
processOutgoing: function (force) {
|
|
//if mode == 1 its on reply, if mode ===false its on interval
|
|
var mode = this.sendSettings.send.mode;
|
|
|
|
if (force == true || mode) {
|
|
this.busy = false;
|
|
}
|
|
|
|
//locked?
|
|
if (this.busy) {
|
|
_debug && console.log('busy, abort');
|
|
return;
|
|
}
|
|
this.busy = true;
|
|
|
|
var thiz = this;
|
|
|
|
if (!this.outgoing) {
|
|
this.outgoing = [];
|
|
}
|
|
/************************************************************/
|
|
/* update timers */
|
|
var interval = parseInt(this.sendSettings.send.interval);
|
|
//set the interval to 0 in case its not specified:
|
|
if (!mode && !interval) {
|
|
interval = 0;
|
|
}
|
|
|
|
|
|
//clear interval timer in case user changed settings to "onReply"
|
|
if (mode === 1 && this.queueTimer) {
|
|
clearTimeout(this.queueTimer);
|
|
this.queueTimer = null;
|
|
_debug && console.log('cleared interval timer!');
|
|
} else if (mode === 0 && this._onReplyTimeout) {
|
|
this._clearOnReplyTimeout();
|
|
return;
|
|
}
|
|
|
|
_debug && console.log('process , mode = ' + mode + ' | interval = ' + interval + ' | messages to send = ' + this.outgoing.length);
|
|
|
|
//send via interval
|
|
if (!mode && interval > 0) {
|
|
//interval has changed
|
|
if (this._lastInterval && this._lastInterval !== interval && this.queueTimer) {
|
|
clearTimeout(this.queueTimer);
|
|
this.queueTimer = null;
|
|
}
|
|
|
|
//create a timer
|
|
if (!this.queueTimer) {
|
|
this.queueTimer = setInterval(function () {
|
|
thiz.busy = false;//reset lock
|
|
thiz.processOutgoing();
|
|
}, interval);
|
|
this._lastInterval = interval;
|
|
}
|
|
}
|
|
|
|
var messageToSend = this.outgoing[0];//pick the first
|
|
var delegate = this.delegate;
|
|
|
|
//now finally send it out
|
|
if (messageToSend) {
|
|
if (!messageToSend.didPrepare) {
|
|
messageToSend.msg = "" + this.prepareMessage(messageToSend.msg);
|
|
messageToSend.didPrepare = true;
|
|
}
|
|
|
|
//delegate : nxapp.manager.DeviceManager || xcf.manager.DeviceManager
|
|
|
|
//send via interval mode
|
|
if (!mode) {
|
|
try {
|
|
if (delegate && delegate.sendDeviceCommand) {
|
|
_debug && console.log('-send message : ' + messageToSend.msg);
|
|
delegate.sendDeviceCommand(thiz, messageToSend.msg, messageToSend.src, messageToSend.id, null, messageToSend.wait, messageToSend.stop, messageToSend.pause, null, messageToSend.args);
|
|
} else {
|
|
console.error('have no delegate');
|
|
}
|
|
} catch (e) {
|
|
console.error('error sending message : ' + e.message);
|
|
}
|
|
//remove from out going
|
|
thiz.outgoing.remove(messageToSend);
|
|
} else {
|
|
|
|
//send via onReply mode
|
|
|
|
//special case, first command && nothing received yet:
|
|
if (/*force==true || mode*/ this.onReplyStatus) {
|
|
try {
|
|
|
|
if (delegate && delegate.sendDeviceCommand) {
|
|
delegate.sendDeviceCommand(thiz, messageToSend.msg, messageToSend.src, messageToSend.id, null, messageToSend.wait, messageToSend.stop, messageToSend.pause, null, messageToSend.args);
|
|
} else {
|
|
console.error('have no delegate');
|
|
}
|
|
} catch (e) {
|
|
console.error('error sending message : ' + e.message);
|
|
logError(e, 'error sending message ');
|
|
}
|
|
//remove from out going
|
|
thiz.outgoing.remove(messageToSend);
|
|
thiz.busy = false;//reset lock
|
|
this.onReplyStatus = false;
|
|
|
|
if (thiz.hasMessages()) {
|
|
//setup new timer
|
|
thiz._updateOnReplyTimeout();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
/**
|
|
* Send message send a string to the device. Basing on the send settings this message will be queued or send
|
|
* on reply.
|
|
* @param msg {string} the string to send
|
|
* @param now {string} force sending now!
|
|
* @param src {string} the id of the source block
|
|
* @param id {string} the id of the send job
|
|
*/
|
|
callMethod: function (method, args, src, id) {
|
|
if (this.delegate && this.delegate.callMethod) {
|
|
if (!_.isString(args)) {
|
|
args = JSON.stringify(args);
|
|
}
|
|
return this.delegate.callMethod(this, method, args, src, id);
|
|
}
|
|
},
|
|
/**
|
|
* @param msg {string} the string to send
|
|
* @param now {string} force sending now!
|
|
* @param src {string} the id of the source block
|
|
* @param id {string} the id of the send job
|
|
*/
|
|
runShell: function (code, args, src, id, block) {
|
|
if (this.delegate && this.delegate.runShell) {
|
|
if (!_.isString(args)) {
|
|
args = JSON.stringify(args);
|
|
}
|
|
return this.delegate.runShell(this, code, args, src, id, block);
|
|
} else {
|
|
console.error('-run shell failed');
|
|
}
|
|
},
|
|
/**
|
|
* Clear the onReply timeout, reset busy and proceed sending
|
|
* @private
|
|
*/
|
|
_clearOnReplyTimeout: function () {
|
|
clearTimeout(this._onReplyTimeout);
|
|
delete this._onReplyTimeout;
|
|
this.busy = false;
|
|
delete this.incoming;
|
|
this.onReplyStatus = true;
|
|
this.processOutgoing();
|
|
},
|
|
/**
|
|
* Create a timeout if we're in "onReply" mode
|
|
* @private
|
|
*/
|
|
_updateOnReplyTimeout: function () {
|
|
if (this.sendSettings.send.mode) {
|
|
var thiz = this;
|
|
if (this._onReplyTimeout) {
|
|
|
|
} else {
|
|
this._onReplyTimeout = setTimeout(function () {
|
|
thiz._clearOnReplyTimeout();
|
|
}, parseInt(this.sendSettings.send.timeout) || 100);
|
|
}
|
|
}
|
|
},
|
|
/**
|
|
* Send message send a string to the device. Basing on the send settings this message will be queued or send
|
|
* on reply.
|
|
* @param msg {string} the string to send
|
|
* @param now {string} force sending now!
|
|
* @param src {string} the id of the source block
|
|
* @param id {string} the id of the send job
|
|
* @param wait {boolean}
|
|
* @param stop {boolean}
|
|
* @param pause {boolean}
|
|
* @param args {object}
|
|
*/
|
|
sendMessage: function (msg, now, src, id, wait, stop, pause, args) {
|
|
|
|
if (!this.sendSettings) {
|
|
console.error('have no send settings');
|
|
return;
|
|
}
|
|
|
|
//check we have a queue array
|
|
if (!this.outgoing) {
|
|
this.outgoing = [];
|
|
}
|
|
|
|
/**
|
|
* if this.sendSettings.send.mode == false, its sending via 'interval', if true its on 'reply'
|
|
*/
|
|
if (now !== false) {
|
|
var _interval = parseInt(this.sendSettings.send.interval) || 0;
|
|
|
|
//we send per interval
|
|
if (!this.sendSettings.send.mode && _interval > 0) {
|
|
|
|
//add it to the queue
|
|
this.outgoing.push({
|
|
msg: msg,
|
|
src: src,
|
|
id: id,
|
|
wait: wait,
|
|
stop: stop,
|
|
pause: pause,
|
|
args: args
|
|
});
|
|
|
|
//trigger outgoing
|
|
this.processOutgoing();
|
|
|
|
} else if (!_interval) {
|
|
if (this.delegate && this.delegate.sendDeviceCommand) {
|
|
return this.delegate.sendDeviceCommand(this, msg, src, id, null, wait, stop, pause, null, args);
|
|
} else {
|
|
console.error('have no delegate');
|
|
}
|
|
}
|
|
//we send on reply
|
|
else if (this.sendSettings.send.mode) {
|
|
|
|
if (this.outgoing.length == 0 && !this._onReplyTimeout) {
|
|
this.onReplyStatus = true;
|
|
}
|
|
this._updateOnReplyTimeout();
|
|
//first message, set onReplyState to true
|
|
//add it to the queue
|
|
this.outgoing.push({
|
|
msg: msg,
|
|
src: src,
|
|
id: id,
|
|
wait: wait
|
|
});
|
|
|
|
//trigger outgoing
|
|
this.processOutgoing();
|
|
|
|
return;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//we send directly
|
|
if (this.delegate && this.delegate.sendDeviceCommand) {
|
|
return this.delegate.sendDeviceCommand(this, msg, src, id, null, wait, stop, pause, null, args);
|
|
} else {
|
|
console.error('have no delegate');
|
|
}
|
|
|
|
return false;
|
|
},
|
|
/**
|
|
* Deal with Javascript special characters, indexOf("\n") fails otherwise
|
|
* @returns {string}
|
|
*/
|
|
getLineBreakSend: function () {
|
|
if (!this.sendSettings) {
|
|
return '';
|
|
}
|
|
var lineBreak = '' + this.sendSettings.constants.end;
|
|
var lb = JSON.parse('"' + lineBreak + '"');
|
|
return lb || '\r';
|
|
},
|
|
/**
|
|
* Deal with Javascript special characters, indexOf("\n") fails otherwise
|
|
* @returns {string}
|
|
*/
|
|
getLineBreak: function () {
|
|
if (!this.responseSettings || !this.responseSettings.cTypeDelimiter) {
|
|
return '';
|
|
}
|
|
return utils.convertAllEscapes(this.responseSettings.delimiter, "none");
|
|
},
|
|
/**
|
|
* Splits a message string from the device server into an array of messages. Its using 'responseSettings'
|
|
* @param str
|
|
* @returns {string[]}
|
|
*/
|
|
split: function (str) {
|
|
if (!this.responseSettings || !this.getLineBreak()) {
|
|
return [str];
|
|
}
|
|
if (this.responseSettings.cTypeDelimiter) {
|
|
var lineBreak = this.getLineBreak();
|
|
var has = str.indexOf(lineBreak);
|
|
if (has != -1) {
|
|
var _split = str.split(lineBreak);
|
|
return _split;
|
|
}
|
|
return [];
|
|
}
|
|
return [];
|
|
},
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Utils
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
/**
|
|
* Return true if we have message
|
|
* @returns {boolean}
|
|
*/
|
|
hasMessages: function () {
|
|
return this.outgoing && this.outgoing.length > 0;
|
|
},
|
|
/**
|
|
*
|
|
* @param message
|
|
*/
|
|
updateOnReplyStatus: function (message) {
|
|
var _onReplyString = '' + this.unescape(this.sendSettings.send.onReply);
|
|
var _messageString = '' + this.unescape(message);
|
|
this.onReplyStatus = _onReplyString === _messageString || _onReplyString === "" || _messageString.indexOf(_onReplyString) !== -1;
|
|
_debug && console.log(' matches: ' + this.onReplyStatus + ' | ' + utils.stringToHex(_onReplyString) + ' - ' + utils.stringToHex(_messageString));
|
|
return this.onReplyStatus;
|
|
},
|
|
byteDelimiter: function (delimiter, cb) {
|
|
if (!_.isArray(delimiter)) {
|
|
delimiter = [delimiter];
|
|
}
|
|
var buf = [];
|
|
var nextDelimIndex = 0;
|
|
return function (buffer) {
|
|
for (var i = 0; i < buffer.length; i++) {
|
|
buf[buf.length] = buffer[i];
|
|
if (isEqual(delimiter, buf.slice(-delimiter.length))) {
|
|
cb(buf, i);
|
|
buf = [];
|
|
nextDelimIndex = 0;
|
|
|
|
}
|
|
}
|
|
};
|
|
},
|
|
/**
|
|
* Standard callback when we have a RAW message, not split by the delimiter.
|
|
* @param data
|
|
*/
|
|
onMessageRaw: function (data) {
|
|
|
|
var bytes = data.bytes;
|
|
var bytesArray = utils.bufferFromDecString(bytes);
|
|
if (!this.bytesIncomeBuf) {
|
|
this.bytesIncomeBuf = [];
|
|
}
|
|
|
|
bytesArray = this.bytesIncomeBuf.concat(bytesArray);
|
|
var messages = [];
|
|
var lastDelimiterPos = 0;
|
|
var responseSettings = this.responseSettings;
|
|
var sendSettings = this.sendSettings;
|
|
var delimiterBytes;
|
|
|
|
function onPart(_part, lastPos) {
|
|
var part = _part.slice();
|
|
part = part.slice(0, -delimiterBytes.length);
|
|
var str = toString(part);
|
|
messages.push({
|
|
string: str,
|
|
bytes: part
|
|
});
|
|
lastDelimiterPos = lastPos;
|
|
|
|
}
|
|
|
|
|
|
//collect data if we're in delimiter mode
|
|
if (responseSettings && responseSettings.cTypeDelimiter && responseSettings.delimiter && responseSettings.delimiter.length > 0) {
|
|
var delimiter = utils.convertAllEscapes(responseSettings.delimiter, "none");
|
|
delimiterBytes = utils.stringToBuffer(delimiter);
|
|
var delimiterFn = this.byteDelimiter(delimiterBytes, onPart);
|
|
delimiterFn(bytesArray);
|
|
}
|
|
|
|
|
|
if (sendSettings && sendSettings.send.mode) {
|
|
if (this.updateOnReplyStatus(data.message) && this.hasMessages()) {
|
|
this.processOutgoing();
|
|
}
|
|
}
|
|
|
|
//remove found parts
|
|
if (lastDelimiterPos > 0) {
|
|
for (var i = 0; i < lastDelimiterPos + 1; i++) {
|
|
bytesArray.shift();
|
|
}
|
|
this.bytesIncomeBuf = bytesArray;
|
|
}
|
|
|
|
if (this.bytesIncomeBuf.length > MAX_BUFFER_COUNT) {
|
|
this.bytesIncomeBuf = [];
|
|
}
|
|
|
|
if (messages.length) {
|
|
return messages;
|
|
} else {
|
|
return [];
|
|
}
|
|
},
|
|
/**
|
|
* Standard callback when we have a message from the device we're bound to (specified in profile).
|
|
* 1. put the message in the incoming queue, tag it as 'unread'
|
|
* 2. in case we have messages to send and we are in 'onReply' mode, trigger outgoing queue
|
|
*
|
|
* @param data {Object} : Message Struct build by the device manager
|
|
* @param data.device {Object} : Device info
|
|
* @param data.device.host {String} : The host
|
|
* @param data.device.port {String} : The host's port
|
|
* @param data.device.protocol {String} : The host's protocol
|
|
|
|
* @param data.message {String} : RAW message, untreated
|
|
*
|
|
* @example
|
|
|
|
// for instance you might update the "Volume" Variable within onMessage:
|
|
onMessage:function(data){
|
|
|
|
var value = data.message;
|
|
var volume = 0;
|
|
if (value.indexOf('MV') != -1 && value.indexOf('MVMAX') == -1) {
|
|
var _volume = value.substring(2, value.length);
|
|
_volume = parseInt(_volume.substring(0, 2));
|
|
if (!isNaN(_volume)) {
|
|
this.setVariable('Volume', _volume);
|
|
volume = _volume;
|
|
}
|
|
}
|
|
|
|
// do something else with volume:
|
|
this.log('info',null,'Did update volume to ' + volume);
|
|
|
|
//important, call BaseDriver::onMessage!
|
|
this.inherited(arguments);
|
|
|
|
}
|
|
*/
|
|
onMessage: function (data) {
|
|
_debug && console.log('incoming message : ' + data.message);
|
|
},
|
|
/***
|
|
* Standard callback when we have a feedback message from any device. The message data contains
|
|
* all needed info like which device, the response, etc...
|
|
* @param msg
|
|
*/
|
|
onBroadcastMessage: function (msg) {
|
|
},
|
|
/**
|
|
* Main entry when this instance is started
|
|
* @returns {boolean}
|
|
*/
|
|
start: function () {
|
|
this.outgoing = [];
|
|
this.incoming = [];
|
|
return true;
|
|
},
|
|
/**
|
|
* Set a variable's value
|
|
* @param title {string} the name of the variable
|
|
* @param value {string} the new value
|
|
* @param save {boolean} the new value will be saved
|
|
* @param publish {boolean} the new value will published in the internal MQTT storage
|
|
* @param highlight {boolean} enable/disable highlighting in the interface.
|
|
*/
|
|
setVariable: function (title, value, save, publish, highlight) {
|
|
//console.log('setVariable : '+publish);
|
|
var _variable = this.blockScope.getVariable(title);
|
|
if (_variable) {
|
|
_variable.value = value;
|
|
if (highlight === false) {
|
|
_variable.__ignoreChangeMark = true;
|
|
}
|
|
_variable.set('value', value);
|
|
if (highlight === false) {
|
|
_variable.__ignoreChangeMark = false;
|
|
}
|
|
} else {
|
|
|
|
_debug && console.log('no such variable : ' + title);
|
|
return;
|
|
}
|
|
|
|
if (publish === 'undefined' || publish == null) {
|
|
//console.log('publish true');
|
|
publish = true;
|
|
}
|
|
//console.log('setVariable : '+publish);
|
|
this.publish(types.EVENTS.ON_DRIVER_VARIABLE_CHANGED, {
|
|
item: _variable,
|
|
scope: this.blockScope,
|
|
owner: this,
|
|
save: save === true,
|
|
publish: publish
|
|
});
|
|
},
|
|
/**
|
|
* Return a variable's value
|
|
* @param title {string} the name of the variable
|
|
* @returns {string} the value of the variable
|
|
*/
|
|
getVariable: function (title) {
|
|
var _variable = this.blockScope.getVariable(title);
|
|
if (_variable) {
|
|
return _variable.value;
|
|
}
|
|
return '';
|
|
},
|
|
callCommand: function (title, settings) {
|
|
var _block = this.blockScope.getBlockByName(title);
|
|
if (_block) {
|
|
return _block.solve(this.blockScope, settings);
|
|
} else {
|
|
console.warn('cant call command by name: ' + title + ' not found');
|
|
}
|
|
|
|
},
|
|
getCommand: function (title) {
|
|
return this.blockScope.getBlockByName(title);
|
|
},
|
|
onLostServer: function () {
|
|
},
|
|
destroy: function () {
|
|
this._destroyed = true;
|
|
clearInterval(this.queueTimer);
|
|
delete this.queueTimer;
|
|
if (this.blockScope) {
|
|
this.blockScope.destroy();
|
|
}
|
|
delete this.blockScope;
|
|
}
|
|
});
|
|
|
|
dcl.chainAfter(Module, 'onMessage');
|
|
dcl.chainAfter(Module, 'destroy');
|
|
dcl.chainAfter(Module, 'start');
|
|
dcl.chainAfter(Module, 'onLostServer');
|
|
dcl.chainAfter(Module, 'onMessageRaw');
|
|
return Module;
|
|
});
|