Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c022b8259 | ||
|
|
d6d6f6674a |
17 changed files with 135 additions and 79 deletions
|
|
@ -4,14 +4,14 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace 'com.eddy.atomrelay'
|
namespace 'nl.eddydevink.sylda'
|
||||||
// compileSdk/targetSdk stays on 34 (Android 14) by deliberate choice. The target audience
|
// 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
|
// 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.
|
// on API 34 maximises device compatibility. Re-evaluate when the user base has migrated.
|
||||||
compileSdk 34
|
compileSdk 34
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.eddy.atomrelay"
|
applicationId "nl.eddydevink.sylda"
|
||||||
minSdk 26
|
minSdk 26
|
||||||
targetSdk 34
|
targetSdk 34
|
||||||
versionCode 1
|
versionCode 1
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="false"
|
android:allowBackup="false"
|
||||||
android:label="Atom Relay"
|
android:label="@string/app_name"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/AppTheme">
|
android:theme="@style/AppTheme">
|
||||||
|
|
||||||
|
|
@ -30,6 +30,15 @@
|
||||||
<activity
|
<activity
|
||||||
android:name=".SettingsActivity"
|
android:name=".SettingsActivity"
|
||||||
android:label="Instellingen"
|
android:label="Instellingen"
|
||||||
android:parentActivityName=".MainActivity"/>
|
android:parentActivityName=".MainActivity"
|
||||||
|
android:launchMode="singleTop"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
|
||||||
|
</intent-filter>
|
||||||
|
<meta-data
|
||||||
|
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
|
||||||
|
android:resource="@xml/device_filter" />
|
||||||
|
</activity>
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
Binary file not shown.
|
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
package com.eddy.atomrelay
|
package nl.eddydevink.sylda
|
||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
package com.eddy.atomrelay
|
package nl.eddydevink.sylda
|
||||||
|
|
||||||
enum class BleStatus {
|
enum class BleStatus {
|
||||||
Scanning,
|
Scanning,
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
package com.eddy.atomrelay
|
package nl.eddydevink.sylda
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.hardware.usb.UsbConstants
|
import android.hardware.usb.UsbConstants
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
package com.eddy.atomrelay
|
package nl.eddydevink.sylda
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
package com.eddy.atomrelay
|
package nl.eddydevink.sylda
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
package com.eddy.atomrelay
|
package nl.eddydevink.sylda
|
||||||
|
|
||||||
import android.app.AlertDialog
|
import android.app.AlertDialog
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
|
|
@ -52,7 +52,7 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
private const val FLUSH_TIMEOUT_MS = 100
|
private const val FLUSH_TIMEOUT_MS = 100
|
||||||
private const val READ_CHUNK_TIMEOUT_MS = 500
|
private const val READ_CHUNK_TIMEOUT_MS = 500
|
||||||
private const val CDC_CONTROL_TIMEOUT_MS = 500
|
private const val CDC_CONTROL_TIMEOUT_MS = 500
|
||||||
private const val ACTION_USB_PERMISSION = "com.eddy.atomrelay.USB_PERMISSION"
|
private const val ACTION_USB_PERMISSION = "nl.eddydevink.sylda.USB_PERMISSION"
|
||||||
private const val STYLE_SPINNER = 0
|
private const val STYLE_SPINNER = 0
|
||||||
private const val STYLE_HORIZONTAL = 1
|
private const val STYLE_HORIZONTAL = 1
|
||||||
private const val USB_READ_BUF_SIZE = 512
|
private const val USB_READ_BUF_SIZE = 512
|
||||||
|
|
@ -60,11 +60,17 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
private const val UUID_HEX_LEN = 32
|
private const val UUID_HEX_LEN = 32
|
||||||
private const val UUID_BYTE_COUNT = 16
|
private const val UUID_BYTE_COUNT = 16
|
||||||
private const val HMAC_BYTE_COUNT = 32
|
private const val HMAC_BYTE_COUNT = 32
|
||||||
|
private const val VERSION_TIMEOUT_MS = 3000L
|
||||||
|
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 = "1"
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum class UsbAction { NONE, EXCHANGE_KEY, FLASH }
|
private enum class UsbAction { NONE, EXCHANGE_KEY, FLASH }
|
||||||
|
|
||||||
private var currentAction = UsbAction.NONE
|
private var currentAction = UsbAction.NONE
|
||||||
|
private var expectingReboot = false
|
||||||
private var progressDialog: AlertDialog? = null
|
private var progressDialog: AlertDialog? = null
|
||||||
private var dialog: AlertDialog? = null
|
private var dialog: AlertDialog? = null
|
||||||
private var flasherJob: Job? = null
|
private var flasherJob: Job? = null
|
||||||
|
|
@ -109,6 +115,7 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
if (intent.action == UsbManager.ACTION_USB_DEVICE_DETACHED) {
|
if (intent.action == UsbManager.ACTION_USB_DEVICE_DETACHED) {
|
||||||
val device = intent.getParcelableExtra<UsbDevice>(UsbManager.EXTRA_DEVICE)
|
val device = intent.getParcelableExtra<UsbDevice>(UsbManager.EXTRA_DEVICE)
|
||||||
if (device?.vendorId == ESP_VENDOR_ID) {
|
if (device?.vendorId == ESP_VENDOR_ID) {
|
||||||
|
if (expectingReboot) return
|
||||||
if (dialog != null && currentAction == UsbAction.NONE) {
|
if (dialog != null && currentAction == UsbAction.NONE) {
|
||||||
dialog?.dismiss()
|
dialog?.dismiss()
|
||||||
dialog = null
|
dialog = null
|
||||||
|
|
@ -129,16 +136,10 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
supportActionBar?.title = getString(R.string.title_settings)
|
supportActionBar?.title = getString(R.string.title_settings)
|
||||||
|
|
||||||
findViewById<Button>(R.id.exchangeKeyButton).setOnClickListener {
|
|
||||||
startKeyExchange()
|
|
||||||
}
|
|
||||||
|
|
||||||
findViewById<Button>(R.id.flashFirmwareButton).setOnClickListener {
|
findViewById<Button>(R.id.flashFirmwareButton).setOnClickListener {
|
||||||
startFlashing()
|
startFlashing()
|
||||||
}
|
}
|
||||||
|
|
||||||
findViewById<TextView>(R.id.buildNumber).text = getString(R.string.build_number, BuildConfig.BUILD_NUMBER)
|
|
||||||
|
|
||||||
registerReceiver(usbAttachedReceiver, IntentFilter(UsbManager.ACTION_USB_DEVICE_ATTACHED), Context.RECEIVER_EXPORTED)
|
registerReceiver(usbAttachedReceiver, IntentFilter(UsbManager.ACTION_USB_DEVICE_ATTACHED), Context.RECEIVER_EXPORTED)
|
||||||
registerReceiver(usbPermissionReceiver, IntentFilter(ACTION_USB_PERMISSION), Context.RECEIVER_NOT_EXPORTED)
|
registerReceiver(usbPermissionReceiver, IntentFilter(ACTION_USB_PERMISSION), Context.RECEIVER_NOT_EXPORTED)
|
||||||
registerReceiver(usbDetachedReceiver, IntentFilter(UsbManager.ACTION_USB_DEVICE_DETACHED), Context.RECEIVER_EXPORTED)
|
registerReceiver(usbDetachedReceiver, IntentFilter(UsbManager.ACTION_USB_DEVICE_DETACHED), Context.RECEIVER_EXPORTED)
|
||||||
|
|
@ -147,6 +148,13 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
setupLabelEditTexts()
|
setupLabelEditTexts()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onNewIntent(intent: Intent) {
|
||||||
|
super.onNewIntent(intent)
|
||||||
|
if (intent.action == UsbManager.ACTION_USB_DEVICE_ATTACHED && currentAction == UsbAction.NONE) {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
val current = PrefsHelper.getPrefs(this).getString(PrefsHelper.PREF_THEME, "system") ?: "system"
|
val current = PrefsHelper.getPrefs(this).getString(PrefsHelper.PREF_THEME, "system") ?: "system"
|
||||||
|
|
@ -274,7 +282,6 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
.putString(PrefsHelper.PREF_UUID, result.deviceUuid)
|
.putString(PrefsHelper.PREF_UUID, result.deviceUuid)
|
||||||
.putString(PrefsHelper.PREF_KEY, result.hexKey)
|
.putString(PrefsHelper.PREF_KEY, result.hexKey)
|
||||||
.apply()
|
.apply()
|
||||||
Toast.makeText(this@SettingsActivity, getString(R.string.key_read_success), Toast.LENGTH_LONG).show()
|
|
||||||
cleanupAction()
|
cleanupAction()
|
||||||
setResult(RESULT_SCAN)
|
setResult(RESULT_SCAN)
|
||||||
finish()
|
finish()
|
||||||
|
|
@ -319,6 +326,26 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun doFlashing(usbManager: UsbManager, device: UsbDevice) {
|
private fun doFlashing(usbManager: UsbManager, device: UsbDevice) {
|
||||||
|
showProgressDialog(getString(R.string.title_firmware_flash), getString(R.string.msg_checking_version), STYLE_SPINNER)
|
||||||
|
|
||||||
|
lifecycleScope.launch {
|
||||||
|
val version = readEspVersion(usbManager, device)
|
||||||
|
if (version == EXPECTED_FIRMWARE_VERSION && !expectingReboot) {
|
||||||
|
Log.d(TAG, "Firmware version $version matches, skipping flash")
|
||||||
|
progressDialog?.dismiss()
|
||||||
|
progressDialog = null
|
||||||
|
currentAction = UsbAction.EXCHANGE_KEY
|
||||||
|
doKeyExchange(usbManager, device)
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
Log.d(TAG, "Firmware version ${version ?: "none"}, flashing")
|
||||||
|
progressDialog?.dismiss()
|
||||||
|
progressDialog = null
|
||||||
|
doFlashInner(usbManager, device)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doFlashInner(usbManager: UsbManager, device: UsbDevice) {
|
||||||
dialog?.dismiss()
|
dialog?.dismiss()
|
||||||
dialog = null
|
dialog = null
|
||||||
showProgressDialog(getString(R.string.title_firmware_flash), getString(R.string.msg_initializing), STYLE_HORIZONTAL)
|
showProgressDialog(getString(R.string.title_firmware_flash), getString(R.string.msg_initializing), STYLE_HORIZONTAL)
|
||||||
|
|
@ -337,19 +364,14 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
try {
|
try {
|
||||||
flasher.flashDevice(usbManager, device, progressCallback)
|
flasher.flashDevice(usbManager, device, progressCallback)
|
||||||
if (isFinishing || isDestroyed) return@launch
|
if (isFinishing || isDestroyed) return@launch
|
||||||
currentAction = UsbAction.NONE
|
expectingReboot = true
|
||||||
|
currentAction = UsbAction.EXCHANGE_KEY
|
||||||
progressDialog?.dismiss()
|
progressDialog?.dismiss()
|
||||||
progressDialog = null
|
progressDialog = null
|
||||||
dialog = AlertDialog.Builder(this@SettingsActivity)
|
showWaitingDialog(
|
||||||
.setTitle(getString(R.string.title_firmware_flash))
|
getString(R.string.title_firmware_flash),
|
||||||
.setMessage(getString(R.string.msg_flash_complete))
|
getString(R.string.msg_env_waiting_reboot)
|
||||||
.setPositiveButton(getString(R.string.button_close)) { d, _ ->
|
)
|
||||||
d.dismiss()
|
|
||||||
dialog = null
|
|
||||||
}
|
|
||||||
.setCancelable(true)
|
|
||||||
.setOnCancelListener { dialog = null }
|
|
||||||
.show()
|
|
||||||
} catch (e: kotlinx.coroutines.CancellationException) {
|
} catch (e: kotlinx.coroutines.CancellationException) {
|
||||||
cleanupAction()
|
cleanupAction()
|
||||||
throw e
|
throw e
|
||||||
|
|
@ -412,6 +434,7 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
|
|
||||||
private fun cleanupAction() {
|
private fun cleanupAction() {
|
||||||
currentAction = UsbAction.NONE
|
currentAction = UsbAction.NONE
|
||||||
|
expectingReboot = false
|
||||||
dialog?.dismiss()
|
dialog?.dismiss()
|
||||||
dialog = null
|
dialog = null
|
||||||
progressDialog?.dismiss()
|
progressDialog?.dismiss()
|
||||||
|
|
@ -440,6 +463,30 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
data class Error(val resId: Int, val arg: String? = null) : KeyResult()
|
data class Error(val resId: Int, val arg: String? = null) : KeyResult()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun readEspVersion(usbManager: UsbManager, device: UsbDevice): String? {
|
||||||
|
val intf = UsbUtils.findCdcDataInterface(device) ?: return null
|
||||||
|
val connection = usbManager.openDevice(device) ?: return null
|
||||||
|
if (!connection.claimInterface(intf, true)) { connection.close(); return null }
|
||||||
|
|
||||||
|
val epOut = UsbUtils.findBulkEndpoint(intf, UsbConstants.USB_DIR_OUT)
|
||||||
|
?: run { connection.close(); return null }
|
||||||
|
val epIn = UsbUtils.findBulkEndpoint(intf, UsbConstants.USB_DIR_IN)
|
||||||
|
?: run { connection.close(); return null }
|
||||||
|
|
||||||
|
return try {
|
||||||
|
setupCdcControl(connection, device)
|
||||||
|
Thread.sleep(KEY_SETTLE_MS)
|
||||||
|
val cmd = "VERSION?\n".toByteArray(StandardCharsets.US_ASCII)
|
||||||
|
connection.bulkTransfer(epOut, cmd, cmd.size, USB_BULK_TIMEOUT_MS)
|
||||||
|
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()
|
||||||
|
} finally {
|
||||||
|
connection.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun readKeyFromEsp(usbManager: UsbManager, device: UsbDevice, appUuid: String?, appKey: String?): KeyResult? {
|
private fun readKeyFromEsp(usbManager: UsbManager, device: UsbDevice, appUuid: String?, appKey: String?): KeyResult? {
|
||||||
val intf = UsbUtils.findCdcDataInterface(device)
|
val intf = UsbUtils.findCdcDataInterface(device)
|
||||||
?: return KeyResult.Error(R.string.err_no_cdc)
|
?: return KeyResult.Error(R.string.err_no_cdc)
|
||||||
|
|
@ -643,7 +690,6 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
.putString(PrefsHelper.PREF_UUID, espUuid)
|
.putString(PrefsHelper.PREF_UUID, espUuid)
|
||||||
.putString(PrefsHelper.PREF_KEY, espKey)
|
.putString(PrefsHelper.PREF_KEY, espKey)
|
||||||
.apply()
|
.apply()
|
||||||
Toast.makeText(this, getString(R.string.key_read_success), Toast.LENGTH_LONG).show()
|
|
||||||
cleanupAction()
|
cleanupAction()
|
||||||
setResult(RESULT_SCAN)
|
setResult(RESULT_SCAN)
|
||||||
finish()
|
finish()
|
||||||
|
|
@ -692,7 +738,6 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
progressDialog = null
|
progressDialog = null
|
||||||
when (result) {
|
when (result) {
|
||||||
is KeyResult.Success -> {
|
is KeyResult.Success -> {
|
||||||
Toast.makeText(this@SettingsActivity, getString(R.string.key_read_success), Toast.LENGTH_LONG).show()
|
|
||||||
cleanupAction()
|
cleanupAction()
|
||||||
setResult(RESULT_SCAN)
|
setResult(RESULT_SCAN)
|
||||||
finish()
|
finish()
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
package com.eddy.atomrelay
|
package nl.eddydevink.sylda
|
||||||
|
|
||||||
import android.hardware.usb.UsbConstants
|
import android.hardware.usb.UsbConstants
|
||||||
import android.hardware.usb.UsbDeviceConnection
|
import android.hardware.usb.UsbDeviceConnection
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
package com.eddy.atomrelay
|
package nl.eddydevink.sylda
|
||||||
|
|
||||||
import android.hardware.usb.UsbConstants
|
import android.hardware.usb.UsbConstants
|
||||||
import android.hardware.usb.UsbDevice
|
import android.hardware.usb.UsbDevice
|
||||||
|
|
@ -4,14 +4,28 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:padding="16dp">
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="end|top"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/settings_label"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:layout_marginEnd="4dp" />
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/settingsButton"
|
android:id="@+id/settingsButton"
|
||||||
android:layout_width="48dp"
|
android:layout_width="40dp"
|
||||||
android:layout_height="48dp"
|
android:layout_height="40dp"
|
||||||
android:layout_gravity="end|top"
|
|
||||||
android:src="@drawable/ic_settings"
|
android:src="@drawable/ic_settings"
|
||||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
android:background="?android:attr/selectableItemBackgroundBorderless"
|
||||||
android:contentDescription="@string/cd_settings" />
|
android:contentDescription="@string/cd_settings" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
||||||
|
|
@ -12,19 +12,6 @@
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:layout_marginBottom="24dp" />
|
android:layout_marginBottom="24dp" />
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/exchangeKeyButton"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/button_key_exchange" />
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="1dp"
|
|
||||||
android:background="?android:attr/listDivider"
|
|
||||||
android:layout_marginTop="24dp"
|
|
||||||
android:layout_marginBottom="24dp" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
@ -139,12 +126,4 @@
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_weight="1" />
|
android:layout_weight="1" />
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/buildNumber"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textSize="12sp"
|
|
||||||
android:textColor="?android:attr/textColorSecondary"
|
|
||||||
android:gravity="center" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,35 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">Atom Relay</string>
|
<string name="app_name">Sylda</string>
|
||||||
<string name="settings">Instellingen</string>
|
<string name="settings">Instellingen</string>
|
||||||
|
|
||||||
<!-- MainActivity status -->
|
<!-- MainActivity status -->
|
||||||
<string name="status_default">Disconnected</string>
|
<string name="status_default">Niet verbonden</string>
|
||||||
<string name="status_discovering_services">Verbonden, services zoeken…</string>
|
<string name="status_discovering_services">Verbonden, services zoeken…</string>
|
||||||
<string name="status_connecting">Verbinden…</string>
|
<string name="status_connecting">Verbinden…</string>
|
||||||
<string name="status_connected">Connected</string>
|
<string name="status_connected">Verbonden</string>
|
||||||
<string name="status_service_error">Servicefout</string>
|
<string name="status_service_error">Servicefout</string>
|
||||||
<string name="status_service_not_found">Service not found</string>
|
<string name="status_service_not_found">Service niet gevonden</string>
|
||||||
<string name="status_comm_error">Communicatiefout</string>
|
<string name="status_comm_error">Communicatiefout</string>
|
||||||
<string name="status_no_key">Geen HMAC sleutel - open Instellingen</string>
|
<string name="status_no_key">Geen sleutel — open Instellingen</string>
|
||||||
<string name="status_permissions_denied">Tik hier om Bluetooth-toegang in te stellen</string>
|
<string name="status_permissions_denied">Tik hier om Bluetooth-toegang in te stellen</string>
|
||||||
<string name="status_bluetooth_disabled">Bluetooth not enabled</string>
|
<string name="status_bluetooth_disabled">Bluetooth uitgeschakeld</string>
|
||||||
<string name="status_scanning">Scanning…</string>
|
<string name="status_wrong_device">Verkeerd apparaat — opnieuw zoeken…</string>
|
||||||
<string name="status_device_not_found">Device not found</string>
|
<string name="status_scanning">Zoeken…</string>
|
||||||
<string name="status_wrong_device">Verkeerd apparaat — opnieuw scannen…</string>
|
<string name="status_device_not_found">Apparaat niet gevonden</string>
|
||||||
<string name="button_retry_scan">Opnieuw scannen</string>
|
<string name="button_retry_scan">Opnieuw zoeken</string>
|
||||||
|
|
||||||
<!-- MainActivity UI -->
|
<!-- MainActivity UI -->
|
||||||
<string name="cd_settings">Instellingen</string>
|
<string name="cd_settings">Instellingen</string>
|
||||||
<string name="button_on">ON</string>
|
<string name="settings_label">instellingen</string>
|
||||||
<string name="button_hold">HOLD</string>
|
<string name="button_on">AAN</string>
|
||||||
|
<string name="button_hold">VAST</string>
|
||||||
|
|
||||||
<!-- SettingsActivity -->
|
<!-- SettingsActivity -->
|
||||||
<string name="title_settings">Instellingen</string>
|
<string name="title_settings">Instellingen</string>
|
||||||
<string name="msg_settings_intro">Sluit de ESP aan op USB en kies een actie.</string>
|
<string name="msg_settings_intro">Sluit de ESP aan op USB en kies een actie.</string>
|
||||||
<string name="button_key_exchange">Sleutel Uitwisselen</string>
|
<string name="msg_flash_mode_help">Sluit de module aan op de USB-poort.</string>
|
||||||
<string name="msg_flash_mode_help">Sluit de ESP aan via USB. De app reset de ESP automatisch naar download-modus.</string>
|
<string name="button_firmware_flash">Firmware bijwerken</string>
|
||||||
<string name="button_firmware_flash">Firmware Flashen</string>
|
|
||||||
<string name="build_number">Buildnummer: %s</string>
|
|
||||||
<string name="usb_access_denied">USB-toegang geweigerd</string>
|
<string name="usb_access_denied">USB-toegang geweigerd</string>
|
||||||
<string name="key_read_success">Beveiligingssleutel gelezen</string>
|
<string name="key_read_success">Beveiligingssleutel gelezen</string>
|
||||||
<string name="key_exchange_failed">Sleutel uitwisselen mislukt - probeer opnieuw</string>
|
<string name="key_exchange_failed">Sleutel uitwisselen mislukt - probeer opnieuw</string>
|
||||||
|
|
@ -57,7 +56,9 @@
|
||||||
<string name="msg_reading_key">Sleutel uitlezen…</string>
|
<string name="msg_reading_key">Sleutel uitlezen…</string>
|
||||||
<string name="msg_flash_download_mode">Sluit de ESP aan via USB om te flashen.</string>
|
<string name="msg_flash_download_mode">Sluit de ESP aan via USB om te flashen.</string>
|
||||||
<string name="msg_initializing">Initialiseren…</string>
|
<string name="msg_initializing">Initialiseren…</string>
|
||||||
<string name="msg_flash_complete">Firmware geflashed!\n\nDe ESP herstart automatisch. Sleutels blijven behouden in NVS.</string>
|
<string name="msg_checking_version">Firmware versie controleren…</string>
|
||||||
|
<string name="msg_env_waiting_reboot">Wachten op ESP herstart…</string>
|
||||||
|
<string name="msg_flash_complete">Firmware geflashed!\n\nSleutels worden nu uitgelezen…</string>
|
||||||
<string name="button_close">Sluiten</string>
|
<string name="button_close">Sluiten</string>
|
||||||
<string name="button_cancel">Annuleren</string>
|
<string name="button_cancel">Annuleren</string>
|
||||||
|
|
||||||
|
|
|
||||||
4
android/app/src/main/res/xml/device_filter.xml
Normal file
4
android/app/src/main/res/xml/device_filter.xml
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<usb-device vendor-id="12346" product-id="4097" />
|
||||||
|
</resources>
|
||||||
|
|
@ -13,5 +13,5 @@ build_flags =
|
||||||
-DCONFIG_BT_NIMBLE_ENABLED
|
-DCONFIG_BT_NIMBLE_ENABLED
|
||||||
lib_deps =
|
lib_deps =
|
||||||
h2zero/NimBLE-Arduino@^2
|
h2zero/NimBLE-Arduino@^2
|
||||||
upload_port = /dev/ttyACM0
|
upload_port = /dev/ttyACM1
|
||||||
upload_speed = 115200
|
upload_speed = 115200
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
#define NVS_NAMESPACE "hmac"
|
#define NVS_NAMESPACE "hmac"
|
||||||
#define NVS_KEY_NAME "key"
|
#define NVS_KEY_NAME "key"
|
||||||
#define NVS_UUID_NAME "uuid"
|
#define NVS_UUID_NAME "uuid"
|
||||||
|
#define FIRMWARE_VERSION "1"
|
||||||
|
|
||||||
NimBLECharacteristic *pCharacteristic;
|
NimBLECharacteristic *pCharacteristic;
|
||||||
bool deviceConnected = false;
|
bool deviceConnected = false;
|
||||||
|
|
@ -250,6 +251,9 @@ void loop() {
|
||||||
} else {
|
} else {
|
||||||
Serial.println("NO_KEY");
|
Serial.println("NO_KEY");
|
||||||
}
|
}
|
||||||
|
} else if (serialBuf == "VERSION?") {
|
||||||
|
Serial.print("BUILD_NR:");
|
||||||
|
Serial.println(FIRMWARE_VERSION);
|
||||||
} else if (serialBuf.startsWith("SET_KEY:")) {
|
} else if (serialBuf.startsWith("SET_KEY:")) {
|
||||||
String hex = serialBuf.substring(8);
|
String hex = serialBuf.substring(8);
|
||||||
hex.toUpperCase();
|
hex.toUpperCase();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue