Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Не получили письмо с кодом активации?

Официальный форум Simple-Scada.

Автор Тема: HTTP GET POST, ZONT API  (Прочитано 5515 раз)

Azat

  • Новичок
  • *
  • Сообщений: 9
    • Просмотр профиля
HTTP GET POST, ZONT API
« : 22 Сентября 2022, 05:40:46 »
Добрый день

Может ли Simple-Scada 2 получать данные через post/get html запросы
У меня есть прибор zont (отопительный контроллер https://zont-online.ru/internet-magazin/termostaty/zont-h-2000-plus), который получает данные о работе газовых котлов, горелок, работе насосов, трехходовых клапанов, различные температуры воды/воздуха в помещениях, давление газа, уровне газа в емкости и т.д.

Есть документация по Api - https://zont-online.ru/api/docs/#3394112aa9

Хотелось эти данные с прибора (числа) - получать в переменные Скады
Управлять со Скады не нужно!
Всего лишь визуализировать!

Очень нужна помощь, подскажите как)))


« Изменён: 25 Сентября 2022, 11:21:46 от Simple_Scada »

PavelSh

  • Новичок
  • *
  • Сообщений: 3
    • Просмотр профиля
Re: Simple-Scada 2, HTTP GET POS, ZONT API
« Ответ #1 : 22 Сентября 2022, 10:37:57 »
У нас все получилось с Zont. Вытащили показания датчиков температуры,  наличие связи между контроллером и сервером, и исправность датчиков.
Чуть позже отказы вытащим,  но для этого надо сам кортроллер переконфигурировать.
Что у вас конкретно не получается?

Azat

  • Новичок
  • *
  • Сообщений: 9
    • Просмотр профиля
Re: Simple-Scada 2, HTTP GET POS, ZONT API
« Ответ #2 : 22 Сентября 2022, 10:56:14 »
Что у вас конкретно не получается?

Я вообще в этом новичок...
скачал скаду буквально вчера, сейчас разбираюсь с внутренними переменными, различными уровнями и т.д...

вообще необходимость понятной визуализации, потому что на объекте у клиента три котельной в каждой стоит zont H2000+ в котельных по 2,2,3 котла в каскаде...
через ЛК Zontа настроили работу котлов, насосных групп, насосов, трехходовых, тепловентиляторов, беспроводных датчиков температуры, уровень емкости видим...
но хромает визуализации, хотелось более понятную одну схему (экран) с тремя котельными...
настройка и управление пусть остаются в ЛК ZONT, вот мне бы только понять как передать скаде данные с zontа

до этого я согласно документации по Api через Питон достал жсон и в принципе его разобрал по датчикам... вывел в окно все показания с котлов, горелку, модуляцию, датчики и т.д., но там очень муторно создавать это из ничего по сути... в скаде же уже есть элементы - даже газовые котлы)))

На одном из форумов порекомендовали " Мы уже два года так данные выводим в скаду через ZONT, используем Simple SCADA, полёт нормальный." возможно даже Вы или Ваши коллеги, посмотрел документацию - https://simple-scada.com/help/script/requesthttp.html
но это для просто темный лес пока... хотелось бы чтобы подсказали что и как

мне просто получить данные в скаде (переменные) управление не нужно со скады в zont передавать

Azat

  • Новичок
  • *
  • Сообщений: 9
    • Просмотр профиля
Re: Simple-Scada 2, HTTP GET POS, ZONT API
« Ответ #3 : 24 Сентября 2022, 07:28:23 »
У нас все получилось с Zont. Вытащили показания датчиков температуры,  наличие связи между контроллером и сервером, и исправность датчиков.
Чуть позже отказы вытащим,  но для этого надо сам кортроллер переконфигурировать.
Что у вас конкретно не получается?

подскажи вы вот эту документацию использовали - https://simple-scada.com/help/script/requesthttp.html

aHTTP.Post('https://api.myserver.ru/auth/open', aPost, 1); // отмечаем запрос тегом = 1 - сюда какой api подставлял?
aHTTP.Post('https://api.myserver.ru/test/', aPost, 2); // отмечаем запрос тегом = 2 - вот сюда
ну теперь как понимать вот эти строки

Теперь остается вызвать процедуру DoAuthOpen и дождаться получения токена от сервера:
Код: (delphi)
begin
  DoAuthOpen;
end.

Когда сервер вернет ответ, будет выполнен скрипт "Выполнен POST/GET запрос" и значение токена запишется в глобальную переменную "AuthToken". Затем можно выполнить тестовый запрос с использованием токена:
Код: (delphi)
begin
  DoMyTestRequest;
end.
« Изменён: 25 Сентября 2022, 00:11:13 от Simple_Scada »

Simple_Scada

  • Администратор
  • *****
  • Сообщений: 1400
    • Просмотр профиля
Re: Simple-Scada 2, HTTP GET POS, ZONT API
« Ответ #4 : 25 Сентября 2022, 00:22:45 »
Здравствуйте.

Добавили в руководство подробный пример получения данных с контроллера "ZONT H2000+" - ссылка. Пример проекта доступен для скачивания по ссылке. Если требуется получать только текущие данные, то проще всего это будет сделать как описано в скрипте "DataParsingSensorsID".

Если что-то не получится или возникнут вопросы, то пришлите для проверки на support@simple-scada.com Ваш проект и подробно опишите, что именно не получается.

PavelSh

  • Новичок
  • *
  • Сообщений: 3
    • Просмотр профиля
Re: Simple-Scada 2, HTTP GET POS, ZONT API
« Ответ #5 : 25 Сентября 2022, 11:00:21 »
Добрый день, техподдержка Simple Scada уже выложили в онлайн-справку пример работы с Zont. Я тоже выложу наш вариант.

1. Логин и пароль к личному кабинету храним в локальных переменных с выводом на "техническую" страницу проекта, к которой есть доступ только у разработчика. Это необходимо для оперативной смены логин пароля без внесения изменений в проект с перезапуском.
2. Работает скрипт, который следит за "корректностью токена". Если несколько раз запрос с Токеном не срабатывает, то автоматически идет запрос нового Токена.
3. Необходимо учесть, что время жизни Токенов сейчас бесконечно. Раздавать всем их не стоит. Отменить можно, если в личном кабинете изменить пароль. В этом случае все ранее выданные Токены аннулируются.

Вот скрипт, который следит запрашивает Токен (событие раз в секунду)

Код: (delphi)
var
  aHTTP: TM_HTTP;
  aPost: TM_HTTPPost;

const
Interval = 60;


begin
  Timer_Zapros_API_Key.Value := Timer_Zapros_API_Key.Value + 1; //накапливаем секунды в таймер

      if Timer_Zapros_API_Key.Value = 1 then  //если таймер досчитал до 1
        begin
        //если (нет токена или ошибка запроса) и менее 5 запросов
        if ((APIkeyZont_Token_eee.Value = '') OR (Err_HTTP.AsBool = true)) AND (Count_ZaprosApi.Value < 5) Then
          //Производим запрос токена
          Begin
          Count_ZaprosApi.Value := Count_ZaprosApi.Value + 1; //Подсчет кол-ва запросов токена

          aPost := TM_HTTPPost.Create(hptJSON);
          aPost.Add('{"client_name": "Любое название вашего приложения"}');
          aHTTP := RequestHTTP;
          aHTTP.SetSSL(stSSLv23);
          aHTTP.SetHeader('Authorization','Basic ' + Base64Encode(combobox1.Text + ':' + Password.AsStr)); // в combobox1 лежит логин
          aHTTP.SetHeader('ContentType', 'application/json');
          aHTTP.SetHeader('X-ZONT-Client', 'ваша почта для связи со стороны разработчика API Zont');
          aHTTP.Post('https://zont-online.ru/api/get_authtoken', aPost, 70); // отмечаем запрос тегом = 70
          end;
        end;

  if Timer_Zapros_API_Key.Value >= Interval Then //если таймер досчитал до интервала
  Timer_Zapros_API_Key.Value := 0; //обнуляем таймер   

  //сброс счетчика неудачных запросов токена
  if (Err_HTTP.AsBool = false) OR (Sbros_Count.AsBool = true) then
    Count_ZaprosApi.Value := 0;

end.

4. Обрабатываем ответ на запрос Токена (тип - выполнен запрос API)

Код: (delphi)
var
ApiKey: string;

begin

if Response.Tag = 70 then
   begin
    ApiKey := (Response['token'].AsStr);
    Text10.Text := ApiKey; // выводим на экран Токен для визуального контроля его получения
    APIkeyZont_Token_eee.Value := ApiKey;
   end;
end.

5. Делаем запрос данных устройств с ранее полученных Токеном. (раз в секунду)

Код: (delphi)
var
  aHTTP: TM_HTTP;
  aPost: TM_HTTPPost;

begin
  Timer_Zapros_Devices.Value := Timer_Zapros_Devices.Value + 1; //Накапливаем секунды в таймер

  if Timer_Zapros_Devices.Value = 7 then  //если таймер досчитал до 7
        begin
          //производим запрос, если есть токен и нет ошибки запроса
          if (APIkeyZont_Token_eee.Value <> '') AND (Err_HTTP.AsBool = false)  then
            begin
            // формируем POST данные
            aPost := TM_HTTPPost.Create(hptJSON);
            //aPost.Add('"load_io": False');

            // отправляем данные с авторизацией токеном
            aHTTP := RequestHTTP;
            aHTTP.SetSSL(stSSLv23);
            aHTTP.SetHeader('ContentType', 'application/json');
            aHTTP.SetHeader('X-ZONT-Client', 'Ваша почта');
            aHTTP.SetHeader('X-ZONT-Token', APIkeyZont_Token_eee.AsStr);
            aHTTP.Post('https://zont-online.ru/api/devices', aPost, 81); // отмечаем запрос тегом = 80
            end;

        end;

  if Timer_Zapros_Devices.Value >= Interval_zaprosa_devices.Value Then //если таймер досчитал до интервала
  Timer_Zapros_Devices.Value := 0; //обнуляем таймер


end.

6. Обрабатываем ответ на полученный запрос (выполнен запрос API). Часть переменных придется создать вручную.

Код: (delphi)
var
  I,J: Integer;
  Disconnect1, Disconnect2, Disconnect3, Disconnect4: boolean;
  aTemp1, aTemp2, aTemp3, aTemp4, aTemp5, aTemp6, aTemp7, aTemp8, aTemp9, aTemp10, aTemp11, aTemp12: double; //температура датчиков
  aStatus1, aStatus2, aStatus3, aStatus4, aStatus5, aStatus6, aStatus7, aStatus8, aStatus9, aStatus10, aStatus11, aStatus12: string;  //состояние датчиков
  aResult, aResultTerm: string;
  aSimInDevice, aForeignMsisdn: TM_JSONNode;
  aDeviceArray, aThermArray, aTherm, aDevice, aNode: TM_JSONNode;
  aVar1: array [0..3] of byte;  //массив пропуска датчика

begin


  // если код ответа сервера не равен 200 (ОК), то выдаём ошибку
  if Response.Code <> 200 then
    begin
    //AddMessage(Now, mkAlarm, 'Ошибка выполнения HTTP-запроса, tag = ' + Response.Text , TRUE, FALSE);
    Err_HTTP.Value := true;
    Exit;  // прерываем выполнение
    end
  else
    Err_HTTP.Value := false;

 
  // прерываем выполнение, если тег не равен 81
  if Response.Tag <> 81 then
     Exit;

  aResult := '';
  aResultTerm := '';
  aDeviceArray := Response['devices'];      // получаем массив devices
  for I := 0 to aDeviceArray.Count - 1 do
  begin
    aDevice := aDeviceArray.Nodes[I];       // извлекаем очередное устройство из массива aDeviceArray


          //Сброс битов массива пропуска и извлечение IP
          case aDevice['id'].AsInt of
          //Объект_1
          12345: // ID вашего объекта (смотреть в ответе, лучше в Postman)
            begin
            aVar1[0]:= 0;
            Объект_1_ipDevice.Value:= aDevice['ip'].AsStr;
            end;
          //Объект_2
          23456: // ID вашего объекта (смотреть в ответе, лучше в Postman)
            begin
            aVar1[1]:= 0;
            Объект_2_ipDevice.Value:= aDevice['ip'].AsStr;
            end;
          //Объект_3
          34567: // ID вашего объекта (смотреть в ответе, лучше в Postman)
            begin
            aVar1[2]:= 0;
            Объект_3_ipDevice.Value:= aDevice['ip'].AsStr;
            end;
          //Объект_4
          56789: // ID вашего объекта (смотреть в ответе, лучше в Postman)
            begin
            aVar1[3]:= 0;
            Объект_4_ipDevice.Value:= aDevice['ip'].AsStr;
            end;
          end;



          {//Сброс битов массива пропуска
          case aDevice['id'].AsInt of
          //Объект_1
          12345:  Объект_1_ipDevice.Value:= aDevice['ip'].AsInt;
          //Объект_2
          23456: Объект_2_ipDevice.Value:= aDevice['ip'].AsInt;
          //Объект_3
          34567: Объект_3_ipDevice.Value:= aDevice['ip'].AsInt;
          //Объект_4
          56789: Объект_4_ipDevice.Value:= aDevice['ip'].AsInt;
          end;}

    aResult := aResult +
      'Device name = ' + aDevice['name'].AsStr + ', ' + aDevice['notes'].AsStr + Chr(10)+
      'id = ' + aDevice['id'].AsStr + ', ' +
      'ip = ' + aDevice['ip'].AsStr + Chr(10);

    //Проверка связи с объектом
    If aDevice['online'].AsStr = 'true' then
        begin
        aResult := aResult +  ' Связь есть';
        Disconnect1:= false;
        Disconnect2:= false;
        Disconnect3:= false;
        Disconnect4:= false;
        end
    else
        begin
          aResult := aResult +  ' Связи нет';

          case aDevice['id'].AsInt of
          //Объект_1
          12345:  Disconnect1:= true;
          //Объект_2
          23456: Disconnect2:= true;
          //Объект_3
          34567: Disconnect3:= true;
          //Объект_4
          56789: Disconnect4:= true;
          end;

        end;




    // читаем свойство sim_in_device
    aSimInDevice := aDevice['sim_in_device'];

    if aSimInDevice <> nil then  // если оно существует
    begin
      // извлекаем из sim_in_device свойство foreign_msisdn
      aForeignMsisdn := aSimInDevice['foreign_msisdn'];
      if aForeignMsisdn <> nil then // если оно существует, то добавляем в результат
        aResult := aResult + ', номер СИМ карты - ' + aForeignMsisdn.AsStr;
    end;

    // разбор вложенного массива thermometers
    aThermArray := aDevice['thermometers']; // получаем массив thermometers
    aResultTerm := '';
    for J := 0 to aThermArray.Count - 1 do
    begin
      aTherm := aThermArray.Nodes[J];       // поочередно извлекаем термометры из массива aThermArray



      //проверка регистрации датчика в термостате
      if aTherm['is_assigned_to_slot'].AsStr = 'true' then
      begin

        //ВЫВОД ПОКАЗАНИЙ ИЗ ДАТЧИКОВ
        case aDevice['id'].AsInt of
        //Объект_1
        12345:
            begin
               if aTherm['name'].AsStr = 'Темп.КК' then
                 begin
                   aTemp1:= aTherm['last_value'].AsFloat;
                   aStatus1 := aTherm['last_state'].AsStr;
                   aVar1[0] := SetBit(aVar1[0],0,true);
                 end
               else
               if aTherm['name'].AsStr = 'Темп. Отопле' then
                 begin
                   aTemp2:= aTherm['last_value'].AsFloat;
                   aStatus2 := aTherm['last_state'].AsStr;
                   aVar1[0] := SetBit(aVar1[0],1,true);
                 end
               else
               if aTherm['name'].AsStr = 'Темп. ГВС' then
                 begin
                   aTemp3:= aTherm['last_value'].AsFloat;
                   aStatus3 := aTherm['last_state'].AsStr;
                   aVar1[0] := SetBit(aVar1[0],2,True);
                 end;
            end;
        //Объект_2
        23456:
            begin
               if aTherm['name'].AsStr = 'Обратная  КК' then
                 begin
                   aTemp4:= aTherm['last_value'].AsFloat;
                   aStatus4 := aTherm['last_state'].AsStr;
                   aVar1[1] := SetBit(aVar1[1],0,True);
                 end
               else
               if aTherm['name'].AsStr = 'Прямая  КК' then
                 begin
                   aTemp5:= aTherm['last_value'].AsFloat;
                   aStatus5 := aTherm['last_state'].AsStr;
                   aVar1[1] := SetBit(aVar1[1],1,True);
                 end;
             end;
        //Объект_3
        34567:
            begin
               if aTherm['name'].AsStr = 'Датчик подачи ТС' then
                 begin
                   aTemp6:= aTherm['last_value'].AsFloat;
                   aStatus6 := aTherm['last_state'].AsStr;
                   aVar1[2] := SetBit(aVar1[2],0,True);
                 end
               else
               if aTherm['name'].AsStr = 'Датчик обратки ТС' then
                 begin
                   aTemp7:= aTherm['last_value'].AsFloat;
                   aStatus7 := aTherm['last_state'].AsStr;
                   aVar1[2] := SetBit(aVar1[2],1,True);
                 end;
             end;
        //Объект_4
        56789:
            begin
               if aTherm['name'].AsStr = 'Подача ТС' then
                 begin
                   aTemp8:= aTherm['last_value'].AsFloat;
                   aStatus8 := aTherm['last_state'].AsStr;
                   aVar1[3] := SetBit(aVar1[3],0,True);
                 end
               else
               if aTherm['name'].AsStr = 'Обратная ТС' then
                 begin
                   aTemp9:= aTherm['last_value'].AsFloat;
                   aStatus9 := aTherm['last_state'].AsStr;
                   aVar1[3] := SetBit(aVar1[3],1,True);
                 end
               else
               if aTherm['name'].AsStr = 'Подача ГВС' then
                 begin
                   aTemp10:= aTherm['last_value'].AsFloat;
                   aStatus10 := aTherm['last_state'].AsStr;
                   aVar1[3] := SetBit(aVar1[3],2,True);
                 end;
             end;
        end;
      end;




      if aTherm['is_assigned_to_slot'].AsStr = 'true' then
        begin
          aResultTerm := aResultTerm +          // в переменную результата добавляем значения нужных свойств термометра
          'name = ' + aTherm['name'].AsStr + ', ' +
          'last_value = ' + aTherm['last_value'].AsStr + Chr(10);
        end;

    end;

    aResult := aResult + Chr(10) + aResultTerm + Chr(10);

  end;
 
  Text20.Text := aResult;
                                           

  //вывод значений Объект_1
  Объект_1_Tkk.Value:= aTemp1;
  Объект_1_Totopl.Value:= aTemp2;
  Объект_1_Tgvs.Value:= aTemp3;
  Объект_1_Disconnection.Value:= Disconnect1;

      //извлекаем биты проверки пропуска
      Объект_1_Tkk_Lost.Value   := NOT GetBit(aVar1[0],0);
      Объект_1_Totopl_Lost.Value:= NOT GetBit(aVar1[0],1);
     Объект_1_Tgvs_Lost.Value  := NOT GetBit(aVar1[0],2);

      //Tkk
      if aStatus1 = 'ok' then
        Объект_1_Tkk_ERR.Value := 0
      else
        Объект_1_Tkk_ERR.Value := 1;

      //Totopl
      if aStatus2 = 'ok' then
        Объект_1_Totopl_ERR.Value := 0
      else
        Объект_1_Totopl_ERR.Value := 1;

      //Tgvs
      if aStatus3 = 'ok' then
        Объект_1_Tgvs_ERR.Value := 0
      else
        Объект_1_Tgvs_ERR.Value := 1;


  //вывод значений по остальным объектам, аналогично
  ...........................

end.

Для понимания, как разбирать ваш массив данных, рекомендую сначала выполнить запрос в программе Postman, где будет видна структура ответа, ID ваших Device, названия датчиков и прочая информация.

« Изменён: 25 Сентября 2022, 11:08:51 от Simple_Scada »

Azat

  • Новичок
  • *
  • Сообщений: 9
    • Просмотр профиля
Re: Simple-Scada 2, HTTP GET POS, ZONT API
« Ответ #6 : 26 Сентября 2022, 09:58:45 »
Добавили в руководство подробный пример получения данных с контроллера "ZONT H2000+" - ссылка.

Cпасибо огромное!
все получилось! :) ;)

Я тоже выложу наш вариант.

Спасибо все получилось по инструкции
« Изменён: 26 Сентября 2022, 10:06:47 от Simple_Scada »

Azat

  • Новичок
  • *
  • Сообщений: 9
    • Просмотр профиля
Re: HTTP GET POST, ZONT API
« Ответ #7 : 10 Апреля 2024, 06:15:24 »
Добрый день
некоторое время назад стал получать ошибку при запуске проектов "Запрос на аутентификацию вернул ошибку! Код = -1"
в инструкции к API у zont вроде ничего не менялось https://zont-online.ru/api/docs/#3394112aa9
не смог разобрать в причинах

я пробовал через питон, получить json файл там все работает тоже через post запросы и аутентификацию через логин и пароль
кто может подсказать о причинах ошибку и решении
« Изменён: 10 Апреля 2024, 06:21:37 от Azat »

Simple Scada

  • Глобальный модератор
  • *****
  • Сообщений: 285
    • Просмотр профиля
    • Simple-Scada
Re: HTTP GET POST, ZONT API
« Ответ #8 : 10 Апреля 2024, 08:29:39 »
Здравствуйте.

В ZONT API изменился список доступных шифров (которые используются при подключении по https (SSL/TLS) к серверам Zont). Новые шифры были добавлены в Simple-Scada начиная с версии 2.6.7.3. Если Вы используете версию ниже 2.6.7.3, то выполните обновление до версии не ниже 2.6.7.3.
« Изменён: 10 Апреля 2024, 09:01:25 от Simple_Scada »

Azat

  • Новичок
  • *
  • Сообщений: 9
    • Просмотр профиля
Re: HTTP GET POST, ZONT API
« Ответ #9 : 10 Апреля 2024, 09:48:02 »
 :) понял
спасибо