ctucx.git: solax2mqtt

Publish data from Solax solar inverters via MQTT

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
42 
43 
44 
45 
46 
47 
48 
49 
50 
51 
52 
53 
54 
55 
56 
57 
58 
59 
60 
61 
62 
63 
64 
65 
66 
67 
68 
69 import std/[asyncdispatch]
import std/[os, posix]
import std/[tables, json, options]
import std/math
import nmqtt

import types, solax

var mqttContext*       {.threadvar.} : MqttCtx

proc ctrlCHook* () {.noconv.} =
  echo "Ctrl+C fired! \nStopping Server now!"
  waitFor mqttContext.disconnect()
  quit()


proc updateData (config: Config) {.async.} =
  await sleepAsync(500)
  
  while true:
    try:
      let solaxData = await getSolaxData(config.ip, config.password)

      if mqttContext.isConnected:
        await mqttContext.publish(config.mqtt.topic, $solaxData, 2, true)

        for key, value in solaxData:
          await sleepAsync(250)
          await mqttContext.publish(config.mqtt.topic & "/" & key, $value, 2, true)

    except:
      echo "Error[updateData]:\n", getCurrentExceptionMsg()

    await sleepAsync(int(config.updateInterval * 1000))


proc main () {.async.} =
  setControlCHook(ctrlCHook)

  onSignal(SIGTERM):
    echo "Got SIGTERM! \nStopping Server 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("solax2mqtt")
  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 updateData(config)

  runForever()

waitFor main()