Annoucements 1.5
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
FROM node:22-alpine
|
||||
WORKDIR /app
|
||||
|
||||
RUN corepack enable
|
||||
|
||||
COPY package.json pnpm-lock.yaml ./
|
||||
RUN pnpm install --frozen-lockfile --prod
|
||||
|
||||
COPY server ./server
|
||||
|
||||
EXPOSE 7532
|
||||
|
||||
CMD ["node", "server/index.js"]
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
const express = require("express");
|
||||
const http = require("http");
|
||||
const { Server } = require("socket.io");
|
||||
const cors = require("cors");
|
||||
|
||||
const app = express();
|
||||
app.use(cors());
|
||||
|
||||
const server = http.createServer(app);
|
||||
|
||||
const io = new Server(server, {
|
||||
cors: {
|
||||
origin: "*",
|
||||
},
|
||||
});
|
||||
|
||||
const PORT = 7532;
|
||||
|
||||
let currentSlide = 0;
|
||||
const slideSeconds = 7;
|
||||
|
||||
const { XMLParser } = require("fast-xml-parser");
|
||||
|
||||
let slides = [];
|
||||
|
||||
async function loadSlides() {
|
||||
try {
|
||||
const response = await fetch(
|
||||
"http://10.40.0.2:9000/announcements?list-type=2"
|
||||
);
|
||||
|
||||
const xml = await response.text();
|
||||
|
||||
const parser = new XMLParser();
|
||||
const data = parser.parse(xml);
|
||||
|
||||
const contents = data.ListBucketResult?.Contents || [];
|
||||
|
||||
const files = Array.isArray(contents)
|
||||
? contents
|
||||
: [contents];
|
||||
|
||||
slides = files
|
||||
.map((file) => file.Key)
|
||||
.filter((name) =>
|
||||
/\.(png|jpg|jpeg|webp)$/i.test(name)
|
||||
)
|
||||
.map((name) => {
|
||||
const encodedName = name
|
||||
.split("/")
|
||||
.map((part) => encodeURIComponent(part))
|
||||
.join("/");
|
||||
|
||||
return `http://10.40.0.2:9000/announcements/${encodedName}`;
|
||||
});
|
||||
|
||||
console.log("Slides loaded:", slides.length);
|
||||
|
||||
if (currentSlide >= slides.length) {
|
||||
currentSlide = 0;
|
||||
}
|
||||
|
||||
broadcastState();
|
||||
} catch (err) {
|
||||
console.error("Failed to load slides:", err);
|
||||
}
|
||||
}
|
||||
|
||||
const mqtt = require("mqtt");
|
||||
|
||||
let mode = "on";
|
||||
|
||||
const mqttClient = mqtt.connect("mqtt://10.40.0.2");
|
||||
|
||||
mqttClient.on("connect", () => {
|
||||
console.log("MQTT connected");
|
||||
mqttClient.subscribe("announcements/mode");
|
||||
});
|
||||
|
||||
mqttClient.on("message", (topic, message) => {
|
||||
if (topic === "announcements/mode") {
|
||||
const value = message.toString().trim().toLowerCase();
|
||||
|
||||
if (value === "on" || value === "off") {
|
||||
mode = value;
|
||||
broadcastState();
|
||||
console.log("Announcement mode:", mode);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function broadcastState() {
|
||||
io.emit("slideshow:state", {
|
||||
currentSlide,
|
||||
slides,
|
||||
slideSeconds,
|
||||
mode,
|
||||
});
|
||||
}
|
||||
|
||||
io.on("connection", (socket) => {
|
||||
console.log("Client connected:", socket.id);
|
||||
|
||||
socket.emit("slideshow:state", {
|
||||
currentSlide,
|
||||
slides,
|
||||
slideSeconds,
|
||||
mode,
|
||||
});
|
||||
});
|
||||
|
||||
setInterval(() => {
|
||||
if (slides.length === 0) return;
|
||||
|
||||
currentSlide = (currentSlide + 1) % slides.length;
|
||||
broadcastState();
|
||||
}, slideSeconds * 1000);
|
||||
|
||||
app.get("/", (req, res) => {
|
||||
res.send("Announcement server is running");
|
||||
});
|
||||
|
||||
loadSlides();
|
||||
|
||||
setInterval(() => {
|
||||
loadSlides();
|
||||
}, 30000);
|
||||
|
||||
server.listen(PORT, () => {
|
||||
console.log(`Announcement server running on http://10.40.0.2:${PORT}`);
|
||||
});
|
||||
Reference in New Issue
Block a user