New: the AI firewall watches the whole platform and explains each incident in plain words. See how it works

Switching a Wi-Fi relay from my own Python scripts through the commands endpoint

Switching a Wi-Fi relay from my own Python scripts through the commands endpoint

Solved 5 3

Data analyst here, so go easy on me with the electronics.

Our test lab has a lamp over the endurance rig that the operators want on while a test is running. The test runs are started from my Python scripts, so I’d like the script to switch the lamp too. I bought a Sonoff Basic R2 Wi-Fi relay, but out of the box it only works with its own phone app and I can’t find any documented API for it.

We already use Hermetry for the rig’s sensors (an ESP32 sending vibration and temperature over MQTT, works fine). Ideally my script would talk to Hermetry and Hermetry would talk to the relay, so I don’t have to open anything in the lab network and the operators see the lamp state on the same board.

Is that a sane setup? If yes, which endpoint do I call, and how does the relay “hear” it? I found /api/iot/devices/{deviceId}/rpc in the API docs but I’m not sure what has to exist on the device side.

♥ 1

The Sonoff Basic has an ESP8266 inside. You can flash your own sketch on it through the 4-pin header with a USB-serial adapter (3.3 V, not 5 V!). Then it’s just another Hermetry device.

Ask me about 4–20 mA.
♥ 0

Flashed it with a borrowed FTDI adapter, took me three tries to get it into boot mode (hold the button while plugging in). It now connects to Hermetry with its own access token and sends {"relay": 0} every minute. So the sending part is done. What about switching it?

♥ 1

Good, that’s the same setup we use for a few signal lamps. Three pieces:

  1. Device profile of the relay, Commands tab: add a command light.set, tier Basic, one parameter on of type Yes / no. Tier matters, because an API key can only send methods that are in the profile’s catalog.
  2. Firmware: subscribe to v1/rpc/req/+, switch GPIO12 (the relay on the Basic R2), answer on the same id, and report the new state.
void onMsg(char* topic, byte* p, unsigned int n) {
  // topic: v1/rpc/req/42
  String id = String(topic).substring(11);
  StaticJsonDocument<128> d; deserializeJson(d, p, n);
  bool on = d["params"]["on"];
  digitalWrite(12, on ? HIGH : LOW);
  mqtt.publish(("v1/rpc/res/" + id).c_str(), "{"ok":true}");
  mqtt.publish("v1/telemetry", on ? "{"relay":1}" : "{"relay":0}");
}
  1. Your script: an API key from API Keys (Developer menu) with only what it needs. The send route wants iot_rpc.read plus the tier’s permission, so tick those two and nothing else, fill the IP allowlist with the lab PC’s address and keep the 90-day expiry.
import requests
r = requests.post(
    f"https://{HOST}/tenant/{TENANT}/api/iot/devices/{DEVICE}/rpc",
    headers={"Authorization": f"Bearer {KEY}"},
    json={"method": "light.set", "params": {"on": True}, "timeoutMs": 10000},
)
print(r.status_code, r.json()["rpc"]["status"])

A two-way command with a timeout of 30 s or less waits and comes back 200 with SUCCESSFUL. Reference: Commands API

The ESP8266 does TLS, but memory is tight; use BearSSL with smaller buffers if the connect fails.

Accepted solution♥ 4

Works. First call came back 403 because I had only ticked the send permission and not iot_rpc.read. After adding it the lamp clicks and the call returns 200 / SUCCESSFUL in about 300 ms. I also put a Switch card on the operators’ board bound to relay, so they see the state. Thanks both.

♥ 1

Nice! Mains on that board, so put it back in its case before anyone touches it 😄

Ask me about 4–20 mA.
♥ 0
Viewing 6 posts – 1 through 6 (of 6 total)
  • You must be logged in to reply to this topic.

Join the conversation

Sign in to ask and answer, like helpful posts and mark the reply that solved your problem. Every contribution earns points and levels.

Share