commit a624a9a2c48d4c386de401f4cf2fba9ebe16ec40
parent 6e32919abc2924360b81ca5a0aa4829951157a4e
Author: Milan Pässler <me@pbb.lc>
Date: Tue, 4 Jun 2019 00:59:40 +0200
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
|
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);