Вопрос по then(newValue, devName, cellName) в when и asSoon для defineRule

Добрый вечер.

в документации в примерах для when и asSoon указана такая конструкция для последующего then:
then: function (newValue, devName, cellName) {}

откуда берутся эти значения, если в when и asSoon фактически может и не содержаться никаких топиков, а возвращаемое значение этих функций всегда boolean, да еще и срабатывает then всегда только при true

у мненя для кода

Summary

var aRoofHeaters = [
“fl0-box3_1-R7/K1”,
“fl0-box3_1-R7/K2”,
“fl0-box3_1-R7/K3”,
“fl0-box3_1-R7/K4”,
“fl0-box3_1-R7/K5”,
“fl0-box3_1-R7/K6”,
“fl0-box3_1-R6/K1”,
“fl0-box3_1-R6/K2”,
]
var aTimers =
var HeatReqTopic = “fl0-box5-DI1/Input 7”;
timePause = 1 // пауза между включениями

var ps_RoofHeaters = new PersistentStorage(“RoofHeatersControl”, { global: true });
ps_RoofHeaters [“state”] = (ps_RoofHeaters [“state”] === true);
ps_RoofHeaters [“forced”] = (ps_RoofHeaters [“forced”] === true);
var HeatReq = false

function stopTimers(){
aRoofHeaters.forEach(function(topic,idx){
if (typeof aTimers[idx] ===‘number’ && aTimers[idx]>=0) {
clearTimeout(aTimers[idx])
aTimers[idx] = null;
}
})
}

function setRoofHeaterState(){
var state = ( ( ps_RoofHeaters [“state”] && HeatReq) || ps_RoofHeaters [“forced”] )
state = (state === true )? true : false;
log(“RoofHeater: setRoofHeaterState: ({})”,(state)?“Включаю”:“Выключаю”);
stopTimers()
aRoofHeaters.forEach(function(topic,idx){
aTimers[idx] = setTimeout(function() {
aTimers[idx] = null
if (dev[topic] !== state) {
log(“RoofHeater: setRoofHeaterState: {} ({})”,topic,(state)?“Включаю”:“Выключаю”);
dev[topic] = state
}
}, idxtimePause1000*( (state)?1:0 ) + 50 );
})
}

function getRelayStates(){
return !aRoofHeaters.every(function (topic){ return !(dev[topic] === true);})
}

defineRule(“ruleRoofHeaterControl_heat”, {
when: function(){ return ( ( (dev[HeatReqTopic] === true)? true:false ) !== HeatReq ) },
then: function(newValue, devName, cellName) {
HeatReq = (dev[HeatReqTopic] === true)? true : false
log(“RoofHeater: ruleRoofHeater_heat: Запрос от датчика ({})”,(HeatReq)?“Включить”:“Выключить”,newValue, devName, cellName);
dev[“RoofHeatersControl/HeatRequest”] = HeatReq;
setRoofHeaterState()
}
});

defineRule(“ruleRoofHeaterControl_enable”, {
when: function(){ return ( ( (dev[“RoofHeatersControl/Control”] === true)? true:false ) !== ps_RoofHeaters [“state”] ) },
then: function(newValue, devName, cellName) {
ps_RoofHeaters [“state”] = (dev[“RoofHeatersControl/Control”] === true)? true:false ;
log(“RoofHeater: ruleRoofHeater_enable: Управление по датчику ({})”,(ps_RoofHeaters [“state”])?“Включено”:“Выключено”,newValue, devName, cellName);
setRoofHeaterState()
}
});

defineRule(“ruleRoofHeaterControl_forced”, {
when: function(){ return ( ( (dev[“RoofHeatersControl/ForcedOn”] === true)? true:false ) !== ps_RoofHeaters [“forced”] ) },
then: function(newValue, devName, cellName) {
ps_RoofHeaters [“forced”] = (dev[“RoofHeatersControl/ForcedOn”] === true)? true:false ;
log(“RoofHeater: ruleRoofHeaterControl_forced: Принудительно Включить ({})”,(ps_RoofHeaters [“forced”])?“Активно”:“Неактивно”,newValue, devName, cellName);
setRoofHeaterState()
}
});

var getStates = defineRule(“ruleRoofHeaterControl_RelayStates”, {
whenChanged: aRoofHeaters,
then: function(newValue, devName, cellName) {
dev[“RoofHeatersControl/RelayStates”] = getRelayStates()
if (newValue === undefined || newValue === null){return}
log(“RoofHeater: ruleRoofHeaterControl_RelayStates: Реле {}/{} изменило состояние на {}”,devName, cellName, (newValue)?“Включено”:“Выключено” );
// setRoofHeaterState() ! не включать
}
});

defineVirtualDevice(‘RoofHeatersControl’, {
title: ‘Обогрев кровли управление’,
cells: {
ForcedOn: {
title: “Принудительно Включить”,
type: “switch”,
value: ps_RoofHeaters [“forced”],
readonly: false,
order: 1
},
Control: {
title: “Управление по датчику (вкл) / Обогрев Выключен (выкл)”,
type: “switch”,
value: ps_RoofHeaters [“state”],
readonly: false,
order: 2
},
HeatRequest: {
title: “Запрос нагрева от датчика”,
type: “switch”,
value: HeatReq,
readonly: true,
order: 3
},
RelayStates: {
title: “Состояние реле”,
type: “switch”,
value: getRelayStates(),
readonly: true,
order: 4
},
}
});

log(“RoofHeater: rule loaded”);
runRule(getStates);

после нажатия “сохранить” получаю каждый раз разное значение для newValue, devName, cellName типа:

RoofHeater: ruleRoofHeater_heat: Запрос от датчика (Включить) 8.04 fl0-box2_2-UPS3 battery_voltage
RoofHeater: ruleRoofHeater_heat: Запрос от датчика (Включить) 707544 fl0-box2_3-DI2_13 Uptime

при дальнейшей сработке правила такого нет

Добрый день.

К сожалению не силён в JS но порекомендую разобраться как работает наш движок правил wb-rules и как он обрабатывает код, подробнее описано в статье на GitHub.

я пытаюсь понять как и из чего формируются значения newValue, devName, cellName для when и asSoon. Из документации этого непонятно. На мой скромный взгляд этих значений там быть не должно, о чем и написал в первом посте

мне кажется надо:

  1. в документации в примерах кода при описании when и asSoon убрать из строки
    then: function (newValue, devName, cellName)
    всякое упоминание о newValue, devName, cellName, т.к. они не должны существовать.
    Или скажите в чем я ошибся

  2. Исправить фантомное появление значений в этих переменных при старте скрипта после сохранения

Добрый день.

Уточню у коллег, обязательно вернусь к вам с ответом.

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

приложен диагностический архив, доступен только сотрудникам поддержки
(657.7 KB)

Добрый день.
Появление мусора в переменных исправили.
Документацию менять не стали, так как в остальном поведение не изменилось, даже если оно может казаться несколько странным, все равно обратную совместимость не можем ломать.

Спасибо!
1.искать исправление только в testing или для всех?
2.по документации я все же не очень понял логику появления значений (newValue, devName, cellName) для asSoonAs и When.

рассмотрим 3 варианта:
2.1: asSoonAs: function() { return dev["wb-gpio/A1_OUT"]; },
2.2: asSoonAs: function() { return ( dev["wb-gpio/A1_OUT"] !== dev["wb-gpio/A2_OUT"]); },
2.3: asSoonAs: function() { return true },

какие ожидаемые значения (newValue, devName, cellName) мы должны получить для каждого случая?

обновил testing вот результат:

нижняя строчка - после перезагрузки контроллера
верхняя - после нажатия кнопки “сохранить”

так как правильно-то?

Summary

Добрый день.

  • 2.1, 2.2: при сохранении скрипта или старте wb-rules значения newValue, devName, cellName = undefined; если же срабатывание правила было вызвано изменением например wb-gpio/A1_OUT, то в newValue, devName, cellName соответсвтенно значение wb-gpio/A1_OUT.
  • 2.3: тут всегда newValue, devName, cellName = undefined, так как нет обращений к контролам.

Простейший пример:

defineRule({
  asSoonAs: function() {
    return dev["buzzer/volume"] < 50;
  },
  then: function() {
    log("asSoonAs", [].slice.call(arguments));
  }
});

Понял, спасибо.

т.е. у меня при перезагрузке контроллера (если смотреть скриншот здесь ) устройство fl0-box5-DI1 (это МСМ8) инициировало первичное обновление своего состояния, поэтому оно и появилось в логах. Правильно я рассуждаю?

Всё верно, как следствие, при первой загрузке вы видите undefined, а через несколько секунд - нормальные данные после первичного опроса МСМ8.

наоборот, при первичном опросе я вижу МСМ8, а после нажатия “сохранить” вижу undefined