Compare commits

...

13 Commits

Author SHA1 Message Date
88998b8201 switched ota from bigfoot to wellno, mqtt from azure to wellnuo 2025-03-13 12:57:42 -07:00
5b88bdec9f updated azure root certificate 2025-03-13 11:36:35 -07:00
a984b7a6a6 updated azure root certificate 2024-09-02 12:27:45 -07:00
58d034173e fixed a mqtt connecting/sending issue 2024-08-19 15:37:38 -07:00
060a831abd updated mqtt client certificate, added counter to mqtt connect fail and reset after 100 consecutive failed attempts, provision wifi connect check also uses retry 2024-08-18 14:03:38 -07:00
cbe99e6f79 added delay and increaset retry count for connecting to wifi, WiFi.SSID(n) is no longer corrupted. Root cause unknown 2024-07-28 15:48:46 -07:00
de8b89fd19 mqtt now has pin that unlocks commands for 10s - pin command, added mac command to return full mac address 2024-07-25 10:58:35 -07:00
ee77bb4e78 mqtt client id is now a mac address, fixing issue of not being able to have more than one tag connected at the time. Logo and html is updated. Tag will now correctly go into and stay in provision for 2 minutes before reset if it wasn't able to connect to wifi 2024-07-22 13:52:16 -07:00
aa93a71fa1 early BLE init 2024-07-21 20:13:33 -07:00
2b7260135e Merge branch 'dev'
command processor linked to BLE and mqtt
2024-07-21 19:16:38 -07:00
88979da2d6 added command processor linked to BLE and mqtt 2024-07-21 19:15:49 -07:00
ccd3e4ebbe before vacation 2024-06-24 12:12:47 -07:00
842ba81333 sensor stuff 2024-06-13 13:12:46 -07:00
34 changed files with 702 additions and 222 deletions

View File

@ -2,6 +2,10 @@
# CMakeLists in this exact order for cmake to work correctly # CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5) cmake_minimum_required(VERSION 3.5)
execute_process(COMMAND git describe --always --tags --dirty
OUTPUT_VARIABLE WH_VERSION
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
add_definitions("-DWH_VERSION=\"${WH_VERSION}\"")
include($ENV{IDF_PATH}/tools/cmake/project.cmake) include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(wellhub) project(wellhub)

View File

@ -1,3 +1,6 @@
# merge with accepting all incoming changes
git merge [branch] --strategy-option theirs
# MQTT Server # MQTT Server
MQTT server: MQTT server:
@ -6,6 +9,8 @@ MQTT server:
# Getting server certificate: # Getting server certificate:
openssl s_client -showcerts -connect mqtt-dev-server.westus2-1.ts.eventgrid.azure.net:8883
openssl s_client -showcerts -connect mqtt-dev-server.westus2-1.ts.eventgrid.azure.net:8883 </dev/null 2>/dev/null|openssl x509 -outform PEM >eventgrid.azure.pem openssl s_client -showcerts -connect mqtt-dev-server.westus2-1.ts.eventgrid.azure.net:8883 </dev/null 2>/dev/null|openssl x509 -outform PEM >eventgrid.azure.pem
This produces eventgrid.azure.pem certificate file. This produces eventgrid.azure.pem certificate file.
@ -21,12 +26,12 @@ openssl s_client -showcerts -connect mqtt-dev-server.westus2-1.ts.eventgrid.azur
openssl s_client -showcerts -verify 5 -connect mqtt-dev-server.westus2-1.ts.eventgrid.azure.net:8883 < /dev/null openssl s_client -showcerts -verify 5 -connect mqtt-dev-server.westus2-1.ts.eventgrid.azure.net:8883 < /dev/null
openssl s_client -showcerts -verify 5 -connect mqtt-dev-server.westus2-1.ts.eventgrid.azure.net:8883 < /dev/null | openssl s_client -showcerts -verify 5 -connect mqtt-dev-server.westus2-1.ts.eventgrid.azure.net:8883 < /dev/null | awk '/BEGIN CERTIFICATE/,/END CERTIFICATE/{ if(/BEGIN CERTIFICATE/){a++}; out="cert"a".pem"; print >out}'
awk '/BEGIN CERTIFICATE/,/END CERTIFICATE/{ if(/BEGIN CERTIFICATE/){a++}; out="cert"a".pem"; print >out}'
for cert in *.pem; do for cert in *.pem; do
newname=$(openssl x509 -noout -subject -in $cert | sed -nE 's/.*CN ?= ?(.*)/\1/; s/[ ,.*]/_/g; s/__/_/g; s/_-_/-/; s/^_//g;p' | tr '[:upper:]' '[:lower:]').pem newname=$(openssl x509 -noout -subject -in $cert | sed -nE 's/.*CN ?= ?(.*)/\1/; s/[ ,.*]/_/g; s/__/_/g; s/_-_/-/; s/^_//g;p' | tr '[:upper:]' '[:lower:]').pem
echo "${newname}"; mv "${cert}" "${newname}" echo "${newname}"; mv "${cert}" "${newname}"
done done
convert crl to pem convert crl to pem
openssl crl -in "Microsoft Azure ECC TLS Issuing CA 08 - xsign.crt" -inform PEM -out "Microsoft Azure ECC TLS Issuing CA 08 - xsign.pem" openssl crl -in "Microsoft Azure ECC TLS Issuing CA 08 - xsign.crt" -inform PEM -out "Microsoft Azure ECC TLS Issuing CA 08 - xsign.pem"

View File

@ -1,31 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw
WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP
R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx
sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm
NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg
Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG
/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC
AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB
Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA
FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw
AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw
Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB
gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W
PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl
ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz
CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm
lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4
avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2
yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O
yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids
hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+
HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv
MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX
nLRbwHOoq7hHwg==
-----END CERTIFICATE-----

View File

@ -1,5 +0,0 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIHfQeOcidLM6BkYrM6T3psiYhdvf3Xi47RdCO9UUTJS0oAoGCCqGSM49
AwEHoUQDQgAE8/zOkgtPi53H+J4TEt7WLam+HpzBpwPPIGnXe1j0aw8AW0IXf3C5
9dNjXblYkMnfJetfGC+F1RGit8wltxa/1A==
-----END EC PRIVATE KEY-----

View File

@ -1,13 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIB8DCCAZagAwIBAgIRAOkYhrcCE+j1PLQ9BDCRPEcwCgYIKoZIzj0EAwIwRjEZ
MBcGA1UEChMQTXF0dEFwcFNhbXBsZXNDQTEpMCcGA1UEAxMgTXF0dEFwcFNhbXBs
ZXNDQSBJbnRlcm1lZGlhdGUgQ0EwHhcNMjQwNTAyMTAxNzU0WhcNMjQwODEwMTAx
NzQ5WjAbMRkwFwYDVQQDExBjbGllbnQxLWF1dGhuLUlEMFkwEwYHKoZIzj0CAQYI
KoZIzj0DAQcDQgAE8/zOkgtPi53H+J4TEt7WLam+HpzBpwPPIGnXe1j0aw8AW0IX
f3C59dNjXblYkMnfJetfGC+F1RGit8wltxa/1KOBjzCBjDAOBgNVHQ8BAf8EBAMC
B4AwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBQZzhke
y2EVMhqXkvS8f0ShvbfU6TAfBgNVHSMEGDAWgBTP6P7nCctF0+5MHQFtdHOS+9ir
1zAbBgNVHREEFDASghBjbGllbnQxLWF1dGhuLUlEMAoGCCqGSM49BAMCA0gAMEUC
IQCjPsQCjTZl+OySx5ggC7501bJ4+aFvFjPgWBPzF/qiNQIgYzyLOyOJqadWYh85
usAECzpgqLWVXQOkYbqdicc3CtI=
-----END CERTIFICATE-----

View File

@ -1,20 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDXDCCAuOgAwIBAgIQDvLl2DaBUgJV6Sxgj7wv9DAKBggqhkjOPQQDAzBhMQsw
CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe
Fw0yMzA2MDgwMDAwMDBaFw0yNjA4MjUyMzU5NTlaMF0xCzAJBgNVBAYTAlVTMR4w
HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xLjAsBgNVBAMTJU1pY3Jvc29m
dCBBenVyZSBFQ0MgVExTIElzc3VpbmcgQ0EgMDgwdjAQBgcqhkjOPQIBBgUrgQQA
IgNiAATlQzoKIJQIe8bd4sX2x9XBtFvoh5m7Neph3MYORvv/rg2Ew7Cfb00eZ+zS
njUosyOUCspenehe0PyKtmq6pPshLu5Ww/hLEoQT3drwxZ5PaYHmGEGoy2aPBeXa
23k5ruijggFiMIIBXjASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBStVB0D
VHHGL17WWxhYzm4kxdaiCjAfBgNVHSMEGDAWgBSz20ik+aHF2K42QcwRY2liKbxL
xjAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC
MHYGCCsGAQUFBwEBBGowaDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNl
cnQuY29tMEAGCCsGAQUFBzAChjRodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20v
RGlnaUNlcnRHbG9iYWxSb290RzMuY3J0MEIGA1UdHwQ7MDkwN6A1oDOGMWh0dHA6
Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RHMy5jcmwwHQYD
VR0gBBYwFDAIBgZngQwBAgEwCAYGZ4EMAQICMAoGCCqGSM49BAMDA2cAMGQCMD+q
5Uq1fSGZSKRhrnWKKXlp4DvfZCEU/MF3rbdwAaXI/KVM65YRO9HvRbfDpV3x1wIw
CHvqqpg/8YJPDn8NJIS/Rg+lYraOseXeuNYzkjeY6RLxIDB+nLVDs9QJ3/co89Cd
-----END CERTIFICATE-----

24
certs/newca.crt Executable file
View File

@ -0,0 +1,24 @@
-----BEGIN CERTIFICATE-----
MIID8zCCAtugAwIBAgIUCpTomBd4w0aRhwdQVfnrdUn9iQ4wDQYJKoZIhvcNAQEL
BQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMREwDwYDVQQH
DAhTYXJhdG9nYTEUMBIGA1UECgwLV2VsbG51byBMTEMxGDAWBgNVBAMMD1dlbGxO
dWEgTVFUVCBDQTEhMB8GCSqGSIb3DQEJARYScm9iZXJ0QHdlbGxudW8uY29tMB4X
DTI1MDMwOTA3MTYwMloXDTM1MDMwNzA3MTYwMlowgYgxCzAJBgNVBAYTAlVTMRMw
EQYDVQQIDApDYWxpZm9ybmlhMREwDwYDVQQHDAhTYXJhdG9nYTEUMBIGA1UECgwL
V2VsbG51byBMTEMxGDAWBgNVBAMMD1dlbGxOdWEgTVFUVCBDQTEhMB8GCSqGSIb3
DQEJARYScm9iZXJ0QHdlbGxudW8uY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEA0ZnbdUe6Bv3syydl7OZfjYe0MgvqxW3fwSVH2XIzd8NhQ9aqtr2T
Nq2Gkdh3YYgBnnM208NA1T11Be0v1a1bZr3hwPLTuoZrRuyg1Z6fBeWnjBDn+6ga
bEmo4lPbJBjY7AQTgM2U6QsLD9mhw6Od/gGDaxlwlD5wVD+zCIi+iMeKqthAodoF
rnrNQUlUR1pb1if0LuCaZXoCuyok/nOKZcZ62D6TGCaWda8nFB5CWaT4+nqejDSj
w3n2/wZNDyGOne5kB7Yw10ZoyDihZ6E8Vt9kqJenvRnm+sSRr3k5UGPnD5GK508W
Ta+DJlKDWUKe+gwDE8cv6pEU5DnfQzL+OQIDAQABo1MwUTAdBgNVHQ4EFgQUGyfP
aqXbMVml5YL+xnO4PoFepSAwHwYDVR0jBBgwFoAUGyfPaqXbMVml5YL+xnO4PoFe
pSAwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEASRLZrSwfTrWm
OylkF4kmMkP88CbYTRUk3ZYaG7TZARjR5U+HmH103iUts8i6hMVG/T1dL916ujsG
IQgmwH71ImxGJ/P/JGZLqwC6jRZraC2J6SCWshPDjO4Kmc5K+kb+4lkTy9qf1Wbd
JpcCjLCRtxUUjML4r31vE0Xim4t7Crkd8ZFD00irWzxsV2Q0PlJPWjh3Y/OpIEQJ
Lf+S0BMMxskP1/PXQCZUQrrZrKU8yEz8kefrJ5x+zDgvzrD3dD/wI0we9xgeUQSm
PQer1RkyDUbeU6j9hXjDRoAanvsgzdj7NyAReeEd7ksCEFigk3C6nczuiJWv0jW3
KKc75wm2Aw==
-----END CERTIFICATE-----

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -389,15 +389,15 @@ input {
<input type="button" onClick="onButton1()" name="button3" id="button1" value="Button1"> <input type="button" onClick="onButton1()" name="button3" id="button1" value="Button1">
<input type="button" onClick="onButton2()" name="button4" id="button2" value="Button2"> <input type="button" onClick="onButton2()" name="button4" id="button2" value="Button2">
</div> </div>
<h2>Timmah's special WiFi configuration and stuff</h2> <h2>Welcome to WellHub Wifi intialization</h2>
<p><img src="logo.png" alt=""/><br> <p><img src="logo.png" alt=""/><br>
</p> </p>
<div id="msg_ok"> <div id="msg_ok">
<h3>Timmah has ben successfully configured and it is ready for normal use.<br>You can now close this window.</h3> <h3>WellHub has ben successfully configured and it is ready for normal use.<br>You can now close this window.</h3>
</div> </div>
<div id="msg_error"> <div id="msg_error">
<h3>Timmah was not able to connect to selected WiFi. Please check the spelling and password.</h3> <h3>WellHub was not able to connect to selected WiFi. Please check the spelling and password.</h3>
</div> </div>
<div id="wait_scan"> <div id="wait_scan">
<h3>Please wait, scanning local WiFi...</h3> <h3>Please wait, scanning local WiFi...</h3>

View File

@ -29,17 +29,41 @@ CircBuffer * App::getBuffer()
return & m_circ_buffer; return & m_circ_buffer;
} }
CommandProcessor * App::getCommandProcessor()
{
return m_commandProcessor;
}
void App::init() void App::init()
{ {
#pragma message(WH_VERSION)
ESP_LOGW(TAG, "Starting the app..."); ESP_LOGW(TAG, "Starting the app...");
uint8_t mac[8];
esp_read_mac(mac, ESP_MAC_WIFI_STA);
ESP_LOGI(TAG, "mqtt_id: %s, wifi mac: %02x:%02x:%02x:%02x:%02x:%02x ...", SETTINGS.mqtt.device_id,
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
m_led = new Led(LED_PIN); m_led = new Led(LED_PIN);
m_wifi = new Wifi(); m_wifi = new Wifi();
#if 1 m_commandProcessor = new CommandProcessor(*this);
m_ble_service = new BleService(*this);
m_ble_service->start();
bool needs_provision = true; bool needs_provision = true;
#if 0
ESP_LOGI(TAG, "Scanning wifi networks...");
int num_networks = WiFi.scanNetworks(false, false, false, 0);
for(int n = 0; n < num_networks; n++)
{
ESP_LOGI(TAG, "%s, %d", WiFi.SSID(n).c_str(), WiFi.RSSI(n));
}
#endif
if(SETTINGS.wifi.num > 0) if(SETTINGS.wifi.num > 0)
{ {
// try connecting // try connecting
@ -69,6 +93,8 @@ void App::init()
needs_provision = false; needs_provision = false;
} }
else
m_wifi->pause(true);
} }
if(needs_provision) if(needs_provision)
@ -80,16 +106,12 @@ void App::init()
otaCheck(); otaCheck();
m_led->setPulse(255, 0, 255); // m_led->setPulse(255, 0, 255);
m_led->setColor(0, 0, 0);
m_mqtt_service = new MqttService(*this); m_mqtt_service = new MqttService(*this);
m_mqtt_service->start(); m_mqtt_service->start();
m_ble_service = new BleService(*this);
m_ble_service->start();
#endif
m_sensor_service = new SensorService(*this); m_sensor_service = new SensorService(*this);
m_sensor_service->start(); m_sensor_service->start();
} }

View File

@ -12,6 +12,7 @@
#include "BleService.h" #include "BleService.h"
#include "Buffers.h" #include "Buffers.h"
#include "sensors/SensorService.h" #include "sensors/SensorService.h"
#include "CommandProcessor.h"
#include "AppIF.h" #include "AppIF.h"
class App : AppIF class App : AppIF
@ -23,10 +24,12 @@ protected:
SensorService * m_sensor_service = nullptr; SensorService * m_sensor_service = nullptr;
CircBuffer m_circ_buffer; CircBuffer m_circ_buffer;
Led * m_led = nullptr; Led * m_led = nullptr;
CommandProcessor * m_commandProcessor = nullptr;
public: public:
Led * getLed() override; Led * getLed() override;
CircBuffer * getBuffer() override; CircBuffer * getBuffer() override;
CommandProcessor * getCommandProcessor() override;
public: public:
App(); App();

View File

@ -3,12 +3,14 @@
class Led; class Led;
class CircBuffer; class CircBuffer;
class CommandProcessor;
class AppIF class AppIF
{ {
public: public:
virtual Led * getLed() = 0; virtual Led * getLed() = 0;
virtual CircBuffer * getBuffer() = 0; virtual CircBuffer * getBuffer() = 0;
virtual CommandProcessor * getCommandProcessor() = 0;
}; };
#endif #endif

View File

@ -14,7 +14,7 @@ static const char * TAG = "ble";
BleService::BleService(App & app) : m_app(app) BleService::BleService(App & app) : m_app(app)
{ {
m_rw = new ReaderWriter(512);
} }
void BleService::start() void BleService::start()
@ -24,7 +24,7 @@ void BleService::start()
uint8_t wifi_mac[8]; uint8_t wifi_mac[8];
esp_read_mac(wifi_mac, ESP_MAC_WIFI_STA); esp_read_mac(wifi_mac, ESP_MAC_WIFI_STA);
sprintf(m_name, "WP_%u_%02x%02x%02x", SETTINGS.device.id, wifi_mac[3], wifi_mac[4], wifi_mac[5]); sprintf(m_name, "WP_%s_%02x%02x%02x", SETTINGS.mqtt.device_id, wifi_mac[3], wifi_mac[4], wifi_mac[5]);
NimBLEDevice::init(m_name); NimBLEDevice::init(m_name);
NimBLEDevice::setMTU(512); NimBLEDevice::setMTU(512);
@ -64,49 +64,19 @@ void BleService::onDisconnect(NimBLEServer* pServer)
void BleService::onRead(NimBLECharacteristic* pCharacteristic) void BleService::onRead(NimBLECharacteristic* pCharacteristic)
{ {
int a = 1234; // int a = 1234;
pCharacteristic->setValue(a); // pCharacteristic->setValue(a);
ESP_LOGI(TAG, "onRead hello"); // ESP_LOGI(TAG, "onRead hello");
} }
void BleService::onWrite(NimBLECharacteristic* pCharacteristic) void BleService::onWrite(NimBLECharacteristic* pCharacteristic)
{ {
uint32_t len = pCharacteristic->getDataLength(); m_app.getCommandProcessor()->take();
memcpy(m_buffer, pCharacteristic->getValue().c_str(), len); char * buffer = m_app.getCommandProcessor()->process(pCharacteristic->getValue().c_str(), pCharacteristic->getDataLength());
m_buffer[len] = 0; if(buffer != nullptr && strlen(buffer) != 0)
ESP_LOGI(TAG, "'%s'", m_buffer);
Parser p((char *)m_buffer, "|");
char buffer[80];
p.getElementAt(0, buffer, sizeof(buffer));
ESP_LOGI(TAG, "command '%s'", buffer);
if(buffer[0] == 'w')
{ {
ESP_LOGI(TAG, "Scanning wifi networks..."); pCharacteristic->setValue((uint8_t*)buffer, strlen(buffer));
int num_networks = WiFi.scanNetworks(false, false, false, 0);
m_rw->reset();
m_rw->appendf("w|%d|", num_networks);
for(int n = 0; n < num_networks; n++)
{
m_rw->append(WiFi.SSID(n).c_str());
m_rw->append(",");
m_rw->appendf("%d", WiFi.RSSI(n));
if(n < num_networks-1)
m_rw->append("|");
}
ESP_LOGI(TAG, "'%s'", m_rw->getBuffer());
pCharacteristic->setValue((uint8_t*)m_rw->getBuffer(), m_rw->getLen());
pCharacteristic->notify(); pCharacteristic->notify();
} }
else if(buffer[0] == 'd') m_app.getCommandProcessor()->give();
{
SETTINGS.wifi.num = 0;
SETTINGS_SAVE;
esp_restart();
}
} }

View File

@ -5,7 +5,6 @@
#include <stdint.h> #include <stdint.h>
#include <NimBLEDevice.h> #include <NimBLEDevice.h>
#include "ReaderWriter.h"
class App; class App;
@ -14,14 +13,12 @@ class BleService : public NimBLEServerCallbacks, NimBLECharacteristicCallbacks
protected: protected:
App & m_app; App & m_app;
char m_name[32]; char m_name[75];
char m_buffer[512];
NimBLEServer * m_server = nullptr; NimBLEServer * m_server = nullptr;
NimBLEService * m_service = nullptr; NimBLEService * m_service = nullptr;
NimBLECharacteristic * m_characteristic = nullptr; NimBLECharacteristic * m_characteristic = nullptr;
NimBLEAdvertising * m_advertising = nullptr; NimBLEAdvertising * m_advertising = nullptr;
ReaderWriter *m_rw = nullptr;
void onConnect(NimBLEServer* pServer) override; void onConnect(NimBLEServer* pServer) override;
void onDisconnect(NimBLEServer* pServer) override; void onDisconnect(NimBLEServer* pServer) override;

View File

@ -1,9 +1,10 @@
idf_component_register(SRCS main.cpp App.cpp Settings.cpp Led.cpp TaskMgr.cpp Wifi.cpp utilities.cpp idf_component_register(SRCS main.cpp App.cpp Settings.cpp Led.cpp TaskMgr.cpp Wifi.cpp utilities.cpp
ProvisionSoftAP.cpp ReaderWriter.cpp Ota.cpp MqttService.cpp BleService.cpp sensors/Bmp280.cpp ProvisionSoftAP.cpp ReaderWriter.cpp Ota.cpp MqttService.cpp BleService.cpp sensors/Bmp280.cpp
sensors/Bme68x.cpp sensors/SensorService.cpp sensors/LD2410.cpp Buffers.cpp SensorData.cpp sensors/Bme68x.cpp sensors/SensorService.cpp sensors/LD2410.cpp Buffers.cpp SensorData.cpp
CommandProcessor.cpp
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 ../certs/bigfoot-inc.pem EMBED_TXTFILES ../certs/newca.crt
) )
#message(FATAL_ERROR "error ${ROLE}") #message(FATAL_ERROR "error ${ROLE}")

273
main/CommandProcessor.cpp Normal file
View File

@ -0,0 +1,273 @@
#include <esp_log.h>
#include "CommandProcessor.h"
#include "utilities.h"
#include "Settings.h"
#include <WiFi.h>
const char * TAG = "CommandProcessor";
CommandProcessor::CommandProcessor(AppIF & app) : m_app(app), m_rw(512)
{
}
#define BUF_LEN 128
char * getElementAt(int el, Parser & p, char * buffer)
{
buffer[0] = 0;
p.getElementAt(el, buffer, BUF_LEN);
return buffer;
}
bool CommandProcessor::cmdSetGroupId(Parser & p, char * buffer)
{
int value = 0;
if(strToInt(getElementAt(1, p, buffer), value))
{
ESP_LOGW(TAG, "new group value: %u", value);
SETTINGS.device.group_id = value;
SETTINGS_SAVE;
strcpy(m_buffer, "Z|ok");
return true;
}
strcpy(m_buffer, "Z|fail");
return false;
}
bool CommandProcessor::cmdSetWorkingId(Parser & p, char * buffer)
{
int value = 0;
if(strToInt(getElementAt(1, p, buffer), value))
{
ESP_LOGW(TAG, "new device working id: %u", value);
SETTINGS.device.tata_id = value;
SETTINGS_SAVE;
strcpy(m_buffer, "-|ok");
return true;
}
strcpy(m_buffer, "-|fail");
return false;
}
bool CommandProcessor::cmdRestart(Parser & p, char * buffer)
{
esp_restart();
return true;
}
bool CommandProcessor::cmdDeleteStoredSsids(Parser & p, char * buffer)
{
ESP_LOGW(TAG, "delete stored ssid's");
SETTINGS.wifi.num = 0;
SETTINGS_SAVE;
strcpy(m_buffer, "d|ok");
return true;
}
bool CommandProcessor::cmdReturnCurrentSsid(Parser & p, char * buffer)
{
ESP_LOGW(TAG, "return current ssid %s and rssi %d", WiFi.SSID().c_str(), WiFi.RSSI());
m_rw.reset();
m_rw.appendf("a|%s,%d", WiFi.SSID().c_str(), WiFi.RSSI());
ESP_LOGI(TAG, "'%s'", m_rw.getBuffer());
// "a|gumball,-42"
strcpy(m_buffer, m_rw.getBuffer());
return true;
}
bool CommandProcessor::cmdReturnVisibleNetworks(Parser & p, char * buffer)
{
ESP_LOGI(TAG, "Scanning wifi networks...");
int num_networks = WiFi.scanNetworks(false, false, false, 0);
m_rw.reset();
m_rw.appendf("w|%d|", num_networks);
for(int n = 0; n < num_networks; n++)
{
m_rw.append(WiFi.SSID(n).c_str());
m_rw.append(",");
m_rw.appendf("%d", WiFi.RSSI(n));
if(n < num_networks - 1)
m_rw.append("|");
}
ESP_LOGI(TAG, "'%s'", m_rw.getBuffer());
// "w|4|gumball,-40|miro,-79|903noe,-84|TheGoodPlace-2.4,-93"
strcpy(m_buffer, m_rw.getBuffer());
return true;
}
bool CommandProcessor::cmdAddNetwork(Parser & p, char * buffer)
{
if(p.getElementAt(1, buffer, BUF_LEN))
{
ESP_LOGI(TAG, "ssid/pwd: '%s'", buffer);
char ssid[36], pwd[36];
Parser pp(buffer, ",");
if(pp.getElementAt(0, ssid, sizeof(ssid)))
{
ESP_LOGI(TAG, "ssid: %s", ssid);
if(pp.getElementAt(1, pwd, sizeof(pwd)))
{
ESP_LOGI(TAG, "pwd: %s", pwd);
if(SETTINGS.wifi.num < SETTINGS_NUM_WIFI_ENTRIES - 1)
{
int ix = SETTINGS.wifi.num;
strcpy(SETTINGS.wifi.entry[ix].ssid, ssid);
strcpy(SETTINGS.wifi.entry[ix].pwd, pwd);
SETTINGS.wifi.num = ix + 1;
SETTINGS_SAVE;
strcpy(m_buffer, "W|ok");
return true;
}
}
}
}
strcpy(m_buffer, "W|fail");
return false;
}
bool CommandProcessor::cmdReportAllSettings(Parser & p, char * buffer)
{
int64_t up_time = esp_timer_get_time();
m_rw.reset();
m_rw.appendf("-,%u", SETTINGS.device.tata_id); //wid
m_rw.append("|");
m_rw.appendf("Z,%u", SETTINGS.device.group_id); //group id
m_rw.append("|");
m_rw.appendf("0,%s", SETTINGS.mqtt.device_id); //client id mwtt client id(text)
m_rw.append("|");
m_rw.appendf("2,%u", up_time/1000000); //time since reboot (seconds)
m_rw.append("|");
m_rw.append("5,");
for(int n = 0; n < SETTINGS.wifi.num; n++)
{
m_rw.append(SETTINGS.wifi.entry[n].ssid);
m_rw.append("\t");
m_rw.append(SETTINGS.wifi.entry[n].pwd);
if(n < SETTINGS.wifi.num - 1)
m_rw.append("\n");
}
m_rw.append("|");
m_rw.appendf("9,%.3f", SETTINGS.sensors.temperature.temp_offset); //temp offset
strcpy(m_buffer, m_rw.getBuffer());
return true;
}
bool CommandProcessor::cmdSetMqttDevId(Parser & p, char * buffer)
{
if(p.getElementAt(1, buffer, BUF_LEN))
{
ESP_LOGI(TAG, "new mqtt dev id: '%s'", buffer);
strcpy(SETTINGS.mqtt.device_id, buffer);
SETTINGS_SAVE;
strcpy(m_buffer, "0|ok");
return true;
}
strcpy(m_buffer, "0|fail");
return true;
}
bool CommandProcessor::cmdSetTemperatureOffset(Parser & p, char * buffer)
{
float value = 0;
if(strToFloat(getElementAt(1, p, buffer), value))
{
ESP_LOGW(TAG, "new temp offset: %f", value);
SETTINGS.sensors.temperature.temp_offset = value;
SETTINGS_SAVE;
strcpy(m_buffer, "9|ok");
return true;
}
strcpy(m_buffer, "9|fail");
return false;
}
bool CommandProcessor::cmdAuth(Parser & p, char * buffer)
{
int value = 0;
if(strToInt(getElementAt(1, p, buffer), value))
{
if(value == 7856)
{
m_authenticated = true;
m_auth_time = millis();
ESP_LOGW(TAG, "Authenticated for 10s");
strcpy(m_buffer, "pin|ok");
return true;
}
}
return false;
}
bool CommandProcessor::cmdReadFullMac(Parser & p, char * buffer)
{
uint8_t wifi_mac[8];
esp_read_mac(wifi_mac, ESP_MAC_WIFI_STA);
m_rw.reset();
m_rw.appendf("mac,%02x%02x%02x%02x%02x%02x", wifi_mac[0], wifi_mac[1], wifi_mac[2], wifi_mac[3], wifi_mac[4], wifi_mac[5]);
strcpy(m_buffer, m_rw.getBuffer());
return true;
}
#define COMMAND_START if(false){}
#define COMMAND(command, function) else if(strcmp(command, getElementAt(0, p, temp)) == 0) function(p, temp)
#define COMMAND_END else strcpy(m_buffer, "error");
char * CommandProcessor::process(const char * data, uint32_t len)
{
ESP_LOGI(TAG, "%s", data);
Parser p((char *)data, "|");
char temp[BUF_LEN];
if(strcmp("pin", getElementAt(0, p, temp)) == 0)
{
cmdAuth(p, temp);
return m_buffer;
}
if(millis() - m_auth_time > 10000)
{
ESP_LOGI(TAG, "nut autorized");
m_buffer[0] = 0;
return m_buffer;
}
m_auth_time = millis();
COMMAND_START
COMMAND("mac", cmdReadFullMac);
COMMAND("Z", cmdSetGroupId);
COMMAND("0", cmdSetMqttDevId);
COMMAND("-", cmdSetWorkingId);
COMMAND("s", cmdRestart);
COMMAND("d", cmdDeleteStoredSsids);
COMMAND("a", cmdReturnCurrentSsid);
COMMAND("w", cmdReturnVisibleNetworks);
COMMAND("W", cmdAddNetwork);
COMMAND("r", cmdReportAllSettings);
COMMAND("9", cmdSetTemperatureOffset);
COMMAND_END;
if(!m_authenticated)
m_buffer[0] = 0;
return m_buffer;
}

35
main/CommandProcessor.h Normal file
View File

@ -0,0 +1,35 @@
#include <stdint.h>
#include <System.h>
#include "ReaderWriter.h"
#include "AppIF.h"
class CommandProcessor : public Mutex
{
protected:
AppIF & m_app;
Mutex m_mutex;
ReaderWriter m_rw;
char m_buffer[512];
bool m_authenticated = false;
uint32_t m_auth_time = 0;
public:
CommandProcessor(AppIF & app);
public:
char * process(const char * data, uint32_t len = 0);
protected:
bool cmdSetGroupId(Parser & p, char * buffer);
bool cmdSetWorkingId(Parser & p, char * buffer);
bool cmdRestart(Parser & p, char * buffer);
bool cmdDeleteStoredSsids(Parser & p, char * buffer);
bool cmdReturnCurrentSsid(Parser & p, char * buffer);
bool cmdReturnVisibleNetworks(Parser & p, char * buffer);
bool cmdAddNetwork(Parser & p, char * buffer);
bool cmdReportAllSettings(Parser & p, char * buffer);
bool cmdSetTemperatureOffset(Parser & p, char * buffer);
bool cmdSetMqttDevId(Parser & p, char * buffer);
bool cmdAuth(Parser & p, char * buffer);
bool cmdReadFullMac(Parser & p, char * buffer);
};

View File

@ -6,8 +6,10 @@
#include "TaskMgr.h" #include "TaskMgr.h"
#include "app_config.h" #include "app_config.h"
#include "Buffers.h" #include "Buffers.h"
#include "Settings.h"
#include "CommandProcessor.h"
static const char * mqtt_broker = "mqtt-dev-server.westus2-1.ts.eventgrid.azure.net"; static const char * mqtt_broker = "wellnua.com";//"mqtt-dev-server.westus2-1.ts.eventgrid.azure.net";
static const char * topic = "wellnuotopics/topic1"; static const char * topic = "wellnuotopics/topic1";
static const int mqtt_port = 8883; static const int mqtt_port = 8883;
@ -16,8 +18,16 @@ static const char * TAG = "mqtts";
void MqttService::callback(char* topic, uint8_t * payload, uint32_t length) void MqttService::callback(char* topic, uint8_t * payload, uint32_t length)
{ {
ESP_LOGI(TAG, "Message arrived in topic: %s\n", topic); ESP_LOGI(TAG, "Message arrived in topic: %s\n", topic);
m_app_if.getCommandProcessor()->take();
payload[length] = 0; payload[length] = 0;
ESP_LOGW(TAG, "%s", (char*)payload); 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_app_if.getCommandProcessor()->give();
} }
MqttService::MqttService(AppIF & app_if) : m_app_if(app_if) MqttService::MqttService(AppIF & app_if) : m_app_if(app_if)
@ -29,33 +39,50 @@ uint8_t buffer[256];
void MqttService::task() void MqttService::task()
{ {
int try_connect_count = 0;
while(true) while(true)
{ {
// if(m_app_if.getBuffer()->getSemaphore().take(5000)) // wait for the data to become available if(m_app_if.getBuffer()->waitForDataAvailable(1000))
if(m_app_if.getBuffer()->waitForDataAvailable(5000))
{ {
uint8_t len = 0; uint8_t len = 0;
if(m_app_if.getBuffer()->getBlock(buffer, len)) if(m_app_if.getBuffer()->getBlock(buffer, len))
{ {
ESP_LOGI(TAG, "got data, len %d", len); char top[64];
uint8_t mac[6];
WiFi.macAddress(mac);
while (!m_mqtt_client->connected()) while (!m_mqtt_client->connected())
{ {
ESP_LOGI(TAG, "connecting to mqtt broker..."); sprintf(top, "wh_%02X%02X%02X%02X%02X%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
if (m_mqtt_client->connect("Esp32 client", "client1-authn-ID", NULL))
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!"))
{ {
try_connect_count = 0;
ESP_LOGI(TAG, "connected"); ESP_LOGI(TAG, "connected");
if(m_mqtt_client->subscribe("my_topic"))
{ 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);
if(m_mqtt_client->subscribe(top))
ESP_LOGI(TAG, "subscribed");
else
ESP_LOGE(TAG, "subscribe failed");
sprintf(top, "/%08x", SETTINGS.device.group_id);
ESP_LOGI(TAG, "Subscribing to %s", top);
if(m_mqtt_client->subscribe(top))
ESP_LOGI(TAG, "subscribed"); ESP_LOGI(TAG, "subscribed");
}
else else
{
ESP_LOGE(TAG, "subscribe failed"); ESP_LOGE(TAG, "subscribe failed");
}
} }
else else
{ {
if(++try_connect_count > 100)
esp_restart();
ESP_LOGE(TAG, "failed with state %d", m_mqtt_client->state()); ESP_LOGE(TAG, "failed with state %d", m_mqtt_client->state());
delay(5000); delay(5000);
} }
@ -69,7 +96,6 @@ void MqttService::task()
m_mqtt_client->loop(); m_mqtt_client->loop();
ESP_LOGI(TAG, "publishing..."); ESP_LOGI(TAG, "publishing...");
// bool val = m_mqtt_client->publish(topic, "Hi I'm ESP32 ^^");
bool val = m_mqtt_client->publish(topic, buffer, len); bool val = m_mqtt_client->publish(topic, buffer, len);
if(val) if(val)
@ -82,8 +108,10 @@ void MqttService::task()
} }
} }
} }
else if(m_mqtt_client->connected())
{
m_mqtt_client->loop(); m_mqtt_client->loop();
}
} }
} }
@ -95,13 +123,14 @@ void MqttService::start()
m_mqtt_client = new PubSubClient(*m_esp_client); m_mqtt_client = new PubSubClient(*m_esp_client);
m_esp_client->setCACert((const char*)server_cert); m_esp_client->setCACert((const char*)server_cert);
m_esp_client->setCertificate((const char *)client_cert); // for client verification ESP_LOGI(TAG, "%s", server_cert);
m_esp_client->setPrivateKey((const char *)client_key); // for client verification // 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->setServer(mqtt_broker, mqtt_port);
m_mqtt_client->setCallback(std::bind(&MqttService::callback, this, _1, _2, _3)); m_mqtt_client->setCallback(std::bind(&MqttService::callback, this, _1, _2, _3));
m_mqtt_client->setKeepAlive(30); m_mqtt_client->setKeepAlive(40);
m_mqtt_client->setSocketTimeout(30); m_mqtt_client->setSocketTimeout(40);
m_task = TaskMgr::getInstance().createTask(std::bind(&MqttService::task, this), MQTT_TASK_NAME, MQTT_TASK_STACK_SIZE, MQTT_TASK_PRIORITY, MQTT_TASK_CORE); m_task = TaskMgr::getInstance().createTask(std::bind(&MqttService::task, this), MQTT_TASK_NAME, MQTT_TASK_STACK_SIZE, MQTT_TASK_PRIORITY, MQTT_TASK_CORE);
} }

View File

@ -11,9 +11,9 @@
#include "mqtt_client.h" #include "mqtt_client.h"
extern const uint8_t server_cert[] asm("_binary_eventgrid_azure_pem_start"); extern const uint8_t server_cert[] asm("_binary_newca_crt_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");
using namespace std::placeholders; using namespace std::placeholders;

View File

@ -22,7 +22,7 @@
#include <HTTPClient.h> #include <HTTPClient.h>
#define OTA_URL "http://bigfoot-inc.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"); extern const uint8_t server_cert[] asm("_binary_bigfoot_inc_pem_start");
static const char *TAG = "OTA"; static const char *TAG = "OTA";
@ -52,7 +52,7 @@ void Ota::start()
esp_ota_handle_t update_handle = 0; esp_ota_handle_t update_handle = 0;
const esp_partition_t *update_partition = NULL; const esp_partition_t *update_partition = NULL;
ESP_LOGW(TAG, "Starting OTA check..."); ESP_LOGW(TAG, "Starting OTA check '%s'...", OTA_URL);
HTTPClient client; HTTPClient client;

View File

@ -42,10 +42,12 @@ void ProvisionSoftAP::wifiEvent(arduino_event_id_t event, arduino_event_info_t i
switch (event) switch (event)
{ {
case ARDUINO_EVENT_WIFI_AP_STACONNECTED: case ARDUINO_EVENT_WIFI_AP_STACONNECTED:
esp_timer_stop(m_timer);
ESP_LOGI(TAG, "station " MACSTR " joined, AID=%d", MAC2STR(info.wifi_ap_staconnected.mac), info.wifi_ap_staconnected.aid); ESP_LOGI(TAG, "station " MACSTR " joined, AID=%d", MAC2STR(info.wifi_ap_staconnected.mac), info.wifi_ap_staconnected.aid);
break; break;
case ARDUINO_EVENT_WIFI_AP_STADISCONNECTED: case ARDUINO_EVENT_WIFI_AP_STADISCONNECTED:
ESP_ERROR_CHECK(esp_timer_start_periodic(m_timer, INACTIVE_TIMER));
ESP_LOGI(TAG, "station " MACSTR " left", MAC2STR(info.wifi_ap_stadisconnected.mac)); ESP_LOGI(TAG, "station " MACSTR " left", MAC2STR(info.wifi_ap_stadisconnected.mac));
m_webSocket->closeAll(); m_webSocket->closeAll();
break; break;
@ -150,13 +152,14 @@ void ProvisionSoftAP::start(const char * ssid, const char * password)
m_rwriter->appendf("num:%d|", num_networks); m_rwriter->appendf("num:%d|", num_networks);
for (int n = 0; n < num_networks; n++) for (int n = 0; n < num_networks; n++)
{ {
m_rwriter->appendf("%s,%d,%d", WiFi.SSID(n), WiFi.encryptionType(n) == WIFI_AUTH_OPEN ? 0 : 1, WiFi.RSSI(n)); ESP_LOGI(TAG, "'%s', %d", WiFi.SSID(n).c_str(), WiFi.RSSI(n));
m_rwriter->appendf("%s,%d,%d", WiFi.SSID(n).c_str(), WiFi.encryptionType(n) == WIFI_AUTH_OPEN ? 0 : 1, WiFi.RSSI(n));
if(n != num_networks - 1) if(n != num_networks - 1)
m_rwriter->append('|'); m_rwriter->append('|');
} }
ESP_LOGI(TAG, "Sending '%s'", m_rwriter->getBuffer()); ESP_LOGI(TAG, "Sending '%s'", m_rwriter->getBuffer());
m_webSocket->textAll(m_rwriter->getBuffer()); m_webSocket->textAll(m_rwriter->getBuffer());
vTaskDelay(550); vTaskDelay(1550);
} }
if(m_tryConnect) if(m_tryConnect)
@ -175,13 +178,28 @@ void ProvisionSoftAP::start(const char * ssid, const char * password)
} }
} }
void ProvisionSoftAP::timerCallback(void* arg)
{
esp_restart();
}
void ProvisionSoftAP::start() void ProvisionSoftAP::start()
{ {
uint8_t mac[6]; uint8_t mac[6];
WiFi.macAddress(mac); WiFi.macAddress(mac);
char ssid[33]; char ssid[33];
sprintf(ssid, "Wellhub-%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 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 = "provision reset timer";
ESP_ERROR_CHECK(esp_timer_create(&timer, &m_timer));
ESP_ERROR_CHECK(esp_timer_start_periodic(m_timer, INACTIVE_TIMER)); // 5 min
sprintf(ssid, "Wellplug-%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
start(ssid, "12345678"); start(ssid, "12345678");
} }
@ -252,26 +270,36 @@ void ProvisionSoftAP::tryConnect()
{ {
ESP_LOGI(TAG, "trying to connect to %s", m_ssid); ESP_LOGI(TAG, "trying to connect to %s", m_ssid);
WiFi.begin(m_ssid, m_pwd); int connRes = 0;
int connRes = WiFi.waitForConnectResult(5000);
if(connRes == WL_CONNECTED) delay(100);
for(int n = 0; n < 7; n++)
{ {
// all is gud! WiFi.begin(m_ssid, m_pwd);
ESP_LOGI(TAG, "we're connected, sending confirmation"); connRes = WiFi.waitForConnectResult(8000);
m_webSocket->textAll(wifi_ok, sizeof(wifi_ok)-1); if(connRes == WL_CONNECTED)
{
// all is gud!
ESP_LOGI(TAG, "we're connected, sending confirmation");
m_webSocket->textAll(wifi_ok, sizeof(wifi_ok)-1);
strcpy(SETTINGS.wifi.entry[0].ssid, m_ssid); strcpy(SETTINGS.wifi.entry[0].ssid, m_ssid);
strcpy(SETTINGS.wifi.entry[0].pwd, m_pwd); strcpy(SETTINGS.wifi.entry[0].pwd, m_pwd);
SETTINGS.wifi.selected = 0; SETTINGS.wifi.selected = 0;
SETTINGS.wifi.num = 1; SETTINGS.wifi.num = 1;
SETTINGS_SAVE; SETTINGS_SAVE;
vTaskDelay(3000 / portTICK_PERIOD_MS); vTaskDelay(3000 / portTICK_PERIOD_MS);
waitBufferEmpty(); waitBufferEmpty();
ESP_LOGI(TAG, "restarting..."); ESP_LOGI(TAG, "restarting...");
esp_restart(); WiFi.disconnect();
WiFi.mode(WIFI_MODE_NULL);
esp_restart();
}
delay(300);
} }
WiFi.mode(WIFI_MODE_AP); WiFi.mode(WIFI_MODE_AP);
ESP_LOGE(TAG, "nuh-uh peppernip, error %d", connRes); ESP_LOGE(TAG, "nuh-uh peppernip, error %d", connRes);

View File

@ -11,9 +11,12 @@
#include <ESPAsyncWebServer.h> #include <ESPAsyncWebServer.h>
#include <DNSServer.h> #include <DNSServer.h>
#include <list> #include <list>
#include <esp_timer.h>
#include "ReaderWriter.h" #include "ReaderWriter.h"
#include "Settings.h" #include "Settings.h"
#define INACTIVE_TIMER (5*60*1000*1000)
class ProvisionSoftAP class ProvisionSoftAP
{ {
private: private:
@ -26,6 +29,9 @@ private:
ReaderWriter * m_rwriter = nullptr; ReaderWriter * m_rwriter = nullptr;
esp_timer_handle_t m_timer;
static void timerCallback(void* arg);
private: private:
char m_ssid[32] = {0}; char m_ssid[32] = {0};
char m_pwd[32] = {0}; char m_pwd[32] = {0};

View File

@ -90,6 +90,10 @@ void Settings::setDefaults()
m_data->wifi.dns_primary = PP_HTONL(LWIP_MAKEU32(8, 8, 8, 8)); 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)); m_data->wifi.dns_secondary = PP_HTONL(LWIP_MAKEU32(8, 8, 4, 4));
m_data->device.id = 101; m_data->device.tata_id = 100;
m_data->device.group_id = 5101; m_data->device.group_id = 5101;
m_data->sensors.temperature.temp_offset = 0;
strcpy(m_data->mqtt.device_id, "0");
} }

View File

@ -106,10 +106,25 @@ struct LED
// general device level settings // general device level settings
struct DEVICE struct DEVICE
{ {
uint32_t id; uint32_t tata_id;
uint32_t group_id; uint32_t group_id;
}; };
struct MQTT
{
char device_id[64];
};
struct TEMPERATURE
{
float temp_offset;
};
struct SENSORS
{
struct TEMPERATURE temperature;
};
// //
struct NV_DATA struct NV_DATA
@ -118,6 +133,8 @@ struct NV_DATA
struct LED led; struct LED led;
struct WIFI wifi; struct WIFI wifi;
struct DEVICE device; struct DEVICE device;
struct MQTT mqtt;
struct SENSORS sensors;
}; };
#pragma pack(pop) #pragma pack(pop)

View File

@ -8,6 +8,8 @@
#include "utilities.h" #include "utilities.h"
#include "app_config.h" #include "app_config.h"
#include <esp_wifi.h>
static const char *TAG = "Wifi"; static const char *TAG = "Wifi";
#define IGNORE_SSID_MINS 20 #define IGNORE_SSID_MINS 20
@ -62,11 +64,23 @@ void Wifi::task()
{ {
m_wifi_status = WIFI_STATUS::PENDING; m_wifi_status = WIFI_STATUS::PENDING;
m_wifi_status = startConnecting(); m_wifi_status = startConnecting();
delay(500);
while(m_pause)
{
delay(100);
}
} }
delay(15000); delay(15000);
} }
} }
void Wifi::pause(bool pause)
{
m_pause = pause;
}
/// @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 WIFI_STATUS::CONNECTED/NOT_CONENCTED connected /// @return WIFI_STATUS::CONNECTED/NOT_CONENCTED connected
@ -80,9 +94,17 @@ Wifi::WIFI_STATUS Wifi::connectTo(int index)
ESP_LOGI(TAG, "Connecting to %s...", SETTINGS.wifi.entry[index].ssid); ESP_LOGI(TAG, "Connecting to %s...", SETTINGS.wifi.entry[index].ssid);
delay(1000);
// set hostname
uint8_t mac[6];
WiFi.macAddress(mac);
char buffer[32];
sprintf(buffer, "wellhub-tag%02x%02x%02x", mac[3], mac[4], mac[5]);
WiFi.hostname(buffer);
WiFi.mode(WIFI_STA); WiFi.mode(WIFI_STA);
WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS); WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS);
WiFi.hostname("wellhub");
WiFi.begin(SETTINGS.wifi.entry[index].ssid, SETTINGS.wifi.entry[index].pwd); WiFi.begin(SETTINGS.wifi.entry[index].ssid, SETTINGS.wifi.entry[index].pwd);
int status = WiFi.waitForConnectResult(10000); int status = WiFi.waitForConnectResult(10000);
@ -92,8 +114,11 @@ Wifi::WIFI_STATUS Wifi::connectTo(int index)
ESP_LOGI(TAG, "Connected"); ESP_LOGI(TAG, "Connected");
return WIFI_STATUS::CONNECTED; return WIFI_STATUS::CONNECTED;
} }
delay(1000);
WiFi.disconnect(); WiFi.disconnect();
ESP_LOGW(TAG, "Failed to connect"); ESP_LOGW(TAG, "Failed to connect, status: %d", status);
return WIFI_STATUS::NOT_CONNECTED; return WIFI_STATUS::NOT_CONNECTED;
} }
@ -101,7 +126,10 @@ int Wifi::start()
{ {
if(m_task == nullptr) if(m_task == nullptr)
{ {
ESP_LOGW(TAG, "Starting wifi..."); uint8_t mac[8];
esp_read_mac(mac, ESP_MAC_WIFI_STA);
ESP_LOGW(TAG, "Starting wifi, mac: %02x:%02x:%02x:%02x:%02x:%02x ...", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
m_task = TaskMgr::getInstance().createTask(std::bind(&Wifi::task, this), WIFI_TASK_NAME, WIFI_TASK_STACK_SIZE, WIFI_TASK_PRIORITY, WIFI_TASK_CORE); m_task = TaskMgr::getInstance().createTask(std::bind(&Wifi::task, this), WIFI_TASK_NAME, WIFI_TASK_STACK_SIZE, WIFI_TASK_PRIORITY, WIFI_TASK_CORE);
} }
return 0; return 0;
@ -134,7 +162,7 @@ Wifi::WIFI_STATUS Wifi::startConnecting()
if(SETTINGS.wifi.num == 1) if(SETTINGS.wifi.num == 1)
{ {
SETTINGS.wifi.selected = 0; SETTINGS.wifi.selected = 0;
for(int n = 0; n < 3; n++) for(int n = 0; n < 7; n++)
{ {
if(connectTo(SETTINGS.wifi.selected) == WIFI_STATUS::CONNECTED) if(connectTo(SETTINGS.wifi.selected) == WIFI_STATUS::CONNECTED)
return WIFI_STATUS::CONNECTED; return WIFI_STATUS::CONNECTED;

View File

@ -36,6 +36,7 @@ protected:
WIFI_STATUS startConnecting(); WIFI_STATUS startConnecting();
WIFI_STATUS connectTo(int index); WIFI_STATUS connectTo(int index);
int scan(); int scan();
bool m_pause = false;
public: public:
Wifi(); Wifi();
@ -45,6 +46,8 @@ protected:
public: public:
int start(); int start();
void pause(bool pause);
WIFI_STATUS status() { return m_wifi_status; } WIFI_STATUS status() { return m_wifi_status; }
WIFI_STATUS waitForConnection(); WIFI_STATUS waitForConnection();
}; };

View File

@ -5,6 +5,8 @@
#include "SensorService.h" #include "SensorService.h"
#include "Buffers.h" #include "Buffers.h"
#include "SensorData.h" #include "SensorData.h"
#include "Settings.h"
#include "Led.h"
static const char *TAG = "sensors"; static const char *TAG = "sensors";
@ -33,14 +35,28 @@ void SensorService::start()
m_bme68x = new Bme68x(Wire); m_bme68x = new Bme68x(Wire);
m_ld2410 = new LD2410(); m_ld2410 = new LD2410();
bool hw_fault = false;
if(!m_bmp280->init()) if(!m_bmp280->init())
{
hw_fault = true;
ESP_LOGE(TAG, "bmp280 sensor error"); ESP_LOGE(TAG, "bmp280 sensor error");
}
if(!m_bme68x->init()) if(!m_bme68x->init())
{
hw_fault = true;
ESP_LOGE(TAG, "bme68x sensor error"); ESP_LOGE(TAG, "bme68x sensor error");
}
if(!m_ld2410->init()) if(!m_ld2410->init())
{
hw_fault = true;
ESP_LOGE(TAG, "ld2410 sensor error"); ESP_LOGE(TAG, "ld2410 sensor error");
}
if(hw_fault)
m_app_if.getLed()->setColor(255, 0, 0);
assert(m_i2c1_task = TaskMgr::getInstance().createTask(std::bind(&SensorService::run_i2c_1, this), assert(m_i2c1_task = TaskMgr::getInstance().createTask(std::bind(&SensorService::run_i2c_1, this),
I2C1_TASK_NAME, I2C1_TASK_STACK_SIZE, I2C1_TASK_PRIORITY, I2C1_TASK_CORE)); I2C1_TASK_NAME, I2C1_TASK_STACK_SIZE, I2C1_TASK_PRIORITY, I2C1_TASK_CORE));
@ -61,11 +77,11 @@ void::SensorService::processPressure(float pressure)
uint64_t now = esp_timer_get_time(); uint64_t now = esp_timer_get_time();
ESP_LOGI(TAG, "delta T: %d", (uint32_t)((now-previous)/1000)); // ESP_LOGI(TAG, "delta T: %d", (uint32_t)((now-previous)/1000));
filtered = 0.95 * filtered + 0.05 * pressure; filtered = 0.95 * filtered + 0.05 * pressure;
previous = now; previous = now;
ESP_LOGI(TAG, "%0.3f \t%0.3f", pressure, filtered); // ESP_LOGI(TAG, "%0.3f \t%0.3f", pressure, filtered);
} }
void SensorService::postBme68xData(float pressure, float temp) void SensorService::postBme68xData(float pressure, float temp)
@ -76,7 +92,7 @@ void SensorService::postBme68xData(float pressure, float temp)
msg->humidity = m_bme_data.humidity; msg->humidity = m_bme_data.humidity;
msg->light = m_light_value; msg->light = m_light_value;
msg->pressure = pressure; msg->pressure = pressure;
msg->temperature = temp; msg->temperature = temp + SETTINGS.sensors.temperature.temp_offset;
int num_total = 0; int num_total = 0;
@ -164,7 +180,7 @@ void SensorService::run_uart()
if(has_read && esp_timer_get_time() - last_read >= ms_to_us(10000-50)) if(has_read && esp_timer_get_time() - last_read >= ms_to_us(10000-50))
{ {
int64_t now = esp_timer_get_time(); int64_t now = esp_timer_get_time();
ESP_LOGI(TAG, "count %d", (int)m_ld2410->stationary_energy[0]); // ESP_LOGI(TAG, "count %d", (int)m_ld2410->stationary_energy[0]);
if(m_ld2410->stationary_energy[0] != 0) if(m_ld2410->stationary_energy[0] != 0)
{ {
@ -181,7 +197,7 @@ void SensorService::run_uart()
m_app_if.getBuffer()->putBlock((uint8_t*)&msg, sizeof(msg)); m_app_if.getBuffer()->putBlock((uint8_t*)&msg, sizeof(msg));
ESP_LOGI(TAG, "delta t: %lld", (now - last_read)/1000); // ESP_LOGI(TAG, "delta t: %lld", (now - last_read)/1000);
last_read = now; last_read = now;
#if 0 #if 0

View File

@ -27,3 +27,45 @@ void dump_bytes(const void *data, uint32_t len)
if (hasMore) if (hasMore)
ESP_LOGI(TAG, "%s", c); ESP_LOGI(TAG, "%s", c);
} }
bool strToInt(const char *str, int & val, int base)
{
if(str == nullptr || str[0] == 0)
{
ESP_LOGE(TAG, "input str invalid");
return false;
}
char *endptr;
val = strtol(str, &endptr, base);
if(endptr == str || *endptr != 0)
{
ESP_LOGE(TAG, "input str invalid (2)");
return false;
}
return true;
}
bool strToFloat(const char *str, float & val)
{
if(str == nullptr || str[0] == 0)
{
ESP_LOGE(TAG, "input str invalid");
return false;
}
char *endptr;
val = strtof(str, &endptr);
if(endptr == str || *endptr != 0)
{
ESP_LOGE(TAG, "input str invalid (2)");
return false;
}
return true;
}

View File

@ -6,5 +6,7 @@
#include <stdint.h> #include <stdint.h>
void dump_bytes(const void *data, uint32_t len); void dump_bytes(const void *data, uint32_t len);
bool strToInt(const char *str, int & val, int base = 10);
bool strToFloat(const char *str, float & val);
#endif /* __UTILITIES_H__ */ #endif /* __UTILITIES_H__ */

19
old/ota.sh Executable file
View File

@ -0,0 +1,19 @@
#!/bin/bash
# first device connected
idf.py clean
idf.py -DROLE=SENDER build
ret_val=$?
if (($ret_val != 0)); then
exit
fi
rm build/wellhub.enc.bin 2> /dev/null
echo "Encrypting image..."
image_enc/encrypt.py build/wellhub.bin build/wellhub.enc.bin
echo "Uploading..."
lftp -c "open -u mirozmrzli@bigfoot-inc.com,3445trGGDSa9 ftp.bigfoot-inc.com; put build/wellhub.enc.bin"

2
ota.sh
View File

@ -15,5 +15,5 @@ rm build/wellhub.enc.bin 2> /dev/null
echo "Encrypting image..." echo "Encrypting image..."
image_enc/encrypt.py build/wellhub.bin build/wellhub.enc.bin image_enc/encrypt.py build/wellhub.bin build/wellhub.enc.bin
echo "Uploading..." echo "Uploading..."
lftp -c "open -u mirozmrzli@bigfoot-inc.com,3445trGGDSa9 ftp.bigfoot-inc.com; put build/wellhub.enc.bin" lftp -c "open -u well_ftpuser,%%2025!#_ThisIsaLL wellnua.com; put -O FW build/wellhub.enc.bin"

17
test.sh
View File

@ -1,17 +0,0 @@
#!/bin/bash
# first device connected
idf.py -DROLE=SENDER build
ret_val=$?
if (($ret_val != 0)); then
exit
fi
if [$1 == '']; then
idf.py -p /dev/ttyUSB0 flash && idf.py -p /dev/ttyUSB0 monitor -B 450000
else
idf.py -p $1 flash && idf.py -p $1 monitor -B 450000
fi

View File

@ -7,11 +7,17 @@ mqtt_broker = "mqtt-dev-server.westus2-1.ts.eventgrid.azure.net"
mqtt_port = 8883 mqtt_port = 8883
mqtt_topic = "wellnuotopics/topic1" mqtt_topic = "wellnuotopics/topic1"
mqtt_client_id = "client1-authn-ID" mqtt_client_id = "client1-authn-ID"
#mqtt_client_id = "292"
connected = False connected = False
def connect_mqtt(client_id): monitor = ["64B70889043C", "64B70888F8C0", "64B70888FAD0", "64B70888FAC8"]
def on_connect(client, userdata, flags, rc):
macs = []
hist = {}
def connect_mqtt():
def on_connect(client, userdata, flags, rc, props):
global connected global connected
if rc == 0: if rc == 0:
print("Connected to MQTT Broker!") print("Connected to MQTT Broker!")
@ -19,38 +25,68 @@ def connect_mqtt(client_id):
else: else:
print("Failed to connect, return code %d\n", rc) print("Failed to connect, return code %d\n", rc)
client = mqtt_client.Client(mqtt_client.CallbackAPIVersion.VERSION1, "client_id") client = mqtt_client.Client(mqtt_client.CallbackAPIVersion.VERSION2, "asdasxzxdadaswd")
client.tls_set( client.tls_set(
ca_certs='eventgrid.azure_full.pem', ca_certs='eventgrid.azure_full.pem',
certfile='../certs/client1-authn-ID.pem', certfile='../certs/client1-authn-ID.pem',
keyfile='../certs/client1-authn-ID.key' keyfile='../certs/client1-authn-ID.key'
) )
client.username_pw_set(client_id, "") def on_message(client, userdata, message):
bin = message.payload
secs = bin[0] + bin[1]*256 + bin[2]*256*256 + bin[3]*256*256*256
mac = ''.join('{:02x}'.format(x) for x in bin[8:14])
grp_id = bin[14] + bin[15]*256 + bin[16]*256*256 + bin[17]*256*256*256
if not mac in macs:
macs.append(mac)
if not mac in hist:
hist[mac] = 1
print (f"{len(macs)} {mac} {grp_id}")
else:
hist[mac] += 1
if mac in monitor:
print(f"*** {mac} ****")
client.username_pw_set(mqtt_client_id, None)
client.on_connect = on_connect client.on_connect = on_connect
client.on_message = on_message
client.connect(mqtt_broker, mqtt_port) client.connect(mqtt_broker, mqtt_port)
client.subscribe(mqtt_topic)
return client return client
def publish(client, topic, msg): def publish(client, topic, msg):
result = client.publish(topic, msg) result = client.publish(topic, msg)
# result: [0, 1] # result: [0, 1]
status = result[0] # status = result[0]
if status == 0: # if status == 0:
print(f"Sent `{msg}` to topic `{topic}`") # print(f"Sent `{msg}` to topic `{topic}`")
else: # else:
print(f"Failed to send message to topic {topic}") # print(f"Failed to send message to topic {topic}")
def main() -> None: def main() -> None:
client = connect_mqtt(mqtt_client_id) client = connect_mqtt()
client.loop_start() client.loop_start()
while(connected == False): while(connected == False):
time.sleep(1) time.sleep(1)
publish(client, "wellnuotopics/topic1", "hello") # for n in range(100000000):
time.sleep(2) # publish(client, f"/{monitor[0]}", "pin|7856")
client.disconnect() # publish(client, f"/{monitor[0]}", "s")
time.sleep(60)
sorted_dict = dict(sorted(hist.items(), key=lambda x:x[1]))
for key in sorted_dict:
print(f"{key} : {sorted_dict[key]}")
client.disconnect()
if __name__ == "__main__": if __name__ == "__main__":
main() main()