This commit is contained in:
j3d1 2023-02-16 00:14:21 +01:00
parent 9ef60f04d3
commit 55dad602c9
4 changed files with 195 additions and 40 deletions

View file

@ -12,8 +12,6 @@
#include <espressif/esp_common.h> #include <espressif/esp_common.h>
#include <esp/uart.h> #include <esp/uart.h>
#define PUB_MSG_LEN 16
void user_init(void) { void user_init(void) {
uart_set_baud(0, 115200); uart_set_baud(0, 115200);
printf("SDK version: %s\n", sdk_system_get_sdk_version()); printf("SDK version: %s\n", sdk_system_get_sdk_version());
@ -28,7 +26,7 @@ void user_init(void) {
wifi_available_semaphore = xSemaphoreCreateBinary(); 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); xTaskCreate(wifi_task, "wifi_task", 1024, NULL, 1, NULL);
@ -39,7 +37,7 @@ void user_init(void) {
wifi_alive = xSemaphoreCreateBinary(); wifi_alive = xSemaphoreCreateBinary();
publish_queue = xQueueCreate(3, PUB_MSG_LEN); 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);
} }

View file

@ -4,6 +4,7 @@
#include "mqtt.h" #include "mqtt.h"
#include "wifi.h" #include "wifi.h"
#include "lux.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -24,44 +25,190 @@ extern "C" {
/* You can use http://test.mosquitto.org/ to test mqtt_client instead /* You can use http://test.mosquitto.org/ to test mqtt_client instead
* of setting up your own MQTT server */ * of setting up your own MQTT server */
//#define MQTT_HOST ("172.16.0.42") //#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_PORT 1883
#define MQTT_USER NULL #define MQTT_USER NULL
#define MQTT_PASS NULL #define MQTT_PASS NULL
bool is_on = true;
#define PUB_MSG_LEN 16
QueueHandle_t publish_queue; QueueHandle_t publish_queue;
extern "C" void beat_task(void *pvParameters) { extern "C" void beat_task(void *pvParameters) {
TickType_t xLastWakeTime = xTaskGetTickCount(); TickType_t xLastWakeTime = xTaskGetTickCount();
char msg[PUB_MSG_LEN]; char msg[PUB_MSG_LEN];
int count = 0;
while (1) { while (1) {
vTaskDelayUntil(&xLastWakeTime, 10000 / portTICK_PERIOD_MS); vTaskDelayUntil(&xLastWakeTime, 10000 / portTICK_PERIOD_MS);
printf("beat\r\n"); snprintf(msg, PUB_MSG_LEN, R"({"state":"%s", "brightness":%d})", is_on ? "ON" : "OFF", light_value >> 4);
snprintf(msg, PUB_MSG_LEN, "Beat %d\r\n", count++);
if(xQueueSend(publish_queue, (void *) msg, 0) == pdFALSE) { if(xQueueSend(publish_queue, (void *) msg, 0) == pdFALSE) {
printf("Publish queue overflow.\r\n"); printf("Publish queue overflow.\r\n");
} }
} }
} }
template<typename T>
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<T> &operator=(T value) {
has_value_ = true;
value_ = value;
return *this;
}
optional<T> &operator=(const optional<T> &other) {
has_value_ = other.has_value_;
value_ = other.value_;
return *this;
}
optional<T> &operator=(optional<T> &&other) noexcept {
has_value_ = other.has_value_;
value_ = other.value_;
return *this;
}
optional(const optional<T> &other) : has_value_(other.has_value_), value_(other.value_) {}
optional(optional<T> &&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<size_t N>
bool consume_string(const char (&str)[N]) {
return consume_string(str, N - 1);
}
optional<char> read_char() {
if(head < end) {
return {*head++};
}
return {};
}
optional<char> peek_char() {
if(head < end) {
return {*head};
}
return {};
}
optional<int> 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) { static void topic_received(mqtt_message_data_t *md) {
int i;
mqtt_message_t *message = md->message; 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(" = "); if(strncmp((char *) md->topic->lenstring.data, "fiatlux/light/fiatlux_test/set", md->topic->lenstring.len) != 0) {
for (i = 0; i < (int) message->payloadlen; ++i) printf("Invalid topic: %s\n", (char *) md->topic->lenstring.data);
printf("%c", ((char *) (message->payload))[i]); 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) { static const char *get_my_id(void) {
@ -92,13 +239,13 @@ extern "C" void mqtt_task(void *pvParameters) {
struct mqtt_network network; struct mqtt_network network;
mqtt_client_t client = mqtt_client_default; mqtt_client_t client = mqtt_client_default;
char mqtt_client_id[20]; char mqtt_client_id[20];
uint8_t mqtt_buf[100]; uint8_t mqtt_buf[1000];
uint8_t mqtt_readbuf[100]; uint8_t mqtt_readbuf[1000];
mqtt_packet_connect_data_t data = mqtt_packet_connect_data_initializer; mqtt_packet_connect_data_t data = mqtt_packet_connect_data_initializer;
mqtt_network_new(&network); mqtt_network_new(&network);
memset(mqtt_client_id, 0, sizeof(mqtt_client_id)); 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()); strcat(mqtt_client_id, get_my_id());
while (1) { while (1) {
@ -113,8 +260,8 @@ extern "C" void mqtt_task(void *pvParameters) {
continue; continue;
} }
printf("done\n\r"); printf("done\n\r");
mqtt_client_new(&client, &network, 5000, mqtt_buf, 100, mqtt_client_new(&client, &network, 5000, mqtt_buf, 1000,
mqtt_readbuf, 100); mqtt_readbuf, 1000);
data.willFlag = 0; data.willFlag = 0;
data.MQTTVersion = 3; data.MQTTVersion = 3;
@ -132,9 +279,31 @@ extern "C" void mqtt_task(void *pvParameters) {
continue; continue;
} }
printf("done\r\n"); 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); 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) { while (1) {
char msg[PUB_MSG_LEN - 1] = "\0"; 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"); printf("got message to publish\r\n");
mqtt_message_t message; mqtt_message_t message;
message.payload = msg; message.payload = msg;
message.payloadlen = PUB_MSG_LEN; message.payloadlen = strlen(msg);
message.dup = 0; message.dup = 0;
message.qos = MQTT_QOS1; message.qos = MQTT_QOS1;
message.retained = 0; message.retained = 0;
ret = mqtt_publish(&client, "/beat", &message); ret = mqtt_publish(&client, "fiatlux/light/fiatlux_test/state", &message);
if(ret != MQTT_SUCCESS) { if(ret != MQTT_SUCCESS) {
printf("error while publishing message: %d\n", ret); printf("error while publishing message: %d\n", ret);
break; break;

View file

@ -13,6 +13,8 @@
extern "C" { extern "C" {
#endif #endif
#define PUB_MSG_LEN 64
void mqtt_task(void *pvParameters); void mqtt_task(void *pvParameters);
void beat_task(void *pvParameters); void beat_task(void *pvParameters);

View file

@ -279,20 +279,6 @@
<input type="range" min="0" max="4095" value="0" onchange="lightSlider(this.value)" <input type="range" min="0" max="4095" value="0" onchange="lightSlider(this.value)"
class="slider postfill_white_brightness"> class="slider postfill_white_brightness">
</label> </label>
<label>
<span>toggle signal led</span>
<input type="color" oninput="colorTop(this.value)">
</label>
<label>
<span>toggle signal led</span>
<input type="color" oninput="colorBottom(this.value)">
</label>
<label>
<span>toggle signal led</span>
<input type="range" min="0" max="4096" value="0" class="slider"
oninput="lightSlider(this.value)">
</label>
</footer> </footer>
</article> </article>
</div> </div>