Страница 1 из 2
два мажордомо для увеличения надёжности
Добавлено: Ср мар 10, 2021 7:56 pm
tokikz
Здравствуйте! Я у себя для надёжности хочу сделать два разных аппаратных мажордомо, что-бы одна система страховала вторую. При этом главной нет. Кто первый взял оборудование дома под управление - тот и правит балом. Второй на подхвате седит в сети.
У меня одна система на raspberry pi 3 работает. Вторую установил на orange pi zero (дешёвая и работает пока).
Пока сделал простую проверку на живость систем по методу "пинбола": одна система вызывает в другой системе метод объекта такой-же метод такого-же объекта и запускает таймер на ошибку. Этот таймер в случае успешного выполнения метода сбрасывается, иначе сообщает, что не в порядке соседний мажордомо. Пока так.
Вот рабочие коды методов:
- создал класс "Dva_majordomo", в нём объект "majordomo_moj" и методы:
- takt:
Код: Выделить всё
$Aktivnij=gg("majordomo_moj.Aktivnij"); //своё состояние
$Aktivnij_sosed=$params['Aktivnij']; //состояние соседа
sg("majordomo_moj.Aktivnij_sosed",$Aktivnij_sosed);
sg("majordomo_moj.pinpong",1);
if (($Aktivnij==1) && ($Aktivnij_sosed==1)) { // если все активные, делаю активным только соседа
callMethod('majordomo_moj.Stop_major');
};
if (($Aktivnij==0) && ($Aktivnij_sosed==0)) { // если нет активные, делаю активным себя
callMethod('majordomo_moj.Start_major');
};
clearTimeout("alarm_dvaMD");
$schot=gg("majordomo_moj.schot");
$schot++;
sg("majordomo_moj.schot",$schot);
$vremj=time();
sg("majordomo_moj.time",$vremj);
sg("majordomo_moj.n",0);
setTimeOut("zapros_dvaMD", "callMethod('majordomo_moj.zapros');", 10);
- zapros:
Код: Выделить всё
clearTimeout("zapros_dvaMD");
$Aktivnij=gg("majordomo_moj.Aktivnij");
file_get_contents("http://имя:пароль@ip:80/objects/?object=majordomo_moj&op=m&m=takt&Aktivnij=".$Aktivnij);
setTimeOut("alarm_dvaMD", "callMethod('majordomo_moj.alarm');", 50);
- alarm:
Код: Выделить всё
$n=gg("majordomo_moj.n");
if ($n<3){ //повторяю запросы
$n++;sg("majordomo_moj.n",$n);
setTimeOut("zapros_dvaMD", "callMethod('majordomo_moj.zapros');", 10);
} else {// беру управление на себя, если пинг есть
clearTimeout("alarm_dvaMD");
clearTimeout("zapros_dvaMD");
sg("majordomo_moj.n",0);
sg("majordomo_moj.pinpong",0);
if (file_get_contents("http://192.168.0.12/xxx/?cmd=all")) { // PING до любого контроллера в сети
say("Сосед пропал! Управление беру на себя!");
callMethod('majordomo_moj.Start_major');
} else {
say("Управление отключаю, нет ринга и соседа!",2);
callMethod('majordomo_moj.Stop_major');
};
};
- Start_major:
Код: Выделить всё
setGlobal('cycle_megadControl','start'); //запускаю сервис megad
// и остальные
sg('majordomo_moj.Aktivnij',1);
- Stop_major:
Код: Выделить всё
setGlobal('cycle_megadControl','stop'); //останавливаю сервис megad
// и остальные
sg('majordomo_moj.Aktivnij',0);
Созданы свойства объекта majordomo_moj:
time;
schot=0, постоянно будет увеличиваться;
n=0, 3 попытки связаться с соседним мажордомо;
Aktivnij=0, =1, если этот мажордомо активный;
Aktivnij_sosed=0, =1, если соседний мажордомо активный;
pinpong=0, =1, если связь между мажорами установлена
peredacha - для передачи свойств о состоянии систем дома.
Значения =0 нужно изначально присвоить для исключения ошибок при выполнении кода.
В методе onNewMinute объекта ClockChime раз в час проверяю и запускаю метод takt объекта majordomo_moj:
Код: Выделить всё
if ($m=="00") {
if (gg("majordomo_moj.pinpong")==0) {callMethod('majordomo_moj.takt');}; //попытка запуска "пинпонга" между двумя мажордомо
}
Ещё не добавлена передача важных свойств о состоянии систем дома. Но уже система даст знать о сбое, например через телеграмм и SMS.
Re: два мажордомо для увеличения надёжности
Добавлено: Чт мар 11, 2021 8:18 am
cheetah
Тоже задумывался об этом. Смотрел в сторону Heartbeat - там типа плавающие IP и при отказе одного сервера главным назначается второй и наоборот.
Но в итоге отказался от Orange и ушел в сторону полноценного маленького PC без охлаждения. Пока не огорчает.
Re: два мажордомо для увеличения надёжности
Добавлено: Чт мар 11, 2021 9:14 am
tokikz
Вопрос решаем, кто знает как собрать все свойства всех объектов в мажордомо? Предлагаю на "ведущем" мажордомо в методе zapros собрать все свойства объектов в текстовую строку и отправлять соседнему мажордомо к примеру каждые десять секунд.
Я проверил, простая переменная "peremennaj" передаётся из одного мажора в другой так:
file_get_contents("
http://192.168.0.99:80/objects/?object= ... p=m&m=takt&peremennaj=переменная");
ловится в вызываемом методе так:
$peremennaj=$params['peremennaj']; // получаю переменную
sg("majordomo_moj.sss",$peremennaj); //здесь уже сохраняю переменную куда надо (результат в majordomo_moj.sss "переменная")
А что если переменной будут peremennaj=строка_пар_названия_объект+свойство_и_значний_свойств
И, разложив эту строку, синхронизировать все свойства нужных объектов во втором мажордомо.
Само сабой передавать будет только ведущий (Главный), он-же управлять оборудованием умного дома, а страхующий обновлятьвсе принятые свойства объектов.
Я заметил, что при захвате видео с камеры мажордомом через приложение camshoter и посылкой его телеграмм мажордомо в это время бездействует - не управляет оборудованием (file_get_contents не работает в это время) . По этому можно подобные функции переложить на страхующий мажордомо.
Вопрос остаётся: как собрать все свойства определённых объектов в текстовую строку?
Re: два мажордомо для увеличения надёжности
Добавлено: Чт мар 11, 2021 1:37 pm
tokikz
Сейчас попробовал остановить циклы мажордомо - не получилось остановить cycle_oprosReset, cycle_rss, cycle_megad. Кто знает почему?
Re: два мажордомо для увеличения надёжности
Добавлено: Чт мар 11, 2021 2:48 pm
tokikz
Извиняюсь, циклы останавливаются и пускаются, только не мгновенно.
Re: два мажордомо для увеличения надёжности
Добавлено: Чт мар 11, 2021 8:20 pm
tokikz
Ура! Удалось настроить два мажордомо. Друг друга страхуют. Опыт покажет.
Re: два мажордомо для увеличения надёжности
Добавлено: Чт мар 11, 2021 8:34 pm
Chainik
А зачем вообще подхватывать статусы в режиме реального времени?
Ну я еще понимаю те случаи, когда без информации из БД нельзя узнать значение того или иного свойства. А если в любой момент можно узнать соответствующий статус, например, опросив порты ваших MegaD, то непрерывное получение этой информации от главного сервера представляется излишним. Как только резервная система "осознала" себя основной, можно и опросить все устройства с обратной связью однократно. Ну и не забыть командой переконфигурировать MegaD, указав им другой сервер.
Re: два мажордомо для увеличения надёжности
Добавлено: Чт мар 11, 2021 9:22 pm
tokikz
Chainik писал(а): ↑Чт мар 11, 2021 8:34 pm
А если в любой момент можно узнать соответствующий статус, например, опросив порты ваших MegaD, то непрерывное получение этой информации от главного сервера представляется излишним.
Да, вы правы! Я об необходимости передачи данных не о состояния входов/выходов конртоллеров megad, а о состоянии систем дома.
К примеру, автоклав был пущен на приготовление тушёнки. "главный" его разогрел и засёк время на выдерживание при заданной температуре. И в этот момент резервная система "осознала" себя основной. По состоянию портов ей непонятно что делать дальше с разогретым автоклавом.
По этому и нужно передавать "резервному" о своих планах работы того или иного оборудования. У меня для ПВК, автоклава, ректификациоггой колонны создан свой класс с объектами и свойствами, которые помнят шаги выполняемой программы.
Re: два мажордомо для увеличения надёжности
Добавлено: Чт мар 11, 2021 9:29 pm
Chainik
Серьезно все у вас...
Но помимо свойств еще есть "динамические" объекты, таймеры, например. Не думали, как быть с ними?
Re: два мажордомо для увеличения надёжности
Добавлено: Чт мар 11, 2021 9:44 pm
tokikz
таймеры я использую в основном для цикличного вызова скрипка/метода. Для засечки времени использую time() с записью метки времени в свойство. А в цикле проверяю разницу этой метки с текущим временем для выдержки заданного времени. Как-то так:
Код: Выделить всё
$rejim=gg('Kub.rejim');
$t_rejim=gg('Kub.time');
$vremj=time();
callMethod('ds_Deflegmator.read');
callMethod('ds_niz_kolonna.read');
callMethod('ds_predoxr_vozd.read');
callMethod('ds_kuba.read');
callMethod('D_davlenie_kuba.read');
$p=getGlobal('D_davlenie_kuba.value'); $p--; $p++;
if ($p>2.1){
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '0', dolgno_sost = '0' WHERE imj='ШИМ ТЭН1 колонны';");
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '0', dolgno_sost = '0' WHERE imj='ШИМ ТЭН2 колонны';");
sg('Kub.rejim','Автоклав_авария_Р');
};
$t_kuba=gg('ds_kuba.t');
$t_Deflegmator=gg('ds_Deflegmator.t');
$t_niz_kolonna=gg('ds_niz_kolonna.t');
$t_predoxr_vozd=gg('ds_predoxr_vozd.t');
if ($t_predoxr_vozd>48){
callMethod('TEN1_kuba.off'); callMethod('TEN2_kuba.off'); callMethod('sist_oxlagden.off');
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '0' WHERE imj='Такты от сервера 18'");
sg('Kub.rejim',"Неисправность охлаждения");
};
if ($rejim=="Перегоняй") {
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '50' WHERE imj='Такты от сервера 18'");
callMethod('TEN1_kuba.on');
callMethod('TEN2_kuba.on');
sg('Kub.rejim',"Перегон_нагрев");
sg('Kub.time',$vremj);
};
if ($rejim=="Перегон_нагрев") {
if ($t_Deflegmator>40) {
callMethod('sist_oxlagden.on');
sg('Kub.rejim',"Перегон_пошло");
sg('Kub.time',$vremj);
};
};
if ($rejim=="Перегон_пошло") {
if (($t_niz_kolonna>97) || ($t_Deflegmator>96.5) || ($t_kuba>99)) {
callMethod('TEN1_kuba.off');
callMethod('TEN2_kuba.off');
sg('Kub.rejim',"Перегон_охлажд");
sg('Kub.time',$vremj);
};
};
if ($rejim=="Перегон_охлажд") {
if (($vremj-$t_rejim)>60) {
callMethod('sist_oxlagden.off');
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '0' WHERE imj='Такты от сервера 18'");
sg('Kub.rejim',"Перегон_end");
sg('Kub.time',$vremj);
};
};
if ($rejim=='Автоклав_тушёнка'){ //вкл. Нагрев
say("Разогреваю автоклав.",2);
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '50' WHERE imj='Такты от сервера 18'");
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '100', dolgno_sost = '100' WHERE imj='ШИМ ТЭН1 колонны';");// включаю ТЭН
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '100', dolgno_sost = '100' WHERE imj='ШИМ ТЭН2 колонны';");// включаю ТЭН
sg('Kub.rejim','Автоклав_тушёнка_нагрев_до_103');
sg('Kub.nomer',1); sg('Kub.time',$vremj);
};
if ($rejim=='Автоклав_тушёнка_нагрев_до_103'){ //нагрев до 103 на 2кВт
if ($t_Deflegmator>102){
say("Автоклав нагрелся. t=".$t_Deflegmator.".Таймер на 60 мин",4);
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '100', dolgno_sost = '100' WHERE imj='ШИМ ТЭН1 колонны';");
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '0', dolgno_sost = '0' WHERE imj='ШИМ ТЭН2 колонны';");
sg('Kub.rejim','Автоклав_тушёнка_держи_103');
sg('Kub.nomer',3); sg('Kub.time',$vremj); //засекаю время
};
};
if ($rejim=='Автоклав_тушёнка_держи_103'){
$t_Deflegmator_start=gg('Kub.time');$t_Deflegmator_start--;$t_Deflegmator_start++;
$T_sejchas=time();$T_sejchas--;$T_sejchas++;
if (($T_sejchas-$t_Deflegmator_start)>60*60) { say('Автоклав прокипятил, продолжаю прогрев до 115',4);
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '100', dolgno_sost = '100' WHERE imj='ШИМ ТЭН1 колонны';");
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '100', dolgno_sost = '100' WHERE imj='ШИМ ТЭН2 колонны';");
sg('Kub.rejim','Автоклав_тушёнка_нагрев_до_115');
sg('Kub.nomer',4); sg('Kub.time',$vremj);
} else {
$t_Deflegmatort=round(($T_sejchas-$t_Deflegmator_start)/60);$t_Deflegmatort--;$t_Deflegmatort++;
if (($t_Deflegmatort==0) || ($t_Deflegmatort==10) || ($t_Deflegmatort==20) || ($t_Deflegmatort==30) || ($t_Deflegmatort==40) || ($t_Deflegmatort==50)) {
say('Автоклав t='.$t_Deflegmator.', Р='.$p.', время '.$t_Deflegmatort.' мин.',2);
};
if ($t_Deflegmator<101){ // нагрев до 102 на 1кВт
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '100', dolgno_sost = '100' WHERE imj='ШИМ ТЭН1 колонны';");
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '0', dolgno_sost = '0' WHERE imj='ШИМ ТЭН2 колонны';");
};
if (($t_Deflegmator>102) && ($t_Deflegmator<102)){ // поддержание 102-103 на 0.6кВт
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '60', dolgno_sost = '0' WHERE imj='ШИМ ТЭН1 колонны';");
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '0', dolgno_sost = '0' WHERE imj='ШИМ ТЭН2 колонны';");
};
if ($t_Deflegmator>103) { // при превышении 103 на 0.2кВт
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '10', dolgno_sost = '0' WHERE imj='ШИМ ТЭН1 колонны';");
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '0', dolgno_sost = '0' WHERE imj='ШИМ ТЭН2 колонны';");
};
if ($t_Deflegmator>104) { // при превышении 104 отключаю
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '0', dolgno_sost = '0' WHERE imj='ШИМ ТЭН1 колонны';");
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '0', dolgno_sost = '0' WHERE imj='ШИМ ТЭН2 колонны';");
};
};
};
if ($rejim=='Автоклав_тушёнка_нагрев_до_115'){ //нагрев до 115 на 2кВт
if ($t_Deflegmator>115){
say("Автоклав нагрелся. t=".$t_Deflegmator.".Таймер на 15 мин",4);
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '100', dolgno_sost = '100' WHERE imj='ШИМ ТЭН1 колонны';");
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '0', dolgno_sost = '0' WHERE imj='ШИМ ТЭН2 колонны';");
sg('Kub.rejim','Автоклав_тушёнка_держи_115');
sg('Kub.nomer',5); sg('Kub.time',$vremj); //засекаю время
};
};
if ($rejim=='Автоклав_тушёнка_держи_115'){
$t_Deflegmator_start=gg('Kub.time');$t_Deflegmator_start--;$t_Deflegmator_start++;
$T_sejchas=time();$T_sejchas--;$T_sejchas++;
if (($T_sejchas-$t_Deflegmator_start)>15*60) { say('Автоклав отключён через 40 минут',4);
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '0', dolgno_sost = '0' WHERE imj='ШИМ ТЭН1 колонны';");
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '0', dolgno_sost = '0' WHERE imj='ШИМ ТЭН2 колонны';");
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '0' WHERE imj='Такты от сервера 18'");
sg('Kub.rejim','Автоклав_остываю');
sg('Kub.nomer',6); sg('Kub.time',$vremj);
} else {
$t_Deflegmatort=round(($T_sejchas-$t_Deflegmator_start)/60);$t_Deflegmatort--;$t_Deflegmatort++;
if (($t_Deflegmatort==0) || ($t_Deflegmatort==10) || ($t_Deflegmatort==20) || ($t_Deflegmatort==30) || ($t_Deflegmatort==40) || ($t_Deflegmatort==50)) {
say('Автоклав t='.$t_Deflegmator.', Р='.$p.', время '.$t_Deflegmatort.' мин.',2);
};
if ($t_Deflegmator<114.5){ // нагрев до 114 на 1кВт
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '100', dolgno_sost = '100' WHERE imj='ШИМ ТЭН1 колонны';");
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '0', dolgno_sost = '0' WHERE imj='ШИМ ТЭН2 колонны';");
};
if (($t_Deflegmator>114.5) && ($t_Deflegmator<115.5)){ // поддержание 117-118 на 0.6кВт
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '70', dolgno_sost = '0' WHERE imj='ШИМ ТЭН1 колонны';");
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '0', dolgno_sost = '0' WHERE imj='ШИМ ТЭН2 колонны';");
};
if ($t_Deflegmator>115.5) { // при превышении 118 на 0.2кВт
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '20', dolgno_sost = '0' WHERE imj='ШИМ ТЭН1 колонны';");
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '0', dolgno_sost = '0' WHERE imj='ШИМ ТЭН2 колонны';");
};
if ($t_Deflegmator>116) { // при превышении 123 отключаю
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '0', dolgno_sost = '0' WHERE imj='ШИМ ТЭН1 колонны';");
SQLExec("UPDATE a_out_diskret_ram SET peremennaj = '0', dolgno_sost = '0' WHERE imj='ШИМ ТЭН2 колонны';");
};
};
};
if ($rejim=='Автоклав_яблоки'){ //вкл. Нагрев
.....