Чтение погоды с погодных серверов

> [HTML Version](weather.html)

В Simple-Scada можно выполнять [HTTP POST/GET/PUT запросы](tmhttp.md) к сторонним серверам для чтения данных с них. Ниже рассмотрены примеры получения данных с некоторых популярных погодных серверов.

**Примеры скриптов**

**(./images/tog_code_1.png) 1. Погода с weatherstack.com [(./images/link.png)](https://simple-scada.com/help/script/weather.html?anchor=weath1)**

Сайт weatherstack.com имеет удобный API для чтения погодных данных. После регистрации на сайте вы получите уникальный ключ доступа (API Access Key), который нужно использовать в GET-запросах для получения данных о погоде. В документации weatherstack смотрим примеры запросов и составляем запрос, например для Москвы он должен быть таким:

````
http://api.weatherstack.com/current?access\_key=API\_ACCESS\_KEY\&query=Moscow

````
, вместо API\_ACCESS\_KEY нужно вставить полученный при регистрации ключ доступа. Обратите внимание, если требуется передать параметр содержащий пробел, например "New York", то пробел нужно заменить на "%20", т.е. "New%20York". Убедиться в правильности составленного запроса можно вставив его в адресную строку браузера:

_(./images/weather_1.png)_



Браузер отобразил ответ с корректными данными, значит запрос составлен правильно. Как видно, ответ передается в формате JSON, позже мы извлечем из него нужные нам свойства. Теперь можно приступить к решению задачи в Simple-Scada. Сначала создадим интерфейс в проекте. Температуру и местное время будем выводить в компоненты Текст. А дополнительные параметры "ветер", "давление" и "влажность" выведем в компонент Таблица. На изображении ниже показан созданный интерфейс и имена, которые мы дали компонентам:

_(./images/weather_2.png)_



Интерфейс готов. Сделаем так, чтобы погода обновлялась сразу после запуска проекта, а затем через каждые 10 минут. Для этого [создадим новый скрипт](via-script-editor.md) с типом события "[Таймер](second-passed.md)" - в параметре скрипта "Интервал" укажем значение 600 секунд и активируем опцию "Выполнить сразу после запуска проекта". Напишем код скрипта:

````
var  
  aHTTP: TM\_HTTP;  
  aQuery: string;  
begin  
  // формируем текст HTTP запроса  
  aQuery := 'http://api.weatherstack.com/current?access\_key=' +  
    'здесь должен быть ваш API ключ доступа' +  // \!\!\!  
    '\&query=Moscow';  
  
  aHTTP := RequestHTTP;     // создаём экземпляр запроса  
  aHTTP.Get(aQuery, 77);    // вызываем GET с запросом aQuery и отмечаем его тегом = 77  
end.

````


Данный скрипт будет выполнять HTTP GET запрос через каждые 10 минут. Мы отметили запрос тегом равным 77, чтобы не перепутать его с другими запросами при обработке ответа. Теперь [создадим новый скрипт](via-script-editor.md) с типом события "[Выполнен HTTP запрос](postgetcompleted.md)". Такой скрипт будет вызываться при выполнении любого HTTP запроса, а параметр Response будет содержать ответ сервера. Известно, что сервер возвращает ответ в формате JSON. Текущая температура вложена в объект "current" и имеет имя "temperature". Чтобы получить ее значение, в коде скрипта нужно написать: Response\['current'\]\['temperature'\]. Simple-Scada автоматически извлечет значение свойства из JSON-строки. Аналогично извлекаем другие интересующие нас параметры и выводим их в компоненты Текст и Таблица. В результате код скрипта будет таким:

````
begin  
  // если это результат выполнения запроса с тегом 77  
  if Response.Tag = 77 then  
  begin  
    txtLocalTime.Text := Response\['location'\]\['localtime'\].AsStr;  
    txtTemperature.Text := Response\['current'\]\['temperature'\].AsStr + ' °С';  
    tblWeather.GetCell(0, 1).Text := Response\['current'\]\['wind\_speed'\].AsStr + ' км/ч';  
    tblWeather.GetCell(1, 1).Text := Response\['current'\]\['pressure'\].AsStr + ' мбар';  
    tblWeather.GetCell(2, 1).Text := Response\['current'\]\['humidity'\].AsStr + ' %';  
  end;  
end.

````
Запускаем проект и смотрим результат. Значения считались сразу после запуска, а затем обновляются через каждые 10 минут:

_(./images/weather_3.png)_

**(./images/tog_code_1.png) 2. Погода с openweathermap.org [(./images/link.png)](https://simple-scada.com/help/script/weather.html?anchor=weath2)**

Принцип тот же, что и в первом примере. Регистрируемся на сайте openweathermap.org, получаем ключ доступа и выполняем запросы погоды. Отличие только в форме запроса. Вот пример запроса для чтения текущей погоды:

````
     // формируем текст HTTP запроса  
    aQuery := 'http://api.openweathermap.org/data/2.5/weather?q=Moscow,RU\&appid=' +  
      'здесь должен быть ваш API ключ доступа' +  // \!\!\!  
      '\&units=metric';
````

````
**(./images/tog_code_1.png) 3. Погода с accuweather.com [(./images/link.png)](https://simple-scada.com/help/script/weather.html?anchor=weath3)**

Принцип тот же, что и в первом примере. Регистрируемся на сайте. Добавляем новое приложение и получаем API Key. Текст запроса для получения текущей погоды с accuweather.com выглядит так:

````
   aQuery := 'http://dataservice.accuweather.com/currentconditions/v1/294021?apikey=' +  
    'здесь должен быть ваш API ключ доступа' +  // \!\!\!  
    '\&language=ru-RU';
````

````
**(./images/tog_code_1.png) 4. Погода с Яндекс.Погода [(./images/link.png)](https://simple-scada.com/help/script/weather.html?anchor=weath4)**

Для примера рассмотрим использование тарифа "[Погода на вашем сайте](https://yandex.ru/dev/weather/doc/ru/concepts/forecast-info)". Сначала необходимо зарегистрироваться на сайте "API Яндекс Погоды" и получить ключ API. Запросы для "Яндекс Погоды" должны содержать заголовок "X-Yandex-Weather-Key" со значением ключа API. Запросы осуществляются через HTTPS, поэтому нужно добавить в запрос заголовок и включить SSL. 

Cогласно документации "API Яндекс Погоды" формируем GET-запрос и проверяем его в браузере, например через сервис [REQBIN](https://reqbin.com/post-online):

_(./images/ya1.png)_



Ошибок при выполнении запроса не возникло, мы получили корректные данные в ответ, значит запрос составлен правильно. Теперь можно приступить к решению задачи в Simple-Scada. Сначала создадим интерфейс для отображения нужной нам информации. Температуры и описание погоды будем выводить на мнемосхему при помощи компонента "[Текст](https://simple-scada.com/help/manual/text.html)". Ветер, давление и влажность отобразим через компонент "[Таблица](https://simple-scada.com/help/manual/table.html)". На изображении ниже показан созданный интерфейс и имена, которые были назначены объектам:

_(./images/ya2.png)_



Интерфейс готов. Реализуем обновление погоды при запуске проекта, а затем раз в час. Для этого [создадим новый скрипт](via-script-editor.md) с типом события "[Начало часа](hour-passed.md)" и активируем опцию "Выполнить сразу после запуска проекта". Напишем код скрипта:

````
var  
  aHTTP: TM\_HTTP;  
  aQuery: string;  
begin  
  // формируем текст HTTP запроса  
  aQuery := 'https://api.weather.yandex.ru/v2/informers?lat=43.5992\&lon=39.7257';  
  aHTTP := RequestHTTP;     // создаем экземпляр запроса  
  aHTTP.SetSSL;             // включаем SSL  
  aHTTP.SetHeader('X-Yandex-Weather-Key', 'здесь должен быть ваш API ключ доступа');     // добавляем заголовок с ключом API  
  aHTTP.Get(aQuery, 77);    // вызываем GET с запросом aQuery и отмечаем его тегом = 77  
end.

````
Данный скрипт будет выполнять HTTP GET запрос раз в час. Мы отметили запрос тегом равным 77, чтобы не перепутать его с другими запросами при обработке ответа. Теперь [создадим новый скрипт](via-script-editor.md) с типом события "[Выполнен HTTP запрос](postgetcompleted.md)". Такой скрипт будет вызываться при выполнении любого HTTP запроса, а параметр Response будет содержать ответ сервера. Нам известно, что сервер возвращает ответ в формате JSON. Вся интересующая нас информация о текущей погоде хранится в объекте "fact". Поэтому сначала извлекаем массив "fact" и далее получаем нужные нам параметры. В результате код скрипта будет таким:

````
var  
  aResult: string;  
  aFact : TM\_JSONNode;  
begin  
  // если это результат выполнения запроса с тегом 77  
  if Response.Tag = 77 then  
  begin  
    aFact := Response\['fact'\]; // извлекаем массив "fact" в aFact  
    txtTemp.Text :=  aFact\['temp'\].AsStr + ' °С';  
    txtFeelsLike.Text := 'Ощущается как: ' + aFact\['temp'\].AsStr + ' °С';  
    tblWeather.GetCell(0, 1).Text := aFact\['wind\_speed'\].AsStr + ' м/сек';  
    tblWeather.GetCell(1, 1).Text := aFact\['pressure\_mm'\].AsStr + ' мм рт. ст.';  
    tblWeather.GetCell(2, 1).Text := aFact\['humidity'\].AsStr + ' %';  
  
    // параметр "feels\_like" возвращается только для населенных пунктов, где данная информация актуальна  
    txtTempWater.Text := 'Температура воды: ' + aFact\['feels\_like'\].AsStr + ' °С';  
  
    // сохраняем "код погодного описания" в переменную для дальнейшего преобразования  
    vrCondition.Value := aFact\['condition'\].AsStr;  
  end;  
end.   ````
                  

Теперь можно создать скрипт для расшифровки погодного описания, который сохраняется в переменную "vrCondition". Для этого связываем переменную "vrCondition" с компонентом "Текст" с именем "txtCondition" и на событие "[OnDataChange](by-obj-event.md)" пишем следующий код:

````
 procedure TextCondition(Kode, WeathDesc: string);  
 var AVarVal: string;  
 begin  
   AVarVal := (Sender as TM\_Text).Variable.AsStr;  
   if AVarVal = Kode then  
     (Sender as TM\_Text).Text := WeathDesc;  
 end;  
  
begin  
  if Sender is TM\_Text then   // проверяем, что Sender это текст  
    with Sender as TM\_Text do // приводим Sender к типу "TM\_Text"  
    begin  
      Text := 'Неизвестно...';  
      TextCondition('clear', 'Ясно');  
      TextCondition('partly-cloudy', 'Малооблачно');  
      TextCondition('cloudy', 'Облачно с прояснениями');  
      TextCondition('overcast', 'Пасмурно');  
      TextCondition('partly-cloudy-and-light-rain', 'Малооблачно, небольшой дождь');  
      TextCondition('partly-cloudy-and-rain', 'Малооблачно, дождь');  
      TextCondition('overcast-and-rain', 'Значительная облачность, сильный дождь');  
      TextCondition('overcast-thunderstorms-with-rain', 'Сильный дождь с грозой');  
      TextCondition('cloudy-and-light-rain', 'Облачно, небольшой дождь');  
      TextCondition('overcast-and-light-rain', 'Значительная облачность, небольшой дождь');  
      TextCondition('cloudy-and-rain', 'Облачно, дождь');  
      TextCondition('overcast-and-wet-snow', 'Дождь со снегом');  
      TextCondition('partly-cloudy-and-light-snow', 'Небольшой снег');  
      TextCondition('partly-cloudy-and-snow', 'Малооблачно, снег');  
      TextCondition('overcast-and-snow', 'Снегопад');  
      TextCondition('cloudy-and-light-snow', 'Облачно, небольшой снег');  
      TextCondition('overcast-and-light-snow', 'Значительная облачность, небольшой снег');  
      TextCondition('cloudy-and-snow', 'Облачно, снег');  
    end;  
end.

````
Проект готов, можно его запустить и посмотреть результат: 

_(./images/ya3.png)_

