React Native向TTGO T-Display通过BLE发送数据乱码问题排查
问题:React Native BLE发送字符串到TTGO T-Display出现乱码
问题描述
通过蓝牙低功耗(BLE)从React Native应用向TTGO T-Display发送字符串(如"John")时,设备接收到的是乱码(如"e&g")。
已尝试方案
测试过不同编码方式和数据类型,问题未解决。
乱码原因分析
- 数据格式不匹配:React Native直接传递字符串给BLE写特征值方法时,底层可能将字符串转换为不符合预期的字节格式,Arduino端按默认方式解析就会出现乱码。
- 编码不一致:部分数据使用Base64编码发送,但Arduino端未做解码处理,直接显示编码后的字符串导致乱码。
- Arduino端未正确处理显示:原代码仅获取了接收值,未实现正确的字符串解析与屏幕显示逻辑。
解决方案
1. React Native端修改:统一按UTF-8字节数组发送数据
BLE传输的是字节流,需确保发送端将字符串转换为标准UTF-8字节数组,避免编码歧义:
async function scanAndConnect(color, medicijnNaam, voornaam, notitie) { let connectedDevice = null; // 字符串转UTF-8字节数组工具函数 function stringToUtf8Bytes(str) { const encoder = new TextEncoder(); return encoder.encode(str); } try { const isReady = await prepareBluetooth(); if (!isReady) { console.error("Bluetooth voorbereiding mislukt."); return; } const TTGO_T_DISPLAY_UUID = '4fafc201-1fb5-459e-8fcc-c5c9c331914b'; const TTGO_T_DISPLAY_Characteristic_UUID = 'beb5483e-36e1-4688-b7f5-ea07361b26a8'; const scanAndConnectDevice = new Promise((resolve, reject) => { manager.startDeviceScan(null, null, async (error, device) => { if (error) { console.error(error); reject(error); return; } if (device.name === 'TTGO_T_Display') { console.log('Apparaat gevonden: ', device.name); try { manager.stopDeviceScan(); const isConnected = await device.isConnected(); if (isConnected) { console.log('Device already connected.'); resolve(device); return; } connectedDevice = await device.connect(); console.log('Succesvol verbonden met ', device.name); await connectedDevice.discoverAllServicesAndCharacteristics(); resolve(connectedDevice); } catch (err) { console.error('Fout bij verbinden met device:', err); reject(err); } } }); }); const device = await scanAndConnectDevice; if (color) { const colorRGB = convertToColor(color); if (Array.isArray(colorRGB) && colorRGB.length === 3) { const [r, g, b] = colorRGB; const colorInt = (r << 16) | (g << 8) | b; const colorHex = colorInt.toString(16).padStart(6, '0').toUpperCase(); await device.writeCharacteristicWithResponseForService( TTGO_T_DISPLAY_UUID, TTGO_T_DISPLAY_Characteristic_UUID, stringToUtf8Bytes(colorHex) ); console.log('Kleur verzonden naar TTGO T-display:', colorHex); } else { console.error('Ongeldige kleurarray:', colorRGB); } } if (voornaam) { try { console.log('Bezig met verzenden van voornaam:', voornaam); await device.writeCharacteristicWithResponseForService( TTGO_T_DISPLAY_UUID, TTGO_T_DISPLAY_Characteristic_UUID, stringToUtf8Bytes(voornaam) ); console.log('Voornaam succesvol verzonden naar TTGO T-display:', voornaam); } catch (error) { console.error('Fout bij het verzenden van de voornaam:', error); } } if (medicijnNaam) { try { console.log('Bezig met verzenden van medicijnnaam:', medicijnNaam); // 去掉Base64编码,直接传UTF-8字节 await device.writeCharacteristicWithResponseForService( TTGO_T_DISPLAY_UUID, TTGO_T_DISPLAY_Characteristic_UUID, stringToUtf8Bytes(medicijnNaam) ); console.log('Medicijnnaam succesvol verzonden naar TTGO T-display:', medicijnNaam); } catch (error) { console.error('Fout bij het verzenden van de medicijnNaam:', error); } } if (notitie) { try { console.log('Bezig met verzenden van notitie:', notitie); // 去掉Base64编码,直接传UTF-8字节 await device.writeCharacteristicWithResponseForService( TTGO_T_DISPLAY_UUID, TTGO_T_DISPLAY_Characteristic_UUID, stringToUtf8Bytes(notitie) ); console.log('Notitie succesvol verzonden naar TTGO T-display:', notitie); } catch (error) { console.error('Fout bij het verzenden van de notitie:', error); } } } catch (error) { console.warn('Fout tijdens scannen en verbinden:', error); } finally { if (connectedDevice) { try { await connectedDevice.cancelConnection(); console.log('Verbinding geannuleerd.'); } catch (err) { console.error('Fout bij annuleren van de verbinding:', err); } } } } scanAndConnect(null, null, "John", null);
2. Arduino端修改:正确解析并显示接收数据
在onWrite回调中,直接解析UTF-8字符串并显示到屏幕,同时添加串口打印方便调试:
#include <BLEDevice.h> #include <BLEUtils.h> #include <BLEServer.h> #include <TFT_eSPI.h> #define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b" #define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8" TFT_eSPI tft = TFT_eSPI(); uint16_t currentColor = TFT_BLACK; class MyServerCallbacks: public BLEServerCallbacks { void onConnect(BLEServer* pServer) { Serial.println("Apparaat verbonden"); } void onDisconnect(BLEServer* pServer) { Serial.println("Apparaat losgekoppeld"); } }; class MyCallbacks: public BLECharacteristicCallbacks { void onWrite(BLECharacteristic *pCharacteristic) { std::string value = pCharacteristic->getValue(); if (value.length() > 0) { // 串口打印接收数据,调试用 Serial.print("Ontvangen data: "); Serial.println(value.c_str()); // 清空屏幕,设置文本样式并显示字符串 tft.fillScreen(currentColor); tft.setTextColor(TFT_WHITE); tft.setTextSize(2); tft.setCursor(10, 10); tft.print(value.c_str()); } } }; void setup() { Serial.begin(9600); tft.begin(); tft.setRotation(1); tft.fillScreen(currentColor); tft.setTextColor(TFT_WHITE); tft.setTextSize(2); tft.setCursor(10,10); tft.print("Wachten op data..."); BLEDevice::init("TTGO_T_Display"); BLEServer *pServer = BLEDevice::createServer(); pServer->setCallbacks(new MyServerCallbacks()); BLEService *pService = pServer->createService(SERVICE_UUID); BLECharacteristic *pCharacteristic = pService->createCharacteristic( CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_WRITE ); pCharacteristic->setCallbacks(new MyCallbacks()); pService->start(); BLEAdvertising *pAdvertising = pServer->getAdvertising(); pAdvertising->start(); } void loop() { // 无需额外操作 }
验证步骤
- 上传修改后的Arduino代码到TTGO T-Display,打开串口监视器。
- 运行修改后的React Native应用,触发字符串发送。
- 查看TTGO屏幕是否正确显示字符串,同时检查串口监视器的接收日志是否和发送内容一致。
内容的提问来源于stack exchange,提问作者simeon hailemariam
相关产品推荐
相关产品推荐

