Как преобразовать полезную нагрузку byte* в строку

Я хотел бы преобразовать полезную нагрузку byte *в строку, потому что я хочу сравнить содержимое полезной нагрузки с другой строкой.

void mqttCallbackHandler(char *topic, byte *payload, unsigned int length) {
  String payloadstr = ???
  ...
}

, 👍3


5 ответов


Лучший ответ:

8

В зависимости от того, что задает сообщение в теме, полезная нагрузка может быть или не быть строкой с НУЛЕВЫМ завершением. Вот почему они предоставляют параметр length.

Вы можете сравнить данные с memcmp (), который похож на strcmp (), но не ищет НУЛЕВОЕ завершение - вместо этого он принимает параметр length. Это хорошо, если в вашей полезной нагрузке могут быть НУЛЕВЫЕ байты.

Альтернативой является strncmp (), который одновременно ищет НУЛЕВОЕ завершение, а также ограничивает длину с помощью параметра length. Лучше всего для полезных нагрузок, которые, как вы знаете, являются строками, но вы не уверены, имеют ли они НУЛЕВОЕ завершение или нет.

Вот обратный вызов (для PubSubClient на ESP8266) У меня есть в одном из моих проектов, который использует strncmp():

void callback(char *topic, byte *payload, unsigned int length) {
    if (!strcmp(topic, SUBTOPIC)) {
        if (!strncmp((char *)payload, "on", length)) {
            digitalWrite(POWERPIN, HIGH);
            powerState = true;
            client.publish(PUBTOPIC, "on", true);
        } else if (!strncmp((char *)payload, "off", length)) {
            digitalWrite(POWERPIN, LOW);
            powerState = false;
            client.publish(PUBTOPIC, "off", true);
        }
    }
}

Простого приведения полезной нагрузки к (char *) достаточно, чтобы функции приняли ее как строку, а параметр length не позволит заглянуть в конец полезной нагрузки, если нет нулевого завершения.

Это не идеально - однобайтовая полезная нагрузка o будет ложно соответствовать первой on, но если это критическая проблема, я уверен, что вы можете найти способ обойти ее, проверив, какая длина равна.

,

strncmp хорош для внутреннего сравнения, что делать, если я хочу отправить данные в rest API?, @dvdmn


2

Подумайте о том, чтобы просто использовать возвращаемый указатель.

Полезная нагрузка - это указатель типа byte. Вы можете сравнить каждый байт в строке с тем байтом, на который указывает указатель. Затем увеличьте указатель до следующего байта и повторите процесс. Вам не нужно выделять больше памяти для новой строки.

Если строка типа необходима. Например, если вы используете сложный библиотечный метод, который требует передачи строки, вы можете скопировать байт за байтом то, на что указывает возвращаемый указатель, в локально определенную строку.

,

2

Для сравнения массива байтов со строковым объектом можно преобразовать массив байтов в другой строковый объект, но это требует динамического выделения памяти для всей копии строки. Это недружественная память, и ее желательно избегать на небольших микроконтроллерах.

Самый дешевый способ добиться того, что вы хотите, - сравнить их как символьные массивы :

if (strcmp((char *) payload, theReferenceString.c_str()) == 0) {
    // the strings are equal
}

strcmp () - это стандартная функция C, которая выполняет сравнение байт за байтом , точно так же, как это было предложено st2000.

,

что делать, если строка полезной нагрузки не заканчивается нулем?, @Juraj

@Juraj: тогда memcmp()., @Edgar Bonet


3

Это старый пост, но, вероятно, кто-то может использовать эту информацию:

void mqtt_callback(char* topic, byte* payload, unsigned int length) {
  String topicStr = topic; 
  String recv_payload = String(( char *) payload);

  Serial.println( "mqtt_callback - message arrived - topic [" + topicStr + 
                  "] payload [" + recv_payload + "]" );
}
,

Спасибо, что ответили на мой вопрос. Но как строковый конструктор знает, где находится конец массива char ?, @tavis


0

Ответ Марко сработал для меня, но сработал лучше:

payload[length] = 0;
String recv_payload = String(( char *) payload);

Таким образом, полный код будет следующим:

void mqtt_callback(char* topic, byte* payload, unsigned int length) {
  String topicStr = topic; 
  payload[length] = 0;
  String recv_payload = String(( char *) payload);

  Serial.println( "mqtt_callback - message arrived - topic [" + topicStr + 
                  "] payload [" + recv_payload + "]" );
}
,