Automatisation avec Pebble pratique, Noolite stable et esp8266 abordable

Depuis le dernier article (le lien a duré presque un an. Et au cours de cette année, j'ai repensé certaines choses, Internet et il s'est avéré quelque chose comme l'IoT :) → l'Internet des objets).

J'essaierai de résumer une nouvelle partie des connaissances accumulées, de décrire où je m'efforce et ce que je veux atteindre → je vous demande de lire.

Noolite F v2.0


Dans le titre, j'ai eu les mots: galets et noolite. Passons à eux!
Je gère toujours avec des galets ma lumière noolite, mon garage et mon portail. Beaucoup d'informations utiles ont déjà été écrites sur noolite, la recherche montre de nouveaux articles.

En plus des unités de première génération du système noolite, j'en ai de nouvelles: une unité de puissance SLF-1-200 (nooLite-F) avec rétroaction ( et cryptage de nouvelle génération ).

image

bloc d'alimentation SB-1-150

image

et adaptateur USB MTRF-64 USB mis à jour.

image

Toute la lumière dans ma maison sur le système noolite.

Jusqu'à récemment, j'avais un adaptateur USB de première génération avec 16 appareils et maintenant 64 canaux (MTRF-64 USB) dans le «système home cramp», ainsi que pour les appareils de nouvelle génération avec rétroaction (noolite F). Mais la technologie évolue dans la bonne direction, créant de nouveaux appareils modernes.

Il existe 2 options les plus importantes pour les nouveaux appareils: le feedback et le principe d'identification des appareils par adresses: ID. Désormais, il n'est plus nécessaire d'écrire des périphériques sur le canal 1 et de contrôler le canal. Vous pouvez maintenant accéder à un périphérique spécifique dans un canal par son ID et lui envoyer une commande d'exécution.

La documentation des blocs de nouvelle génération est disponible sur le site Web du fabricant.

Tout fonctionne via le port série en utilisant du code 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 


En utilisant les fonctions nécessaires au bon moment, nous pouvons contrôler les blocs noolite et recevoir le statut des nouveaux. Comme j'ai 99% de ces anciens blocs, il me reste à utiliser l'ancien schéma d'écriture de 1 bloc sur 1 canal, en tenant compte du fait que l'adaptateur USB prend en charge les anciens et les nouveaux blocs (merci aux développeurs pour la compatibilité sans danse du tambourin). À la volée, vous pouvez gérer et recevoir l'état des nouveaux blocs et gérer les anciens.

Jusqu'à récemment, il n'y avait pas un seul interrupteur à bouton-poussoir dans la maison. J'ai dû ajouter de la lumière au garage (je suis juste arrivé pour mettre les choses en ordre: D), et aussi un interrupteur est apparu dans le rétro-éclairage du miroir de maquillage. Sachant qu'il existe une unité d'alimentation SB-1-150 , j'ai réglé l'interrupteur normal et connecté l'unité. Le rétro-éclairage du miroir était constitué d'une plaque blanche, ampoules 3w 4000 K, lumière blanche. Le SB-1-150 est unique en ce qu'il peut être placé dans la boîte de l'interrupteur mural (interrupteur) dans le contexte du circuit existant et en connectant un interrupteur à bouton-poussoir à l'unité elle-même.

Exactement ce dont mes filles ont besoin pour le maquillage :)
image

Caillou


Lorsque j'ai commencé à m'impliquer dans l'automatisation, l'un des principaux facteurs était: une gestion compétente et pratique.

Il semble commode de contrôler à partir d'un smartphone, mais ... et ce n'est pas pratique de charger l'application à chaque fois, où il y a de petits boutons inconfortables, de la publicité pour gauchers, ou jusqu'à ce que vous arriviez à appuyer sur le bouton ... tout désir disparaît. La commande vocale disparaît, car elle est également gênante et étrange :) - laissez-la rester dans les intrigues des films de science-fiction.

image

Et j'ai résolu le problème d'une autre manière - grâce à une montre-bracelet, qui, CONSTAMMENT avec moi, ne prend pas de place et combine toutes les commodités, la mobilité et la vitesse de contrôle. Généralement - Pebble est vivant! Mais le plus important est que, pour l'horloge, vous pouvez toujours écrire des applications - vos propres applications, pour gérer vos systèmes d'automatisation. C’est en fait une bombe.


La tragédie de la fermeture de la société pebble.com (Fitbit a acheté tous les pebble.com pour des brevets) n'a pas affecté leurs performances et leurs performances. Récemment, il y a eu une mise à jour d'ios, android - la montre a été détachée des services cloud de galets (en cas de cessation du support) et de l'autorisation.

Visuellement - rien n'a changé, mais le service reste : cloudpebble.net - WTF? C'est une chose très utile. Si vous pouvez écrire du code en JS (et que vous ne souhaitez pas passer beaucoup de temps sur C ++) - veuillez vous féliciter à bord :) - Cloud Pebble vous permet de "lancer" rapidement l'application. C'est comme ça que je l'ai fait. Bien sûr, les performances de JS ne doivent pas être comparées à C ++ (c'est sacré), être enlisées. oui!

Code JS Pebble Cloud pour travailler avec l'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'); } ); }); 


Le code est écrit, compilé directement sur le site Web Pebble du cloud et, via le téléphone, téléchargeant l'application compilée, peut être installé sur l'horloge - en quelques secondes. Tout est si simple que tout jeune ingénieur en automatisation peut le gérer;)

C'est dommage ... c'est dommage que Pebble ait cessé d'exister et pour le moment je ne vois pas d'alternative. Pebble Time sera toujours dans nos cœurs!

MQTT


L'année dernière, j'ai rencontré un protocole aussi merveilleux que MQTT (Historique: La première version du protocole a été développée par le Dr Andy Stanford-Clark (IBM) et Arlene Nipper (Arcom) en 1999 et publiée sous une licence libre de droits. La spécification MQTT 3.1.1 était normalisé par le consortium OASIS en 2014. Lien ).

Il y a beaucoup d'informations sur le fonctionnement du protocole et ce que sont les clients ... et j'ai été très déçu qu'il n'y ait pas de vrais clients pour les applications mobiles, uniquement sur Android.

Comprendre que le manque d'une bonne application mobile est un très gros problème (trou) dans le domaine de l'IoT (beaucoup de gens disent, mais ils font très peu ....) - Moi et mon équipe, au travail, avons décidé de créer un client pour android, ios, wp pour qu'il réponde à tous les critères et soit confortable. J'écrirai un peu plus tard sur le client, ainsi que sur la façon dont nous nous sommes fait des amis ESP8266 + MTRF64 (Noolite) et avons préparé le firmware Nodemcu. Ce sera génial, pratique, bon marché et beau! Suivez l'actualité de l'application ici .

image

Vous pouvez maintenant contrôler l'éclairage Noolite sans aucun serveur domestique ni adaptateur USB pour 50 à 100 $!

Schéma général de la domotique


Le schéma suivant existe toujours:

Vidéosurveillance: vidéosurveillance xeoma [caméra ip]
Serveur sur l'unité centrale: nginx + gunicorn + python + mqtt broker
Gestion: montre Pebble + client MQTT
Modules de commande (nœuds système): ESP8266 + optocoupleurs \ ds18b20, capteurs dht11 [22]

En raison du fait que j'ai vu de nombreuses commodités dans le protocole MQTT, à partir de l'architecture d'abonnement et de la communication instantanée avec les appareils IoT finaux, se terminant par le fait que les messages MQTT peuvent traverser le routeur sans «transférer» aucun port là-bas et danser avec un tambourin. Idéalement! Amuse toi bien! Avec ferveur :)

Tout cela m'a amené à décentraliser le système, c'est-à-dire à éviter un «home korchvagen» et à passer à de nombreux soi-disant nœuds et à utiliser un courtier MQTT cloud (il existe des courtiers MQTT gratuits, par exemple: mqtt.ximxim.com (sur le site, connectez-vous et passez pour y accéder). )) - puisque esp8266 résout tous les problèmes, et cela, à son tour, fonctionne via wifi en utilisant le protocole MQTT.

Étant donné que MQTT Buddy fournira un service de script, je ne penserai pas à écrire des scripts à la maison, je vais juste les créer dans une solution cloud et ce sera un véritable IoT et cela fonctionnera! Des paroles aux actes!

ESP8266


Lorsque j'ai fait connaissance avec cette carte de développement, j'ai été immédiatement impressionné par le fait que la carte est petite, il existe un support pour le langage de programmation LUA sur le firmware Nodemcu. Ce dont vous avez besoin + module MQTT est. Dans l'automatisation, des solutions simples et fiables sont le fondement. Le coût de 2 $ à 5 $ pour une taxe (pour le 5ème modèle immédiatement avec un adaptateur USB à bord) vous permet de déployer rapidement des sous-systèmes.

La connexion WiFi est rapide, de nombreuses possibilités. Par exemple: portail / garage \ arrosage \ contrôle d'éclairage. J'ai 30% d'irrigation de pelouse alimenté par le système Noolite (blocs de contact sec), les 70% restants de la carte de développement esp8266 contrôlés via le langage LUA en utilisant le protocole MQTT.

Exemple de code LUA pour esp8266, obtention de l'ip et appel du fichier de travail avec 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) 


- fichier 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) 


Le problème


S'agissant d'une vaste communauté de personnes qui réfléchissent , je voulais aborder un sujet extrêmement important, ou plutôt le problème que je veux résoudre, mais il n'y a pas assez de temps pour des recherches / connaissances plus approfondies.

L'essentiel: avec la décentralisation, la vidéosurveillance demeure, ce qui nécessite d'une manière ou d'une autre une machine hôte pour transférer (minimum) les images source vers un serveur de surveillance vidéo (par exemple ivideon) ou même pour traiter la vidéo sur une machine domestique, comme xeoma (bien qu'ils aient également un cloud) - d'une manière ou d'une autre - vous devez «AVANCE» les flux vidéo, les images pour la puissance de calcul finale (solutions cloud) - ou vice versa - pour simplifier la diffusion en continu.

On pense à recevoir des images sources de la caméra (il y a aussi un problème ici, toutes les caméras n'ont pas d'URL pour recevoir une image de la caméra et il est généralement difficile de savoir comment les autres reconnaîtront cette URL ....) et à transmettre au canal MQTT où les données binaires sont prises en charge (que il y a une image qui peut être facilement transmise via le protocole mqtt sous forme binaire).

Peut-être que quelqu'un a déjà essayé de mettre en œuvre de telles choses = ESP8266 + webcam Web IP?
Répondez s'il vous plaît (bogdanovich.alex [@] gmail.com). Je vous en serai très reconnaissant!

Lors de la mise en œuvre de probros, la question du serveur domestique disparaîtra. Pourquoi? Parce qu'il mange de l'électricité et chauffe ma fournaise :)

image

Bonne journée et bonne humeur!

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


All Articles