diff --git a/firmware/fiatlux.c b/firmware/fiatlux.c index dc7e9f1..66211e7 100644 --- a/firmware/fiatlux.c +++ b/firmware/fiatlux.c @@ -12,8 +12,6 @@ #include #include -#define PUB_MSG_LEN 16 - void user_init(void) { uart_set_baud(0, 115200); printf("SDK version: %s\n", sdk_system_get_sdk_version()); @@ -28,7 +26,7 @@ void user_init(void) { wifi_available_semaphore = xSemaphoreCreateBinary(); - //xTaskCreate(mqtt_task, "mqtt_task", 1024, NULL, 1, NULL); + xTaskCreate(mqtt_task, "mqtt_task", 1024, NULL, 1, NULL); xTaskCreate(wifi_task, "wifi_task", 1024, NULL, 1, NULL); @@ -39,7 +37,7 @@ void user_init(void) { wifi_alive = xSemaphoreCreateBinary(); publish_queue = xQueueCreate(3, PUB_MSG_LEN); - //xTaskCreate(&beat_task, "beat_task", 256, NULL, 3, NULL); + xTaskCreate(&beat_task, "beat_task", 256, NULL, 3, NULL); } diff --git a/firmware/mqtt.cpp b/firmware/mqtt.cpp index 50ecaee..a6afa93 100644 --- a/firmware/mqtt.cpp +++ b/firmware/mqtt.cpp @@ -4,6 +4,7 @@ #include "mqtt.h" #include "wifi.h" +#include "lux.h" #include #include @@ -24,44 +25,190 @@ extern "C" { /* You can use http://test.mosquitto.org/ to test mqtt_client instead * of setting up your own MQTT server */ //#define MQTT_HOST ("172.16.0.42") -#define MQTT_HOST ("10.23.42.187") +//#define MQTT_HOST ("10.23.42.187") +#define MQTT_HOST ("172.16.1.53") #define MQTT_PORT 1883 #define MQTT_USER NULL #define MQTT_PASS NULL - -#define PUB_MSG_LEN 16 +bool is_on = true; QueueHandle_t publish_queue; extern "C" void beat_task(void *pvParameters) { TickType_t xLastWakeTime = xTaskGetTickCount(); char msg[PUB_MSG_LEN]; - int count = 0; while (1) { vTaskDelayUntil(&xLastWakeTime, 10000 / portTICK_PERIOD_MS); - printf("beat\r\n"); - snprintf(msg, PUB_MSG_LEN, "Beat %d\r\n", count++); + snprintf(msg, PUB_MSG_LEN, R"({"state":"%s", "brightness":%d})", is_on ? "ON" : "OFF", light_value >> 4); if(xQueueSend(publish_queue, (void *) msg, 0) == pdFALSE) { printf("Publish queue overflow.\r\n"); } } } +template +class optional { + bool has_value_; + T value_; + public: + optional() : has_value_(false) {} + + optional(T value) : has_value_(true), value_(value) {} + + bool has_value() const { return has_value_; } + + T value() const { return value_; } + + T value_or(T default_value) const { + return has_value_ ? value_ : default_value; + } + + T operator*() const { return value_; } + + T operator->() const { return value_; } + + operator bool() const { return has_value_; } + + optional &operator=(T value) { + has_value_ = true; + value_ = value; + return *this; + } + + optional &operator=(const optional &other) { + has_value_ = other.has_value_; + value_ = other.value_; + return *this; + } + + optional &operator=(optional &&other) noexcept { + has_value_ = other.has_value_; + value_ = other.value_; + return *this; + } + + optional(const optional &other) : has_value_(other.has_value_), value_(other.value_) {} + + optional(optional &&other) noexcept : has_value_(other.has_value_), value_(other.value_) {} + + +}; + +class parser { + char *head; + const char *end; + + public: + + parser(char *begin, const char *end) : head(begin), end(end) {} + + bool consume_char(char c) { + if(head < end && *head == c) { + head++; + return true; + } + return false; + } + + bool consume_string(const char *str, size_t len) { + if(head + len <= end && strncmp(head, str, len) == 0) { + head += len; + return true; + } + return false; + } + + template + bool consume_string(const char (&str)[N]) { + return consume_string(str, N - 1); + } + + optional read_char() { + if(head < end) { + return {*head++}; + } + return {}; + } + + optional peek_char() { + if(head < end) { + return {*head}; + } + return {}; + } + + optional read_int() { + int value = 0; + bool negative = false; + if(consume_char('-')) { + negative = true; + } + auto peek = head; + while (peek < end && *peek >= '0' && *peek <= '9') { + value = value * 10 + (*peek - '0'); + peek++; + } + if(peek == head) { + return {}; + } + head = peek; + return {negative ? -value : value}; + } +}; + static void topic_received(mqtt_message_data_t *md) { - int i; mqtt_message_t *message = md->message; - printf("Received: "); - for (i = 0; i < md->topic->lenstring.len; ++i) - printf("%c", md->topic->lenstring.data[i]); - printf(" = "); - for (i = 0; i < (int) message->payloadlen; ++i) - printf("%c", ((char *) (message->payload))[i]); + if(strncmp((char *) md->topic->lenstring.data, "fiatlux/light/fiatlux_test/set", md->topic->lenstring.len) != 0) { + printf("Invalid topic: %s\n", (char *) md->topic->lenstring.data); + return; + } - printf("\r\n"); + char *payload = (char *) message->payload; + char *payload_end = payload + message->payloadlen; + + parser p(payload, payload_end); + + if(!p.consume_char('{')) { + printf("expected '{' at start of payload\n"); + return; + } + while (true) { + if(p.consume_string(R"("state":)")) { + if(p.consume_string("\"ON\"")) { + is_on = true; + printf("ON\n"); + } else if(p.consume_string("\"OFF\"")) { + is_on = false; + printf("OFF\n"); + } else { + printf("Invalid state\n"); + return; + } + } else if(p.consume_string(R"("brightness":)")) { + auto brightness = p.read_int(); + if(!brightness) { + printf("Invalid brightness\n"); + return; + } + light_value = *brightness * 0xFFF / 255; + printf("Brightness: %d\n", *brightness); + } else { + printf("Invalid key\n"); + return; + } + if(p.consume_char(',')) { + continue; + } + if(p.consume_char('}')) { + break; + } + printf("expected ',' or '}'\n"); + return; + } } static const char *get_my_id(void) { @@ -92,13 +239,13 @@ extern "C" void mqtt_task(void *pvParameters) { struct mqtt_network network; mqtt_client_t client = mqtt_client_default; char mqtt_client_id[20]; - uint8_t mqtt_buf[100]; - uint8_t mqtt_readbuf[100]; + uint8_t mqtt_buf[1000]; + uint8_t mqtt_readbuf[1000]; mqtt_packet_connect_data_t data = mqtt_packet_connect_data_initializer; mqtt_network_new(&network); memset(mqtt_client_id, 0, sizeof(mqtt_client_id)); - strcpy(mqtt_client_id, "ESP-"); + strcpy(mqtt_client_id, "fiatlux-"); strcat(mqtt_client_id, get_my_id()); while (1) { @@ -113,8 +260,8 @@ extern "C" void mqtt_task(void *pvParameters) { continue; } printf("done\n\r"); - mqtt_client_new(&client, &network, 5000, mqtt_buf, 100, - mqtt_readbuf, 100); + mqtt_client_new(&client, &network, 5000, mqtt_buf, 1000, + mqtt_readbuf, 1000); data.willFlag = 0; data.MQTTVersion = 3; @@ -132,9 +279,31 @@ extern "C" void mqtt_task(void *pvParameters) { continue; } printf("done\r\n"); - mqtt_subscribe(&client, "/esptopic", MQTT_QOS1, topic_received); + + //Mqtt auto dicovery + + mqtt_subscribe(&client, "fiatlux/light/fiatlux_test/set", MQTT_QOS1, topic_received); + //mqtt_subscribe(&client, "fiatlux/light/fiatlux_test/state", MQTT_QOS1, topic_received); xQueueReset(publish_queue); + { + const char *msg_txt = R"json({ "name": "Fiatlux Test 0", + "unique_id": "fiatlux_test", + "command_topic": "fiatlux/light/fiatlux_test/set", + "state_topic": "fiatlux/light/fiatlux_test/state", + "brightness": true, "schema": "json" })json"; + mqtt_message_t message; + message.payload = (void *) msg_txt; + message.payloadlen = strlen(msg_txt); + message.dup = 0; + message.qos = MQTT_QOS1; + message.retained = 0; + ret = mqtt_publish(&client, "homeassistant/light/fiatlux_test/config", &message); + if(ret != MQTT_SUCCESS) { + printf("error: %d %s\n", ret, msg_txt); + } + } + while (1) { char msg[PUB_MSG_LEN - 1] = "\0"; @@ -143,11 +312,11 @@ extern "C" void mqtt_task(void *pvParameters) { printf("got message to publish\r\n"); mqtt_message_t message; message.payload = msg; - message.payloadlen = PUB_MSG_LEN; + message.payloadlen = strlen(msg); message.dup = 0; message.qos = MQTT_QOS1; message.retained = 0; - ret = mqtt_publish(&client, "/beat", &message); + ret = mqtt_publish(&client, "fiatlux/light/fiatlux_test/state", &message); if(ret != MQTT_SUCCESS) { printf("error while publishing message: %d\n", ret); break; diff --git a/firmware/mqtt.h b/firmware/mqtt.h index 80d15d4..8e6d147 100644 --- a/firmware/mqtt.h +++ b/firmware/mqtt.h @@ -13,6 +13,8 @@ extern "C" { #endif +#define PUB_MSG_LEN 64 + void mqtt_task(void *pvParameters); void beat_task(void *pvParameters); diff --git a/firmware/webdir/index.html b/firmware/webdir/index.html index 12c449a..52e074d 100644 --- a/firmware/webdir/index.html +++ b/firmware/webdir/index.html @@ -279,20 +279,6 @@ - - - -