other/train-to-cloud-city/devices/rfid/start.js (110 lines of code) (raw):
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
const http = require("http");
const express = require("express");
const path = require("path");
const url = require("url");
const { initTrain, getMotor } = require("./utils/train.js");
const { getPorts } = require("./utils/checkpoints.js");
const {
setMissionPattern,
updateLocation,
updateInputMailbox,
} = require("./utils/firestoreHelpers.js");
const {
readCargo,
resetGameState,
updateGameLoop,
storeSignal,
} = require("./trainGame.js");
require("./utils/metrics.js");
const expressApp = express();
expressApp.use(express.json());
expressApp.use(express.static("express"));
expressApp.use(express.static("public"));
const { SerialPort, ReadlineParser } = require("serialport");
/**
* listenToReaders (setup)
* ----------------------
* -> should update state of current train location
* -> push up information to firestore
*/
async function listenToReaders() {
const ports = await getPorts();
ports?.forEach((port, index) => {
// listeners are passed their location role (i.e station, checkpoint, etc);
if (port?.role === "mission_check") {
const listener = new SerialPort(port).pipe(new ReadlineParser());
listener.on("data", (chunk) => setMissionPattern(chunk, port?.role));
return;
}
if (port?.role === "station") {
const listener = new SerialPort(port).pipe(new ReadlineParser());
listener.on("data", (chunk) => readCargo(chunk, port?.role));
return;
}
if (port?.role.indexOf("checkpoint") > -1) {
const listener = new SerialPort(port).pipe(new ReadlineParser());
listener.on("data", () => updateLocation(port?.role));
return;
}
if (port?.role.indexOf("signal") > -1) {
const listener = new SerialPort(port);
storeSignal(listener?.settings?.role, listener);
}
});
}
/**
* initialize
*/
(async function initialize() {
initTrain();
listenToReaders();
await updateInputMailbox("reset");
})();
/**
* GET /stop
*/
expressApp.get("/stop", async (req, res) => {
console.log("Stopping train ...");
try {
const motor = await getMotor();
motor.stop();
} catch (error) {
res.send(`/?message=${encodeURIComponent("Stopping train")}`);
res.status(400).json({ error });
}
});
/**
* get /reset
*/
expressApp.get("/reset", async (req, res) => {
console.log("Resetting train state ...");
try {
resetGameState();
await updateInputMailbox("reset");
res
.status(200)
.redirect(`/?message=${encodeURIComponent("Resetting train")}`);
} catch (error) {
console.error(error);
res.status(400).json({ error });
}
});
/**
* GET /start
*/
expressApp.get("/start", async (req, res) => {
const urlParts = url.parse(req.url, true);
const query = urlParts.query;
try {
const motor = await getMotor();
motor.setPower(30);
console.log("Starting train demo ...");
res
.status(200)
.redirect(`/?message=${encodeURIComponent("Starting train")}`);
} catch (error) {
console.error(error);
res.status(400).json({ error });
}
});
/**
* GET /
*/
expressApp.get("/", (req, res) => {
const urlParts = url.parse(req.url, true);
const query = urlParts.query;
res.sendFile(path.join(__dirname + "/public/index.html"));
});
async function gracefulExit() {
console.log("Caught interrupt signal. Resetting the game.");
resetGameState();
try {
await updateInputMailbox("reset");
console.log("Reset completed, exiting out.");
} catch (error) {
console.log(error);
}
process.exit(0);
}
// Attempt graceful exit if ctrl-c or unexpected crash
[`exit`, `SIGINT`, `uncaughtException`, `SIGTERM`].forEach((eventType) =>
process.on(eventType, gracefulExit),
);
expressApp.listen(3000, () => console.log("Listening to 3000"));