Detection of a power outage

Salut à tous,

J’ai créé une scène qui pourrait en intéresser quelques un : la détection d’une coupure de courant à la maison et l’alerte via Telegram.

Niveau du scénario : Avancé

Ce scénario utilise des fonctionnalités pas encore présentes dans Gladys. Pour passer outre, j’ai utilisé Node-Red, installé sur le même Raspberry Pi.

:play_button: Documentation officielle de Gladys sur le sujet : Intégrer Node-RED avec Gladys Assistant en MQTT | Gladys Assistant

Prérequis

J’utilise chez moi 100% du Zigbee. Pour cette scène, j’utilise deux composants dont un n’est pas connecté :

Voici un schéma qui représente (dans l’ordre) : la prise connectée, l’onduleur, la multiprise (pour la box fibre) et le raspberry pi avec Gladys et Node Red.

Pourquoi un onduleur ?

Cela permet, en cas de coupure de courant dans la maison, de continuer à alimenter Gladys en électricité.

Comment détecter une panne de courant ?

L’idée est très simple, il y a une panne de courant si :

  • ma prise connectée ne consomme plus d’énergie (attention, si elle est éteinte cela sera aussi détecté)
  • ma prise n’envoie plus de données pendant plus d’une minute

C’est ce second point qui n’est pas encore géré (à ma connaissance) par Gladys à l’heure où j’écris ces lignes.

Configuration de Node Red

Il faut installer Node Red et configurer l’interconnexion avec Zigbee2MQTT (couvert déjà par un grand nombre de tutos).

Schéma général

Comment faire ?

  1. Dans un premier temps, stocker la dernière valeur renvoyée par la prise connectée dans un fichier.




    J’ajoute la brique « Get Complete State » pour m’assurer d’avoir toutes les données de la prise. Ensuite « Add timestamp » me permet d’ajouter la date de la réception des données que je stocke enfin dans un fichier appelé arbitrairement « prise_nous2_last_data.txt ».



  2. Ensuite je lis ce fichier toutes les minutes et je compare la date qu’il contient avec l’heure actuelle moins une minute.





    La brique « Parse JSON » est nécessaire pour pouvoir utiliser les données stockée dans le fichier correctement.


    Puis avec un bloc de fonction, je calcule l’heure en cours, moins une minute :


    Enfin, je procède à deux tests avec les deux briques « switch mode » : si la prise consomme moins de 5W ou si la date a dépassé 1 minute :




    Pour terminer, je créé un message à envoyer dans Telegra avec le dernier bloc « JSON » :

Export JSON Node Red
[
    {
        "id": "877e6dde4f64094e",
        "type": "tab",
        "label": "Panne de courant",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "2d047039d3727cc5",
        "type": "zigbee2mqtt-in",
        "z": "877e6dde4f64094e",
        "name": "PriseNous2 (Onduleur)",
        "server": "6dda341ee7a029cb",
        "friendly_name": "PriseNous2",
        "device_id": "REDACTED",
        "state": "0",
        "outputAtStartup": true,
        "x": 140,
        "y": 160,
        "wires": [
            [
                "9cc8b65f8ce767af"
            ]
        ]
    },
    {
        "id": "c57fa22873f8262e",
        "type": "file",
        "z": "877e6dde4f64094e",
        "name": "Write file",
        "filename": "prise_nous2_last_data.txt",
        "filenameType": "str",
        "appendNewline": false,
        "createDir": false,
        "overwriteFile": "true",
        "encoding": "none",
        "x": 740,
        "y": 160,
        "wires": [
            []
        ]
    },
    {
        "id": "3c9969810f1b7d9c",
        "type": "file in",
        "z": "877e6dde4f64094e",
        "name": "Read file",
        "filename": "prise_nous2_last_data.txt",
        "filenameType": "str",
        "format": "utf8",
        "chunk": false,
        "sendError": false,
        "encoding": "none",
        "allProps": false,
        "x": 300,
        "y": 320,
        "wires": [
            [
                "393212bfa20c5210"
            ]
        ]
    },
    {
        "id": "4f2d7369b4194a31",
        "type": "inject",
        "z": "877e6dde4f64094e",
        "name": "Every minutes",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "10",
        "crontab": "",
        "once": false,
        "onceDelay": "60",
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 140,
        "y": 320,
        "wires": [
            [
                "3c9969810f1b7d9c"
            ]
        ]
    },
    {
        "id": "21bca9ada5443cb1",
        "type": "change",
        "z": "877e6dde4f64094e",
        "name": "Add timestamp",
        "rules": [
            {
                "t": "set",
                "p": "payload.timestamp",
                "pt": "msg",
                "to": "",
                "tot": "date"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 580,
        "y": 160,
        "wires": [
            [
                "c57fa22873f8262e"
            ]
        ]
    },
    {
        "id": "d32f71ec6761bdda",
        "type": "switch",
        "z": "877e6dde4f64094e",
        "name": "Test timestamp",
        "property": "payload.timestamp",
        "propertyType": "msg",
        "rules": [
            {
                "t": "lt",
                "v": "payload.lastminutetimestamp",
                "vt": "msg"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 1,
        "x": 880,
        "y": 320,
        "wires": [
            [
                "cabbc5db0e4652b6",
                "e803e70cdfe1f77a"
            ]
        ]
    },
    {
        "id": "09bee4816c7b6a4b",
        "type": "function",
        "z": "877e6dde4f64094e",
        "name": "Get last 1 minute timestamp",
        "func": "var oneMinInMs = 60000;\nvar lastminute = Date.now() - oneMinInMs;\nmsg.payload.lastminutetimestamp = lastminute;\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 660,
        "y": 320,
        "wires": [
            [
                "d32f71ec6761bdda"
            ]
        ]
    },
    {
        "id": "cabbc5db0e4652b6",
        "type": "debug",
        "z": "877e6dde4f64094e",
        "name": "PANNE DE COURANT",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 910,
        "y": 280,
        "wires": []
    },
    {
        "id": "393212bfa20c5210",
        "type": "json",
        "z": "877e6dde4f64094e",
        "name": "Parse JSON",
        "property": "payload",
        "action": "",
        "pretty": false,
        "x": 450,
        "y": 320,
        "wires": [
            [
                "09bee4816c7b6a4b",
                "af16ab7a64e96d55"
            ]
        ]
    },
    {
        "id": "1868c1c355f975cf",
        "type": "telegram sender",
        "z": "877e6dde4f64094e",
        "name": "Telegram",
        "bot": "REDACTED",
        "haserroroutput": false,
        "outputs": 1,
        "x": 1500,
        "y": 320,
        "wires": [
            []
        ]
    },
    {
        "id": "dfaa974da87838fe",
        "type": "function",
        "z": "877e6dde4f64094e",
        "name": "JSON TELEGRAM",
        "func": "msg.payload = {\n    chatId: REDACTED,\n    type: 'message',\n    content: '⚡‼️ Panne de courant détectée à la maison'\n}\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1330,
        "y": 320,
        "wires": [
            [
                "1868c1c355f975cf"
            ]
        ]
    },
    {
        "id": "e803e70cdfe1f77a",
        "type": "switch",
        "z": "877e6dde4f64094e",
        "name": "Test Power > 5W",
        "property": "payload.power",
        "propertyType": "msg",
        "rules": [
            {
                "t": "lt",
                "v": "5",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 1,
        "x": 1110,
        "y": 320,
        "wires": [
            [
                "dfaa974da87838fe"
            ]
        ]
    },
    {
        "id": "af16ab7a64e96d55",
        "type": "debug",
        "z": "877e6dde4f64094e",
        "name": "READ FILE",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 450,
        "y": 360,
        "wires": []
    },
    {
        "id": "9cc8b65f8ce767af",
        "type": "zigbee2mqtt-get",
        "z": "877e6dde4f64094e",
        "name": "Get Complete State",
        "server": "6dda341ee7a029cb",
        "friendly_name": "PriseNous2",
        "device_id": "REDACTED",
        "state": "0",
        "x": 370,
        "y": 160,
        "wires": [
            [
                "21bca9ada5443cb1"
            ]
        ]
    },
    {
        "id": "6dda341ee7a029cb",
        "type": "zigbee2mqtt-server",
        "name": "Zigbee2MQTT",
        "host": "127.0.0.1",
        "mqtt_port": "1884",
        "mqtt_username": "z2m",
        "mqtt_password": "REDACTED",
        "tls": "",
        "usetls": false,
        "base_topic": "zigbee2mqtt"
    },
    {
        "id": "1008fcc5ae346779",
        "type": "telegram bot",
        "botname": "Node Red Gladys Ermont",
        "usernames": "",
        "chatids": "REDACTED",
        "baseapiurl": "",
        "updatemode": "polling",
        "pollinterval": "300",
        "usesocks": false,
        "sockshost": "",
        "socksport": "6667",
        "socksusername": "anonymous",
        "sockspassword": "",
        "bothost": "",
        "botpath": "",
        "localbotport": "8443",
        "publicbotport": "8443",
        "privatekey": "",
        "certificate": "",
        "useselfsignedcertificate": false,
        "sslterminated": false,
        "verboselogging": false
    }
]

Conclusion

Si mon onduleur ne consomme plus de courant, c’est qu’il n’y a plus d’électricité à la maison. Dans ce cas, la prise connectée sur laquelle l’onduleur est connecté ne consommera plus de courant ou n’enverra plus de données.
Node Red me permet de réaliser cela assez facilement en réalité.

N’hésitez pas à me faire vos retours s’il faut expliciter encore plus certaines parties !

8 Likes

Great tutorial!

I might set it up at home because I’m already equipped with a UPS and a smart plug.
So far I rely on notifications from my NAS that tell me when it has switched to the UPS… But an integrated solution in Gladys would be great!

Actually, in the long run I think I’ll use/create a UPS dedicated to Gladys on my Pi, that way I could have a VERY long runtime in case of a power outage, and wouldn’t lose my home monitoring/alarm scenes :+1:

2 Likes

Thanks for this super-comprehensive tutorial @lmilcent! I edited the Domadoo link with an affiliate link as requested :wink:

2 Likes

Thanks :blush:
And yes, might as well let everyone benefit (tutorial and affiliate link!).

I find it interesting to have this kind of scene presentation; it can spark ideas.

1 Like