Здравствуйте! Речь будет идти о контроллере WB6 Задача: написать правило, обновляющее значение виртуального устройства по определенной формуле Реализация с моей стороны:
Здесь стоит отметить, что формула правильная, т.к большую часть времени значение является корректным (dev1/ch1 выражается в Вт, а dev1/ch2 в кВт)
После того, как я это все реализовал, начал выявляться ряд проблем:
В случайные моменты времени вычисляемое значение является неправильным, причем всегда в меньшую сторону от ожидаемого, хотя, опять же, большую часть времени вычисляется все верно, а в коде в это время ничего не менялось
Иногда значение перестает обновляться и тут я уже начал смотреть сам, почему это происходит. Вот, что получилось заметить: когда dev["dev1/dep"] является истиной, dev["StandCoef/value"] обновляется не каждый просмотр правил, а в “случайные промежутки времени”. Т.е для конкретики: в момент времени 16:00:06 я сохранил правило, оно сразу же исполнилось (значение высчиталось). Но за тем последовало то, что правило срабатывало через 6 секунд, потом через 8, потом вообще не срабатывало (переменная все это время является true), а значения dev["dev1/ch1"] и dev["dev1/ch2"] обновляются гораздо чаще.
Подумал, что проблема кроется в типе правил, но when “срабатывают при каждом просмотре, при котором функция, заданная в when , возвращает истинное значение”. Так и есть в моей ситуации, так что не понимаю, почему не заходит в then-часть.
Пробовал менять на asSoonAs, не работало, но и не должно, исходя из описания данного типа правил
Больше как продолжение предыдущего пункта, но выделю отдельно. Я подумал, что можно попробовать убрать переменную dev["dev1/dep"], и заменить ее просто на true, чтобы переменная обновляла значение, как нужно. В итоге повторилась проблема под пунктом 1, но, кроме того, хоть из логирования было видно, что then-часть исполняется по несколько раз в секунду, иногда исполнение формулы останавливалось на секунд 20 и возобновлялось после, что очень странно, так как условие всегда истинно.
Разумеется, хотелось бы в первую очередь конкретного вывода значения в 100% случаев, но и также узнать, почему 2 и 3 пункты случаются
Может, стоило сделать как-то лучше с моей стороны; за любые предложения заранее большое спасибо!
Добрый день!
Судя по вашему описанию, возможные проблемы могут быть связаны с несколькими аспектами:
Правила в WB6 выполняются в зависимости от частоты изменений значений используемых в них переменных. Если значения переменных изменяются слишком часто, может возникать проблема с тем, что правило не успевает срабатывать так, как ожидается.
Ваше текущее правило может не совсем корректно учитываться из-за частоты обновления переменных или других ограничений. Попробуйте следующее:
Обновление при изменении переменных**: Убедитесь, что правило срабатывает при изменении всех необходимых переменных. Вы можете использовать несколько when условий для этого.
Использование asSoonAs**: Если вы хотите, чтобы правило срабатывало, как только изменяются связанные переменные, попробуйте использовать тип asSoonAs. Однако, так как вы уже пробовали этот тип и он не сработал, можно попробовать другой подход.
А можно сделать как-то так, чтобы значения не изменялись слишком часто?
Фактически, важно изменение только одной переменной: dev["dev1/dep"], оно и учитывается, или вы имеете в виду смотреть за изменениями переменных, которые используются в арифметическом выражении? (dev["dev1/ch1"] и dev["dev1/ch2"])
Можете, пожалуйста, привести пример кода с такой формой. Это несколько when-условий через запятую?
Вообще возникла идея исполнять данное правило каждую секунду, две, например, для уменьшения частоты. Как такое лучше осуществить, через cron или таймеры?
Только что попробовал сделать через cron, чтобы правило срабатывало через секунду, и произошло следующее:
Значение сначала обновлялось так, как и должно, а потом начала выходить задержка, даже в несколько минут, а так же ко всему этому система сама работала медленнее.
Стек вызовов закидывается функциями thencron’ом, получается, да? Потому что значение обновляется с сильной задержкой (т.е. он берет значения “из прошлого” и оперирует ими в арифметике и на выход получается то число, которое должно было быть минутами ранее)
Как можно сделать так, чтобы правило срабатывало каждую секунду и брала значения в настоящем времени?
Проблема с ростом очереди, скорее всего действительно, связана с тем, что логика обработки данных не успевает завершаться, что приводит к накоплению очереди.
Для более точного анализа и предоставления оптимальных решений, пожалуйста, опишите ваш проект подробнее: что выполняется, откуда поступают данные и что вы хотите получить в итоге.
Кроме того, прошу вас приложить диагностический файл для более глубокого понимания проблемы.
Сам по себе проект комплексный, но я постараюсь объяснить данную подзадачу, по которой и возникла проблема:
Нужно, чтобы на SVG-панель выводилось значение, полученное из арифметического действия, которое я ранее расписывал. Значение, конечно же, в этом случае - “виртуальная переменная”, т.е virtual device (dev["StandCoef/value"]). Желательно, чтобы значение обновлялось через какой-то интервал, как я пробовал ранее - 1с, например
Две переменные (dev["dev1/ch1"] и dev["dev1/ch2"]), используемые при делении, идут по modbus’у RS485. Получаются они корректно, как я полагаю, т.к отображаются правильно и показывают то, что нужно
Конечная цель - правильно отобразить переменную на SVG-панели, т.е. правильно ее получить как число в первую очередь, что сейчас не получается в 100% случаев
Если что-то не объяснил или объяснил плохо, то прошу об этом сразу же сообщить. В целом, как мне изначально казалось, задача очень простая; я реализовал ее, но единственная проблема - это с обновлением значения. Это собственно и хотелось бы выяснить
Не сильно понимаю, что это за файл и откуда его можно взять, так что попрошу вас объяснить, как это можно сделать, и я сразу же это осуществлю
Вот как можно использовать логическое И (&&) в функции when вместо логического ИЛИ (||):
when: function() {
// Условие для проверки всех необходимых переменных
return dev["dev1/dep"] && dev["dev1/ch1"] && dev["dev1/ch2"];
}
В этом случае функция when вернёт true только если все указанные переменные (dev["dev1/dep"], dev["dev1/ch1"], и dev["dev1/ch2"]) имеют истинные значения. Если хотя бы одна из них ложна, функция вернёт false.
Пример с таймером отсечки и проверкой на ноль:
Вот как можно переписать ваш таймер с использованием тернарного оператора для проверки на ноль:
var timer = setInterval(function () {
// Проверяем значение dev["dev1/ch2"]
if (dev["dev1/ch2"] !== 0) {
// Если значение не равно нулю, вычисляем коэффициент
dev["StandCoef/value"] = (1e3 * dev["dev1/ch1"]) / dev["dev1/ch2"];
} else {
// Если значение равно нулю, устанавливаем коэффициент в null
dev["StandCoef/value"] = null;
}
}, 1000); // Интервал 1000 миллисекунд (1 секунда)
В этом коде каждые 1000 миллисекунд выполняется проверка значения dev["dev1/ch2"]. Если оно не равно нулю, рассчитывается коэффициент и сохраняется в dev["StandCoef/value"]. Если значение равно нулю, устанавливается dev["StandCoef/value"] в null.
приложен диагностический архив, доступен только сотрудникам поддержки
(111.3 KB)
И хотелось бы поинтересоваться, можно ли как-то подключится к WB через ssh, но со своего терминала? А то контроллер на облаке и немного неудобно там использовать подключение по ssh, а также сохранять файлы себе на систему
Использовал данный пример. Сначала не понял, нужно ли var кидать в само правило (в then), попробовал, возникла та же проблема с очередью, что было ожидаемо, но, когда я вытащил var timer вне всякого правила все заработало как и должно было с самого начала. Я посидел, понаблюдал за значениями и пока кажется, что все считается корректно!
Правда вопрос про очередь остается, т.к, хоть я и вытащил var за само правило, проблема с очередью должна была остаться, разве нет?
В итоге все работает хорошо, callback срабатывает по интервалу как и надо, благодарю за подробное объяснение!
Прикрепляю рабочий код, который я получил в итоге (чуть измененный от примера):
Спасибо за ваш отзыв и подробное описание вашей работы с кодом. Рад, что вы смогли успешно запустить таймер и что он работает корректно.
Что касается вашего вопроса о проблеме с очередью, я хотел бы пояснить:
Когда вы помещаете var timer вне правила, он устанавливается глобально, и это позволяет избежать создания множества таймеров при каждом срабатывании правила и это предотвращает потенциальные проблемы с очередью.
Если у вас возникнут дополнительные вопросы или потребуется помощь, не стесняйтесь обращаться!