ArduinoJson - необъяснимое поведение '.size()'

json

Я использую ESP8266, ArduinoJson v6.21.5. PlatformIO и Vscode.

Файл конфигурации сохраняется и корректно считывается во флэш-память ESP8266:

{
    "gen_pubTopic": [
        "DvirHome/Messages",
        "DvirHome/log",
        "DvirHome/debug"
    ],
    "subTopic": [
        "DvirHome/Light/int/KitchenLEDs",
        "DvirHome/All",
        "DvirHome/Light/int",
        "DvirHome/Light"
    ],
    "pubTopic": [
        "DvirHome/Light/int/KitchenLEDs/Avail",
        "DvirHome/Light/int/KitchenLEDs/State"
    ]
}

В случае отсутствия файла конфигурации t[], t2[] и t3[] жестко запрограммированы во избежание сбой загрузки.

Для чтения тем есть 3 цикла for (из файла конфигурации или из жестко запрограммированного).

Необъяснимая часть:

  1. Файл конфигурации сохраняется и читается должным образом, а код выполняется без сбоев.

  2. когда цикл for содержит DOC["gen_pubTopic"].size(), темы читаются как положено, но когда они определены как DOC["gen_pubTopic"].size() |3 происходит сбой.

  3. x, x2 и x3 определяются перед каждым циклом for. Опять же, как определено в пункте 2), все равно никаких изменений.

  4. В какой-то момент это происходило на третьем цикле for, а иногда и на втором цикле for.

  5. Печать значений xi показывает ожидаемые значения.

  6. Чтобы было понятно: без использования "резервной аннотации" |2 код выполняется без сбоев.

  7. На всех этапах, описанных выше, резервный этап не тестируется (это означает, что файл конфигурации сохраняется и читается), и происходит сбой, когда "резервная аннотация" добавляется.

Цените любую идею.

void start_iot2(JsonDocument &DOC)
{
       
  /* Default values */
  const char *t[] = {"DvirHome/Messages", "DvirHome/log", "DvirHome/debug"};
  const char *t2[] = {"DvirHome/Device", "DvirHome/All"};
  const char *t3[] = {"DvirHome/Device/Avail", "DvirHome/Device/State"};
    
  uint8_t x = DOC["gen_pubTopic"].size() | 3;
  for (uint8_t i = 0; i < x; i++)
  {
    /* Some Code */
    /* debug code */
    Serial.print("Gen_");
    Serial.println(i);
  }

  uint8_t x2 = DOC["subTopic"].size() | 2;    
  for (uint8_t i = 0; i < x2; i++)
  {
    /* Some Code */
    /* debug code */
    Serial.print("Sub_");
    Serial.println(i);
  }
    
  uint8_t x3 = DOC["pubTopic"].size() | 2;
  for (uint8_t i = 0; i < x3; i++)
  {
    /* Some Code */ 
    /* debug code */
    Serial.print("Pub_");
    Serial.println(i);
  }
  
  iot.start_services(extMQTT);
}

Изменить_1 Добавлен /*код отладки */ в циклы for. В какой-то момент Serial Monitor показал:

Sub_0
Sub_1
Sub_2
Sub_3
Sub_4
Sub_5

а размер массива SubTopic по умолчанию равен 4 и |2.

, 👍2

Обсуждение

Я не знаю, чего вы ожидали | 3 сделать., @timemage

|3 устанавливается как значение в случае, если файл конфигурации не существует., @Guy . D

Боюсь, вы не знаете, что | значение на самом деле означает. Пожалуйста, [отредактируйте] свой вопрос и подробно опишите, что, по вашему мнению, он делает., @the busybee

*|3 устанавливается как значение в случае, если файл конфигурации не существует* - это не то, что он делает., @Nick Gammon


1 ответ


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

4

"Резервное обозначение" вы имеете в виду JsonVariant::operator| и работает только для < a href="https://arduinojson.org/v6/api/jsonvariant/">JsonVariant.

В вашей программе вы применяете | к unsigned long, поэтому встроенный побитовый оператор "или"; применяется оператор. Он последовательно выполняет операцию «или». операция (например, 2 | 4 — это 6).

Другими словами, doc["key"] | 4 ведет себя так, как вы описываете, но не doc.size() | 4.

В отличие от многих других языков, вы не можете использовать логическое «или» (|| ) либо потому, что он возвращает логическое значение. Итак, если вы хотите внести минимальные изменения в свой код, вам придется сделать что-то вроде этого:

uint8_t x = DOC["gen_pubTopic"].size();
if (!x) x = 3;
,

Я предпочитаю явные условия скрытым функциям C: if (x == 0) // ... ;-) Это не раздражает случайного читателя источника и гораздо лучше показывает намерение., @the busybee

@Бенуа - спасибо за краткий ответ, @Guy . D

Я хочу убедиться, что использование iot.add_pubTopic(DOC["pubTopic"][i] | t3[i]); корректно (используя t3[i] как «резервный вариант»), @Guy . D

Нет, я думаю, что нет. Похоже, что аргумент add_pubTopic по-прежнему является unsigned long, для которого | означает "побитовое или". Вероятно, это даже не следует компилировать, потому что t3[i] — это строка., @John