# Log signatures for the KOTA sensorbox firmware. # # Derived from the firmware source (log strings, Status::set_status calls) and # checked against real captures (tests/fixtures). Patterns match the cleaned # line text, not the tag: the deployed v1.0 build logs some messages under # different tags than the source (e.g. SD mount under INFLUX_BUFFER). # # Fields: # id unique, "." # pattern Python regex (search). Named groups can be used in `title`. # Matched against the line with its error ID ("[E-SD-03] ") # removed. Rules without a pattern ("kota.*") are raised by # the engine from the structured KOTA: lines (diag/kota.py). # severity critical | error | warning | info | ignore # ignore = never shown (benign ESP_LOGE lines, LED-only rules) # title short technician-facing headline # meaning what it means, in plain words # actions what to do, in order (prefer no-unscrewing actions first) # explained_by list of rule ids; while one of them is active this finding # is shown as a consequence of it instead of a root cause # milestone boot milestone reached when the line is seen # clears finding ids resolved when this line is seen # led status LED colour this line sets (firmware Status::set_status) # led_from only change the LED if it currently has this colour # (Status::set_status_conditional) # split_by named group; one finding per distinct value (e.g. per sensor) # min_count finding becomes active only after this many occurrences # min_uptime_ms ignore occurrences earlier than this uptime # ---------------------------------------------------------------- milestones [[rule]] id = "boot.app_started" pattern = 'app_init: Project name:\s+kota-sensorboard' severity = "ignore" milestone = "app_started" led = "GREEN" # Status::init() -> STATUS_OK [[rule]] id = "boot.sd_mounted" pattern = 'SD card mounted successfully' severity = "ignore" milestone = "sd_mounted" [[rule]] id = "boot.env_loaded" pattern = 'Read INFLUX_URL from \.env file' severity = "ignore" milestone = "env_loaded" [[rule]] id = "boot.matter_started" pattern = 'ESP-Matter started successfully' severity = "ignore" milestone = "matter_started" [[rule]] id = "boot.local_wifi_mode" pattern = 'SSID/PASSWORD found in \.env' severity = "ignore" milestone = "local_wifi_mode" [[rule]] id = "boot.sensors_ready" # DeviceStatus::init installs the temperature sensor; it is the last init # step, and any earlier init failure aborts before reaching it. pattern = 'temperature_sensor: Range \[' severity = "ignore" milestone = "sensors_ready" [[rule]] id = "net.wifi_connected" pattern = 'sta ip: \d|got ip:|WIFI_SERVICE: Got IP address|IPv4 address changed|Interface IP Address changed' severity = "ignore" milestone = "wifi_connected" clears = ["matter.not_commissioned", "wifi.disconnected"] [[rule]] id = "matter.commissioned" pattern = 'MAIN: Commissioning complete|MAIN: Fabric is committed' severity = "ignore" milestone = "matter_commissioned" clears = ["matter.not_commissioned", "matter.commissioning_failed"] [[rule]] id = "net.time_synced" pattern = 'SNTP: Time synchronized' severity = "ignore" milestone = "time_synced" clears = ["rtc.clock_not_running", "net.dns_fail"] [[rule]] id = "influx.upload_ok" pattern = 'INFLUX: HTTP request performed, status code: 2\d\d' severity = "ignore" milestone = "data_uploaded" clears = ["influx.buffer_fail", "net.dns_fail", "net.tls_fail"] [[rule]] id = "influx.write_ok" pattern = 'Successfully wrote to Influx' severity = "ignore" milestone = "data_uploaded" led = "GREEN" led_from = "PURPLE" [[rule]] id = "ota.registered" pattern = 'Device registered successfully|OTA token loaded from NVS' severity = "ignore" milestone = "ota_registered" clears = ["ota.registration_failed"] [[rule]] id = "ota.checked" pattern = 'OTA_CLIENT: No update available' severity = "ignore" milestone = "ota_checked" clears = ["ota.check_failed"] led = "GREEN" led_from = "PURPLE" # ----------------------------------------------------------- benign E lines [[rule]] id = "benign.mac" pattern = 'Device MAC address' severity = "ignore" [[rule]] id = "benign.attr_cb" pattern = 'MAIN: Attribute update callback' severity = "ignore" [[rule]] id = "benign.zcl" pattern = 'chip\[ZCL\]: WRITE ERR|data_model: Cluster cannot be NULL' severity = "ignore" [[rule]] id = "benign.wifi_start" # Harmless Wi-Fi noise seen on every 1.0.16 boot: Matter asks for a connect # while the station is already connecting, and an unpaired box polls a # network it does not have yet (matter.not_commissioned covers that case). pattern = 'wifi:sta is connecting, return error|esp_wifi_connect\(\) failed: ESP_ERR_WIFI_CONN|Failed to get configured network when updating network status' severity = "ignore" [[rule]] id = "benign.connect_chain" # Transport-level echo of a failure that a more specific rule reports. pattern = 'esp-tls: Failed to open new connection|transport_base: Failed to open a new connection|HTTP_CLIENT: Connection failed, sock < 0|INFLUX: Failed to perform HTTP request: 0,|INFLUX_BUFFER: Failed to write chunk to Influx|OTA_CLIENT: Error ESP_ERR_HTTP_CONNECT at' severity = "ignore" # ------------------------------------------------------------------ network [[rule]] id = "matter.not_commissioned" pattern = 'CHIPoBLE advertising started|MAIN: Commissioning window opened' severity = "warning" title = "Box is not connected to Wi-Fi (not commissioned in Matter)" meaning = "The box is waiting to be added to a Matter network over Bluetooth. Until then it has no Wi-Fi, so it cannot upload data or receive firmware updates." actions = [ "Add the box in the customer's Matter app (Apple Home, Google Home, ...) by scanning the QR sticker, or enter the manual code printed under it.", "Use a 2.4 GHz Wi-Fi network; keep the phone close to the box during pairing.", "If pairing keeps failing: hold the Matter button 5 s (factory reset) and try again.", ] milestone = "ble_advertising" [[rule]] id = "matter.commissioning_failed" pattern = 'Commissioning failed, fail safe timer expired' severity = "error" title = "Matter pairing attempt failed" meaning = "A phone started adding the box to Matter but did not finish in time." actions = [ "Retry pairing from the Matter app with the phone next to the box.", "Check the Wi-Fi is 2.4 GHz and the password entered in the app is correct.", ] [[rule]] id = "net.dns_fail" pattern = '''couldn't get hostname for :(?P[\w.-]+)''' severity = "error" title = "No Internet: server names cannot be resolved" meaning = "The box could not look up a server name. Either it has no Wi-Fi connection, or the network has no working Internet/DNS." actions = [ "Check the site Wi-Fi has Internet (open a website on a phone connected to the same network).", "If the box was never paired: commission it in Matter first.", "Check the router does not block new devices (guest isolation, MAC filtering).", ] explained_by = ["matter.not_commissioned", "wifi.disconnected", "wifi.setup_portal"] [[rule]] id = "net.tls_fail" pattern = 'mbedtls_ssl_handshake returned|Failed to verify peer certificate|esp-tls-mbedtls: .*[Hh]andshake' severity = "error" title = "Secure connection to the server failed" meaning = "The box reached the server but the encrypted (HTTPS) connection failed. Common causes: wrong clock on the box, or a network that intercepts HTTPS (corporate proxy/firewall)." actions = [ "Try another network (e.g. phone hotspot) to rule out a firewall.", "Check the clock finding below: HTTPS needs the correct date.", ] explained_by = ["rtc.clock_not_running"] [[rule]] id = "wifi.disconnected" pattern = 'WiFi disconnected, retrying in' severity = "error" min_count = 3 title = "Box cannot connect to the configured Wi-Fi" meaning = "The Wi-Fi name/password from the SD card does not work: wrong password, network out of range, or not 2.4 GHz." actions = [ "Check SSID and PASSWORD in ENV.TXT (re-provision the SD card with the tool).", "Make sure the network is 2.4 GHz and in range.", ] [[rule]] id = "wifi.setup_portal" pattern = 'WiFi provisioning portal ready: connect to "(?P[^"]+)"' severity = "warning" title = "Box is in Wi-Fi setup mode (network {ssid})" meaning = "The box is hosting its own Wi-Fi network for configuration instead of connecting to the site Wi-Fi." actions = [ "Connect a phone to {ssid} and open http://sensorbox.local/ to enter the Wi-Fi details,", "or short-press the Matter button (< 2 s) to leave setup mode.", ] led = "WHITE" # ------------------------------------------------------------------- InfluxDB [[rule]] id = "influx.buffer_fail" pattern = 'Failed to write chunk with \d+ retries to Influx|MAIN: Failed to flush Influx buffer' severity = "error" title = "Measurements cannot be uploaded to InfluxDB" meaning = "Uploads keep failing, so readings are stored on the SD card and sent later. The LED turns purple (firmware v1.0 also restarts itself after about 2.5 minutes in this state)." actions = [ "Fix the network problem first (see the finding this is grouped under).", "Buffered data is uploaded automatically once the connection works.", ] explained_by = ["net.dns_fail", "net.tls_fail", "matter.not_commissioned", "wifi.disconnected", "wifi.setup_portal"] [[rule]] id = "influx.purple" pattern = 'Failed to write chunk with \d+ retries to Influx|Failed to flush buffer before writing|Failed to append new entry to buffer' severity = "ignore" led = "PURPLE" [[rule]] id = "influx.auth" pattern = 'INFLUX: Failed to perform HTTP request: (?P401|403)' severity = "critical" title = "InfluxDB rejected the token (HTTP {code})" meaning = "The box reaches the database but the INFLUX_TOKEN on the SD card is wrong or revoked." actions = [ "Re-provision the SD card with the current ENV.TXT (SD card is inside the case).", "If all boxes show this: the shared token was rotated - update ENV.TXT for everyone.", ] [[rule]] id = "influx.not_found" pattern = 'INFLUX: Failed to perform HTTP request: (?P404)' severity = "critical" title = "InfluxDB bucket or organisation not found (HTTP 404)" meaning = "INFLUX_URL on the SD card points to a bucket/org that does not exist." actions = ["Re-provision the SD card with the correct ENV.TXT."] [[rule]] id = "influx.server_error" pattern = 'INFLUX: Failed to perform HTTP request: (?P5\d\d)' severity = "warning" title = "InfluxDB server error (HTTP {code})" meaning = "The database server has a problem. The box is fine; data is buffered on the SD card." actions = ["Nothing to fix on the box. Report to the backend team if it persists."] [[rule]] id = "influx.bad_request" pattern = 'INFLUX: Bad request, check line protocol format' severity = "warning" title = "InfluxDB refused some measurements (HTTP 400)" meaning = "A measurement was malformed and dropped (firmware issue, not a hardware fault)." actions = ["Save the session log and send it to the firmware team."] [[rule]] id = "influx.env_missing" split_by = "key" pattern = 'Failed to read (?PINFLUX_URL|INFLUX_TOKEN) from \.env file' severity = "critical" title = "ENV.TXT on the SD card is missing {key}" meaning = "The box cannot start without the InfluxDB settings; it shows white and restarts." actions = ["Re-provision the SD card with the tool (SD card is inside the case)."] [[rule]] id = "influx.init_fail" pattern = 'MAIN: Failed to initialize Influx buffer' severity = "critical" title = "Data upload could not be initialised" meaning = "Start-up stopped because the InfluxDB settings could not be read from the SD card. The box restarts." actions = ["Re-provision the SD card with the tool (SD card is inside the case)."] explained_by = ["influx.env_missing", "sd.mount_fail", "sd.card_fail", "sd.env_open_fail"] led = "WHITE" # ----------------------------------------------------------------- SD card [[rule]] id = "sd.card_fail" pattern = 'Failed to initialize the card \((?P[^)]+)\)' severity = "critical" title = "SD card not detected ({err})" meaning = "The SD card does not respond: missing, not seated, or damaged. The box shows white and restarts." actions = [ "Open the case and re-seat the SD card.", "Try a freshly provisioned card.", ] led = "WHITE" [[rule]] id = "sd.mount_fail" pattern = 'Failed to mount filesystem' severity = "critical" title = "SD card is not formatted correctly" meaning = "The card responds but has no readable FAT32 file system." actions = ["Re-provision the card with the tool (FAT32, MBR) - SD card is inside the case."] led = "WHITE" [[rule]] id = "sd.env_open_fail" pattern = 'Failed to open \.env file for reading' severity = "critical" title = "ENV.TXT not found on the SD card" meaning = "The card is readable but the configuration file is missing." actions = ["Re-provision the card with the tool (SD card is inside the case)."] [[rule]] id = "sd.write_fail" pattern = 'Failed to (create buffer file|open buffer file for appending)' severity = "error" title = "Cannot write to the SD card" meaning = "Offline data cannot be stored: the card is full, write-protected or failing." actions = ["Replace / re-provision the SD card (inside the case)."] # --------------------------------------------------------------- RTC / I2C [[rule]] id = "rtc.init_failed" pattern = 'MAIN: Failed to initialize RTC: (?P\S+)' severity = "critical" title = "Clock chip (RTC) or I2C bus not responding ({err})" meaning = "The RTC is the first chip the firmware talks to over I2C, so this also appears when the I2C cable between the boards is loose or broken. LED blue, the box restarts." actions = [ "Open the case and check the I2C cable/connector between the boards.", "If the cable is fine: the RTC module is faulty.", ] explained_by = ["kota.i2c_stuck"] led = "BLUE" [[rule]] id = "rtc.clock_not_running" pattern = 'RTC is uninitialized, using current time as timestamp' severity = "warning" min_count = 5 title = "Clock is not set - sensor readings are on hold" meaning = "The clock chip answers but its clock is not running (it reads 1 Jan 2000; typical after its coin cell was removed or is empty), and there is no Internet time yet. Readings are held until the time is set, so no data is recorded." actions = [ "Give the box Internet access: the clock is set automatically on the first connection.", "If this comes back after every power-off: replace the RTC coin cell (inside the case).", ] explained_by = ["kota.rtc_stopped"] [[rule]] id = "i2c.errors" pattern = 'I2C (read|write) failed: (?P\S+)|Failed to add I2C device' severity = "error" min_count = 2 title = "I2C bus communication errors" meaning = "Sensors are not answering reliably on the I2C bus: loose connector, damaged cable, or a failing sensor." actions = ["Open the case and check the I2C cable/connectors between the boards."] explained_by = ["kota.i2c_stuck", "kota.sensor_missing"] # ------------------------------------------------------------------ sensors [[rule]] id = "sensor.init_failed" split_by = "sensor" pattern = 'MAIN: Failed to initialize (?PBME688|SEN66|AS7341|Microphone|Flicker sensor|DeviceStatus): (?P.+)' severity = "critical" title = "{sensor} failed to start" meaning = "Start-up stopped at the {sensor} sensor ({err}). LED red, the box restarts." actions = [ "Open the case and check the {sensor} connector/cable.", "If several sensors fail in turn: check the shared I2C cable.", ] explained_by = ["kota.i2c_stuck", "kota.sensor_missing"] led = "RED" [[rule]] id = "sensor.selfcheck_failed" split_by = "sensor" pattern = '(?PBME688|SEN66|AS7341|Microphone|Flicker sensor) self check failed' severity = "error" title = "{sensor} failed the post-update self-check" meaning = "After a firmware update the {sensor} did not work; the box rolls back to the previous firmware." actions = ["Check the {sensor} connector (inside the case), then power-cycle."] [[rule]] id = "sen66.not_ready" pattern = 'SEN66: (Failed while awaiting sensor ready|Self-check failed: Sensor not ready|Failed to read measurement)' severity = "error" title = "Air-quality sensor (SEN66) not delivering data" meaning = "The SEN66 answers but never reports a measurement." actions = ["Check the SEN66 cable (inside the case); the sensor may be faulty."] [[rule]] id = "bme688.read_fail" pattern = 'Failed to get (BME688 )?data from BME688|No new data available from BME688' severity = "warning" min_count = 3 title = "Temperature/humidity sensor (BME688) read errors" meaning = "The BME688 repeatedly fails to return a reading." actions = ["Check the BME688 connection (inside the case)."] [[rule]] id = "as7341.read_fail" pattern = 'Failed to read (spectral|basic counts) data' severity = "warning" min_count = 2 title = "Light sensor (AS7341) read errors" meaning = "The AS7341 repeatedly fails to return a reading." actions = ["Check the AS7341 connection (inside the case)."] [[rule]] id = "mic.silent" pattern = 'MICROPHONE: .*dB peak: -inf' severity = "warning" min_count = 2 title = "Microphone records pure silence" meaning = "Every audio sample is zero. A real room is never perfectly silent, so the microphone or its wiring is likely faulty." actions = [ "Make some noise near the box and watch whether this finding keeps growing.", "If it does: check the microphone board/cable (inside the case).", ] [[rule]] id = "mic.read_fail" pattern = 'Failed to read samples' severity = "error" title = "Microphone read error" meaning = "The audio interface returned an error." actions = ["Check the microphone board/cable (inside the case)."] [[rule]] id = "gather.stalled" pattern = 'tasks still running, waiting' severity = "warning" min_uptime_ms = 180000 min_count = 5 title = "Sensor readings are stuck" meaning = "A sensor has not finished its reading for minutes (the first 2 minutes of warm-up are normal)." actions = ["See the grouped cause, or note which sensor stopped logging and check its cable."] explained_by = ["rtc.clock_not_running", "sen66.not_ready"] # ---------------------------------------------------------- OTA / firmware [[rule]] id = "ota.registration_failed" pattern = 'Device registration failed' severity = "warning" title = "Box is not registered for firmware updates" meaning = "The box could not reach the update server (bin.kota-app.com) to register, so it will not receive new firmware." actions = ["Fix the network problem; registration is retried automatically every few seconds."] explained_by = ["net.dns_fail", "net.tls_fail", "matter.not_commissioned", "wifi.disconnected", "wifi.setup_portal"] [[rule]] id = "ota.check_failed" pattern = 'Failed to check for updates|OTA Update check failed with status code: (?P\d+)' severity = "error" title = "Firmware update check failed" meaning = "The update server could not be reached or refused the request. LED purple." actions = ["Fix the network problem; the check is retried every 15 minutes."] explained_by = ["net.dns_fail", "net.tls_fail", "matter.not_commissioned", "wifi.disconnected"] led = "PURPLE" [[rule]] id = "ota.unauthorized" pattern = 'Unauthorized, clearing saved token' severity = "warning" title = "Update server did not accept the box - it will re-register" meaning = "The saved update token was rejected; the box registers again automatically." actions = ["Nothing to do unless it repeats. Then report the box MAC to the backend team."] [[rule]] id = "ota.updating" pattern = 'New update available, starting OTA update' severity = "info" title = "Firmware update is downloading - do not switch off" meaning = "The box found new firmware and is installing it (LED yellow). It restarts when done." actions = ["Wait. Do not switch the power off."] milestone = "ota_update_started" led = "YELLOW" [[rule]] id = "ota.update_failed" pattern = 'OTA update failed: (?P\S+)' severity = "error" title = "Firmware update failed ({err})" meaning = "The download or installation was interrupted; the box keeps its current firmware and retries later." actions = ["Check the network is stable; the update is retried automatically."] [[rule]] id = "ota.update_ok" pattern = 'OTA update successful, rebooting' severity = "info" title = "Firmware update installed - restarting" meaning = "New firmware was installed. After the restart it runs a self-check (LED orange, ~2.5 min)." actions = ["Wait for green."] milestone = "ota_update_done" [[rule]] id = "ota.selfcheck" pattern = 'Device is in selfcheck mode' severity = "info" title = "Post-update self-check running (~2.5 min)" meaning = "The new firmware is testing all sensors before it is accepted (LED orange)." actions = ["Wait. Do not switch off."] led = "ORANGE" [[rule]] id = "ota.selfcheck_failed" pattern = 'Failing selfcheck: (?P.+)' severity = "error" title = "Update self-check failed: {reason}" meaning = "The new firmware rejected itself; the box rolls back to the previous version." actions = ["Check the named sensor (inside the case), then power-cycle."] led = "RED" [[rule]] id = "ota.selfcheck_passed" pattern = 'Passing selfcheck' severity = "ignore" milestone = "ota_update_accepted" led = "GREEN" [[rule]] id = "ota.reset_during_update" pattern = 'Device was reset during update' severity = "warning" title = "Box was switched off during a firmware update" meaning = "An update was interrupted; the box reports it and retries." actions = ["Leave the box powered while the LED is yellow or orange."] # --------------------------------------------------------------- system [[rule]] id = "sys.out_of_resources" pattern = 'Failed to create (task for sensor|gather task|main gather task)' severity = "error" title = "Firmware ran out of memory" meaning = "The firmware could not start an internal task (LED red); it restarts itself after 30 s." actions = ["Power-cycle. If it repeats, save the session log for the firmware team."] led = "RED" [[rule]] id = "sys.factory_reset" pattern = 'Factory reset button pressed|Factory resetting device' severity = "warning" title = "Factory reset triggered with the Matter button" meaning = "The box forgets its Matter network and must be paired again with the QR sticker." actions = ["Re-commission the box in the Matter app."] led = "WHITE" [[rule]] id = "mic.disabled" pattern = 'MICROPHONE: Microphone is in shutdown state' severity = "info" title = "Microphone is switched off - no noise measurements" meaning = "The microphone switch on the back of the case (just above the power switch) is OFF, so noise levels are not recorded." actions = ["If this box should measure noise: flip the microphone switch (back of the case, above the power switch). No restart needed - it is picked up within about 10 s."] [[rule]] id = "gather.empty_reading" pattern = 'SENSOR_GATHERER: Failed to get line protocol from sensor' severity = "warning" min_count = 2 title = "A sensor returned no data" meaning = "One of the sensors skipped its reading; the preceding log lines name the sensor." actions = ["Check the log lines just before this message for the sensor name."] explained_by = ["mic.disabled", "mic.read_fail", "bme688.read_fail", "as7341.read_fail", "rtc.clock_not_running"] # ------------------------------------------------ structured KOTA: lines # Firmware 1.0.16+ reports its state as "KOTA: key=value ..." lines. # These rules have no pattern: the engine raises them from the parsed fields # (see diag/kota.py for the line formats). Named values in {braces} come # from the line's fields. [[rule]] id = "kota.i2c_stuck" severity = "critical" title = "I2C bus stuck (SDA={sda}, SCL={scl})" meaning = "A data line of the sensor bus is held low before any sensor is used: a shorted or broken sensor cable, or a faulty sensor. LED blue, 2 pulses." actions = [ "Open the case and check the I2C cable between the boards.", "Unplug the sensors one by one to find the one holding the bus.", ] [[rule]] id = "kota.sensor_missing" split_by = "sensor" severity = "error" title = "{sensor} does not answer on the I2C bus" meaning = "The start-up scan did not find the {sensor} at address {addr}. The other sensors answer, so the bus itself works: the {sensor} cable, connector or the sensor is faulty." actions = [ "Open the case and re-seat the {sensor} cable/connector.", "If it is still missing after a restart: replace the {sensor}.", ] explained_by = ["kota.i2c_stuck"] [[rule]] id = "kota.rtc_read_failed" severity = "critical" title = "Clock chip (RTC) cannot be read ({err})" meaning = "The DS1307 clock does not answer. It is on the shared I2C bus, so a loose cable also causes this." actions = [ "Open the case and check the I2C cable/connector between the boards.", "If the cable is fine: replace the RTC module.", ] explained_by = ["kota.i2c_stuck", "kota.sensor_missing"] [[rule]] id = "kota.rtc_stopped" severity = "warning" title = "Clock chip was stopped at start-up (time {time})" meaning = "The RTC answers but its clock was not running - typical after its coin cell was removed or is empty. It is set again from the Internet once the box is online; until then readings are held." actions = [ "Give the box Internet access: the clock is set automatically.", "If this comes back after every power-off: replace the RTC coin cell (inside the case).", ] [[rule]] id = "kota.rtc_not_ticking" severity = "error" title = "Clock chip does not keep time" meaning = "The clock was set from the Internet, but 2 s later it had not advanced correctly (running={running}, delta={delta}). The RTC module or its crystal is faulty." actions = ["Replace the RTC module (inside the case)."] [[rule]] id = "kota.sd_unmounted" severity = "critical" title = "SD card not mounted ({err})" meaning = "The firmware cannot use the SD card: missing, not seated, not FAT32 or damaged. Without it the box cannot read ENV.TXT. LED white, fast blinking." actions = [ "Open the case and re-seat the SD card.", "Re-provision the card with the tool (FAT32, MBR) or try a freshly provisioned card.", ] [[rule]] id = "kota.sd_not_fat32" severity = "warning" title = "SD card file system is {fs}, not FAT32" meaning = "The card works, but the provisioning standard is FAT32." actions = ["Re-provision the card with the tool when convenient."] [[rule]] id = "kota.sd_full" severity = "warning" title = "SD card is almost full ({free} free)" meaning = "Offline readings may soon not be stored." actions = ["Check the buffered readings upload (Internet access), or replace the card."] [[rule]] id = "kota.buffer_backlog" severity = "warning" title = "{lines} readings are waiting on the SD card to be uploaded" meaning = "The box stored readings while it could not upload them. They are sent automatically once the connection works." actions = ["Fix the connection problem if there is one; watch the health line: the buffer should shrink."] explained_by = ["kota.wifi_down", "matter.not_commissioned", "status.conn", "status.conn.1", "net.dns_fail", "influx.auth"] [[rule]] id = "kota.wifi_down" severity = "error" min_count = 2 title = "Box has no Wi-Fi connection" meaning = "The periodic health report says Wi-Fi is disconnected, so the box cannot upload data or receive updates." actions = [ "Check the site Wi-Fi is on, 2.4 GHz and in range.", "Matter boxes: check the box is still paired in the Matter app. Wi-Fi-from-SD boxes: check SSID/PASSWORD in ENV.TXT.", ] explained_by = ["matter.not_commissioned", "wifi.setup_portal", "wifi.disconnected"] [[rule]] id = "kota.weak_wifi" severity = "warning" title = "Weak Wi-Fi signal ({rssi} dBm)" meaning = "The connection works but the signal is weak; uploads may fail intermittently. Below about -75 dBm is unreliable." actions = ["Move the box or the access point closer, or add a repeater."] [[rule]] id = "kota.time_invalid" severity = "warning" title = "Box has no valid time - readings are on hold" meaning = "Readings are only stored with a valid timestamp. The time comes from the RTC or from the Internet." actions = [ "Give the box Internet access so it can set its clock.", "If it is online and this persists: check the RTC findings.", ] explained_by = ["kota.wifi_down", "matter.not_commissioned", "kota.rtc_not_ticking", "kota.rtc_read_failed", "kota.rtc_stopped", "rtc.clock_not_running", "net.dns_fail"] [[rule]] id = "kota.no_upload" severity = "error" title = "Connected to Wi-Fi, but no data uploaded yet (5+ min)" meaning = "The box has Wi-Fi but no upload to InfluxDB has succeeded yet." actions = [ "Check the network has Internet (open a website on a phone on the same Wi-Fi).", "Check INFLUX_URL / INFLUX_TOKEN in ENV.TXT (re-provision the SD card).", ] explained_by = ["kota.time_invalid", "influx.auth", "influx.not_found", "status.conn.1", "net.dns_fail", "net.tls_fail", "influx.server_error"] [[rule]] id = "kota.low_heap" severity = "warning" title = "Firmware memory is low ({heap} bytes free)" meaning = "Internal memory is running low; the firmware may fail to start tasks and restart." actions = ["Save the session log for the firmware team."] [[rule]] id = "kota.ota_unregistered" severity = "warning" min_count = 3 title = "Online, but not registered for firmware updates" meaning = "The box has Wi-Fi but is still not registered with the update server, so it will not receive new firmware." actions = ["Check the network allows HTTPS to bin.kota-app.com; registration is retried automatically."] explained_by = ["ota.registration_failed", "net.dns_fail", "net.tls_fail"]