Fix BLE scan + touch logic + UUID + version read
- Client: change passive BLE scan to active scan (setActiveScan(true)) Server puts name/UUID in scan response; passive scan never received them, so isAdvertisingService() and getName() failed. - Server: add INPUT_PULLUP on touch pins to prevent floating triggers when sensors disconnected - Server: update BLE UUID characteristic in SET_ID handler (pUuidChar->setValue) so reconnecting clients see correct UUID - Server: touch logic changed from t1Active/t2Active to !t1Active/!t2Active (door closed = relay ON) - Android: flushReadBuffer before VERSION? to discard stale boot log output; use Regex for BUILD_NR parsing - copy_firmware.sh: copy to firmware/server/ and firmware/client/ subdirectories to match EspFlasher.assetPath() - version.txt: server=20 client=5
This commit is contained in:
parent
6a07505d02
commit
cd2d949f87
7 changed files with 64 additions and 31 deletions
Binary file not shown.
Binary file not shown.
|
|
@ -440,6 +440,8 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
showProgressDialog(getString(R.string.title_firmware_flash), getString(R.string.msg_checking_version), STYLE_SPINNER)
|
showProgressDialog(getString(R.string.title_firmware_flash), getString(R.string.msg_checking_version), STYLE_SPINNER)
|
||||||
|
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
|
val expected = getExpectedFirmwareVersion()
|
||||||
|
Log.d(TAG, "doFlashing: expected firmware version=$expected, expectingReboot=$expectingReboot")
|
||||||
val version = readEspVersion(usbManager, device)
|
val version = readEspVersion(usbManager, device)
|
||||||
if (version == getExpectedFirmwareVersion() && !expectingReboot) {
|
if (version == getExpectedFirmwareVersion() && !expectingReboot) {
|
||||||
Log.d(TAG, "Firmware version $version matches, up to date")
|
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? {
|
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
|
val connection = usbManager.openDevice(device) ?: return null
|
||||||
if (!connection.claimInterface(intf, true)) { connection.close(); return null }
|
if (!connection.claimInterface(intf, true)) { connection.close(); return null }
|
||||||
|
|
||||||
|
|
@ -595,12 +607,18 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
return try {
|
return try {
|
||||||
setupCdcControl(connection, device)
|
setupCdcControl(connection, device)
|
||||||
Thread.sleep(KEY_SETTLE_MS)
|
Thread.sleep(KEY_SETTLE_MS)
|
||||||
|
|
||||||
|
flushReadBuffer(connection, epIn)
|
||||||
|
|
||||||
val cmd = "VERSION?\n".toByteArray(StandardCharsets.US_ASCII)
|
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)
|
Thread.sleep(RESPONSE_WAIT_MS)
|
||||||
val response = readResponse(connection, epIn, VERSION_TIMEOUT_MS)
|
val response = readResponse(connection, epIn, VERSION_TIMEOUT_MS)
|
||||||
val versionLine = response.lines().firstOrNull { it.startsWith("BUILD_NR:") }
|
Log.d(TAG, "readEspVersion: raw response='${response.replace("\r", "\\r").replace("\n", "\\n")}' (len=${response.length})")
|
||||||
versionLine?.removePrefix("BUILD_NR:")?.trim()
|
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 {
|
} finally {
|
||||||
connection.close()
|
connection.close()
|
||||||
}
|
}
|
||||||
|
|
@ -753,16 +771,20 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
val sb = StringBuilder()
|
val sb = StringBuilder()
|
||||||
val startTime = System.currentTimeMillis()
|
val startTime = System.currentTimeMillis()
|
||||||
|
|
||||||
|
var reads = 0
|
||||||
while (System.currentTimeMillis() - startTime < timeoutMs) {
|
while (System.currentTimeMillis() - startTime < timeoutMs) {
|
||||||
val len = connection.bulkTransfer(epIn, buf, buf.size, READ_CHUNK_TIMEOUT_MS)
|
val len = connection.bulkTransfer(epIn, buf, buf.size, READ_CHUNK_TIMEOUT_MS)
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
|
reads++
|
||||||
sb.append(String(buf, 0, len, StandardCharsets.US_ASCII))
|
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")) {
|
if ((sb.contains("HMAC_KEY:") || sb.contains("NO_KEY") || sb.contains("OK") || sb.contains("ERROR")) && sb.contains("\n")) {
|
||||||
break
|
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()
|
return sb.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ class MyScanCallbacks : public NimBLEScanCallbacks {
|
||||||
serverAddress = advertisedDevice->getAddress();
|
serverAddress = advertisedDevice->getAddress();
|
||||||
serverFound = true;
|
serverFound = true;
|
||||||
NimBLEDevice::getScan()->stop();
|
NimBLEDevice::getScan()->stop();
|
||||||
|
ESP_LOGI(TAG, "Found server: %s", advertisedDevice->getAddress().toString().c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -220,8 +221,8 @@ void setup() {
|
||||||
|
|
||||||
allProvisioned = keyProvisioned && uuidProvisioned && serverProvisioned;
|
allProvisioned = keyProvisioned && uuidProvisioned && serverProvisioned;
|
||||||
|
|
||||||
pinMode(TOUCH1_PIN, INPUT);
|
pinMode(TOUCH1_PIN, INPUT_PULLUP);
|
||||||
pinMode(TOUCH2_PIN, INPUT);
|
pinMode(TOUCH2_PIN, INPUT_PULLUP);
|
||||||
pinMode(BUTTON_PIN, INPUT);
|
pinMode(BUTTON_PIN, INPUT);
|
||||||
|
|
||||||
if (allProvisioned) {
|
if (allProvisioned) {
|
||||||
|
|
@ -231,7 +232,7 @@ void setup() {
|
||||||
pScan->setScanCallbacks(new MyScanCallbacks());
|
pScan->setScanCallbacks(new MyScanCallbacks());
|
||||||
pScan->setInterval(97);
|
pScan->setInterval(97);
|
||||||
pScan->setWindow(37);
|
pScan->setWindow(37);
|
||||||
pScan->setActiveScan(false);
|
pScan->setActiveScan(true);
|
||||||
pScan->setMaxResults(0);
|
pScan->setMaxResults(0);
|
||||||
bleReady = true;
|
bleReady = true;
|
||||||
ESP_LOGI(TAG, "BLE: initialized, scanning for service UUID");
|
ESP_LOGI(TAG, "BLE: initialized, scanning for service UUID");
|
||||||
|
|
@ -286,7 +287,7 @@ void loop() {
|
||||||
pScan->setScanCallbacks(new MyScanCallbacks());
|
pScan->setScanCallbacks(new MyScanCallbacks());
|
||||||
pScan->setInterval(97);
|
pScan->setInterval(97);
|
||||||
pScan->setWindow(37);
|
pScan->setWindow(37);
|
||||||
pScan->setActiveScan(false);
|
pScan->setActiveScan(true);
|
||||||
pScan->setMaxResults(0);
|
pScan->setMaxResults(0);
|
||||||
bleReady = true;
|
bleReady = true;
|
||||||
ESP_LOGI(TAG, "BLE: initialized after key provisioning");
|
ESP_LOGI(TAG, "BLE: initialized after key provisioning");
|
||||||
|
|
@ -329,7 +330,7 @@ void loop() {
|
||||||
pScan->setScanCallbacks(new MyScanCallbacks());
|
pScan->setScanCallbacks(new MyScanCallbacks());
|
||||||
pScan->setInterval(97);
|
pScan->setInterval(97);
|
||||||
pScan->setWindow(37);
|
pScan->setWindow(37);
|
||||||
pScan->setActiveScan(false);
|
pScan->setActiveScan(true);
|
||||||
pScan->setMaxResults(0);
|
pScan->setMaxResults(0);
|
||||||
bleReady = true;
|
bleReady = true;
|
||||||
ESP_LOGI(TAG, "BLE: initialized after server provisioning");
|
ESP_LOGI(TAG, "BLE: initialized after server provisioning");
|
||||||
|
|
|
||||||
13
src/main.cpp
13
src/main.cpp
|
|
@ -48,6 +48,7 @@ CRGB leds[NUM_LEDS];
|
||||||
#define FIRMWARE_VERSION FIRMWARE_VERSION_SERVER
|
#define FIRMWARE_VERSION FIRMWARE_VERSION_SERVER
|
||||||
|
|
||||||
NimBLECharacteristic *pCharacteristic;
|
NimBLECharacteristic *pCharacteristic;
|
||||||
|
NimBLECharacteristic *pUuidChar;
|
||||||
bool relay1State = false;
|
bool relay1State = false;
|
||||||
bool relay2State = false;
|
bool relay2State = false;
|
||||||
|
|
||||||
|
|
@ -401,8 +402,8 @@ void setup() {
|
||||||
ESP_LOGD(TAG, "Generated new UUID");
|
ESP_LOGD(TAG, "Generated new UUID");
|
||||||
}
|
}
|
||||||
|
|
||||||
pinMode(TOUCH1_PIN, INPUT);
|
pinMode(TOUCH1_PIN, INPUT_PULLUP);
|
||||||
pinMode(TOUCH2_PIN, INPUT);
|
pinMode(TOUCH2_PIN, INPUT_PULLUP);
|
||||||
pinMode(BUTTON_PIN, INPUT);
|
pinMode(BUTTON_PIN, INPUT);
|
||||||
pinMode(RELAY1_PIN, OUTPUT);
|
pinMode(RELAY1_PIN, OUTPUT);
|
||||||
pinMode(RELAY2_PIN, OUTPUT);
|
pinMode(RELAY2_PIN, OUTPUT);
|
||||||
|
|
@ -424,7 +425,7 @@ void setup() {
|
||||||
);
|
);
|
||||||
pCharacteristic->setCallbacks(new MyCharacteristicCallbacks());
|
pCharacteristic->setCallbacks(new MyCharacteristicCallbacks());
|
||||||
|
|
||||||
NimBLECharacteristic *pUuidChar = pService->createCharacteristic(
|
pUuidChar = pService->createCharacteristic(
|
||||||
UUID_CHAR_UUID,
|
UUID_CHAR_UUID,
|
||||||
NIMBLE_PROPERTY::READ
|
NIMBLE_PROPERTY::READ
|
||||||
);
|
);
|
||||||
|
|
@ -488,6 +489,7 @@ void loop() {
|
||||||
} else if (serialBuf == "ID?") {
|
} else if (serialBuf == "ID?") {
|
||||||
Serial.println("SylDa_Server");
|
Serial.println("SylDa_Server");
|
||||||
} else if (serialBuf == "VERSION?") {
|
} else if (serialBuf == "VERSION?") {
|
||||||
|
Serial.flush();
|
||||||
Serial.print("BUILD_NR:");
|
Serial.print("BUILD_NR:");
|
||||||
Serial.println(FIRMWARE_VERSION);
|
Serial.println(FIRMWARE_VERSION);
|
||||||
} else if (serialBuf.startsWith("SET_KEY:")) {
|
} else if (serialBuf.startsWith("SET_KEY:")) {
|
||||||
|
|
@ -515,6 +517,7 @@ void loop() {
|
||||||
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;
|
||||||
|
pUuidChar->setValue(deviceUuid, ESP_UUID_LEN);
|
||||||
Serial.println("OK");
|
Serial.println("OK");
|
||||||
Serial.println("UUID stored in NVS");
|
Serial.println("UUID stored in NVS");
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -585,9 +588,9 @@ void loop() {
|
||||||
bool btnActive = (millis() - btnChange > DEBOUNCE_MS) && btnStable;
|
bool btnActive = (millis() - btnChange > DEBOUNCE_MS) && btnStable;
|
||||||
|
|
||||||
if (!otaInProgress) {
|
if (!otaInProgress) {
|
||||||
relay1State = t1Active || btnActive ||
|
relay1State = !t1Active || btnActive ||
|
||||||
(connActive[0] && bleRelay1[0]) || (connActive[1] && bleRelay1[1]);
|
(connActive[0] && bleRelay1[0]) || (connActive[1] && bleRelay1[1]);
|
||||||
relay2State = t2Active ||
|
relay2State = !t2Active ||
|
||||||
(connActive[0] && bleRelay2[0]) || (connActive[1] && bleRelay2[1]);
|
(connActive[0] && bleRelay2[0]) || (connActive[1] && bleRelay2[1]);
|
||||||
} else {
|
} else {
|
||||||
relay1State = false;
|
relay1State = false;
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,29 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
BINARY_DIR="$(cd "$(dirname "$0")/.." && pwd)/.pio/build/s3lite-server"
|
PROJECT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
ASSETS_DIR="$(cd "$(dirname "$0")/.." && pwd)/android/app/src/main/assets/firmware"
|
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/"
|
mkdir -p "$ASSETS_DIR"
|
||||||
cp "$BINARY_DIR/partitions.bin" "$ASSETS_DIR/"
|
cp "$BINARY_DIR/bootloader.bin" "$ASSETS_DIR/"
|
||||||
cp "$BINARY_DIR/firmware.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)
|
BOOT_APP0=$(find ~/.platformio/packages/framework-arduinoespressif32 -name "boot_app0.bin" 2>/dev/null | head -1)
|
||||||
if [ -n "$BOOT_APP0" ]; then
|
if [ -n "$BOOT_APP0" ]; then
|
||||||
cp "$BOOT_APP0" "$ASSETS_DIR/"
|
cp "$BOOT_APP0" "$ASSETS_DIR/"
|
||||||
else
|
else
|
||||||
echo "ERROR: boot_app0.bin not found"
|
echo "ERROR: boot_app0.bin not found"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Firmware binaries copied to $ASSETS_DIR:"
|
echo "Copied to $ASSETS_DIR:"
|
||||||
ls -la "$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"
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
server=17
|
server=20
|
||||||
client=3
|
client=5
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue