UNPKG

adaptorex

Version:

Connect all your live interactive storytelling devices and software

244 lines (231 loc) 7.05 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 }