最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

android - Problem in sending message to the lora device using protobuf - Stack Overflow

programmeradmin0浏览0评论

I'm building an app similar to Meshtastic using kotlin. So far, I’ve successfully implemented BLE scanning/discovery, pairing, and connecting via GATT—plus I can read device info like battery level and signal strength.

My current issue is with sending messages. I’m using Protobuf for serialization and writing to the message GATT characteristic without errors, but the LoRa device isn’t displaying or processing the sent message. I’m wondering if the problem is related to the BLE channel, the UUIDs used, or the message format.

This is the code for the gatt and sending the messages using mehsprotobuf

private val gattCallback = object : BluetoothGattCallback() {

    override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
        try {
            val device = gatt.device
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                Log.d("BLEManager", "Connected to GATT server: ${device.address}")
                connectionStates[device] = true
                deviceConnectionStates[device] = bluetoothGatt
                gatt.discoverServices()
            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                Log.d("BLEManager", "Disconnected from GATT server: ${device.address}")
                connectionStates[device] = false
                deviceConnectionStates[device] = null
                //Toast.makeText(context, "Device disconnected", Toast.LENGTH_SHORT).show()
            }
        } catch (e: SecurityException) {
            Log.d("BLEManager", "Error in connection state change: $e")
        }
    }

    override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
        try {
            if (status == BluetoothGatt.GATT_SUCCESS) {

                val btmService = gatt.getService(BTM_SERVICE_UUID)

                if (btmService != null) {
                    Log.d("BLEManager", "BTM Service discovered.")

                    val myNodeInfoCharacteristic = btmService.getCharacteristic(BTM_FROM_RADIO_CHARACTER)
                    if (myNodeInfoCharacteristic != null) {
                        gatt.readCharacteristic(myNodeInfoCharacteristic)
                        Log.d("BLEManager", "BTM_MY_NODE_INFO_CHARACTER is found: $myNodeInfoCharacteristic")
                    } else {
                        Log.e("BLEManager", "BTM_MY_NODE_INFO_CHARACTER not found.")
                    }


                    // Read signal strength
                    readSignalStrength(gatt)

                    // Read battery level
                    readBatteryLevel(gatt)

                    // Request configuration (frequency)
                    requestConfiguration(gatt)



                    val fromRadioCharacteristic = btmService.getCharacteristic(BTM_FROM_RADIO_CHARACTER)
                    if (fromRadioCharacteristic != null) {
                        gatt.setCharacteristicNotification(fromRadioCharacteristic, true)
                        fromRadioCharacteristic.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
                        gatt.writeCharacteristic(fromRadioCharacteristic)
                        Log.e("BLEManager", "Notification enabled: ${fromRadioCharacteristic}")
                    } else {
                        Log.e("BLEManager", "Characteristic not found.")
                    }


                    // Store the BTM_TO_RADIO_CHARACTER for writing later
                    val toRadioCharacteristic = btmService.getCharacteristic(BTM_TO_RADIO_CHARACTER)
                    if (toRadioCharacteristic != null) {
                        [email protected] = toRadioCharacteristic
                        Log.d("BLEManager", "BTM_TO_RADIO_CHARACTER ready for writing: $toRadioCharacteristic")
                    }

                    // Read the BTM_FROM_NUM_CHARACTER
                    val fromNumCharacteristic = btmService.getCharacteristic(BTM_FROM_NUM_CHARACTER)
                    if (fromNumCharacteristic != null) {
                        gatt.readCharacteristic(fromNumCharacteristic)
                        Log.d("BLEManager", "Reading BTM_FROM_NUM_CHARACTER: $fromNumCharacteristic")
                    }


            } else {
                    Log.d("BLEManager", "Everything failed cos BTM_SERVICE_UUID is null")
                }
                }
            }catch (e:SecurityException){
            Log.d("BLEManager", "Service discovery failed: $e")
        }
    }

    @Deprecated("Deprecated in Java")
    override fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
        if (characteristic.uuid == BTM_FROM_RADIO_CHARACTER) {
            try {
                val messageBytes = characteristic.value
                val fromRadioMessage = MeshProtos.FromRadio.parseFrom(messageBytes)

                if (fromRadioMessage.hasPacket()) {
                    val packet = fromRadioMessage.packet
                    val fromNodeId = packet.from
                    val toNodeId = packet.to
                    val payload = packet.decoded.payload.toStringUtf8()

                    Log.d("BLE", "Received message from node $fromNodeId: $payload ")
                    Log.d("BLEManager", "Received message: $toNodeId")

                }else{
                    Log.d("BLEManager", "The radio has no packet")
                }

                if (fromRadioMessage.hasConfig()) {
                    val config = fromRadioMessage.config
                    val frequency = config.lora.frequencyOffset
                    Log.d("BLEManager", "Frequency: $frequency Hz")
                }else{
                    Log.d("BLEManager", "The radio no packet")
                }

                if (fromRadioMessage.hasMyInfo()) {
                    val localNodeId = fromRadioMessage.myInfo.myNodeNum
                    Log.d("BLE", "Local Node ID: $localNodeId")
                    // Store the local node ID for future use
                }else{
                    Log.d("BLEManager", "The radio  packet")
                }
            } catch (e: Exception) {
                Log.e("BLEManager", "Failed to parse ACK message: ${e.message}")
            }
        }
    }


    @Deprecated("Deprecated in Java")
    override fun onCharacteristicRead(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int) {
        if (status == BluetoothGatt.GATT_SUCCESS) {
            try {
                val myNodeInfo = MyNodeInfo.parseFrom(characteristic.value)
                val nodeId = myNodeInfo.myNodeNum
                Log.d("BLEManager", "Retrieved node ID: $nodeId")

                when (characteristic.uuid) {
                    UUID.fromString("00002a19-0000-1000-8000-00805f9b34fb") -> {
                        val batteryLevel = characteristic.value[0].toInt()
                        Log.d("BLEManager", "Battery level: $batteryLevel%")
                        // Update UI or store the battery level
                    }

                }

            } catch (e: Exception) {
                Log.e("BLEManager", "Failed to parse MyNodeInfo: ${e.message}")
            }

        }
    }

    override fun onCharacteristicWrite(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int) {
        if (status == BluetoothGatt.GATT_SUCCESS) {
            Log.d("BLEManager", "Message sent successfully")
            } else {
            Log.e("BLEManager", "Failed to send message with status: $status")
        }
    }

    override fun onReadRemoteRssi(gatt: BluetoothGatt, rssi: Int, status: Int) {
        if (status == BluetoothGatt.GATT_SUCCESS) {
            Log.d("BLEManager", "Signal strength (RSSI): $rssi dBm")
        }
    }
}

private fun readSignalStrength(gatt: BluetoothGatt) {
    try {
        gatt.readRemoteRssi()
    }catch (e: SecurityException){
        Log.d("BLEManager", "rss: $e")
    }
}

private fun readBatteryLevel(gatt: BluetoothGatt) {
    val batteryService = gatt.getService(UUID.fromString("0000180f-0000-1000-8000-00805f9b34fb"))
    val batteryLevelCharacteristic = batteryService?.getCharacteristic(UUID.fromString("00002a19-0000-1000-8000-00805f9b34fb"))

    if (batteryLevelCharacteristic != null) {
        try {
            gatt.readCharacteristic(batteryLevelCharacteristic)
        }catch (e: SecurityException){
            Log.d("BLEManager", "Battery level: $e")
        }
    } else {
        Log.e("BLEManager", "Battery Level characteristic not found.")
    }
}

private fun requestConfiguration(gatt: BluetoothGatt) {
    val toRadioCharacteristic = gatt.getService(BTM_SERVICE_UUID)
        ?.getCharacteristic(BTM_TO_RADIO_CHARACTER)

    if (toRadioCharacteristic != null) {
        val configRequest = MeshProtos.ToRadio.newBuilder()
            .setWantConfigId(1) // Request configuration
            .build()

        val messageBytes = configRequest.toByteArray()
        toRadioCharacteristic.value = messageBytes
        try {
            gatt.writeCharacteristic(toRadioCharacteristic)
            Log.d("BLEManager", "$toRadioCharacteristic: $messageBytes")
        }catch (e: SecurityException){
            Log.d("BLEManager", "request configuration: e")
        }
    }
}


fun sendMessage(device: BluetoothDevice, message: String) {
    connectionStates[device] = true
    deviceConnectionStates[device] = bluetoothGatt
    //selectDevice(device)
    try {
        val toRadioCharacteristic = bluetoothGatt?.getService(BTM_SERVICE_UUID)
            ?.getCharacteristic(BTM_TO_RADIO_CHARACTER)

        if (toRadioCharacteristic != null) {

            val meshPacket = MeshProtos.Data.newBuilder()
                .setPortnum(Portnums.PortNum.TEXT_MESSAGE_APP)
                .setPayload(message.toByteStringUtf8())
                .build()

            val protobufMessage = MeshProtos.MeshPacket.newBuilder()
                .setFrom(0x00000001)
                .setTo(0x00000002)
                .setChannel(3)
                .setDecoded(meshPacket)
                .build()


            val toRadioMessage = MeshProtos.ToRadio.newBuilder()
                .setPacket(protobufMessage)
                .build()


            val messageBytes = toRadioMessage.toByteArray()

            toRadioCharacteristic.writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
            toRadioCharacteristic.value = messageBytes
            val success = bluetoothGatt?.writeCharacteristic(toRadioCharacteristic)
            if (success != null) {
                Log.d("BLEManager", "Message sent to BTM_TO_RADIO_CHARACTER: $message")
                saveMessageToDatabase(
                    message = message,
                    incoming = false
                )
                //publish(mqttTopic, message, 1, true)
            } else {
                Log.e("BLEManager", "Failed to send message to BTM_TO_RADIO_CHARACTER.")
            }
        } else {
            Log.e("BLEManager", "BTM_TO_RADIO_CHARACTER not found.")
        }
    } catch (e: SecurityException) {
        Log.e("BLEManager", "Error writing to BTM_TO_RADIO_CHARACTER: ${e.message}")
    }
}

What i want to do is to send message to the lora devces(esp32 devices) and moreover i want the message to appear on the OLED screen of the device. I included the protobuf but the device is not able to process the message and moreover i am not able to retrieve the node id of the lora device. it always tells me the retrieve node id is 0. I want to be able to send message to the lora device which will appear on it screen. Again i have no error

发布评论

评论列表(0)

  1. 暂无评论