UNPKG

adaptorex

Version:

Connect all your live interactive storytelling devices and software

221 lines (207 loc) 8.04 kB
const action_schema = { "setLights":{ "title":"Set Lights", "description":"Change the DMX values of your DMX-USB-PRO box.", "documentation":"https://docs.adaptorex.org/basics/actions/usb-dmx-pro/setLights.html", "anyOf":[ { "title":"Values", "type":"array", "format":"table", "default":[{"channel":1, "value":"0"}], "items":{ "type":"object", "additionalProperties":false, "properties":{ "channel":{ "type":"integer", "default":1, "minimum":1, "maximum":512 }, "value":{ "type":"string", "default":0 } }, "required":["channel","value"] } }, { "title":"Slider", "type":"array", "format":"table", "items":{ "type":"object", "additionalProperties":false, "properties":{ "channel":{ "type":"integer", "default":1, "minimum":1, "maximum":512 }, "value":{ "type":"integer", "format":"range", "default":0, "minimum":0, "maximum":255 } }, "required":["channel","value"] } } ] } } const settings_schema = { "type":"object", "title":"DMX USB Pro Class Settings", "required":["serialPort"], "default":{"serialPort":"","autoConnectOnStart":true}, "additionalProperties":false, "properties":{ "serialPort":{ "type":"string", "enum":["eins","zwei"] }, "autoConnectOnStart":{ // would be nicer to just do this via HTML? "type": "boolean" }, } } const DMX = require("./dmx"); try{ var { SerialPort } = require('serialport'); }catch(e){ log.error("dmx-usb", "cannot require serialport. Probably no serialport available on the server running adaptor") throw(e) // TODO: throw adaptor error so frontend gets 4xx instead of 500 response } const plugin = require('../plugin.js') class myPlugin extends plugin.Plugin { constructor() { super() this.action_schema = adaptor.deepClone(action_schema); this.schema.actions = this.action_schema this.settings_schema = adaptor.deepClone(settings_schema); this.settings = null; this.myDMX = new DMX(); // TODO: catch Serial and DMX errors --> how? } ////////////// LIFECYCLE HOOKS PLUGIN //////////////////////// ///////////////////////////////////////////////////////////// async setup(config, game) { // LIFECYCLE HOOK super.setup(config, game) this.addTemplate("setLights", (payload, action) => { const title = `dmx-usb-pro ${action.name}` let subtitle const body = [{text:""}] for(let i = 0; i < payload.length; i++) { body[0]["text"] += `${payload[i].channel}: ${payload[i].value}` if(i < payload.length -1) { body[0]["text"] += ", " } } return {title, subtitle, body} }) log.info("dmx-usb setup","STARTING ####", config.settings); this.connected = false; await this.getSerialPorts(); this.settings = config.settings; if (config.settings.autoConnectOnStart){ this.connectDMX(config); } log.info("dmx-usb settings schema",this.settings_schema.plugins); return {actions:this.action_schema, settings:this.settings_schema} } async update(updateData){ // LIFECYCLE HOOK log.info("dmx-usb update",updateData); if(this.settings.serialPort != updateData.serialPort) { this.settings = updateData; this.connect() } else { this.settings = updateData; // update Schema data } } async load(plugindata){ // LIFECYCLE HOOK on POST operator {game}/{plugin}/_load // middleware function // LASSE BUILDS THIS await this.getSerialPorts(); plugindata.schema.settings = this.settings_schema; plugindata.connected = this.connected; return plugindata } disconnect(){ // LIFECYCLE HOOK // TODO:TEST log.info("dmx-usb disconnect", this.connected) this.closeSerial(); this.connected = false; log.info("dmx-usb disconnect done", this.connected) return{connected:this.connected} } connect(){ // LIFECYCLE HOOK log.info("dmx-usb connect", this.connected) this.closeSerial(); // TODO: put in connectDMX function below // TODO: use .open() async function and await it to get return values this.myDMX.addUniverse("one","enttec-usb-dmx-pro",this.settings.serialPort); this.myDMX.universes.one.dev.on("error",(e)=>{ log.error("dmx-usb","serialPort lost connection",e); this.connected = false; }) this.myDMX.universes.one.dev.on("open",()=>{ this.myDMX.update("one", {1:0,2:0,3:0,4:0}); // initializes black on channels 1-4*/ this.connected = true; log.info("dmx-usb connect done", this.connected) }) // THIS IS A LIE. we don't know yet if its connected (need to maybe use .open() function and autoOpen:false) return{connected:this.connected} } command() { // LIFECYCLE HOOK log.info("dmx-usb-class","command not implemented") } setLights(params) { // defined above in action_schema let output = {}; for (let setLights of params) { output[parseInt(setLights.channel)] = setLights.value; } log.info("dmx-usb",output); log.info("dmx-usb universe info:",Object.keys(this.myDMX.universes).length); // check if already connected to a universe. if (Object.keys(this.myDMX.universes).length > 0){ this.myDMX.update("one",output); } else { log.error("dmx-usb", "no serial connection established to DMX Box. no universe set.") } } /////////////////// HELPER FUNCTIONS //////////////////////// ///////////////////////////////////////////////////////////// async getSerialPorts(){ await SerialPort.list().then( (ports)=> { let portList = []; for (const port of ports) { //log.info("dmx-usb","possible ports for DMX USB PRO Plugin:", port.path); portList.push(port.path) }; this.settings_schema.properties.serialPort.enum = portList; // populate schema with list of ports. log.info("dmx-usb portList scan",portList) return portList }); } connectDMX(config){ this.closeSerial(); this.myDMX.addUniverse("one","enttec-usb-dmx-pro",config.settings.serialPort); this.myDMX.update("one", {1:0,2:0,3:0,4:0} ); // initializes black on channels 1-4 log.info("DMX OBJECT",this.myDMX.universes.one.dev.close); this.connected = true; } closeSerial(){ if (this.myDMX && this.myDMX.universes.one && this.myDMX.universes.one.dev && this.myDMX.universes.one.dev.isOpen){ this.myDMX.universes.one.dev.close(); } } } module.exports = { Plugin:myPlugin }