Bladeren bron

Add device layer for consuming MQTT messages and signaling main loop

rmt-backend
jrhoffa 3 jaren geleden
bovenliggende
commit
170a7ebe32
4 gewijzigde bestanden met toevoegingen van 159 en 3 verwijderingen
  1. +1
    -0
      main/CMakeLists.txt
  2. +76
    -0
      main/device.cpp
  3. +57
    -0
      main/device.hpp
  4. +25
    -3
      main/main.cpp

+ 1
- 0
main/CMakeLists.txt Bestand weergeven

@@ -5,6 +5,7 @@ idf_component_register(
"http_serv.cpp"
"ota.cpp"
"mqtt.cpp"
"device.cpp"

INCLUDE_DIRS "."
)


+ 76
- 0
main/device.cpp Bestand weergeven

@@ -0,0 +1,76 @@
static const char *TAG = "device";
#include <esp_log.h>

#include "device.hpp"


Device::Device(std::string _id) :
id(_id),
state_topic("light/" + id + "/state"),
cmd_topic("light/" + id + "/cmd"),
ready(false), should_publish(false),
mutex(xSemaphoreCreateMutex()),
sem(xSemaphoreCreateBinary()),
power_on(true),
client(start_mqtt_client(on_mqtt_connect, on_mqtt_message, this))
{}
void Device::set_mqtt_config(cJSON*) {
xSemaphoreTake(mutex, portMAX_DELAY);

// TODO: update power_on and effect from JSON
publish_state_locked();

xSemaphoreGive(mutex);
}

void Device::on_mqtt_connect(esp_mqtt_client_handle_t client) {
xSemaphoreTake(mutex, portMAX_DELAY);

ESP_LOGI(TAG, "Connected to MQTT");

if (esp_mqtt_client_subscribe(client, cmd_topic.c_str(), 0) < 0) {
ESP_LOGE(TAG, "Failed to subscribe to %s", cmd_topic.c_str());
}
if (0 > esp_mqtt_client_publish(
client,
("homeassistant/light/" + id + "/config").c_str(),
("{"
"\"unique_id\": \"" + id + "\", "
"\"device\": {\"name\": \"blinky_" + id + "\"}, "
"\"state_topic\": \"" + state_topic + "\", "
"\"command_topic\": \"" + cmd_topic + "\", "
"\"schema\": \"json\", "
"\"effect\": True, "
"\"effect_list\": [\"dummy\"]"
"}").c_str(), 0,
0, 0
)) {
ESP_LOGE(TAG, "Failed to publish discovery message");
}

ready = true;
if (should_publish) publish_state_locked();

xSemaphoreGive(mutex);
}

void Device::on_mqtt_message(esp_mqtt_client_handle_t, esp_mqtt_event_handle_t) {
ESP_LOGI(TAG, "Received command via MQTT");
// TODO: extract JSON, call set_mqtt_config
xSemaphoreGive(sem);
}

void Device::publish_state_locked() {
if (!(should_publish = !ready)) {
ESP_ERROR_CHECK(esp_mqtt_client_publish(
client,
state_topic.c_str(),
("{"
"\"state\": \"" + std::string(power_on ? "ON" : "OFF") + "\", "
"\"effect\": \"" + effect + "\""
"}").c_str(), 0,
0, 0
));
}
}

+ 57
- 0
main/device.hpp Bestand weergeven

@@ -0,0 +1,57 @@
#pragma once

#include <string>

#include <cJSON.h>

#include "mqtt.hpp"


class Device {
public:
Device(std::string id);
void set_mqtt_config(cJSON*);

void lock() const { xSemaphoreTake(mutex, portMAX_DELAY); }
void unlock() const { xSemaphoreGive(mutex); }

bool wait(int timeout_ms = -1) const {
return pdTRUE == xSemaphoreTake(
sem,
(timeout_ms < 0 ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms))
);
}

// Only call while locked
const std::string& get_effect() const { return effect; }
bool is_on() const { return power_on; }

private:
std::string id;

std::string state_topic;
std::string cmd_topic;

bool ready, should_publish;

SemaphoreHandle_t mutex;
SemaphoreHandle_t sem;

bool power_on;
std::string effect;

esp_mqtt_client_handle_t client;

static void on_mqtt_connect(esp_mqtt_client_handle_t client, void* data) {
((Device*)data)->on_mqtt_connect(client);
}
static void on_mqtt_message(esp_mqtt_client_handle_t client, esp_mqtt_event_handle_t event, void* data) {
((Device*)data)->on_mqtt_message(client, event);
}

void on_mqtt_connect(esp_mqtt_client_handle_t);
void on_mqtt_message(esp_mqtt_client_handle_t, esp_mqtt_event_handle_t);

void publish_state_locked();
};

+ 25
- 3
main/main.cpp Bestand weergeven

@@ -10,7 +10,7 @@ static const char *TAG = "blinky";
#include "wifi.hpp"
#include "http_serv.hpp"
#include "ota.hpp"
#include "mqtt.hpp"
#include "device.hpp"


// mDNS / NetBIOS
@@ -80,6 +80,13 @@ static void log_dir(const std::string &path) {
}


int64_t now_us() {
struct timeval tv_now;
gettimeofday(&tv_now, NULL);
return (int64_t)tv_now.tv_sec * 1000000L + (int64_t)tv_now.tv_usec;
}


// Entry Point

extern "C" void app_main(void) {
@@ -108,8 +115,23 @@ extern "C" void app_main(void) {
log_dir("/spiffs");

// TODO: Something useful
esp_mqtt_client_handle_t client = start_mqtt_client(NULL, NULL, NULL);
esp_mqtt_client_subscribe(client, "#", 0);
Device device("blinky-jr");

/*
int period_us = 1000000;
int64_t target_us = now_us();
while (true) {
int64_t delay_us = target_us - now_us();
if (delay_us < 0) delay_us = 0;
if (device.wait(delay_us / 1000))
ESP_LOGI(TAG, "Reload!");
else {
ESP_LOGI(TAG, "Timeout!");
target_us += period_us;
}
}
*/
while (device.wait()) ESP_LOGI(TAG, "Reload!");

// Spin
}

Laden…
Annuleren
Opslaan