diff --git a/android/app/src/main/assets/firmware/client/firmware.bin b/android/app/src/main/assets/firmware/client/firmware.bin index f979c0a..71b8020 100644 Binary files a/android/app/src/main/assets/firmware/client/firmware.bin and b/android/app/src/main/assets/firmware/client/firmware.bin differ diff --git a/android/app/src/main/assets/firmware/server/firmware.bin b/android/app/src/main/assets/firmware/server/firmware.bin index a06fef0..83a42b6 100644 Binary files a/android/app/src/main/assets/firmware/server/firmware.bin and b/android/app/src/main/assets/firmware/server/firmware.bin differ diff --git a/android/app/src/main/java/nl/eddydevink/sylda/SettingsActivity.kt b/android/app/src/main/java/nl/eddydevink/sylda/SettingsActivity.kt index 58496f6..24990e7 100644 --- a/android/app/src/main/java/nl/eddydevink/sylda/SettingsActivity.kt +++ b/android/app/src/main/java/nl/eddydevink/sylda/SettingsActivity.kt @@ -440,6 +440,8 @@ class SettingsActivity : AppCompatActivity() { showProgressDialog(getString(R.string.title_firmware_flash), getString(R.string.msg_checking_version), STYLE_SPINNER) lifecycleScope.launch { + val expected = getExpectedFirmwareVersion() + Log.d(TAG, "doFlashing: expected firmware version=$expected, expectingReboot=$expectingReboot") val version = readEspVersion(usbManager, device) if (version == getExpectedFirmwareVersion() && !expectingReboot) { Log.d(TAG, "Firmware version $version matches, up to date") @@ -583,7 +585,17 @@ class SettingsActivity : AppCompatActivity() { } private fun readEspVersion(usbManager: UsbManager, device: UsbDevice): String? { - val intf = UsbUtils.findCdcDataInterface(device) ?: return null + Log.d(TAG, "readEspVersion: device=${device.deviceName}, id=${device.deviceId}, interfaces=${device.interfaceCount}") + for (i in 0 until device.interfaceCount) { + val intf = device.getInterface(i) + Log.d(TAG, "readEspVersion: intf[$i]=class:0x${intf.interfaceClass.toString(16)} subclass:0x${intf.interfaceSubclass.toString(16)} proto:0x${intf.interfaceProtocol.toString(16)} eps=${intf.endpointCount}") + } + val intf = UsbUtils.findCdcDataInterface(device) + if (intf == null) { + Log.w(TAG, "readEspVersion: no CDC data interface (class 0x0A) found") + return null + } + Log.d(TAG, "readEspVersion: found CDC data iface=${intf.id}") val connection = usbManager.openDevice(device) ?: return null if (!connection.claimInterface(intf, true)) { connection.close(); return null } @@ -595,12 +607,18 @@ class SettingsActivity : AppCompatActivity() { return try { setupCdcControl(connection, device) Thread.sleep(KEY_SETTLE_MS) + + flushReadBuffer(connection, epIn) + val cmd = "VERSION?\n".toByteArray(StandardCharsets.US_ASCII) - connection.bulkTransfer(epOut, cmd, cmd.size, USB_BULK_TIMEOUT_MS) + val writeResult = connection.bulkTransfer(epOut, cmd, cmd.size, USB_BULK_TIMEOUT_MS) + Log.d(TAG, "readEspVersion: bulkTransfer OUT result=$writeResult (expected ${cmd.size})") Thread.sleep(RESPONSE_WAIT_MS) val response = readResponse(connection, epIn, VERSION_TIMEOUT_MS) - val versionLine = response.lines().firstOrNull { it.startsWith("BUILD_NR:") } - versionLine?.removePrefix("BUILD_NR:")?.trim() + Log.d(TAG, "readEspVersion: raw response='${response.replace("\r", "\\r").replace("\n", "\\n")}' (len=${response.length})") + val match = Regex("BUILD_NR:(\\d+)").find(response) + Log.d(TAG, "readEspVersion: regex match=$match, group1=${match?.groupValues?.get(1)}") + match?.groupValues?.get(1) } finally { connection.close() } @@ -753,16 +771,20 @@ class SettingsActivity : AppCompatActivity() { val sb = StringBuilder() val startTime = System.currentTimeMillis() + var reads = 0 while (System.currentTimeMillis() - startTime < timeoutMs) { val len = connection.bulkTransfer(epIn, buf, buf.size, READ_CHUNK_TIMEOUT_MS) if (len > 0) { + reads++ sb.append(String(buf, 0, len, StandardCharsets.US_ASCII)) + Log.d(TAG, "readResponse: chunk len=$len, sb now='${sb.toString().replace("\r","\\r").replace("\n","\\n")}'") if ((sb.contains("HMAC_KEY:") || sb.contains("NO_KEY") || sb.contains("OK") || sb.contains("ERROR")) && sb.contains("\n")) { break } } } + Log.d(TAG, "readResponse: done after ${System.currentTimeMillis()-startTime}ms, ${reads} reads, response='${sb.toString().replace("\r","\\r").replace("\n","\\n")}'") return sb.toString() } diff --git a/src/client.cpp b/src/client.cpp index af513c3..6fb39a8 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -66,6 +66,7 @@ class MyScanCallbacks : public NimBLEScanCallbacks { serverAddress = advertisedDevice->getAddress(); serverFound = true; NimBLEDevice::getScan()->stop(); + ESP_LOGI(TAG, "Found server: %s", advertisedDevice->getAddress().toString().c_str()); } } }; @@ -220,8 +221,8 @@ void setup() { allProvisioned = keyProvisioned && uuidProvisioned && serverProvisioned; - pinMode(TOUCH1_PIN, INPUT); - pinMode(TOUCH2_PIN, INPUT); + pinMode(TOUCH1_PIN, INPUT_PULLUP); + pinMode(TOUCH2_PIN, INPUT_PULLUP); pinMode(BUTTON_PIN, INPUT); if (allProvisioned) { @@ -231,7 +232,7 @@ void setup() { pScan->setScanCallbacks(new MyScanCallbacks()); pScan->setInterval(97); pScan->setWindow(37); - pScan->setActiveScan(false); + pScan->setActiveScan(true); pScan->setMaxResults(0); bleReady = true; ESP_LOGI(TAG, "BLE: initialized, scanning for service UUID"); @@ -286,7 +287,7 @@ void loop() { pScan->setScanCallbacks(new MyScanCallbacks()); pScan->setInterval(97); pScan->setWindow(37); - pScan->setActiveScan(false); + pScan->setActiveScan(true); pScan->setMaxResults(0); bleReady = true; ESP_LOGI(TAG, "BLE: initialized after key provisioning"); @@ -329,7 +330,7 @@ void loop() { pScan->setScanCallbacks(new MyScanCallbacks()); pScan->setInterval(97); pScan->setWindow(37); - pScan->setActiveScan(false); + pScan->setActiveScan(true); pScan->setMaxResults(0); bleReady = true; ESP_LOGI(TAG, "BLE: initialized after server provisioning"); diff --git a/src/main.cpp b/src/main.cpp index 473712c..e52bbec 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -48,6 +48,7 @@ CRGB leds[NUM_LEDS]; #define FIRMWARE_VERSION FIRMWARE_VERSION_SERVER NimBLECharacteristic *pCharacteristic; +NimBLECharacteristic *pUuidChar; bool relay1State = false; bool relay2State = false; @@ -401,8 +402,8 @@ void setup() { ESP_LOGD(TAG, "Generated new UUID"); } - pinMode(TOUCH1_PIN, INPUT); - pinMode(TOUCH2_PIN, INPUT); + pinMode(TOUCH1_PIN, INPUT_PULLUP); + pinMode(TOUCH2_PIN, INPUT_PULLUP); pinMode(BUTTON_PIN, INPUT); pinMode(RELAY1_PIN, OUTPUT); pinMode(RELAY2_PIN, OUTPUT); @@ -424,7 +425,7 @@ void setup() { ); pCharacteristic->setCallbacks(new MyCharacteristicCallbacks()); - NimBLECharacteristic *pUuidChar = pService->createCharacteristic( + pUuidChar = pService->createCharacteristic( UUID_CHAR_UUID, NIMBLE_PROPERTY::READ ); @@ -488,6 +489,7 @@ void loop() { } else if (serialBuf == "ID?") { Serial.println("SylDa_Server"); } else if (serialBuf == "VERSION?") { + Serial.flush(); Serial.print("BUILD_NR:"); Serial.println(FIRMWARE_VERSION); } else if (serialBuf.startsWith("SET_KEY:")) { @@ -515,6 +517,7 @@ void loop() { preferences.putBytes(NVS_UUID_NAME, deviceUuid, ESP_UUID_LEN); preferences.end(); uuidProvisioned = true; + pUuidChar->setValue(deviceUuid, ESP_UUID_LEN); Serial.println("OK"); Serial.println("UUID stored in NVS"); } else { @@ -585,9 +588,9 @@ void loop() { bool btnActive = (millis() - btnChange > DEBOUNCE_MS) && btnStable; if (!otaInProgress) { - relay1State = t1Active || btnActive || + relay1State = !t1Active || btnActive || (connActive[0] && bleRelay1[0]) || (connActive[1] && bleRelay1[1]); - relay2State = t2Active || + relay2State = !t2Active || (connActive[0] && bleRelay2[0]) || (connActive[1] && bleRelay2[1]); } else { relay1State = false; diff --git a/tools/copy_firmware.sh b/tools/copy_firmware.sh index ccb34ca..8c743fb 100755 --- a/tools/copy_firmware.sh +++ b/tools/copy_firmware.sh @@ -1,22 +1,29 @@ #!/bin/bash set -e -BINARY_DIR="$(cd "$(dirname "$0")/.." && pwd)/.pio/build/s3lite-server" -ASSETS_DIR="$(cd "$(dirname "$0")/.." && pwd)/android/app/src/main/assets/firmware" +PROJECT_DIR="$(cd "$(dirname "$0")/.." && pwd)" +ASSETS_BASE="$PROJECT_DIR/android/app/src/main/assets/firmware" -mkdir -p "$ASSETS_DIR" +copy_binaries() { + local BINARY_DIR="$1" + local ASSETS_DIR="$2" -cp "$BINARY_DIR/bootloader.bin" "$ASSETS_DIR/" -cp "$BINARY_DIR/partitions.bin" "$ASSETS_DIR/" -cp "$BINARY_DIR/firmware.bin" "$ASSETS_DIR/" + mkdir -p "$ASSETS_DIR" + cp "$BINARY_DIR/bootloader.bin" "$ASSETS_DIR/" + cp "$BINARY_DIR/partitions.bin" "$ASSETS_DIR/" + cp "$BINARY_DIR/firmware.bin" "$ASSETS_DIR/" -BOOT_APP0=$(find ~/.platformio/packages/framework-arduinoespressif32 -name "boot_app0.bin" 2>/dev/null | head -1) -if [ -n "$BOOT_APP0" ]; then - cp "$BOOT_APP0" "$ASSETS_DIR/" -else - echo "ERROR: boot_app0.bin not found" - exit 1 -fi + BOOT_APP0=$(find ~/.platformio/packages/framework-arduinoespressif32 -name "boot_app0.bin" 2>/dev/null | head -1) + if [ -n "$BOOT_APP0" ]; then + cp "$BOOT_APP0" "$ASSETS_DIR/" + else + echo "ERROR: boot_app0.bin not found" + exit 1 + fi -echo "Firmware binaries copied to $ASSETS_DIR:" -ls -la "$ASSETS_DIR" \ No newline at end of file + echo "Copied to $ASSETS_DIR:" + ls -la "$ASSETS_DIR" +} + +copy_binaries "$PROJECT_DIR/.pio/build/s3lite-server" "$ASSETS_BASE/server" +copy_binaries "$PROJECT_DIR/.pio/build/s3lite-client" "$ASSETS_BASE/client" \ No newline at end of file diff --git a/version.txt b/version.txt index b579b18..0618236 100644 --- a/version.txt +++ b/version.txt @@ -1,2 +1,2 @@ -server=17 -client=3 +server=20 +client=5