Added support for 4 LED and progress of OTA in LEDS
This commit is contained in:
parent
92cf2e6f09
commit
e5c75fd70e
40
main/App.cpp
40
main/App.cpp
@ -85,11 +85,11 @@ void App::init()
|
||||
|
||||
if(getLocalTime(&timeinfo))
|
||||
{
|
||||
ESP_LOGI(TAG, "ok");
|
||||
ESP_LOGI(TAG, "pool.ntp.org ok");
|
||||
break;
|
||||
}
|
||||
else
|
||||
ESP_LOGE(TAG, "Failed");
|
||||
ESP_LOGE(TAG, "pool.ntp.org Failed");
|
||||
}
|
||||
|
||||
needs_provision = false;
|
||||
@ -106,6 +106,22 @@ void App::init()
|
||||
if(wifi_status == Wifi::WIFI_STATUS::CONNECTED)
|
||||
{
|
||||
ESP_LOGI(TAG, "Connected via fallback network");
|
||||
ESP_LOGI(TAG, "Getting local time...");
|
||||
struct tm timeinfo;
|
||||
|
||||
int tries = 5;
|
||||
while (tries--)
|
||||
{
|
||||
configTime(0, 0, "pool.ntp.org"); // needed?
|
||||
|
||||
if(getLocalTime(&timeinfo))
|
||||
{
|
||||
ESP_LOGI(TAG, "pool.ntp.org ok");
|
||||
break;
|
||||
}
|
||||
else
|
||||
ESP_LOGE(TAG, "pool.ntp.org Failed");
|
||||
}
|
||||
needs_provision = false;
|
||||
}
|
||||
else
|
||||
@ -126,6 +142,22 @@ void App::init()
|
||||
if(wifi_status == Wifi::WIFI_STATUS::CONNECTED)
|
||||
{
|
||||
ESP_LOGI(TAG, "Connected to fallback network");
|
||||
ESP_LOGI(TAG, "Getting local time...");
|
||||
struct tm timeinfo;
|
||||
|
||||
int tries = 5;
|
||||
while (tries--)
|
||||
{
|
||||
configTime(0, 0, "pool.ntp.org"); // needed?
|
||||
|
||||
if(getLocalTime(&timeinfo))
|
||||
{
|
||||
ESP_LOGI(TAG, "pool.ntp.org ok");
|
||||
break;
|
||||
}
|
||||
else
|
||||
ESP_LOGE(TAG, "pool.ntp.org Failed");
|
||||
}
|
||||
needs_provision = false;
|
||||
}
|
||||
else
|
||||
@ -141,10 +173,10 @@ void App::init()
|
||||
provision.start();
|
||||
}
|
||||
|
||||
//otaCheck();
|
||||
otaCheck();
|
||||
|
||||
// m_led->setPulse(255, 0, 255);
|
||||
m_led->setColor(0, 0, 0);
|
||||
m_led->allOff();
|
||||
|
||||
m_mqtt_service = new MqttService(*this);
|
||||
m_mqtt_service->start();
|
||||
|
||||
@ -189,7 +189,7 @@ bool CommandProcessor::cmdReportAllSettings(Parser & p, char * buffer)
|
||||
{
|
||||
int64_t up_time = esp_timer_get_time();
|
||||
uint8_t wifi_mac[8];
|
||||
|
||||
ESP_LOGI(TAG, "cmdReportAllSettings:");
|
||||
//added mac address
|
||||
esp_read_mac(wifi_mac, ESP_MAC_WIFI_STA);
|
||||
m_rw.reset();
|
||||
|
||||
47
main/Led.cpp
47
main/Led.cpp
@ -53,6 +53,39 @@ void Led::steady(uint8_t r, uint8_t g, uint8_t b, uint8_t d)
|
||||
}
|
||||
}
|
||||
|
||||
void Led::setLedColor(uint8_t led_index, uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
if (led_index < m_strip->numPixels()) {
|
||||
m_strip->setPixelColor(led_index, scale(r), scale(g), scale(b));
|
||||
m_strip->show();
|
||||
}
|
||||
}
|
||||
|
||||
void Led::suspendTask()
|
||||
{
|
||||
if (m_task != nullptr) {
|
||||
vTaskSuspend(m_task);
|
||||
ESP_LOGI("LED", "LED task suspended for OTA");
|
||||
}
|
||||
}
|
||||
|
||||
void Led::resumeTask()
|
||||
{
|
||||
if (m_task != nullptr) {
|
||||
vTaskResume(m_task);
|
||||
ESP_LOGI("LED", "LED task resumed");
|
||||
}
|
||||
}
|
||||
|
||||
void Led::setDirectColor(uint8_t led_index, uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
// Direct LED control without going through the task queue
|
||||
if (led_index < m_strip->numPixels()) {
|
||||
m_strip->setPixelColor(led_index, scale(r), scale(g), scale(b));
|
||||
m_strip->show();
|
||||
}
|
||||
}
|
||||
|
||||
void Led::run()
|
||||
{
|
||||
struct LED_QUEUE msg;
|
||||
@ -99,10 +132,12 @@ Led::Led(uint32_t pin) : m_queue(5)
|
||||
{
|
||||
ESP_LOGW("led", "Starting led...");
|
||||
|
||||
m_strip = new Adafruit_NeoPixel(1, pin, NEO_GRB + NEO_KHZ800);
|
||||
m_strip = new Adafruit_NeoPixel(4, pin, NEO_GRB + NEO_KHZ800);
|
||||
|
||||
m_strip->begin();
|
||||
m_strip->setPixelColor(0, 0, 0, 0);
|
||||
for(int i = 0; i < 4; i++) {
|
||||
m_strip->setPixelColor(i, 0, 0, 0);
|
||||
}
|
||||
m_strip->show();
|
||||
|
||||
m_brightness = SETTINGS.led.brightness;
|
||||
@ -139,6 +174,14 @@ void Led::setPulse(uint8_t r, uint8_t g, uint8_t b)
|
||||
m_queue.send(&msg, 1000);
|
||||
}
|
||||
|
||||
void Led::allOff()
|
||||
{
|
||||
for(int i = 0; i < 4; i++) {
|
||||
m_strip->setPixelColor(i, 0, 0, 0);
|
||||
}
|
||||
m_strip->show();
|
||||
}
|
||||
|
||||
void Led::setBrightness(uint8_t brightness)
|
||||
{
|
||||
m_brightness = brightness;
|
||||
|
||||
@ -48,6 +48,11 @@ public:
|
||||
void setBrightness(uint8_t brightness);
|
||||
void setColor(uint8_t r, uint8_t g, uint8_t b);
|
||||
void setPulse(uint8_t r, uint8_t g, uint8_t b);
|
||||
void setLedColor(uint8_t led_index, uint8_t r, uint8_t g, uint8_t b);
|
||||
void suspendTask();
|
||||
void resumeTask();
|
||||
void allOff();
|
||||
void setDirectColor(uint8_t led_index, uint8_t r, uint8_t g, uint8_t b);
|
||||
};
|
||||
|
||||
#endif /* __LED_H__ */
|
||||
@ -24,9 +24,9 @@ void MqttService::callback(char* topic, uint8_t * payload, uint32_t length)
|
||||
ESP_LOGW(TAG, "%s", (char*)payload);
|
||||
char * buffer = m_app_if.getCommandProcessor()->process((char *)payload, strlen((char *)payload));
|
||||
// reply to
|
||||
ESP_LOGI(TAG, "%s", buffer);
|
||||
m_mqtt_client->publish("/well_hub", buffer, strlen(buffer));
|
||||
|
||||
m_mqtt_client->publish("/well_hub", buffer, strlen(buffer));
|
||||
ESP_LOGW(TAG, "Published to /well_hub: %s", buffer);
|
||||
m_app_if.getCommandProcessor()->give();
|
||||
}
|
||||
|
||||
@ -56,25 +56,29 @@ void MqttService::task()
|
||||
{
|
||||
sprintf(top, "wh_%02X%02X%02X%02X%02X%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
|
||||
if(strcmp(SETTINGS.mqtt.device_id, "0") == 0) {
|
||||
strcpy(SETTINGS.mqtt.device_id, top);
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "connecting to mqtt broker, dev id '%s'...", SETTINGS.mqtt.device_id);
|
||||
//if (m_mqtt_client->connect(top, SETTINGS.mqtt.device_id, NULL))
|
||||
if (m_mqtt_client->connect(top, "well_user", "We3l1_best!"))
|
||||
if (m_mqtt_client->connect(SETTINGS.mqtt.device_id, "well_user", "We3l1_best!"))
|
||||
{
|
||||
try_connect_count = 0;
|
||||
ESP_LOGI(TAG, "connected");
|
||||
|
||||
sprintf(top, "/%02X%02X%02X%02X%02X%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
|
||||
ESP_LOGI(TAG, "Subscribing to %s", top);
|
||||
ESP_LOGW(TAG, "Subscribing to %s", top);
|
||||
if(m_mqtt_client->subscribe(top))
|
||||
ESP_LOGI(TAG, "subscribed");
|
||||
ESP_LOGW(TAG, "subscribed");
|
||||
else
|
||||
ESP_LOGE(TAG, "subscribe failed");
|
||||
|
||||
sprintf(top, "/%08x", SETTINGS.device.group_id);
|
||||
ESP_LOGI(TAG, "Subscribing to %s", top);
|
||||
ESP_LOGW(TAG, "Subscribing to %s", top);
|
||||
if(m_mqtt_client->subscribe(top))
|
||||
ESP_LOGI(TAG, "subscribed");
|
||||
ESP_LOGW(TAG, "subscribed");
|
||||
else
|
||||
ESP_LOGE(TAG, "subscribe failed");
|
||||
}
|
||||
|
||||
65
main/Ota.cpp
65
main/Ota.cpp
@ -22,7 +22,7 @@
|
||||
|
||||
#include <HTTPClient.h>
|
||||
|
||||
#define OTA_URL "http://wellnua.com/FW/wellhub.enc.bin"
|
||||
//#define OTA_URL "http://wellnua.com/FW/wellhub.enc.bin"
|
||||
extern const uint8_t server_cert[] asm("_binary_bigfoot_inc_pem_start");
|
||||
|
||||
static const char *TAG = "OTA";
|
||||
@ -34,6 +34,48 @@ Ota::Ota(AppIF & app) : m_app(app)
|
||||
|
||||
}
|
||||
|
||||
/// @brief Display download progress on 4 LEDs using binary representation
|
||||
/// @param progress_percent Progress from 0-100
|
||||
void Ota::displayProgress(int progress_percent)
|
||||
{
|
||||
// Clamp progress to 0-100 range
|
||||
if (progress_percent < 0) progress_percent = 0;
|
||||
if (progress_percent > 100) progress_percent = 100;
|
||||
|
||||
// Color definitions (R, G, B)
|
||||
struct Color {
|
||||
uint8_t r, g, b;
|
||||
};
|
||||
|
||||
const Color colors[4] = {
|
||||
{255, 0, 0}, // 00 = Red
|
||||
{0, 255, 0}, // 01 = Green
|
||||
{0, 0, 255}, // 10 = Blue
|
||||
{255, 255, 0} // 11 = Yellow
|
||||
};
|
||||
|
||||
// Convert progress to 8-bit binary (we only need 0-100, but using 8 bits for full range)
|
||||
uint8_t binary_progress = (uint8_t)progress_percent;
|
||||
|
||||
// Extract 2-bit values for each LED (D, C, B, A from left to right)
|
||||
// LED positions: D=3, C=2, B=1, A=0
|
||||
uint8_t led_values[4];
|
||||
led_values[0] = (binary_progress >> 0) & 0x03; // LED A (rightmost) - bits 1:0
|
||||
led_values[1] = (binary_progress >> 2) & 0x03; // LED B - bits 3:2
|
||||
led_values[2] = (binary_progress >> 4) & 0x03; // LED C - bits 5:4
|
||||
led_values[3] = (binary_progress >> 6) & 0x03; // LED D (leftmost) - bits 7:6
|
||||
|
||||
// Set each LED color based on its 2-bit value
|
||||
for (int i = 0; i < 4; i++) {
|
||||
const Color& color = colors[led_values[i]];
|
||||
|
||||
// Assuming you have access to LED strip with 4 LEDs
|
||||
// You may need to modify this based on your actual LED setup
|
||||
m_app.getLed()->setDirectColor(i, color.r, color.g, color.b);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Ota::taskFatalError()
|
||||
{
|
||||
ESP_LOGE(TAG, "Exiting task due to fatal error...");
|
||||
@ -51,13 +93,14 @@ void Ota::start()
|
||||
/* update handle : set by esp_ota_begin(), must be freed via esp_ota_end() */
|
||||
esp_ota_handle_t update_handle = 0;
|
||||
const esp_partition_t *update_partition = NULL;
|
||||
String otaUrl = "http://wellnua.com/FW/group/" + String(SETTINGS.device.group_id) + "/wellhub.enc.bin";
|
||||
|
||||
ESP_LOGW(TAG, "Starting OTA check '%s'...", OTA_URL);
|
||||
|
||||
ESP_LOGW(TAG, "Starting OTA check '%s'...", otaUrl.c_str());
|
||||
|
||||
HTTPClient client;
|
||||
|
||||
//client.begin(OTA_URL, (const char *)server_cert);
|
||||
client.begin(OTA_URL);
|
||||
client.begin(otaUrl);
|
||||
int http_code = client.GET();
|
||||
|
||||
if(http_code != HTTP_CODE_OK)
|
||||
@ -104,10 +147,12 @@ void Ota::start()
|
||||
if (data_read != FW_HEADER)
|
||||
{
|
||||
ESP_LOGE(TAG, "Error: SSL data read error");
|
||||
client.end();
|
||||
return;
|
||||
}
|
||||
|
||||
esp_aes_context m_dec_ctx;
|
||||
|
||||
uint8_t m_dec_iv[16];
|
||||
|
||||
memset(m_dec_iv, 0, sizeof(m_dec_iv));
|
||||
@ -124,6 +169,7 @@ void Ota::start()
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int left = remote_len-FW_HEADER; // encryption header
|
||||
|
||||
while (1)
|
||||
@ -138,6 +184,7 @@ void Ota::start()
|
||||
if (data_read < 0)
|
||||
{
|
||||
ESP_LOGE(TAG, "Error: SSL data read error");
|
||||
client.end();
|
||||
return;
|
||||
}
|
||||
else if (data_read > 0)
|
||||
@ -191,7 +238,6 @@ void Ota::start()
|
||||
ESP_LOGW(TAG, "The firmware has been rolled back to the previous version.");
|
||||
|
||||
client.end();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -204,8 +250,9 @@ void Ota::start()
|
||||
return;
|
||||
}
|
||||
|
||||
m_app.getLed()->setPulse(255, 255, 0);
|
||||
|
||||
//m_app.getLed()->setPulse(255, 255, 0);
|
||||
m_app.getLed()->suspendTask();
|
||||
displayProgress(0);
|
||||
image_header_was_checked = true;
|
||||
|
||||
ESP_LOGI(TAG, "Starting...");
|
||||
@ -221,6 +268,8 @@ void Ota::start()
|
||||
else
|
||||
{
|
||||
ESP_LOGE(TAG, "received package does not fit len");
|
||||
client.end();
|
||||
m_app.getLed()->resumeTask();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -241,6 +290,8 @@ void Ota::start()
|
||||
{
|
||||
last_reported = progress;
|
||||
ESP_LOGI(TAG, "%d%%", last_reported);
|
||||
// Display progress on LEDs
|
||||
displayProgress(last_reported);
|
||||
delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,11 +19,10 @@ class Ota
|
||||
{
|
||||
public:
|
||||
void start();
|
||||
|
||||
void displayProgress(int progress_percent);
|
||||
private:
|
||||
char otaWriteData[BUFFSIZE + 1] = { 0 };
|
||||
AppIF & m_app;
|
||||
|
||||
private:
|
||||
void taskFatalError();
|
||||
|
||||
|
||||
@ -81,6 +81,10 @@ struct MESSAGE_NOTIFY_LIGHT // 21 bytes
|
||||
createHeader(&(msgaddr_)->header); \
|
||||
(msgaddr_)->id = MESSAGE_TYPE_NOTIFY_LIGHT;
|
||||
|
||||
#define MQTT_MESSAGE_NOTIFY_PRESSURE(msgaddr_) \
|
||||
createHeader(&(msgaddr_)->header); \
|
||||
(msgaddr_)->id = MESSAGE_TYPE_NOTIFY_PRESSURE;
|
||||
|
||||
|
||||
#define MESSAGE_TYPE_NOTIFY_PRESSURE 0x01
|
||||
#define MESSAGE_TYPE_NOTIFY_TEMPERATURE 0x02
|
||||
|
||||
@ -67,23 +67,95 @@ void SensorService::start()
|
||||
pinMode(LIGHT_SENSOR_PIN, INPUT);
|
||||
}
|
||||
|
||||
void::SensorService::processPressure(float pressure)
|
||||
// Kalman filter variables
|
||||
static double kp_q = 0.5; // process noise
|
||||
static double kp_r = 32; // sensor noise
|
||||
static double kp_p = 1023; // estimation error
|
||||
static double kp_x = 0; // initial value
|
||||
|
||||
// Pressure monitoring variables
|
||||
static uint64_t pressure_period_started = 0;
|
||||
static float pressure_filtered_min = 0;
|
||||
static float pressure_filtered_max = 0;
|
||||
static const uint64_t pressure_window_ms = 1000; // 1000ms = 1 second
|
||||
|
||||
double getFilteredValue(double m)
|
||||
{
|
||||
static float filtered = 0;
|
||||
static uint64_t previous = esp_timer_get_time();
|
||||
|
||||
if(filtered == 0 && pressure != 0)
|
||||
filtered = pressure;
|
||||
|
||||
uint64_t now = esp_timer_get_time();
|
||||
|
||||
// ESP_LOGI(TAG, "delta T: %d", (uint32_t)((now-previous)/1000));
|
||||
|
||||
filtered = 0.95 * filtered + 0.05 * pressure;
|
||||
previous = now;
|
||||
// ESP_LOGI(TAG, "%0.3f \t%0.3f", pressure, filtered);
|
||||
if(kp_x == 0) kp_x=m;
|
||||
double k_k;
|
||||
kp_p = kp_p + kp_q;
|
||||
k_k = kp_p / (kp_p + kp_r);
|
||||
kp_x = kp_x + k_k * (m - kp_x);
|
||||
kp_p = (1 - k_k) * kp_p;
|
||||
return kp_x;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void::SensorService::processPressure(float pressure)
|
||||
{
|
||||
//static uint64_t previous = esp_timer_get_time();
|
||||
|
||||
// Get filtered pressure value using Kalman filter
|
||||
double filtered = getFilteredValue((double)pressure);
|
||||
double PRESSURE_THRESHOLD = 14.0;
|
||||
uint64_t now = esp_timer_get_time();
|
||||
uint64_t now_ms = now / 1000; // Convert to milliseconds
|
||||
|
||||
// Initialize pressure monitoring period
|
||||
if (pressure_period_started == 0) {
|
||||
pressure_period_started = now_ms;
|
||||
pressure_filtered_min = filtered;
|
||||
pressure_filtered_max = filtered;
|
||||
}
|
||||
else {
|
||||
// Track min and max during the window
|
||||
if (filtered > pressure_filtered_max) {
|
||||
pressure_filtered_max = filtered;
|
||||
//ESP_LOGE(TAG, "pressure_filtered_max: %0.3f", filtered);
|
||||
}
|
||||
|
||||
if (filtered < pressure_filtered_min) {
|
||||
pressure_filtered_min = filtered;
|
||||
//ESP_LOGE(TAG, "pressure_filtered_min: %0.3f", filtered);
|
||||
}
|
||||
|
||||
// Check if window period has elapsed
|
||||
if (now_ms > (pressure_period_started + pressure_window_ms)) {
|
||||
double change = 1000*abs(pressure_filtered_max - pressure_filtered_min);
|
||||
ESP_LOGE(TAG, "@P: %0.3f", change);
|
||||
|
||||
// Check for significant pressure change (door detection)
|
||||
if (change > PRESSURE_THRESHOLD) { // Threshold of 1
|
||||
//ESP_LOGE(TAG, "Door detected - pressure change: %0.3f", change);
|
||||
|
||||
// Send MQTT notification
|
||||
struct MESSAGE_NOTIFY_PRESSURE msg;
|
||||
MQTT_MESSAGE_NOTIFY_PRESSURE(&msg);
|
||||
msg.value = change; // or you could send the change value
|
||||
m_app_if.getBuffer()->putBlock((uint8_t*)&msg, sizeof(msg));
|
||||
//ESP_LOGE(TAG, "Door detected - pressure change: %0.3f, time: %u.%06u", change, msg.header.sec, msg.header.usec);
|
||||
// Convert epoch time to human-readable format
|
||||
time_t timestamp = msg.header.sec;
|
||||
struct tm *timeinfo = localtime(×tamp);
|
||||
|
||||
char time_str[64];
|
||||
strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", timeinfo);
|
||||
ESP_LOGE(TAG, "Door detected - pressure change: %0.3f, time: %s.%06u", change, time_str, msg.header.usec);
|
||||
}
|
||||
|
||||
// Reset for next window
|
||||
pressure_period_started = now_ms;
|
||||
pressure_filtered_min = filtered;
|
||||
pressure_filtered_max = filtered;
|
||||
}
|
||||
}
|
||||
|
||||
//previous = now;
|
||||
// Optional: store current filtered value for other uses
|
||||
//m_pressure_value = filtered;
|
||||
}
|
||||
void SensorService::postBme68xData(float pressure, float temp)
|
||||
{
|
||||
uint8_t msg_buffer[sizeof(struct MESSAGE_SENSORS_BLOCK) + 10*sizeof(struct GAS_DATA)];
|
||||
@ -132,12 +204,15 @@ void SensorService::processLight(int light_value)
|
||||
{
|
||||
if(last_light_val >= 0)
|
||||
{
|
||||
if(abs(min_light_val - last_light_val) > 4096*5/100)
|
||||
double change = abs(min_light_val - last_light_val);
|
||||
ESP_LOGE(TAG, "@L: %0.3f", change);
|
||||
|
||||
if(change > 4096*2/100.0)
|
||||
{
|
||||
ESP_LOGI(TAG, "light tripped");
|
||||
struct MESSAGE_NOTIFY_LIGHT msg;
|
||||
MQTT_MESSAGE_NOTIFY_LIGHT(&msg);
|
||||
msg.value = min_light_val;
|
||||
msg.value = abs(min_light_val - last_light_val);
|
||||
m_app_if.getBuffer()->putBlock((uint8_t*)&msg, sizeof(msg));
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,6 +34,7 @@ protected:
|
||||
uint16_t m_light_value = 0;
|
||||
|
||||
public:
|
||||
|
||||
SensorService(AppIF & app_if);
|
||||
void start();
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user