Перейти к публикации
iT4iT.CLUB
Kitsum

esp8266 и парсинг погоды с OpenWeatherMap

Рекомендованные сообщения

Всем доброго времени суток, сегодня поговорим о esp8266 и парсинге погоды с интернета. Это довольно интересная альтернатива метеостанции описанной в параллельной теме и думаю, что первый пост стоит посвятить базовой программе - своего рода фундаменту, на базе которого можно производить дальнейшие модификации от подключения дисплея до прикручивания MQTT протокола для системы умного дома.

О самом проекте OpenWeatherMap много написано в сети, но я познакомился с ним недавно, как и с микроконтроллером esp8266 который мы будем программировать в доработанной среде Arduino IDE. Но перед тем как начать, необходимо посетить сайт, с которого мы будем вытаскивать данные об окружающей среде.

И так, OpenWeatherMap предоставляет нам удобный и бесплатный API. На момент публикации статьи (05.2016) мы можем:

  • Производить не более 60 запросов в минуту
  • Не более 50000 запросов в день
  • Два типа прогноза (на 5 и на 16 дней)
  • Доступность сервиса 95%
  • Интервал обновление данных < 2 часов

Отлично, нас все устраивает. Регистрируемся и в личном кабинете переходим в раздел API Keys. По умолчанию нам уже дадут один ключ, можно воспользоваться им, а можно создать новый и обозвать его более понятным именем. Это довольно актуально, если планируется использовать несколько устройств, да и вообще должен быть порядок везде.

esp-owm1.png

Без данного ключа получить доступ к API невозможно.

Осталось определиться с интересующей нас местностью. API гласит, что есть несколько вариантов:

  • По названию города и коду страны
  • По уникальному идентификатору города
  • По географическим координатам
  • По почтовому индексу

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

esp-owm2.png

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

Список всех доступных населенных пунктов можно найти тут http://openweathermap.org/help/city_list.txt

Теперь переходим к самому интересному - скетч. В начале поста я оставил ссылку на ресурс, подробно описывающий все процедуры необходимые, чтобы завести контроллер и использовать Arduino IDE для прошивки. Но я пошел еще более простым путем и приобрел ESP-12E с обвесом под NodeMCU, это позволило прошивать контроллер без нажатия кнопок RESET и FLASH.

esp-owm3.jpg

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

Программа

Скрытый текст

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <ArduinoJson.h>

const char* ssid     = "WiFi AP name";
const char* password = "WiFi AP password";
const String server  = "api.openweathermap.org";
const String lat     = "51.31";
const String lon     = "37.89";
const String appid   = "b1f6b0a1ea9e10feb04eb3a2de2ad2b9";
const String url     = "http://" + server + "/data/2.5/weather?lat=" + lat + "&lon=" + lon + "&units=metric&appid=" + appid;

unsigned long lastConnectionTime = 0;
unsigned long postingInterval = 0;

String httpData;

struct weather_structure {
  unsigned int id;
  const char* main;
  const char* icon;
  const char* descript;
  float temp;
  float pressure;
  byte  humidity;
  float speed;
  float deg;
};
weather_structure weather;

void setup() {
  Serial.begin(115200);
  Serial.print("\nConnecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("\nWiFi connected\nIP address: ");
  Serial.println(WiFi.localIP());
  Serial.println();
}

void loop() {
  if (WiFi.status() == WL_CONNECTED) {
    if (millis() < lastConnectionTime) lastConnectionTime = 0;
    if (millis() - lastConnectionTime > postingInterval or lastConnectionTime == 0) {
      if (httpRequest() and parseData()) {
        Serial.println("\nWeather");
        Serial.printf("id: %d\n", weather.id);
        Serial.printf("main: %s\n", weather.main);
        Serial.printf("description: %s\n", weather.descript);
        Serial.printf("icon: %s\n", weather.icon);
        Serial.printf("temp: %d celsius\n", round(weather.temp));
        Serial.printf("humidity: %d %\n", round(weather.humidity));
        Serial.printf("pressure: %d hPa or %d mmHg\n", round(weather.pressure), round(weather.pressure * 0.75));
        Serial.printf("wind's speed: %d\n", round(weather.speed));
        Serial.printf("wind's direction: %d\n", round(weather.deg));
        Serial.println();
      }
    }
  }
}

bool httpRequest() {
  HTTPClient client;
  bool find = false;
  //client.setTimeout(1000);
  Serial.print("Connecting ");
  client.begin(url);
  int httpCode = client.GET();

  if (httpCode > 0) {
    Serial.printf("successfully, code: %d\n", httpCode);
    if (httpCode == HTTP_CODE_OK) {
      httpData = client.getString();
      if (httpData.indexOf(F("\"main\":{\"temp\":")) > -1) {
        lastConnectionTime = millis();
        find = true;
      }
      else Serial.println("Failed, json string is not found");
    }
  }
  else Serial.printf("failed, error: %s\n", client.errorToString(httpCode).c_str());

  postingInterval = find ? 600L * 1000L : 60L * 1000L;
  client.end();

  return find;
}

bool parseData() {
  Serial.println(httpData);

  DynamicJsonBuffer jsonBuffer;
  JsonObject& root = jsonBuffer.parseObject(httpData);

  if (!root.success()) {
    Serial.println("Json parsing failed!");
    return false;
  }

  weather.id       = root["weather"][0]["id"];
  weather.main     = root["weather"][0]["main"];
  weather.descript = root["weather"][0]["description"];
  weather.icon     = root["weather"][0]["icon"];
  weather.temp     = root["main"]["temp"];
  weather.humidity = root["main"]["humidity"];
  weather.pressure = root["main"]["pressure"];
  weather.speed    = root["wind"]["speed"];
  weather.deg      = root["wind"]["deg"];

  httpData = "";
  return true;
}

 

Все, что нам нужно редактировать, это начальные переменные (ключ указан рабочий, но это все временно)

const char* ssid     = "WiFi AP name";
const char* password = "WiFi AP password";
const String server  = "api.openweathermap.org";
const String lat     = "51.31";
const String lon     = "37.89";
const String appid   = "b1f6b0a1ea9e10feb04eb3a2de2ad2b9";

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

И так, на данный момент мы собираем:

  • weather.id - Идентификатор погодных условий (будет полезен, см. отсылку с weather.icon)
  • weather.main - Группа метеорологических параметров
  • weather.descript - Описание погодных условий в группе
  • weather.icon - Идентификатор иконки (подробнее ознакомиться с ними можно тут)
  • weather.temp - Текущая температура в градусах Цельсия
  • weather.humidity - Текущая влажность в %
  • weather.pressure - Текущее давление (по умолчанию сервер отдает её в hPa, но при умножении на 0,75 мы получаем mmHg)
  • weather.speed - Скорость ветра метры/сек.
  • weather.deg - Направление ветра в градусах

Выглядит это следующим образом

Connecting to Lenovo S90
......
WiFi connected
IP address: 
10.10.1.243

Connecting successfully, code: 200
{"coord":{"lon":37.84,"lat":51.3},"weather":[{"id":802,"main":"Clouds","description":"scattered clouds","icon":"03d"}],"base":"cmc stations","main":{"temp":18.24,"pressure":996.52,"humidity":92,"temp_min":18.24,"temp_max":18.24,"sea_level":1021.77,"grnd_level":996.52},"wind":{"speed":2.01,"deg":30.5008},"clouds":{"all":48},"dt":1464076525,"sys":{"message":0.0025,"country":"RU","sunrise":1464053115,"sunset":1464110798},"id":487928,"name":"Staryy Oskol","cod":200}


Weather
id: 802
main: Clouds
description: scattered clouds
icon: 03d
temp: 18 celsius
humidity: 92 %
pressure: 997 hPa or 747 mmHg
wind's speed: 2
wind's direction: 31

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

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

я 07 ту что с внешней антенкой прошил так. 

scheme.jpg

 

 

Изменено пользователем svchekalin
канденсатор не той емкасти
  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

@Alexander Воспользуйтесь библиотекой LiquidCrystal_I2C

Чтобы вывести что-то на дисплей имеются стандартные функции

lcd.setCursor(0,2);       // Выставить позицию
lcd.print(weather.temp);  // Вывести температуру

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

@Kitsum А если сервер в ответ присылает строку вот такого вида  -  hostname:192.169.0.103;dhtt1:61.0;dhth1:30.0;dsw1:-3.0;  её с помощью ArduinoJson разобрать не получиться.?!

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

@EndWar формат json имеет строгий синтаксис. Отталкиваясь от этого, Ваша строка должна иметь следующий вид

{"hostname":"192.169.0.103","dhtt1":61,"dhth1":30,"dsw1":-3}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Не подскажете, что нужно изменить дабы запрос информации с сервера производился не каждые 10 мин, а каждый час?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

@В К Найдите строку

postingInterval = find ? 600L * 1000L : 60L * 1000L;

и замените ее на

postingInterval = find ? 3600L * 1000L : 60L * 1000L;

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

спасибо большое за Ваш код. Скопировал себе, поменял настройки WiFi, координаты и API ключ, прошил, но в ответ получил Connecting successfully, code 401. Что это означает? 

image.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас

  • Похожие публикации

    • Автор: Kitsum
      Просмотреть файл [esp8266] Библиотека CMD, реализует настройку микроконтроллера и управление вашей программой через терминал.
      Основная задача библиотеки, это прием пользовательских команд через UART интерфейс, их обработка и выполнение пользовательского кода, связанного с той или иной командой.
      Данная библиотека позволяет реализовать:
      Управление микроконтроллером Любую настройку, будь то WiFi, другие библиотеки или часть Вашей программы Вызывать Ваши задачи (функции) из терминала по команде и передавать им требуемые параметры Использовать контроллер в качестве шлюза между датчиками и программами на PC Внимание: любая команда, передаваемая в терминал обязана заканчиваться символом перевода строки "\n".
      Подключение библиотеки
      #include <cmd.h> Инициализация объекта, к которому мы будем обращаться для добавления команд. В качестве параметра объекту необходимо передать указатель на объект Serial или любой другой схожий по типу интерфейс.
      cmd command(&Serial); В функции Setup описываем какие команды требуется обрабатывать. Например, по команде "test" вызывать пользовательскую функцию с именем "myFunctionName". Имя пользовательской функции может быть абсолютно любым.
      void Setup() { Serial.begin(115200); command.add("test", myFunctionName); } Пользовательская функция будет вызываться каждый раз, когда по интерфейсу Serial поступит команда "test". Если команда будет передана с параметрами, то эти параметры будут переданы в качестве аргументов пользовательской функции.
      В функции loop должна находится команда вызова обработчика.
      void loop() { command.handleEvents(); } Пользовательская функция обязана соответствовать ряду требований:
      Не возвращать никакого результата (быть объявленной с типом void) Принимать в качестве первого аргумента переменную с типом byte в которой будет храниться число равное количеству переданных параметров Принимать в качестве второго параметра переменную с типом char** в которой будет храниться указатель на массив со всеми указателями (char*) на переданные параметры void myFunctionName(byte argc, char** argv) { /* ... */ } Функция всегда должна иметь такой вид, даже если не подразумевается, что ей будут передаваться какие-либо параметры.
      Чтобы перебрать все переданные параметры и вывести их в консоль, можно воспользоваться следующим примером
      void myFunctionName(byte argc, char** argv) { if (0 < argc) { for (uint8_t i = 0; i < argc; i++) { Serial.printf("%i. %s\n", i, argv[i]); } } } Пример вызова пользовательской функции без параметров и с ними
      # test No parameter was passed # test p1 p2 p3 p4 p5 0. p1 1. p2 2. p3 3. p4 4. p5 Помните, что параметры представлены в виде указателей и работать с ними нужно как с обычными переменными не получится т.к указатель содержит не значение переменной (переданный параметр), а указатель на ту область памяти микроконтроллера в которой это значение находится.
      Чтобы сравнить два значения, например, параметр под индексом 0 (идет первым в списке) с каким-либо значением в программе, воспользуйтесь функцией strcmp, которая возвращает целочисленное значение, указывающее на лексическое расхождение строк. Если строки равны, то возвращаемое значение равно 0.
      if (!strcmp(argv[0], "wifi")) { Serial.println(F("Первый аргумент WiFi")); } else { Serial.println(F("Первый аргумент НЕ WiFi!!!")); } Для копирования значения указателя в другую переменную с типом char можно воспользоваться функцией strcpy
      char myVar[20]; strcpy(myVar, argv[0]); if (myVar == "123456") { Serial.prinln(F("ok")); } Также можно обернуть указатель объектом String и получить весь функционал этого объекта, который будет содержать значение параметра
      String param1(argv[0]); // String param1 = argv[0]; Serial.printf("argv[0] length: %i\n", param1.length()); Serial.printf("argv[0] is integer?: %s\n", param1.toInt() ? "YES" : "NO"); if (param1 == "qwerty") { Serial.println(F("Hello QWERTY!")); } С библиотекой идут несколько примеров, в том числе и пример конфигурации WiFi в режиме STA.
      Автор Kitsum Добавлен 05.12.2018 Категория Библиотеки  
    • Автор: Kitsum
      Просмотреть файл [esp8266] Библиотека smartBlink, реализует умное управление штатным светодиодом, что позволяет добавить индикацию состояния вашей программы или микроконтроллера.
      Основная задача библиотеки, это добавление индикации состояния Вашей программы или микроконтроллера. Отображение состояния производится посредством светодиода. Что самое важное, работа библиотеки через прерывание, это позволяет ей поддерживать индикацию даже в то время, когда выполняется длительный код основной программы. Например, Вы можете использовать её для отображения в каком режиме сейчас работает WiFi микроконтроллера, STA или AP и т.д. Или ход выполнения какой-либо операции, например, передача данных на внешний сервер.
      Подключение библиотеки
      #include <smartBlink.h> Чтобы инициализировать управление светодиодом необходимо создать объект, через который мы буем задавать режимы работы индикации.
      smartBlink::smartBlink(byte gpio, bool on = LOW); Объекту необходимо передать два параметра, первый это номер порта, на котором находится светодиод, а второй это уровень логического сигнала, который заставит светодиод работать. Сигнал может быть низким (LOW) или высоким (HIGH), это зависит от схемотехники подключения светодиода.
      Например, штатный светодиод модуля ESP12, использующий GPIO2 (порт 2) можно объявить следующим образом.
      #define led2_pin 2 #define led2_on_signal LOW smartBlink led2(led2_pin, led2_on_signal); Теперь можно в основной программе использовать метод устанавливающий какой режим индикации использовать.
      smartBlink::setMode(mode_t mode); Например, зададим режим светодиода led2 в котором светодиод будет давать одну короткую вспышку раз в секунду.
      led2.setMode(smartBlink::mode_flash1); Режимов работы может быть несколько.
      led2.setMode(smartBlink::mode_off); led2.setMode(smartBlink::mode_flash1); led2.setMode(smartBlink::mode_flash2); led2.setMode(smartBlink::mode_flash3); led2.setMode(smartBlink::mode_flash4); led2.setMode(smartBlink::mode_burn); led2.setMode(smartBlink::mode_inhalf); Чтобы вернуть предыдущий режим индикации для ранее объявленного светодиода led2 используйте следующий метод
      led2.previous(); Благодаря работе библиотеки через прерывания по таймеру, индикация будет работать даже в тех случаях, когда выполняется долгий код.
      С библиотекой идут несколько примеров.
      Автор Kitsum Добавлен 10.12.2018 Категория Библиотеки  
    • Автор: Kitsum
      Основная задача библиотеки, это добавление индикации состояния Вашей программы или микроконтроллера. Отображение состояния производится посредством светодиода. Что самое важное, работа библиотеки через прерывание, это позволяет ей поддерживать индикацию даже в то время, когда выполняется длительный код основной программы. Например, Вы можете использовать её для отображения в каком режиме сейчас работает WiFi микроконтроллера, STA или AP и т.д. Или ход выполнения какой-либо операции, например, передача данных на внешний сервер.
      Подключение библиотеки
      #include <smartBlink.h> Чтобы инициализировать управление светодиодом необходимо создать объект, через который мы буем задавать режимы работы индикации.
      smartBlink::smartBlink(byte gpio, bool on = LOW); Объекту необходимо передать два параметра, первый это номер порта, на котором находится светодиод, а второй это уровень логического сигнала, который заставит светодиод работать. Сигнал может быть низким (LOW) или высоким (HIGH), это зависит от схемотехники подключения светодиода.
      Например, штатный светодиод модуля ESP12, использующий GPIO2 (порт 2) можно объявить следующим образом.
      #define led2_pin 2 #define led2_on_signal LOW smartBlink led2(led2_pin, led2_on_signal); Теперь можно в основной программе использовать метод устанавливающий какой режим индикации использовать.
      smartBlink::setMode(mode_t mode); Например, зададим режим светодиода led2 в котором светодиод будет давать одну короткую вспышку раз в секунду.
      led2.setMode(smartBlink::mode_flash1); Режимов работы может быть несколько.
      led2.setMode(smartBlink::mode_off); led2.setMode(smartBlink::mode_flash1); led2.setMode(smartBlink::mode_flash2); led2.setMode(smartBlink::mode_flash3); led2.setMode(smartBlink::mode_flash4); led2.setMode(smartBlink::mode_burn); led2.setMode(smartBlink::mode_inhalf); Чтобы вернуть предыдущий режим индикации для ранее объявленного светодиода led2 используйте следующий метод
      led2.previous(); Благодаря работе библиотеки через прерывания по таймеру, индикация будет работать даже в тех случаях, когда выполняется долгий код.
      С библиотекой идут несколько примеров.
    • Автор: Kitsum
      Просмотреть файл [esp8266] Библиотека Cron, реализует планировщик задач для периодического выполнения пользовательских функций.
      Основная задача библиотеки, это вызов пользовательских функций через установленный интервал времени. Библиотека работает по схожему принципу с широко известной программой Cron распространяемой в составе UNIX систем. От этой утилиты библиотека и унаследовала название.
      Библиотека работает исходя из принципов однопоточного выполнения кода в микроконтроллере. Когда обработчик библиотеки получает процессорное время, он проверяет список всех пользовательских задач в поиске задач, которые необходимо выполнить, основываясь на установленном интервале времени для каждой задачи.
      Данная библиотека предоставляет следующий функционал
      Позволяет добавлять большое количество пользовательских заданий в виде функций. Количество задач ограничено только их сложностью и свободной памятью микроконтроллера. Предоставляет возможность холодного старта задачи. Дает возможность вызова задачи при старте микроконтроллера с последующим выполнением задачи через установленный интервал времени. Поиск задачи по лексическому идентификатору. Получение время последнего вызова задачи. Обнуление интервала вызова задачи или установку нового интервала в мс. Останавливать задачу на неопределенный срок. Проверять активность задачи. Подключение библиотеки
      #include <cron.h> Пример добавление задачи, которая вызывает функцию blink_f каждую секунду
      cron.add(1000, blink_f); Добавление этой же задачи в режиме холодного старта
      cron.add(1000, blink_f, true); Добавление задачи и присвоение ей человек понятного идентификатора
      cron.add(1000, blink_f, "Blink"); Добавление задачи с холодным стартом и присвоением ей человек понятного идентификатора
      cron.add(1000, blink_f, "Blink", true); В качестве временного интервала вызова задачи необходимо указывать количество миллисекунд. Но можно воспользоваться готовыми константами.
      Фундаментальные константы
      cron::second cron::minute cron::hour cron::day Самые распространенные значения
      cron::time_1s cron::time_5s cron::time_10s cron::time_15s cron::time_30s cron::time_1m cron::time_5m cron::time_10m cron::time_15m cron::time_30m cron::time_1h cron::time_5h cron::time_10h cron::time_12h cron::time_1d С константами можно производить арифметические операции чтобы получить необходимые временные интервалы.
      cron.update("Blink", cron::time_1s); cron.update("Blink", cron::time_1s * 12); cron.update("Blink", cron::time_30s + 500); и т.д
      В функции loop должна находится команда вызова обработчика.
      void loop() { cron.handleEvents(); } Поиск задачи по установленному ранее идентификатору
      cron.find("Blink"); В ответ возвращается объект типа cronEvent который содержит все данные задачи или 0 если задача не была найдена. Можно использовать в качестве простой проверки.
      if (cron.find("Blink")) { /* … */ } Следующий метод позволяет получить время последнего вызова задачи
      uint32_t time = cron.lastRun("Blink"); В качестве параметра можно передать идентификатор с типом cronEvent полученный с помощью метода поиска задачи.
      Перезапуск таймера задачи производится следующим образом
      cron.update("Blink"); А так можно установить новый интервал вызова задачи
      cron.update("Blink", cron::time_10m); Остановка выполнения задачи
      cron.stop("Blink"); Проверка активности задачи
      bool active = cron.isActive("Blink"); С библиотекой идут несколько примеров.
      Автор Kitsum Добавлен 09.12.2018 Категория Библиотеки  
    • Автор: Kitsum
      Основная задача библиотеки, это вызов пользовательских функций через установленный интервал времени. Библиотека работает по схожему принципу с широко известной программой Cron распространяемой в составе UNIX систем. От этой утилиты библиотека и унаследовала название.
      Библиотека работает исходя из принципов однопоточного выполнения кода в микроконтроллере. Когда обработчик библиотеки получает процессорное время, он проверяет список всех пользовательских задач в поиске задач, которые необходимо выполнить, основываясь на установленном интервале времени для каждой задачи.
      Данная библиотека предоставляет следующий функционал
      Позволяет добавлять большое количество пользовательских заданий в виде функций. Количество задач ограничено только их сложностью и свободной памятью микроконтроллера. Предоставляет возможность холодного старта задачи. Дает возможность вызова задачи при старте микроконтроллера с последующим выполнением задачи через установленный интервал времени. Поиск задачи по лексическому идентификатору. Получение время последнего вызова задачи. Обнуление интервала вызова задачи или установку нового интервала в мс. Останавливать задачу на неопределенный срок. Проверять активность задачи. Подключение библиотеки
      #include <cron.h> Пример добавление задачи, которая вызывает функцию blink_f каждую секунду
      cron.add(1000, blink_f); Добавление этой же задачи в режиме холодного старта
      cron.add(1000, blink_f, true); Добавление задачи и присвоение ей человек понятного идентификатора
      cron.add(1000, blink_f, "Blink"); Добавление задачи с холодным стартом и присвоением ей человек понятного идентификатора
      cron.add(1000, blink_f, "Blink", true); В качестве временного интервала вызова задачи необходимо указывать количество миллисекунд. Но можно воспользоваться готовыми константами.
      Фундаментальные константы
      cron::second cron::minute cron::hour cron::day Самые распространенные значения
      cron::time_1s cron::time_5s cron::time_10s cron::time_15s cron::time_30s cron::time_1m cron::time_5m cron::time_10m cron::time_15m cron::time_30m cron::time_1h cron::time_5h cron::time_10h cron::time_12h cron::time_1d С константами можно производить арифметические операции чтобы получить необходимые временные интервалы.
      cron.update("Blink", cron::time_1s); cron.update("Blink", cron::time_1s * 12); cron.update("Blink", cron::time_30s + 500); и т.д
      В функции loop должна находится команда вызова обработчика.
      void loop() { cron.handleEvents(); } Поиск задачи по установленному ранее идентификатору
      cron.find("Blink"); В ответ возвращается объект типа cronEvent который содержит все данные задачи или 0 если задача не была найдена. Можно использовать в качестве простой проверки.
      if (cron.find("Blink")) { /* … */ } Следующий метод позволяет получить время последнего вызова задачи
      uint32_t time = cron.lastRun("Blink"); В качестве параметра можно передать идентификатор с типом cronEvent полученный с помощью метода поиска задачи.
      Перезапуск таймера задачи производится следующим образом
      cron.update("Blink"); А так можно установить новый интервал вызова задачи
      cron.update("Blink", cron::time_10m); Остановка выполнения задачи
      cron.stop("Blink"); Проверка активности задачи
      bool active = cron.isActive("Blink"); С библиотекой идут несколько примеров.
    • Автор: Kitsum
      Основная задача библиотеки, это прием пользовательских команд через UART интерфейс, их обработка и выполнение пользовательского кода, связанного с той или иной командой.
      Данная библиотека позволяет реализовать:
      Управление микроконтроллером Любую настройку, будь то WiFi, другие библиотеки или часть Вашей программы Вызывать Ваши задачи (функции) из терминала по команде и передавать им требуемые параметры Использовать контроллер в качестве шлюза между датчиками и программами на PC Внимание: любая команда, передаваемая в терминал обязана заканчиваться символом перевода строки "\n".
      Подключение библиотеки
      #include <cmd.h> Инициализация объекта, к которому мы будем обращаться для добавления команд. В качестве параметра объекту необходимо передать указатель на объект Serial или любой другой схожий по типу интерфейс.
      cmd command(&Serial); В функции Setup описываем какие команды требуется обрабатывать. Например, по команде "test" вызывать пользовательскую функцию с именем "myFunctionName". Имя пользовательской функции может быть абсолютно любым.
      void Setup() { Serial.begin(115200); command.add("test", myFunctionName); } Пользовательская функция будет вызываться каждый раз, когда по интерфейсу Serial поступит команда "test". Если команда будет передана с параметрами, то эти параметры будут переданы в качестве аргументов пользовательской функции.
      В функции loop должна находится команда вызова обработчика.
      void loop() { command.handleEvents(); } Пользовательская функция обязана соответствовать ряду требований:
      Не возвращать никакого результата (быть объявленной с типом void) Принимать в качестве первого аргумента переменную с типом byte в которой будет храниться число равное количеству переданных параметров Принимать в качестве второго параметра переменную с типом char** в которой будет храниться указатель на массив со всеми указателями (char*) на переданные параметры void myFunctionName(byte argc, char** argv) { /* ... */ } Функция всегда должна иметь такой вид, даже если не подразумевается, что ей будут передаваться какие-либо параметры.
      Чтобы перебрать все переданные параметры и вывести их в консоль, можно воспользоваться следующим примером
      void myFunctionName(byte argc, char** argv) { if (0 < argc) { for (uint8_t i = 0; i < argc; i++) { Serial.printf("%i. %s\n", i, argv[i]); } } } Пример вызова пользовательской функции без параметров и с ними
      # test No parameter was passed # test p1 p2 p3 p4 p5 0. p1 1. p2 2. p3 3. p4 4. p5 Помните, что параметры представлены в виде указателей и работать с ними нужно как с обычными переменными не получится т.к указатель содержит не значение переменной (переданный параметр), а указатель на ту область памяти микроконтроллера в которой это значение находится.
      Чтобы сравнить два значения, например, параметр под индексом 0 (идет первым в списке) с каким-либо значением в программе, воспользуйтесь функцией strcmp, которая возвращает целочисленное значение, указывающее на лексическое расхождение строк. Если строки равны, то возвращаемое значение равно 0.
      if (!strcmp(argv[0], "wifi")) { Serial.println(F("Первый аргумент WiFi")); } else { Serial.println(F("Первый аргумент НЕ WiFi!!!")); } Для копирования значения указателя в другую переменную с типом char можно воспользоваться функцией strcpy
      char myVar[20]; strcpy(myVar, argv[0]); if (myVar == "123456") { Serial.prinln(F("ok")); } Также можно обернуть указатель объектом String и получить весь функционал этого объекта, который будет содержать значение параметра
      String param1(argv[0]); // String param1 = argv[0]; Serial.printf("argv[0] length: %i\n", param1.length()); Serial.printf("argv[0] is integer?: %s\n", param1.toInt() ? "YES" : "NO"); if (param1 == "qwerty") { Serial.println(F("Hello QWERTY!")); } С библиотекой идут несколько примеров, в том числе и пример конфигурации WiFi в режиме STA.
  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу.

×