UNPKG

adaptorex

Version:

Connect all your live interactive storytelling devices and software

198 lines (166 loc) 5.58 kB
/** * * This plugin summons many typical communication protocols. It allows to connect create different types of connections and to address them in levels. * It adds a send action to cue creation that allows to send messages to all previously created devices. * It allows to switch or listen based on the state of the created devices. * * * @requires device * @requires plugin * * @module devices/devices * @copyright Lasse Marburg 2021 * @license MIT */ const deviceModule = require("./device.js") const {Plugin} = require("../plugin.js") var schema = require("./schema.json") class Devices extends Plugin { constructor() { super(schema) } async setup(config, game) { this.update(config.settings) await super.setup(config, game) this.schema.actions.send.test = "Hallo" this.addTemplate("send", (payload, action) => { let subtitle = `To device ${payload.to}` let body = [{text:`${payload.method || ""} ${payload.path || ""} ${payload.message || ""}`}] return {subtitle:subtitle, body:body} }) for(let collection in this.schema.collections) { this[collection].add = async (device) => { this[collection].items[device._id] = deviceModule.getDevice(device, {name: collection, db_coll: this.game.db["devices_" + collection], emitUpdate: this[collection].emitItemUpdate.bind(this[collection])}, config, game) this[collection].items[device._id].ready = true await this.addDeviceToSchema(device) } this[collection].update = (item, item_doc) => { if(item.name != item_doc.name) { this.addDeviceToSchema(item_doc, item) } } this[collection].remove = async (item) => { try { await item.close() } catch (error) { log.error(this.name, error) } delete this[collection].items[item._id] let index = this.schema.actions.send.properties.to.enum.indexOf(item.name) this.schema.actions.send.properties.to.enum.splice(index, 1) await this.schemaUpdate(this.schema) } await this[collection].loadItems() } await this.load({}) deviceModule.setVirtualMidiPort(this.name) return this.schema } async addDeviceToSchema(device, legacy_device) { if(device.settings.to_device || (!device.settings.to_device && !device.settings.from_device)) { if(legacy_device) { let index = this.schema.actions.send.properties.to.enum.indexOf(legacy_device.name) this.schema.actions.send.properties.to.enum.splice(index, 1, device.name) } else { this.schema.actions.send.properties.to.enum.push(device.name) } } await this.schemaUpdate(this.schema) } async load(setup) { let level = await this.game.db.levels.distinct('name',{}) this.schema.definitions.init.properties.level.enum = level for(let collection in this.schema.collections) { this.schema.collections[collection].properties.init = this.schema.definitions.init } try { let serialports = await deviceModule.getSerialPorts() this.schema.collections.serial.properties.settings.properties.port.enum = serialports } catch (error) { log.error(this.name, "Error when finding serial ports.") log.error(this.name, error) delete this.schema.collections.serial } try { let midiports = await deviceModule.getMidiPorts() } catch (error) { log.error(this.name, error) delete this.schema.collections.midi } await this.schemaUpdate(this.schema) setup.schema = this.schema return setup } update(settings) { if(settings.hasOwnProperty("midi")) { if(settings.midi.active) { deviceModule.activateMidi() } else { deviceModule.deactivateMidi() } } } /** * Find device by name. * * Search for device across all device collections. * * @param {string} name device name property * @returns {Object} device item */ findDevice(name) { for(let collection in this.schema.collections) { if(this[collection].findItem('name', name)) { return this[collection].findItem('name', name) } } } /** * Send payload to device * * if device send() returns a value, its stored in session document. * */ async send(data, session) { if(typeof data.to === "string") { var device = this.findDevice(data.to) } else if(typeof data.to === "object") { var device = this.findDevice(data.to.name) } if(!device) { throw new adaptor.InvalidError(data.to + " is not a valid device.") } data.message = session.variables.parseJSON(data.message) let result = await device.send(data.message,{path:data.path,is_float:data.is_float,method:data.method}) if(result) { let store = {} store[device.name] = result await session.variables.store(store) } } command(input) { switch(input[0]) { case "ports": deviceModule.getPorts() .then(ports => { log.info(this.name, ports) }) .catch(function(error){ log.error(this.name, error) }.bind(this)) break case "midi": if(input[1] == "on") { deviceModule.activateMidi() log.info(this.name, "please restart adaptor:ex to reactivate midi") } else if(input[1] == "off") { deviceModule.deactivateMidi() } break default: super.command(input) break } } } module.exports.Plugin = Devices