首页 > 解决方案 > 在 Arduino 上解析蓝牙 ble.write json 字符串

问题描述

我正在尝试解析从我的手机进入 Arduino 的 JSON 字符串。我对 C++ 和这些库还很陌生,所以我遇到了一些问题。以下是我到目前为止的代码。除了我试图将 json[] 设置为来自手机的值的部分之外,一切正常。它是一个有效的 JSON,并返回到如下所示的控制台。

错误:初始化程序无法确定“json”的大小

从手机收到的 JSON:

{"SSID":"Sample","PSK":"test","TOKEN":"1234","HOSTNAME":"secondarycontroller"}

ESP32 代码:

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <ArduinoJson.h>

#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string value = pCharacteristic->getValue();


      if(value.length() > 0) {

        StaticJsonDocument<800> doc;
        char json[] = value;
        DeserializationError error = deserializeJson(doc, json);
        if (error) {
          Serial.print(F("deserializeJson() failed: "));
          Serial.println(error.c_str());
          return;
        }

        Serial.println(doc["SSID"]);
        Serial.println(doc["PSK"]);
        Serial.println(doc["HOSTNAME"]);
        Serial.println(doc["TOKEN"]);


        Serial.println("*********");
        Serial.print("New value: ");
        for (int i = 0; i < value.length(); i++)
          Serial.print(value[i]);

        Serial.println();
        Serial.println("*********");
      }
    }
};

void setup() {
  Serial.begin(115200);
  pinMode(LEDpin, OUTPUT);

  Serial.println("1- Download and install an BLE scanner app in your phone");
  Serial.println("2- Scan for BLE devices in the app");
  Serial.println("3- Connect to MyESP32");
  Serial.println("4- Go to CUSTOM CHARACTERISTIC in CUSTOM SERVICE and write something");
  Serial.println("5- See the magic =)");

  BLEDevice::init("MyESP32");
  BLEServer *pServer = BLEDevice::createServer();

  BLEService *pService = pServer->createService(SERVICE_UUID);

  BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID,
                                         BLECharacteristic::PROPERTY_READ |
                                         BLECharacteristic::PROPERTY_WRITE
                                       );

  pCharacteristic->setCallbacks(new MyCallbacks());

  pCharacteristic->setValue("Hello World");
  pService->start();

  BLEAdvertising *pAdvertising = pServer->getAdvertising();
  pAdvertising->start();


}

void loop() {
  // put your main code here, to run repeatedly:
  delay(2000);
}

标签: c++jsonarduino

解决方案


根据desrializeJson() 的文档,第二个输入参数接受char*零拷贝;和,const char*const std::string&重复。

文档中的原型(仅相关的):

// writable input => zero-copy
DeserializationError deserializeJson(JsonDocument& doc, char* input);
DeserializationError deserializeJson(JsonDocument& doc, char* input, size_t inputSize);

// read-only input => duplication
DeserializationError deserializeJson(JsonDocument& doc, const char* input);
DeserializationError deserializeJson(JsonDocument& doc, const char* input, size_t inputSize);
// ...
DeserializationError deserializeJson(JsonDocument& doc, const std::string& input);

观察上述原型中的第二个参数!


因此,以下几行:

char json[] = value;
DeserializationError error = deserializeJson(doc, json);

将会:

const char* json = value.c_str();
DeserializationError error = deserializeJson(doc, json);

或者,直接这样传递value

DeserializationError error = deserializeJson(doc, value);

那应该可以解决您的问题。


你得到的错误是关于这一行的:

char json[] = value;
//       ^^

char这里缺少数组的大小。您必须在此上下文中指定静态数组的大小。另外,value在这种情况下不能直接兑换。


小费:

在以下情况下使用std::string::empty() :

if(value.length() > 0)

IE

if( !value.empty() )

它更具可读性和表现力!


推荐阅读