ctucx.git: smartied

[nimlang] smarthome server

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 
import asyncdispatch, tables, times, options, tables
import ../types, ../vars, ../modbus, ../influx, ../utils

proc updatePowermeter (key: string, device: DeviceConfig) {.async.} =
  let deviceAddress    = device.address.get
  let currentTimestamp = toUnix(getTime())

  let voltage   = (await mb.asyncReadFloat(deviceAddress, 0)).isaRound(3)
  let current   = (await mb.asyncReadFloat(deviceAddress, 6)).isaRound(3)
  let frequency = (await mb.asyncReadFloat(deviceAddress, 70)).isaRound(3)
  let `import`  = (await mb.asyncReadFloat(deviceAddress, 72)).isaRound(3)
  let cosphi    = (await mb.asyncReadFloat(deviceAddress, 30)).isaRound(3)
  let power     = (await mb.asyncReadFloat(deviceAddress, 12)).isaRound(3)

  if server.config.serverConfig.influx.isSome:
    let config = server.config.serverConfig.influx.get

    if config.powermetersDatabase.isSome:
      if server.state[key].lastUpdated.isSome:
        if (currentTimestamp - server.state[key].lastUpdated.get) < 30:
          break

      var tags, fields = initTable[string, string]()

      tags["device"] = key

      fields["voltage"]   = $voltage
      fields["current"]   = $current
      fields["frequency"] = $frequency
      fields["import"]    = $`import`
      fields["cosphi"]    = $cosphi
      fields["power"]     = $power

      discard await config.insertDatabase(config.powermetersDatabase.get, key, tags, fields, currentTimestamp * 1000000000)

  server.state[key].voltage     = voltage
  server.state[key].frequency   = frequency
  server.state[key].`import`    = `import`
  server.state[key].cosphi      = cosphi
  server.state[key].power       = power
  server.state[key].lastUpdated = some(currentTimestamp)

  broadcastServerState()

proc updatePowermeters () {.async.} =
  for key, device in server.config.devices.pairs():
    if device.type != PowerMeter:
      continue

    try:
      await updatePowermeter(key, device)
    except:
      echo "Error[updatePowermeters]:\n", getCurrentExceptionMsg()

proc powermetersLoop () {.async.} =
  await sleepAsync(500)
  while true:
    await updatePowermeters()
    await sleepAsync(int(server.config.serverConfig.powermeterUpdateIntervalSec * 1000))

proc initModbusPowermeters* () =
  for key, device in server.config.devices.pairs():
    if device.type != PowerMeter:
      continue

    server.state[key] = DeviceState(type: PowerMeter)

  asyncCheck powermetersLoop()