Compare commits

..

3 commits

Author SHA1 Message Date
Christopher Cookman e615d6e441 Add test event system 2025-08-31 23:36:02 -06:00
Christopher Cookman 596b79ad0d Gwug 2025-08-31 23:31:57 -06:00
Christopher Cookman 258c99850d Add alarm styles 2025-08-31 23:28:18 -06:00
2 changed files with 104 additions and 3 deletions

View file

@ -33,6 +33,93 @@ async function fetchEvents() {
setTimeout(fetchEvents, 1000); setTimeout(fetchEvents, 1000);
} }
dataTypes = {
DoorMode: {
1: 'NormallyOpen',
2: 'NormallyClosed',
3: 'Controlled'
},
Direction: {
1: 'In',
2: 'Out'
},
EventType: {
0: 'None',
1: 'Swipe',
2: 'Door',
3: 'Alarm',
255: 'Overwritten'
},
EventReason: {
0: 'None',
1: 'Swipe',
2: 'SwipeOpen',
3: 'SwipeClose',
5: 'Denied',
6: 'NoAccessRights',
7: 'IncorrectPassword',
8: 'AntiPassback',
9: 'MoreCards',
10: 'FirstCardOpen',
11: 'DoorIsNormallyClosed',
12: 'Interlock',
13: 'NotInAllowedTimePeriod',
15: 'InvalidTimezone',
18: 'AccessDenied',
20: 'PushbuttonOk',
23: 'DoorOpened',
24: 'DoorClosed',
25: 'DoorOpenedSupervisorPassword',
28: 'ControllerPowerOn',
29: 'ControllerReset',
31: 'PushbuttonInvalidDoorLocked',
32: 'PushbuttonInvalidOffline',
33: 'PushbuttonInvalidInterlock',
34: 'PushbuttonInvalidThreat',
37: 'DoorOpenTooLong',
38: 'ForcedOpen',
39: 'Fire',
40: 'ForcedClosed',
41: 'TheftPrevention',
42: 'Zone24x7',
43: 'Emergency',
44: 'RemoteOpenDoor',
45: 'RemoteOpenDoorUSBReader'
}
}
const validEvents = {
1: [1,2,3,6,7],
2: [25],
3: [23,24,28,37,38,39,40,41,42,43,44,45]
}
if (process.env.EVENT_TESTING == true) {
setInterval(() => {
const eventTypes = Object.keys(validEvents);
const eventType = parseInt(eventTypes[Math.floor(Math.random() * eventTypes.length)]);
const reasons = validEvents[eventType];
const eventReason = reasons[Math.floor(Math.random() * reasons.length)];
const cardNumber = Math.floor(Math.random() * 1000000) + 1;
const granted = [5, 6, 7, 18].includes(eventReason) ? false : true;
const testEvent = {
Controller: 123456789,
EventIndex: ++lastEventIndex,
Timestamp: new Date().toISOString().replace('T', ' ').substring(0, 19),
Type: eventType,
Reason: eventReason,
Granted: granted,
CardNumber: cardNumber,
Door: 1,
Direction: eventType == 1 ? (Math.random() < 0.5 ? 1 : 2) : 0,
}
log.info(`Generated test event: ${JSON.stringify(testEvent)}`);
emitter.emit('event', testEvent);
}, 1000);
}
(async () => { (async () => {
await getLastEventIndex(); await getLastEventIndex();
await fetchEvents(); await fetchEvents();

View file

@ -79,6 +79,9 @@
const reasons = <% - JSON.stringify(dataTypes.EventReason) %>; const reasons = <% - JSON.stringify(dataTypes.EventReason) %>;
const tr = document.createElement('tr'); const tr = document.createElement('tr');
if (log.Type === 3) {
tr.style.background = '#f7c5c5';
}
tr.innerHTML = ` tr.innerHTML = `
<td>${log.Controller}</td> <td>${log.Controller}</td>
<td>${log.EventIndex}</td> <td>${log.EventIndex}</td>
@ -93,6 +96,18 @@
<td>${reasons[log.Reason] || log.Reason}</td> <td>${reasons[log.Reason] || log.Reason}</td>
`; `;
tbody.insertBefore(tr, tbody.firstChild); tbody.insertBefore(tr, tbody.firstChild);
tr.style.background = 'orange';
setTimeout(() => {
let opacity = 1;
const fade = setInterval(() => {
opacity -= 0.05;
tr.style.background = `rgba(255,165,0,${opacity})`;
if (opacity <= 0.1) {
tr.style.background = '';
clearInterval(fade);
}
}, 40);
}, 0);
}; };
ws.onopen = function () { ws.onopen = function () {
@ -128,7 +143,7 @@
</thead> </thead>
<tbody> <tbody>
<% logs.forEach(function(log) { %> <% logs.forEach(function(log) { %>
<tr> <tr style="<%= log.Type === 3 ? 'background:#f7c5c5;' : '' %>"></tr>
<td> <td>
<%= log.Controller %> <%= log.Controller %>
</td> </td>
@ -145,13 +160,12 @@
const ss = pad(date.getSeconds()); const ss = pad(date.getSeconds());
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone; const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
%> %>
%>
<%= `${yyyy}-${mm}-${dd} ${HH}:${MM}:${ss} ${tz}` %> <%= `${yyyy}-${mm}-${dd} ${HH}:${MM}:${ss} ${tz}` %>
</td> </td>
<td> <td>
<%= dataTypes.EventType[log.Type] %> <%= dataTypes.EventType[log.Type] %>
</td> </td>
<td style="<%= log.Type === 1 ? `background:${log.Granted ? '#c8f7c5' : '#f7c5c5'};` : '' %>"> <td style="<%= (log.Type === 1 || log.Type === 2) ? `background:${log.Granted ? '#c8f7c5' : '#f7c5c5'};` : '' %>">
<%= log.Granted ? "True" : "False" %> <%= log.Granted ? "True" : "False" %>
</td> </td>
<td> <td>