commit e6e7f78bf6b3d7a968f9a179f8d32565f4fdc30b
parent daaedb68ee030901e1d51e8f20062fa4829b005a
Author: Milan Pässler <me@pbb.lc>
Date: Sun, 21 Jul 2019 11:39:33 +0200
parent daaedb68ee030901e1d51e8f20062fa4829b005a
Author: Milan Pässler <me@pbb.lc>
Date: Sun, 21 Jul 2019 11:39:33 +0200
lacrosse
7 files changed, 101 insertions(+), 19 deletions(-)
diff --git a/config.json b/config.json @@ -15,6 +15,16 @@ "type": "PowerMeter", "model": "SDM120", "address": 60 + }, + "lacrosse-21": { + "type": "LacrosseTempSensor", + "id": "21", + "address": 21 + }, + "lacrosse-31": { + "type": "LacrosseTempSensor", + "id": "31", + "address": 31 } }, "clientConfigs": { @@ -86,7 +96,9 @@ "httpPort": 5000, "tcpPort": 5001, "wsPort": 5002, - "modbusAddr": "192.168.1.1", - "modbusPort": 502, + "modbusAddr": "127.0.0.1", + "modbusPort": 5502, + "lacrosseAddr": "127.0.0.1", + "lacrossePort": 2342, "powermeterUpdateIntervalSec": 20 }
diff --git a/src/backend_lacrosse.nim b/src/backend_lacrosse.nim @@ -0,0 +1,51 @@ +import asyncdispatch +import asyncnet +import types +import tables +import util +import json +import vars +import times + +proc lacrosseHandleLoop(sock: AsyncSocket) {.async.} = + while true: + try: + let line = await sock.recvLine() + if line == "": + break + + let msg = parseJson(line).to(LacrosseMessage) + + for key, device in server.config.devices.pairs(): + if device.type != LacrosseTempSensor: + continue + if device.id != msg.id: + continue + + server.state[key].humidity = msg.hum + server.state[key].temperature = msg.temp + server.state[key].weakBattery = bool(msg.weakBatt) + server.state[key].lastUpdated2 = toUnix(getTime()) + + broadcast($(%*server.state)) + except: + let e = getCurrentException() + echo("error while updating lacrosse: ", e.msg) + +proc lacrosseConnectLoop() {.async.} = + while true: + try: + let sock = await asyncnet.dial(server.config.lacrosseAddr, Port(server.config.lacrossePort)) + await lacrosseHandleLoop(sock) + except: + let e = getCurrentException() + echo("error while connectiong to lacrosse relay: ", e.msg) + await sleepAsync(1000) + +proc initBackendLacrosse*() = + for key, device in server.config.devices.pairs(): + if device.type != LacrosseTempSensor: + continue + server.state[key] = DeviceState(type: LacrosseTempSensor) + + asyncCheck lacrosseConnectLoop()
diff --git a/src/backend_powermeter.nim b/src/backend_powermeter.nim @@ -25,7 +25,6 @@ proc updatePowermeter(key: string, device: DeviceConfig) {.async.} = broadcast($(%*server.state)) proc updatePowermeters() {.async.} = - GC_fullCollect() echo "updating powermeters" for key, device in server.config.devices.pairs(): if device.type != PowerMeter: @@ -37,24 +36,17 @@ proc updatePowermeters() {.async.} = let e = getCurrentException() echo("error while updating powermeter ", key, ": ", e.msg) -proc timerFunc(fd: AsyncFD): bool {.gcsafe.} = - let fut = updatePowermeters() - fut.addCallback(proc () = - addTimer(int(server.config.powermeterUpdateIntervalSec * 1000), true, timerFunc) - ) - return false +proc powermetersLoop() {.async.} = + await sleepAsync(500) + while true: + await updatePowermeters() + await sleepAsync(int(server.config.powermeterUpdateIntervalSec * 1000)) proc initBackendPowermeter*() = - addTimer(1000, true, timerFunc) for key, device in server.config.devices.pairs(): if device.type != PowerMeter: continue - server.state[key] = DeviceState( - type: PowerMeter, - power: 0f, - cosphi: 0f, - voltage: 0f, - `import`: 0f, - frequency: 0f - ) + server.state[key] = DeviceState(type: PowerMeter) + + asyncCheck powermetersLoop()
diff --git a/src/backend_relayboard.nim b/src/backend_relayboard.nim @@ -18,4 +18,8 @@ proc updateRelayboards() {.async.} = echo("error while updating relayboard ", key, ": ", e.msg) proc initBackendRelayboard*() = + for key, device in server.config.devices.pairs(): + if device.type != RelayBoard: + continue + server.state[key] = DeviceState(type: RelayBoard) asyncCheck updateRelayboards()
diff --git a/src/frontend_ws.nim b/src/frontend_ws.nim @@ -37,5 +37,10 @@ proc processWsClient(req: Request) {.async.} = proc serveWs*() {.async.} = registerBroadcastHandler(broadcast) wsClients = @[] + + addTimer(1000, false, proc (fd: AsyncFD): bool {.gcsafe.} = + broadcast("") + ) + var httpServer = newAsyncHttpServer() await httpServer.serve(Port(server.config.wsPort), processWsClient)
diff --git a/src/smartied.nim b/src/smartied.nim @@ -4,6 +4,7 @@ import frontend_ws import frontend_http import backend_powermeter import backend_relayboard +import backend_lacrosse import types import modbus import json @@ -18,6 +19,7 @@ initUtil() initModbus() initBackendPowermeter() initBackendRelayboard() +initBackendLacrosse() asyncCheck serveTcp() asyncCheck serveWs()
diff --git a/src/types.nim b/src/types.nim @@ -5,7 +5,8 @@ import sequtils type DeviceType* = enum PowerMeter, - RelayBoard + RelayBoard, + LacrosseTempSensor type DeviceConfig* = object address*: uint8 @@ -15,6 +16,8 @@ type DeviceConfig* = object of RelayBoard: firstRegister*: uint8 count*: uint8 + of LacrosseTempSensor: + id*: string type Config* = object tcpPort*: uint16 @@ -22,6 +25,8 @@ type Config* = object httpPort*: uint16 modbusAddr*: string modbusPort*: uint16 + lacrosseAddr*: string + lacrossePort*: uint16 powermeterUpdateIntervalSec*: uint devices*: Table[string, DeviceConfig] clientConfigs*: Table[string, JsonNode] @@ -37,6 +42,11 @@ type DeviceState* = object lastUpdated*: int64 of RelayBoard: relays*: seq[bool] + of LacrosseTempSensor: + humidity*: float32 + temperature*: float32 + weakBattery*: bool + lastUpdated2*: int64 type Server* = object state*: Table[string, DeviceState] @@ -68,5 +78,11 @@ type Response* = object status*: ResponseStatus data*: JsonNode +type LacrosseMessage* = object + id*: string + temp*: float32 + hum*: float32 + weakBatt*: int + type modbus* = pointer