initial lightfactory support

This commit is contained in:
2023-10-21 10:13:13 -05:00
parent 7f2eaacd2f
commit 66405aefa0
4 changed files with 158 additions and 0 deletions
View File
+99
View File
@@ -0,0 +1,99 @@
exports.config = {
defaultName: 'LightFactory',
connectionType: 'TCPsocket',
remotePort: 3100,
mayChangePorts: true,
searchOptions: {
type: 'TCPport',
searchBuffer: Buffer.from('authenticate 1\n', 'ascii'),
testPort: 3100,
validateResponse(msg, info) {
return msg.toString().substring(0, 5) === 'Ready';
},
},
};
exports.ready = function ready(device) {
device.data.cueLists = {};
device.send('get cue list\n');
};
function cleanMessage(message) {
return message.split('\n').filter((line) => line.trim() !== '');
}
// TODO(jwetzell): process updates? are they live or do we need to poll?
exports.data = function data(_device, _message) {
const message = _message.toString();
const device = _device;
console.log(message);
if (message.includes('Current Cue List')) {
// NOTE(jwetzell): loading cue list info
const cueListMessage = cleanMessage(message);
if (cueListMessage.includes('<LIST START>') && cueListMessage.includes('<LIST FINISHED>')) {
console.log('message is a cue list message');
const cueListstartIndex = cueListMessage.indexOf('<LIST START>');
const cueListFinishedIndex = cueListMessage.indexOf('<LIST FINISHED>');
for (let i = cueListstartIndex + 1; i < cueListFinishedIndex; i++) {
const cueListName = cueListMessage[i];
if (device.data.cueLists[cueListName] === undefined) {
device.data.cueLists[cueListName] = {
name: cueListName,
cues: {},
active: false,
};
} else {
// NOTE(jwetzell): reset active as it will be computed in a few lines
device.data.cueLists[cueListName].active = false;
}
}
const activeCueListLine = cueListMessage[cueListFinishedIndex + 1];
if (activeCueListLine) {
const activeCueListLineParts = activeCueListLine.split('Current Cue List');
const activeCueList = activeCueListLineParts[activeCueListLineParts.length - 1].trim();
if (activeCueList && device.data.cueLists[activeCueList] !== undefined) {
device.data.cueLists[activeCueList].active = true;
}
}
device.data.cueListToLoad = Object.keys(device.data.cueLists)[0];
console.log(device.data.cueListToLoad);
device.send(`get cues ${device.data.cueListToLoad}\n`);
}
} else if (message.includes('Current Live Cue')) {
// NOTE(jwetzell): loading cues for a cue list
const cueList = device.data.cueLists[device.data.cueListToLoad];
const cueListCuesMessage = cleanMessage(message);
console.log(cueListCuesMessage);
if (cueListCuesMessage.includes('<LIST START>') && cueListCuesMessage.includes('<LIST FINISHED>')) {
console.log('message is a cue list message');
const cuesStartIndex = cueListCuesMessage.indexOf('<LIST START>');
const cuesFinishedIndex = cueListCuesMessage.indexOf('<LIST FINISHED>');
for (let i = cuesStartIndex + 1; i < cuesFinishedIndex; i++) {
const cueName = cueListCuesMessage[i];
if (cueList.cues[cueName] === undefined) {
cueList.cues[cueName] = {
name: cueName,
active: false,
};
} else {
// NOTE(jwetzell): reset active as it will be computed in a few lines
cueList[cueName].active = false;
}
}
}
const cueListNames = Object.keys(device.data.cueLists);
const cueListIndex = cueListNames.indexOf(device.data.cueListToLoad);
device.data.cueListToLoad = cueListNames.at(cueListIndex + 1);
if (device.data.cueListToLoad !== undefined) {
device.send(`get cues ${device.data.cueListToLoad}\n`);
}
}
device.draw();
};
// TODO(jwetzell): keep alive? refresh cue list info?
exports.heartbeat = function heartbeat(device) {};
+28
View File
@@ -0,0 +1,28 @@
section {
background-color: #2d2d2d;
border: gray 1px solid;
padding: 10px;
padding-top: 0px;
border-radius: 10px;
overflow: hidden;
}
table {
width: 100%;
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;
}
+31
View File
@@ -0,0 +1,31 @@
<header>
<h1><%= listName %></h1>
</header>
<div>
<!-- Server Loop -->
<% Object.entries(data.cueLists).forEach(([cueListName,cueListData]) => { %>
<section>
<h2>Cue List: <%= cueListData.name %> <%= cueListData.active ? '(Active)': '' %></h2>
<table>
<tr>
<th>Name</th>
</tr>
<!-- Tracker Loop -->
<% Object.entries(cueListData.cues).forEach(([cueName,cueData]) => { %>
<tr>
<td><%= cueName %></td>
</tr>
<% }); %>
</table>
</section>
<%
});
%>
</div>