Replace Serial.* logging with ESP_LOG* macros (issue #8)
All checks were successful
CI / firmware (pull_request) Successful in 1m21s
CI / android (pull_request) Successful in 7s

- Convert all Serial.println/printf debug logging to ESP_LOGE/W/I/D
- Add TAG-based log identification (server/client)
- Lower CORE_DEBUG_LEVEL from 5 to 3 for production
- Keep Serial.printf for USB serial protocol commands (KEY?, VERSION?, etc.)
This commit is contained in:
eddy 2026-08-02 20:51:21 +02:00
commit 32489fbabb
3 changed files with 85 additions and 107 deletions

View file

@ -5,7 +5,7 @@ framework = arduino
board_build.arduino.memory_type = qio_qspi board_build.arduino.memory_type = qio_qspi
build_flags = build_flags =
-DESP32S3 -DESP32S3
-DCORE_DEBUG_LEVEL=5 -DCORE_DEBUG_LEVEL=3
-DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_CDC_ON_BOOT=1
-DARDUINO_USB_MODE=1 -DARDUINO_USB_MODE=1
lib_deps = lib_deps =
@ -24,7 +24,7 @@ framework = arduino
board_build.arduino.memory_type = qio_qspi board_build.arduino.memory_type = qio_qspi
build_flags = build_flags =
-DESP32S3 -DESP32S3
-DCORE_DEBUG_LEVEL=5 -DCORE_DEBUG_LEVEL=3
-DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_CDC_ON_BOOT=1
-DARDUINO_USB_MODE=1 -DARDUINO_USB_MODE=1
-DDEVICE_ID=1 -DDEVICE_ID=1

View file

@ -6,8 +6,11 @@
#include <mbedtls/sha256.h> #include <mbedtls/sha256.h>
#include <Preferences.h> #include <Preferences.h>
#include <esp_log.h>
#include "version.h" #include "version.h"
static const char *TAG = "client";
#define TOUCH1_PIN 8 #define TOUCH1_PIN 8
#define TOUCH2_PIN 6 #define TOUCH2_PIN 6
#define BUTTON_PIN 41 #define BUTTON_PIN 41
@ -70,14 +73,14 @@ class MyScanCallbacks : public NimBLEScanCallbacks {
class MyClientCallbacks : public NimBLEClientCallbacks { class MyClientCallbacks : public NimBLEClientCallbacks {
void onConnect(NimBLEClient *client) override { void onConnect(NimBLEClient *client) override {
connected = true; connected = true;
Serial.println("BLE: connected to server"); ESP_LOGI(TAG, "BLE: connected to server");
} }
void onDisconnect(NimBLEClient *client, int reason) override { void onDisconnect(NimBLEClient *client, int reason) override {
connected = false; connected = false;
relay1SendState = false; relay1SendState = false;
relay2SendState = false; relay2SendState = false;
pCmdChar = nullptr; pCmdChar = nullptr;
Serial.printf("BLE: disconnected (reason=%d)\n", reason); ESP_LOGW(TAG, "BLE: disconnected (reason=%d)", reason);
} }
}; };
@ -129,7 +132,7 @@ static bool connectToServer() {
pClient->setClientCallbacks(&clientCallbacks); pClient->setClientCallbacks(&clientCallbacks);
if (!pClient->connect(serverAddress)) { if (!pClient->connect(serverAddress)) {
Serial.println("BLE: connect failed"); ESP_LOGE(TAG, "BLE: connect failed");
NimBLEDevice::deleteClient(pClient); NimBLEDevice::deleteClient(pClient);
pClient = nullptr; pClient = nullptr;
return false; return false;
@ -137,14 +140,14 @@ static bool connectToServer() {
NimBLERemoteService *pSvc = pClient->getService(SERVICE_UUID); NimBLERemoteService *pSvc = pClient->getService(SERVICE_UUID);
if (pSvc == nullptr) { if (pSvc == nullptr) {
Serial.println("BLE: service not found"); ESP_LOGW(TAG, "BLE: service not found");
disconnectClient(); disconnectClient();
return false; return false;
} }
NimBLERemoteCharacteristic *pUuidChar = pSvc->getCharacteristic(UUID_CHAR_UUID); NimBLERemoteCharacteristic *pUuidChar = pSvc->getCharacteristic(UUID_CHAR_UUID);
if (pUuidChar == nullptr) { if (pUuidChar == nullptr) {
Serial.println("BLE: UUID characteristic not found"); ESP_LOGW(TAG, "BLE: UUID characteristic not found");
disconnectClient(); disconnectClient();
return false; return false;
} }
@ -152,14 +155,14 @@ static bool connectToServer() {
std::string uuidVal = pUuidChar->readValue(); std::string uuidVal = pUuidChar->readValue();
if (uuidVal.length() != ESP_UUID_LEN || if (uuidVal.length() != ESP_UUID_LEN ||
memcmp(uuidVal.data(), serverUuid, ESP_UUID_LEN) != 0) { memcmp(uuidVal.data(), serverUuid, ESP_UUID_LEN) != 0) {
Serial.println("BLE: server UUID mismatch — disconnecting"); ESP_LOGW(TAG, "BLE: server UUID mismatch — disconnecting");
disconnectClient(); disconnectClient();
return false; return false;
} }
pCmdChar = pSvc->getCharacteristic(CHARACTERISTIC_UUID); pCmdChar = pSvc->getCharacteristic(CHARACTERISTIC_UUID);
if (pCmdChar == nullptr) { if (pCmdChar == nullptr) {
Serial.println("BLE: command characteristic not found"); ESP_LOGW(TAG, "BLE: command characteristic not found");
disconnectClient(); disconnectClient();
return false; return false;
} }
@ -167,14 +170,14 @@ static bool connectToServer() {
seq = 0; seq = 0;
relay1SendState = false; relay1SendState = false;
relay2SendState = false; relay2SendState = false;
Serial.println("BLE: server UUID verified, ready"); ESP_LOGI(TAG, "BLE: server UUID verified, ready");
return true; return true;
} }
void setup() { void setup() {
Serial.begin(115200); Serial.begin(115200);
delay(2000); delay(2000);
Serial.println("=== SylDa Client ==="); ESP_LOGI(TAG, "=== SylDa Client v%s ===", FIRMWARE_VERSION_CLIENT);
FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS); FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
leds[0] = CRGB::Red; leds[0] = CRGB::Red;
@ -188,17 +191,15 @@ void setup() {
if (len == HMAC_KEY_LEN) { if (len == HMAC_KEY_LEN) {
keyProvisioned = true; keyProvisioned = true;
Serial.println("HMAC key loaded from NVS"); ESP_LOGI(TAG, "HMAC key loaded from NVS");
} else { } else {
keyProvisioned = false; keyProvisioned = false;
Serial.println("No HMAC key — use USB SET_KEY to provision"); ESP_LOGW(TAG, "No HMAC key — use USB SET_KEY to provision");
} }
if (uuidLen == ESP_UUID_LEN) { if (uuidLen == ESP_UUID_LEN) {
uuidProvisioned = true; uuidProvisioned = true;
Serial.print("UUID loaded from NVS: "); ESP_LOGD(TAG, "UUID loaded from NVS");
for (int i = 0; i < ESP_UUID_LEN; i++) Serial.printf("%02X", deviceUuid[i]);
Serial.println();
} else { } else {
uuidProvisioned = false; uuidProvisioned = false;
for (int i = 0; i < ESP_UUID_LEN; i++) deviceUuid[i] = (uint8_t)(esp_random() & 0xFF); for (int i = 0; i < ESP_UUID_LEN; i++) deviceUuid[i] = (uint8_t)(esp_random() & 0xFF);
@ -206,19 +207,15 @@ void setup() {
preferences.putBytes(NVS_UUID_NAME, deviceUuid, ESP_UUID_LEN); preferences.putBytes(NVS_UUID_NAME, deviceUuid, ESP_UUID_LEN);
preferences.end(); preferences.end();
uuidProvisioned = true; uuidProvisioned = true;
Serial.print("Generated new UUID: "); ESP_LOGD(TAG, "Generated new UUID");
for (int i = 0; i < ESP_UUID_LEN; i++) Serial.printf("%02X", deviceUuid[i]);
Serial.println();
} }
if (serverLen == ESP_UUID_LEN) { if (serverLen == ESP_UUID_LEN) {
serverProvisioned = true; serverProvisioned = true;
Serial.print("Server UUID loaded from NVS: "); ESP_LOGD(TAG, "Server UUID loaded from NVS");
for (int i = 0; i < ESP_UUID_LEN; i++) Serial.printf("%02X", serverUuid[i]);
Serial.println();
} else { } else {
serverProvisioned = false; serverProvisioned = false;
Serial.println("No server UUID — use USB SET_SERVER to provision"); ESP_LOGW(TAG, "No server UUID — use USB SET_SERVER to provision");
} }
allProvisioned = keyProvisioned && uuidProvisioned && serverProvisioned; allProvisioned = keyProvisioned && uuidProvisioned && serverProvisioned;
@ -237,10 +234,10 @@ void setup() {
pScan->setActiveScan(false); pScan->setActiveScan(false);
pScan->setMaxResults(0); pScan->setMaxResults(0);
bleReady = true; bleReady = true;
Serial.println("BLE: initialized, will scan for SylDa_Server"); ESP_LOGI(TAG, "BLE: initialized, will scan for SylDa_Server");
} }
Serial.println("Setup done."); ESP_LOGI(TAG, "Setup done.");
} }
void loop() { void loop() {
@ -290,7 +287,7 @@ void loop() {
pScan->setActiveScan(false); pScan->setActiveScan(false);
pScan->setMaxResults(0); pScan->setMaxResults(0);
bleReady = true; bleReady = true;
Serial.println("BLE: initialized after provisioning"); ESP_LOGI(TAG, "BLE: initialized after key provisioning");
} }
} else { } else {
Serial.println("ERROR: invalid key format"); Serial.println("ERROR: invalid key format");
@ -331,7 +328,7 @@ void loop() {
pScan->setActiveScan(false); pScan->setActiveScan(false);
pScan->setMaxResults(0); pScan->setMaxResults(0);
bleReady = true; bleReady = true;
Serial.println("BLE: initialized after provisioning"); ESP_LOGI(TAG, "BLE: initialized after server provisioning");
} }
} else { } else {
Serial.println("ERROR: invalid server UUID format"); Serial.println("ERROR: invalid server UUID format");
@ -363,9 +360,6 @@ void loop() {
bool btnActive = (millis() - btnChange > DEBOUNCE_MS) && btnStable; bool btnActive = (millis() - btnChange > DEBOUNCE_MS) && btnStable;
static bool prevBtnActive = false; static bool prevBtnActive = false;
if (btnActive && !prevBtnActive) {
Serial.printf("Button: pressed\n");
}
prevBtnActive = btnActive; prevBtnActive = btnActive;
bool relay1State = !t1Active || btnActive; bool relay1State = !t1Active || btnActive;
@ -415,7 +409,7 @@ void loop() {
buildHmacPacket(relay1State ? 0x01 : 0x00, pkt); buildHmacPacket(relay1State ? 0x01 : 0x00, pkt);
pCmdChar->writeValue(pkt, HMAC_PKT_SIZE, false); pCmdChar->writeValue(pkt, HMAC_PKT_SIZE, false);
relay1SendState = relay1State; relay1SendState = relay1State;
Serial.printf("TX: relay1 %s (seq=%lu)\n", relay1State ? "ON" : "OFF", seq); ESP_LOGD(TAG, "TX: relay1 %s (seq=%lu)", relay1State ? "ON" : "OFF", seq);
lastCmd = millis(); lastCmd = millis();
} }
if (relay2State != relay2SendState) { if (relay2State != relay2SendState) {
@ -423,7 +417,7 @@ void loop() {
buildHmacPacket(relay2State ? 0x02 : 0x03, pkt); buildHmacPacket(relay2State ? 0x02 : 0x03, pkt);
pCmdChar->writeValue(pkt, HMAC_PKT_SIZE, false); pCmdChar->writeValue(pkt, HMAC_PKT_SIZE, false);
relay2SendState = relay2State; relay2SendState = relay2State;
Serial.printf("TX: relay2 %s (seq=%lu)\n", relay2State ? "ON" : "OFF", seq); ESP_LOGD(TAG, "TX: relay2 %s (seq=%lu)", relay2State ? "ON" : "OFF", seq);
lastCmd = millis(); lastCmd = millis();
} }
} }
@ -444,21 +438,20 @@ void loop() {
if (!pScan->isScanning() && scanRunnable) { if (!pScan->isScanning() && scanRunnable) {
scanRunnable = false; scanRunnable = false;
if (serverFound) { if (serverFound) {
Serial.printf("BLE: found SylDa_Server (%s), connecting...\n", ESP_LOGI(TAG, "BLE: found SylDa_Server, connecting...");
serverAddress.toString().c_str());
connectToServer(); connectToServer();
} }
} }
} }
if (connected && pClient != nullptr && !pClient->isConnected()) { if (connected && pClient != nullptr && !pClient->isConnected()) {
Serial.println("BLE: lost connection"); ESP_LOGW(TAG, "BLE: lost connection");
disconnectClient(); disconnectClient();
} }
static uint32_t heartbeat = 0; static uint32_t heartbeat = 0;
if (millis() - heartbeat > 60000) { if (millis() - heartbeat > 60000) {
Serial.printf("[heartbeat] t1=%s t2=%s btn=%s r1=%s r2=%s connected=%s\n", ESP_LOGI(TAG, "[heartbeat] t1=%s t2=%s btn=%s r1=%s r2=%s connected=%s",
!t1Active ? "YES" : "no", !t1Active ? "YES" : "no",
!t2Active ? "YES" : "no", !t2Active ? "YES" : "no",
btnActive ? "YES" : "no", btnActive ? "YES" : "no",

View file

@ -9,8 +9,11 @@
#include <esp_ota_ops.h> #include <esp_ota_ops.h>
#include <esp_partition.h> #include <esp_partition.h>
#include <nvs_flash.h> #include <nvs_flash.h>
#include <esp_log.h>
#include "version.h" #include "version.h"
static const char *TAG = "server";
#define RELAY1_PIN 1 #define RELAY1_PIN 1
#define RELAY2_PIN 2 #define RELAY2_PIN 2
#define TOUCH1_PIN 8 #define TOUCH1_PIN 8
@ -104,12 +107,12 @@ class MyServerCallbacks : public NimBLEServerCallbacks {
bleRelay2[slot] = false; bleRelay2[slot] = false;
lastSeq[slot] = 0; lastSeq[slot] = 0;
connectedCount++; connectedCount++;
Serial.printf("BLE: device connected (conn=%d, slot=%d, clients=%d/%d, mac=%s)\n", ESP_LOGI(TAG, "BLE: connected (slot=%d, clients=%d/%d, mac=%s)",
handle, slot, connectedCount, MAX_CLIENTS, slot, connectedCount, MAX_CLIENTS,
connInfo.getAddress().toString().c_str()); connInfo.getAddress().toString().c_str());
} else { } else {
Serial.printf("BLE: device connected but no free slot (conn=%d, clients=%d/%d)\n", ESP_LOGW(TAG, "BLE: connected but no free slot (clients=%d/%d)",
handle, connectedCount, MAX_CLIENTS); connectedCount, MAX_CLIENTS);
} }
pServer->startAdvertising(); pServer->startAdvertising();
} }
@ -123,8 +126,8 @@ class MyServerCallbacks : public NimBLEServerCallbacks {
lastSeq[i] = 0; lastSeq[i] = 0;
connHandles[i] = 0xFFFF; connHandles[i] = 0xFFFF;
connectedCount--; connectedCount--;
Serial.printf("BLE: device disconnected (conn=%d, slot=%d, clients=%d/%d, mac=%s)\n", ESP_LOGI(TAG, "BLE: disconnected (slot=%d, clients=%d/%d, mac=%s)",
handle, i, connectedCount, MAX_CLIENTS, i, connectedCount, MAX_CLIENTS,
connInfo.getAddress().toString().c_str()); connInfo.getAddress().toString().c_str());
break; break;
} }
@ -134,7 +137,7 @@ class MyServerCallbacks : public NimBLEServerCallbacks {
static bool verifyHmac(const uint8_t *packet, int idx) { static bool verifyHmac(const uint8_t *packet, int idx) {
if (idx < 0 || idx >= MAX_CLIENTS || !connActive[idx]) { if (idx < 0 || idx >= MAX_CLIENTS || !connActive[idx]) {
Serial.printf("BLE: HMAC verify called for invalid idx=%d\n", idx); ESP_LOGW(TAG, "HMAC verify for invalid idx=%d", idx);
return false; return false;
} }
@ -145,7 +148,7 @@ static bool verifyHmac(const uint8_t *packet, int idx) {
(uint32_t)packet[4]; (uint32_t)packet[4];
if (seq <= lastSeq[idx]) { if (seq <= lastSeq[idx]) {
Serial.printf("BLE: replay rejected (seq=%lu, last=%lu, slot=%d)\n", seq, lastSeq[idx], idx); ESP_LOGW(TAG, "Replay rejected (seq=%lu, last=%lu, slot=%d)", seq, lastSeq[idx], idx);
return false; return false;
} }
@ -161,7 +164,7 @@ static bool verifyHmac(const uint8_t *packet, int idx) {
mbedtls_md_hmac(mdInfo, hmacKey, HMAC_KEY_LEN, hmacData, 5, computed); mbedtls_md_hmac(mdInfo, hmacKey, HMAC_KEY_LEN, hmacData, 5, computed);
if (memcmp(computed, packet + 5, 32) != 0) { if (memcmp(computed, packet + 5, 32) != 0) {
Serial.println("BLE: HMAC mismatch"); ESP_LOGE(TAG, "HMAC mismatch");
return false; return false;
} }
@ -209,12 +212,12 @@ static void sendOtaNotify(NimBLECharacteristic *otaChar, uint8_t status, uint32_
otaChar->setValue(buf, 5); otaChar->setValue(buf, 5);
bool ok = otaChar->notify(); bool ok = otaChar->notify();
if (!ok) { if (!ok) {
Serial.printf("OTA: notify() returned false for status=0x%02X seq=%lu\n", status, seq); ESP_LOGW(TAG, "OTA notify() failed (status=0x%02X seq=%lu)", status, seq);
} }
} }
static void abortOta(NimBLECharacteristic *otaChar, const char *reason) { static void abortOta(NimBLECharacteristic *otaChar, const char *reason) {
Serial.printf("OTA: abort — %s\n", reason); ESP_LOGE(TAG, "OTA: abort — %s", reason);
if (otaHandle != 0) { if (otaHandle != 0) {
esp_ota_end(otaHandle); esp_ota_end(otaHandle);
} }
@ -238,13 +241,13 @@ class OtaCharacteristicCallbacks : public NimBLECharacteristicCallbacks {
((uint32_t)data[3] << 8) | (uint32_t)data[4]; ((uint32_t)data[3] << 8) | (uint32_t)data[4];
otaPartition = esp_ota_get_next_update_partition(nullptr); otaPartition = esp_ota_get_next_update_partition(nullptr);
if (otaPartition == nullptr) { if (otaPartition == nullptr) {
Serial.println("OTA: no update partition found"); ESP_LOGE(TAG, "OTA: no update partition found");
sendOtaNotify(pChar, OTA_STATUS_ERROR, 0); sendOtaNotify(pChar, OTA_STATUS_ERROR, 0);
return; return;
} }
esp_err_t err = esp_ota_begin(otaPartition, otaExpectedSize, &otaHandle); esp_err_t err = esp_ota_begin(otaPartition, otaExpectedSize, &otaHandle);
if (err != ESP_OK) { if (err != ESP_OK) {
Serial.printf("OTA: begin failed (%d)\n", err); ESP_LOGE(TAG, "OTA: begin failed (%d)", err);
sendOtaNotify(pChar, OTA_STATUS_ERROR, 0); sendOtaNotify(pChar, OTA_STATUS_ERROR, 0);
return; return;
} }
@ -261,7 +264,7 @@ class OtaCharacteristicCallbacks : public NimBLECharacteristicCallbacks {
bleRelay1[i] = false; bleRelay1[i] = false;
bleRelay2[i] = false; bleRelay2[i] = false;
} }
Serial.printf("OTA: started, expecting %lu bytes\n", otaExpectedSize); ESP_LOGI(TAG, "OTA: started, expecting %lu bytes", otaExpectedSize);
return; return;
} }
@ -272,37 +275,35 @@ class OtaCharacteristicCallbacks : public NimBLECharacteristicCallbacks {
mbedtls_sha256_free(&otaShaCtx); mbedtls_sha256_free(&otaShaCtx);
otaShaStarted = false; otaShaStarted = false;
Serial.printf("OTA: SHA256 verify — written=%lu expected=%lu\n", otaWritten, otaExpectedSize); ESP_LOGD(TAG, "OTA: SHA256 verify (written=%lu expected=%lu)", otaWritten, otaExpectedSize);
if (memcmp(computedSha, otaExpectedSha, 32) != 0) { if (memcmp(computedSha, otaExpectedSha, 32) != 0) {
Serial.println("OTA: SHA256 mismatch — aborting"); ESP_LOGE(TAG, "OTA: SHA256 mismatch — aborting");
esp_ota_abort(otaHandle); esp_ota_abort(otaHandle);
otaReset(); otaReset();
sendOtaNotify(pChar, OTA_STATUS_ERROR, 0); sendOtaNotify(pChar, OTA_STATUS_ERROR, 0);
return; return;
} }
Serial.println("OTA: SHA256 OK, setting otaReady=true, sending COMPLETE notify"); ESP_LOGI(TAG, "OTA: SHA256 OK, waiting for 0xFF confirm");
otaReady = true; otaReady = true;
sendOtaNotify(pChar, OTA_STATUS_COMPLETE, 0); sendOtaNotify(pChar, OTA_STATUS_COMPLETE, 0);
Serial.printf("OTA: COMPLETE notify sent, otaReady=%d, otaConfirmed=%d, otaInProgress=%d\n",
otaReady, otaConfirmed, otaInProgress);
return; return;
} }
if (!otaInProgress) { if (!otaInProgress) {
Serial.printf("OTA: write ignored — otaInProgress=false (len=%d, data0=0x%02X)\n", len, data[0]); ESP_LOGD(TAG, "OTA: write ignored (not in progress, len=%d data0=0x%02X)", len, data[0]);
return; return;
} }
if (len == 1 && data[0] == 0xFF) { if (len == 1 && data[0] == 0xFF) {
Serial.printf("OTA: 0xFF received — otaReady=%d, otaEnded=%d, otaConfirmed=%d, otaInProgress=%d\n", ESP_LOGD(TAG, "OTA: 0xFF received (ready=%d ended=%d confirmed=%d inProgress=%d)",
otaReady, otaEnded, otaConfirmed, otaInProgress); otaReady, otaEnded, otaConfirmed, otaInProgress);
if (!otaEnded) { if (!otaEnded) {
Serial.println("OTA: 0xFF arrived early (esp_ota_end not yet called), deferring"); ESP_LOGD(TAG, "OTA: 0xFF arrived early, deferring");
otaEarlyConfirm = true; otaEarlyConfirm = true;
return; return;
} }
Serial.println("OTA: 0xFF confirm accepted, setting otaConfirmed=true"); ESP_LOGI(TAG, "OTA: 0xFF confirm accepted");
otaConfirmed = true; otaConfirmed = true;
return; return;
} }
@ -312,12 +313,9 @@ class OtaCharacteristicCallbacks : public NimBLECharacteristicCallbacks {
((uint32_t)data[2] << 8) | (uint32_t)data[3]; ((uint32_t)data[2] << 8) | (uint32_t)data[3];
size_t dataLen = len - 4; size_t dataLen = len - 4;
mbedtls_sha256_update_ret(&otaShaCtx, data + 4, dataLen); mbedtls_sha256_update_ret(&otaShaCtx, data + 4, dataLen);
unsigned long t0 = micros();
esp_err_t err = esp_ota_write(otaHandle, data + 4, dataLen); esp_err_t err = esp_ota_write(otaHandle, data + 4, dataLen);
unsigned long elapsed = micros() - t0;
Serial.printf("OTA: chunk %lu write %d bytes in %lu us\n", seq, dataLen, elapsed);
if (err != ESP_OK) { if (err != ESP_OK) {
Serial.printf("OTA: write err at seq %lu (%d)\n", seq, err); ESP_LOGE(TAG, "OTA: write error at seq %lu (%d)", seq, err);
sendOtaNotify(pChar, OTA_STATUS_NAK, seq); sendOtaNotify(pChar, OTA_STATUS_NAK, seq);
abortOta(pChar, "write error"); abortOta(pChar, "write error");
return; return;
@ -334,15 +332,14 @@ class MyCharacteristicCallbacks : public NimBLECharacteristicCallbacks {
int idx = findClientIdx(connInfo.getConnHandle()); int idx = findClientIdx(connInfo.getConnHandle());
if (idx < 0) { if (idx < 0) {
Serial.printf("BLE: write from unknown conn handle %d\n", connInfo.getConnHandle()); ESP_LOGW(TAG, "BLE: write from unknown conn handle %d", connInfo.getConnHandle());
return; return;
} }
std::string value = pChar->getValue(); std::string value = pChar->getValue();
if (value.length() != HMAC_PKT_SIZE) { if (value.length() != HMAC_PKT_SIZE) {
Serial.printf("BLE: bad packet length %d (expected %d), slot=%d mac=%s\n", ESP_LOGW(TAG, "BLE: bad packet length %d (expected %d), slot=%d",
(int)value.length(), HMAC_PKT_SIZE, idx, (int)value.length(), HMAC_PKT_SIZE, idx);
connInfo.getAddress().toString().c_str());
return; return;
} }
@ -357,16 +354,16 @@ class MyCharacteristicCallbacks : public NimBLECharacteristicCallbacks {
if (cmd == 0x01) { if (cmd == 0x01) {
bleRelay1[idx] = true; bleRelay1[idx] = true;
Serial.printf("BLE: relay1 ON (seq=%lu, slot=%d)\n", seq, idx); ESP_LOGI(TAG, "BLE: relay1 ON (seq=%lu, slot=%d)", seq, idx);
} else if (cmd == 0x00) { } else if (cmd == 0x00) {
bleRelay1[idx] = false; bleRelay1[idx] = false;
Serial.printf("BLE: relay1 OFF (seq=%lu, slot=%d)\n", seq, idx); ESP_LOGI(TAG, "BLE: relay1 OFF (seq=%lu, slot=%d)", seq, idx);
} else if (cmd == 0x02) { } else if (cmd == 0x02) {
bleRelay2[idx] = true; bleRelay2[idx] = true;
Serial.printf("BLE: relay2 ON (seq=%lu, slot=%d)\n", seq, idx); ESP_LOGI(TAG, "BLE: relay2 ON (seq=%lu, slot=%d)", seq, idx);
} else if (cmd == 0x03) { } else if (cmd == 0x03) {
bleRelay2[idx] = false; bleRelay2[idx] = false;
Serial.printf("BLE: relay2 OFF (seq=%lu, slot=%d)\n", seq, idx); ESP_LOGI(TAG, "BLE: relay2 OFF (seq=%lu, slot=%d)", seq, idx);
} }
} }
}; };
@ -374,7 +371,7 @@ class MyCharacteristicCallbacks : public NimBLECharacteristicCallbacks {
void setup() { void setup() {
Serial.begin(115200); Serial.begin(115200);
delay(2000); delay(2000);
Serial.println("=== AtomS3 Lite BLE Relay ==="); ESP_LOGI(TAG, "=== AtomS3 Lite BLE Relay v%s ===", FIRMWARE_VERSION);
FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS); FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
@ -385,17 +382,15 @@ void setup() {
if (len == HMAC_KEY_LEN) { if (len == HMAC_KEY_LEN) {
keyProvisioned = true; keyProvisioned = true;
Serial.println("HMAC key loaded from NVS"); ESP_LOGI(TAG, "HMAC key loaded from NVS");
} else { } else {
keyProvisioned = false; keyProvisioned = false;
Serial.println("No HMAC key provisioned — connect USB and run SET_KEY"); ESP_LOGW(TAG, "No HMAC key — connect USB and run SET_KEY");
} }
if (uuidLen == ESP_UUID_LEN) { if (uuidLen == ESP_UUID_LEN) {
uuidProvisioned = true; uuidProvisioned = true;
Serial.print("UUID loaded from NVS: "); ESP_LOGD(TAG, "UUID loaded from NVS");
for (int i = 0; i < ESP_UUID_LEN; i++) Serial.printf("%02X", deviceUuid[i]);
Serial.println();
} else { } else {
uuidProvisioned = false; uuidProvisioned = false;
for (int i = 0; i < ESP_UUID_LEN; i++) deviceUuid[i] = (uint8_t)(esp_random() & 0xFF); for (int i = 0; i < ESP_UUID_LEN; i++) deviceUuid[i] = (uint8_t)(esp_random() & 0xFF);
@ -403,9 +398,7 @@ void setup() {
preferences.putBytes(NVS_UUID_NAME, deviceUuid, ESP_UUID_LEN); preferences.putBytes(NVS_UUID_NAME, deviceUuid, ESP_UUID_LEN);
preferences.end(); preferences.end();
uuidProvisioned = true; uuidProvisioned = true;
Serial.print("Generated new UUID: "); ESP_LOGD(TAG, "Generated new UUID");
for (int i = 0; i < ESP_UUID_LEN; i++) Serial.printf("%02X", deviceUuid[i]);
Serial.println();
} }
pinMode(TOUCH1_PIN, INPUT); pinMode(TOUCH1_PIN, INPUT);
@ -416,7 +409,6 @@ void setup() {
leds[0] = CRGB::Red; leds[0] = CRGB::Red;
FastLED.show(); FastLED.show();
Serial.println("LED red (no connection), starting BLE...");
NimBLEDevice::init("SylDa_Server"); NimBLEDevice::init("SylDa_Server");
NimBLEDevice::setMTU(248); NimBLEDevice::setMTU(248);
@ -462,20 +454,15 @@ void setup() {
pAdvertising->setMinInterval(32); pAdvertising->setMinInterval(32);
pAdvertising->setMaxInterval(64); pAdvertising->setMaxInterval(64);
bool advOk = pAdvertising->start(); bool advOk = pAdvertising->start();
Serial.printf("BLE: advertising started as 'SylDa_Server' (start=%d, isAdv=%d)\n", ESP_LOGI(TAG, "BLE: advertising started");
advOk, pAdvertising->isAdvertising());
if (keyProvisioned) { if (keyProvisioned) {
Serial.print("HMAC Key: "); ESP_LOGD(TAG, "HMAC key present");
for (int i = 0; i < HMAC_KEY_LEN; i++) {
Serial.printf("%02X", hmacKey[i]);
}
Serial.println();
} else { } else {
Serial.println("No HMAC key — use USB SET_KEY to provision"); ESP_LOGW(TAG, "No HMAC key — use USB SET_KEY to provision");
} }
Serial.println("Setup done."); ESP_LOGI(TAG, "Setup done.");
} }
void loop() { void loop() {
@ -537,43 +524,41 @@ void loop() {
} }
if (otaReady) { if (otaReady) {
Serial.printf("OTA: loop() processing otaReady — otaWritten=%lu, otaExpectedSize=%lu\n", ESP_LOGD(TAG, "OTA: processing otaReady (written=%lu expected=%lu)",
otaWritten, otaExpectedSize); otaWritten, otaExpectedSize);
esp_err_t err = esp_ota_end(otaHandle); esp_err_t err = esp_ota_end(otaHandle);
if (err != ESP_OK) { if (err != ESP_OK) {
Serial.printf("OTA: esp_ota_end failed (%d) — aborting\n", err); ESP_LOGE(TAG, "OTA: esp_ota_end failed (%d) — aborting", err);
otaReset(); otaReset();
} else { } else {
Serial.println("OTA: esp_ota_end OK, setting otaEnded=true, waiting for 0xFF confirm"); ESP_LOGI(TAG, "OTA: esp_ota_end OK, waiting for 0xFF confirm");
otaEnded = true; otaEnded = true;
otaEndedAt = millis(); otaEndedAt = millis();
} }
otaReady = false; otaReady = false;
Serial.printf("OTA: otaReady cleared — otaReady=%d, otaEnded=%d, otaConfirmed=%d, otaInProgress=%d\n",
otaReady, otaEnded, otaConfirmed, otaInProgress);
} }
if (otaEnded && otaEarlyConfirm) { if (otaEnded && otaEarlyConfirm) {
Serial.println("OTA: processing deferred 0xFF confirm"); ESP_LOGD(TAG, "OTA: processing deferred 0xFF confirm");
otaConfirmed = true; otaConfirmed = true;
otaEarlyConfirm = false; otaEarlyConfirm = false;
} }
if (otaEnded && !otaConfirmed && (millis() - otaEndedAt > OTA_CONFIRM_TIMEOUT_MS)) { if (otaEnded && !otaConfirmed && (millis() - otaEndedAt > OTA_CONFIRM_TIMEOUT_MS)) {
Serial.printf("OTA: 0xFF confirm timeout (%lu ms) — discarding update, resuming normal operation\n", ESP_LOGW(TAG, "OTA: 0xFF confirm timeout (%lu ms) — discarding update",
millis() - otaEndedAt); millis() - otaEndedAt);
otaReset(); otaReset();
} }
if (otaConfirmed) { if (otaConfirmed) {
Serial.println("OTA: otaConfirmed=true, setting boot partition"); ESP_LOGI(TAG, "OTA: confirmed, setting boot partition");
esp_err_t err = esp_ota_set_boot_partition(otaPartition); esp_err_t err = esp_ota_set_boot_partition(otaPartition);
if (err != ESP_OK) { if (err != ESP_OK) {
Serial.printf("OTA: set boot partition failed (%d)\n", err); ESP_LOGE(TAG, "OTA: set boot partition failed (%d)", err);
} else { } else {
leds[0] = CRGB::Green; leds[0] = CRGB::Green;
FastLED.show(); FastLED.show();
Serial.println("OTA: done, rebooting..."); ESP_LOGI(TAG, "OTA: done, rebooting...");
delay(500); delay(500);
esp_restart(); esp_restart();
} }
@ -652,7 +637,7 @@ void loop() {
if (relay1State != lastRelay1 || relay2State != lastRelay2) { if (relay1State != lastRelay1 || relay2State != lastRelay2) {
bool anyBle1 = (connActive[0] && bleRelay1[0]) || (connActive[1] && bleRelay1[1]); bool anyBle1 = (connActive[0] && bleRelay1[0]) || (connActive[1] && bleRelay1[1]);
bool anyBle2 = (connActive[0] && bleRelay2[0]) || (connActive[1] && bleRelay2[1]); bool anyBle2 = (connActive[0] && bleRelay2[0]) || (connActive[1] && bleRelay2[1]);
Serial.printf("Relays: R1=%s R2=%s (t1=%s t2=%s btn=%s ble1=%s ble2=%s)\n", ESP_LOGI(TAG, "Relays: R1=%s R2=%s (t1=%s t2=%s btn=%s ble1=%s ble2=%s)",
relay1State ? "ON" : "OFF", relay1State ? "ON" : "OFF",
relay2State ? "ON" : "OFF", relay2State ? "ON" : "OFF",
t1Active ? "YES" : "no", t1Active ? "YES" : "no",
@ -668,7 +653,7 @@ void loop() {
if (!otaInProgress && millis() - heartbeat > 60000) { if (!otaInProgress && millis() - heartbeat > 60000) {
bool anyBle1 = (connActive[0] && bleRelay1[0]) || (connActive[1] && bleRelay1[1]); bool anyBle1 = (connActive[0] && bleRelay1[0]) || (connActive[1] && bleRelay1[1]);
bool anyBle2 = (connActive[0] && bleRelay2[0]) || (connActive[1] && bleRelay2[1]); bool anyBle2 = (connActive[0] && bleRelay2[0]) || (connActive[1] && bleRelay2[1]);
Serial.printf("[heartbeat] R1=%s R2=%s t1=%s t2=%s btn=%s ble1=%s ble2=%s clients=%d\n", ESP_LOGI(TAG, "[heartbeat] R1=%s R2=%s t1=%s t2=%s btn=%s ble1=%s ble2=%s clients=%d",
relay1State ? "ON" : "OFF", relay1State ? "ON" : "OFF",
relay2State ? "ON" : "OFF", relay2State ? "ON" : "OFF",
t1Active ? "YES" : "no", t1Active ? "YES" : "no",