Port StatusScreen (new name) to Vue
This commit is contained in:
parent
31c0c3be1c
commit
c669fde8bd
9
.dir-locals.el
Normal file
9
.dir-locals.el
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
;;; Directory Local Variables
|
||||||
|
;;; For more information see (info "(emacs) Directory Variables")
|
||||||
|
|
||||||
|
((web-mode . ((eval . (progn (prettier-js-mode t)
|
||||||
|
(editorconfig-mode t)))
|
||||||
|
(web-mode-script-padding . 0)
|
||||||
|
(web-mode-style-padding . 0)))
|
||||||
|
(js2-mode . ((eval . (progn (prettier-js-mode t)
|
||||||
|
(editorconfig-mode t))))))
|
6192
package-lock.json
generated
6192
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
12
package.json
12
package.json
@ -5,20 +5,24 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"aprs-parser": "^1.0.4",
|
"aprs-parser": "^1.0.4",
|
||||||
"ol": "^5.0.3",
|
"ol": "^5.3.3",
|
||||||
|
"vue": "^2.6.10",
|
||||||
|
"vue-hot-reload-api": "^2.3.3",
|
||||||
"ws": "^5.2.2"
|
"ws": "^5.2.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"parcel": "^1.9.7"
|
"@vue/component-compiler-utils": "^3.0.0",
|
||||||
|
"parcel": "^1.12.3",
|
||||||
|
"vue-template-compiler": "^2.6.10"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
"monkeyPatch": "sed -i '8s| APRSIS| //APRSIS|' node_modules/aprs-parser/lib/index.js",
|
"monkeyPatch": "sed -i '8s| APRSIS| //APRSIS|' node_modules/aprs-parser/lib/index.js",
|
||||||
"serve": "node src/server.js",
|
"serve": "node src/server.js",
|
||||||
"prestart": "npm run monkeyPatch",
|
"prestart": "npm run monkeyPatch",
|
||||||
"start": "node_modules/.bin/parcel src/index.html",
|
"start": "npx parcel src/index.html",
|
||||||
"prebuild": "npm run monkeyPatch",
|
"prebuild": "npm run monkeyPatch",
|
||||||
"build": "node_modules/.bin/parcel build --public-url ./ src/index.html"
|
"build": "npx parcel build --public-url ./ src/index.html"
|
||||||
},
|
},
|
||||||
"author": "Adam Goldsmith <contact@adamgoldsmith.name>",
|
"author": "Adam Goldsmith <contact@adamgoldsmith.name>",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
|
142
src/StationRow.vue
Normal file
142
src/StationRow.vue
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
<template>
|
||||||
|
<tr :class="{ timedOut, lowVoltage, neverHeard: !status.lastHeard }">
|
||||||
|
<td :title="callsign">{{ tacticalOrCall }}</td>
|
||||||
|
<template v-if="status.lastHeard">
|
||||||
|
<td>{{ formatTime(status.lastHeard) }}</td>
|
||||||
|
<td>{{ formatTime(now - status.lastHeard, true) }}</td>
|
||||||
|
<td>{{ status.lastVoltage || "" }}</td>
|
||||||
|
<td>{{ status.lastTemperature || "" }}</td>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<td>Never Heard</td>
|
||||||
|
<td>Never Heard</td>
|
||||||
|
<td>Never Heard</td>
|
||||||
|
<td>Never Heard</td>
|
||||||
|
</template>
|
||||||
|
</tr>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import config from "./status_config.yaml";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "StationRow",
|
||||||
|
props: { callsign: String, tactical: String, messages: Array, now: Date },
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
status: {
|
||||||
|
lastHeard: null,
|
||||||
|
delta: null,
|
||||||
|
lastVoltage: null,
|
||||||
|
lastTemperature: null
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
notify(title, body) {
|
||||||
|
return new Notification(title, { body: body, requireInteraction: true });
|
||||||
|
},
|
||||||
|
|
||||||
|
formatTime(time, isDuration = false) {
|
||||||
|
return new Date(time).toLocaleTimeString(
|
||||||
|
"en-GB",
|
||||||
|
isDuration ? { timeZone: "UTC" } : {}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
prettyDuration(duration) {
|
||||||
|
let date = new Date(duration);
|
||||||
|
return [
|
||||||
|
...Object.entries({
|
||||||
|
hours: date.getUTCHours(),
|
||||||
|
minutes: date.getUTCMinutes(),
|
||||||
|
seconds: date.getUTCSeconds(),
|
||||||
|
milliseconds: date.getUTCMilliseconds()
|
||||||
|
})
|
||||||
|
]
|
||||||
|
.filter(([suffix, num]) => num > 0)
|
||||||
|
.map(([suffix, num]) => num + " " + suffix)
|
||||||
|
.join(" ");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
messages() {
|
||||||
|
Object.assign(
|
||||||
|
this.status,
|
||||||
|
this.messages.reduce((acc, message) => {
|
||||||
|
acc.lastHeard = message.date.getTime();
|
||||||
|
acc.delta = message.date - acc.lastHeard;
|
||||||
|
if ("data" in message && "analog" in message.data) {
|
||||||
|
acc.lastVoltage = message.data.analog[0] / 10;
|
||||||
|
acc.lastTemperature = message.data.analog[1];
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, {})
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
lowVoltage(newVal) {
|
||||||
|
if (newVal) {
|
||||||
|
this.notify(
|
||||||
|
`${this.tacticalOrCall}'s battery has dropepd below ${config.lowVoltage}V`,
|
||||||
|
`Voltage: ${this.status.lastVoltage}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
timedOut(newVal) {
|
||||||
|
if (newVal) {
|
||||||
|
this.notify(
|
||||||
|
`${
|
||||||
|
this.tacticalOrCall
|
||||||
|
} has not been heard for over ${this.prettyDuration(
|
||||||
|
config.timeoutLength
|
||||||
|
)}!`,
|
||||||
|
`Last Heard: ${this.formatTime(
|
||||||
|
this.status.lastHeard
|
||||||
|
)} (${this.prettyDuration(this.now - this.status.lastHeard)} ago!)`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
tacticalOrCall() {
|
||||||
|
return this.tactical || this.callsign;
|
||||||
|
},
|
||||||
|
|
||||||
|
timedOut() {
|
||||||
|
if (!this.status.lastHeard) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let nowDelta = new Date(this.now - this.status.lastHeard);
|
||||||
|
return nowDelta.getTime() > config.timeoutLength;
|
||||||
|
},
|
||||||
|
|
||||||
|
lowVoltage() {
|
||||||
|
return (
|
||||||
|
this.status.lastVoltage && this.status.lastVoltage < config.lowVoltage
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
tr.timedOut {
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr.lowVoltage {
|
||||||
|
background-color: yellow;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr.neverHeard {
|
||||||
|
background-color: purple;
|
||||||
|
color: #eee;
|
||||||
|
}
|
||||||
|
</style>
|
104
src/StatusScreen.vue
Normal file
104
src/StatusScreen.vue
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Callsign</th>
|
||||||
|
<th>Last Heard</th>
|
||||||
|
<th>Time since Last Heard</th>
|
||||||
|
<th>Last Voltage</th>
|
||||||
|
<th>Last Temperature</th>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<StationRow
|
||||||
|
v-for="(tactical, callsign) in config.trackedStations"
|
||||||
|
:key="callsign"
|
||||||
|
:callsign="callsign"
|
||||||
|
:tactical="tactical"
|
||||||
|
:messages="messagesFromStation[callsign] || []"
|
||||||
|
:now="now"
|
||||||
|
>
|
||||||
|
</StationRow>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import aprs from "aprs-parser";
|
||||||
|
|
||||||
|
import StationRow from "./StationRow.vue";
|
||||||
|
|
||||||
|
import config from "./status_config.yaml";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "StationStatus",
|
||||||
|
components: { StationRow },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
config: config,
|
||||||
|
aprsStream: null,
|
||||||
|
parser: new aprs.APRSParser(),
|
||||||
|
messages: [],
|
||||||
|
messagesFromStation: {},
|
||||||
|
now: new Date()
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
// request notification permissions
|
||||||
|
if (Notification.permission !== "granted") {
|
||||||
|
Notification.requestPermission(permission => {
|
||||||
|
if (permission === "granted") {
|
||||||
|
new Notification("Test notification", { body: "whatever" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect to websocket aprs stream
|
||||||
|
this.connectToStream();
|
||||||
|
|
||||||
|
// update shared current time every second
|
||||||
|
window.setInterval(() => (this.now = new Date()), 1000);
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
connectToStream() {
|
||||||
|
this.aprsStream = new WebSocket("ws://localhost:4321");
|
||||||
|
this.aprsStream.onclose = () => {
|
||||||
|
// Try to reconnect every 5 seconds
|
||||||
|
let interval = window.setTimeout(() => {
|
||||||
|
window.clearInterval(interval);
|
||||||
|
this.connectToStream();
|
||||||
|
}, 5000);
|
||||||
|
};
|
||||||
|
this.aprsStream.onmessage = event =>
|
||||||
|
this.handleMessage(JSON.parse(event.data));
|
||||||
|
},
|
||||||
|
|
||||||
|
handleMessage(packet) {
|
||||||
|
let message = this.parser.parse(packet[1]);
|
||||||
|
message.date = new Date(); // TODO: use data[0] instead
|
||||||
|
|
||||||
|
console.log(message);
|
||||||
|
this.messages.push(message);
|
||||||
|
let callsign = message.from && message.from.toString();
|
||||||
|
if (callsign in this.messagesFromStation) {
|
||||||
|
this.messagesFromStation[callsign].push(message);
|
||||||
|
} else {
|
||||||
|
this.$set(this.messagesFromStation, callsign, [message]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
table td,
|
||||||
|
table th {
|
||||||
|
border: 1px solid black;
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,21 +0,0 @@
|
|||||||
table.stations {
|
|
||||||
border-collapse: collapse;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.stations td, table.stations th{
|
|
||||||
border: 1px solid black;
|
|
||||||
padding: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.stations tr.timedOut {
|
|
||||||
background-color: red;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.stations tr.lowVoltage {
|
|
||||||
background-color: yellow;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.stations tr.neverHeard {
|
|
||||||
background-color: purple;
|
|
||||||
color: #eee;
|
|
||||||
}
|
|
@ -1,12 +1,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<script src="./index.js"></script>
|
|
||||||
<link rel="stylesheet" type="text/css" href="index.css">
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="wrapper">
|
<div id="app"> </div>
|
||||||
<table class="stations">
|
<script src="./index.js"></script>
|
||||||
</table>
|
|
||||||
<a href="map.html">Map</a>
|
|
||||||
</div>
|
|
||||||
</body>
|
</body>
|
||||||
|
193
src/index.js
193
src/index.js
@ -1,190 +1,7 @@
|
|||||||
const aprs = require('aprs-parser');
|
import Vue from 'vue';
|
||||||
|
import App from './StatusScreen.vue';
|
||||||
|
|
||||||
// null here means just use the original callsign
|
new Vue({
|
||||||
const trackedStations = {
|
el: '#app',
|
||||||
// Digis/iGates
|
render: h => h(App),
|
||||||
"W1FN-1": null,
|
|
||||||
"W1FN-3": null,
|
|
||||||
"W1FN-5": null,
|
|
||||||
"W1FN-6": null,
|
|
||||||
"W1FN-7": null,
|
|
||||||
"W1FN-8": null,
|
|
||||||
"W1FN-9": null,
|
|
||||||
"W1FN-10": null,
|
|
||||||
"N1GMC-1": null,
|
|
||||||
"N1GMC-2": null,
|
|
||||||
|
|
||||||
// Vehicles
|
|
||||||
"KC1GDW-6": "Metric Rover",
|
|
||||||
"WB1BRE-10": "Recovery 1",
|
|
||||||
"KC1GDW-10": "Recovery 2",
|
|
||||||
"W1LKS-9": "Recovery 3",
|
|
||||||
"WB1BRE-11": "Rover 1-2 (VT)",
|
|
||||||
"KC1GDW-5": "Rover 2-1 (NH)",
|
|
||||||
"WB1BRE-9": "Rover 2-3",
|
|
||||||
"N0JSR-9": "Rover 2-8 (VT)",
|
|
||||||
"N1EMF-7": "Rover 3-4",
|
|
||||||
"K1DSP-9": "Rover 4-5",
|
|
||||||
"WB1BRE-15": "Rover 5-6",
|
|
||||||
"AB1XQ-9": "Rover 5-8",
|
|
||||||
"KC1BOS-2": "Rover 6-7",
|
|
||||||
"K1EHZ-3": "Rover 7-8",
|
|
||||||
"KC1GDW-8": "Rover 8-2 (NH)",
|
|
||||||
"WB1BRE-13": "Rover FPL",
|
|
||||||
"W1HS-9": "Rover SF-1",
|
|
||||||
"W1KUA-9": "Safety 1",
|
|
||||||
"KC1GDW-12": "Shuttle 1",
|
|
||||||
"KC1GDW-13": "Shuttle 2",
|
|
||||||
"KC1GDW-14": "Supply 1",
|
|
||||||
"KC1GDW-11": "Supply 2",
|
|
||||||
"WB1BRE-14": "Supply 3",
|
|
||||||
"WB1BRE-8": "Trouble 1 (North)",
|
|
||||||
"AE1H-8": "Trouble 2 (South)",
|
|
||||||
};
|
|
||||||
|
|
||||||
const timeoutLength = 10 * 60 * 1000; // 10 Minutes
|
|
||||||
const lowVoltage = 11.9;
|
|
||||||
|
|
||||||
|
|
||||||
///////// End of Config /////////
|
|
||||||
|
|
||||||
window.stations = {};
|
|
||||||
window.messages = [];
|
|
||||||
let aprsStream;
|
|
||||||
let parser = new aprs.APRSParser();
|
|
||||||
|
|
||||||
if (Notification.permission !== "granted") {
|
|
||||||
Notification.requestPermission(permission => {
|
|
||||||
if (permission === "granted") {
|
|
||||||
new Notification("Test notification", {body: "whatever"});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTactical(callsign) {
|
|
||||||
if (trackedStations[callsign])
|
|
||||||
return `${trackedStations[callsign]} [${callsign}]`;
|
|
||||||
else
|
|
||||||
return callsign;
|
|
||||||
}
|
|
||||||
|
|
||||||
function prettyDuration(duration) {
|
|
||||||
let date = new Date(timeoutLength);
|
|
||||||
return date.getUTCHours() > 0 ? date.getUTCHours() + " Hours": "" +
|
|
||||||
date.getUTCMinutes() > 0 ? date.getUTCMinutes() + " Minutes": "" +
|
|
||||||
date.getUTCSeconds() > 0 ? date.getUTCSeconds() + " Seconds": "" +
|
|
||||||
date.getUTCMilliseconds() > 0 ? date.getUTCMilliseconds() + " Milliseconds" : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
function redrawTable() {
|
|
||||||
let table = document.querySelector('table.stations');
|
|
||||||
table.innerHTML =
|
|
||||||
`<tr><th>Callsign</th>` +
|
|
||||||
`<th>Last Heard</th>` +
|
|
||||||
`<th>Time since Last Heard</th>` +
|
|
||||||
`<th>Last Voltage</th>` +
|
|
||||||
`<th>Last Temperature</th>`;
|
|
||||||
for (let callsign in trackedStations) {
|
|
||||||
let tr = table.appendChild(document.createElement('tr'));
|
|
||||||
tr.innerHTML = `<td>${getTactical(callsign)}</td>`;
|
|
||||||
if (!(callsign in stations)) {
|
|
||||||
tr.classList.add('neverHeard');
|
|
||||||
tr.innerHTML +=
|
|
||||||
'<td>Never Heard</td>' +
|
|
||||||
'<td>Never Heard</td>' +
|
|
||||||
'<td>Never Heard</td>' +
|
|
||||||
'<td>Never Heard</td>';
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
let station = stations[callsign];
|
|
||||||
let lastHeard = new Date(station.lastHeard);
|
|
||||||
let nowDelta = new Date(new Date() - lastHeard);
|
|
||||||
|
|
||||||
// TODO: should be set by same thing that sends alert
|
|
||||||
if (nowDelta.getTime() > timeoutLength) {
|
|
||||||
tr.classList.add('timedOut');
|
|
||||||
}
|
|
||||||
if (station.lastVoltage < lowVoltage) {
|
|
||||||
tr.classList.add('lowVoltage');
|
|
||||||
}
|
|
||||||
tr.innerHTML +=
|
|
||||||
`<td>${lastHeard.toLocaleTimeString('en-GB')}</td>` +
|
|
||||||
`<td>${nowDelta.toLocaleTimeString('en-GB', {timeZone: "UTC"})}</td>` +
|
|
||||||
`<td>${station.lastVoltage||''}</td>` +
|
|
||||||
`<td>${station.lastTemperature||''}</td>`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function notify(title, body) {
|
|
||||||
return new Notification(title, {body: body, requireInteraction: true});
|
|
||||||
}
|
|
||||||
|
|
||||||
function alertNotHeard(callsign) {
|
|
||||||
notify(`${getTactical(callsign)} has not been heard for ${prettyDuration(timeoutLength)}!`,
|
|
||||||
`Last Heard: ${new Date(stations[callsign].lastHeard).toLocaleTimeString('en-GB')}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
function alertVoltage(callsign) {
|
|
||||||
notify(`${getTactical(callsign)}'s battery has dropepd below ${lowVoltage}V`,
|
|
||||||
`Voltage: ${stations[callsign].lastVoltage}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleMessage(packet) {
|
|
||||||
let message = parser.parse(packet[1]);
|
|
||||||
let callsign = message.from.toString();
|
|
||||||
let date = new Date(); // TODO: use data[0] instead
|
|
||||||
|
|
||||||
console.log(message);
|
|
||||||
messages.push(message);
|
|
||||||
|
|
||||||
// TODO: hacky filter
|
|
||||||
if (callsign in trackedStations) {
|
|
||||||
|
|
||||||
if (!(callsign in stations)) {
|
|
||||||
stations[callsign] = {};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
window.clearTimeout(stations[callsign].timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
stations[callsign].lastHeard = date.getTime();
|
|
||||||
stations[callsign].delta = date - stations[callsign].lastHeard;
|
|
||||||
stations[callsign].timeout = window.setTimeout(
|
|
||||||
alertNotHeard, timeoutLength, callsign);
|
|
||||||
|
|
||||||
if ('data' in message && 'analog' in message.data) {
|
|
||||||
stations[callsign].lastVoltage = message.data.analog[0] / 10;
|
|
||||||
stations[callsign].lastTemperature = message.data.analog[1];
|
|
||||||
|
|
||||||
if (stations[callsign].lastVoltage <= lowVoltage) {
|
|
||||||
alertVoltage(callsign);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
localStorage.setItem("stations", JSON.stringify(stations));
|
|
||||||
|
|
||||||
redrawTable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function connectToStream() {
|
|
||||||
aprsStream = new WebSocket("ws://localhost:1234");
|
|
||||||
aprsStream.onclose = () => {
|
|
||||||
// Try to reconnect every 5 seconds
|
|
||||||
let interval = window.setInterval(() => {
|
|
||||||
window.clearInterval(interval);
|
|
||||||
connectToStream();
|
|
||||||
}, 5000);
|
|
||||||
};
|
|
||||||
aprsStream.onmessage = event => handleMessage(JSON.parse(event.data));
|
|
||||||
}
|
|
||||||
|
|
||||||
connectToStream();
|
|
||||||
|
|
||||||
window.addEventListener("load", redrawTable);
|
|
||||||
window.addEventListener("load", () => {
|
|
||||||
stations = JSON.parse(localStorage.getItem("stations") || '{}');
|
|
||||||
});
|
});
|
||||||
window.setInterval(redrawTable, 1000);
|
|
||||||
|
@ -3,7 +3,7 @@ const net = require('net');
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|
||||||
const client = new net.Socket();
|
const client = new net.Socket();
|
||||||
const wss = new WebSocket.Server({host: "127.0.0.1", port: 1234});
|
const wss = new WebSocket.Server({host: "127.0.0.1", port: 4321});
|
||||||
|
|
||||||
wss.broadcast = function(data) {
|
wss.broadcast = function(data) {
|
||||||
wss.clients.forEach(client => {
|
wss.clients.forEach(client => {
|
||||||
|
42
src/status_config.yaml
Normal file
42
src/status_config.yaml
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
timeoutLength: 600000 # 10 * 60 * 1000 = 10 minutes
|
||||||
|
lowVoltage: 11.9
|
||||||
|
|
||||||
|
trackedStations:
|
||||||
|
# Digis/iGates
|
||||||
|
W1FN-1:
|
||||||
|
W1FN-3:
|
||||||
|
W1FN-5:
|
||||||
|
W1FN-6:
|
||||||
|
W1FN-7:
|
||||||
|
W1FN-8:
|
||||||
|
W1FN-9:
|
||||||
|
W1FN-10:
|
||||||
|
N1GMC-1:
|
||||||
|
N1GMC-2:
|
||||||
|
|
||||||
|
# Vehicles
|
||||||
|
KC1GDW-6: Metric Rover
|
||||||
|
WB1BRE-10: Recovery 1
|
||||||
|
KC1GDW-10: Recovery 2
|
||||||
|
W1LKS-9: Recovery 3
|
||||||
|
WB1BRE-11: Rover 1-2 (VT)
|
||||||
|
KC1GDW-5: Rover 2-1 (NH)
|
||||||
|
WB1BRE-9: Rover 2-3
|
||||||
|
N0JSR-9: Rover 2-8 (VT)
|
||||||
|
N1EMF-7: Rover 3-4
|
||||||
|
K1DSP-9: Rover 4-5
|
||||||
|
WB1BRE-15: Rover 5-6
|
||||||
|
AB1XQ-9: Rover 5-8
|
||||||
|
KC1BOS-2: Rover 6-7
|
||||||
|
K1EHZ-3: Rover 7-8
|
||||||
|
KC1GDW-8: Rover 8-2 (NH)
|
||||||
|
WB1BRE-13: Rover FPL
|
||||||
|
W1HS-9: Rover SF-1
|
||||||
|
W1KUA-9: Safety 1
|
||||||
|
KC1GDW-12: Shuttle 1
|
||||||
|
KC1GDW-13: Shuttle 2
|
||||||
|
KC1GDW-14: Supply 1
|
||||||
|
KC1GDW-11: Supply 2
|
||||||
|
WB1BRE-14: Supply 3
|
||||||
|
WB1BRE-8: Trouble 1 (North)
|
||||||
|
AE1H-8: Trouble 2 (South)
|
Loading…
Reference in New Issue
Block a user