somewhat refactored wifi, still not fully clear when provision should automatically start

This commit is contained in:
Miro Zmrzli 2024-05-23 13:42:05 -07:00
parent 3acbbd44c2
commit bf29ccda08
17 changed files with 245 additions and 379 deletions

17
Wifi.md Normal file
View File

@ -0,0 +1,17 @@
```mermaid
graph
A(Wifi start)
B[Start provision]
A-->|not provisioned
SETTINGS.wifi.num = 0|B
C{{single
or
multiple}}
A-->|provisioned
SETTINGS.wifi.num > 0|C
D[connect]
C-->|single
SETTINGS.wifi.num = 1|D
```

View File

@ -1,22 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDpDCCAoygAwIBAgIBADANBgkqhkiG9w0BAQsFADCBkDELMAkGA1UEBhMCR0Ix
FzAVBgNVBAgMDlVuaXRlZCBLaW5nZG9tMQ4wDAYDVQQHDAVEZXJieTESMBAGA1UE
CgwJTW9zcXVpdHRvMQswCQYDVQQLDAJDQTEWMBQGA1UEAwwNbW9zcXVpdHRvLm9y
ZzEfMB0GCSqGSIb3DQEJARYQcm9nZXJAYXRjaG9vLm9yZzAeFw0yNDA1MTkwMjQx
MjNaFw0yNDA4MTcwMjQxMjNaMH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxp
Zm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRIwEAYDVQQKDAlNaXJvIElu
Yy4xDTALBgNVBAMMBE1pcm8xHzAdBgkqhkiG9w0BCQEWEHdpbC5lQGNveW90ZS5j
b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDWip9n32uj4VritcwO
/jcKcKcpqOjcY4YFFV4iltCgLLAO3xQhOp0b2QliFGhdy01jNpyoNFW3zEMQzzuJ
mGq1pTY75KVdYXT8/LLxUo4ZCZn2oIU5JdHvY5+D0B0ROXIEH9TswZf203D1qa2z
rMH+3Sl01hTyfMmwM/T2iARCgObjZmRDxUfYdjZAC0TyzSj7/2MWi9QIQ8zV5Zjp
DUlgaiMTacHLqZeqqgzGtu1Xi8f3ALWptvIZ/pJWRZn+u1qLFPZ9BBKcxzQB27EJ
YPgRE8bOX9EodCudC6rVt9v4jjIVitp6M6YJIrFMT0XqZ266NaZzcnrz19OZALpx
MXd/AgMBAAGjGjAYMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgXgMA0GCSqGSIb3DQEB
CwUAA4IBAQByyKl8sJbM6XyulcSrO8+0aqjQ2tFFUMqs/SpOkpG5AW8AwFW70UXC
lPCjOK4DLBJnLtZ2RvBNZTi8sIHpBx9eAxh1eScr3/B0l5TTHha/ddnrk/lLMB39
OAVsx5ne6k+5VX6ID5siApx+KPRlyY3NfKeirpVof49Yv1ira/yXK0aFHPeTbz8+
XkNKzUz8uItgZ/S0obcxQAVSevvuWZzpVKN9rhJp5jLbbwaV+nYHbBbXsHU/peGf
TpKeLRBPj4+NwcLz1OZp7X/BeCXAFmZyUoH514UVkl/mZUMtDEzr+Fnuct1FyFsX
B0u2/aNTp81ZP/pmcasqF9H1Y2lG9aT5
-----END CERTIFICATE-----

View File

@ -1,28 +0,0 @@
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDWip9n32uj4Vri
tcwO/jcKcKcpqOjcY4YFFV4iltCgLLAO3xQhOp0b2QliFGhdy01jNpyoNFW3zEMQ
zzuJmGq1pTY75KVdYXT8/LLxUo4ZCZn2oIU5JdHvY5+D0B0ROXIEH9TswZf203D1
qa2zrMH+3Sl01hTyfMmwM/T2iARCgObjZmRDxUfYdjZAC0TyzSj7/2MWi9QIQ8zV
5ZjpDUlgaiMTacHLqZeqqgzGtu1Xi8f3ALWptvIZ/pJWRZn+u1qLFPZ9BBKcxzQB
27EJYPgRE8bOX9EodCudC6rVt9v4jjIVitp6M6YJIrFMT0XqZ266NaZzcnrz19OZ
ALpxMXd/AgMBAAECggEAYpMO6wscyg+hUsl1GO51G7bnF50kYR7ZVTycJAhnkzD1
M+ALv7jOtxzh0s7NpUrkI9HT6PUi7XBM4ExXbsE5RnzCjoJf+KfuuM7i6T6lS5u9
wjO/AqL98qAzirz0nhVm7b4ydxX8XMyJ+lYcGZInEJNNmQFEXqY3hV5aD2wviN4Z
oiOR4uzHceR+6ADGzsnL/Kf5wGjZqAZE9+keVlsgJ/GrOHVFGhFdWlX0crAyezbf
U6TAgzdE/xoDIV6mYfLxUsWKl/Ty6ubLXRrAqmKxeigR2guYYWeS2h/caJ3zuIfV
51thJqaeTCTW4KPta3CEft4tuyiNxhW8CKbGHxIbAQKBgQDf3f3/w6ovtzf/ROC7
UeBi2qGFMFioxZxlSSgEJEyGFSiHk9y0K5jMBivyU6fyEz6fm/7XUFpzuxv1yFai
JZP9rUIPtnRTxEyL5dP7O0aX8DF2DtLgdBWLo2xh9bGalov9TOnM9B9ByD5d4Alj
UkYcR+3+cLcNRkKAVz175+XYewKBgQD1VfVqs86PTKtvu8ft4hNzGZRbyZzGdUGM
BSOu49KG319evqmjqsGzmkM28PqIouVH0vJ2W5uKJpQ964D+X1TnSrjOlZihdyNp
O4k5tMYTKjBKvsGPvm+Xhu385poCnra5r/9h16D/+q0S5nfSr0WkM/UeIzBVnPVX
WfOLNHtHzQKBgFUW/cpPRsqoK2KdfYX1kwI/85C6VZigs9dTvSAF5Ag61pLhwsvA
nm0+E0oiPf2nDvB/zJdudVLz1abQJQ2wltWfGzL5uLF2NVofWzlsyGJL66Dh9YlW
1jGjRjjduEn32vHGYD+EsrTANeRcmXTk+r0ZIf7KPOmQwQojHr2P4S8tAoGAODF3
I/iJUHNMNSx6r7b/o3Zxb9CvExnaaJrowG84UmIpcwcSzgUXlu63hIcPq2o8QAZG
OOvkpXEOtVwS0LC/Prbzu4WyTxF9z+WuGcSZNdyM8SHeLfF9l+R08F9VWVJHIiL4
yM1d+CPPrquROHWi6uhntX5z3Lg1zcsxqGnd7uUCgYBkq/I1bV+vGY4Vh3FuzJOa
XIEHmquei6pPuHPgSBPYZSu87uIyIwcZSGBVsRqbXyIKPhzDZ/SOe0fBh/SZD0QH
6bfhA2BwF4PyhtFyX5cwsiWMurCTjspws5fCT0KqikgkjXC/IlDAioB2an+lsPTz
71KGRyxMkyHbcthk9/uPOg==
-----END PRIVATE KEY-----

View File

@ -1,24 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIEAzCCAuugAwIBAgIUBY1hlCGvdj4NhBXkZ/uLUZNILAwwDQYJKoZIhvcNAQEL
BQAwgZAxCzAJBgNVBAYTAkdCMRcwFQYDVQQIDA5Vbml0ZWQgS2luZ2RvbTEOMAwG
A1UEBwwFRGVyYnkxEjAQBgNVBAoMCU1vc3F1aXR0bzELMAkGA1UECwwCQ0ExFjAU
BgNVBAMMDW1vc3F1aXR0by5vcmcxHzAdBgkqhkiG9w0BCQEWEHJvZ2VyQGF0Y2hv
by5vcmcwHhcNMjAwNjA5MTEwNjM5WhcNMzAwNjA3MTEwNjM5WjCBkDELMAkGA1UE
BhMCR0IxFzAVBgNVBAgMDlVuaXRlZCBLaW5nZG9tMQ4wDAYDVQQHDAVEZXJieTES
MBAGA1UECgwJTW9zcXVpdHRvMQswCQYDVQQLDAJDQTEWMBQGA1UEAwwNbW9zcXVp
dHRvLm9yZzEfMB0GCSqGSIb3DQEJARYQcm9nZXJAYXRjaG9vLm9yZzCCASIwDQYJ
KoZIhvcNAQEBBQADggEPADCCAQoCggEBAME0HKmIzfTOwkKLT3THHe+ObdizamPg
UZmD64Tf3zJdNeYGYn4CEXbyP6fy3tWc8S2boW6dzrH8SdFf9uo320GJA9B7U1FW
Te3xda/Lm3JFfaHjkWw7jBwcauQZjpGINHapHRlpiCZsquAthOgxW9SgDgYlGzEA
s06pkEFiMw+qDfLo/sxFKB6vQlFekMeCymjLCbNwPJyqyhFmPWwio/PDMruBTzPH
3cioBnrJWKXc3OjXdLGFJOfj7pP0j/dr2LH72eSvv3PQQFl90CZPFhrCUcRHSSxo
E6yjGOdnz7f6PveLIB574kQORwt8ePn0yidrTC1ictikED3nHYhMUOUCAwEAAaNT
MFEwHQYDVR0OBBYEFPVV6xBUFPiGKDyo5V3+Hbh4N9YSMB8GA1UdIwQYMBaAFPVV
6xBUFPiGKDyo5V3+Hbh4N9YSMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
BQADggEBAGa9kS21N70ThM6/Hj9D7mbVxKLBjVWe2TPsGfbl3rEDfZ+OKRZ2j6AC
6r7jb4TZO3dzF2p6dgbrlU71Y/4K0TdzIjRj3cQ3KSm41JvUQ0hZ/c04iGDg/xWf
+pp58nfPAYwuerruPNWmlStWAXf0UTqRtg4hQDWBuUFDJTuWuuBvEXudz74eh/wK
sMwfu1HFvjy5Z0iMDU8PUDepjVolOCue9ashlS4EB5IECdSR2TItnAIiIwimx839
LdUdRudafMu5T5Xma182OC0/u/xRlEm+tvKGGmfFcN0piqVl8OrSPBgIlb+1IKJE
m/XriWr/Cq4h/JfB7NTsezVslgkBaoU=
-----END CERTIFICATE-----

View File

@ -1,24 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIEAzCCAuugAwIBAgIUBY1hlCGvdj4NhBXkZ/uLUZNILAwwDQYJKoZIhvcNAQEL
BQAwgZAxCzAJBgNVBAYTAkdCMRcwFQYDVQQIDA5Vbml0ZWQgS2luZ2RvbTEOMAwG
A1UEBwwFRGVyYnkxEjAQBgNVBAoMCU1vc3F1aXR0bzELMAkGA1UECwwCQ0ExFjAU
BgNVBAMMDW1vc3F1aXR0by5vcmcxHzAdBgkqhkiG9w0BCQEWEHJvZ2VyQGF0Y2hv
by5vcmcwHhcNMjAwNjA5MTEwNjM5WhcNMzAwNjA3MTEwNjM5WjCBkDELMAkGA1UE
BhMCR0IxFzAVBgNVBAgMDlVuaXRlZCBLaW5nZG9tMQ4wDAYDVQQHDAVEZXJieTES
MBAGA1UECgwJTW9zcXVpdHRvMQswCQYDVQQLDAJDQTEWMBQGA1UEAwwNbW9zcXVp
dHRvLm9yZzEfMB0GCSqGSIb3DQEJARYQcm9nZXJAYXRjaG9vLm9yZzCCASIwDQYJ
KoZIhvcNAQEBBQADggEPADCCAQoCggEBAME0HKmIzfTOwkKLT3THHe+ObdizamPg
UZmD64Tf3zJdNeYGYn4CEXbyP6fy3tWc8S2boW6dzrH8SdFf9uo320GJA9B7U1FW
Te3xda/Lm3JFfaHjkWw7jBwcauQZjpGINHapHRlpiCZsquAthOgxW9SgDgYlGzEA
s06pkEFiMw+qDfLo/sxFKB6vQlFekMeCymjLCbNwPJyqyhFmPWwio/PDMruBTzPH
3cioBnrJWKXc3OjXdLGFJOfj7pP0j/dr2LH72eSvv3PQQFl90CZPFhrCUcRHSSxo
E6yjGOdnz7f6PveLIB574kQORwt8ePn0yidrTC1ictikED3nHYhMUOUCAwEAAaNT
MFEwHQYDVR0OBBYEFPVV6xBUFPiGKDyo5V3+Hbh4N9YSMB8GA1UdIwQYMBaAFPVV
6xBUFPiGKDyo5V3+Hbh4N9YSMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
BQADggEBAGa9kS21N70ThM6/Hj9D7mbVxKLBjVWe2TPsGfbl3rEDfZ+OKRZ2j6AC
6r7jb4TZO3dzF2p6dgbrlU71Y/4K0TdzIjRj3cQ3KSm41JvUQ0hZ/c04iGDg/xWf
+pp58nfPAYwuerruPNWmlStWAXf0UTqRtg4hQDWBuUFDJTuWuuBvEXudz74eh/wK
sMwfu1HFvjy5Z0iMDU8PUDepjVolOCue9ashlS4EB5IECdSR2TItnAIiIwimx839
LdUdRudafMu5T5Xma182OC0/u/xRlEm+tvKGGmfFcN0piqVl8OrSPBgIlb+1IKJE
m/XriWr/Cq4h/JfB7NTsezVslgkBaoU=
-----END CERTIFICATE-----

View File

@ -16,7 +16,7 @@
#define LED_PIN 26 #define LED_PIN 26
//static const char * TAG = "app"; static const char * TAG = "app";
App::App() App::App()
{ {
@ -34,18 +34,21 @@ void App::init()
{ {
// try connecting // try connecting
m_led->setColor(0, 255, 0); m_led->setColor(0, 255, 0);
uint32_t status = m_wifi->start(); m_wifi->start();
if(status == WH_OK)
Wifi::WIFI_STATUS wifi_status = m_wifi->waitForConnection();
if(wifi_status == Wifi::WIFI_STATUS::CONNECTED)
{ {
ESP_LOGI(TAG, "Getting local time"); ESP_LOGI(TAG, "Getting local time...");
struct tm timeinfo; struct tm timeinfo;
configTime(0, 0, "pool.ntp.org"); configTime(0, 0, "pool.ntp.org");
if(getLocalTime(&timeinfo)) if(getLocalTime(&timeinfo))
ESP_LOGI(TAG, "Got local time"); ESP_LOGI(TAG, "ok");
else else
ESP_LOGE(TAG, "Failed to get local time"); ESP_LOGE(TAG, "Failed");
m_led->setColor(0, 0, 0); // m_led->setColor(0, 0, 0);
MDNS.begin("esp32"); MDNS.begin("esp32");
needs_provision = false; needs_provision = false;
} }
@ -58,21 +61,27 @@ void App::init()
provision.start(); provision.start();
} }
otaCheck();
m_led->setPulse(255, 0, 255);
m_mqtt = new Mqtt();
m_mqtt->start();
}
void App::otaCheck()
{
ota_update::OTA ota(*this); ota_update::OTA ota(*this);
ota.start(); ota.start();
m_led->setColor(0, 0, 0);
Mqtt m;
m.test();
// Mqtt::test();
} }
void App::start() void App::start()
{ {
while(true) // while(true)
{ // {
vTaskDelay(pdMS_TO_TICKS(10020)); // vTaskDelay(pdMS_TO_TICKS(10020));
} // }
} }
void App::readSensors() void App::readSensors()

View File

@ -8,17 +8,21 @@
#include "Settings.h" #include "Settings.h"
#include "Led.h" #include "Led.h"
#include "Wifi.h" #include "Wifi.h"
#include "Mqtt.h"
class App class App
{ {
protected: protected:
Wifi * m_wifi = nullptr; Wifi * m_wifi = nullptr;
Mqtt * m_mqtt = nullptr;
public: public:
Led * m_led = nullptr; Led * m_led = nullptr;
public: public:
App(); App();
void otaCheck();
void init(); void init();
void start(); void start();
void readSensors(); void readSensors();

View File

@ -3,7 +3,6 @@ idf_component_register(SRCS main.cpp App.cpp Settings.cpp Led.cpp TaskFactory.cp
INCLUDE_DIRS "." INCLUDE_DIRS "."
EMBED_TXTFILES ../html/logo.png ../html/provision.html EMBED_TXTFILES ../html/logo.png ../html/provision.html
EMBED_TXTFILES ../certs/eventgrid.azure.pem ../certs/client1-authn-ID.key ../certs/client1-authn-ID.pem EMBED_TXTFILES ../certs/eventgrid.azure.pem ../certs/client1-authn-ID.key ../certs/client1-authn-ID.pem
EMBED_TXTFILES ../certs/mosquitto.org.crt ../certs/client.crt ../certs/client.key
) )
#message(FATAL_ERROR "error ${ROLE}") #message(FATAL_ERROR "error ${ROLE}")

View File

@ -2,6 +2,77 @@
#include "Mqtt.h" #include "Mqtt.h"
extern const uint8_t logo_png_start[] asm("_binary_eventgrid_azure_pem_start"); #include <esp_log.h>
extern const uint8_t logo_png_end[] asm("_binary_eventgrid_azure_pem_end"); #include "TaskFactory.h"
static const char * mqtt_broker = "mqtt-dev-server.westus2-1.ts.eventgrid.azure.net";
static const char * topic = "wellnuotopics/topic1";
static const int mqtt_port = 8883;
static const char * TAG = "mqtts";
void Mqtt::callback(char* topic, uint8_t * payload, uint32_t length)
{
ESP_LOGI(TAG, "Message arrived in topic: %s\n", topic);
payload[length] = 0;
ESP_LOGW(TAG, "%s", (char*)payload);
}
void Mqtt::task()
{
while(true)
{
while (!m_mqtt_client->connected())
{
ESP_LOGI(TAG, "connecting to mqtt broker...");
if (m_mqtt_client->connect("Esp32 client", "client1-authn-ID", NULL))
ESP_LOGI(TAG, "connected");
else
{
ESP_LOGE(TAG, "failed with state %d", m_mqtt_client->state());
delay(5000);
}
}
int n = 0;
while(true)
{
if(!m_mqtt_client->connected())
break;
m_mqtt_client->loop();
ESP_LOGI(TAG, "publishing...");
bool val = m_mqtt_client->publish(topic, "Hi I'm ESP32 ^^");
if(val)
ESP_LOGI(TAG, "%d publish ok", n);
else
ESP_LOGE(TAG, "%d publish failed", n);
ESP_LOGI(TAG, "%d", TaskFactory::getStackHighWaterMark());
delay(50000);
n++;
}
}
}
void Mqtt::start()
{
ESP_LOGW(TAG, "Starting mqtt");
m_esp_client = new WiFiClientSecure();
m_mqtt_client = new PubSubClient(*m_esp_client);
m_esp_client->setCACert((const char*)server_cert);
m_esp_client->setCertificate((const char *)client_cert); // for client verification
m_esp_client->setPrivateKey((const char *)client_key); // for client verification
m_mqtt_client->setServer(mqtt_broker, mqtt_port);
m_mqtt_client->setCallback(std::bind(&Mqtt::callback, this, _1, _2, _3));
m_task = TASK_FACTORY.createTask(std::bind(&Mqtt::task, this), "mqtt task", 6144, 5, 0);
}

View File

@ -4,224 +4,31 @@
#define __MQTT_T__ #define __MQTT_T__
#include <stdint.h> #include <stdint.h>
#include <esp_log.h>
#include <WiFiClientSecure.h> #include <WiFiClientSecure.h>
#include <PubSubClient.h> #include <PubSubClient.h>
#include <functional> #include <functional>
#include "mqtt_client.h" #include "mqtt_client.h"
static const char *TAG = "MQTTS";
extern const uint8_t server_cert[] asm("_binary_eventgrid_azure_pem_start"); extern const uint8_t server_cert[] asm("_binary_eventgrid_azure_pem_start");
extern const uint8_t client_cert[] asm("_binary_client1_authn_ID_pem_start"); extern const uint8_t client_cert[] asm("_binary_client1_authn_ID_pem_start");
extern const uint8_t client_key[] asm("_binary_client1_authn_ID_key_start"); extern const uint8_t client_key[] asm("_binary_client1_authn_ID_key_start");
extern const uint8_t test_cert[] asm("_binary_mosquitto_org_crt_start");
extern const uint8_t test_client_cert[] asm("_binary_client_crt_start");
extern const uint8_t test_client_key[] asm("_binary_client_key_start");
esp_mqtt_client_handle_t client;
using namespace std::placeholders; using namespace std::placeholders;
class Mqtt class Mqtt
{ {
#if 0 protected:
WiFiClientSecure *m_esp_client;
PubSubClient *m_mqtt_client;
void callback(char* topic, uint8_t * payload, uint32_t length);
TaskHandle_t m_task = nullptr;
void task();
public: public:
void start();
static void log_error_if_nonzero(const char *message, int error_code)
{
if (error_code != 0) {
ESP_LOGE(TAG, "Last error %s: 0x%x", message, error_code);
}
}
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%d", base, event_id);
esp_mqtt_event_handle_t event = (esp_mqtt_event_handle_t)event_data;
esp_mqtt_client_handle_t client = event->client;
int msg_id;
switch ((esp_mqtt_event_id_t)event_id) {
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
// msg_id = esp_mqtt_client_subscribe(client, "wellnuotopics/topic1", 0);
// ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
// msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1);
// ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
// msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1");
// ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
break;
case MQTT_EVENT_SUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
msg_id = esp_mqtt_client_publish(client, "wellnuotopics/topic1", "0", 0, 0, 0);
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_UNSUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_PUBLISHED:
ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_DATA:
ESP_LOGI(TAG, "MQTT_EVENT_DATA");
printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
printf("DATA=%.*s\r\n", event->data_len, event->data);
break;
case MQTT_EVENT_ERROR:
ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {
log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err);
log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err);
log_error_if_nonzero("captured as transport's socket errno", event->error_handle->esp_transport_sock_errno);
ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));
}
break;
default:
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break;
}
}
static void mqtt_app_start(void)
{
esp_mqtt_client_config_t mqtt_cfg;
memset(&mqtt_cfg, 0, sizeof(mqtt_cfg));
// test server
// mqtt_cfg.uri = "mqtts://test.mosquitto.org:8884";
// mqtt_cfg.cert_pem = (const char *)test_cert;
// mqtt_cfg.client_key_pem = (const char *)test_client_key;
// mqtt_cfg.client_cert_pem = (const char *)test_client_cert;
mqtt_cfg.uri = "mqtts://mqtt-dev-server.westus2-1.ts.eventgrid.azure.net:8883";
mqtt_cfg.username = "client1-authn-ID";
mqtt_cfg.client_id = "client1-esp";
mqtt_cfg.cert_pem = (const char *)server_cert;
mqtt_cfg.client_key_pem = (const char *)client_key;
mqtt_cfg.client_cert_pem = (const char *)client_cert;
ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
client = esp_mqtt_client_init(&mqtt_cfg);
/* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */
esp_mqtt_client_register_event(client, (esp_mqtt_event_id_t)ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
esp_mqtt_client_start(client);
}
static void test()
{
mqtt_app_start();
while(true)
{
delay(5000);
int val = esp_mqtt_client_publish (client, "wellnuotopics/topic1", "mytestdata", 10, 0, false);
ESP_LOGI(TAG, "publish: %d", val);
}
}
#endif
public:
#if 1
void callback(char* topic, byte* payload, unsigned int length) {
printf("Message arrived in topic: %s\n", topic);
printf("Message:'");
for (int i = 0; i < length; i++) {
printf("%c", (char)payload[i]);
}
printf("'\n");
printf("-----------------------\n");
}
#include "time.h"
void printLocalTime()
{
struct tm timeinfo;
char buf[48];
if(!getLocalTime(&timeinfo)){
printf("Failed to obtain time\n");
return;
}
strftime(buf, 26, "%Y-%m-%d %H:%M:%S", &timeinfo);
ESP_LOGI(TAG, "%s", buf);
}
void test()
{
const char* mqtt_broker = "mqtt-dev-server.westus2-1.ts.eventgrid.azure.net";
const char* topic = "wellnuotopics/topic1";
const int mqtt_port = 8883 ;
WiFiClientSecure espClient;
PubSubClient client(espClient);
espClient.setCACert((const char*)server_cert);
espClient.setCertificate((const char *)client_cert); // for client verification
espClient.setPrivateKey((const char *)client_key); // for client verification
client.setServer(mqtt_broker, mqtt_port);
client.setCallback(std::bind(&Mqtt::callback, this, _1, _2, _3));
printLocalTime();
while (!client.connected())
{
String client_id = "esp32-client";
client_id += String(WiFi.macAddress());
// Print the Name and the id of the esp32 controller
ESP_LOGI("", "connecting client %s mqtt broker...", client_id.c_str());
if (client.connect("Esp32 client", "client1-authn-ID", NULL)) {
ESP_LOGI("", "Public emqx mqtt broker connected");
} else {
ESP_LOGE("", "failed with state %d", client.state());
delay(5000);
}
}
bool val;
// val = client.subscribe(topic);
// if(val)
// ESP_LOGI(TAG, "sub ok");
// else
// ESP_LOGI(TAG, "sub failed");
// Publish and Subscribe
// val = client.publish(topic, "Hi I'm ESP32 ^^");
// if(val)
// ESP_LOGI(TAG, "publish ok");
// else
// ESP_LOGI(TAG, "publish failed");
int n = 0;
while(true)
{
// client.loop();
delay(2500);
val = client.publish(topic, "Hi I'm ESP32 ^^");
if(val)
ESP_LOGI(TAG, "%d publish ok", n);
else
ESP_LOGE(TAG, "%d publish failed", n);
n++;
}
}
#endif
}; };
#endif #endif

View File

@ -166,12 +166,12 @@ void OTA::start()
if (memcmp(new_app_info.version, running_app_info.version, sizeof(new_app_info.version) + sizeof(new_app_info.project_name) + sizeof(new_app_info.time) + sizeof(new_app_info.date)) == 0) if (memcmp(new_app_info.version, running_app_info.version, sizeof(new_app_info.version) + sizeof(new_app_info.project_name) + sizeof(new_app_info.time) + sizeof(new_app_info.date)) == 0)
{ {
ESP_LOGW(TAG, "Current running version is the same as a remote. No need for update."); ESP_LOGI(TAG, "Current running version is the same as a remote. No need for update.");
httpCleanup(client); httpCleanup(client);
return; return;
} }
m_app.m_led->setPulse(255, 0, 255); m_app.m_led->setPulse(255, 255, 0);
image_header_was_checked = true; image_header_was_checked = true;
@ -190,7 +190,6 @@ void OTA::start()
httpCleanup(client); httpCleanup(client);
taskFatalError(); taskFatalError();
} }
} }
err = esp_ota_write(update_handle, (const void *) otaWriteData, data_read); err = esp_ota_write(update_handle, (const void *) otaWriteData, data_read);

View File

@ -8,6 +8,7 @@
#include "Settings.h" #include "Settings.h"
#include "errors.h" #include "errors.h"
#include <string.h> #include <string.h>
#include <esp_netif.h>
static const char *TAG = "Settings"; static const char *TAG = "Settings";
@ -84,6 +85,9 @@ void Settings::setDefaults()
m_data.version = SETTINGS_VERSION; m_data.version = SETTINGS_VERSION;
m_data.led.brightness = 25; // 25 % m_data.led.brightness = 25; // 25 %
m_data.wifi.subnet_mask = PP_HTONL(LWIP_MAKEU32(255, 255, 255, 0));
m_data.wifi.dns_primary = PP_HTONL(LWIP_MAKEU32(8, 8, 8, 8));
m_data.wifi.dns_secondary = PP_HTONL(LWIP_MAKEU32(8, 8, 4, 4));
// strcpy(m_data.wifi.entry[0].ssid, "gumball"); // strcpy(m_data.wifi.entry[0].ssid, "gumball");
// strcpy(m_data.wifi.entry[0].pwd, "mikelemembe"); // strcpy(m_data.wifi.entry[0].pwd, "mikelemembe");

View File

@ -70,7 +70,7 @@ struct SETTINGS_LEGACY
uint32_t TEMP_OFFSET; uint32_t TEMP_OFFSET;
}; };
#define SETTINGS_VERSION 4 // cannot be 0 #define SETTINGS_VERSION 2 // cannot be 0
#define SETTINGS_NUM_WIFI_ENTRIES 8 #define SETTINGS_NUM_WIFI_ENTRIES 8
// wifi definitions // wifi definitions
@ -87,6 +87,11 @@ struct WIFI
uint8_t always_scan_before_connect; uint8_t always_scan_before_connect;
struct WIFI_ENTRY entry[SETTINGS_NUM_WIFI_ENTRIES]; struct WIFI_ENTRY entry[SETTINGS_NUM_WIFI_ENTRIES];
uint8_t selected; uint8_t selected;
// network stuff
uint32_t subnet_mask;
uint32_t dns_primary;
uint32_t dns_secondary;
}; };
// //

View File

@ -29,7 +29,8 @@ protected:
public: public:
TaskHandle_t createTask(TASK_FUNCTION task_function, const char *name, uint32_t stack_size, UBaseType_t priority, BaseType_t core); TaskHandle_t createTask(TASK_FUNCTION task_function, const char *name, uint32_t stack_size, UBaseType_t priority, BaseType_t core);
static uint32_t getStackHighWaterMark(TaskHandle_t task){ return (uint32_t)uxTaskGetStackHighWaterMark(task); } static uint32_t getStackHighWaterMark(TaskHandle_t task = NULL){ return (uint32_t)uxTaskGetStackHighWaterMark(task); }
static void deleteTask(TaskHandle_t task = NULL){ vTaskDelete(task); }
TaskFactory(); TaskFactory();
~TaskFactory(); ~TaskFactory();

View File

@ -18,30 +18,30 @@ Wifi::Wifi()
esp_log_level_set("wifi", ESP_LOG_WARN); esp_log_level_set("wifi", ESP_LOG_WARN);
esp_log_level_set("wifi_init", ESP_LOG_INFO); esp_log_level_set("wifi_init", ESP_LOG_INFO);
// memset(m_ignored, 0, SETTINGS_NUM_WIFI_ENTRIES);
WiFi.onEvent(std::bind(&Wifi::wifi_event, this, _1, _2)); WiFi.onEvent(std::bind(&Wifi::wifi_event, this, _1, _2));
#ifdef USE_TIMER
esp_timer_create_args_t timer;
timer.arg = this;
timer.callback = &timerCallback;
timer.dispatch_method = ESP_TIMER_TASK;
timer.skip_unhandled_events = true;
timer.name = "wifi countdown timer";
// esp_timer_create_args_t timer; ESP_ERROR_CHECK(esp_timer_create(&timer, &m_timer));
// timer.arg = this; ESP_ERROR_CHECK(esp_timer_start_periodic(m_timer, 60000000)); // 1 min
// timer.callback = &timerCallback; #endif
// timer.dispatch_method = ESP_TIMER_TASK;
// timer.skip_unhandled_events = true;
// timer.name = "wifi countdown timer";
// ESP_ERROR_CHECK(esp_timer_create(&timer, &m_timer));
// ESP_ERROR_CHECK(esp_timer_start_periodic(m_timer, 60000000)); // 1 min
// m_task = TASK_FACTORY.createTask(std::bind(&Wifi::wifiTask, this), "wifi task", 2048, 5, 0);
} }
// void Wifi::timerCallback(void* arg) #ifdef USE_TIMER
// { void Wifi::timerCallback(void* arg)
// for(int n = 0; n < SETTINGS_NUM_WIFI_ENTRIES; n++) {
// { for(int n = 0; n < SETTINGS_NUM_WIFI_ENTRIES; n++)
// if(((Wifi*)arg)->m_ignored[n] > 0) {
// ((Wifi*)arg)->m_ignored[n]--; if(((Wifi*)arg)->m_ignored[n] > 0)
// } ((Wifi*)arg)->m_ignored[n]--;
// } }
}
#endif
void Wifi::wifi_event(arduino_event_id_t event, arduino_event_info_t info) void Wifi::wifi_event(arduino_event_id_t event, arduino_event_info_t info)
{ {
@ -53,25 +53,29 @@ void Wifi::wifi_event(arduino_event_id_t event, arduino_event_info_t info)
} }
} }
// void Wifi::wifiTask() void Wifi::task()
// { {
// while(true) while(true)
// { {
// delay(1000); if(!WiFi.isConnected())
// ESP_LOGI(TAG, "in wifi task!"); {
// } m_wifi_status = WIFI_STATUS::PENDING;
// } m_wifi_status = startConnecting();
}
delay(15000);
}
}
/// @brief Connect to provisioned wifi /// @brief Connect to provisioned wifi
/// @param index index of wifi in settings /// @param index index of wifi in settings
/// @return ok/not connected /// @return WIFI_STATUS::CONNECTED/NOT_CONENCTED connected
uint32_t Wifi::connectTo(int index) Wifi::WIFI_STATUS Wifi::connectTo(int index)
{ {
IPAddress local_IP(0, 0, 0, 0); IPAddress local_IP(0, 0, 0, 0);
IPAddress gateway(0, 0, 0, 0); IPAddress gateway(0, 0, 0, 0);
IPAddress subnet(255, 255, 255, 0); IPAddress subnet(SETTINGS.wifi.subnet_mask);
IPAddress primaryDNS(8, 8, 8, 8); IPAddress primaryDNS(SETTINGS.wifi.dns_primary);
IPAddress secondaryDNS(8, 8, 4, 4); IPAddress secondaryDNS(SETTINGS.wifi.dns_secondary);
ESP_LOGI(TAG, "Connecting to %s...", SETTINGS.wifi.entry[index].ssid); ESP_LOGI(TAG, "Connecting to %s...", SETTINGS.wifi.entry[index].ssid);
@ -85,25 +89,45 @@ uint32_t Wifi::connectTo(int index)
if(status == WL_CONNECTED) if(status == WL_CONNECTED)
{ {
ESP_LOGI(TAG, "Connected"); ESP_LOGI(TAG, "Connected");
return WH_OK; return WIFI_STATUS::CONNECTED;
} }
WiFi.disconnect(); WiFi.disconnect();
ESP_LOGW(TAG, "Failed to connect"); ESP_LOGW(TAG, "Failed to connect");
return WH_ERR_WIFI_NOT_CONNECTED; return WIFI_STATUS::NOT_CONNECTED;
}
int Wifi::start()
{
if(m_task == nullptr)
{
ESP_LOGW(TAG, "Starting wifi");
m_task = TASK_FACTORY.createTask(std::bind(&Wifi::task, this), "wifi task", 4096, 5, 0);
}
return 0;
}
Wifi::WIFI_STATUS Wifi::waitForConnection()
{
Wifi::WIFI_STATUS st;
while((st = status()) == Wifi::WIFI_STATUS::PENDING)
delay(500);
return st;
} }
/// @brief Connects to wifi. Returns immediately if already connected. /// @brief Connects to wifi. Returns immediately if already connected.
/// @return WH_OK | WH_ERR_WIFI_NOT_PROVISIONED /// @return WH_OK | WH_ERR_WIFI_NOT_PROVISIONED
uint32_t Wifi::start() Wifi::WIFI_STATUS Wifi::startConnecting()
{ {
if(SETTINGS.wifi.num == 0) if(SETTINGS.wifi.num == 0)
{ {
ESP_LOGE(TAG, "Not provisioned!"); ESP_LOGE(TAG, "Not provisioned!");
return WH_ERR_WIFI_NOT_PROVISIONED; return WIFI_STATUS::NOT_PROVISIONED;
} }
if(WiFi.isConnected()) if(WiFi.isConnected())
return WH_OK; return WIFI_STATUS::CONNECTED;
// if only one network is provisioned // if only one network is provisioned
if(SETTINGS.wifi.num == 1) if(SETTINGS.wifi.num == 1)
@ -111,14 +135,14 @@ uint32_t Wifi::start()
SETTINGS.wifi.selected = 0; SETTINGS.wifi.selected = 0;
for(int n = 0; n < 3; n++) for(int n = 0; n < 3; n++)
{ {
if(connectTo(SETTINGS.wifi.selected) == WH_OK) if(connectTo(SETTINGS.wifi.selected) == WIFI_STATUS::CONNECTED)
return WH_OK; return WIFI_STATUS::CONNECTED;
WiFi.disconnect(); WiFi.disconnect();
} }
ESP_LOGW(TAG, "Cannot connect, need provisioning"); ESP_LOGE(TAG, "Not connected");
return WH_ERR_WIFI_NOT_PROVISIONED; return WIFI_STATUS::NOT_CONNECTED;
} }
// multiple networks are provisioned. Use either specific network or scan for highest rssi // multiple networks are provisioned. Use either specific network or scan for highest rssi
@ -130,12 +154,12 @@ uint32_t Wifi::start()
ssid_ix = scan(); ssid_ix = scan();
if(ssid_ix < 0) if(ssid_ix < 0)
return WH_ERR_WIFI_NOT_PROVISIONED; return WIFI_STATUS::NOT_PROVISIONED;
if(connectTo(ssid_ix) == WH_OK) if(connectTo(ssid_ix) == WH_OK)
{ {
SETTINGS.wifi.selected = ssid_ix; SETTINGS.wifi.selected = ssid_ix;
return WH_OK; return WIFI_STATUS::CONNECTED;
} }
// didn't work. go through them all giving priority to one with highest rssi // didn't work. go through them all giving priority to one with highest rssi
@ -148,7 +172,7 @@ uint32_t Wifi::start()
if(ssid_ix >= 0) if(ssid_ix >= 0)
{ {
if(connectTo(ssid_ix) == WH_OK) if(connectTo(ssid_ix) == WH_OK)
return WH_OK; return WIFI_STATUS::CONNECTED;
else else
m_ignored[ssid_ix] = IGNORE_SSID_MINS; m_ignored[ssid_ix] = IGNORE_SSID_MINS;
} }
@ -164,12 +188,12 @@ uint32_t Wifi::start()
for(int n = 0; n < SETTINGS.wifi.num; n++) for(int n = 0; n < SETTINGS.wifi.num; n++)
{ {
if(connectTo(n) == WH_OK) if(connectTo(n) == WH_OK)
return WH_OK; return WIFI_STATUS::CONNECTED;
} }
} }
ESP_LOGW(TAG, "Cannot connect, need provisioning"); ESP_LOGE(TAG, "Cannot connect, need provisioning");
return WH_ERR_WIFI_NOT_PROVISIONED; return WIFI_STATUS::NOT_PROVISIONED;
} }
/// @brief Scans all visible ssid's and picks known ssid with highest rssi that is not ignored. /// @brief Scans all visible ssid's and picks known ssid with highest rssi that is not ignored.

View File

@ -8,16 +8,33 @@
#include "Settings.h" #include "Settings.h"
#include "TaskFactory.h" #include "TaskFactory.h"
#define _USE_TIMER
class Wifi class Wifi
{ {
public:
typedef enum
{
NOT_CONNECTED,
PENDING,
NOT_PROVISIONED,
CONNECTED
} WIFI_STATUS;
protected: protected:
uint8_t m_ignored[SETTINGS_NUM_WIFI_ENTRIES]; uint8_t m_ignored[SETTINGS_NUM_WIFI_ENTRIES];
// esp_timer_handle_t m_timer; WIFI_STATUS m_wifi_status = WIFI_STATUS::NOT_CONNECTED;
// static void timerCallback(void* arg);
// TaskHandle_t m_task = nullptr;
// void wifiTask();
uint32_t connectTo(int index); #ifdef USE_TIMER
esp_timer_handle_t m_timer;
static void timerCallback(void* arg);
#endif
TaskHandle_t m_task = nullptr;
void task();
WIFI_STATUS startConnecting();
WIFI_STATUS connectTo(int index);
int scan(); int scan();
public: public:
@ -27,7 +44,9 @@ protected:
void wifi_event(arduino_event_id_t event, arduino_event_info_t info); void wifi_event(arduino_event_id_t event, arduino_event_info_t info);
public: public:
uint32_t start(); int start();
WIFI_STATUS status() { return m_wifi_status; }
WIFI_STATUS waitForConnection();
}; };
#endif /* __WIFI_H__ */ #endif /* __WIFI_H__ */

View File

@ -6,6 +6,7 @@
#include <esp_log.h> #include <esp_log.h>
#include <SPI.h> #include <SPI.h>
#include <errno.h> #include <errno.h>
#include "TaskFactory.h"
#include "esp_task_wdt.h" #include "esp_task_wdt.h"
#include "App.h" #include "App.h"
@ -19,9 +20,13 @@ extern "C" void app_main(void)
ESP_ERROR_CHECK(esp_task_wdt_init(15, false)); ESP_ERROR_CHECK(esp_task_wdt_init(15, false));
ESP_LOGI(TAG, "Starting app..."); ESP_LOGW(TAG, "Starting the app...");
App * app = new App(); App * app = new App();
app->init(); app->init();
app->start(); app->start();
ESP_LOGI(TAG, "stack high water mark %d", TaskFactory::getStackHighWaterMark());
// we're no longer needed
TaskFactory::deleteTask();
} }