init : function (controller) { var deviceState = require(__dirname + '/../../lib/deviceState'), subdevices = {}, className = '', i; if (process.platform === 'linux') { for (i in controller.config.subdevices) { if (controller.config.subdevices.hasOwnProperty(i)) { className = ''; if ((controller.config.className) && (controller.config.className[i])) { className = controller.config.className[i]; } subdevices.push({ id : controller.config.subdevices[i], label : i, type : 'switch', className : className }); } } deviceState.updateState(controller.config.deviceId, controller.config.typeClass, { state : 'ok', value : { devices : subdevices } }); } else { deviceState.updateState(controller.config.deviceId, controller.config.typeClass, { state : 'err', value : {} }); } },
updateState : function (test) { 'use strict'; var smartthingsController = require(__dirname + '/../../../../devices/smartthings/controller'), deviceState = require(__dirname + '/../../../../lib/deviceState'), now = new Date(), smartthings = { deviceId : 'FOO', config : { celsius : false } }, response = { mode : 'Home', devices : [ { id : '01234567890', label : 'Test Switch', values : { switch : { value : 'on' } } }, { id : '09876543210', label : 'Test Door', values : { contact : { value : 'closed' }, battery : { value: '55' }, temperature : { value : '72' } } } ] }, newState; deviceState.updateState('FOO', 'smartthings', { state : 'ok' }); smartthingsController.updateState(smartthings, response); newState = deviceState.getDeviceState('FOO'); test.strictEqual(newState.value.devices[0].type, 'switch', 'The first device is a switch'); test.strictEqual(newState.value.devices[0].peripheral, undefined, 'The first device has no peripheral'); test.strictEqual(newState.value.devices[1].type, 'contact', 'The first device is a contact sensor'); test.strictEqual(newState.value.devices[1].peripheral.temp, 72, 'The second device has a peripheral function'); test.strictEqual(newState.value.devices[1].peripheral.battery, 55, 'The second device has a battery'); test.strictEqual(newState.updated > (Math.round(now.getTime() / 1000) - 1), true, 'State object should be newer than the initial time'); test.done(); },
callback = function (err, state) { var stStateClone = JSON.parse(JSON.stringify(stState)); stStateClone.value = state; deviceState.updateState('FOO', 'smartthings', stStateClone); },
callback = function (deviceId, err, reply, params, appParams) { var deviceState = require(__dirname + '/../lib/deviceState'), message = 'err', errorMsg = err; params = params || {}; if (err) { if ((err.code === 'ECONNRESET') || (err.code === 'ECONNREFUSED') || (err.code === 'EHOSTUNREACH') || (err.code === 'ETIMEDOUT')) { errorMsg = 'Device is off or unreachable'; } else if (err.code){ errorMsg = err.code; } console.log('\x1b[31m' + controller.config.title + '\x1b[0m: ' + errorMsg); } else { console.log('\x1b[32m' + controller.config.title + '\x1b[0m: State executed'); message = 'ok'; } params.state = message; deviceState.updateState(deviceId, controller.config.typeClass, params); apps.execute(device, command, { state : message, value : reply }, controllers, appParams); };
config.callback = function (err, reply, ignoreState, appParams) { var deviceState = require(__dirname + '/deviceState'), errorMsg = err, state = err ? 'err' : 'ok'; callback(err, reply); if (err) { if ((err.code === 'ECONNRESET') || (err.code === 'ECONNREFUSED') || (err.code === 'EHOSTUNREACH') || (err.code === 'ETIMEDOUT')) { errorMsg = 'Device is off or unreachable'; } else if (err.code === 'ENOENT') { errorMsg = 'System command could not be found'; } else if (err.code){ errorMsg = err.code; } if (err !== 'ignore') { console.log('\x1b[31m' + controller.config.title + '\x1b[0m: ' + errorMsg); } if (!ignoreState) { deviceState.updateState(device, controller.config.typeClass, { state : state }); } if (endResponse) { response.end('{"device":"' + device + '","command":"' + command + '","status":"ok"}'); } } if (reply) { console.log('\x1b[32m' + controller.config.title + '\x1b[0m: Command executed'); if (!ignoreState) { deviceState.updateState(device, controller.config.typeClass, { state : state, value : reply }); } if (endResponse) { response.end('{"device":"' + device + '","command":"' + command + '","status":"ok"}'); } } apps.execute(device, command, { state : state, value : reply }, controllers, appParams); };
var callback = function (err, reply) { var deviceState = require(__dirname + '/../../lib/deviceState'), message = 'err'; if (reply) { message = 'ok'; } deviceState.updateState(controller.config.deviceId, controller.config.typeClass, { state : message }); };
getDeviceState : function (test) { 'use strict'; var deviceState = require(__dirname + '/../../../lib/deviceState'), testFauxDevice, allStates; deviceState.updateState('faux-device', 'faux-type', { state : 'ok', value : 100 }); deviceState.updateState('faux-device2', 'faux-type', { state : 'ok', value : 150 }); testFauxDevice = deviceState.getDeviceState('faux-device'); allStates = deviceState.getDeviceState(); test.notStrictEqual(parseInt(testFauxDevice.updated, 10), NaN, 'Timestamp should return a number.'); test.strictEqual(testFauxDevice.value, 100, 'Returned value should match set value.'); test.strictEqual(allStates['faux-device'].value, 100, 'Should return all device states'); test.strictEqual(allStates['faux-device2'].value, 150, 'Should return all device states'); test.done(); },
stocksOpen : function (config, explicit) { var deviceState = require(__dirname + '/../lib/deviceState'), stocksState = deviceState.getDeviceState(config.device.deviceId), date = new Date(), utcTime = date.getTime() + (date.getTimezoneOffset() * 60000), // Try to determine if we're in DST by comparing one month that is // in DST against the current timezone offset. january = new Date(date.getFullYear(), 0, 1), july = new Date(date.getFullYear(), 6, 1), dst = date.getTimezoneOffset() < Math.max(january.getTimezoneOffset(), july.getTimezoneOffset()), nycOffset = dst ? -4 : -5, nycTime = new Date(utcTime + (3600000 * nycOffset)), open = false; if(explicit) { nycTime = explicit; } // Trading isn't open on weekends, so we don't need to poll. if((nycTime.getDay() !== 6) && (nycTime.getDay() !== 0)) { // Trading is only open from 9am - 4pm. if((nycTime.getHours() >= 9) && (nycTime.getHours() < 16)) { open = true; deviceState.updateState(config.device.deviceId, 'stocks', { state : 'ok', value : stocksState.value }); } else { deviceState.updateState(config.device.deviceId, 'stocks', { state : 'err', value : stocksState.value }); console.log('\x1b[35m' + config.device.title + '\x1b[0m: Stock trading is closed - after hours'); } } else { deviceState.updateState(config.device.deviceId, 'stocks', { state : 'err', value : stocksState.value }); console.log('\x1b[35m' + config.device.title + '\x1b[0m: Stock trading is closed - weekend'); } return open; },
response.once('end', function() { var deviceState = require(__dirname + '/../lib/deviceState'), weatherData = {}, city; if(dataReply) { dataReply = JSON.parse(dataReply); if((dataReply.query) && (dataReply.query.results)) { city = dataReply.query.results.channel; if(city.title.indexOf('Error') !== -1) { deviceState.updateState(weather.deviceId, 'weather', { state : 'err', value : city.title }); } else { weatherData = { 'city' : city.location.city, 'temp' : city.item.condition.temp, 'text' : city.item.condition.text, 'humidity' : city.atmosphere.humidity, 'sunrise' : city.astronomy.sunrise, 'sunset' : city.astronomy.sunset, 'code' : city.item.condition.code, 'forecast' : city.item.forecast }; deviceState.updateState(weather.deviceId, 'weather', { state : 'ok', value : weatherData }); } weather.callback(null, weatherData); } else { weather.callback('No data returned from API'); } } else { weather.callback('No data returned from API'); } });
init : function (controller, config) { var deviceState = require(__dirname + '/../lib/deviceState'), subdevices = {}, i, j = 0; if(process.platform === 'linux') { for(i in controller.config.subdevices) { subdevices[j] = { id : controller.config.subdevices[i], label : i, type : 'switch' }; j += 1; } deviceState.updateState(controller.config.deviceId, controller.config.typeClass, { state : 'ok', value : { devices : subdevices } }); } else { deviceState.updateState(controller.config.deviceId, controller.config.typeClass, { state : 'err', value : {} }); } },
newState : function (test) { 'use strict'; var deviceState = require(__dirname + '/../../../lib/deviceState'), fauxDeviceState; deviceState.updateState('faux-device', 'faux-type', {}); fauxDeviceState = deviceState.getDeviceState('faux-device'); test.notStrictEqual(parseInt(fauxDeviceState.value.updated, 10), NaN, 'Timestamp should return a number.'); test.done(); },
updateState : function (test) { 'use strict'; var deviceState = require(__dirname + '/../../../lib/deviceState'), newDeviceState, existingState; deviceState.updateState('faux-device', 'faux-type', {}); deviceState.updateState('existing-device', 'faux-type', { value : 50 }); deviceState.updateState('faux-device', 'faux-type', { state : 'ok', value : 100 }); newDeviceState = deviceState.getDeviceState('faux-device'); deviceState.updateState('existing-device', 'existing-type', {}); existingState = deviceState.getDeviceState('existing-device'); test.strictEqual(newDeviceState.state, 'ok', 'Device state should have been set to ok'); test.strictEqual(newDeviceState.value, 100, 'Device value should have been set to 100'); test.notStrictEqual(parseInt(newDeviceState.updated, 10), NaN, 'Timestamp should return a number.'); test.strictEqual(existingState.state, 'err', 'Device state should have been set to err since no ok had been sent'); test.strictEqual(existingState.value, 50, 'Device value should have been kept at 50 since no updated had been made'); test.notStrictEqual(parseInt(existingState.updated, 10), NaN, 'Timestamp should return a number.'); test.done(); }
updateState : function (test) { 'use strict'; State.FOO = {}; State.FOO.state = 'ok'; var smartthingsController = require(__dirname + '/../../../controllers/smartthings'), now = new Date(), smartthings = { deviceId : 'FOO' }, response = { mode : 'Home', devices : [ { id : '01234567890', label : 'Test Switch', values : { switch : { value : 'on' } } }, { id : '09876543210', label : 'Test Door', values : { contact : { value : 'closed' }, temperature : { value : 72 } } } ] }; smartthingsController.updateState(smartthings, response); test.strictEqual(State.FOO.value.devices[0].type, 'switch', 'The first device is a switch'); test.strictEqual(State.FOO.value.devices[1].type, 'contact', 'The first device is a contact sensor'); test.strictEqual(State.FOO.value.devices[1].peripheral.temp, 72, 'The second device has a peripheral function'); test.strictEqual(State.FOO.updated > (now.getTime() - 1), true, 'State object should be newer than the initial time'); test.done(); },
callback = function(err, stocks) { var message = '', i = 0, stockName; deviceState.updateState(deviceId, 'stocks', { state : 'ok', value : stocks }); if((controller.config.limits) && (stocks)) { for(stockName in controller.config.limits) { if((typeof controller.config.limits[stockName].sell !== 'undefined') && (stocks[stockName]) && (stocks[stockName].price >= controller.config.limits[stockName].sell)) { message = message + 'Your ' + stocks[stockName].name + ' stock is doing well at ' + stocks[stockName].ask + '. Think about selling? '; } else if((typeof controller.config.limits[stockName].buy !== 'undefined') && (stocks[stockName]) && (stocks[stockName].price <= controller.config.limits[stockName].buy)) { message = message + 'Your ' + stocks[stockName].name + ' stock is low at ' + stocks[stockName].ask + '. Think about buying? '; } else if(stocks[stockName]){ console.log('\x1b[35mSchedule\x1b[0m: ' + stocks[stockName].name + ' is at ' + stocks[stockName].price + ' - within range'); } else { console.log('\x1b[31mSchedule\x1b[0m: Failed to fetch valid stock data'); } } } if(message) { console.log('\x1b[35mSchedule\x1b[0m: ' + message); for(i; i < controller.config.notify.length; i += 1) { if(typeof controllers[controller.config.notify[i]] !== 'undefined') { if(controllers[controller.config.notify[i]].config.typeClass === 'mp3') { runCommand.runCommand(controller.config.notify[i], 'text-cash', controllers, 'single', false); } else { runCommand.runCommand(controller.config.notify[i], 'text-' + message, controllers, 'single', false); } } } } };
getDevicePath : function (test) { 'use strict'; var stState = { state : 'ok', value : { devices : { 0 : { id : '01234567890', label : 'Test Switch', type : 'switch', state : 'off' }, 1 : { id : '09876543210', label : 'Test Door', type : 'contact', state : 'off', peripheral : { temp: 72 } } } } }; var smartthingsController = require(__dirname + '/../../../../devices/smartthings/controller'), deviceState = require(__dirname + '/../../../../lib/deviceState'), callback = function (err, state) { var stStateClone = JSON.parse(JSON.stringify(stState)); stStateClone.value = state; deviceState.updateState('FOO', 'smartthings', stStateClone); }, smartthings = { device : { deviceId : 'FOO' } }, finalState; deviceState.updateState('FOO', 'smartthings', stState); smartthingsController.getDevicePath('state-switch-Test Switch-on', smartthings, callback); smartthingsController.getDevicePath('state-contact-Test Door-on', smartthings, callback); finalState = deviceState.getDeviceState('FOO'); test.strictEqual(finalState.value.devices[0].state, 'on', 'The first device should now be on'); test.strictEqual(finalState.value.devices[1].state, 'on', 'The second device should now be open'); test.done(); }
response.once('end', function() { var deviceState = require(__dirname + '/../lib/deviceState'), stockData = {}, stock, data, state, i = 0; if(dataReply) { data = JSON.parse(dataReply); if(data && data.query && data.query.results && data.query.results.quote) { for(i in data.query.results.quote) { stock = data.query.results.quote[i]; stockData[stock.symbol] = { 'name' : stock.symbol, 'price' : stock.LastTradePriceOnly, 'ask' : stock.AskRealtime, 'bid' : stock.BidRealtime, 'dayHigh' : stock.DaysHigh, 'dayLow' : stock.DaysLow, 'yearHigh' : stock.YearHigh, 'yearLow' : stock.YearLow, 'dayChangePercent' : stock.ChangeinPercent, 'dayChangeValue' : stock.Change }; } } state = that.stocksOpen(config) ? 'ok' : 'err'; deviceState.updateState(stocks.deviceId, 'stocks', { state: state, value : stockData }); } stocks.callback(state === 'err' ? 'ignore' : null, stockData); });
updateState : function (smartthings, response, controller) { var subdevices = [], smartthingsData = {}, deviceState = require(__dirname + '/../../lib/deviceState'), util = require(__dirname + '/../../lib/sharedUtil').util, smartthingsState = deviceState.getDeviceState(smartthings.deviceId), state = 'err', mode = '', i = 0, currDevice = {}, device, matched, findByName = function (find, i) { var found = {}, device = find[i], devices = ((smartthingsState) && (smartthingsState.value)) ? smartthingsState.value.devices : null, j = 0; if ((devices) && (devices[i])) { // It's likely that the array structure is the same. // In that case, we can just quickly validate it's the // same and pass that along. if (device.id === devices[i].id) { found = devices[i]; } // Otherwise, let's search for it. else { for (j; j < devices.length; j += 1) { if (device.id === devices[j].id) { found = devices[j]; break; } } } } return found; }; if ((response) && (response.mode) && (response.devices)) { mode = util.sanitize(response.mode); state = 'ok'; for (i; i < response.devices.length; i += 1) { device = response.devices[i]; if ((device.values) && (device.id) && (device.label)) { matched = findByName(response.devices, i); currDevice = { id : util.sanitize(device.id), label : util.sanitize(device.label), lastOn : util.sanitize(matched.lastOn), lastOff : util.sanitize(matched.lastOff), duration : util.sanitize(matched.duration) }; if ((smartthings.className) && (smartthings.className[device.label])) { currDevice.className = smartthings.className[device.label]; } // SmartThings supports multi-role devices - meaning a single device // may report temp as well as be a contact sensor. For now, we're // only concerned with the primary role - and take priority over // those functions that seem most valuable. if (device.values.switch) { // You're a switch currDevice.type = 'switch'; currDevice.state = util.sanitize(device.values.switch.value); } else if (device.values.lock) { // You're a lock currDevice.type = 'lock'; currDevice.state = util.sanitize(device.values.lock.value); } else if (device.values.contact) { // You're a contact sensor currDevice.type = 'contact'; currDevice.state = device.values.contact.value === 'open' ? 'on' : 'off'; currDevice.readOnly = true; } else if (device.values.water) { // You're a moisture sensor currDevice.type = 'water'; currDevice.state = device.values.water.value === 'wet' ? 'on' : 'off'; currDevice.readOnly = true; } else if (device.values.motion) { // You're a motion sensor currDevice.type = 'motion'; currDevice.state = device.values.motion.value === 'active' ? 'on' : 'off'; currDevice.readOnly = true; } else if (device.values.presence) { // You're a presence sensor currDevice.type = 'presence'; currDevice.state = device.values.presence.value === 'present' ? 'on' : 'off'; currDevice.readOnly = true; } // These are commonly secondary sensors for a given device. if ((device.values.temperature) || (device.values.vibrate) || (device.values.battery)) { // If you have a proper state, temp is peripheral sensor. if (currDevice.state) { currDevice.peripheral = currDevice.peripheral || {}; if (device.values.temperature) { currDevice.peripheral.temp = parseInt(util.sanitize(device.values.temperature.value), 10); if (smartthings.config.celsius) { currDevice.peripheral.temp = util.fToC(currDevice.peripheral.temp); } } if (device.values.vibrate) { currDevice.peripheral.vibrate = util.sanitize(device.values.vibrate.value); } if (device.values.battery) { currDevice.peripheral.battery = parseInt(util.sanitize(device.values.battery.value), 10); } } else { // If you have no proper state, you're just a temperature // sensor. if (device.values.temperature) { currDevice.state = parseInt(util.sanitize(device.values.temperature.value), 10); if (smartthings.config.celsius) { currDevice.state = util.fToC(currDevice.state); } } // ...or a vibrate sensor. if (device.values.vibrate) { currDevice.state = util.sanitize(device.values.vibrate.value); } // ...or something with a battery. if (device.values.battery) { currDevice.peripheral = currDevice.peripheral || {}; currDevice.peripheral.battery = parseInt(util.sanitize(device.values.battery.value), 10); } } } subdevices.push(currDevice); } } smartthingsData = { state : state, value : { devices : subdevices, mode : mode, groups : response.groups } }; deviceState.updateState(smartthings.deviceId, 'smartthings', smartthingsData); } else if (response.error) { console.log('\x1b[31m' + controller.title + '\x1b[0m: ' + util.sanitize(response.message)); } return smartthingsData; },
init : function (controller) { var deviceState = require(__dirname + '/../../lib/deviceState'); deviceState.updateState(controller.config.deviceId, 'clientNotify', { state : 'ok' }); },
init : function (controller) { var deviceState = require(__dirname + '/../../lib/deviceState'); deviceState.updateState(controller.config.deviceId, controller.config.typeClass, { state : 'ok' }); },
updateState : function (smartthings, response) { var subDevices = [], smartthingsData = {}, deviceState = require(__dirname + '/../../lib/deviceState'), state = 'err', mode = '', i = 0, currDevice = {}, device; if((response) && (response.mode) && (response.devices)) { mode = response.mode; state = 'ok'; for(i; i < response.devices.length; i += 1) { device = response.devices[i]; if((device.values) && (device.id) && (device.label)) { currDevice = { id : device.id, label : device.label }; if((smartthings.className) && (smartthings.className[device.label])) { currDevice.className = smartthings.className[device.label]; } // SmartThings supports multi-role devices - meaning a single device // may report temp as well as be a contact sensor. For now, we're // only concerned with the primary role - and take priority over // those functions that seem most valuable. if(device.values.switch) { // You're a switch currDevice.type = 'switch'; currDevice.state = device.values.switch.value; } else if(device.values.lock) { // You're a lock currDevice.type = 'lock'; currDevice.state = device.values.lock.value; } else if(device.values.contact) { // You're a contact sensor currDevice.type = 'contact'; currDevice.state = device.values.contact.value === 'open' ? 'on' : 'off'; } else if(device.values.water) { // You're a moisture sensor currDevice.type = 'water'; currDevice.state = device.values.water.value === 'wet' ? 'on' : 'off'; } else if(device.values.motion) { // You're a motion sensor currDevice.type = 'motion'; currDevice.state = device.values.motion.value === 'active' ? 'on' : 'off'; } else if(device.values.presence) { // You're a presence sensor currDevice.type = 'presence'; currDevice.state = device.values.presence.value === 'present' ? 'on' : 'off'; } // These are commonly secondary sensors for a given device. if((device.values.temperature) || (device.values.vibrate) || (device.values.battery)) { // If you have a proper state, temp is peripheral sensor. if(currDevice.state) { currDevice.peripheral = currDevice.peripheral || {}; if(device.values.temperature) { currDevice.peripheral.temp = parseInt(device.values.temperature.value, 10); } if(device.values.vibrate) { currDevice.peripheral.vibrate = device.values.vibrate.value; } if(device.values.battery) { currDevice.peripheral.battery = parseInt(device.values.battery.value, 10); } } else { // If you have no proper state, you're just a temperature // sensor. if(device.values.temperature) { currDevice.state = parseInt(device.values.temperature.value, 10); } // ...or a vibrate sensor. if(device.values.vibrate) { currDevice.state = device.values.vibrate.value; } // ...or something with a battery. if(device.values.battery) { currDevice.peripheral.battery = parseInt(device.values.battery.value, 10); } } } subDevices.push(currDevice); } } smartthingsData = { state : state, value : { devices : subDevices, mode : mode, groups : response.groups } }; deviceState.updateState(smartthings.deviceId, 'smartthings', smartthingsData); } return smartthingsData; },
updateState : function (smartthings, response) { var subDevices = {}, deviceState = require(__dirname + '/../lib/deviceState'), state = 'err', mode = '', i = 0, device; if((response) && (response.mode) && (response.devices)) { mode = response.mode; state = 'ok'; for(i; i < response.devices.length; i += 1) { device = response.devices[i]; if(device.values) { subDevices[i] = { id : device.id, label : device.label }; // SmartThings supports multi-role devices - meaning a single device // may report temp as well as be a contact sensor. For now, we're // only concerned with the primary role - and take priority over // those functions that seem most valuable. if(device.values.switch) { // You're a switch subDevices[i].type = 'switch'; subDevices[i].state = device.values.switch.value; } else if(device.values.lock) { // You're a lock subDevices[i].type = 'lock'; subDevices[i].state = device.values.lock.value; } else if(device.values.contact) { // You're a contact sensor subDevices[i].type = 'contact'; subDevices[i].state = device.values.contact.value === 'open' ? 'on' : 'off'; } else if(device.values.water) { // You're a moisture sensor subDevices[i].type = 'water'; subDevices[i].state = device.values.water.value === 'wet' ? 'on' : 'off'; } else if(device.values.motion) { // You're a motion sensor subDevices[i].type = 'motion'; subDevices[i].state = device.values.motion.value === 'active' ? 'on' : 'off'; } else if(device.values.presence) { // You're a presence sensor subDevices[i].type = 'presence'; subDevices[i].state = device.values.presence.value === 'present' ? 'on' : 'off'; } // These are commonly secondary sensors for a given device. if((device.values.temperature) || (device.values.vibrate)) { // If you have a proper state, temp is peripheral sensor. if(subDevices[i].state) { subDevices[i].peripheral = subDevices[i].peripheral || {}; if(device.values.temperature) { subDevices[i].peripheral.temp = device.values.temperature.value; } if(device.values.vibrate) { subDevices[i].peripheral.temp = device.values.temperature.value; } } // If you have no proper state, you're just a temperature sensor. else { if(device.values.temperature) { subDevices[i].state = device.values.temperature.value; } if(device.values.vibrate) { subDevices[i].state = device.values.vibrate.value; } } } } } deviceState.updateState(smartthings.deviceId, 'smartthings', { state : state, value : { devices : subDevices, mode : mode, groups : response.groups } }); } },
loadController : function (devices) { var schedule = require(__dirname + '/schedule'), runCommand = require(__dirname + '/runCommand'), deviceState = require(__dirname + '/deviceState'), currentState, deviceId, lastGood = '', controllers = { 'config' : devices.config }, initialState = {}; for(deviceId in devices) { if((typeof devices[deviceId] === 'object') && (devices[deviceId].disabled !== true) && (deviceId !== 'config')) { devices[deviceId].deviceId = deviceId; controllers[deviceId] = this.loadControllerFile(devices[deviceId], deviceId, controllers.config); if(controllers[deviceId].hasOwnProperty('markup')) { lastGood = deviceId; } } } if(!controllers.hasOwnProperty(controllers.config.default)) { console.log('\x1b[31m=====================================================================\x1b[0m'); if(controllers.hasOwnProperty(lastGood)) { console.log('\x1b[31mWARNING\x1b[0m: You\'ve specified an invalid controller as your default view!'); console.log('\x1b[31mWARNING\x1b[0m: Using ' + lastGood + ' as default device!'); controllers.config.default = lastGood; } else { console.log('\x1b[31mWARNING\x1b[0m: You have no valid controllers configured!'); console.log('\x1b[31mWARNING\x1b[0m: Server refusing to start till you fix your config!'); controllers = null; } console.log('\x1b[31m=====================================================================\x1b[0m'); } if(controllers) { // We run this now so that any issued commands have the basic controller // to use. runCommand.init(controllers); for(deviceId in controllers) { if(deviceId !== 'config') { controllers[deviceId] = this.initController(controllers[deviceId], controllers.config); currentState = deviceState.getDeviceState(deviceId); initialState = {}; if(currentState) { if(currentState.state) { initialState.state = currentState.state; } if(currentState.value) { initialState.value = currentState.value; } } deviceState.updateState(deviceId, controllers[deviceId].config.typeClass, initialState); } } schedule.scheduleInit(controllers); } // We run this again to update the controllers with any changes that may // have occurred during the controller init. runCommand.init(controllers); return controllers; },