commit 3d0277f80c9b4d74d36621b6de79c65f2d1065bc
parent 735b9127def9bb697b21df80398357c73e6ac75a
Author: Milan Pässler <me@pbb.lc>
Date: Sun, 21 Jul 2019 17:23:31 +0200
parent 735b9127def9bb697b21df80398357c73e6ac75a
Author: Milan Pässler <me@pbb.lc>
Date: Sun, 21 Jul 2019 17:23:31 +0200
foo
6 files changed, 5 insertions(+), 219 deletions(-)
diff --git a/server/index.js b/server/index.js @@ -1,181 +0,0 @@ -"use strict"; - -const url = require("url"); -const http = require("http"); -const net = require("net"); -const modbus = require("modbus-tcp"); -const WebSocket = require("ws"); -const fetch = require("node-fetch"); - -const state = {}; - -function broadcastState() { - wss.broadcast(JSON.stringify(state)); -} - -const server = http.createServer(function(req, res) { - let requestUrl = url.parse(req.url); - if (req.method === "GET" && requestUrl.pathname === "/powermeter.json") { - res.writeHead(200, { "Content-Type": "application/json; charset=utf-8" }); - res.end(JSON.stringify(state.powermeter)); - } else { - res.writeHead(404, { 'Content-Type': 'text/plain' }); - res.end('404'); - } -}); - -const wss = new WebSocket.Server({ server }); - -wss.broadcast = function broadcast(data) { - wss.clients.forEach(function each(client) { - if (client.readyState === WebSocket.OPEN) { - client.send(data); - } - }); -}; - -wss.on('connection', function connection(ws) { - ws.send(JSON.stringify(state)); -}); - -setInterval(function sendKeepalive() { - wss.broadcast(""); -}, 1000); - - -const client = new modbus.Client(); -const socket = new net.Socket(); -socket.on("close", function(e) { - console.log("reconnecting", e); - socket.setTimeout(300, function() { - socket.connect({'host': '192.168.1.1', 'port': 502 }); - }); -}); -socket.connect({'host': '192.168.1.1', 'port': 502 }); -client.pipe(socket); - -/* lights */ - -const lights = [ - "Deckenbeleuchtung", - "Bett", - "Kueche", - "Bad", -]; - -wss.on('connection', function connection(ws) { - ws.on('message', function incoming(message) { - const input = String(message).split(' '); - - if (input[0] == 'set' && input[1] < 9 && (input[2] == 'on' || input[2] == 'off')) { - let val = 0; - - if (input[2] == 'on') { - val = 1; - } - - setRelay(input[1], val); - } - }); -}); - -function mapToNames(data) { - return lights.map((name, id) => { - return { - name, - id: id + 1, - value: data[id], - }; - }); -} - -function setRelay(id, val) { - client.writeSingleCoil(10, '10'+id, val); - client.readCoils(10, 101, 108, function (err, data){ - state.lights = mapToNames(data); - broadcastState(); - }) -} - -function readRelays(ws) { - client.readCoils(10, 101, 108, function (err, data){ - state.lights = mapToNames(data); - }); -} - -readRelays(); - -/* powermeter */ - -state.powermeter = { - 60: { name: "Kueche" }, - 50: { name: "Sonstiges" }, -}; - -const registers = { - voltage: 0, - power: 12, - frequency: 70, - import: 72, - cosphi: 30, -}; - -function unixTimestamp() { - return Math.floor(Number(new Date()) / 1000); -} - -function round(num, places) { - const factor = Math.pow(10, places); - return Math.round(num * factor) / factor; -} - -function getFloat32Register(counterId, registerId, client, socket) { - return new Promise(function(fulfill, reject) { - client.readInputRegisters(counterId, registerId, registerId+1, function (err, data) { - if (err) return reject(); - - // Create a buffer - var buf = new ArrayBuffer(4); - // Create a data view of it - var view = new DataView(buf); - - // set bytes - view.setUint8(0, data[0][0]); - view.setUint8(1, data[0][1]); - view.setUint8(2, data[1][0]); - view.setUint8(3, data[1][1]); - - //const buf = Buffer.concat(data).buffer; - //const view = new DataView(buf); - const num = view.getFloat32(0); - - fulfill(num); - }); - }); -} - -async function fetchValues() { - for (let [id, counter] of Object.entries(state.powermeter)) { - for (let key of Object.keys(registers)) { - try { - counter.values[key] = round(await getFloat32Register(id, registers[key], client, socket), 2); - counter.lastUpdated = unixTimestamp(); - } catch(e) {} - } - } - broadcastState(); -} - - -for (let [id, counter] of Object.entries(state.powermeter)) { - counter.values = Object.keys(registers).reduce(function(result, key) { - result[key] = 0; - return result; - }, {}); - counter.lastUpdated = unixTimestamp(); -} - -setInterval(fetchValues, 20000); -fetchValues(); - -server.listen(8080);
diff --git a/server/package.json b/server/package.json @@ -1,7 +0,0 @@ -{ - "dependencies": { - "modbus-tcp": "^0.4.13", - "node-fetch": "^2.6.0", - "ws": "^7.0.0" - } -}
diff --git a/server/yarn.lock b/server/yarn.lock @@ -1,25 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -async-limiter@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" - integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg== - -modbus-tcp@^0.4.13: - version "0.4.13" - resolved "https://registry.yarnpkg.com/modbus-tcp/-/modbus-tcp-0.4.13.tgz#3e0e93af516d78a19f0f62686e64558e6ae6426b" - integrity sha512-TytYObBTQhEMzjfFgGK3iESUoneH9WJRWHoZkt7PBuNnnx2nSOW0tOLC1YeQKNi/Qv7Xv0IjbVhxOoHyXOaV9g== - -node-fetch@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" - integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== - -ws@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.0.0.tgz#79351cbc3f784b3c20d0821baf4b4ff809ffbf51" - integrity sha512-cknCal4k0EAOrh1SHHPPWWh4qm93g1IuGGGwBjWkXmCG7LsDtL8w9w+YVfaF+KSVwiHQKDIMsSLBVftKf9d1pg== - dependencies: - async-limiter "^1.0.0"
diff --git a/src/layout.js b/src/layout.js @@ -17,9 +17,9 @@ import "./spinner.js"; import "./row.js"; const createRedirect = (id) => { - const config = state.config.views.filter(view => view.url == id); + const config = state.config.views.filter(view => view.url == id)[0]; const redirect = document.createElement("script"); - redirect.innerHTML = `window.location = "${config.destination}";`; + redirect.innerHTML = `window.location = "${config.destination}";`; }; const viewTypes = {
diff --git a/src/state.js b/src/state.js @@ -38,7 +38,7 @@ class State { } _initWS() { - this.ws = new WebSocket(`ws://${window.location.hostname}/ws`); + this.ws = new WebSocket(`${window.location.protocol === "https:" ? "wss" : "ws"}://${window.location.hostname}/${window.location.pathname.split("/").slice(0, -1).join("/")}/ws`); this.ws.onclose = () => { this.connected = false; this._initWS(); @@ -53,11 +53,11 @@ class State { })); }; this.ws.onmessage = (msg) => { - /*clearInterval(this._timeout); + clearInterval(this._timeout); this._timeout = setTimeout(() => { this.ws.close(); this.ws.onclose(); - }, 2000);*/ + }, 2000); if (!msg.data.length) return; // keepalive this._setData(JSON.parse(msg.data)); };