Alerts & Webhook

flowchart TD
    A[Sensor Read] --> B[EventBus publish]
    B --> C[rules.lua callback]
    C --> D{Threshold crossed?}
    D -->|No| E[Clear sustain counter]
    D -->|Yes| F[Increment sustain]
    F --> G{N readings OR T minutes?}
    G -->|Not yet| H[Wait for next read]
    G -->|Yes| I{Cooldown expired?}
    I -->|No| H
    I -->|Yes| J[notify]
    J --> K[Log.warn]
    J --> L[Telegram.broadcast]
    J --> M[MQTT publish alert]

Lua Alert Engine

Alert logic lives in /scripts/rules.lua on LittleFS - hot-reloadable without recompiling. The firmware provides the bindings; the script defines the rules.

Available Lua bindings for alerts:

Function Description
EventBus.subscribe(event, fn) Subscribe to sensor events (temperature, current, battery)
Telegram.send(chat_id, msg) Send to a specific Telegram chat
Telegram.broadcast(msg) Send to all configured chat_ids
MQTT.publish(topic, payload) Publish alert to MQTT
Config.get(key) Read config values (supports dot notation and array indices)
Node.uptime() Current uptime in ms (for cooldown/sustain timing)
Node.setTimeout(ms, fn) Delayed execution (e.g. boot alerts after WiFi ready)
Log.warn(msg) Log alert to serial/WebSocket terminal

Telegram config (config.json):

"telegram": {
  "bot_token": "your-bot-token",
  "chat_ids": ["12345678910", "-10987654321"]
}

Both array and object format supported for chat_ids:

"chat_ids": {"user1": "12345678910", "user2": "-10987654321"}

Object format enables per-recipient routing in Lua:

local user1 = Config.get("telegram.chat_ids.user1")
Telegram.send(user1, "critical alert")

Example rules.lua

local prefix = Config.get("mqtt.topic_prefix")
local unit   = Config.get("temperature.unit") or "C"

local sustain = {}
local cooldown = {}
local COOLDOWN_MS = 900000   -- 15 minutes
local TEMP_SUSTAIN = 5       -- 5 readings or 5 minutes

local function can_alert(key)
  local now = Node.uptime()
  if cooldown[key] and (now - cooldown[key]) < COOLDOWN_MS then
    return false
  end
  cooldown[key] = now
  return true
end

local function notify(msg)
  Log.warn(msg)
  Telegram.broadcast(msg)
  MQTT.publish(prefix .. "/alert", msg)
end

-- Temperature: sustained low temp alert
EventBus.subscribe("temperature", function(data)
  for _, s in ipairs(data.sensors) do
    local key = "low_temp:" .. s.name
    if s.name == "House Supply" and s.temp_c <= 55 then
      sustain[key] = (sustain[key] or 0) + 1
      if sustain[key] >= TEMP_SUSTAIN and can_alert(key) then
        notify(s.name .. ": " .. s.temp .. unit .. " - Low temp")
        sustain[key] = 0
      end
    else
      sustain[key] = 0
    end
  end
end)

-- Battery: immediate alert
EventBus.subscribe("battery", function(data)
  if data.present and data.percent <= 20 and not data.charging then
    if can_alert("battery_low") then
      notify("Battery low: " .. data.percent .. "%")
    end
  end
end)

EventBus data format (temperature):

{
  "sensors": [
    { "name": "House Supply", "temp_c": 54.4, "temp": 129.9, "address": "28..." }
  ]
}
  • temp_c - always Celsius (use for thresholds)
  • temp - display unit (C or F depending on temperature.unit config)

Sustain pattern: alert only fires after N consecutive readings cross the threshold. Prevents false alerts from single sensor glitches or brief temperature dips when loading fuel.

Cooldown pattern: after an alert fires, the same key won’t fire again for COOLDOWN_MS milliseconds. Prevents alert spam when a condition persists.


Webhook

Optional HTTP POST fired from Lua or TelegramModule on every alert:

"webhook": {
  "url": "http://homeassistant.local:8123/api/webhook/module-alert",
  "message_template": "{{value}}"
}

{{value}} is replaced with the full alert message. Supports http:// and https://. Leave url empty to disable.


Boot alert (main.lua)

Send a Telegram message when the node starts (delayed 10s for WiFi/firewall):

Node.setTimeout(10000, function()
  local name = Config.get("device.name") or "unknown"
  local ip = Node.ip() or "no IP"
  Telegram.broadcast(name .. " booted - " .. ip)
end)

Home Assistant automation for MQTT alerts

automation:
  - alias: "Thesada Node Alert - Telegram"
    triggers:
      - trigger: mqtt
        topic: thesada/node/alert
    actions:
      - action: notify.send_message
        data:
          entity_id: notify.telegram_notify
          message: "{{ trigger.payload }}"

Thesada - CERN-OHL-P-2.0 / GPL-3.0-only / CC BY 4.0

This site uses Just the Docs, a documentation theme for Jekyll.