From 483bd878ab76e6a3a066f2560dfd9f8148d20177 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Sun, 14 Mar 2021 11:42:04 +0800 Subject: [PATCH] untested change to use new hwmodel --- .../main/java/com/geeksville/mesh/NodeInfo.kt | 23 ++- .../java/com/geeksville/mesh/model/NodeDB.kt | 7 +- .../geeksville/mesh/service/MeshService.kt | 151 +++++++++++------- .../geeksville/mesh/service/MockInterface.kt | 2 +- app/src/main/proto | 2 +- 5 files changed, 119 insertions(+), 66 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/NodeInfo.kt b/app/src/main/java/com/geeksville/mesh/NodeInfo.kt index 77d26af77..bd8bacc85 100644 --- a/app/src/main/java/com/geeksville/mesh/NodeInfo.kt +++ b/app/src/main/java/com/geeksville/mesh/NodeInfo.kt @@ -14,12 +14,27 @@ import kotlinx.serialization.Serializable @Serializable @Parcelize -data class MeshUser(val id: String, val longName: String, val shortName: String) : +data class MeshUser( + val id: String, + val longName: String, + val shortName: String, + val hwModel: MeshProtos.HardwareModel +) : Parcelable { override fun toString(): String { - return "MeshUser(id=${id.anonymize}, longName=${longName.anonymize}, shortName=${shortName.anonymize})" + return "MeshUser(id=${id.anonymize}, longName=${longName.anonymize}, shortName=${shortName.anonymize}, hwModel=${hwModelString})" } + + /** a string version of the hardware model, converted into pretty lowercase and changing _ to -, and p to dot + * or null if unset + * */ + val hwModelString: String? + get() = + if (hwModel == MeshProtos.HardwareModel.UNSET) + null + else + hwModel.name.replace('_', '-').replace('p', '.').toLowerCase() } @Serializable @@ -95,8 +110,8 @@ data class NodeInfo( get() { return position?.takeIf { (it.latitude <= 90.0 && it.latitude >= -90) && // If GPS gives a crap position don't crash our app - it.latitude != 0.0 && - it.longitude != 0.0 + it.latitude != 0.0 && + it.longitude != 0.0 } } diff --git a/app/src/main/java/com/geeksville/mesh/model/NodeDB.kt b/app/src/main/java/com/geeksville/mesh/model/NodeDB.kt index d2f35f5ff..01ac4e18c 100644 --- a/app/src/main/java/com/geeksville/mesh/model/NodeDB.kt +++ b/app/src/main/java/com/geeksville/mesh/model/NodeDB.kt @@ -1,6 +1,7 @@ package com.geeksville.mesh.model import androidx.lifecycle.MutableLiveData +import com.geeksville.mesh.MeshProtos import com.geeksville.mesh.MeshUser import com.geeksville.mesh.NodeInfo import com.geeksville.mesh.Position @@ -25,7 +26,8 @@ class NodeDB(private val ui: UIViewModel) { MeshUser( "+16508765308".format(8), "Kevin MesterNoLoc", - "KLO" + "KLO", + MeshProtos.HardwareModel.ANDROID_SIM ), null ) @@ -36,7 +38,8 @@ class NodeDB(private val ui: UIViewModel) { MeshUser( "+165087653%02d".format(9 + index), "Kevin Mester$index", - "KM$index" + "KM$index", + MeshProtos.HardwareModel.ANDROID_SIM ), it ) diff --git a/app/src/main/java/com/geeksville/mesh/service/MeshService.kt b/app/src/main/java/com/geeksville/mesh/service/MeshService.kt index 217ee0f29..a9860cbfd 100644 --- a/app/src/main/java/com/geeksville/mesh/service/MeshService.kt +++ b/app/src/main/java/com/geeksville/mesh/service/MeshService.kt @@ -544,7 +544,7 @@ class MeshService : Service(), Logging { debug("Sending channels to device") asChannels.forEach { - setChannel(it) + setChannel(it) } channels = asChannels.toTypedArray() @@ -727,7 +727,8 @@ class MeshService : Service(), Logging { // Handle new style routing info Portnums.PortNum.ROUTING_APP_VALUE -> { - shouldBroadcast = true // We always send acks to other apps, because they might care about the messages they sent + shouldBroadcast = + true // We always send acks to other apps, because they might care about the messages they sent val u = MeshProtos.Routing.parseFrom(data.payload) if (u.errorReasonValue == MeshProtos.Routing.Error.NONE_VALUE) handleAckNak(true, data.requestId) @@ -780,11 +781,10 @@ class MeshService : Service(), Logging { channels[ch.index] = ch debug("Admin: Received channel ${ch.index}") if (ch.index + 1 < mi.maxChannels) { - if(ch.hasSettings()) { + if (ch.hasSettings()) { // Not done yet, request next channel requestChannel(ch.index + 1) - } - else { + } else { debug("We've received the primary channel, allowing rest of app to start...") onHasSettings() } @@ -808,7 +808,8 @@ class MeshService : Service(), Logging { it.user = MeshUser( if (p.id.isNotEmpty()) p.id else oldId, // If the new update doesn't contain an ID keep our old value p.longName, - p.shortName + p.shortName, + p.hwModel ) } } @@ -1187,7 +1188,8 @@ class MeshService : Service(), Logging { MeshUser( info.user.id, info.user.longName, - info.user.shortName + info.user.shortName, + info.user.hwModel ) if (info.hasPosition()) { @@ -1214,6 +1216,79 @@ class MeshService : Service(), Logging { } + private var rawMyNodeInfo: MeshProtos.MyNodeInfo? = null + + /** Regenerate the myNodeInfo model. We call this twice. Once after we receive myNodeInfo from the device + * and again after we have the node DB (which might allow us a better notion of our HwModel. + */ + private fun regenMyNodeInfo() { + val myInfo = rawMyNodeInfo + if (myInfo != null) { + val a = RadioInterfaceService.getBondedDeviceAddress(this) + val isBluetoothInterface = a != null && a.startsWith("x") + + var hwModelStr = myInfo.hwModelDeprecated + if(hwModelStr.isEmpty()) { + try { + val ni = toNodeInfo(myNodeNum) + val asStr = ni.user?.hwModelString + if (asStr != null) + hwModelStr = asStr + } catch(_: NodeNumNotFoundException) { + warn("Can't find local node to get hardware model") + } + } + val mi = with(myInfo) { + MyNodeInfo( + myNodeNum, + hasGps, + hwModelStr, + firmwareVersion, + firmwareUpdateFilename != null, + isBluetoothInterface && com.geeksville.mesh.service.SoftwareUpdateService.shouldUpdate( + this@MeshService, + DeviceVersion(firmwareVersion) + ), + currentPacketId.toLong() and 0xffffffffL, + if (messageTimeoutMsec == 0) 5 * 60 * 1000 else messageTimeoutMsec, // constants from current device code + minAppVersion, + maxChannels + ) + } + + newMyNodeInfo = mi + setFirmwareUpdateFilename(mi) + } + } + + private fun sendAnalytics() { + val myInfo = rawMyNodeInfo + val mi = myNodeInfo + if (myInfo != null && mi != null) { + /// Track types of devices and firmware versions in use + GeeksvilleApplication.analytics.setUserInfo( + // DataPair("region", mi.region), + DataPair("firmware", mi.firmwareVersion), + DataPair("has_gps", mi.hasGPS), + DataPair("hw_model", mi.model), + DataPair("dev_error_count", myInfo.errorCount) + ) + + if (myInfo.errorCode.number != 0) { + GeeksvilleApplication.analytics.track( + "dev_error", + DataPair("code", myInfo.errorCode.number), + DataPair("address", myInfo.errorAddress), + + // We also include this info, because it is required to correctly decode address from the map file + DataPair("firmware", mi.firmwareVersion), + DataPair("hw_model", mi.model) + // DataPair("region", mi.region) + ) + } + } + } + /** * Update the nodeinfo (called from either new API version or the old one) */ @@ -1226,62 +1301,18 @@ class MeshService : Service(), Logging { ) insertPacket(packetToSave) - setFirmwareUpdateFilename(myInfo) - - val a = RadioInterfaceService.getBondedDeviceAddress(this) - val isBluetoothInterface = a != null && a.startsWith("x") - - val mi = with(myInfo) { - MyNodeInfo( - myNodeNum, - hasGps, - hwModel, - firmwareVersion, - firmwareUpdateFilename != null, - isBluetoothInterface && SoftwareUpdateService.shouldUpdate( - this@MeshService, - DeviceVersion(firmwareVersion) - ), - currentPacketId.toLong() and 0xffffffffL, - if (messageTimeoutMsec == 0) 5 * 60 * 1000 else messageTimeoutMsec, // constants from current device code - minAppVersion, - maxChannels - ) - } - - newMyNodeInfo = mi + rawMyNodeInfo = myInfo + regenMyNodeInfo() // We'll need to get a new set of channels and settings now radioConfig = null // prefill the channel array with null channels - channels = Array(mi.maxChannels) { + channels = Array(myInfo.maxChannels) { val b = ChannelProtos.Channel.newBuilder() b.index = it b.build() } - - /// Track types of devices and firmware versions in use - GeeksvilleApplication.analytics.setUserInfo( - // DataPair("region", mi.region), - DataPair("firmware", mi.firmwareVersion), - DataPair("has_gps", mi.hasGPS), - DataPair("hw_model", mi.model), - DataPair("dev_error_count", myInfo.errorCount) - ) - - if (myInfo.errorCode.number != 0) { - GeeksvilleApplication.analytics.track( - "dev_error", - DataPair("code", myInfo.errorCode.number), - DataPair("address", myInfo.errorAddress), - - // We also include this info, because it is required to correctly decode address from the map file - DataPair("firmware", mi.firmwareVersion), - DataPair("hw_model", mi.model) - // DataPair("region", mi.region) - ) - } } @@ -1372,6 +1403,10 @@ class MeshService : Service(), Logging { newNodes.clear() // Just to save RAM ;-) haveNodeDB = true // we now have nodes from real hardware + + regenMyNodeInfo() // we have a node db now, so can possibly find a better hwmodel + sendAnalytics() + requestRadioConfig() } } else @@ -1543,12 +1578,12 @@ class MeshService : Service(), Logging { /*** * Return the filename we will install on the device */ - private fun setFirmwareUpdateFilename(info: MeshProtos.MyNodeInfo) { + private fun setFirmwareUpdateFilename(info: MyNodeInfo) { firmwareUpdateFilename = try { - if (info.region != null && info.firmwareVersion != null && info.hwModel != null) + if (info.firmwareVersion != null && info.model != null) SoftwareUpdateService.getUpdateFilename( this, - info.hwModel + info.model ) else null @@ -1660,7 +1695,7 @@ class MeshService : Service(), Logging { info("sendData dest=${p.to}, id=${p.id} <- ${p.bytes!!.size} bytes (connectionState=$connectionState)") - if(p.dataType == 0) + if (p.dataType == 0) throw Exception("Port numbers must be non-zero!") // we are now more strict // Keep a record of datapackets, so GUIs can show proper chat history diff --git a/app/src/main/java/com/geeksville/mesh/service/MockInterface.kt b/app/src/main/java/com/geeksville/mesh/service/MockInterface.kt index 7c76458e5..edaa0c462 100644 --- a/app/src/main/java/com/geeksville/mesh/service/MockInterface.kt +++ b/app/src/main/java/com/geeksville/mesh/service/MockInterface.kt @@ -142,6 +142,7 @@ class MockInterface(private val service: RadioInterfaceService) : Logging, IRadi id = DataPacket.nodeNumToDefaultId(numIn) longName = "Sim " + num.toHexString() shortName = getInitials(longName) + hwModel = MeshProtos.HardwareModel.ANDROID_SIM }.build() position = MeshProtos.Position.newBuilder().apply { latitudeI = Position.degI(lat) @@ -160,7 +161,6 @@ class MockInterface(private val service: RadioInterfaceService) : Logging, IRadi MeshProtos.FromRadio.newBuilder().apply { myInfo = MeshProtos.MyNodeInfo.newBuilder().apply { myNodeNum = MY_NODE - hwModel = "Sim" messageTimeoutMsec = 5 * 60 * 1000 firmwareVersion = service.getString(R.string.cur_firmware_version) numBands = 13 diff --git a/app/src/main/proto b/app/src/main/proto index 7c025b9a4..ac26ffdc7 160000 --- a/app/src/main/proto +++ b/app/src/main/proto @@ -1 +1 @@ -Subproject commit 7c025b9a4d54bb410ec17ee653122861b413f177 +Subproject commit ac26ffdc71dad5765124186df5ec38771a0e5240