Commit Graph

18 Commits

Author SHA1 Message Date
Yellowcooln 1881ad9b93 feat: derive modem battery percent from voltage 2026-06-15 20:39:22 -04:00
Yellowcooln 5aebb4dd24 style: format sensor manager polling change 2026-06-15 19:56:10 -04:00
Yellowcooln 1c186d7feb fix: throttle only pyMC modem sensor polling 2026-06-15 18:34:05 -04:00
Yellowcooln f2b7d254a7 fix: slow sensor polling to 60 seconds 2026-06-15 18:32:12 -04:00
Yellowcooln 5d3733a960 fix: satisfy pre-commit for modem HTTP telemetry 2026-06-14 20:08:29 -04:00
Yellowcooln dde487bce3 fix: add generic PyMC modem stats sensor 2026-06-14 18:00:15 -04:00
Lloyd 0c33483947 refactor: clean up import statements and whitespace in local_cli, base, and update_endpoints modules 2026-05-27 20:16:23 +01:00
Lloyd 45a44eb47b Refactor test cases and base code for consistency and readability
- Updated byte representations in tests to use lowercase hex format for consistency.
- Reformatted code for better readability, including line breaks and indentation adjustments.
- Consolidated multiple lines into single lines where appropriate to enhance clarity.
- Ensured that all test cases maintain consistent formatting and style across the test suite.
2026-05-27 20:15:10 +01:00
Zack Carlson e20eaa7f02 feat: add LAFVIN UPS Module 3S sensor plugin (lafvin_ups_3s)
Adds a new sensor type for the LAFVIN UPS Module 3S, an INA219-based
uninterruptible power supply for Raspberry Pi. Reports pack voltage,
current, power, estimated state-of-charge, and charge state for a
3S Li-ion/LiPo battery configuration (9.0–12.6 V range).

The INA219 address defaults to 0x41 (as wired on the LAFVIN board)
and shunt resistance is configurable for accurate current readings.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 11:09:47 -07:00
Zack Carlson 6e89272bce Add Waveshare UPS HAT (E) sensor plug-in
The HAT (E) uses a dedicated BMS MCU (not an INA219) at I2C address 0x2D.
It exposes charge state, pack voltage/current, per-cell voltages, remaining
capacity in mAh, and time-to-empty/full estimates directly via I2C registers.

Tested on Raspberry Pi 4B with pyMC_Repeater running pymc-battery-writer.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 09:25:38 -07:00
Zack Carlson f88d3c52be Revert "Add NMEA GPS sensor plug-in"
This reverts commit 8b0607aa1c.
2026-05-18 22:55:05 -07:00
Zack Carlson 8b0607aa1c Add NMEA GPS sensor plug-in
nmea_gps.py reads NMEA 0183 sentences directly from a serial GPS receiver
(/dev/serial0 by default) and exposes fix status, position, motion, accuracy,
and satellite fields as sensor readings.

Parses GGA, RMC, and GSA sentence types using stdlib only (no pynmea2
dependency) — pyserial is already required by the repeater.

Designed for use when the repeater's built-in GPS service is disabled
(gps.enabled: false). Both cannot share the serial port simultaneously.
With gps.api_fallback_to_config_location: true the repeater continues
advertising the manually-configured location while the sensor plugin handles
raw GPS data.

Returns: fix_valid, fix_quality, fix_type, latitude, longitude, altitude_m,
speed_kmh, course_degrees, hdop, pdop, vdop, satellites_used, utc_datetime.
Position and motion fields are null when fix_valid is false to avoid
reporting config-fallback coordinates as real GPS data.

Tested on Raspberry Pi 3B+ (DietPi) with a u-blox GPS module on /dev/serial0.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 22:50:17 -07:00
Zack Carlson 9c1661f097 Add SHTC3 and Waveshare UPS HAT (D) sensor plug-ins
- shtc3.py: SHTC3 temperature/humidity sensor (RAK1901 WisBlock module,
  I2C 0x70). Uses smbus2 i2c_rdwr for raw I2C reads since SHTC3 requires
  16-bit command words with no register-byte prefix. Returns temperature_c,
  temperature_f, humidity_pct.

- waveshare_ups_d.py: Waveshare UPS HAT (D) battery monitor via INA219 at
  I2C 0x43. Uses the HAT's actual shunt (0.01 Ω, CAL=26868) rather than the
  generic INA219 defaults. Returns bus_voltage_v, shunt_voltage_mv,
  current_ma, power_mw, battery_percent (piecewise-linear SoC for 21700
  cell), and charge_state (charging/discharging/idle). Sign convention
  matches Waveshare sample code: negative current = charging.

Both plug-ins tested on Raspberry Pi 3B+ (DietPi) with RAK1901 WisBlock
sensor and Waveshare UPS HAT (D).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 22:32:20 -07:00
Lloyd 0e7bb05208 Refactor INA219 sensor integration. 2026-05-13 12:34:05 +01:00
Joshua Mesilane a01d59381b fix(ens210): check correct VALID bit in T_VAL/H_VAL polling
Bit 0 of byte 2 is the T_VALID/H_VALID flag (datasheet Figure 32/33,
page 23 example: t_valid = (t_val>>16) & 0x1). The previous code checked
bit 1 (CRC LSB), which caused sporadic timeouts when the CRC happened to
have a 0 in that position.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 17:07:28 +10:00
Joshua Mesilane 7865e9cb4b fix: standardise sensor module structure and docs
- Use multi-line ensure_python_modules list format in ens210.py,
  matching the established pattern from ina219.py
- Fix auto_install_packages indentation in ina219.py docstring
- Remove smbus2 from pyproject.toml core dependencies; sensor packages
  are handled at runtime via ensure_python_modules/auto_install_packages
- Update docs/adding_sensors.md template and guidance to match

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 16:33:37 +10:00
Joshua Mesilane 9bfe1259da feat: add ENS210 temperature/humidity sensor plug-in
Adds support for the ENS210 relative humidity and temperature sensor
as a new plug-in under repeater/sensors/ens210.py. Also adds a
commented configuration example to config.yaml.example and a
contributor guide at docs/adding_sensors.md explaining how to add
further sensor plug-ins.

## Implementation notes

### Why smbus2 instead of an Adafruit/CircuitPython library

The ENS210 has no maintained Adafruit CircuitPython driver. The
available third-party options are either unmaintained or bring in the
full Blinka/CircuitPython hardware-abstraction stack as a dependency.
smbus2 is a thin, widely-packaged wrapper around the Linux i2c-dev
kernel interface that is already present on Raspberry Pi OS and most
Debian-based systems. It has no transitive dependencies and adds no
abstraction cost.

The ENS210 protocol is simple enough that direct register access is
preferable: two writes to start a measurement (REG_SENS_RUN + REG_SENS_START)
and two three-byte block reads to retrieve temperature and humidity.
The status/validity bit is checked inline rather than relying on a
library to surface it. There is no value a higher-level driver would
add here.

### Read strategy

A fixed post-trigger delay is unreliable — the sensor datasheet quotes
~130 ms typical conversion time but the actual ready time varies. The
implementation instead polls the data-valid status bit (bit 1 of the
third byte in each register block) every 50 ms for up to
read_timeout_seconds (default 1.0 s), breaking as soon as both T and
H report valid data. This is the same approach used in the validated
reference script.

The I2C bus is opened and closed on every read rather than kept open
across poll cycles. Keeping a persistent SMBus handle caused subsequent
reads to time out, consistent with the Linux i2c-dev file descriptor
accumulating state between transactions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 11:46:26 +10:00
Lloyd 66532a0647 feat: Add sensor plugin framework and Sensors 2026-05-12 14:18:33 +01:00