Prepare one account key and one device
- In Workspace → Developer, create a named API credential and copy its one-time secret.
- In Workspace → Devices, create an Energy Plug (or another device with writable
powerplus energy telemetry) and copy its one-time device secret. - Export the four values below. Treat both secrets as passwords and never commit them.
export HAP_API_KEY='hapk_…'
export HAP_API_SECRET='sec_…'
export HAP_DEVICE_CODE='hap_…'
export HAP_DEVICE_SECRET='dev_…'
All examples target https://homeautopro.in. A successful run prints HomeAutoPro ... example: PASS. Account endpoints use the API key pair; device-ingest endpoints use the separate per-device secret.
ESP8266 + DHT11 temperature and humidity
For the PlatformIO nodemcuv2 board (NodeMCU 1.0 / ESP-12E), the board label D2 maps to GPIO4. Pin labels are board-specific: verify your selected board's variant before reusing that mapping.
Wiring
- DHT11 VCC → 3.3 V
- DHT11 GND → GND
- DHT11 DATA → D2 (GPIO4 on this NodeMCU definition)
- Use the module's onboard pull-up, or a suitable external DATA-to-3.3 V pull-up for a bare sensor.
HomeAutoPro capabilities
[
{"name":"Temperature","key":"temperature","value_type":"float","access":"read_only","unit":"°C","minimum":-20,"maximum":60,"step":0.1,"telemetry":true},
{"name":"Humidity","key":"humidity","value_type":"float","access":"read_only","unit":"%","minimum":0,"maximum":100,"step":0.1,"telemetry":true}
]
Create a Custom Device with these telemetry capabilities, or add them to a dedicated multi-capability development fixture. Keep each device's one-time secret in ignored local configuration.
Non-blocking firmware pattern
#include
constexpr uint8_t DHT_PIN = D2; // GPIO4 for nodemcuv2 only
constexpr uint32_t SAMPLE_MS = 2500; // DHT11 is intentionally slow
DHT dht(DHT_PIN, DHT11);
uint32_t lastSample = 0;
void setup() {
Serial.begin(115200);
dht.begin();
// Connect Wi-Fi and authenticate the HomeAutoPro device WebSocket here.
}
void loop() {
socket.loop(); // Never block command handling
if (millis() - lastSample < SAMPLE_MS) return;
lastSample = millis();
float humidity = dht.readHumidity();
float temperature = dht.readTemperature();
if (isnan(temperature) || isnan(humidity)) {
Serial.println("DHT11_READ_FAILED");
return; // Never publish fake zero values
}
StaticJsonDocument<192> message;
message["type"] = "telemetry";
message["telemetry"]["temperature"] = temperature;
message["telemetry"]["humidity"] = humidity;
sendAuthenticatedJson(message); // Publish on change or a periodic maximum interval
}
Sample locally every 2–5 seconds, but publish only on a meaningful change or periodic refresh. HomeAutoPro validates the declared numeric ranges, persists accepted records, and emits realtime browser updates.
DHT22: the same architecture works by changing DHT11 to DHT22. Keep the sampling interval at two seconds or slower. DHT22 compatibility is documented, not physically claimed here.
Troubleshooting: repeated failures usually indicate an incorrect board-pin mapping, missing pull-up, wiring/power issues, or sampling too quickly. Retain the last valid reading and mark it stale; never replace a failed read with 0 °C or 0%.
Python: authentication, device reads, state, and telemetry
Install the only dependency with python -m pip install requests, save this exactly as homeautopro_example.py, and run python homeautopro_example.py.
import os
import requests
BASE = "https://homeautopro.in"
account_headers = {
"X-API-Key": os.environ["HAP_API_KEY"],
"X-API-Secret": os.environ["HAP_API_SECRET"],
}
device_headers = {
"X-Device-Secret": os.environ["HAP_DEVICE_SECRET"],
"Content-Type": "application/json",
"X-Simulated": "true",
}
device_code = os.environ["HAP_DEVICE_CODE"]
devices_response = requests.get(f"{BASE}/api/devices", headers=account_headers, timeout=10)
devices_response.raise_for_status()
device = next(row for row in devices_response.json() if row["device_code"] == device_code)
detail_response = requests.get(f"{BASE}/api/devices/{device['id']}", headers=account_headers, timeout=10)
detail_response.raise_for_status()
assert detail_response.json()["device_code"] == device_code
state_response = requests.post(
f"{BASE}/api/device-ingest/{device_code}/state",
headers=device_headers,
json={"state": {"power": True}},
timeout=10,
)
state_response.raise_for_status()
assert state_response.json()["status"] == "accepted"
telemetry_response = requests.post(
f"{BASE}/api/device-ingest/{device_code}/telemetry",
headers=device_headers,
json={"telemetry": {"voltage": 230.0, "current": 0.5, "power_w": 115.0, "energy_kwh": 1.25}},
timeout=10,
)
telemetry_response.raise_for_status()
assert telemetry_response.json()["recorded"] is True
print("HomeAutoPro Python example: PASS")
Node.js: authentication, device reads, state, and telemetry
No package install is required. Save this exactly as homeautopro-example.mjs, then run node homeautopro-example.mjs.
const base = "https://homeautopro.in";
const accountHeaders = {
"X-API-Key": process.env.HAP_API_KEY,
"X-API-Secret": process.env.HAP_API_SECRET,
};
const deviceHeaders = {
"X-Device-Secret": process.env.HAP_DEVICE_SECRET,
"Content-Type": "application/json",
"X-Simulated": "true",
};
const deviceCode = process.env.HAP_DEVICE_CODE;
async function checked(url, options = {}) {
const response = await fetch(url, options);
if (!response.ok) throw new Error(`${response.status} ${await response.text()}`);
return response.json();
}
const devices = await checked(`${base}/api/devices`, { headers: accountHeaders });
const device = devices.find((row) => row.device_code === deviceCode);
if (!device) throw new Error("HAP_DEVICE_CODE is not owned by this API credential");
const detail = await checked(`${base}/api/devices/${device.id}`, { headers: accountHeaders });
if (detail.device_code !== deviceCode) throw new Error("Device detail mismatch");
const state = await checked(`${base}/api/device-ingest/${deviceCode}/state`, {
method: "POST",
headers: deviceHeaders,
body: JSON.stringify({ state: { power: true } }),
});
if (state.status !== "accepted") throw new Error("State was not accepted");
const telemetry = await checked(`${base}/api/device-ingest/${deviceCode}/telemetry`, {
method: "POST",
headers: deviceHeaders,
body: JSON.stringify({ telemetry: { voltage: 230.0, current: 0.5, power_w: 115.0, energy_kwh: 1.25 } }),
});
if (telemetry.recorded !== true) throw new Error("Telemetry was not recorded");
console.log("HomeAutoPro Node.js example: PASS");
cURL: authentication, list/get, state, and telemetry
After exporting the four variables above, run each command exactly. The first command writes your owned devices to devices.json; copy the matching device's id into HAP_DEVICE_ID for the second command.
curl --fail-with-body --silent --show-error \
-H "X-API-Key: $HAP_API_KEY" \
-H "X-API-Secret: $HAP_API_SECRET" \
https://homeautopro.in/api/devices -o devices.json
export HAP_DEVICE_ID='paste-id-from-devices.json'
curl --fail-with-body --silent --show-error \
-H "X-API-Key: $HAP_API_KEY" \
-H "X-API-Secret: $HAP_API_SECRET" \
"https://homeautopro.in/api/devices/$HAP_DEVICE_ID"
curl --fail-with-body --silent --show-error -X POST \
-H "X-Device-Secret: $HAP_DEVICE_SECRET" \
-H "Content-Type: application/json" \
-H "X-Simulated: true" \
-d '{"state":{"power":true}}' \
"https://homeautopro.in/api/device-ingest/$HAP_DEVICE_CODE/state"
curl --fail-with-body --silent --show-error -X POST \
-H "X-Device-Secret: $HAP_DEVICE_SECRET" \
-H "Content-Type: application/json" \
-H "X-Simulated: true" \
-d '{"telemetry":{"voltage":230.0,"current":0.5,"power_w":115.0,"energy_kwh":1.25}}' \
"https://homeautopro.in/api/device-ingest/$HAP_DEVICE_CODE/telemetry"
echo 'HomeAutoPro cURL example: PASS'
What happens next
State ingestion updates reported state and emits a realtime browser event. Telemetry ingestion stores a retained sample; values from examples are explicitly marked simulated in the Energy dashboard. Commands sent from the browser update desired state separately until a connected device acknowledges them.
Interactive endpoint schemas are available in the OpenAPI reference. The canonical device catalog lists writable and telemetry capabilities for every device type.