ctucx.git: smartie-pwa

[js] smarthome web-gui

commit a624a9a2c48d4c386de401f4cf2fba9ebe16ec40
parent 6e32919abc2924360b81ca5a0aa4829951157a4e
Author: Milan Pässler <me@pbb.lc>
Date: Tue, 4 Jun 2019 00:59:40 +0200

replace gosdm
2 files changed, 86 insertions(+), 51 deletions(-)
M
src/power-meter.js
|
12
++++++------
M
websocket-relay/server.js
|
125
++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
diff --git a/src/power-meter.js b/src/power-meter.js
@@ -55,14 +55,14 @@ class PowerMeter extends LitElement {
 							<div class="table-column">Frequency</div>
 							<div class="table-column">Import</div>
 						</div>
-						${Object.entries(state.data.powermeter).map(([_, d]) => html`
+						${state.data.powermeter.map(d => html`
 							<div class="table-row">
 								<div class="table-column">${d.name}</div>
-								<div class="table-column">${round(d.Voltage.L1, 2)} V</div>
-								<div class="table-column">${round(d.Power.L1, 2)} W</div>
-								<div class="table-column">${round(d.Cosphi.L1, 2)}</div>
-								<div class="table-column">${round(d.Frequency, 2)}</div>
-								<div class="table-column">${round(d.TotalImport, 2)} kWh</div>
+								<div class="table-column">${round(d.values.voltage, 2)} V</div>
+								<div class="table-column">${round(d.values.power, 2)} W</div>
+								<div class="table-column">${round(d.values.cosphi, 2)}</div>
+								<div class="table-column">${round(d.values.frequency, 2)}</div>
+								<div class="table-column">${round(d.values.import, 2)} kWh</div>
 							</div>
 						`)}
 					</div>
diff --git a/websocket-relay/server.js b/websocket-relay/server.js
@@ -1,5 +1,6 @@
 "use strict";
 
+const http      = require("http");
 const net       = require("net");
 const modbus    = require("modbus-tcp");
 const WebSocket = require("ws");

@@ -11,7 +12,18 @@ function broadcastState() {
 	wss.broadcast(JSON.stringify(state));
 }
 
-const wss = new WebSocket.Server({ port: 8080 });
+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) {

@@ -27,7 +39,7 @@ wss.on('connection', function connection(ws) {
 
 setInterval(function sendKeepalive() {
 	wss.broadcast("");
-}, 2000);
+}, 1000);
 
 /* lights */
 

@@ -106,53 +118,76 @@ const counters = [
 	{ id: 50, name: "Sonstiges" },
 ];
 
-let timeout;
-let gosdm;
+const registers = {
+	voltage: 0,
+	power: 12,
+	frequency: 70,
+	import: 72,
+	cosphi: 30,
+};
 
-async function initWS() {
-	state.powermeter = {};
-	await Promise.all(counters.map(async function(counter) {
-		const d = await fetch(`http://127.0.0.1/gosdm/last/${counter.id}`)
-			.then(resp => resp.json());
+function unixTimestamp() {
+	return Math.floor(Number(new Date()) / 1000);
+}
 
-		state.powermeter[d.ModbusDeviceId] = {
-			...d,
-			name: counter.name,
-		};
-	}));
-	broadcastState();
+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();
 
-	gosdm = new WebSocket(`ws://127.0.0.1/gosdm/ws`);
-	gosdm.onclose = () => {
-		state.powermeter = undefined;
-		broadcastState();
-		initWS();
-	};
-	gosdm.onmessage = (msg) => {
-		clearTimeout(timeout);
-		timeout = setTimeout(() => {
-			gosdm.close();
-		}, 5000);
-
-		const m = JSON.parse(msg.data);
-		if (!m.IEC61850) return;
-
-		const d = state.powermeter[m.DeviceId];
-
-		if (m.IEC61850 === "Frequency") {
-			d.Frequency = m.Value;
-		} else if (m.IEC61850 === "VoltageL1") {
-			d.Voltage.L1 = m.Value;
-		} else if (m.IEC61850 === "CosphiL1") {
-			d.Cosphi.L1 = m.Value;
-		} else if (m.IEC61850 === "PowerL1") {
-			d.Power.L1 = m.Value;
-		} else if (m.IEC61850 === "Import") {
-			d.TotalImport = m.Value;
+	// 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() {
+	const client = new modbus.Client();
+	const socket = new net.Socket();
+
+
+	socket.connect({'host': '192.168.1.1', 'port': 502 });
+	client.pipe(socket);
+
+	for (let counter of state.powermeter) {
+		for (let key of Object.keys(registers)) {
+			//try {
+				counter.values[key] = await getFloat32Register(counter.id, registers[key], client, socket);
+				counter.lastUpdated = unixTimestamp();
+			//} catch(e) {}
 		}
+	}
+	socket.end();
 
-		broadcastState();
-	};
+	broadcastState();
 }
 
-initWS();
+state.powermeter = counters.map(function(c) {
+	return {
+		...c,
+		values: Object.keys(registers).reduce(function(result, key) {
+			result[key] = 0;
+			return result;
+		}, {}),
+		lastUpdated: unixTimestamp(),
+	};
+});
+
+setInterval(fetchValues, 60000);
+fetchValues();
+
+server.listen(8080);