[Из песочницы] Как я домофон Vizit к mqtt подключал

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

Собран на скорую руку из того что валялось под ногами было в наличии.В итоге выглядит всё это дело так.

image
Так как у меня уже есть замечательная система автоматизации iobroker было решено подключать к ней для возможности централизованного управления и конфигурации изменения поведения в едином интерфейсе. Настало время выбрать как будет общаться железо и общая система. Что только не приходило в голову в качестве протокола обмена от эмуляции 1wire до get запросов, в итоге победил протокол mqtt как самый удобный в моём видении ситуации, на нём и реализован обмен между железкой и iobroker.

На планшете это выглядит как вкладка с отображением текущей камеры и управлением

image

Часть первая железная. Состоит из arduino uno, ethernet shields, и небольшой схемы согласования с домофонной линией. Сама схема:

image

Тут всё просто, оптопарой отслеживается поступающий звонок и при поступлении просто прижимает нулевую ногу ардуино. Открывание двери реализовано на реле в нормальном состоянии всегда замкнуто, при поступлении команды от iobroker (нажали кнопку в интерфейсе, автоматом по условию в скрипте, поступила команда с телеграмм) разрывает линию на 7.5 секунд, при этом vizit воспринимает это как команду открыть и запускает гостя.

Дополнительно на оптопаре vo2 реализовано автоматическое переключение телевизора в режим AV для отображения с камеры домофона.

Часть вторая программная, которая тоже разделена по сути на двое. Первая — это скетч, который прошивается в ардуино и реализует обмен по протоколу mqtt с системой iobroker.

#include 
#include 
#include 

int flag = 0;

#define ring1_pin 0  //звонок с домофона 1
#define open1_pin 2  //открыть домофон 1
#define open2_pin 3  //открыть домофон 2
#define mon1_pin 5  //сигнал на переключение тв

#define ID_CONNECT "DoorbellControll"

byte mac[]    = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };
byte server[] = { 192, 168, 55, 170 };
byte ip[]     = { 192, 168, 55, 40 };

EthernetClient ethClient;
PubSubClient client(server, 1883, callback, ethClient);

void callback(char* topic, byte* payload, unsigned int length) {
  payload[length] = '\0';
  String strTopic = String(topic);
  String strPayload = String((char*)payload);

  if (strTopic == "myhome/DoorbellControll/open1") {
    if (strPayload == "false") {
      digitalWrite(2, HIGH);
    }
    else if (strPayload == "true") {
      digitalWrite(2, LOW);
    }
  }
  else if (strTopic == "myhome/DoorbellControll/open2") {
    if (strPayload == "false") digitalWrite(3, LOW);
    else if (strPayload == "true") digitalWrite(3, HIGH);
  }
  else if (strTopic == "myhome/DoorbellControll/mon1") {
    if (strPayload == "false") digitalWrite(5, LOW);
    else if (strPayload == "true") digitalWrite(5, HIGH);
  }
}


void reconnect() {
  while (!client.connected()) {
    if (client.connect(ID_CONNECT)) {
      client.subscribe("myhome/DoorbellControll/#");
    } else {
      delay(5000);
    }
  }
}

void setup() {

  pinMode(ring1_pin, INPUT);

  pinMode(open1_pin, OUTPUT);
  digitalWrite(open1_pin, HIGH);

  pinMode(open2_pin, OUTPUT);
  digitalWrite(open2_pin, LOW);

  pinMode(mon1_pin, OUTPUT);
  digitalWrite(mon1_pin, LOW);


  Ethernet.begin(mac, ip);
  if (client.connect("DoorbellControll")) {
    client.publish("myhome/DoorbellControll/open1", "false");
    client.publish("myhome/DoorbellControll/open2", "false");
    client.publish("myhome/DoorbellControll/mon1", "false");
    client.publish("myhome/DoorbellControll/ring1", "false");
    client.subscribe("myhome/DoorbellControll/#");
  }
}
void loop() {
  client.loop();
  //Отслеживаем звонок в домофон
  if (digitalRead(ring1_pin) == LOW && flag == 0) {
    client.publish("myhome/DoorbellControll/ring1", "true");
    flag = 1;//выставляем  переменную flag в единицу
  }
  else if (digitalRead(ring1_pin) == HIGH && flag == 1) {
    client.publish("myhome/DoorbellControll/ring1", "false");
    flag = 0; //обнуляем переменную flag
  }
  if (!client.connected()) {
    reconnect();
    client.subscribe("myhome/DoorbellControll/#");

  }
}


И вторая — скрипт на js для реализации взаимодействия с пользователем:

//************Создаём виртуальные объекты с которыми далее будем взаимодействовать********************
createState('doorbellcontroll.rings', 'false');
createState('doorbellcontroll.visopen', 'false');    //кнопка открыть в vis


on("mqtt.0.myhome.DoorbellControll.ring1", function (obj){
    if  (obj.newState.val == "true" || obj.newState.val === true) {
        setState('javascript.0.doorbellcontroll.rings', true);
    setTimeout(function() {
    }, 60000);
    }
});

//******** Открываем страничку с камерами и управлением, шлём оповещение в телеграм и проговариваем голосом ****************
on("javascript.0.doorbellcontroll.rings", function (obj){
    if  (obj.newState.val == "true" || obj.newState.val === true) {
        setState('sayit.0.tts.text', 'Звонок в домофон');       // Проговариваем оповещение о звонке
        sendTo('telegram.0', 'Звонок в домофон');               // Шлём в телеграм
        setState('mqtt.0.myhome.DoorbellControll.mon1', true);  // Включаем видеовход на телеке
        setState("vis.0.control.command", '{"instance": "FFFFFFFF", "command": "changeView", "data": "Camers"}');   // Переходим на страницу "Камеры"
//*********** Ждём 30 секунд и переходим на главную ********************
    setTimeout(function () {
        setState('mqtt.0.myhome.DoorbellControll.mon1', false); // Выключаем  видеовход на телеке          
        setState("vis.0.control.command", '{"instance": "FFFFFFFF", "command": "changeView", "data": "StartView"}');    // Возвращаемся на страницу "Home"
        setState('javascript.0.doorbellcontroll.rings', false);
    }, 30000);
    }
});

//*******************Ожидает нажатия кнопки "Открыть" в Vis**************
on("javascript.0.doorbellcontroll.visopen", function (obj){
    if  (obj.newState.val == "true" || obj.newState.val === true) {
        setState('mqtt.0.myhome.DoorbellControll.open1', true);     // Открываем двери  
        toLog(' Подъездная дверь открыта. ', true, 'orange');           //Выводим в лог
    
    setTimeout(function () {
        setState('mqtt.0.myhome.DoorbellControll.open1', false);    
        setState('javascript.0.doorbellcontroll.visopen', false);    // Возвращаем статус обратно
    }, 7500);    

    }       
});


В системе iobroker отображается как объекты с которыми можно взаимодействовать.

image

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

© Geektimes