import std/asyncdispatch import std/[os, posix, threadpool] import std/[tables, json, options] import nmqtt import types var mqttContext* {.threadvar.} : MqttCtx proc CtrlCHook* () {.noconv.} = echo "Ctrl+C fired! \nStopping now!" waitFor mqttContext.disconnect() quit() proc asyncReadLine*(file: File): Future[string] = var fut = newFuture[string]() var flowVar = spawn file.readLine() addTimer(50, false, proc(fd: AsyncFD): bool = if flowVar.isReady(): fut.complete(^flowVar) return true ) return fut proc readSerial(serial: string) {.async.} = let file = open(serial, fmReadWrite) while true: try: let line = await file.asyncReadLine() let data = parseJson(line) let json = %* { "id": data["id"].getStr, "temperature": data["temp"].getFloat, "newBattery": data["newBatt"].getBool, "weakBattery": data["weakBatt"].getBool } if (data["hum"].getInt != 106): json.add("humidity", newJInt(data["hum"].getInt)) if mqttContext.isConnected: await mqttContext.publish("lacrosse2mqtt/" & json["id"].getStr, $json, 2, true) await mqttContext.publish("lacrosse2mqtt/" & json["id"].getStr & "/temperature", $json["temperature"], 2, true) if (data["hum"].getInt != 106): await mqttContext.publish("lacrosse2mqtt/" & json["id"].getStr & "/humidity", $json["humidity"], 2, true) await mqttContext.publish("lacrosse2mqtt/" & json["id"].getStr & "/newBattery", $json["newBattery"], 2, true) await mqttContext.publish("lacrosse2mqtt/" & json["id"].getStr & "/weakBattery", $json["weakBattery"], 2, true) except JsonParsingError: continue except: let e = getCurrentException() msg = getCurrentExceptionMsg() echo "Got exception ", repr(e), " with message ", msg proc main () {.async.} = setControlCHook(CtrlCHook) onSignal(SIGTERM): echo "Got SIGTERM! \nStopping now!" waitFor mqttContext.disconnect() quit() var configFile = "./config.json" if getEnv("CONFIG_PATH") != "": configFile = getEnv("CONFIG_PATH") if not fileExists(configFile): echo "Config file not found" quit() let config = parseFile(configFile).to(Config) mqttContext = newMqttCtx("lacrosse2mqtt") mqttContext.set_host(config.mqtt.host, config.mqtt.port) mqttContext.set_verbosity(1) if (config.mqtt.username.isSome and config.mqtt.password.isSome): mqttContext.set_auth(config.mqtt.username.get, config.mqtt.password.get) await mqttContext.start() asyncCheck readSerial(config.serialDevice) asyncCheck main() runForever()