Вопросы по скриптам в Simple-Scada 2

Автор Simple-Scada, 29 января 2016, 15:19:20

samum

спасибо, через GUID я что-то и не догадался ))) так работает сразу

globalhook

#1591
Доброго времени суток.
Столкнулся с непонятной проблемой. HTTP сервер отвечает на мой запрос, сформированный в simple scada, код ответа 200, однако, count выдает 0.
Проверял валидность ответа - на любом сайте результат один - OK.
Код: pascal
if Response.Tag = 10 then
begin
  Log1.Text := IntToStr(Response.Code);
  Text255.Text:=Response.text;
  Text257.Text:= IntToStr(Response.Count);
  Text258.Text := Response['hptr'].AsStr;
end;

Файл в полным ответом пристегнул.
Поля postman

Simple-Scada

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

Если бы сервер возвращал массив объектов, то Count было бы равно количеству объектов в массиве. У Вас сервер сразу возвращает объект, и Вы можете напрямую обращаться к любым свойствам этого объекта, например: Response['hptr'], Response['ddur'] и т.д. Если задача в том, чтобы пройти в цикле по свойствам объекта, то можно сделать так:
Код: pascal
var
  I: Integer;
begin
  I := 0;
  while Response.Nodes[I] <> nil do
  begin
    // здесь можно получить значение свойства, например так Response.Nodes[I].AsStr
    Inc(I);
  end;
end.
Но непонятно в чем смысл, если проще обратиться напрямую.

globalhook

В этом и проблема, что в 6 строке я и пытаюсь читать напрямую, но значение все равно нуль, хотя оно должно быть и есть.

Simple-Scada

Мы проверили с Вашим скриптом и файлом ответа, который Вы прикрепили. Все свойства читаются корректно. Если разобраться самостоятельно не получается, то вышлите текущую версию проекта на support@simple-scada.com, мы проверим его и напишем что нужно исправить.

globalhook

#1595
Загрузили получаемый от оборудования json на github. Выполняем запрос:
Код: pascal
 var
  aHTTP: TM_HTTP;
  aRequest: string;
begin
  aHTTP := RequestHTTP;
  aHTTP.SetHeader('Accept', 'application/json');
  aHTTP.Get('https://rogalsky83.github.io/test/TestFile.json', 55);
end.
Скрипт (выполнен Get/Post запрос):
Код: pascal
var
  aResult: string;
   aNode: TM_JSONNode;
begin           
  if response.Code <>200  then 
    Text1.Text:= 'Ошибка ' + IntToStr(Response.Code);

  if response.code = 200 then 
    if Response.Tag = 55 then
    begin    
      aNode := Response.NodesStr['drtc'];
      if Assigned(aNode) then               
        Text5.text := aNode.AsStr;           
      Text3.Text:=IntToStr(Response.Count);
      Text1.Text:=Response.Text;
    end;
end.
В результате: Response.Count=0, aNode - не существует, хотя в Response.Text весь JSON отображается.

При этом, если использовать такой-же JSON файл, созданный копированием текста из Postman, то все работает:
Код: pascal
 var
  aHTTP: TM_HTTP;
  aRequest: string;
begin
  aHTTP := RequestHTTP;
  aHTTP.SetHeader('Accept', 'application/json');
  aHTTP.Get('https://rogalsky83.github.io/test/kamera4.json', 55);
end.
Отличие этих файлов только в том, что первый файл был получен Get.sreame, а второй просто raw текст из postman.
Есть предположение, что Simple-Scada не разбирает как json из-за какого-то заголовка, но заголовки ответа посмотреть нет возможности.

Simple-Scada

В соответствии со спецификацией JSON RFC 7159 (Раздел 8.1): "Реализации JSON НЕ ДОЛЖНЫ добавлять метку порядка байтов в начало текста JSON.". У Вас в ответе на запрос "TestFile.json" метка порядка байтов добавляется, т.е. ответ выглядит так:
Код: pascal
#$FEFF'{'#$D#$A'  "drtc": "2024-11-12T11:16:51",...

В ответе на запрос "kamera4.json" нет метки порядка байтов (как и должно быть):
Код: pascal
'{'#$D#$A'  "drtc": "2024-11-12T11:16:51",...

Поэтому "kamera4.json" читается нормально. Уберите метку порядка байтов из ответов, чтобы они соответствовали спецификации, тогда проблем не будет.
Также в ближайшее обновление добавим автоматическое удаление метки порядка байтов перед обработкой текста JSON.

will smith

здравствуйте. Помогите, пожалуйста со скриптом, меняющим цвет элемента в зависимости от значения переменной
1= зеленый круг
0 = красный круг
в 2022 уже делал - не могу найти тот проект  ::)

ARV

#1598
Код: pascal
// покраснение объекта, если его переменная TRUE
begin
  with Sender as TM_Object do begin
    if Variable.AsBool
      then Color := clLightCoral // не совсем красный
      else Color := clSilver; 
    // если объект ТЕКСТ, то меняем цвет шрифта
    if Sender is TM_Text
      then TM_Text(Sender).FontColor := Color;
  end;
end.
Вам надо заменить соответственно цвета: clLightCoral на clGreen, clSilver на clRed

globalhook

#1599
Цитата: Simple-Scada от 12 ноября 2024, 16:37:02В соответствии со спецификацией JSON RFC 7159 (Раздел 8.1): "Реализации JSON НЕ ДОЛЖНЫ добавлять метку порядка байтов в начало текста JSON.". У Вас в ответе на запрос "TestFile.json"...
Большое спасибо за терпение и погружение в вопрос. Будем с нетерпением ждать обновления, поскольку изменить ответ HTTP сервера не получится

Simple-Scada

Добавили автоматическое удаление метки порядка байтов в обновление 2.6.15.0.

Andrey1883

#1601
Здравствуйте!
помогите пожалуйста решить одну задачу!
Имеется переменная в которую записываются данные с некоторой периодичностью (в автоматическом режиме ПЛК опрашивает вход один раз за 60 секунд, в ручном режиме, соответственно, время может быть иным)
Физически это выглядит как мультиплексор из клапанов: 11 входов и 1 выход ! Выход подключен к измерителю концентрации ! Соответственно, ПЛК, перебирая эти входы (переключает клапана), измеряет концентрацию в разных точках системы и заносит измеренные значения в разные переменные (11 точек - 11 переменных)! данные в переменных хранятся до следующего измерения!
Я хочу создать некий архив!
В скаду забираю данные и настраиваю переменные на архивирование по изменению.

создаю таблицу вот такого вида (фактически их 11 для каждой точки измерения) - скриншот Таблица_1.

путем нажатия кнопки "обновить" должно получиться что-то вот такое - скриншот Таблица_2.

Возможно есть более изящное и простое решение!

Оператору удобнее отслеживать эти показатели именно в табличном виде! графики никак не хотят анализировать

PS
а может создать 15 внутренних переменных для каждой точки, и записывать каждое измерение в свою переменную, затем с датой и временем заносить в таблицу! на 16 измерении переписывать 1-ю переменную, как циклическая запись!!

что лучше вообще будет с точки зрения нагрузки и вообще правильности реализации!!

ARV

Вопрос: а по какой причине событие от клавиатуры возникает только по комбинации с управляющими клавишами? Какая причина не позволяет любое нажатие отслеживать?

Simple-Scada

Andrey1883, если нужно всегда видеть 11 последних значений (даже после перезапуска скады), то нужно на ПЛК сделать набор переменных с последними значениями (одна хранит предпоследнее, другая значение перед предпоследним и т.д.) и привязать их к соответствующим ячейкам таблицы.
В ином случае придётся заполнять таблицу в скаде с нуля после каждого перезапуска проекта и она заполнится только через 11 минут (если на ПЛК автоматический режим). Т.е. по событию OnDatachange переменной заполнять в таблице первую ячейку, затем вторую и так далее до 11, а затем смещать все значения в таблице влево, удаляя первое и добавляя последнее (самое новое).

Цитата: ARV от 27 ноября 2024, 10:11:24а по какой причине событие от клавиатуры возникает только по комбинации с управляющими клавишами?
Это сделано для того, чтобы было невозможно выполнить скрипт на сервере случайным нажатием одной клавиши на клавиатуре клиента.

B.B

#1604
Цитата: Max от 04 октября 2024, 10:00:20Добрый день. Подскажите пожалуйста, может быть есть скрипт для подсчета астрономического восхода и захода солнца? Планируется ли добавление в функционал расписания включение/отключения по заходу/восходу?

Подскажу примерные формулы (не учитывают сумерки) ... реализацию в скрипте не проверял (просто набил в ответе  :P )
1. Считаем склонение солнца в день года (подробнее см. в J. A. Duffie and W. A. Beckman, "Solar Engineering of Thermal Processes, 3rd Edition" pp. 13-14, J. Wiley and Sons, New York (2006))   
  sigma=(23.45*PI/180)*sin(2*PI*(284+_НОМЕР_ДНЯ_ОТ НАЧАЛА_ГОДА_)/365)
  Високосные года можно учитывать, а можно и не учитывать (небольшая погрешность в единицы минут получится)
2. Для известной широты места в градусах (далее _L_) считаем угол восхода/заката
  sunrise = acos(-tan((_L_*PI/180))*tan(sigma))
3. От истинного полудня отнимается угол восхода/заката (один час это 15 градусов) и получаем время восхода 
  _ВОСХОД_= 12-sunrise/(15*PI/180) 
  в полученной дроби целая часть - час восхода 
  ((_ВОСХОД_*60) div 60) - минуты восхода 
  _ЗАКАТ_= 12+sunrise/(15*PI/180) 
  в полученной дроби целая часть - час заката 
  ((_ЗАКАТ_*60) div 60) - минуты заката

Код: pascal
var 
 sigma,sunriseAngle,sunrise,sunset: Single;
 sunriseHour, sunriseMinutes, sunsetHour, sunsetMinutes : Extended;
begin
// склонение солнца в текущий день года 
  sigma:=(23.45*PI/180)*sin(2*PI*(284+DayOfTheYear(Now))/365);
// для 45 градусов северной широты угол восхода солнца равен
  sunriseAngle:= arccos(-tan((45*PI/180))*tan(sigma));
// угол восхода
  sunrise:= 12-sunriseAngle/(15*PI/180);
// угол заката
  sunset:=12+sunriseAngle/(15*PI/180);

// искомые часы и минуты
  sunriseHour:=Int(sunrise);
  sunriseMinutes:=Int((sunrise*60) div 60);
  sunsetHour:=Int(sunset);
  sunsetMinutes:=Int((sunset*60) div 60);
end.

UPD 3-12-2024
Добрался до редактора...

Почему-то
sunriseMinutes:=Int((sunrise*60) div 60);
даёт ошибку incopatible types "SINGLE" and "INTRGER"

рабочий код ниже.

Код: pascal
var 
 sigma,sunriseAngle,sunrise,sunset: Single;
 sunriseHour,sunriseMinutes,sunsetHour,sunsetMinutes : Extended;
begin
// склонение солнца в текущий день года
  sigma:=(23.45*PI/180)*sin(2*PI*(284+DayOfTheYear(Now))/365);
// для 45 градусов северной широты угол восхода солнца равен
  sunriseAngle:= arccos(-tan((45*PI/180))*tan(sigma));
// угол восхода
  sunrise:= 12-sunriseAngle/(15*PI/180);
// угол заката
  sunset:=12+sunriseAngle/(15*PI/180);

// искомые часы и минуты
  sunriseHour:=Int(sunrise);
  sunriseMinutes:=Int((sunrise-sunriseHour)*60);

  sunsetHour:=Int(sunset);
  sunsetMinutes:=Int((sunset-sunsetHour)*60);
end.