Логика работы скриптов

тут только одна проблемка, контроллер у меня один и на нем отопление дома, а эксперименты с кодом зачастую приводят к ошибкам которые могу стопорнуть систему. :frowning:

вопрос по объектам объявленным вне кода, они состоят из данных и функций, как они видятся? сохраняются ли данные объекта как глобальные, то есть до перезапуска движка? И как работают функции объекта (методы), при каждом вызове их внутреннее пространство создается заново, а данные объекта одни для всех одновременно вызванных функций?

Ну, в общем и целом, вы все правильно понимаете, но тема достаточно сложная, чтобы ее в рамках форума подробно расписывать. Я вот нашел на Хабре неплохую статью к вашим вопросам, посмотрите, пожалуйста: Особенности работы или «За что я люблю JavaScript»: Замыкания, Прототипирование и Контекст, думаю, многое прояснится. Не спешите со сложными конструкциями в коде правил, многое можно делать достаточно просто.

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

Да, как я выше писал, движок – это Duktape, в плане языка можете ориентироваться на него.

Здравствуйте!
Я не понял логику работы, подскажите, пожалуйста, такой момент.
Я хочу иметь несколько однотипных правил, потому создаю объект, объявляю свойства и методы.

	var swichControlGROUP1 = function (ruleName,
	...
	{//конструктор первичные установки
	this.RN = ruleName;
	if (this.RN == undefined) {this.RN = "swichControlGROUP1"};

	this.IDN = inputDevName;
	this.ICN = inputCellName;
	...
	var IDN = this.IDN;
	...

и метод - запуск правила:

	this.defineRule = function ()
	{
defineRule(this.RN, 
{
  	whenChanged: this.IDN + "/" + this.ICN,
	then: function (newValue,devName,cellName)
	{
		log (" start rule this.IDN   this.ICN :" + IDN + "/" + swichControlGROUP1.ICN );
                    log (" start rule this.IDN   this.ICN :" + this.IDN + "/" + this.ICN );
      if (newValue == 0)
...

вот тут я поплыл. Если в whenChanged: this.IDN + “/” + this.ICN, верно интерпретируются имена входов (скрипт отрабатывает), то после then все, мой this куда-то улетает и я вижу undefined в переменных во всех вариантах какие я придумал

2019-02-28 01:50:13 start rule this.IDN this.ICN :undefined/undefined
2019-02-28 01:50:13 start rule this.IDN this.ICN :undefined/undefined

вызываю так, все инициализирую:

	var SW1 = new swichControlGROUP1();
	SW1.RN = "sw1_rule";
	SW1.IDN = "wb-gpio";
	SW1.ICN = "EXT1_DR1";
	SW1.ODN = "wb-mr6c_13";
	SW1.OCN = "K1";
	SW1.DDN = "wb-dac";
	SW1.DCM = "EXT_O1";
	SW1.SDL = 5000;

	log ("SW1.IDN   SW1.ICN :" + SW1.IDN + "/" + SW1.ICN );  Этот лог все корректно показывает.

	SW1.defineRule();

Уверен, мне просто не хватает знаний в JS, помогите, пожалуйста.

polygon, добрый день!
На первый взгляд мне кажется, что проблема связана с тем, что контекст вызова (this) у вас изменяется внутри анонимной функции

function (newValue,devName,cellName)

Нужные вам значения внутри её должны передаваться через devName и cellName

добрый! Да, я тоже так думаю, но как я понимаю, эти свойства нативные, и они передаются вашей системой автоматически и я могу их использовать в функции. Что туда записать что-то иное - я не знаю, а можно? Можно ли туда свои свойства добавить? Я попробую…
Мне советовали уже отходить от ООП, не париться, но тут я не вижу запарки, мне кажется, я верно делаю, ведь думать о разных переменных, пересечениях и т.д. в век, когда космические корабли бороздят просторы вселенной)) Мне кажется, вы создали классный продукт, и мне очень хочется в меру сил использовать его возможности.
Я переделал свой скрипт, который вам присылал в парадигме ООП, учел там некоторые конструкции таймеров, которые прочитал в документации по движку, но не могу проверить работу, у меня просто до таймеров дело не доходит, т.к. проблема с этой областью видимости) А параметры, которые мне придется передавать, их не только имя и значение. Там и сущности, на которые оказывается воздействие, их то куда приставить? Очень надеюсь на вашу помощь или не помощь сообщества в этом вопросе. Если вы не против, я закину вам скрипт полностью, который тут указан, может вам будет проще разобраться, если вы, конечно, посчитаете это возможным.

Сохраните this уровня defineRule в отдельное поле, тогда он будет доступен из then-функции.

this.defineRule = function () {
   var self = this;
....
   then: function (newValue,devName,cellName) {
      log (self.IDN);
   }
}
1 лайк

Большое вам спасибо! У меня заработало после вашего совета. Логика в том, чтобы вовнутрь перенести ссылку, а дальше все, что внутри этой функции, получается, уже видит её. Если, конечно, я правильно понял.

а вы можете меня проконсультировать?

Здравствуйте! Я не совсем понял что такое глобальная функция, это правила? (я не программист)
Как я понимаю, и как обычно, где я сталкивался, это бывало, создавая функцию с уникальным именем все внутренние переменные, которые повторяются в других функциях, никогда не пересекутся. Извините за констатацию очевидного…
Далее про определения правил. Мне, как пользователю, доступно установить имя правила, я так понимаю, оно и должно создавать уникальность, свой контекст.

Пожалуйста, объясните мне, почему вот эти два скрипта работают только по одиночке в контроллере? И логи все пишут верно. Как только я к одному из них добавляю второй, первый работать перестает, логи задваиваются. Я содержимое обоих файлов сразу оборачиваю в функцию, полностью, и вызываю её в конце этого файла. У функций уникальные имена. Внутри функций также поле имени с уникальным содержанием, которое везде добавляется к именам всех правил, делая их уникальными.
Что не так?
Switch_prohod_sw3.txt (3.9 КБ)
Switch_prohod_sw4.txt (3.9 КБ)

скрипты идентичные, меняются только входные данные.

polygon, добрый день!
Сложно разобраться со скриптами – я бы посоветовал оставить “скелет” ваших правил и понять, в каком месте что-то начинает происходить не так, как ожидается. Так и отлаживать проще.
Возникает ли та же ошибка при перезапуске движка правил с подключенными обоими скриптами?

Вот я загружаю оба ваших скрипта:
image
image

Здесь в логах не видно вашу проблему?

Глобальные объекты (речь идет об “области видимости”)-- доступные всему сценарию, судя по коду вы все правильно понимаете.

Вот я загружаю оба, ребучу:

2019-04-26 12:17:04sw4_prochod:Работа проходного выключателя начата
2019-04-26 12:17:04defineRule: sw4_prochod.work
2019-04-26 12:17:04defineRule: sw4_prochod_releaseDelayTimeoutName
2019-04-26 12:17:04sw4_prochod:Работа проходного выключателя начата
2019-04-26 12:17:04defineRule: sw4_prochod.work
2019-04-26 12:17:04defineRule: sw4_prochod_releaseDelayTimeoutName

делаю рестарт правил:
2019-04-26 12:21:53sw3_prochod:Инициализация
2019-04-26 12:21:53sw3_prochod:Инициализация окончена, ожидание запуска
2019-04-26 12:21:53sw4_prochod:Инициализация
2019-04-26 12:21:53sw4_prochod:Инициализация окончена, ожидание запуска
2019-04-26 12:21:53add your rules to /etc/wb-rules/
2019-04-26 12:21:59sw4_prochod:Работа проходного выключателя начата
2019-04-26 12:21:59defineRule: sw4_prochod.work
2019-04-26 12:21:59defineRule: sw4_prochod_releaseDelayTimeoutName
2019-04-26 12:21:59sw4_prochod:Работа проходного выключателя начата
2019-04-26 12:21:59defineRule: sw4_prochod.work
2019-04-26 12:21:59defineRule: sw4_prochod_releaseDelayTimeoutName

Инициализация проходит раздельно, а как только начинается правило все смешивается.

А задайте явно следующие переменные как локальные для соотв. функций sw3_prochod и sw4_prochod:
Например:

image
Должно получиться.

да, так заработало. т.е. если я без var определяю переменную, она становится глобальной?

Да, совершенно верно. Вот прямо цитата из книги JavaScript: The Definitive Guide, Fourth Edition by David Flanagan

“Although you can get away with not using the var statement when you write code in the global scope, you must always use var to declare local variables.”

я читал, что можно и так и так. Буду всегда определять через var. Спасибо!
Я правильно сделал, что обернул в правила код, где вызывается dev? тут нет такой конструкции, вот она:

var f_ini = true;
var initimer = RN + "_initimer";

defineRule(RN + "_initialisation",{
asSoonAs: function(){return f_ini;},
then:function(){
			
	log(RN + ".initialisation: " + "Инициализация устройства " + RN);
	
	defineVirtualDevice(RN, {
		title: RN, 
		cells:{
			start: {
				type: "switch",
				value: false
			},
			sygnal: {
				type: "text",
				value: dev[OUTPUT]
			},  
			interval: {
				type: "text",
				value: INTERVAL/1000
			},
			output: {
				type: "text",
				value: OUTPUT
			}
		}
	});
	
	log(RN + ".initialisation: " + "Инициализация окончена, ожидание запуска" + RN);
	
	f_ini = false;
}

});

верно ли далее как примере, о котором мы говорим, я запускаю обработку сигналов через вермя 5 сек? Чтобы если я создам вирт девайс, а потом с ним работают, с его полями, то надо дать время системе его принять?

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

В случае с виртуальными устройствами логика такая: когда виртуальное устройство создано, появляется соответствующий dev, к свойствам которого вы можете обращаться.

Сложности обычно возникают при старте/инициализации, в тот момент, когда вы не можете понять, создано ли устройство уже. Искусственные задержки (типа этих пяти секунд) позволяют “быть в достаточной степени уверенным”, что движок правил успел загрузить все скрипты и создать все нужные виртуальные устройства.

Код из разных скриптов выполняется последовательно, поскольку движок однопоточный. И если фрагмент кода, ожидающий, что устройство уже создано, выполняется первым, до того, как виртуальное устройство создано, то это приводит к ошибке.

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

так это не программирование, это движок…
У меня в одной функции и создание и обращение. Перекрестных вещей я стараюсь не допускать. Получается, если в этой функции я сначала создам вирт девайс, потом к нему обращусь через время, то сбоев не будет. Какое это время? 5-10 сек или минуты?