diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml
new file mode 100644
index 0000000..cee8d4a
--- /dev/null
+++ b/.forgejo/workflows/ci.yml
@@ -0,0 +1,55 @@
+name: CI
+
+on:
+ push:
+ branches: [main]
+ pull_request:
+ branches: [main]
+
+jobs:
+ firmware:
+ runs-on: self-hosted
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Install PlatformIO
+ run: pip install platformio
+
+ - name: Build firmware
+ run: pio run
+
+ - name: Copy firmware to Android assets
+ run: bash tools/copy_firmware.sh
+
+ - name: Upload firmware artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: firmware
+ path: |
+ .pio/build/m5stack-atoms3r/firmware.bin
+ .pio/build/m5stack-atoms3r/bootloader.bin
+ .pio/build/m5stack-atoms3r/partitions.bin
+ android/app/src/main/assets/firmware/boot_app0.bin
+
+ android:
+ needs: firmware
+ runs-on: self-hosted
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Download firmware
+ uses: actions/download-artifact@v4
+ with:
+ name: firmware
+
+ - name: Build debug APK
+ working-directory: android
+ run: ./gradlew assembleDebug
+ env:
+ ANDROID_HOME: ${{ vars.ANDROID_HOME || '/opt/android-sdk' }}
+
+ - name: Upload debug APK
+ uses: actions/upload-artifact@v4
+ with:
+ name: app-debug
+ path: android/app/build/outputs/apk/debug/app-debug.apk
diff --git a/.forgejo/workflows/release.yml b/.forgejo/workflows/release.yml
new file mode 100644
index 0000000..bdb4d82
--- /dev/null
+++ b/.forgejo/workflows/release.yml
@@ -0,0 +1,64 @@
+name: Release
+
+on:
+ push:
+ tags:
+ - 'v*'
+ workflow_dispatch:
+
+jobs:
+ build:
+ runs-on: self-hosted
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Install PlatformIO
+ run: pip install platformio
+
+ - name: Build firmware
+ run: pio run
+
+ - name: Copy firmware to Android assets
+ run: bash tools/copy_firmware.sh
+
+ - name: Decode keystore
+ run: echo "${{ secrets.KEYSTORE_B64 }}" | base64 -d > android/keystore/sylda.jks
+ if: env.KEYSTORE_B64 != ''
+
+ - name: Write signing.properties
+ run: |
+ cat > android/signing.properties << 'PROPS'
+ storeFile=keystore/sylda.jks
+ storePassword=${{ secrets.KEYSTORE_PASS }}
+ keyAlias=${{ secrets.KEY_ALIAS }}
+ keyPassword=${{ secrets.KEY_PASS }}
+ PROPS
+
+ - name: Build release APK + AAB
+ working-directory: android
+ run: ./gradlew assembleRelease bundleRelease
+ env:
+ ANDROID_HOME: ${{ vars.ANDROID_HOME || '/opt/android-sdk' }}
+
+ - name: Gather release artifacts
+ run: |
+ mkdir -p release/artifacts
+ cp android/app/build/outputs/apk/release/app-release.apk release/artifacts/
+ cp android/app/build/outputs/bundle/release/app-release.aab release/artifacts/
+ cp android/app/src/main/assets/firmware/*.bin release/artifacts/
+ cd release/artifacts
+ sha256sum * > checksums.txt
+
+ - name: Upload release artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: release
+ path: release/artifacts/*
+
+ - name: Create Forgejo release
+ uses: https://git.eddydevink.nl/api/packages/eddy/actions/forgejo-release@v1
+ with:
+ token: ${{ secrets.FORGEJO_TOKEN }}
+ tag: ${{ github.ref_name }}
+ title: ${{ github.ref_name }}
+ files: release/artifacts/*
diff --git a/.gitignore b/.gitignore
index de6c73b..2cf8684 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,4 +42,5 @@ appstore.md
codereview.md
DC3-24V*.md
DC3-24V*.pdf
-esplibalternatief.md
\ No newline at end of file
+esplibalternatief.md
+release/
diff --git a/AGENTS.md b/AGENTS.md
index dfba093..128ce01 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -19,7 +19,8 @@ ESP32-S3-PICO-1-N8R8 (Atom S3R Voice), 2 relais, 2 touch sensors (JR223B), BLE,
- PlatformIO, `platform = espressif32@6.7.0`, board `esp32-s3-devkitc-1`
- CDC USB serial (`ARDUINO_USB_CDC_ON_BOOT=1`), QIO OPI flash
-- Upload laptop: `pio run -t upload`, port `/dev/ttyACM0`, 115200 baud
+- **Upload:** `pio run -t upload` (via `--no-stub`, OPI flash vereist dit). Poort: **NOOIT `/dev/ttyACM0`** (dat is het Atreus toetsenbord). ESP32 herkennen via `ls /dev/serial/by-id/ | grep -i espressif` en die poort gebruiken. PlatformIO: pas `upload_port` in `platformio.ini` aan naar de gevonden poort.
+- **Direct flashen (handmatig):** `~/.platformio/packages/tool-esptoolpy/esptool.py --no-stub --chip esp32s3 --port /dev/ttyACM1 --baud 115200 --before default_reset --after hard_reset write_flash --flash_mode keep --flash_size keep 0x0 .pio/build/m5stack-atoms3r/bootloader.bin 0x8000 .pio/build/m5stack-atoms3r/partitions.bin 0xE000 ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin 0x10000 .pio/build/m5stack-atoms3r/firmware.bin`
- NVS: namespace "hmac", key "key" (32 bytes HMAC)
- BLE advertising "SylDa_Server", HMAC-verified relay commands
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 3e3b80c..4331f86 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -11,7 +11,7 @@ android {
// compileSdk/targetSdk stays on 34 (Android 14) by deliberate choice. The target audience
// consists of physically disabled users who are very reluctant to update their phones. Staying
// on API 34 maximises device compatibility. Re-evaluate when the user base has migrated.
- compileSdk 36
+ compileSdk 34
if (hasSigningConfig) {
def props = new Properties()
@@ -30,7 +30,7 @@ android {
defaultConfig {
applicationId "nl.eddydevink.sylda"
minSdk 26
- targetSdk 36
+ targetSdk 34
versionCode 1
versionName "1.0"
buildConfigField "String", "BUILD_NUMBER", "\"${new java.text.SimpleDateFormat("yyyyMMddHHmmss").format(new Date())}\""
diff --git a/android/app/src/main/assets/firmware/firmware.bin b/android/app/src/main/assets/firmware/firmware.bin
index 9c849f5..142bde6 100644
Binary files a/android/app/src/main/assets/firmware/firmware.bin and b/android/app/src/main/assets/firmware/firmware.bin differ
diff --git a/android/app/src/main/java/nl/eddydevink/sylda/MainActivity.kt b/android/app/src/main/java/nl/eddydevink/sylda/MainActivity.kt
index 23e4f4e..87cb207 100644
--- a/android/app/src/main/java/nl/eddydevink/sylda/MainActivity.kt
+++ b/android/app/src/main/java/nl/eddydevink/sylda/MainActivity.kt
@@ -23,7 +23,7 @@ class MainActivity : AppCompatActivity(), BleCallbacks {
private const val REQUEST_SETTINGS = 1
private const val POST_SETTINGS_RESCAN_MS = 500L
private const val ON_RESUME_SCAN_DELAY_MS = 300L
- private const val BUNDLED_FIRMWARE_VERSION = "5"
+ private const val BUNDLED_FIRMWARE_VERSION = "6"
}
private lateinit var manager: BleRelayManager
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 10d810d..59ea230 100644
--- a/android/app/src/main/java/nl/eddydevink/sylda/SettingsActivity.kt
+++ b/android/app/src/main/java/nl/eddydevink/sylda/SettingsActivity.kt
@@ -64,7 +64,7 @@ class SettingsActivity : AppCompatActivity() {
private const val REBOOT_WAIT_MS = 5000L
private const val REBOOT_POLL_MS = 500L
private const val REBOOT_MAX_WAIT_MS = 15000L
- private const val EXPECTED_FIRMWARE_VERSION = "5"
+ private const val EXPECTED_FIRMWARE_VERSION = "6"
}
private enum class UsbAction { NONE, EXCHANGE_KEY, FLASH }
diff --git a/android/app/src/main/res/layout/activity_main.xml b/android/app/src/main/res/layout/activity_main.xml
index 730ca59..1219dc9 100644
--- a/android/app/src/main/res/layout/activity_main.xml
+++ b/android/app/src/main/res/layout/activity_main.xml
@@ -2,77 +2,69 @@
-
-
+ android:padding="16dp">
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:text="@string/settings_label"
+ android:textSize="14sp"
+ android:layout_marginEnd="4dp" />
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/app/src/main/res/layout/activity_settings.xml b/android/app/src/main/res/layout/activity_settings.xml
index 7e4321a..abd743c 100644
--- a/android/app/src/main/res/layout/activity_settings.xml
+++ b/android/app/src/main/res/layout/activity_settings.xml
@@ -3,147 +3,138 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
- android:fitsSystemWindows="true">
+ android:padding="24dp">
+
+
+
+
+
+
+
+
+
+
+
+
+
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_marginBottom="16dp">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:hint="@string/hint_label_relay1"
+ android:maxLines="1"
+ android:inputType="text"
+ android:imeOptions="actionDone"
+ android:gravity="center" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/platformio.ini b/platformio.ini
index 4f488bb..11bd9a7 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -14,4 +14,5 @@ build_flags =
lib_deps =
h2zero/NimBLE-Arduino@^2
upload_port = /dev/ttyACM1
-upload_speed = 115200
\ No newline at end of file
+upload_speed = 115200
+upload_flags = --no-stub
\ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
index c8f2568..8062e2e 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -35,7 +35,7 @@
#define NVS_NAMESPACE "hmac"
#define NVS_KEY_NAME "key"
#define NVS_UUID_NAME "uuid"
-#define FIRMWARE_VERSION "5"
+#define FIRMWARE_VERSION "6"
NimBLECharacteristic *pCharacteristic;
bool deviceConnected = false;
@@ -338,8 +338,8 @@ void setup() {
}
Serial.println("LED blink done, starting BLE...");
- NimBLEDevice::setMTU(512);
NimBLEDevice::init("SylDa_Server");
+ NimBLEDevice::setMTU(248);
NimBLEServer *pServer = NimBLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());