Skip to main content

SAES Neg Power MQTT Bridge (Unofficial)

Standalone MQTT monitoring and explicit activation control for SAES NEG POWER MINI. No PowerSupply or pressure-gauge inheritance. A private internal adapter translates MQTT commands into Modbus TCP or RS232/RTU transactions. Connecting, disconnecting, restarting the service and recovering a connection never automatically start or stop heating.

The manual documents the interfaces but omits the register map. The implementation uses a map recovered from the supplied manager software; see docs/protocol.md for evidence, defaults, units and unresolved details. Tests use local dummy devices. This has not been deployed or qualified against a physical NEG controller.

Install from this directory with python3 -m pip install . or python3 -m pip install pysaes-neg-power-tspspi. Copy the example configuration, give the service user ownership, and use mode 0600. Create the configured state_directory owned by that same user with mode 0700. Run:

negpowermqtt --config /path/to/negpowermqtt.conf

Each device entry gets an independent polling/reconnect worker. Add additional entries with unique names and endpoints for additional controllers. For serial, replace device_host with serial_port; optional baudrate, parity, and stopbits default to 38400, N, 1. Ethernet defaults to port 502 and unit 1; the configured device values must agree with the front panel.

Control defaults to disabled. Set control_enabled: true for a device when using external publishers to control it. Queries and monitoring work while control is disabled. No hardware writes have been performed during development.

MQTT topics

For base /lab and name neg1:

Topic Direction Payload
/lab/neg/neg1/state Service publishes Timestamp, online flag, identity, status, settings
/lab/neg/neg1/availability Service publishes Online flag and timestamp; MQTT last will also reports disconnect
/lab/neg/neg1/command External publisher sends JSON command envelope below
/lab/neg/neg1/result Service publishes Request id, result, timestamp, details/readback

Publications use QoS 1 and are not retained. Periodic state is refreshed every 10 seconds by default. Query requests trigger a fresh snapshot. An offline device sends availability=false and retries; no cached state is substituted. Check timestamps; broker outages can delay or duplicate MQTT deliveries.

Commands require a unique id, an action, and Unix issued_at/expires_at values with validity at most 60 seconds. Publish with retain=false. Retained subscription deliveries, expired/future commands, malformed settings and unknown actions/fields are rejected. No topic permits arbitrary register access.

Actions:

  • query: obtain a fresh state/settings snapshot.
  • set_settings: set and verify voltage, ramp, hold and maximum temperature; require standby; leave output state unchanged.
  • start: set and verify the complete supplied settings, check standby, alarms, thermocouple and current temperature, then start the controller's ramp.
  • stop: explicitly request output stop and return status readback.

start executes the controller's voltage ramp and hold. The maximum temperature is a controller cutoff, not a PID temperature target. A valid thermocouple and firmware support are required. The service does not create pump recipes, infer settings from pump type, clear alarms, or resume a ramp after reboot. Use the activation parameters specified for the actual pump. Hold zero explicitly selects indefinite operation; stopping the daemon does not terminate it.

Example start payload (timestamps must be generated when publishing):

{
  "id": "activation-unique-id",
  "action": "start",
  "issued_at": 1700000000,
  "expires_at": 1700000030,
  "settings": {
    "voltage_V": 8.8,
    "ramp_minutes": 15,
    "hold_minutes": 60,
    "max_temperature_K": 573
  }
}

These settings demonstrate the schema; they are not a recommended pump recipe. Temperature is an integer kelvin value on the wire (573 K is approximately 300 degrees Celsius). State also reports the measured temperature in Celsius.

completed means a query or settings transaction completed with readback. accepted means start/stop was acknowledged and status was read back; it does not mean activation finished or the temperature cutoff was physically verified. rejected means the service did not accept the command. uncertain means writes may have executed or settings may be partial; query state before deciding what to do next. An uncertain start is never resent automatically.

The SQLite journal records each accepted request id before its first possible write. Exact duplicates return the saved result without replay; reusing an id with different content is rejected. This survives service restarts and lost result delivery. An interrupted claimed request remains uncertain. Do not delete the journal to retry a command. Offline commands are rejected, not saved for execution when the device returns. Commands queued across a broker reconnect are discarded. A retry uses the same id, timestamps and payload; an expired retry is rejected. Only issue a new control id after reconciling the device state.

The broker must authenticate publishers and enforce topic permissions: service accounts subscribe only to their command topics and publish only state, availability and result; observer accounts read those publications; control accounts publish only intended command topics. The service cannot identify a publisher from a normal MQTT message, so access control belongs at the broker. Use one command owner per controller; front-panel or other software changes can race separate Modbus transactions. MQTT delivery is not a real-time interlock; use the controller's hardware protections.

See examples/publish_command.py for an external publisher using its own private credentials file. A FreeBSD rc.d template is provided at service/negpowermqtt; no services or users have been installed by creating this repository.

Development

PYTHONPATH=src python3 -m pytest -q
python3 -m build

Tests cover TCP/RTU framing, settings validation/readback, temperature/start checks, retained/expired commands, persistent deduplication, uncertain writes, multiple devices, and real Paho MQTT interaction with a local dummy broker.

Metadata

Release files for pysaes-neg-power-tspspi 0.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pysaes-neg-power-tspspi 0.0.1
File Size Uploaded
pysaes_neg_power_tspspi-0.0.1.tar.gz 25.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pysaes-neg-power-tspspi 0.0.1
File Interpreter ABI Platform
pysaes_neg_power_tspspi-0.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 41.5 kB

Release files / pysaes_neg_power_tspspi-0.0.1.tar.gz

Download URL pysaes_neg_power_tspspi-0.0.1.tar.gz
Size 25.5 kB
Tags Source
SHA-256 checksum
How to use checksums
fd28fcce570408b324b2974f091561b1aff3c33f69103432e299a7c6d101bf51
BLAKE2b-256 checksum
How to use checksums
72a46a2200dd3525c15bb0f8faff11f43d2a0c81496d27512603ad43af090403
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.11.11

Release files / pysaes_neg_power_tspspi-0.0.1-py3-none-any.whl

Download URL pysaes_neg_power_tspspi-0.0.1-py3-none-any.whl
Size 16.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6eac5b63dc0d9346e0679a735ec2dd3b6595d50353ad719414537bcb3948decb
BLAKE2b-256 checksum
How to use checksums
4d1ea80140582643d90f4efc205267ecafb756e680181b1c483e42d90ba431b6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.11.11

Release history Release notifications | RSS feed

This release

0.0.1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page