Skip to content

Commit 9836583

Browse files
authored
Merge pull request #390 from sinricpro/ota-update
Support OTA and model level commands
2 parents 75fe2b8 + 040e8af commit 9836583

22 files changed

+1429
-11
lines changed

.github/workflows/build-esp8266-esp32.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
runs-on: ubuntu-latest
1515
strategy:
1616
matrix:
17-
example: [examples/ACUnit, examples/AirQualitySensor/AirQualitySensor, examples/Blinds, examples/ContactSensor, examples/DimSwitch, examples/doorbell, examples/Fan, examples/GarageDoor, examples/Light/Light, examples/Lock/Lock, examples/Lock/Lock_with_feedback, examples/MotionSensor, examples/PowerSensor, examples/Relay/MultiRelays_advance, examples/Relay/Relay, examples/Speaker, examples/Switch/MultiSwitch_advance, examples/Switch/MultiSwitch_beginner, examples/Switch/MultiSwitch_intermediate, examples/Switch/Switch, examples/Thermostat, examples/TV]
17+
example: [examples/ACUnit, examples/AirQualitySensor/AirQualitySensor, examples/Blinds, examples/ContactSensor, examples/DimSwitch, examples/doorbell, examples/Fan, examples/GarageDoor, examples/Light/Light, examples/Lock/Lock, examples/Lock/Lock_with_feedback, examples/MotionSensor, examples/PowerSensor, examples/Relay/MultiRelays_advance, examples/Relay/Relay, examples/Speaker, examples/Switch/MultiSwitch_advance, examples/Switch/MultiSwitch_beginner, examples/Switch/MultiSwitch_intermediate, examples/Switch/Switch, examples/Thermostat, examples/TV, examples/OTAUpdate, examples/Health]
1818

1919
steps:
2020

.github/workflows/build-rpipicow.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
runs-on: ubuntu-latest
1414
strategy:
1515
matrix:
16-
example: [examples/ACUnit, examples/AirQualitySensor/AirQualitySensor, examples/Blinds, examples/ContactSensor, examples/DimSwitch, examples/doorbell, examples/Fan, examples/GarageDoor, examples/Light/Light, examples/Lock/Lock, examples/Lock/Lock_with_feedback, examples/MotionSensor, examples/PowerSensor, examples/Relay/MultiRelays_advance, examples/Relay/Relay, examples/Speaker, examples/Switch/MultiSwitch_advance, examples/Switch/MultiSwitch_beginner, examples/Switch/MultiSwitch_intermediate, examples/Switch/Switch, examples/Thermostat, examples/TV]
16+
example: [examples/ACUnit, examples/AirQualitySensor/AirQualitySensor, examples/Blinds, examples/ContactSensor, examples/DimSwitch, examples/doorbell, examples/Fan, examples/GarageDoor, examples/Light/Light, examples/Lock/Lock, examples/Lock/Lock_with_feedback, examples/MotionSensor, examples/PowerSensor, examples/Relay/MultiRelays_advance, examples/Relay/Relay, examples/Speaker, examples/Switch/MultiSwitch_advance, examples/Switch/MultiSwitch_beginner, examples/Switch/MultiSwitch_intermediate, examples/Switch/Switch, examples/Thermostat, examples/TV, examples/Health]
1717

1818
steps:
1919
- name: Step 1 - Checkout Repo

changelog.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
# Changelog
2+
## Version 3.2.0
3+
### New
4+
- Support OTA Updates
5+
- Module level command support for WiFi settings, ESP Health
6+
27
## Version 3.1.0
38
Upgrade:
49
- Upgrade to ArduinoJson 7

examples/Health/Health.ino

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Example for how to monitor ESP health.
3+
*
4+
* If you encounter any issues:
5+
* - check the readme.md at https://github.com/sinricpro/esp8266-esp32-sdk/blob/master/README.md
6+
* - ensure all dependent libraries are installed
7+
* - see https://github.com/sinricpro/esp8266-esp32-sdk/blob/master/README.md#arduinoide
8+
* - see https://github.com/sinricpro/esp8266-esp32-sdk/blob/master/README.md#dependencies
9+
* - open serial monitor and check whats happening
10+
* - check full user documentation at https://sinricpro.github.io/esp8266-esp32-sdk
11+
* - visit https://github.com/sinricpro/esp8266-esp32-sdk/issues and check for existing issues or open a new one
12+
*/
13+
14+
// Uncomment the following line to enable serial debug output
15+
#define ENABLE_DEBUG
16+
17+
#ifdef ENABLE_DEBUG
18+
#define DEBUG_ESP_PORT Serial
19+
#define NODEBUG_WEBSOCKETS
20+
#define NDEBUG
21+
#endif
22+
23+
#include <Arduino.h>
24+
#include <ArduinoJson.h>
25+
26+
#if defined(ESP8266)
27+
#include <ESP8266WiFi.h>
28+
#elif defined(ESP32)
29+
#include <WiFi.h>
30+
#endif
31+
32+
#include "SinricPro.h"
33+
#include "SinricProSwitch.h"
34+
#include "HealthDiagnostics.h"
35+
36+
#define WIFI_SSID "YOUR-WIFI-SSID"
37+
#define WIFI_PASS "YOUR-WIFI-PASSWORD"
38+
#define APP_KEY "YOUR-APP-KEY" // Should look like "de0bxxxx-1x3x-4x3x-ax2x-5dabxxxxxxxx"
39+
#define APP_SECRET "YOUR-APP-SECRET" // Should look like "5f36xxxx-x3x7-4x3x-xexe-e86724a9xxxx-4c4axxxx-3x3x-x5xe-x9x3-333d65xxxxxx"
40+
#define SWITCH_ID "YOUR-DEVICE-ID" // Should look like "5dc1564130xxxxxxxxxxxxxx"
41+
42+
#define BAUD_RATE 115200 // Change baudrate to your need
43+
44+
HealthDiagnostics healthDiagnostics;
45+
46+
// setup function for WiFi connection
47+
void setupWiFi() {
48+
Serial.printf("\r\n[Wifi]: Connecting");
49+
50+
#if defined(ESP8266)
51+
WiFi.setSleepMode(WIFI_NONE_SLEEP);
52+
WiFi.setAutoReconnect(true);
53+
#elif defined(ESP32)
54+
WiFi.setSleep(false);
55+
WiFi.setAutoReconnect(true);
56+
#endif
57+
58+
WiFi.begin(WIFI_SSID, WIFI_PASS);
59+
60+
while (WiFi.status() != WL_CONNECTED) {
61+
Serial.printf(".");
62+
delay(250);
63+
}
64+
65+
Serial.printf("connected!\r\n[WiFi]: IP-Address is %s\r\n", WiFi.localIP().toString().c_str());
66+
}
67+
68+
// setup function for SinricPro
69+
void setupSinricPro() {
70+
SinricProSwitch& mySwitch = SinricPro[SWITCH_ID];
71+
72+
// setup SinricPro
73+
SinricPro.onConnected([]() {
74+
Serial.printf("Connected to SinricPro\r\n");
75+
});
76+
77+
SinricPro.onDisconnected([]() {
78+
Serial.printf("Disconnected from SinricPro\r\n");
79+
});
80+
81+
SinricPro.onReportHealth([&](String &healthReport) {
82+
return healthDiagnostics.reportHealth(healthReport);
83+
});
84+
85+
SinricPro.begin(APP_KEY, APP_SECRET);
86+
}
87+
88+
// main setup function
89+
void setup() {
90+
Serial.begin(BAUD_RATE);
91+
Serial.printf("\r\n\r\n");
92+
setupWiFi();
93+
setupSinricPro();
94+
}
95+
96+
void loop() {
97+
SinricPro.handle();
98+
}

examples/Health/HealthDiagnostics.cpp

+137
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
#include "HealthDiagnostics.h"
2+
3+
String HealthDiagnostics::getChipId() {
4+
#if defined(ESP32)
5+
return String((uint32_t)ESP.getEfuseMac(), HEX);
6+
#elif defined(ESP8266)
7+
return String(ESP.getChipId(), HEX);
8+
#elif defined(ARDUINO_ARCH_RP2040)
9+
return String(rp2040.getChipID(), HEX);
10+
#endif
11+
}
12+
13+
void HealthDiagnostics::addHeapInfo(JsonObject& doc) {
14+
#if defined(ESP32)
15+
doc["freeHeap"] = ESP.getFreeHeap();
16+
doc["totalHeap"] = ESP.getHeapSize();
17+
doc["minFreeHeap"] = ESP.getMinFreeHeap();
18+
doc["maxAllocHeap"] = ESP.getMaxAllocHeap();
19+
20+
multi_heap_info_t heap_info;
21+
heap_caps_get_info(&heap_info, MALLOC_CAP_INTERNAL);
22+
23+
JsonObject internalHeap = doc["internalHeap"].to<JsonObject>();
24+
internalHeap["totalFreeBytes"] = heap_info.total_free_bytes;
25+
internalHeap["totalAllocatedBytes"] = heap_info.total_allocated_bytes;
26+
internalHeap["largestFreeBlock"] = heap_info.largest_free_block;
27+
internalHeap["minimumFreeBytes"] = heap_info.minimum_free_bytes;
28+
internalHeap["allocatedBlocks"] = heap_info.allocated_blocks;
29+
internalHeap["freeBlocks"] = heap_info.free_blocks;
30+
internalHeap["totalBlocks"] = heap_info.total_blocks;
31+
32+
heap_caps_get_info(&heap_info, MALLOC_CAP_SPIRAM);
33+
34+
JsonObject psram = doc["psram"].to<JsonObject>();
35+
psram["totalFreeBytes"] = heap_info.total_free_bytes;
36+
psram["totalAllocatedBytes"] = heap_info.total_allocated_bytes;
37+
psram["largestFreeBlock"] = heap_info.largest_free_block;
38+
psram["minimumFreeBytes"] = heap_info.minimum_free_bytes;
39+
psram["allocatedBlocks"] = heap_info.allocated_blocks;
40+
psram["freeBlocks"] = heap_info.free_blocks;
41+
psram["totalBlocks"] = heap_info.total_blocks;
42+
43+
#elif defined(ESP8266)
44+
doc["freeHeap"] = ESP.getFreeHeap();
45+
doc["heapFragmentation"] = ESP.getHeapFragmentation();
46+
doc["maxFreeBlockSize"] = ESP.getMaxFreeBlockSize();
47+
48+
// Get detailed heap information.
49+
JsonObject heapInfo = doc["heapInfo"].to<JsonObject>();
50+
UMM_HEAP_INFO ummHeapInfo;
51+
umm_info(&ummHeapInfo, 0);
52+
heapInfo["freeBlocks"] = ummHeapInfo.freeBlocks;
53+
heapInfo["usedBlocks"] = ummHeapInfo.usedBlocks;
54+
heapInfo["totalBlocks"] = ummHeapInfo.totalBlocks;
55+
heapInfo["totalEntries"] = ummHeapInfo.totalEntries;
56+
heapInfo["usedEntries"] = ummHeapInfo.usedEntries;
57+
heapInfo["freeEntries"] = ummHeapInfo.freeEntries;
58+
heapInfo["maxFreeContiguousBytes"] = umm_max_block_size();
59+
60+
#elif defined(ARDUINO_ARCH_RP2040)
61+
doc["freeHeap"] = rp2040.getFreeHeap();
62+
doc["totalHeap"] = rp2040.getTotalHeap();
63+
#endif
64+
}
65+
66+
void HealthDiagnostics::addWiFiInfo(JsonObject& doc) {
67+
doc["ssid"] = WiFi.SSID();
68+
69+
#if defined(ESP32) || defined(ESP8266)
70+
doc["bssid"] = WiFi.BSSIDstr();
71+
#endif
72+
73+
doc["rssi"] = WiFi.RSSI();
74+
doc["ipAddress"] = WiFi.localIP().toString();
75+
doc["subnetMask"] = WiFi.subnetMask().toString();
76+
doc["gateway"] = WiFi.gatewayIP().toString();
77+
doc["dns"] = WiFi.dnsIP().toString();
78+
doc["macAddress"] = WiFi.macAddress();
79+
doc["channel"] = WiFi.channel();
80+
}
81+
82+
void HealthDiagnostics::addSketchInfo(JsonObject& doc) {
83+
#if defined(ESP32) || defined(ESP8266)
84+
doc["cpuFreq"] = ESP.getCpuFreqMHz();
85+
doc["sketchSize"] = ESP.getSketchSize();
86+
doc["freeSketchSpace"] = ESP.getFreeSketchSpace();
87+
doc["flashChipSize"] = ESP.getFlashChipSize();
88+
doc["flashChipSpeed"] = ESP.getFlashChipSpeed();
89+
#endif
90+
}
91+
92+
void HealthDiagnostics::addResetCause(JsonObject& doc) {
93+
#if defined(ESP32)
94+
switch (esp_reset_reason()) {
95+
case ESP_RST_POWERON: doc["reason"] = "Power-on event"; break;
96+
case ESP_RST_EXT: doc["reason"] = "External pin reset"; break;
97+
case ESP_RST_SW: doc["reason"] = "Software reset via esp_restart"; break;
98+
case ESP_RST_PANIC: doc["reason"] = "Software reset due to exception/panic"; break;
99+
case ESP_RST_INT_WDT: doc["reason"] = "Reset (software or hardware) due to interrupt watchdog"; break;
100+
case ESP_RST_TASK_WDT: doc["reason"] = "Reset due to task watchdog"; break;
101+
case ESP_RST_WDT: doc["reason"] = "Reset due to other watchdogs"; break;
102+
case ESP_RST_DEEPSLEEP: doc["reason"] = "Deep sleep reset"; break;
103+
case ESP_RST_BROWNOUT: doc["reason"] = "Brownout reset"; break;
104+
case ESP_RST_SDIO: doc["reason"] = "Reset over SDIO"; break;
105+
default: doc["reason"] = "Unknown reset reason"; break;
106+
}
107+
#elif defined(ESP8266)
108+
doc["reason"] = ESP.getResetReason();
109+
#endif
110+
111+
//doc["crashDetails"] = "" // Use something like https://github.com/krzychb/EspSaveCrash
112+
}
113+
114+
bool HealthDiagnostics::reportHealth(String& healthReport) {
115+
JsonDocument doc;
116+
doc["chipId"] = getChipId();
117+
doc["uptime"] = millis() / 1000; // seconds
118+
119+
// Add detailed heap information.
120+
JsonObject heap = doc["heap"].to<JsonObject>();
121+
addHeapInfo(heap);
122+
123+
// Detailed Sketch information.
124+
JsonObject sketch = doc["sketch"].to<JsonObject>();
125+
addSketchInfo(sketch);
126+
127+
// Detailed WiFi information.
128+
JsonObject wifi = doc["wifi"].to<JsonObject>();
129+
addWiFiInfo(wifi);
130+
131+
// Add last reset reson
132+
JsonObject resetInfo = doc["reset"].to<JsonObject>();
133+
addResetCause(resetInfo);
134+
135+
serializeJson(doc, healthReport);
136+
return true;
137+
}

examples/Health/HealthDiagnostics.h

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#ifndef HEALTH_DIAGNOSTICS_H
2+
#define HEALTH_DIAGNOSTICS_H
3+
4+
#include <Arduino.h>
5+
#include <ArduinoJson.h>
6+
7+
#if defined(ESP32)
8+
#include <WiFi.h>
9+
#include "esp_system.h"
10+
#include <esp_wifi.h>
11+
#include <esp_heap_caps.h>
12+
#elif defined(ESP8266)
13+
#include <ESP8266WiFi.h>
14+
#include <user_interface.h>
15+
extern "C" {
16+
#include "umm_malloc/umm_heap_select.h"
17+
#include "umm_malloc/umm_malloc.h"
18+
}
19+
#elif defined(ARDUINO_ARCH_RP2040)
20+
#include <WiFi.h>
21+
#endif
22+
23+
/**
24+
* @brief Class to handle health diagnostics
25+
*/
26+
class HealthDiagnostics {
27+
public:
28+
/**
29+
* @brief Report the health diagnostic information.
30+
*
31+
* @param healthReport A reference to a String to store the health report in JSON format.
32+
* @return True on success, otherwise false.
33+
*/
34+
bool reportHealth(String& healthReport);
35+
36+
private:
37+
String getChipId();
38+
void addHeapInfo(JsonObject& doc);
39+
void addWiFiInfo(JsonObject& doc);
40+
void addSketchInfo(JsonObject& doc);
41+
void addResetCause(JsonObject& doc);
42+
};
43+
44+
#endif // HEALTH_DIAGNOSTICS_H

examples/OTAUpdate/Cert.cpp

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#include "Cert.h"
2+
3+
// Ref: https://projects.petrucci.ch/esp32/?page=ssl.php&url=otaupdates.sinric.pro
4+
5+
6+
const char* rootCACertificate = R"EOF(
7+
-----BEGIN CERTIFICATE-----
8+
MIIEVzCCAj+gAwIBAgIRAIOPbGPOsTmMYgZigxXJ/d4wDQYJKoZIhvcNAQELBQAw
9+
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
10+
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjQwMzEzMDAwMDAw
11+
WhcNMjcwMzEyMjM1OTU5WjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
12+
RW5jcnlwdDELMAkGA1UEAxMCRTUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNCzqK
13+
a2GOtu/cX1jnxkJFVKtj9mZhSAouWXW0gQI3ULc/FnncmOyhKJdyIBwsz9V8UiBO
14+
VHhbhBRrwJCuhezAUUE8Wod/Bk3U/mDR+mwt4X2VEIiiCFQPmRpM5uoKrNijgfgw
15+
gfUwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcD
16+
ATASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBSfK1/PPCFPnQS37SssxMZw
17+
i9LXDTAfBgNVHSMEGDAWgBR5tFnme7bl5AFzgAiIyBpY9umbbjAyBggrBgEFBQcB
18+
AQQmMCQwIgYIKwYBBQUHMAKGFmh0dHA6Ly94MS5pLmxlbmNyLm9yZy8wEwYDVR0g
19+
BAwwCjAIBgZngQwBAgEwJwYDVR0fBCAwHjAcoBqgGIYWaHR0cDovL3gxLmMubGVu
20+
Y3Iub3JnLzANBgkqhkiG9w0BAQsFAAOCAgEAH3KdNEVCQdqk0LKyuNImTKdRJY1C
21+
2uw2SJajuhqkyGPY8C+zzsufZ+mgnhnq1A2KVQOSykOEnUbx1cy637rBAihx97r+
22+
bcwbZM6sTDIaEriR/PLk6LKs9Be0uoVxgOKDcpG9svD33J+G9Lcfv1K9luDmSTgG
23+
6XNFIN5vfI5gs/lMPyojEMdIzK9blcl2/1vKxO8WGCcjvsQ1nJ/Pwt8LQZBfOFyV
24+
XP8ubAp/au3dc4EKWG9MO5zcx1qT9+NXRGdVWxGvmBFRAajciMfXME1ZuGmk3/GO
25+
koAM7ZkjZmleyokP1LGzmfJcUd9s7eeu1/9/eg5XlXd/55GtYjAM+C4DG5i7eaNq
26+
cm2F+yxYIPt6cbbtYVNJCGfHWqHEQ4FYStUyFnv8sjyqU8ypgZaNJ9aVcWSICLOI
27+
E1/Qv/7oKsnZCWJ926wU6RqG1OYPGOi1zuABhLw61cuPVDT28nQS/e6z95cJXq0e
28+
K1BcaJ6fJZsmbjRgD5p3mvEf5vdQM7MCEvU0tHbsx2I5mHHJoABHb8KVBgWp/lcX
29+
GWiWaeOyB7RP+OfDtvi2OsapxXiV7vNVs7fMlrRjY1joKaqmmycnBvAq14AEbtyL
30+
sVfOS66B8apkeFX2NY4XPEYV4ZSCe8VHPrdrERk2wILG3T/EGmSIkCYVUMSnjmJd
31+
VQD9F6Na/+zmXCc=
32+
-----END CERTIFICATE-----
33+
)EOF";

examples/OTAUpdate/Cert.h

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#pragma once
2+
3+
extern const char* rootCACertificate;

0 commit comments

Comments
 (0)