Off и On - тут всё понятно. Работает как обычный выключатель, но при этом запрещает автоматическое управление. Например нам нужно, чтобы свет горел постоянно, а не погасал при отсутствии активности в комнате. Либо наоборот, мы меняем лампочку, и нам не нужно чтобы он включился.
Auto - В этом режиме реле будет слушаться логики. Например включаться при движении когда темно.
Time - Реле включится на время.
Теперь подробнее:
Разберем Авто режим. Я упомянул слово "Логика". Суть умного дома, это не включать лампочку с телефона. А действовать по заранее установленным правилам. И эти правила надо где то записывать. К этой теме следующий абзац не относится, но он нужен, чтобы объяснить принцип работы кнопки выключателя. Вы легко переделайте всё на свою конструкцию. А вот как у меня. Вся логика хранится в методах объектов реле класса Relays.
Свойства:
status - Стандартное свойство показывающее состояние контактов реле.
modeSwitch - мое свойство, связанное с радио переключателем. Может иметь значения 0,1,2,3 соответствующие кнопкам скрина.
bottonColor - цвет кнопки выключателя, когда реле включено. В обычном выключателе и так понятно его состояние. А тут, при режиме Авто или таймер, состояние можно определить по цвету кнопки. Теперь методы класса:
turnOn - Стандартный метод включения реле. При его вызове, в общем коде метода устанавливается свойство status. Добавим туда еще и установку нашего нового свойства modeSwitch. Оно будет дублировать свойство status только в режимах Вкл и Выкл. Проверка is_numeric() не даст записать в это свойство, если оно не было задействовано ранее для объекта реле. Их же у нас много, а такие переключатели нужны далеко не для всех. И ещё, при выполнении turnOn, свойство modeSwitch будет установлено 1 только если ранее было именно 0.
Код: Выделить всё
$this->setProperty('status', 1);
$a=$this->getProperty('modeSwitch') ;
if (is_numeric($a) && $a==0) {
$this->setProperty('modeSwitch', 1);
}
Код: Выделить всё
$this->setProperty('status', 0);
if ($this->getProperty('modeSwitch') == 1) {
$this->setProperty('modeSwitch', 0);
}
logic - новый метод. В нем я и храню логику. Этот общий метод будет выполняться перед кодом метода объекта. Если свойство modeSwitch не задано, ничего не делаем. При 0 выключаем реле, при 1 включаем. Это позволит выключать или выключать реле несмотря на условия логики, если мы выбрали кнопку вкл или выкл на радио переключателе. В общем коде метода напишем
Код: Выделить всё
$ms=$this->getProperty('modeSwitch');
if (!is_numeric($ms)) {
return;
} elseif ($ms==0) {
$this->callMethod('turnOff');
} elseif ($ms==1) {
$this->callMethod('turnOn');
}
В его методе turnOn добавим код установки цвета активной кнопки
Код: Выделить всё
$this->setProperty('bottonColor','#ff0000');
Код: Выделить всё
$this->setProperty('bottonColor',NULL);
Код: Выделить всё
$this->callMethod('turnOff');
Название:Лампочка%testRelay.bottonColor%
testRelay это имя нашего объекта класса Relays. %testRelay.bottonColor% добавит в конец код цвета кнопки. Его не будет видно.
Данные:
0|Off
1|On
2|Auto
3|Time
Связанный объект: укажем наш объект testRelay
Свойство: modeSwitch
Только чтение: Да Это очень важно, т.к. изменения состояния в свойство modeSwitch мы будем передавать в коде ниже
Код:
Код: Выделить всё
$n='testRelay';
$obj=getObject($n);
clearTimeOut($n.'_work');
switch ($params['VALUE']) {
case 0: // Off
$obj->setProperty('modeSwitch',0);
$obj->callMethod('turnOff');
break;
case 1: // On
$obj->setProperty('modeSwitch',1);
$obj->callMethod('turnOn');
break;
case 2: // Auto
if ($obj->getProperty('modeSwitch')==2) {
$obj->callMethod('switch');
} else {
$obj->setProperty('modeSwitch',2);
$obj->callMethod('logic');
}
break;
case 3: // Time
// После выбора Time возврат на Off если было Off, On или Time
// Возврат на Auto если было выбрано ранее
$m=$obj->getProperty('modeSwitch');
if (in_array($m, [0, 1, 3])) { $s="sg('$n.modeSwitch',0); cm('$n.turnOff');"; }
if ($m == 2) { $s="sg('$n.modeSwitch',2); cm('$n.logic');"; }
// Установить таймер активности в комнате.
setTimeOut($n.'_work',$s, 5*60);
$obj->setProperty('modeSwitch',3);
$obj->callMethod('turnOn');
}
Рассмотрим как работает код. $params['VALUE'] содержит значение нажатой кнопки.
Если мы нажали Off, то записываем в modeSwitch 0 и выключаем реле. On - по аналогии.
2 - Auto. Тут вся хитрость. Если это повторное нажатие кнопки, то инвертируем состояние реле. Если до этого был выбран другой режим, то запускаем метод logic, который решит, нужно ли реле работать. Если у вас логика находится в другом месте, то тут нужно будет вызвать код, в котором принимается решение.
3 - Time. Если ранее был выбран режим On или Off, то по истечении таймера выбираем режим Off. Если ранее был Auto, то его и вернем, но проверим логику. Если повторно нажать на кнопку Time, то таймер будет пересоздан, и возврата на предыдущий режим не будет. Полезно при сознательном уходе с режима Auto, если мы не хотим, чтобы реле включилось потом по условиям логики.
Всё уже должно работать! Кроме условий логики, к которым я обещал вернуться в конце.
Код метода logic в объекте реле. Я взял самый простой пример. Разберем его работу.
Если modeSwitch 0 или 1, то ничего не проверяем. Реле будет включено или выключено в родительском коде метода. Если modeSwitch не задан, то код всё равно будет работать, т.к. я использую его и для некоторых объектов, у которых нет переключателей в меню. Далее комментарии в коде всё объясняют.
Код: Выделить всё
// прервать выполнение если modeSwitch число и оно <2
$ms=$this->getProperty('modeSwitch');
if (is_numeric($ms) && $ms<2) { return; }
// Проверка свойств объектов, которые могут изменить решение
$ot = $this->object_title;
$f = 0; // Предполагаем, что реле будет выключено
// включить при активности в комнате когда стемнело
if (gg('HallArea.SomebodyHere')) {
if (gg('HallArea.Luminiscence') < 40) {
$f = 1;
}}
// включить при существовании таймера
if (timeOutExists($ot.'_work')) { $f = 1; }
// выполнить
$s=$this->getProperty('status');
if ($f>$s) { $this->callMethod('turnOn'); }
if ($f<$s) { $this->callMethod('turnOff'); }