diff --git a/plugins/sennheiser/channel.js b/plugins/sennheiser/channel.js new file mode 100644 index 0000000..ce03de9 --- /dev/null +++ b/plugins/sennheiser/channel.js @@ -0,0 +1,95 @@ +class Channel { + constructor() { + // common attributes + this.frequency = { + hz: null, + bank: null, + channel: null, + }; + this.rfConfig = { + min: null, // hz + max: null, // hz + step: null, // hz + }; + this.name = ''; + this.mute = null; // 0 = disabled, 1 = enabled + this.firmwareRevision = ''; // #.#.# + + this.msg = []; // list of msg strings (Ok, Low Battery, Low RF Signal, etc.) + this.configIndex = null; + + // EM only + this.em = { + squelch: null, + afOut: null, + equalizer: null, // 0 = flat, 1 = low cut, 2 = low&high boost, 3 = high boost + rf1: { + min: null, // % + max: null, // % + active: null, // 0 = inactive, 1 = active + }, + rf2: { + min: null, // % + max: null, // % + active: null, // 0 = inactive, 1 = active + }, + states: { + mutes: { + // 4 bit number 1 bit per flag 0 = disabled, 1 = enabled + mute: null, // bit 0 + txMute: null, // bit 1 + rfMute: null, // bit 2 + rxMute: null, // bit 3 + }, + pilot: 0, // 0 = no pilot for cycle, 1 = pilot for whole cycle, 2 = pilot signle for part of cycle + }, + rf: { + level: 0, // % + antenna: null, // 1 or 2 + pilot: null, // 0 = no pilot, 1 = pilot + }, + af: { + peak: 0, // % + peakHold: 0, // % + mute: { + // 4 bit number 1 bit per flag + mute: null, + txMute: null, + rfMute: null, + rxMute: null, + }, + }, + bat: null, // % 0,30,70,100 + }; + + // SR Only + this.sr = { + sensitivity: null, // -42..0 + equalizer: { + enabled: null, // 0=off,1=on + low: null, // -5..5 + lowMid: null, // -5..5 + mid: null, // -5..5 + midHigh: null, // -5..5 + high: null, // -5..5 + }, + mode: null, // 0 = mono, 1 = stereo + af: [ + { + peak: 0, // % + peakHold: 0, // % + }, + { + peak: 0, // % + peakHold: 0, // % + }, + ], + states: { + mute: null, // 0 = on, 1 = off + muteFlag: null, // 0 = rf mute on whole cycle, 1 = rf mute off whole cycle, 2 = rf mute changed during cycle + }, + }; + } +} + +module.exports = Channel; diff --git a/plugins/sennheiser/icon.png b/plugins/sennheiser/icon.png new file mode 100644 index 0000000..2c0d01e Binary files /dev/null and b/plugins/sennheiser/icon.png differ diff --git a/plugins/sennheiser/info.html b/plugins/sennheiser/info.html new file mode 100644 index 0000000..e69de29 diff --git a/plugins/sennheiser/main.js b/plugins/sennheiser/main.js new file mode 100644 index 0000000..e625df3 --- /dev/null +++ b/plugins/sennheiser/main.js @@ -0,0 +1,40 @@ +const Channel = require('./channel'); + +exports.config = { + defaultName: 'Sennheiser Wireless', + connectionType: 'UDPsocket', + heartbeatInterval: 5000, + heartbeatTimeout: 10000, + defaultPort: 53212, + mayChangePort: false, + searchOptions: { + type: 'UDPsocket', + searchBuffer: Buffer.from('Name\r', 'ascii'), + testPort: 53212, + validateResponse(msg, info) { + return msg.toString().includes('Name'); + }, + }, +}; + +exports.ready = function ready(_device) { + const device = _device; + + // send an immediate request for both types of attributes + _device.send('Push 0 0 1'); + _device.send('Push 0 0 2'); + + device.data.channel = new Channel(); +}; + +exports.data = function data(_device, message) { + console.log(message); + // Parse return message +}; + +exports.update = function update(device, doc, updateType, data) {}; + +exports.heartbeat = function heartbeat(device) { + // tell unit to send both attribute updates every 500ms for 5 seconds + device.send('Push 5 500 3'); +}; diff --git a/plugins/sennheiser/styles.css b/plugins/sennheiser/styles.css new file mode 100644 index 0000000..c1b63b2 --- /dev/null +++ b/plugins/sennheiser/styles.css @@ -0,0 +1,101 @@ +table.channel { + width: 120px; + height: 320px; + background-color: #1a1a1d; + border: #3b3c42 1px solid; + border-collapse: collapse; + color: white; + text-align: center; + float: left; + margin: 2px; + margin-bottom: 20px; +} +table td { + border: #3b3c42 1px solid; + vertical-align: top; +} + +.chan_name { + width: 100px; + color: white !important; + font-size: 18px; + font-weight: bold; +} + +.bar-wrapper { + width: 20px; + height: 90px; + margin: 0px auto; + margin-top: 5px; + margin-bottom: 5px; + + border-radius: 6px; + outline: #1a1a1d 2px solid; + outline-offset: -1px; + overflow: hidden; +} +.bar-wrapper.green { + background: linear-gradient(0deg, #4742af, #554ed4 30%, #554ed4 80%, #df664d); +} +.bar-wrapper.pink { + background: linear-gradient(0deg, #383943, #4e505d 40%); +} +.bar-wrapper.orange { + background: linear-gradient(0deg, #50c3c3, #5bdfe0 30%, #5bdfe0 80%); +} +.bar { + width: 20px; + background-color: #202124; + outline: rgba(255, 255, 255, 0.1) 1px solid; +} + +.batt-wrapper { + width: 84px; + height: 35px; + margin: 0px auto; + border: #333 2px solid; + border-radius: 5px; + padding: 2px; + margin: 10px auto; + position: relative; +} +.batt-wrapper.green { + border-color: greenyellow; +} +.batt-knob { + background-color: #333; + position: absolute; + right: -5px; + top: 10px; + width: 5px; + height: 16px; + border-radius: 2px; +} +.batt-knob.green { + background-color: greenyellow; +} +.batt-bar { + height: 26px; + background: linear-gradient(0deg, rgb(145, 220, 33), greenyellow 100%); + border-radius: 2px; + color: #1a1a1d; + padding-top: 9px; +} + +.rf-indicator-wrapper { + line-height: 8px; + margin-bottom: 4px; + font-size: 6px; + padding-top: 4px; + letter-spacing: 1px; +} +.rf-indicator { + color: #333; +} + +small { + color: dimgray; +} +small small { + color: #444; +} diff --git a/plugins/sennheiser/template.ejs b/plugins/sennheiser/template.ejs new file mode 100644 index 0000000..1277fe8 --- /dev/null +++ b/plugins/sennheiser/template.ejs @@ -0,0 +1,52 @@ +
+

<%= listName %>

+

<%= data.channel.firmwareRevision %>

+
+ + + + + + + + + + + + + + + +
<%= data.channel.name %>
+
+ 1 + 2 +
+ rf +
+
+
+ + TODO
+ dB +
+
+
 
+ audio +
+
+
+ + TODO
+ dB +
+
+
+
+ TODO +
+
+
+
+ TODO [msg and states] +