Преобразование byte* в int в Arduino

Я пытаюсь преобразовать значение byte* в int, вот как это у меня получилось.

void mqttCallback(char* topic, byte* payload, unsigned int length) {

  String topicStr = topic;
  int* payload_value;
  int updates_cal;

    payload_value = (int*)payload;
    //updates_cal = *payload_value;


    Serial.print((int)payload_value);


  delay(1);

  Serial.println();
  Serial.println("-----------------------");

}

Я получаю полезные данные MQTT в виде целочисленного значения. Который я хочу получить в своем NodeMCU (ESP8266).

Есть ли способ сделать это?

Спасибо!

, 👍2

Обсуждение

Если вы хотите преобразовать byte * в int, то он у вас уже есть, предполагая, что int достаточно велик для хранения адреса на вашей платформе. Но какой в этом смысл? Ваше payload_value — это адрес., @AnT

@AnT Мне просто нужно целое число (без указателя). Как я могу Serial.print его?, @user3201500

**Какое** конкретное целое число вам нужно? Взято откуда?, @AnT

@AnT целое число публикуется MQTT в виде сообщения., @user3201500

Описание формата сообщения MQQT предполагает, что вторая часть моего ответа (а также ответа Дункана С) является правильным способом сделать это., @AnT

Я пробовал это, но это ошибка. Вот как выглядит ошибка:, @user3201500

Исключение (9): epc1=0x40202430 epc2=0x00000000 epc3=0x00000000 excvaddr=0x3ffeeb79 depc=0x00000000 >>>стек>>> 8 января 2013 г., первая причина: 4, режим загрузки: (1,6), @user3201500

Учитывая длинные комментарии в принятом ответе, рассмотрите возможность редактирования этих вопросов и / или заголовка, чтобы отразить более четкое изложение желаемого., @Kelly S. French


3 ответа


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

2

Судя по комментариям, вы на самом деле получаете целочисленные данные в виде текста, в виде последовательности символов ASCII. Это то, что вы отправляете себе с помощью mosquitto_pub. Буфер явно не завершается нулем.

Если эти символы представляют собой целочисленное значение, то способ получить его как целочисленное значение будет

char buffer[128];

// Убедитесь, что `length` меньше указанного выше размера буфера.
// В противном случае вам понадобится буфер большего размера

// Формируем C-строку из полезной нагрузки
memcpy(buffer, payload, length);
buffer[length] = '\0';

// Преобразуем его в целое число
char *end = nullptr;
long value = strtol(buffer, &end, 10);

// Проверяем ошибки конвертации
if (end == buffer || errno == ERANGE)
  ; // Произошла ошибка преобразования
else
  Sterial.println(value);

Еще один подход, который позволяет избежать использования отдельного большого [своего] буфера только для нулевого завершения, заключается в

// Строим строку формата `scanf`, которая будет читаться не более `length`
// символов, не полагаясь на нулевое завершение полезной нагрузки
char format[16];
snprintf(format, sizeof format, "%%%ud", length);

// Конвертируем полезную нагрузку
int payload_value = 0;
if (sscanf((const char *) payload, format, &payload_value) == 1)
  Serial.println(payload_value);
else
  ; // Произошла ошибка преобразования

Однако этот подход менее защищен от целочисленного переполнения, чем предыдущий.


Обратите внимание, что большая часть вышеперечисленных «прыжков через обручи» посвящена добавлению нулевого терминатора во входной буфер. Если вместо этого вы выберете обеспечение нулевого завершения на стороне отправителя, тогда все сведется к простому

// Преобразование C-строки в целое число
char *end = nullptr;
long value = strtol((const char *) payload, &end, 10);

// Проверяем ошибки конвертации
if (end == buffer || errno == ERANGE)
  ; // Произошла ошибка преобразования
else
  Sterial.println(value);

Дополнительные буферы не требуются.

,

Комментарии не для расширенного обсуждения; этот разговор был [перемещен в чат](https://chat.stackexchange.com/rooms/93108/discussion-on-answer-by-ant-convert-byte-to-int-in-arduino)., @Majenko


0

byte* означает "указатель на байт(ы). Обычно он используется для указания на байтовый буфер и обычно также имеет значение длины, чтобы вы знали, сколько байтов находится в буфере. . Похоже, ваша функция имеет значение длины.

Если вы уверены, что данные в параметре payload представляют собой одиночное целое число, а длина верна для целого числа (я полагаю, 2 байта на Arduino), то вы сможете выполнить приведение введите указатель на int* и затем извлеките значение из буфера:

void mqttCallback(char* topic, byte* payload, unsigned int length) {
  String topicStr = topic;
  int payload_value;
  int updates_cal;

  if (length >= 2) {
    // Приводим полезную нагрузку к указателю int и извлекаем значение
    intValue = *((int*)payload); 
  }
}
,

Я пробовал это, но есть какая-то ошибка. Это сброс моего NodeMCU. Номер исключения – 9., @user3201500


1

Не знаю, нашли ли вы ответ, но у меня была точно такая же проблема, и в конце концов я пришел к следующему:

   payload[length] = '\0'; // Добавьте NULL в конец char*, чтобы сделать его строкой.
   int aNumber = atoi((char *)payload);

В конце концов, довольно просто!

,

Имейте в виду, что `payload[length]` не является частью памяти, выделенной для переменной полезной нагрузки. Последний элемент в пространстве памяти массива всегда имеет длину 1. Ваш подход может работать большую часть времени, но вы потенциально можете перезаписать другие переменные, расположенные в этом месте в памяти., @Steve2955