Automatización con Pebble conveniente, Noolite estable y esp8266 asequible

Desde el último artículo (el enlace duró casi un año. Y durante este año, repensé algunas cosas, Internet y resultó algo así como IoT :) → Internet de las cosas).

Intentaré resumir una nueva porción del conocimiento acumulado, describir dónde me estoy esforzando y lo que quiero lograr → Le pido que lo lea.

Noolite F v2.0


En el titular, recibí las palabras: guijarro y noolita. ¡Pasemos a ellos!
Todavía manejo con guijarros mi luz noolita, garaje y puerta. Ya se ha escrito mucha información útil sobre noolita, la búsqueda muestra nuevos artículos.

Además de las unidades de primera generación del sistema noolite, tengo nuevas: una unidad de potencia SLF-1-200 (nooLite-F) con retroalimentación ( y cifrado de nueva generación ).

imagen

bloque de alimentación SB-1-150

imagen

y adaptador usb actualizado MTRF-64 USB.

imagen

Toda la luz en mi casa en el sistema de noolita.

Hasta hace poco, tenía un adaptador USB de primera generación con 16 dispositivos y ahora 64 canales (MTRF-64 USB) en el "calambre doméstico del sistema", y también para dispositivos de nueva generación con retroalimentación (noolite F). Pero la tecnología se está moviendo en la dirección correcta, creando dispositivos nuevos y modernos.

Hay 2 opciones más importantes para los nuevos dispositivos: retroalimentación y el principio de identificación de dispositivos por direcciones: ID. Ahora no tiene que escribir dispositivos en el canal 1 y controlar el canal. Ahora puede acceder a un dispositivo específico en un canal por su ID y enviarle un comando de ejecución.

La documentación para los bloques de nueva generación está disponible en el sitio web del fabricante.

Todo funciona a través del puerto serie usando código python.
# -*- coding: utf-8 -*- #!/usr/bin/env python import serial import time class NooLiteCommand: def __init__(self, ch, cmd, mode=0, ctr=0, res=0, fmt=0, d0=0, d1=0, d2=0, d3=0, id0=0, id1=0, id2=0, id3=0): self.st = 171 self.mode = mode self.ctr = ctr self.res = res self.ch = ch self.cmd = cmd self.fmt = fmt self.d0 = d0 self.d1 = d1 self.d2 = d2 self.d3 = d3 self.id0 = id0 self.id1 = id1 self.id2 = id2 self.id3 = id3 self.sp = 172 @property def crc(self): crc = sum([ self.st, self.mode, self.ctr, self.res, self.ch, self.cmd, self.fmt, self.d0, self.d1, self.d2, self.d3, self.id0, self.id1, self.id2, self.id3, ]) return crc if crc < 256 else divmod(crc, 256)[1] def to_bytes(self): return bytearray([ self.st, self.mode, self.ctr, self.res, self.ch, self.cmd, self.fmt, self.d0, self.d1, self.d2, self.d3, self.id0, self.id1, self.id2, self.id3, self.crc, self.sp ]) class NooliteSerial: def __init__(self, tty_name): self.tty = self._get_tty(tty_name) def on(self, ch): self.send_command(ch, 2, 2, 0) pass def off(self, ch): self.send_command(ch, 0, 2, 0) pass def status(self, ch): m = self.send_command(ch, 128, 2, 0) pass def send_command(self, ch, cmd, mode=0, ctr=0, res=0, fmt=0, d0=0, d1=0, d2=0, d3=0, id0=0, id1=0, id2=0, id3=0): command = NooLiteCommand(ch, cmd, mode, ctr, res, fmt, d0, d1, d2, d3, id0, id1, id2, id3) self.tty.write(command.to_bytes()) while True: bytes_response = list(self.tty.read(117)) if bytes_response: all_responses.append(bytes_response) if bytes_response[3] == 0: break else: break return all_responses @staticmethod def _get_tty(tty_name): serial_port = serial.Serial(tty_name, timeout=0.1) if not serial_port.is_open: serial_port.open() serial_port.flushInput() serial_port.flushOutput() return serial_port noo_serial = NooliteSerial('/dev/ttyUSB0') #ch, cmd, mode, ctr #noo_serial.send_command(1, 15, 2, 0) #    1 #noo_serial.send_command(0, 4, 2, 0) #switch #noo_serial.send_command(0, 2, 2, 0) #turn on #noo_serial.send_command(0, 3, 2, 0) #   #noo_serial.send_command(0, 0, 2, 0) #turn off #noo_serial.send_command(0, 15, 2, 0) #  #noo_serial.send_command(0, 128, 2, 0,0,1) #CMD_Read_State + fmt = 1 #noo_serial.on(0) #noo_serial.status(0) #noo_serial.off(0) #noo_serial.off(0) #noo_serial.status(0) #noo_serial.send_command(ch=0,ctr=8, cmd=4, id0=0,id1=0,id2=48,id3=114) #switch noolite ID 0.0.48.114 


Usando las funciones necesarias en el momento adecuado, podemos controlar los bloques de noolita y recibir el estado de los nuevos. Como tengo el 99% de estos bloques antiguos, me queda usar el viejo esquema de escribir 1 bloque en 1 canal, teniendo en cuenta el hecho de que el adaptador usb admite bloques antiguos y nuevos (gracias a los desarrolladores por la compatibilidad sin bailar pandereta). Sobre la marcha, puede administrar y recibir el estado de los nuevos bloques y administrar los antiguos.

Hasta hace poco, no había un solo interruptor de botón en la casa. Tuve que agregar luz al garaje (acabo de llegar para poner las cosas en orden: D), y también apareció un interruptor en la luz de fondo del espejo de maquillaje. Sabiendo que hay una unidad de potencia SB-1-150 , configuré el interruptor normal y conecté la unidad. La retroiluminación del espejo estaba hecha de una placa blanca, bombillas de 3w 4000 K, luz blanca. El SB-1-150 es único porque puede colocarse en la caja del interruptor de pared (interruptor) en el contexto del circuito existente y al conectar un interruptor de botón a la unidad misma.

Exactamente lo que mis chicas necesitan para maquillarse :)
imagen

Guijarro


Cuando comencé a involucrarme en la automatización, uno de los principales factores fue: una gestión competente y conveniente.

Parece conveniente controlar desde un teléfono inteligente, pero ... y no es conveniente cargar la aplicación cada vez, donde hay pequeños botones incómodos, publicidad zurda, o hasta que presionas el botón ... todo deseo desaparece. El control por voz desaparece, ya que también es inconveniente y extraño :): déjalo en las tramas de las películas de ciencia ficción.

imagen

Y resolví el problema de otra manera: a través de un reloj de pulsera, que CONSTANTEMENTE conmigo, no ocupa espacio y combina todas las comodidades, movilidad y velocidad de control. En general, ¡Pebble está vivo! Pero lo más importante es que, para el reloj, aún puede escribir aplicaciones, sus propias aplicaciones, para administrar sus sistemas de automatización. En realidad es una bomba.

Guijarro está vivo!

La tragedia de cerrar la compañía pebble.com (Fitbit compró todas las patentes de pebble.com) no afectó su desempeño y desempeño. Recientemente hubo una actualización de iOS, Android: el reloj se desató de los servicios de nube de guijarros (en caso de finalización del soporte) y autorización.

Visualmente, nada ha cambiado, pero el servicio permanece : cloudpebble.net - WTF? Esto es algo muy útil. Si puede escribir código en JS (y no desea pasar mucho tiempo en C ++), por favor, sea bienvenido a bordo :): el guijarro en la nube le permite "lanzar" rápidamente la aplicación. Bueno, así es como lo hice. Por supuesto, el rendimiento de JS no debe compararse con C ++ (esto es sagrado), debe empantanarse. si!

Código JS de Pebble Cloud para trabajar con API
 var UI = require('ui'); var ajax = require('ajax'); var noolite = [ ['','http://your-home-server-ip-address:1183/mqtt/gate/slidegate', 'images/gate.png'], ['','http://your-home-server-ip-address:1183/mqtt/gate/garage', 'images/door.png'], ['!','http://your-home-server-ip-address:1183/noolite/switch/103', 'images/light.png'], [' ','http://your-home-server-ip-address:1183/noolite/switch/100', 'images/system2.png'], ['1  ','', 'images/light.png'], ['2  ','', 'images/light.png'], [' 1','http://your-home-server-ip-address:1183/noolite/switch/101', 'images/light.png'], [' 2','http://your-home-server-ip-address:1183/noolite/switch/102', 'images/light.png'], ['','', 'images/water.png'], ['','http://your-home-server-ip-address:1183/admin/system/1', 'images/system1.png'], ]; var water = [ [' ','http://your-home-server-ip-address:1183/admin/poliv/1', 'images/water.png'], [' ','http://your-home-server-ip-address:1183/admin/poliv/2', 'images/water.png'], [' 1 ','http://your-home-server-ip-address:1183/noolite/switch/20', 'images/water.png'], [' 2 ','http://your-home-server-ip-address:1183/noolite/switch/21', 'images/water.png'], [' 3 ','http://your-home-server-ip-address:1183/noolite/switch/22', 'images/water.png'], [' 4 ','http://your-home-server-ip-address:1183/noolite/switch/23', 'images/water.png'], [' 5 ','http://your-home-server-ip-address:1183/admin/poliv/switch/5', 'images/water.png'], [' 6 ','http://your-home-server-ip-address:1183/admin/poliv/switch/6', 'images/water.png'], [' 7 ','http://your-home-server-ip-address:1183/admin/poliv/switch/7', 'images/water.png'], [' 8 ','http://your-home-server-ip-address:1183/admin/poliv/switch/8', 'images/water.png'], [' 9 ','http://your-home-server-ip-address:1183/admin/poliv/switch/9', 'images/water.png'], ]; var light1 = [ [' ','http://your-home-server-ip-address:1183/noolite/switch/6', 'images/light.png'], [' ','http://your-home-server-ip-address:1183/noolite/switch/0', 'images/light.png'], ['  ','http://your-home-server-ip-address:1183/noolite/switch/1', 'images/light.png'], ['  ','http://your-home-server-ip-address:1183/noolite/switch/7', 'images/light.png'], ['  ','http://your-home-server-ip-address:1183/noolite/switch/8', 'images/light.png'], [' 1 ','http://your-home-server-ip-address:1183/noolite/switch/2', 'images/light.png'], [' 1 ','http://your-home-server-ip-address:1183/noolite/switch/3', 'images/light.png'], [' 1 ','http://your-home-server-ip-address:1183/noolite/switch/4', 'images/light.png'], [' ','http://your-home-server-ip-address:1183/noolite/switch/5', 'images/light.png'], [' ','http://your-home-server-ip-address:1183/noolite/switch/9', 'images/light.png'], ]; var light2 = [ [' ','http://your-home-server-ip-address:1183/noolite/switch/15', 'images/light.png'], [' ','http://your-home-server-ip-address:1183/noolite/switch/16', 'images/light.png'], [' 2 ','http://your-home-server-ip-address:1183/noolite/switch/10', 'images/light.png'], [' 2 ','http://your-home-server-ip-address:1183/noolite/switch/11', 'images/light.png'], [' 2 ','http://your-home-server-ip-address:1183/noolite/switch/12', 'images/light.png'], [' ','http://your-home-server-ip-address:1183/noolite/switch/13', 'images/light.png'], ['  ','http://your-home-server-ip-address:1183/noolite/switch/14', 'images/light.png'], ]; var menu = new UI.Menu({ sections: [{ items: [{ title: '', subtitle: '' }] }] }); var menu1 = new UI.Menu({ sections: [{ items: [{ title: '', subtitle: '' }] }] }); var menu2 = new UI.Menu({ sections: [{ items: [{ title: '', subtitle: '' }] }] }); var menu3 = new UI.Menu({ sections: [{ items: [{ title: '', subtitle: '' }] }] }); var items = []; for (var i=0; i<noolite.length; i++) { items[i] = { title: noolite[i][0], subtitle: '', icon: noolite[i][2] }; } var items1 = []; for (var i=0; i<light1.length; i++) { items1[i] = { title: light1[i][0], subtitle: '', icon: light1[i][2] }; } var items2 = []; for (var i=0; i<light2.length; i++) { items2[i] = { title: light2[i][0], subtitle: '', icon: light2[i][2] }; } var items3 = []; for (var i=0; i<water.length; i++) { items3[i] = { title: water[i][0], subtitle: '', icon: water[i][2] }; } menu.items(0, items); menu1.items(0, items1); menu2.items(0, items2); menu3.items(0, items3); menu.show(); menu.on('select', function(e) { if (e.itemIndex == 4) { menu1.show(); } else if (e.itemIndex == 5) { menu2.show(); } else if (e.itemIndex ==8) { menu3.show(); } else { var url = noolite[e.itemIndex][1]; console.log(url); ajax({ url: url, method: 'get' }, function(data) { console.log('switched OK'); }, function(error) { // Failure! console.log('error'); } ); } }); menu1.on('select', function(e) { var url = light1[e.itemIndex][1]; console.log(url); ajax({ url: url, method: 'get' }, function(data) { console.log('switched OK'); }, function(error) { // Failure! console.log('error'); } ); }); menu2.on('select', function(e) { var url = light2[e.itemIndex][1]; console.log(url); ajax({ url: url, method: 'get' }, function(data) { console.log('switched OK'); }, function(error) { // Failure! console.log('error'); } ); }); menu3.on('select', function(e) { var url = water[e.itemIndex][1]; ajax({ url: url, method: 'get' }, function(data) { console.log('switched OK'); }, function(error) { // Failure! console.log('error'); } ); }); 


El código está escrito, compilado directamente en el sitio web de Pebble en la nube, y a través del teléfono, descargando la aplicación compilada, puede instalarse en el reloj, en segundos. Todo es tan simple que cualquier joven ingeniero de automatización puede manejarlo;)

Es una pena ... es una pena que Pebble haya dejado de existir y por el momento no veo una alternativa. Pebble Time siempre estará en nuestros corazones!

MQTT


El año pasado, conocí un protocolo tan maravilloso como MQTT (Historia: la primera versión del protocolo fue desarrollada por el Dr. Andy Stanford-Clark (IBM) y Arlene Nipper (Arcom) en 1999 y publicada bajo una licencia libre de regalías. La especificación MQTT 3.1.1 fue estandarizado por el consorcio OASIS en 2014. Enlace ).

Hay mucha información sobre cómo funciona el protocolo y qué son los clientes ... y me decepcionó mucho que no haya clientes reales para aplicaciones móviles, solo en Android.

Entendiendo que la falta de una buena aplicación móvil es un gran problema (agujero) en el campo de IoT (muchas personas dicen, pero hacen muy poco ...) - Yo y mi equipo, en el trabajo, decidimos crear un cliente para Android, iOS, WP para que cumpla con todos los criterios y sea cómodo. Escribiré sobre el cliente un poco más tarde, así como sobre cómo hicimos amigos ESP8266 + MTRF64 (Noolite) y preparamos el firmware de Nodemcu. ¡Será genial, conveniente, barato y hermoso! Sigue las noticias de la aplicación aquí .

imagen

¡Ahora puede controlar la iluminación Noolite sin servidores domésticos y adaptadores usb por $ 50-100!

Esquema general de domótica


El siguiente esquema todavía existe:

Video vigilancia: video vigilancia xeoma [cámara ip]
Servidor en la unidad del sistema: nginx + gunicorn + python + mqtt broker
Gestión: reloj Pebble + cliente MQTT
Módulos de control (nodos del sistema): ESP8266 + optoacopladores \ ds18b20, sensores dht11 [22]

Debido al hecho de que vi muchas comodidades en el protocolo MQTT, comenzando por la arquitectura de suscripción y la comunicación instantánea con dispositivos IoT finales, terminando con el hecho de que los mensajes MQTT pueden volar a través del enrutador sin "reenviar" ningún puerto allí y bailar con una pandereta. Convenientemente! Diviértete! Fervientemente :)

Todo esto me llevó a descentralizar el sistema, es decir, evitar un "korchvagen casero" y cambiar a muchos de los llamados nodos y usar un agente MQTT en la nube (hay agentes MQTT gratuitos, por ejemplo: mqtt.ximxim.com (en el sitio de inicio de sesión y pase para acceder) )) - dado que esp8266 resuelve todos los problemas y, a su vez, funciona a través de wifi utilizando el protocolo MQTT.

Dado que MQTT Buddy proporcionará un servicio de secuencias de comandos, no pensaré en escribir ninguna secuencia de comandos de inicio, simplemente las crearé en una solución en la nube y esto será un IoT real y funcionará. De las palabras a los hechos!

ESP8266


Cuando me familiaricé con esta placa de desarrollo, me impresionó de inmediato el hecho de que la placa es pequeña, hay soporte para el lenguaje de programación LUA en el firmware Nodemcu. Lo que necesitas es un módulo MQTT. En automatización, las soluciones simples y confiables son la base. El costo de $ 2 a $ 5 por una tarifa (para el quinto modelo inmediatamente con un adaptador USB a bordo) le permite implementar rápidamente subsistemas.

La conexión WiFi es rápida, con muchas posibilidades. Por ejemplo: puerta / garaje \ riego \ control de iluminación. Tengo un 30% de riego de césped con el sistema Noolite (bloques de contacto seco), el 70% restante de la placa de desarrollo esp8266 controlada a través del lenguaje LUA utilizando el protocolo MQTT.

Código LUA de muestra para esp8266, obteniendo ip y llamando al archivo de trabajo con MQTT
 --load credentials dofile("credentials.lua") function init(name, pass) wifi.setmode(wifi.STATION) wifi.sta.config(name, pass) wifi.sta.connect() tmr.alarm(0, 1000, 1, function() if wifi.sta.getip()== nil then print("IP unavaiable, Waiting...") else tmr.stop(0) print("Config done, IP is "..wifi.sta.getip()) print("mac : "..wifi.sta.getmac()) dofile("mqtt.lua") end end) end print("START!") init(SSID,PASSWORD) 


- archivo mqtt.lua

 local door = 7 -- gpio13 local window = 6 -- gpio12 local cooler = 5 --gpio14 local led = 4 --GPIO2 board led! LOW == turn ON local light1 = 8 --gpio 15 local light2 = 1 --gpio 5 local light3 = 2 -- gpio 4 function register_myself() m:subscribe("mqtt_buddy/#",0,function(conn) print ("subscribed to Xim mqtt.ximxim.com server") end) end m = mqtt.Client("MQTT_BUDDY_SHOW_ROOM", 120, MQTT_USER, MQTT_PASS) m:on("connect", function(client) print ("connected to Xim mqtt.ximxim.com server") end) m:on("offline", function(client) reconnect_mqtt() end) m:on("message", function(client, topic, data) --print(topic.." data:"..data) if topic == "mqtt_buddy/window" and data == "1" then print "open-close window..." gpio.write(window, gpio.HIGH) gpio.write(led, gpio.LOW) tmr.alarm(1, 1000, tmr.ALARM_SINGLE, function() gpio.write(window, gpio.LOW) gpio.write(led, gpio.HIGH) print "command to close\open window is sent!" end) elseif topic == "mqtt_buddy/door" and data == "1" then print "open-close door..." gpio.write(door, gpio.HIGH) gpio.write(led, gpio.LOW) tmr.alarm(2, 1000, tmr.ALARM_SINGLE, function() gpio.write(door, gpio.LOW) gpio.write(led, gpio.HIGH) print "command to close\open door is sent!" end) elseif topic == "mqtt_buddy/cooler" then if data == "1" then print "switch on fan..." gpio.write(cooler, gpio.HIGH) gpio.write(led, gpio.LOW) else print "switch off fan..." gpio.write(cooler, gpio.LOW) gpio.write(led, gpio.HIGH) end elseif topic == "mqtt_buddy/light1" then if data == "1" then print "switch light1 ON..." gpio.write(light1, gpio.HIGH) gpio.write(led, gpio.LOW) else print "switch light1 off..." gpio.write(light1, gpio.LOW) gpio.write(led, gpio.HIGH) end elseif topic == "mqtt_buddy/light2" then if data == "1" then print "switch light2 ON..." gpio.write(light2, gpio.HIGH) gpio.write(led, gpio.LOW) else print "switch light2 off..." gpio.write(light2, gpio.LOW) gpio.write(led, gpio.HIGH) end elseif topic == "mqtt_buddy/light3" then if data == "1" then print "switch light3 ON..." gpio.write(light3, gpio.HIGH) gpio.write(led, gpio.LOW) else print "switch light3 off..." gpio.write(light3, gpio.LOW) gpio.write(led, gpio.HIGH) end end end) m:connect(MQTT_SERVER, MQTT_SERVER_PORT, 0, function(conn) register_myself() end) 


El problema


En cuanto a una gran comunidad de personas pensantes , quería tocar un tema extremadamente importante, o más bien el problema que quiero resolver, pero no hay suficiente tiempo para una investigación / conocimiento más profundo.

El resultado final: con la descentralización, la videovigilancia permanece, lo que de una forma u otra requiere una máquina host para (mínimo) transferir imágenes de origen a un servidor de videovigilancia (por ejemplo, ivideon) o incluso procesar video en una máquina doméstica, como xeoma (aunque también tienen una nube). de una forma u otra: necesita "AVANZAR" las transmisiones de video, las imágenes para la potencia informática final (soluciones en la nube), o viceversa, para simplificar la transmisión.

Hay pensamientos de recibir imágenes de origen de la cámara (también hay un problema aquí, no todas las cámaras tienen una URL para recibir una imagen de la cámara y generalmente no está claro cómo otros reconocerán esta URL ...) y reenvían al canal MQTT donde se admiten datos binarios (que hay una imagen que se puede transmitir fácilmente a través del protocolo mqtt en forma binaria).

¿Quizás alguien ya ha intentado implementar tales cosas = ESP8266 + cámara web IP?
Responda por favor (bogdanovich.alex [@] gmail.com). Estaré muy agradecido!

Al implementar probros, la pregunta del servidor doméstico desaparecerá. Por qué Porque él come electricidad y calienta mi horno :)

imagen

¡Todo un día positivo y buen humor!

Source: https://habr.com/ru/post/es403273/


All Articles