esp demo sketch

This commit is contained in:
2026-02-05 21:42:09 +01:00
parent 3f6e8a0808
commit a1e95ec23e

284
esp-demo/esp-demo.ino Normal file
View File

@@ -0,0 +1,284 @@
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <Hash.h>
// ---- Configure these ----
const char *WIFI_SSID = "YOUR_WIFI_SSID";
const char *WIFI_PASS = "YOUR_WIFI_PASS";
const char *MQTT_HOST = "192.168.1.10"; // broker address (use host running mosquitto)
const uint16_t MQTT_PORT = 1883;
const char *MQTT_USER = "testuser"; // from test/.env
const char *MQTT_PASS = "testpass"; // from test/.env
const char *MQTT_TOPIC = "lambdaiot"; // main topic
// GPIO
const uint8_t ACTOR_PIN = D1; // digital output
// Publishing interval (ms)
const unsigned long SENSOR_PUBLISH_INTERVAL = 5000;
WiFiClient wifiClient;
PubSubClient mqtt(wifiClient);
String macAddress;
String deviceId;
String sensorId;
String actorId;
unsigned long lastPublishAt = 0;
// DNS namespace UUID bytes: 6ba7b810-9dad-11d1-80b4-00c04fd430c8
const char *DNS_NAMESPACE_UUID = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";
// ---- UUID helpers ----
bool parseUuidBytes(const String &uuidStr, uint8_t out[16]) {
String hex = uuidStr;
hex.replace("-", "");
if (hex.length() != 32) {
return false;
}
for (int i = 0; i < 16; i++) {
char c1 = hex[i * 2];
char c2 = hex[i * 2 + 1];
auto hexVal = [](char c) -> int {
if (c >= '0' && c <= '9') return c - '0';
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
return -1;
};
int v1 = hexVal(c1);
int v2 = hexVal(c2);
if (v1 < 0 || v2 < 0) {
return false;
}
out[i] = (uint8_t)((v1 << 4) | v2);
}
return true;
}
String formatUuid(const uint8_t bytes[16]) {
char buf[37];
snprintf(buf, sizeof(buf),
"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
bytes[0], bytes[1], bytes[2], bytes[3],
bytes[4], bytes[5],
bytes[6], bytes[7],
bytes[8], bytes[9],
bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15]);
return String(buf);
}
String uuidV5(const uint8_t namespaceBytes[16], const String &name) {
// SHA1(namespace + name)
SHA1Builder sha;
sha.begin();
sha.add(namespaceBytes, 16);
sha.add((const uint8_t *)name.c_str(), name.length());
sha.calculate();
uint8_t hash[20];
sha.getHash(hash);
uint8_t out[16];
memcpy(out, hash, 16);
// Set version (5) and variant (RFC 4122)
out[6] = (out[6] & 0x0F) | 0x50;
out[8] = (out[8] & 0x3F) | 0x80;
return formatUuid(out);
}
// ---- MQTT messaging ----
void publishDiscovery() {
StaticJsonDocument<512> doc;
doc["mac_address"] = macAddress;
JsonObject dev = doc.createNestedObject("device");
dev["id"] = deviceId;
dev["name"] = "ESP8266 Demo";
dev["description"] = "ESP8266 MQTT demo device";
dev["location"] = "Lab";
dev["status_id"] = 1;
JsonArray sensors = doc.createNestedArray("sensors");
JsonObject s0 = sensors.createNestedObject();
s0["id"] = sensorId;
s0["name"] = "Temperature";
s0["type"] = "ADC";
s0["data_type_id"] = 2;
JsonArray actors = doc.createNestedArray("actors");
JsonObject a0 = actors.createNestedObject();
a0["id"] = actorId;
a0["name"] = "DigitalOut";
a0["type"] = "GPIO";
a0["data_type_id"] = 1;
char buf[512];
size_t n = serializeJson(doc, buf, sizeof(buf));
String topic = String(MQTT_TOPIC) + "/discovery";
mqtt.publish(topic.c_str(), buf, n);
}
void publishSensorReading() {
int adc = analogRead(A0);
float value = (float)adc; // raw ADC value
StaticJsonDocument<256> doc;
doc["type"] = "sensor_reading";
doc["sensor_id"] = sensorId;
doc["value"] = value;
char buf[256];
size_t n = serializeJson(doc, buf, sizeof(buf));
mqtt.publish(MQTT_TOPIC, buf, n);
}
void publishActorState(int state) {
StaticJsonDocument<256> doc;
doc["type"] = "actor_state";
doc["actor_id"] = actorId;
doc["value"] = state;
char buf[256];
size_t n = serializeJson(doc, buf, sizeof(buf));
mqtt.publish(MQTT_TOPIC, buf, n);
}
void publishDeviceCheckResponse() {
StaticJsonDocument<256> doc;
doc["type"] = "device_check_response";
doc["device_id"] = deviceId;
doc["status"] = "ok";
char buf[256];
size_t n = serializeJson(doc, buf, sizeof(buf));
mqtt.publish(MQTT_TOPIC, buf, n);
}
void handleActorCommand(JsonObject payload) {
if (!payload.containsKey("actor_id")) return;
String id = payload["actor_id"].as<String>();
if (id != actorId) return;
int value = 0;
if (payload.containsKey("value")) {
if (payload["value"].is<bool>()) {
value = payload["value"].as<bool>() ? 1 : 0;
} else if (payload["value"].is<int>()) {
value = payload["value"].as<int>() != 0 ? 1 : 0;
} else if (payload["value"].is<float>()) {
value = payload["value"].as<float>() != 0 ? 1 : 0;
} else if (payload["value"].is<const char *>()) {
String v = payload["value"].as<String>();
v.toLowerCase();
if (v == "true" || v == "1" || v == "on") value = 1;
else value = 0;
}
}
digitalWrite(ACTOR_PIN, value ? HIGH : LOW);
publishActorState(value);
}
void handleSensorTrigger(JsonObject payload) {
if (!payload.containsKey("sensor_id")) return;
String id = payload["sensor_id"].as<String>();
if (id != sensorId) return;
publishSensorReading();
}
void handleDeviceCheckRequest(JsonObject payload) {
if (!payload.containsKey("device_id")) return;
String id = payload["device_id"].as<String>();
if (id != deviceId) return;
publishDeviceCheckResponse();
}
void mqttCallback(char *topic, uint8_t *payload, unsigned int length) {
StaticJsonDocument<512> doc;
DeserializationError err = deserializeJson(doc, payload, length);
if (err) {
return;
}
const char *type = doc["type"] | "";
String msgType = String(type);
msgType.toLowerCase();
if (msgType == "actor_command") {
handleActorCommand(doc.as<JsonObject>());
return;
}
if (msgType == "sensor_trigger") {
handleSensorTrigger(doc.as<JsonObject>());
return;
}
if (msgType == "device_check_request") {
handleDeviceCheckRequest(doc.as<JsonObject>());
return;
}
}
// ---- Setup/loop ----
void ensureMqtt() {
while (!mqtt.connected()) {
String clientId = "esp-demo-" + String(ESP.getChipId());
if (mqtt.connect(clientId.c_str(), MQTT_USER, MQTT_PASS)) {
mqtt.subscribe(MQTT_TOPIC);
publishDiscovery();
} else {
delay(2000);
}
}
}
void setup() {
pinMode(ACTOR_PIN, OUTPUT);
digitalWrite(ACTOR_PIN, LOW);
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
macAddress = WiFi.macAddress();
macAddress.toLowerCase();
uint8_t dnsNs[16];
parseUuidBytes(String(DNS_NAMESPACE_UUID), dnsNs);
String macNoSep = macAddress;
macNoSep.replace(":", "");
deviceId = uuidV5(dnsNs, macNoSep);
uint8_t deviceNs[16];
parseUuidBytes(deviceId, deviceNs);
sensorId = uuidV5(deviceNs, "sensor-0");
actorId = uuidV5(deviceNs, "actor-0");
mqtt.setServer(MQTT_HOST, MQTT_PORT);
mqtt.setCallback(mqttCallback);
ensureMqtt();
lastPublishAt = millis();
}
void loop() {
ensureMqtt();
mqtt.loop();
unsigned long now = millis();
if (now - lastPublishAt >= SENSOR_PUBLISH_INTERVAL) {
lastPublishAt = now;
publishSensorReading();
}
}