два мажордомо для увеличения надёжности

Использование системы в различных ситуациях, вопросы программирования сценариев.

Модератор: immortal

tokikz
Сообщения: 20
Зарегистрирован: Сб апр 25, 2020 3:07 pm
Благодарил (а): 4 раза
Поблагодарили: 8 раз

два мажордомо для увеличения надёжности

Сообщение tokikz » Ср мар 10, 2021 7:56 pm

Здравствуйте! Я у себя для надёжности хочу сделать два разных аппаратных мажордомо, что-бы одна система страховала вторую. При этом главной нет. Кто первый взял оборудование дома под управление - тот и правит балом. Второй на подхвате седит в сети.
У меня одна система на 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.
Последний раз редактировалось tokikz Пн мар 15, 2021 11:29 pm, всего редактировалось 1 раз.
cheetah
Сообщения: 17
Зарегистрирован: Вт окт 23, 2018 12:22 pm
Благодарил (а): 14 раз
Поблагодарили: 0

Re: два мажордомо для увеличения надёжности

Сообщение cheetah » Чт мар 11, 2021 8:18 am

Тоже задумывался об этом. Смотрел в сторону Heartbeat - там типа плавающие IP и при отказе одного сервера главным назначается второй и наоборот.
Но в итоге отказался от Orange и ушел в сторону полноценного маленького PC без охлаждения. Пока не огорчает.
tokikz
Сообщения: 20
Зарегистрирован: Сб апр 25, 2020 3:07 pm
Благодарил (а): 4 раза
Поблагодарили: 8 раз

Re: два мажордомо для увеличения надёжности

Сообщение tokikz » Чт мар 11, 2021 9:14 am

Вопрос решаем, кто знает как собрать все свойства всех объектов в мажордомо? Предлагаю на "ведущем" мажордомо в методе 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 не работает в это время) . По этому можно подобные функции переложить на страхующий мажордомо.
Вопрос остаётся: как собрать все свойства определённых объектов в текстовую строку?
tokikz
Сообщения: 20
Зарегистрирован: Сб апр 25, 2020 3:07 pm
Благодарил (а): 4 раза
Поблагодарили: 8 раз

Re: два мажордомо для увеличения надёжности

Сообщение tokikz » Чт мар 11, 2021 1:37 pm

Сейчас попробовал остановить циклы мажордомо - не получилось остановить cycle_oprosReset, cycle_rss, cycle_megad. Кто знает почему?
tokikz
Сообщения: 20
Зарегистрирован: Сб апр 25, 2020 3:07 pm
Благодарил (а): 4 раза
Поблагодарили: 8 раз

Re: два мажордомо для увеличения надёжности

Сообщение tokikz » Чт мар 11, 2021 2:48 pm

Извиняюсь, циклы останавливаются и пускаются, только не мгновенно.
tokikz
Сообщения: 20
Зарегистрирован: Сб апр 25, 2020 3:07 pm
Благодарил (а): 4 раза
Поблагодарили: 8 раз

Re: два мажордомо для увеличения надёжности

Сообщение tokikz » Чт мар 11, 2021 8:20 pm

Ура! Удалось настроить два мажордомо. Друг друга страхуют. Опыт покажет.
Chainik
Сообщения: 1462
Зарегистрирован: Вс янв 10, 2016 11:05 am
Благодарил (а): 260 раз
Поблагодарили: 454 раза

Re: два мажордомо для увеличения надёжности

Сообщение Chainik » Чт мар 11, 2021 8:34 pm

А зачем вообще подхватывать статусы в режиме реального времени?
Ну я еще понимаю те случаи, когда без информации из БД нельзя узнать значение того или иного свойства. А если в любой момент можно узнать соответствующий статус, например, опросив порты ваших MegaD, то непрерывное получение этой информации от главного сервера представляется излишним. Как только резервная система "осознала" себя основной, можно и опросить все устройства с обратной связью однократно. Ну и не забыть командой переконфигурировать MegaD, указав им другой сервер.
tokikz
Сообщения: 20
Зарегистрирован: Сб апр 25, 2020 3:07 pm
Благодарил (а): 4 раза
Поблагодарили: 8 раз

Re: два мажордомо для увеличения надёжности

Сообщение tokikz » Чт мар 11, 2021 9:22 pm

Chainik писал(а):
Чт мар 11, 2021 8:34 pm
А если в любой момент можно узнать соответствующий статус, например, опросив порты ваших MegaD, то непрерывное получение этой информации от главного сервера представляется излишним.
Да, вы правы! Я об необходимости передачи данных не о состояния входов/выходов конртоллеров megad, а о состоянии систем дома.
К примеру, автоклав был пущен на приготовление тушёнки. "главный" его разогрел и засёк время на выдерживание при заданной температуре. И в этот момент резервная система "осознала" себя основной. По состоянию портов ей непонятно что делать дальше с разогретым автоклавом.
По этому и нужно передавать "резервному" о своих планах работы того или иного оборудования. У меня для ПВК, автоклава, ректификациоггой колонны создан свой класс с объектами и свойствами, которые помнят шаги выполняемой программы.
Chainik
Сообщения: 1462
Зарегистрирован: Вс янв 10, 2016 11:05 am
Благодарил (а): 260 раз
Поблагодарили: 454 раза

Re: два мажордомо для увеличения надёжности

Сообщение Chainik » Чт мар 11, 2021 9:29 pm

Серьезно все у вас...
Но помимо свойств еще есть "динамические" объекты, таймеры, например. Не думали, как быть с ними?
tokikz
Сообщения: 20
Зарегистрирован: Сб апр 25, 2020 3:07 pm
Благодарил (а): 4 раза
Поблагодарили: 8 раз

Re: два мажордомо для увеличения надёжности

Сообщение tokikz » Чт мар 11, 2021 9:44 pm

таймеры я использую в основном для цикличного вызова скрипка/метода. Для засечки времени использую 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=='Автоклав_яблоки'){ //вкл. Нагрев
.....
Последний раз редактировалось tokikz Пн мар 15, 2021 11:22 pm, всего редактировалось 1 раз.
Ответить