diff --git a/package-lock.json b/package-lock.json index aaa32d8..7e27d59 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,14 +1,15 @@ { "name": "cue-view", - "version": "1.0.1", + "version": "1.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "cue-view", - "version": "1.0.1", + "version": "1.1.0", "license": "CC BY-SA 4.0", "dependencies": { + "@jwetzell/posistagenet": "^0.4.6", "atem-connection": "^3.3.0", "bonjour": "^3.5.0", "electron-updater": "^6.1.1", @@ -307,6 +308,11 @@ "node": ">=14.15" } }, + "node_modules/@jwetzell/posistagenet": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/@jwetzell/posistagenet/-/posistagenet-0.4.6.tgz", + "integrity": "sha512-ZOY7/TylNoZyRNwoc4fAPZ3Ezf9CBO0ciX6EC03nBeOADaknaoHQpl9yc7f0x4t8bOeF4y2Hdpq3UtEw9JPdfg==" + }, "node_modules/@malept/cross-spawn-promise": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", @@ -5348,6 +5354,11 @@ "pkg-prebuilds": "^0.2.1" } }, + "@jwetzell/posistagenet": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/@jwetzell/posistagenet/-/posistagenet-0.4.6.tgz", + "integrity": "sha512-ZOY7/TylNoZyRNwoc4fAPZ3Ezf9CBO0ciX6EC03nBeOADaknaoHQpl9yc7f0x4t8bOeF4y2Hdpq3UtEw9JPdfg==" + }, "@malept/cross-spawn-promise": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", diff --git a/package.json b/package.json index 793e742..a5bc0f2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "cue-view", "productName": "Cue View", - "version": "1.0.1", + "version": "1.1.0", "description": "A dashboard for everything in your show", "main": "main.js", "scripts": { @@ -30,6 +30,7 @@ "prettier": "^3.0.2" }, "dependencies": { + "@jwetzell/posistagenet": "^0.4.6", "atem-connection": "^3.3.0", "bonjour": "^3.5.0", "electron-updater": "^6.1.1", diff --git a/plugins/posistagenet/icon.afphoto b/plugins/posistagenet/icon.afphoto new file mode 100644 index 0000000..402dff6 Binary files /dev/null and b/plugins/posistagenet/icon.afphoto differ diff --git a/plugins/posistagenet/icon.png b/plugins/posistagenet/icon.png new file mode 100644 index 0000000..21e3411 Binary files /dev/null and b/plugins/posistagenet/icon.png differ diff --git a/plugins/posistagenet/info.html b/plugins/posistagenet/info.html new file mode 100644 index 0000000..40798ac --- /dev/null +++ b/plugins/posistagenet/info.html @@ -0,0 +1 @@ +
PosiStageNet requires no configuration.
diff --git a/plugins/posistagenet/main.js b/plugins/posistagenet/main.js new file mode 100644 index 0000000..e6c169a --- /dev/null +++ b/plugins/posistagenet/main.js @@ -0,0 +1,58 @@ +const { Decoder } = require('@jwetzell/posistagenet'); + +exports.config = { + defaultName: 'PosiStageNet', + connectionType: 'multicast', + port: 56565, + remotePort: 56565, + mayChangePorts: false, + heartbeatInterval: 5000, + heartbeatTimeout: 15000, + searchOptions: { + type: 'multicast', + address: `236.10.10.10`, + port: 56565, + validateResponse(msg, info) { + // TODO(jwetzell): find a way to check that this is a posistagenet message + return true; + }, + }, +}; + +exports.ready = function ready(_device) { + const device = _device; + device.data = {}; + const networkInterfaces = device.getNetworkInterfaces(); + + Object.keys(networkInterfaces).forEach((networkInterfaceID) => { + const networkInterface = networkInterfaces[networkInterfaceID]; + device.connection.addMembership(`236.10.10.10`, networkInterface[0].address); + }); +}; + +exports.data = function data(_device, buf, info) { + const device = _device; + + if (!device.decoders) { + device.decoders = {}; + } + + if (!device.decoders[info.address]) { + device.decoders[info.address] = new Decoder(); + } + + device.decoders[info.address].decode(buf); + + Object.keys(device.decoders).forEach((address) => { + device.data[address] = { + trackers: device.decoders[address].trackers, + system_name: device.decoders[address].system_name, + fields: device.decoders[address].getTrackerFields(), + }; + }); + device.draw(); +}; + +exports.heartbeat = function heartbeat(device) {}; + +exports.update = function update(_device, doc, updateType, updateData) {}; diff --git a/plugins/posistagenet/styles.css b/plugins/posistagenet/styles.css new file mode 100644 index 0000000..4df893f --- /dev/null +++ b/plugins/posistagenet/styles.css @@ -0,0 +1,46 @@ +section { + background-color: #2d2d2d; + border: gray 1px solid; + padding: 10px; + padding-top: 0px; + border-radius: 10px; + overflow: hidden; +} +table { + border: #414142 1px solid; + background-color: #272727; +} +table, +th, +td { + border-collapse: collapse; + color: #ccc; + + font-size: 13px; +} +th { + padding: 2px 10px; +} +td { + text-align: center; + padding: 2px 7px; + font-family: 'Courier New', Courier, monospace; +} +.bg-pos { + background-color: #443727; +} +.bg-speed { + background-color: #32422e; +} +.bg-ori { + background-color: #2e4242; +} +.bg-accel { + background-color: #392b3f; +} +.bg-trgtpos { + background-color: #3a2732; +} +.border-right { + border-right: 1px solid #272727; +} diff --git a/plugins/posistagenet/template.ejs b/plugins/posistagenet/template.ejs new file mode 100644 index 0000000..a3ae454 --- /dev/null +++ b/plugins/posistagenet/template.ejs @@ -0,0 +1,154 @@ +| + <% if(instanceData.fields.has('tracker_name')) { %> + | + <% } %> + + <% if(instanceData.fields.has('pos')) { %> + | POS | + <% } %> + + <% if(instanceData.fields.has('speed')) { %> +SPEED | + <% } %> + + <% if(instanceData.fields.has('ori')) { %> +ORI | + <% } %> + + <% if(instanceData.fields.has('status')) { %> ++ <% } %> + + <% if(instanceData.fields.has('accel')) { %> + | ACCEL | + <% } %> + + <% if(instanceData.fields.has('trgtpos')) { %> +TRGTPOS | + <% } %> + + <% if(instanceData.fields.has('timestamp')) { %> ++ <% } %> + | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ID | + <% if(instanceData.fields.has('tracker_name')) { %> +Name | + <% } %> + + <% if(instanceData.fields.has('pos')) { %> +x | +y | +z | + <% } %> + + <% if(instanceData.fields.has('speed')) { %> +x | +y | +z | + <% } %> + + <% if(instanceData.fields.has('ori')) { %> +x | +y | +z | + <% } %> + + <% if(instanceData.fields.has('status')) { %> +validity | + <% } %> + + <% if(instanceData.fields.has('accel')) { %> +x | +y | +z | + <% } %> + + <% if(instanceData.fields.has('trgtpos')) { %> +x | +y | +z | + <% } %> + + <% if(instanceData.fields.has('timestamp')) { %> +tracker_timestamp | + <% } %> + +
| <%= trackerId %> | + <% if(instanceData.fields.has('tracker_name')) { %> +<%= trackerData.tracker_name?.tracker_name%> | + <% } %> + + <% if(instanceData.fields.has('pos')) { %> + +<%= trackerData.pos?.pos_x?.toFixed(2) %> | +<%= trackerData.pos?.pos_y?.toFixed(2) %> | +<%= trackerData.pos?.pos_z?.toFixed(2) %> | + <% } %> + + <% if(instanceData.fields.has('speed')) { %> + +<%= trackerData.speed?.speed_x?.toFixed(2) %> | +<%= trackerData.speed?.speed_y?.toFixed(2) %> | +<%= trackerData.speed?.speed_z?.toFixed(2) %> | + <% } %> + + <% if(instanceData.fields.has('ori')) { %> + +<%= trackerData.ori?.ori_x?.toFixed(2) %> | +<%= trackerData.ori?.ori_y?.toFixed(2) %> | +<%= trackerData.ori?.ori_z?.toFixed(2) %> | + <% } %> + + <% if(instanceData.fields.has('status')) { %> +<%= trackerData.status?.validity?.toFixed(2) %> | + <% } %> + + <% if(instanceData.fields.has('accel')) { %> + +<%= trackerData.accel?.accel_x?.toFixed(2) %> | +<%= trackerData.accel?.accel_y?.toFixed(2) %> | +<%= trackerData.accel?.accel_z?.toFixed(2) %> | + <% } %> + + <% if(instanceData.fields.has('trgtpos')) { %> + +<%= trackerData.trgtpos?.trgtpos_x?.toFixed(2) %> | +<%= trackerData.trgtpos?.trgtpos_y?.toFixed(2) %> | +<%= trackerData.trgtpos?.trgtpos_z?.toFixed(2) %> | + <% } %> + + <% if(instanceData.fields.has('timestamp')) { %> +<%= trackerData.timestamp?.tracker_timestamp %> | + <% } %> + +