• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Запрос примеров для Sming

JustACat

Moderator
Команда форума
чтобы таймером самому себе не наступать на пятки
Можно еще запускать таймер разово, то есть вызывать:
[inline]procTimer.initializeMs(100, process).startOnce();[/inline]
Каждый раз в конце самой этой вашей процедуры void process() после всех обработок. Тогда таймер вторично не вызовется точно.
Правда это не избавит вас от вызова других прерываний (если они есть - тут уже к @anakod'у) во время выполнения вашего кода. Тогда, если критично, то да, надо как-то запрещать прерывания на время выполнения критичного кода.
 

Okadzaki

New member
Прошу добавить, или указать на существующий пример планировщика. Например на веб-странице указать время, оно запишется в файл, и по достижению этого время, будет выдана 1 или 0 на соответствующей ноге. Время берётся по NTP.
В итоге, чтобы при выключении питания, программа опять открывала файл, брало ближайшее событие (время), и по его достижению - меняло состояние на ноге.
Предпологаю, что числа нужно хранить в файле как массив JSON в формате time_t (UnixTime), но как-то реализовать не получилось.
 

anakod

Moderator
Команда форума
Okadzaki, приведите код, подскажем. А вообще хороший пример чтения\записи данных в файл есть в примере HttpServer_ConfigNetwork. Для работы с массивами: json.createNestedArray("...")
 

Okadzaki

New member
Okadzaki, приведите код, подскажем. А вообще хороший пример чтения\записи данных в файл есть в примере HttpServer_ConfigNetwork. Для работы с массивами: json.createNestedArray("...")
Есть например следующий обработчик страницы:
Код:
void onSchedule(HttpRequest &request, HttpResponse &response)
{
    if (request.getRequestMethod() == RequestMethod::POST){
        uint8_t min = request.getPostParameter("minutes").toInt();
        uint8_t hour = request.getPostParameter("hour").toInt();
        uint8_t sec = request.getPostParameter("Seconds").toInt();

        uint16_t year = request.getPostParameter("year").toInt();
        uint8_t month = request.getPostParameter("month").toInt();
        uint8_t day = request.getPostParameter("day").toInt();
         
    bool state = request.getPostParameter("state").toInt();
     time_t time = convertToUnixTime(sec,min,hour,day,month,year);
     scheduleFile.save(time,state);
    }
    TemplateFileStream *tmpl = new TemplateFileStream("schedule.html");
    auto &vars = tmpl->variables();
    response.sendTemplate(tmpl);
}
Структура JSON, что будет хранится в файле - ориентировачно такая:
JavaScript:
{
  "times":[
  {
  "time": 111111111,
  "state": true
  },
  {
  "time": 111111111,
  "state": true
  }
  ]
}
А вот как сделать так, чтобы при записи в файл, оно дополняло массив ( а если файл с конфигурацией вообще пуст - создать массив, добавить в него первый объект) - не знаю.

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

А раз в секунду, проверять, совпадает ли текущее время с тем ближайшем событием из файла. Как-то так:
Код:
void checkEvent(){
time_t now = SystemClock.now(true);
if (now == eventTime){
    digitalWrite(RELAY_PIN,event_state);
    scheduleFile.deleteEvent();
}
}

void connectOK(){
    Serial.print("OK");
    WifiAccessPoint.enable(false);
    ntp.setAutoQueryInterval(30);
    ntp.setAutoQuery(true);
    /*if (!AppSettings.rtc_sync){
        ntp.requestTime();
    }*/
    schedulePlan.initializeMs(1000,checkEvent);

}

Сама же структура scheduleFile включает в себя функции по записи в файл, чтения ближайшего события, и удаление последнего события.
 

alexhi

Member
Подскажите как в SMING настроить ногу RXD как цифровой вход , пробывал так pinMode(3,INPUT); не получается.
 

JustACat

Moderator
Команда форума
alexhi, а вывод дебага отключали?
[inline]Serial.systemDebugOutput(false);[/inline]
Хотя это же на TXD должно влиять, ну может еще что-то нужно...
Если только может еще не делать в начале:
[inline]Serial.begin();[/inline]
Т.к. в нем же как раз происходит настройка UART и запуск его прерываний.
 

alexhi

Member
JustCat,спасибо. Так работает:

Serial.systemDebugOutput(false);
[HASHTAG]#define[/HASHTAG] PIN_RXD 3
pinMode(PIN_RXD,INPUT);
while (1)
{
WDT.alive();
delay(1000);
Serial.println(digitalRead(PIN_RXD));
}
 

anakod

Moderator
Команда форума
Okadzaki, в целом все правильно. Хороший пример открытия и загрузки файла:
https://github.com/anakod/Sming/blob/master/HttpServer_ConfigNetwork/include/AppSettings.h

Если файла нет - инициализируете структуру, добавляете пустой массив (как создаются объекты в методе save). Далее по необходимости добавляете и удаляете узлы.
Посмотрите документацию на исходную библиотеку: https://github.com/bblanchon/ArduinoJson там есть примеры и информация по методам.

А вот пример создания массива и добавления элементов:
https://github.com/anakod/Sming/blob/master/HttpServer_ConfigNetwork/app/application.cpp#L84
 

Okadzaki

New member
А каким образом я смогу тогда просто дописать в файл элемент массива?
 
Последнее редактирование модератором:

anakod

Moderator
Команда форума
Загружаете текущее состояние из файла, получаете нужный узел по имени (собственно Ваш массив), а затем так же добавляете в него новый элемент.
 

anakod

Moderator
Команда форума
Okadzaki, если приложите полный код (архивом), то возможно что-нибудь еще смогу подсказать.
Обратное тоже верно: когда доделаете, буду очень рад принять pull-request в основной репозиторий, мне кажется пример планирования задач по времени - действительно интересная вещь для пользователей.
 

Okadzaki

New member
Возникла проблема с сохранением в файл JSON.
Есть следующая структура, в которой хранятся данные об файле с расписанием.
Код:
#define TIMERS_FILE ".timers.conf"
struct ScheduleFile{

   void save(time_t time, bool state){
     DynamicJsonBuffer jsonBuffer;
     if (!exist()){
       JsonObject& root = jsonBuffer.createObject();
       root["count"] = 1;
       JsonArray& timesArray = root.createNestedArray("times");
       JsonObject &item = timesArray.createNestedObject();
       item.add("time",time);
       item.add("state",state);
       fileSetContent(TIMERS_FILE,root.toJsonString());
     }else{
       int size = fileGetSize(TIMERS_FILE);
       char* jsonString = new char[size + 1];
       fileGetContent(TIMERS_FILE, jsonString, size + 1);
       JsonObject& root = jsonBuffer.parseObject(jsonString);
       uint8 count = root["count"];
       root["count"] = count + 1;
       JsonArray& timesArray = root["times"];
       JsonObject &item = timesArray.createNestedObject();
       item.add("time",time);
       item.add("state",state);
       delete[] jsonString;
       fileSetContent(TIMERS_FILE,root.toJsonString());
     }
   }



   bool exist() { return fileExist(TIMERS_FILE); }

};
На вход поступает bool и time_t (UNIX time число).
Проблема заключается именно при записи в файл, если он уже существует. Вариации файла .timers.conf представлены ниже:
Произошла первая запись в файл(файл до этого момента не существовал):
JavaScript:
{
  "count": 1,
  "times": [
  {
  "time": 1449832271,
  "state": true
  }
  ]
}
Вторая:
JavaScript:
{
  "count": 2,
  "times": [
    {
      "time": 1449832271,
      "state": true
    },
    {
      "time": 1452600732,
      "state": true
    }
  ]
}
Третья:
JavaScript:
{
  "s.conf": 3,
  "": [
    {
      " 3,\r\n  \"\": [\r\n    {\r\n      \" 3,\\r\\n  \\\"\\\": [\\r\\n    {\\r\\n      \\\" 3,\\\\r\\\\n  \\\\\\\"\\\\\\\": [\\\\r\\\\n    {\\\\r\\\\n      \\\\\\\" 3": 1449832271,
      "\" 3,\\r\\n  \\\"\\\": [\\r\\n    {\\r\\n      \\\" 3,\\\\r\\\\n  \\\\\\\"\\\\\\\": [\\\\r\\\\n    {\\\\r\\\\n      \\\\\\\" 3": true
    },
    {
      "\\\" 3,\\\\r\\\\n  \\\\\\\"\\\\\\\": [\\\\r\\\\n    {\\\\r\\\\n      \\\\\\\" 3": 1452600732,
      "\\\\n    {\\\\r\\\\n      \\\\\\\" 3": true
    },
    {
      "time": 1454288461,
      "state": false
    }
  ]
}
Четвертая:
JavaScript:
{
  "": 3,
  "": [
    {
      "я?h": 1449832271,
      "\" 3,\\r\\n  \\\"\\\": [\\r\\n    {\\r\\n      \\\" 3,\\\\r\\\\n  \\\\n  \\\\\\\\n  \\\\\\\\\\\\\\\\n  \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n  \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n  \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\set-3\">\n \\\\Ђlя?Ш": true
    },
    {
      "t-3\">\n \\\\Ђnя?Ш": 1452600732,
      "\\\\n    {\\\\r\\\\n      \\\\\\\" 3": true
    },
    {
      "time": 1454288461,
      "state": false
    }
  ],
  "count": 1,
  "times":
}

После пятой записи, файл тупо становится размером в 2 байта, и ничего в себе не хранит.7
Подскажите, в чем ошибка?
 

anakod

Moderator
Команда форума
Ошибка из-за того что delete[] jsonString; делается до того как файл записан. Соответственно данные могут быть потеряны (т.к. ArduinoJson не копирует память а использует исходную).
 

Okadzaki

New member
Ошибка из-за того что delete[] jsonString; делается до того как файл записан. Соответственно данные могут быть потеряны (т.к. ArduinoJson не копирует память а использует исходную).
Да, действительно проблема была в этом. Спасибо
 

Данило

New member
Здравствуйте.
Не подбросите пример для Mqtt. Почему то не публикует сообщение без таймера, если просто вызвать метод.
 

anakod

Moderator
Команда форума
Пример есть в стандартных.
Возможно проблема в том что Вы пробуете опубликовать сообщение до того как соединение с сервером установлено?
 

VelAndr

New member
Здравствуйте!
Начинаю изучать Ваш sming - все очень красиво выглядит. В процессе написания первой тестовой прошивки (на основе примера ConfigNetwork) у меня не получилось сформировать файл с файловой системой spiffs с веб-контентом (чтобы не загружать страницы по FTP). Я пробовал использовать find | mkespfsimage > spiff_rom.bin , но ничего не получилось - в файловой системе остался все тот же index.html.
Как правильно это делать, и можно ли вообще это сделать?
Спасибо!
 
Сверху Снизу