Погода в проекте

Автор vyacheslav, 17 марта 2018, 11:46:45

Eugene_

#15
проблема при чтении с accuweather.com из примеров.
Релиз SCADA последний. Не срабатывает парсинг ответа сервера, вот реальный пример ответа скопированный из буфера response, совпадает с ответом в ЛК сайта accuweather.com:
[
  {
    "LocalObservationDateTime": "2021-08-05T17:25:00+04:00",
    "EpochTime": 1628169900,
    "WeatherText": "Sunny",
    "WeatherIcon": 1,
    "HasPrecipitation": false,
    "PrecipitationType": null,
    "IsDayTime": true,
    "Temperature": {
      "Metric": {
        "Value": 37.8,
        "Unit": "C",
        "UnitType": 17
      },
      "Imperial": {
        "Value": 100,
        "Unit": "F",
        "UnitType": 18
      }
    },
    "MobileLink": "http://www.accuweather.com/en/ae/sharjah/321623/current-weather/321623?lang=en-us",
    "Link": "http://www.accuweather.com/en/ae/sharjah/321623/current-weather/321623?lang=en-us"
  }
]

Eugene_

#16
Вариант  txtTemperature.Text := Response['Temperature']['Metric']['Value'].AsStr + ' °С'; не срабатывает, если сделать просто txtTemperature.Text := Response.Text то в текстовом поле ответ сервера появляется, то есть проблем с авторизацией нет.

При этом - если поднять свой сервер и он дает такой ответ в буфер Response, то парсинг работает. Дело в скобках [] в ответе может ?
Ответ:
{
   "buffer0":x,
   "buffer1":y
}


Eugene_

#17
Верно, дело в скобках.
с openweathermap.org - возвращает {} пары имя: значение. парсинг из текста выше работает.
с accuweather.com - возвращает [] массив данных

Как разобрать верно ответ с массивом средствами SCADA ?
мануал по JSON https://www.w3bai.com/ru/json/json_syntax.html

Работает, вопрос закрыт. Ниже код на выбор с двух серверов, vrWeather_Temperature для архивирования
Код: pascal
begin
  // если это результат выполнения запроса с тегом 666
  if Response.Tag = 666 then
  begin

    //  https://accuweather.com
    txtLocalTime.Text := Response.Nodes[0]['LocalObservationDateTime'].AsStr;
    vrWeather_Temperature.Value := Response.Nodes[0]['Temperature']['Metric']['Value'].AsFloat;
    txtTemperature.Text := UTF8ToString(FloatToStr(vrWeather_Temperature.Value,1)) + ' °С';

    {
    //  https://home.openweathermap.org
    txtLocalTime.Text := TimeToStr(Now);
    vrWeather_Temperature.Value :=  Response['main']['temp'].AsFloat;
    txtTemperature.Text := UTF8ToString(FloatToStr(vrWeather_Temperature.Value,1)) + ' °С';
    }
  end;
end.

Simple-Scada

#18
Обратите внимание, ответ от сервера пришёл внутри квадратных скобок [], которые указывают на то, что это массив данных, а внутри квадратных скобок элементы массива (в Вашем случае элементами массива являются объекты и массив состоит из одного элемента). При обращении к элементам массива нужно указывать индекс элемента. А при обращении к ключам объекта нужно указывать имя ключа. Поэтому код должен выглядеть следующим образом:
Код: pascal
xtTemperature.Text:= Response.Nodes[0]['Temperature']['Metric']['Value'].AsStr + ' °С';
Описание разбора JSON с примерами есть в руководстве по этой ссылке. Там же описан пример прохода по элементам массива в цикле (на случай, если массив приходит от сервера с разным количеством элементов).

Eugene_

#19
Спасибо, да , уже сам разобрался - долго правил ответ в форуме  :)

Eugene_

прошу посмотреть обработку HTTP запросов. С самого момента появления этой функции периодически наблюдается ошибка как на картинке ниже. Проявляется редко - раз в 2-3 недели, пару раз приводило к полному отказу скрипта, приходилось перезагружать сервис SCADA.
В тексте выдается ошибка на строку 13, но если подставить любую другую строку разбора ответа поведение не меняется. Полагаю такое происходит в том случае, если внешний сервер погоды вернул ответ "ok 200" на запрос, но тело ответа пустое и парсить скрипту SCADA нечего. Может добавите какое-то условие предпроверки внутри процедуры разбора ответа , к примеру длинна > Х символов и т.д. ?

Simple-Scada

Здравствуйте.

В данном случае все работает в соответствии с кодом скрипта. Вы в коде скрипта сначала обращаетесь к полям ответа Response[], не проверяя был ли ответ. Если его не было (например, связь с HTTP-сервером была разорвана), то скрипт попытается обратиться к несуществующим полям ответа. Поэтому сначала проверьте код ответа "if Response.Code = 200 then", а затем уже извлекайте данные из ответа.
Также, если Вы считаете, что HTTP-сервер на один и тот же запрос может вернуть ответ с разным набором полей (что неправильно со стороны HTTP-сервера), то в скриптах можно проверить существование любых полей в ответе, прежде чем обращаться к ним. Например:
Код: pascal
var
  aValue: string;
  aNode: TM_JSONNode;
begin
  aNode := Response['current'];  // получаем поле "current" из ответа HTTP-сервера
  if aNode <> nil then           // если такое поле действительно существует
    aValue := aNode.AsStr;       // то читаем из него значение
end.

Цитироватьпару раз приводило к полному отказу скрипта, приходилось перезагружать сервис SCADA.
Данная ошибка на 100% не может никак повлиять на работу сервера скады. Отказ скрипта явно был вызван чем-то другим.

Eugene_

#22
да, скорее всего так и придется переделать. спасибо.

Уточнение - aNode при каждом вызове изменяет (обновляет) состояние в этом примере ?
То есть такой вариант возможен ?
Код: pascal
begin
  aNode := Response['X1'];  
  if aNode <> nil then  aValue1 := aNode.AsStr;  
 
  aNode := Response['X2'];  
  if aNode <> nil then  aValue2 := aNode.AsStr;   

  aNode := Response['X3'];  
  if aNode <> nil then  aValue3 := aNode.AsStr;      
end.

Simple_Scada

Да, такой вариант возможен.

Eugene_

Иногда конструкция IntToStr (Response.Code) возвращает строку "-1", а не "200". В списке ответов на HTTP запрос такого кода нету. Подскажите, как можно интерпретировать такое значение ?

Simple-Scada

#25
Значение -1 говорит о том, что никакого ответа не было. Например, если разорвать сеть между скадой и HTTP-сервером, а затем попытаться выполнить запрос, то HTTP сервер не сможет ответить, скада дождётся таймаута и вернёт код -1.

vigorts

#26
Здравствуйте. Подскажите пожалуйста , что за ошибка такая. Скрипт компиляцию проходит, а сервер ругается. (Яндекс погода).

Simple_Scada

Здравствуйте.

Ошибка говорит о том, что в скрипте выполняется обращение по несуществующему указателю(в ответе сервера нет данных для полей "['location']['localtime']"). На Вашем скриншоте приведен код из примера чтения погоды с weatherstack.com. Но если Вы читаете погоду с Яндекс.Погода, то очевидно, что данный код не будет работать, т.к. это пример для weatherstack. У каждого погодного сервера свой API, свойства в котором могут именоваться по разному. По аналогии с примером для weatherstack, сначала составьте запрос и протестируйте его через браузер, получите ответ от сервера, посмотрите какие свойства он возвращает и используйте необходимые свойства при обработке ответа от сервера.

Если разобраться не получится, то пришлите для проверки текущую версию Вашего проекта из директории "..\Simple-Scada 2\Projects\" на почту техподдержки support@simple-scada.com.

vigorts

#28
Здравствуйте. Уже понял что не правильно обрабатываю ответ от сервера, для меня это пока сложновато, но пытаюсь разобраться.
Спасибо, если что, то пришлю проект.