diff --git a/plugins/shure/icon.png b/plugins/shure/icon.png
new file mode 100644
index 0000000..1ef31f0
Binary files /dev/null and b/plugins/shure/icon.png differ
diff --git a/plugins/shure/info.html b/plugins/shure/info.html
new file mode 100644
index 0000000..e69de29
diff --git a/plugins/shure/main.js b/plugins/shure/main.js
new file mode 100644
index 0000000..7811d00
--- /dev/null
+++ b/plugins/shure/main.js
@@ -0,0 +1,111 @@
+const _ = require('lodash');
+
+exports.config = {
+ defaultName: 'Shure Wireless',
+ connectionType: 'TCPsocket',
+ heartbeatInterval: 10000,
+ heartbeatTimeout: 15000,
+ defaultPort: 2202,
+ mayChangePort: false,
+ searchOptions: {
+ type: 'UDPsocket',
+ searchBuffer: Buffer.from([0x25, 0x32, 0x53, 0x52, 0x43, 0x48, 0x0d]),
+ devicePort: 4352,
+ listenPort: 4352,
+ validateResponse(msg, info) {
+ console.log(msg.toString());
+ return msg.toString().indexOf('%2ACKN=') >= 0;
+ },
+ },
+};
+
+let blankChannel = {
+ chan_name: '?',
+ batt_bars: '',
+ batt_charge: '',
+ batt_cycle: '',
+ batt_health: '',
+ batt_run_time: '',
+ batt_temp_c: '',
+ batt_temp_f: '',
+ batt_type: '',
+ audio_gain: '',
+ audio_mute: '',
+ tx_mute_button_status: '',
+ audio_lvl: 0,
+ rx_rf_lvl: 0,
+};
+
+exports.ready = function ready(device) {
+ device.data.channels = [
+ {},
+ _.clone(blankChannel),
+ _.clone(blankChannel),
+ _.clone(blankChannel),
+ _.clone(blankChannel),
+ ];
+};
+
+exports.data = function data(device, message) {
+ let msgStr = message.toString();
+
+ if (!msgStr.startsWith('< ')) {
+ return;
+ }
+
+ msgStr = msgStr.slice(2).slice(0, -1);
+ let msgs = msgStr.split('><');
+
+ msgs.forEach((msg, i) => {
+ msg = msg.trim();
+ let m = msg.split(' ');
+
+ // console.log(msg);
+
+ let ch = device.data.channels[Number(m[1])];
+
+ //console.log(m);
+
+ if (m[0] == 'REP') {
+ if (m[2] == 'CHAN_NAME') {
+ ch.chan_name = msg.substring(17).slice(0, -2).trim();
+ } else if (m[2] == 'BATT_RUN_TIME') {
+ ch.batt_run_time = Number(m[3]);
+ } else if (m[2] == 'BATT_TEMP_F') {
+ ch.batt_temp_f = Number(m[3]);
+ } else if (m[2] == 'BATT_HEALTH') {
+ ch.batt_health = Number(m[3]);
+ } else if (m[2] == 'AUDIO_GAIN') {
+ ch.audio_gain = Number(m[3]);
+ } else if (m[2] == 'AUDIO_MUTE') {
+ ch.audio_mute = m[3];
+ } else if (m[2] == 'TX_MUTE_BUTTON_STATUS') {
+ ch.tx_mute_button_status = m[3];
+ } else if (m[2] == 'AUDIO_LVL') {
+ ch.audio_lvl = Number(m[3]);
+ } else if (m[2] == 'RX_RF_LVL') {
+ ch.rx_rf_lvl = Number(m[3]);
+ } else if (m[2] == 'RF_ANTENNA') {
+ ch.rf_antenna = m[3];
+ } else if (m[1] == 'DEVICE_ID') {
+ let id = msg.substring(15).slice(0, -1).trim();
+ this.deviceInfoUpdate(device, 'defaultName', id);
+ } else if (m[1] == 'FW_VER') {
+ device.data.version = m[2].substring(1);
+ }
+ } else if (m[0] == 'SAMPLE') {
+ ch.rf_antenna = m[3];
+ ch.rx_rf_lvl = Number(m[4]);
+ ch.audio_lvl = Number(m[5]);
+ }
+ });
+
+ device.draw();
+};
+
+exports.heartbeat = function heartbeat(device) {
+ device.send('< GET 0 ALL >');
+ device.send('< GET MODEL >');
+ //device.send('< SET 0 METER_RATE 00000 >');
+ //device.send('< SAMPLE 0 AUDIO_LVL>');
+};
diff --git a/plugins/shure/styles.css b/plugins/shure/styles.css
new file mode 100644
index 0000000..3d7dc92
--- /dev/null
+++ b/plugins/shure/styles.css
@@ -0,0 +1,34 @@
+table.channel {
+ width: 120px;
+ height: 400px;
+ background-color: black;
+ border: gray 1px solid;
+ border-collapse: collapse;
+ color: white;
+ text-align: center;
+ float: left;
+}
+table td {
+ border: #666 1px solid;
+}
+
+.chan_name {
+ width: 100px;
+ color: #b2ff33 !important;
+ font-size: 18px;
+ font-weight: bold;
+}
+
+.mute-button {
+ background-color: #222;
+ padding: 10px;
+ margin: 5px;
+ border-radius: 4px;
+}
+.mute-button.red {
+ background-color: red;
+}
+
+small {
+ color: gray;
+}
diff --git a/plugins/shure/template.ejs b/plugins/shure/template.ejs
new file mode 100644
index 0000000..01ae442
--- /dev/null
+++ b/plugins/shure/template.ejs
@@ -0,0 +1,47 @@
+<%= listName %>
+ <%= data.version || "" %>
+
| <%= i %> | +|
| <%= ch.chan_name %> | +|
| <%= ch.audio_gain %>db | +<%= ch.audio_lvl %> | +
| + <% if(ch.audio_mute=="ON" || ch.tx_mute_button_status=="PRESSED"){ %> + + <% }else{ %> + + <% } %> + | +|
| RF Level <%= ch.rx_rf_lvl %>dbm |
+ |
|
+ Time: <%= ch.batt_run_time %> Health: <%= ch.batt_health %> Temp: <%= ch.batt_temp_f %>F + |
+ |