2024-11-26 08:38:12 -03:00
|
|
|
/*
|
2026-01-02 14:06:05 -06:00
|
|
|
* Copyright (c) 2025-2026 Meshtastic LLC
|
2024-11-26 08:38:12 -03:00
|
|
|
*
|
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
2020-02-10 15:31:56 -08:00
|
|
|
package com.geeksville.mesh.service
|
2020-01-22 21:25:31 -08:00
|
|
|
|
2020-10-21 17:51:30 +08:00
|
|
|
import android.app.Service
|
2020-02-25 08:10:23 -08:00
|
|
|
import android.content.Context
|
|
|
|
|
import android.content.Intent
|
2023-06-18 17:33:06 -03:00
|
|
|
import android.content.pm.ServiceInfo
|
2025-07-29 09:42:36 -05:00
|
|
|
import android.os.Build
|
2020-01-22 21:25:31 -08:00
|
|
|
import android.os.IBinder
|
2023-01-03 21:02:31 -03:00
|
|
|
import androidx.core.app.ServiceCompat
|
2025-12-28 08:30:15 -06:00
|
|
|
import co.touchlab.kermit.Logger
|
2025-01-02 06:38:33 -03:00
|
|
|
import com.geeksville.mesh.BuildConfig
|
2024-10-13 06:10:28 -05:00
|
|
|
import com.geeksville.mesh.concurrent.handledLaunch
|
2025-05-30 13:17:09 -05:00
|
|
|
import com.geeksville.mesh.model.NO_DEVICE_SELECTED
|
2022-04-22 10:22:03 -07:00
|
|
|
import com.geeksville.mesh.repository.radio.RadioInterfaceService
|
2025-01-02 06:38:33 -03:00
|
|
|
import com.geeksville.mesh.util.toRemoteExceptions
|
2022-02-08 13:50:21 -08:00
|
|
|
import dagger.hilt.android.AndroidEntryPoint
|
2022-12-24 00:20:54 -03:00
|
|
|
import kotlinx.coroutines.CoroutineScope
|
|
|
|
|
import kotlinx.coroutines.Dispatchers
|
|
|
|
|
import kotlinx.coroutines.Job
|
2025-09-25 09:57:26 -04:00
|
|
|
import kotlinx.coroutines.flow.first
|
2022-05-20 09:13:59 -03:00
|
|
|
import kotlinx.coroutines.flow.launchIn
|
|
|
|
|
import kotlinx.coroutines.flow.onEach
|
2026-01-02 11:13:38 -06:00
|
|
|
import kotlinx.coroutines.runBlocking
|
2025-10-03 20:19:37 -04:00
|
|
|
import org.meshtastic.core.common.hasLocationPermission
|
2025-09-26 17:45:11 -04:00
|
|
|
import org.meshtastic.core.data.repository.RadioConfigRepository
|
2025-09-24 11:43:46 -04:00
|
|
|
import org.meshtastic.core.model.DataPacket
|
|
|
|
|
import org.meshtastic.core.model.DeviceVersion
|
|
|
|
|
import org.meshtastic.core.model.MeshUser
|
|
|
|
|
import org.meshtastic.core.model.MyNodeInfo
|
|
|
|
|
import org.meshtastic.core.model.NodeInfo
|
|
|
|
|
import org.meshtastic.core.model.Position
|
2025-09-30 16:55:56 -04:00
|
|
|
import org.meshtastic.core.service.IMeshService
|
2025-10-12 13:07:03 -04:00
|
|
|
import org.meshtastic.core.service.MeshServiceNotifications
|
|
|
|
|
import org.meshtastic.core.service.SERVICE_NOTIFY_ID
|
2025-09-30 16:55:56 -04:00
|
|
|
import org.meshtastic.core.service.ServiceRepository
|
2022-02-08 13:50:21 -08:00
|
|
|
import javax.inject.Inject
|
2020-01-24 17:05:55 -08:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
@AndroidEntryPoint
|
2026-01-14 21:22:30 -06:00
|
|
|
@Suppress("TooManyFunctions", "LargeClass")
|
2026-01-02 11:13:38 -06:00
|
|
|
class MeshService : Service() {
|
2025-08-12 17:19:40 -05:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
@Inject lateinit var radioInterfaceService: RadioInterfaceService
|
2025-08-12 17:19:40 -05:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
@Inject lateinit var serviceRepository: ServiceRepository
|
2025-08-12 17:19:40 -05:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
@Inject lateinit var connectionStateHolder: ConnectionStateHandler
|
2020-04-22 18:34:22 -07:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
@Inject lateinit var packetHandler: PacketHandler
|
2020-09-23 22:47:45 -04:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
@Inject lateinit var serviceBroadcasts: MeshServiceBroadcasts
|
2020-04-22 18:34:22 -07:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
@Inject lateinit var nodeManager: MeshNodeManager
|
2025-12-08 14:27:56 -06:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
@Inject lateinit var messageProcessor: MeshMessageProcessor
|
2025-12-13 12:44:23 -08:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
@Inject lateinit var commandSender: MeshCommandSender
|
2025-12-13 12:44:23 -08:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
@Inject lateinit var locationManager: MeshLocationManager
|
2025-12-13 12:44:23 -08:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
@Inject lateinit var connectionManager: MeshConnectionManager
|
2021-03-14 11:42:04 +08:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
@Inject lateinit var serviceNotifications: MeshServiceNotifications
|
2021-03-14 11:42:04 +08:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
@Inject lateinit var radioConfigRepository: RadioConfigRepository
|
2025-08-05 18:41:03 -05:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
@Inject lateinit var router: MeshRouter
|
2025-08-12 17:19:40 -05:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
private val serviceJob = Job()
|
|
|
|
|
private val serviceScope = CoroutineScope(Dispatchers.IO + serviceJob)
|
2025-08-05 18:41:03 -05:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
private val myNodeNum: Int
|
|
|
|
|
get() = nodeManager.myNodeNum ?: throw RadioNotConnectedException()
|
2025-08-12 17:19:40 -05:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
companion object {
|
|
|
|
|
fun actionReceived(portNum: Int): String {
|
|
|
|
|
val portType = org.meshtastic.proto.Portnums.PortNum.forNumber(portNum)
|
|
|
|
|
val portStr = portType?.toString() ?: portNum.toString()
|
|
|
|
|
return com.geeksville.mesh.service.actionReceived(portStr)
|
2025-12-28 08:30:15 -06:00
|
|
|
}
|
2023-10-12 17:52:52 -03:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
fun createIntent(context: Context) = Intent(context, MeshService::class.java)
|
2023-10-12 17:52:52 -03:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
fun changeDeviceAddress(context: Context, service: IMeshService, address: String?) {
|
|
|
|
|
service.setDeviceAddress(address)
|
2026-01-24 20:25:09 -06:00
|
|
|
startService(context)
|
2023-10-12 17:52:52 -03:00
|
|
|
}
|
2024-08-25 10:55:55 -03:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
val minDeviceVersion = DeviceVersion(BuildConfig.MIN_FW_VERSION)
|
|
|
|
|
val absoluteMinDeviceVersion = DeviceVersion(BuildConfig.ABS_MIN_FW_VERSION)
|
2025-08-12 17:19:40 -05:00
|
|
|
}
|
|
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
override fun onCreate() {
|
|
|
|
|
super.onCreate()
|
|
|
|
|
Logger.i { "Creating mesh service" }
|
|
|
|
|
serviceNotifications.initChannels()
|
2025-08-12 17:19:40 -05:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
packetHandler.start(serviceScope)
|
|
|
|
|
router.start(serviceScope)
|
|
|
|
|
nodeManager.start(serviceScope)
|
|
|
|
|
connectionManager.start(serviceScope)
|
|
|
|
|
messageProcessor.start(serviceScope)
|
|
|
|
|
commandSender.start(serviceScope)
|
2025-08-12 17:19:40 -05:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
serviceScope.handledLaunch { radioInterfaceService.connect() }
|
2023-10-12 17:52:52 -03:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
radioInterfaceService.receivedData
|
|
|
|
|
.onEach { bytes -> messageProcessor.handleFromRadio(bytes, nodeManager.myNodeNum) }
|
|
|
|
|
.launchIn(serviceScope)
|
2023-10-12 17:52:52 -03:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
serviceRepository.serviceAction.onEach(router.actionHandler::onServiceAction).launchIn(serviceScope)
|
2021-03-02 22:12:42 +08:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
nodeManager.loadCachedNodeDB()
|
2025-08-01 16:10:57 -05:00
|
|
|
}
|
2024-09-18 19:46:39 -03:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
2026-01-17 19:54:13 -06:00
|
|
|
val a = radioInterfaceService.getDeviceAddress()
|
2026-01-02 11:13:38 -06:00
|
|
|
val wantForeground = a != null && a != NO_DEVICE_SELECTED
|
2025-08-12 17:19:40 -05:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
val notification = connectionManager.updateStatusNotification()
|
2025-11-06 12:27:21 -06:00
|
|
|
|
|
|
|
|
try {
|
2026-01-02 11:13:38 -06:00
|
|
|
ServiceCompat.startForeground(
|
|
|
|
|
this,
|
|
|
|
|
SERVICE_NOTIFY_ID,
|
|
|
|
|
notification,
|
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
2026-02-01 17:18:06 -06:00
|
|
|
var types = ServiceInfo.FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE
|
2026-01-02 11:13:38 -06:00
|
|
|
if (hasLocationPermission()) {
|
2026-01-24 20:25:09 -06:00
|
|
|
types = types or ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION
|
2026-01-02 11:13:38 -06:00
|
|
|
}
|
2026-01-24 20:25:09 -06:00
|
|
|
types
|
2026-01-02 11:13:38 -06:00
|
|
|
} else {
|
|
|
|
|
0
|
|
|
|
|
},
|
2025-11-06 12:27:21 -06:00
|
|
|
)
|
|
|
|
|
} catch (ex: Exception) {
|
2026-01-02 11:13:38 -06:00
|
|
|
Logger.e(ex) { "Error starting foreground service" }
|
|
|
|
|
return START_NOT_STICKY
|
2021-01-05 14:01:45 +08:00
|
|
|
}
|
2026-01-02 11:13:38 -06:00
|
|
|
return if (!wantForeground) {
|
2026-01-17 19:54:13 -06:00
|
|
|
Logger.i { "Stopping mesh service because no device is selected" }
|
2026-01-02 11:13:38 -06:00
|
|
|
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE)
|
2026-01-15 09:36:03 -06:00
|
|
|
stopSelf()
|
2026-01-02 11:13:38 -06:00
|
|
|
START_NOT_STICKY
|
2025-08-12 17:19:40 -05:00
|
|
|
} else {
|
2026-01-02 11:13:38 -06:00
|
|
|
START_STICKY
|
2025-01-02 06:38:33 -03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-17 19:54:13 -06:00
|
|
|
override fun onTaskRemoved(rootIntent: Intent?) {
|
|
|
|
|
super.onTaskRemoved(rootIntent)
|
|
|
|
|
Logger.i { "Mesh service: onTaskRemoved" }
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
override fun onBind(intent: Intent?): IBinder = binder
|
2025-06-28 14:50:05 +00:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
override fun onDestroy() {
|
|
|
|
|
Logger.i { "Destroying mesh service" }
|
|
|
|
|
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE)
|
2026-01-15 15:23:33 -08:00
|
|
|
serviceRepository.cancelPendingRetries()
|
2026-01-02 11:13:38 -06:00
|
|
|
serviceJob.cancel()
|
|
|
|
|
super.onDestroy()
|
2025-06-28 14:50:05 +00:00
|
|
|
}
|
2020-04-19 19:23:20 -07:00
|
|
|
|
2025-07-29 09:42:36 -05:00
|
|
|
private val binder =
|
|
|
|
|
object : IMeshService.Stub() {
|
|
|
|
|
override fun setDeviceAddress(deviceAddr: String?) = toRemoteExceptions {
|
2026-01-02 11:13:38 -06:00
|
|
|
Logger.d { "Passing through device change to radio service: ${deviceAddr?.take(8)}..." }
|
|
|
|
|
router.actionHandler.handleUpdateLastAddress(deviceAddr)
|
2025-09-25 20:39:26 -05:00
|
|
|
radioInterfaceService.setDeviceAddress(deviceAddr)
|
2020-07-04 16:54:48 -07:00
|
|
|
}
|
2020-04-19 19:23:20 -07:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
override fun subscribeReceiver(packageName: String, receiverName: String) {
|
2025-09-25 17:22:14 -04:00
|
|
|
serviceBroadcasts.subscribeReceiver(receiverName, packageName)
|
2020-01-26 11:33:51 -08:00
|
|
|
}
|
2020-01-22 21:25:31 -08:00
|
|
|
|
2025-11-06 12:27:21 -06:00
|
|
|
override fun getUpdateStatus(): Int = -4
|
2020-05-13 14:47:55 -07:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
override fun startFirmwareUpdate() {
|
|
|
|
|
// Not implemented yet
|
|
|
|
|
}
|
2020-05-13 14:47:55 -07:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
override fun getMyNodeInfo(): MyNodeInfo? = nodeManager.getMyNodeInfo()
|
2020-05-13 14:47:55 -07:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
override fun getMyId(): String = nodeManager.getMyId()
|
2020-02-17 13:14:53 -08:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
override fun getPacketId(): Int = commandSender.generatePacketId()
|
2023-02-01 12:16:44 -03:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
override fun setOwner(u: MeshUser) = toRemoteExceptions {
|
|
|
|
|
router.actionHandler.handleSetOwner(u, myNodeNum)
|
2025-07-29 09:42:36 -05:00
|
|
|
}
|
2020-01-25 10:00:57 -08:00
|
|
|
|
2026-01-21 08:27:20 -06:00
|
|
|
override fun setRemoteOwner(id: Int, destNum: Int, payload: ByteArray) = toRemoteExceptions {
|
|
|
|
|
router.actionHandler.handleSetRemoteOwner(id, destNum, payload)
|
2025-07-29 09:42:36 -05:00
|
|
|
}
|
2023-04-22 12:06:25 -03:00
|
|
|
|
2025-07-29 09:42:36 -05:00
|
|
|
override fun getRemoteOwner(id: Int, destNum: Int) = toRemoteExceptions {
|
2026-01-02 11:13:38 -06:00
|
|
|
router.actionHandler.handleGetRemoteOwner(id, destNum)
|
2025-07-29 09:42:36 -05:00
|
|
|
}
|
2023-04-22 12:06:25 -03:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
override fun send(p: DataPacket) = toRemoteExceptions { router.actionHandler.handleSend(p, myNodeNum) }
|
2020-01-22 21:25:31 -08:00
|
|
|
|
2025-07-29 09:42:36 -05:00
|
|
|
override fun getConfig(): ByteArray = toRemoteExceptions {
|
2026-01-02 11:13:38 -06:00
|
|
|
runBlocking {
|
|
|
|
|
radioConfigRepository.localConfigFlow.first().toByteArray() ?: throw NoDeviceConfigException()
|
|
|
|
|
}
|
2025-07-29 09:42:36 -05:00
|
|
|
}
|
2022-11-29 17:47:49 -03:00
|
|
|
|
2025-07-29 09:42:36 -05:00
|
|
|
override fun setConfig(payload: ByteArray) = toRemoteExceptions {
|
2026-01-02 11:13:38 -06:00
|
|
|
router.actionHandler.handleSetConfig(payload, myNodeNum)
|
2025-07-29 09:42:36 -05:00
|
|
|
}
|
2023-04-22 12:06:25 -03:00
|
|
|
|
2025-07-29 09:42:36 -05:00
|
|
|
override fun setRemoteConfig(id: Int, num: Int, payload: ByteArray) = toRemoteExceptions {
|
2026-01-02 11:13:38 -06:00
|
|
|
router.actionHandler.handleSetRemoteConfig(id, num, payload)
|
2025-07-29 09:42:36 -05:00
|
|
|
}
|
2023-04-22 12:06:25 -03:00
|
|
|
|
2025-07-29 09:42:36 -05:00
|
|
|
override fun getRemoteConfig(id: Int, destNum: Int, config: Int) = toRemoteExceptions {
|
2026-01-02 11:13:38 -06:00
|
|
|
router.actionHandler.handleGetRemoteConfig(id, destNum, config)
|
2025-07-29 09:42:36 -05:00
|
|
|
}
|
2021-02-27 11:44:05 +08:00
|
|
|
|
2025-07-29 09:42:36 -05:00
|
|
|
override fun setModuleConfig(id: Int, num: Int, payload: ByteArray) = toRemoteExceptions {
|
2026-01-02 11:13:38 -06:00
|
|
|
router.actionHandler.handleSetModuleConfig(id, num, payload)
|
2025-07-29 09:42:36 -05:00
|
|
|
}
|
2023-04-22 12:06:25 -03:00
|
|
|
|
2025-07-29 09:42:36 -05:00
|
|
|
override fun getModuleConfig(id: Int, destNum: Int, config: Int) = toRemoteExceptions {
|
2026-01-02 11:13:38 -06:00
|
|
|
router.actionHandler.handleGetModuleConfig(id, destNum, config)
|
2025-07-29 09:42:36 -05:00
|
|
|
}
|
2023-04-22 12:06:25 -03:00
|
|
|
|
2025-08-09 11:55:42 -05:00
|
|
|
override fun setRingtone(destNum: Int, ringtone: String) = toRemoteExceptions {
|
2026-01-02 11:13:38 -06:00
|
|
|
router.actionHandler.handleSetRingtone(destNum, ringtone)
|
2025-07-29 09:42:36 -05:00
|
|
|
}
|
2023-04-22 12:06:25 -03:00
|
|
|
|
2025-08-09 11:55:42 -05:00
|
|
|
override fun getRingtone(id: Int, destNum: Int) = toRemoteExceptions {
|
2026-01-02 11:13:38 -06:00
|
|
|
router.actionHandler.handleGetRingtone(id, destNum)
|
2025-07-29 09:42:36 -05:00
|
|
|
}
|
2023-04-22 12:06:25 -03:00
|
|
|
|
2025-08-09 11:55:42 -05:00
|
|
|
override fun setCannedMessages(destNum: Int, messages: String) = toRemoteExceptions {
|
2026-01-02 11:13:38 -06:00
|
|
|
router.actionHandler.handleSetCannedMessages(destNum, messages)
|
2025-07-29 09:42:36 -05:00
|
|
|
}
|
2023-04-22 12:06:25 -03:00
|
|
|
|
2025-08-09 11:55:42 -05:00
|
|
|
override fun getCannedMessages(id: Int, destNum: Int) = toRemoteExceptions {
|
2026-01-02 11:13:38 -06:00
|
|
|
router.actionHandler.handleGetCannedMessages(id, destNum)
|
2025-07-29 09:42:36 -05:00
|
|
|
}
|
2022-11-22 22:01:37 -03:00
|
|
|
|
2025-08-12 17:19:40 -05:00
|
|
|
override fun setChannel(payload: ByteArray?) = toRemoteExceptions {
|
2026-01-02 11:13:38 -06:00
|
|
|
router.actionHandler.handleSetChannel(payload, myNodeNum)
|
2025-07-29 09:42:36 -05:00
|
|
|
}
|
2023-04-29 07:14:30 -03:00
|
|
|
|
2025-08-12 17:19:40 -05:00
|
|
|
override fun setRemoteChannel(id: Int, num: Int, payload: ByteArray?) = toRemoteExceptions {
|
2026-01-02 11:13:38 -06:00
|
|
|
router.actionHandler.handleSetRemoteChannel(id, num, payload)
|
2025-07-29 09:42:36 -05:00
|
|
|
}
|
2023-04-29 07:14:30 -03:00
|
|
|
|
2025-07-29 09:42:36 -05:00
|
|
|
override fun getRemoteChannel(id: Int, destNum: Int, index: Int) = toRemoteExceptions {
|
2026-01-02 11:13:38 -06:00
|
|
|
router.actionHandler.handleGetRemoteChannel(id, destNum, index)
|
2025-07-29 09:42:36 -05:00
|
|
|
}
|
2021-02-27 13:43:55 +08:00
|
|
|
|
2026-01-21 08:27:20 -06:00
|
|
|
override fun beginEditSettings(destNum: Int) = toRemoteExceptions {
|
|
|
|
|
router.actionHandler.handleBeginEditSettings(destNum)
|
2025-07-29 09:42:36 -05:00
|
|
|
}
|
2022-11-29 17:47:49 -03:00
|
|
|
|
2026-01-21 08:27:20 -06:00
|
|
|
override fun commitEditSettings(destNum: Int) = toRemoteExceptions {
|
|
|
|
|
router.actionHandler.handleCommitEditSettings(destNum)
|
2025-07-29 09:42:36 -05:00
|
|
|
}
|
2022-11-29 17:47:49 -03:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
override fun getChannelSet(): ByteArray = toRemoteExceptions {
|
|
|
|
|
runBlocking { radioConfigRepository.channelSetFlow.first().toByteArray() }
|
2025-07-29 09:42:36 -05:00
|
|
|
}
|
2020-01-22 21:25:31 -08:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
override fun getNodes(): List<NodeInfo> = nodeManager.getNodes()
|
2022-01-03 21:59:30 -03:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
override fun connectionState(): String = connectionStateHolder.connectionState.value.toString()
|
2022-01-03 21:59:30 -03:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
override fun startProvideLocation() {
|
|
|
|
|
locationManager.start(serviceScope) { commandSender.sendPosition(it) }
|
|
|
|
|
}
|
2024-09-24 07:53:09 -03:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
override fun stopProvideLocation() {
|
|
|
|
|
locationManager.stop()
|
2024-10-03 03:02:13 -05:00
|
|
|
}
|
2025-06-19 11:42:48 -05:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
override fun removeByNodenum(requestId: Int, nodeNum: Int) = toRemoteExceptions {
|
2026-01-24 20:25:09 -06:00
|
|
|
val myNodeNum = nodeManager.myNodeNum
|
|
|
|
|
if (myNodeNum != null) {
|
|
|
|
|
router.actionHandler.handleRemoveByNodenum(nodeNum, requestId, myNodeNum)
|
|
|
|
|
} else {
|
|
|
|
|
nodeManager.removeByNodenum(nodeNum)
|
|
|
|
|
}
|
2025-07-29 09:42:36 -05:00
|
|
|
}
|
2025-06-19 11:42:48 -05:00
|
|
|
|
2026-01-02 11:13:38 -06:00
|
|
|
override fun requestUserInfo(destNum: Int) = toRemoteExceptions {
|
2025-12-22 07:45:06 +11:00
|
|
|
if (destNum != myNodeNum) {
|
2026-01-02 11:13:38 -06:00
|
|
|
commandSender.requestUserInfo(destNum)
|
2025-12-22 07:45:06 +11:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-29 09:42:36 -05:00
|
|
|
override fun requestPosition(destNum: Int, position: Position) = toRemoteExceptions {
|
2026-01-02 11:13:38 -06:00
|
|
|
router.actionHandler.handleRequestPosition(destNum, position, myNodeNum)
|
2022-11-15 22:00:29 -03:00
|
|
|
}
|
2025-07-29 09:42:36 -05:00
|
|
|
|
|
|
|
|
override fun setFixedPosition(destNum: Int, position: Position) = toRemoteExceptions {
|
2026-01-02 11:13:38 -06:00
|
|
|
commandSender.setFixedPosition(destNum, position)
|
2024-09-28 08:09:42 -03:00
|
|
|
}
|
2022-11-06 17:46:57 -03:00
|
|
|
|
2025-07-29 09:42:36 -05:00
|
|
|
override fun requestTraceroute(requestId: Int, destNum: Int) = toRemoteExceptions {
|
2026-01-02 11:13:38 -06:00
|
|
|
commandSender.requestTraceroute(requestId, destNum)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override fun requestNeighborInfo(requestId: Int, destNum: Int) = toRemoteExceptions {
|
|
|
|
|
router.actionHandler.handleRequestNeighborInfo(requestId, destNum)
|
2025-07-29 09:42:36 -05:00
|
|
|
}
|
2023-04-16 06:16:41 -03:00
|
|
|
|
2025-07-29 09:42:36 -05:00
|
|
|
override fun requestShutdown(requestId: Int, destNum: Int) = toRemoteExceptions {
|
2026-01-02 11:13:38 -06:00
|
|
|
router.actionHandler.handleRequestShutdown(requestId, destNum)
|
2025-07-29 09:42:36 -05:00
|
|
|
}
|
2022-09-30 15:57:04 -03:00
|
|
|
|
2025-07-29 09:42:36 -05:00
|
|
|
override fun requestReboot(requestId: Int, destNum: Int) = toRemoteExceptions {
|
2026-01-02 11:13:38 -06:00
|
|
|
router.actionHandler.handleRequestReboot(requestId, destNum)
|
2025-12-06 06:36:54 -06:00
|
|
|
}
|
|
|
|
|
|
2026-01-21 08:27:20 -06:00
|
|
|
override fun rebootToDfu(destNum: Int) = toRemoteExceptions {
|
|
|
|
|
router.actionHandler.handleRebootToDfu(destNum)
|
|
|
|
|
}
|
2022-06-06 17:29:09 -03:00
|
|
|
|
2025-07-29 09:42:36 -05:00
|
|
|
override fun requestFactoryReset(requestId: Int, destNum: Int) = toRemoteExceptions {
|
2026-01-02 11:13:38 -06:00
|
|
|
router.actionHandler.handleRequestFactoryReset(requestId, destNum)
|
2025-07-29 09:42:36 -05:00
|
|
|
}
|
2022-09-18 18:35:13 -03:00
|
|
|
|
2025-11-11 02:38:45 +00:00
|
|
|
override fun requestNodedbReset(requestId: Int, destNum: Int, preserveFavorites: Boolean) =
|
|
|
|
|
toRemoteExceptions {
|
2026-01-02 11:13:38 -06:00
|
|
|
router.actionHandler.handleRequestNodedbReset(requestId, destNum, preserveFavorites)
|
2025-11-11 02:38:45 +00:00
|
|
|
}
|
2025-10-30 16:54:07 +11:00
|
|
|
|
|
|
|
|
override fun getDeviceConnectionStatus(requestId: Int, destNum: Int) = toRemoteExceptions {
|
2026-01-02 11:13:38 -06:00
|
|
|
router.actionHandler.handleGetDeviceConnectionStatus(requestId, destNum)
|
2025-10-30 16:54:07 +11:00
|
|
|
}
|
2025-12-24 14:11:29 -06:00
|
|
|
|
|
|
|
|
override fun requestTelemetry(requestId: Int, destNum: Int, type: Int) = toRemoteExceptions {
|
2026-01-02 11:13:38 -06:00
|
|
|
router.actionHandler.handleRequestTelemetry(requestId, destNum, type)
|
2025-12-24 14:11:29 -06:00
|
|
|
}
|
2026-01-14 21:22:30 -06:00
|
|
|
|
|
|
|
|
override fun requestRebootOta(requestId: Int, destNum: Int, mode: Int, hash: ByteArray?) =
|
|
|
|
|
toRemoteExceptions {
|
|
|
|
|
router.actionHandler.handleRequestRebootOta(requestId, destNum, mode, hash)
|
|
|
|
|
}
|
2022-09-18 18:35:13 -03:00
|
|
|
}
|
2020-05-30 15:48:50 -07:00
|
|
|
}
|