Tutorial - Display the weather alert for your department

Hello,

I will show you here how to display the French weather vigilance in Gladys according to your department.
The maps come from: https://public-api.meteofrance.fr

The final result:

First, you need to create an account and retrieve an API key on the website:

https://portail-api.meteofrance.fr/web/fr/

Here is the Node-Red flow:
( A catch all is present to retrieve errors and send them by email )

Here is the flow in JSON format to import it into your Node-Red:

[
    {
        "id": "a00c3f3cd891b014",
        "type": "tab",
        "label": "Flux - Weather Alert",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "e93503b1.48125",
        "type": "http request",
        "z": "a00c3f3cd891b014",
        "name": "",
        "method": "GET",
        "ret": "obj",
        "paytoqs": "ignore",
        "url": "https://public-api.meteofrance.fr/public/DPVigilance/v1/cartevigilance/encours",
        "tls": "",
        "persist": false,
        "proxy": "",
        "insecureHTTPParser": false,
        "authType": "",
        "senderr": false,
        "headers": [
            {
                "keyType": "other",
                "keyValue": "apikey",
                "valueType": "other",
                "valueValue": "aremplacer"
            }
        ],
        "x": 250,
        "y": 780,
        "wires": [
            [
                "d7e78e8a.b142d"
            ]
        ]
    },
    {
        "id": "d7e78e8a.b142d",
        "type": "function",
        "z": "a00c3f3cd891b014",
        "name": "Extract department data",
        "func": "var result = {\n    details: {\n        domain_max_color_id_today: msg.payload.product.periods[0].timelaps.domain_ids[63].max_color_id,\n        domain_max_color_id_tomorrow: msg.payload.product.periods[1].timelaps.domain_ids[63].max_color_id,\n        update_time: msg.payload.product.update_time\n    },\n    today: msg.payload.product.periods[0].timelaps.domain_ids[63].phenomenon_items.sort(function(a, b) { return a.phenomenon_id - b.phenomenon_id }),\n    tomorrow: msg.payload.product.periods[1].timelaps.domain_ids[63].phenomenon_items.sort(function(a, b) { return a.phenomenon_id - b.phenomenon_id })\n};\n\nmsg.payload = result;\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 510,
        "y": 780,
        "wires": [
            [
                "765139f164b27104",
                "2e8c0dbf61392f10",
                "5311430ac329529a",
                "f8dee65916cd81fd",
                "4f34ac8f589740bf",
                "b2c6e79083051293",
                "3fe286c93a1868c1",
                "21f9b08907f80164",
                "a3277ab55636ee8d",
                "4a1de7f5499804d4",
                "d3d5649284b15e63",
                "90475b38dffb2d44",
                "6a165e40ca126eae",
                "8ded2eea3075dbe6",
                "d1ad6fe78c581801"
            ]
        ]
    },
    {
        "id": "e78c09208c33d102",
        "type": "cronplus",
        "z": "a00c3f3cd891b014",
        "name": "Cron",
        "outputField": "payload",
        "timeZone": "",
        "storeName": "",
        "commandResponseMsgOutput": "output1",
        "defaultLocation": "",
        "defaultLocationType": "default",
        "outputs": 1,
        "options": [
            {
                "name": "schedule1",
                "topic": "topic1",
                "payloadType": "default",
                "payload": "",
                "expressionType": "cron",
                "expression": "0 * * * *",
                "location": "",
                "offset": "0",
                "solarType": "all",
                "solarEvents": "sunrise,sunset"
            }
        ],
        "x": 70,
        "y": 780,
        "wires": [
            [
                "e93503b1.48125"
            ]
        ]
    },
    {
        "id": "765139f164b27104",
        "type": "function",
        "z": "a00c3f3cd891b014",
        "name": "Extract today's department alert level",
        "func": "var json = msg.payload;\n\n// Check if the JSON is valid\nif (json && json.details && json.details.domain_max_color_id_today !== undefined) {\n    var domainMaxColorIdToday = json.details.domain_max_color_id_today;\n    \n    let levelNumber = '';\n    switch (domainMaxColorIdToday) {\n        case 1:\n            levelNumber = 0\n            break;\n        case 2:\n            levelNumber = 1\n            break;\n        case 3:\n            levelNumber = 2\n            break;\n        default:\n            levelNumber = 3\n            break;\n    }\n    return {\n        payload: levelNumber\n    };\n} else {\n    // If the JSON is not valid, return an error message\n    node.error('No values');\n    return null;\n}\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 880,
        "y": 400,
        "wires": [
            [
                "3d49197f8d7f40e7"
            ]
        ]
    },
    {
        "id": "2e8c0dbf61392f10",
        "type": "function",
        "z": "a00c3f3cd891b014",
        "name": "Extract tomorrow's department alert level",
        "func": "var json = msg.payload;\n\n// Check if the JSON is valid\nif (json && json.details && json.details.domain_max_color_id_tomorrow !== undefined) {\n    var domainMaxColorIdTomorrow = json.details.domain_max_color_id_tomorrow;\n\n    let levelNumber = '';\n    switch (domainMaxColorIdTomorrow) {\n        case 1:\n            levelNumber = 0\n            break;\n        case 2:\n            levelNumber = 1\n            break;\n        case 3:\n            levelNumber = 2\n            break;\n        default:\n            levelNumber = 3\n            break;\n    }\n    return {\n        payload: levelNumber\n    };\n} else {\n    // If the JSON is not valid, return an error message\n    node.error('No values');\n    return null;\n}\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 890,
        "y": 460,
        "wires": [
            [
                "6e3d0819638abd47"
            ]
        ]
    },
    {
        "id": "5311430ac329529a",
        "type": "function",
        "z": "a00c3f3cd891b014",
        "name": "Extract department alert update date",
        "func": "var json = msg.payload;\n\n// Check if the JSON is valid\nif (json && json.details && json.details.update_time !== undefined) {\n    var updateTime = json.details.update_time;\n\n    // Convert the update_time value to the desired format\n    var formattedUpdateTime = new Date(updateTime).toLocaleString('fr-FR', {\n        day: '2-digit',\n        month: '2-digit',\n        year: 'numeric',\n        hour: '2-digit',\n        minute: '2-digit'\n    });\n\n    // Create a new message with the formatted update_time value\n    msg.payload = formattedUpdateTime;\n\n    // Send the modified message\n    return msg;\n} else {\n    // If the JSON is not valid, return an error message\n    node.error('Invalid JSON or missing property');\n    return null;\n}\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 900,
        "y": 520,
        "wires": [
            [
                "365325afee9a62cc"
            ]
        ]
    },
    {
        "id": "f8dee65916cd81fd",
        "type": "function",
        "z": "a00c3f3cd891b014",
        "name": "Extract today's wind alert for the department",
        "func": "var json = msg.payload;\n\n// Check if the JSON is valid\nif (json && json.today) {\n    // Search for the item in the \"today\" array where \"phenomenon_id\" is equal to 1\n    var phenomenonItem = json.today.find(item => item.phenomenon_id === \"1\");\n    let levelNumber = '';\n\n    if (phenomenonItem && phenomenonItem.phenomenon_max_color_id !== undefined) {\n        var phenomenonMaxColorId = phenomenonItem.phenomenon_max_color_id;\n        switch (phenomenonMaxColorId) {\n            case 1:\n                levelNumber = 0\n                break;\n            case 2:\n                levelNumber = 1\n                break;\n            case 3:\n                levelNumber = 2\n                break;\n            default:\n                levelNumber = 3\n                break;\n        }\n        return {\n            payload: levelNumber\n        };\n    } else {\n        // If phenomenon_id is not found or phenomenon_max_color_id is undefined, return an error message\n        levelNumber = 4\n        return {\n            payload: levelNumber\n        };\n    }\n} else {\n    // If the JSON is not valid or properties are missing, return an error message\n    node.error('Invalid JSON or missing property');\n    return null;\n}\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 930,
        "y": 580,
        "wires": [
            [
                "6f61d33cbc59185b"
            ]
        ]
    },
    {
        "id": "4f34ac8f589740bf",
        "type": "function",
        "z": "a00c3f3cd891b014",
        "name": "Extract wind alert for tomorrow for the department",
        "func": "var json = msg.payload;\n\n// Check if the JSON is valid\nif (json && json.tomorrow) {\n    // Search for the item in the \"tomorrow\" array where \"phenomenon_id\" is equal to 1\n    var phenomenonItem = json.tomorrow.find(item => item.phenomenon_id === \"1\");\n    let levelNumber = '';\n    \n    if (phenomenonItem && phenomenonItem.phenomenon_max_color_id !== undefined) {\n        var phenomenonMaxColorId = phenomenonItem.phenomenon_max_color_id;\n        switch (phenomenonMaxColorId) {\n            case 1:\n                levelNumber = 0\n                break;\n            case 2:\n                levelNumber = 1\n                break;\n            case 3:\n                levelNumber = 2\n                break;\n            default:\n                levelNumber = 3\n                break;\n        }\n        return {\n            payload: levelNumber\n        };\n    } else {\n        // If phenomenon_id is not found or phenomenon_max_color_id is undefined, return an error message\n        levelNumber = 4\n        return {\n            payload: levelNumber\n        };\n    }\n} else {\n    // If the JSON is not valid or properties are missing, return an error message\n    node.error('Invalid JSON or missing property');\n    return null;\n}\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 940,
        "y": 640,
        "wires": [
            [
                "cf5ea98b3dfcd0b1"
            ]
        ]
    },
    {
        "id": "b2c6e79083051293",
        "type": "function",
        "z": "a00c3f3cd891b014",
        "name": "Extract rain alert for the day for the department",
        "func": "var json = msg.payload;\n\n// Check if the JSON is valid\nif (json && json.today) {\n    // Search for the item in the \"today\" array where \"phenomenon_id\" is equal to 1\n    var phenomenonItem = json.today.find(item => item.phenomenon_id === \"2\");\n    let levelNumber = '';\n    \n    if (phenomenonItem && phenomenonItem.phenomenon_max_color_id !== undefined) {\n        var phenomenonMaxColorId = phenomenonItem.phenomenon_max_color_id;\n        switch (phenomenonMaxColorId) {\n            case 1:\n                levelNumber = 0\n                break;\n            case 2:\n                levelNumber = 1\n                break;\n            case 3:\n                levelNumber = 2\n                break;\n            default:\n                levelNumber = 3\n                break;\n        }\n        return {\n            payload: levelNumber\n        };\n    } else {\n        // If phenomenon_id is not found or phenomenon_max_color_id is undefined, return an error message\n        levelNumber = 4\n        return {\n            payload: levelNumber\n        };\n    }\n} else {\n    // If the JSON is not valid or properties are missing, return an error message\n    node.error('Invalid JSON or missing property');\n    return null;\n}\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 940,
        "y": 700,
        "wires": [
            [
                "b382a4d0eece6e71"
            ]
        ]
    },
    {
        "id": "3fe286c93a1868c1",
        "type": "function",
        "z": "a00c3f3cd891b014",
        "name": "Extract rain alert for tomorrow for the department",
        "func": "var json = msg.payload;\n\n// Check if the JSON is valid\nif (json && json.tomorrow) {\n    // Search for the item in the \"tomorrow\" array where \"phenomenon_id\" is equal to 1\n    var phenomenonItem = json.tomorrow.find(item => item.phenomenon_id === \"2\");\n    let levelNumber = '';\n    \n    if (phenomenonItem && phenomenonItem.phenomenon_max_color_id !== undefined) {\n        var phenomenonMaxColorId = phenomenonItem.phenomenon_max_color_id;\n        switch (phenomenonMaxColorId) {\n            case 1:\n                levelNumber = 0\n                break;\n            case 2:\n                levelNumber = 1\n                break;\n            case 3:\n                levelNumber = 2\n                break;\n            default:\n                levelNumber = 3\n                break;\n        }\n        return {\n            payload: levelNumber\n        };\n    } else {\n        // If phenomenon_id is not found or phenomenon_max_color_id is undefined, return an error message\n        levelNumber = 4\n        return {\n            payload: levelNumber\n        };\n    }\n} else {\n    // If the JSON is not valid or properties are missing, return an error message\n    node.error('Invalid JSON or missing property');\n    return null;\n}\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 950,
        "y": 760,
        "wires": [
            [
                "1a10594d3e2331a9"
            ]
        ]
    },
    {
        "id": "21f9b08907f80164",
        "type": "function",
        "z": "a00c3f3cd891b014",
        "name": "Extract thunderstorm alert for the day for the department",
        "func": "var json = msg.payload;\n\n// Check if the JSON is valid\nif (json && json.today) {\n    // Search for the item in the \"today\" array where \"phenomenon_id\" is equal to 1\n    var phenomenonItem = json.today.find(item => item.phenomenon_id === \"3\");\n    let levelNumber = '';\n    \n    if (phenomenonItem && phenomenonItem.phenomenon_max_color_id !== undefined) {\n        var phenomenonMaxColorId = phenomenonItem.phenomenon_max_color_id;\n        switch (phenomenonMaxColorId) {\n            case 1:\n                levelNumber = 0\n                break;\n            case 2:\n                levelNumber = 1\n                break;\n            case 3:\n                levelNumber = 2\n                break;\n            default:\n                levelNumber = 3\n                break;\n        }\n        return {\n            payload: levelNumber\n        };\n    } else {\n        // If phenomenon_id is not found or phenomenon_max_color_id is undefined    {
        "id": "6a165e40ca126eae",
        "type": "function",
        "z": "a00c3f3cd891b014",
        "name": "Extract tomorrow's snow alert for the department",
        "func": "var json = msg.payload;\n\n// Check if the JSON is valid\nif (json && json.tomorrow) {\n    // Search for the item in the \"tomorrow\" array where \"phenomenon_id\" is equal to 1\n    var phenomenonItem = json.tomorrow.find(item => item.phenomenon_id === \"5\");\n    let levelNumber = '';\n    \n    if (phenomenonItem && phenomenonItem.phenomenon_max_color_id !== undefined) {\n        var phenomenonMaxColorId = phenomenonItem.phenomenon_max_color_id;\n        switch (phenomenonMaxColorId) {\n            case 1:\n                levelNumber = 0\n                break;\n            case 2:\n                levelNumber = 1\n                break;\n            case 3:\n                levelNumber = 2\n                break;\n            default:\n                levelNumber = 3\n                break;\n        }\n        return {\n            payload: levelNumber\n        };\n    } else {\n        // If phenomenon_id is not found or phenomenon_max_color_id is undefined, return an error message\n        levelNumber = 4\n        return {\n            payload: levelNumber\n        };\n    }\n} else {\n    // If the JSON is not valid or properties are missing, return an error message\n    node.error('Invalid JSON or missing property');\n    return null;\n}\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 930,
        "y": 1120,
        "wires": [
            [
                "b60f77286999386e"
            ]
        ]
    },
    {
        "id": "500c995ef4d9dcf5",
        "type": "function",
        "z": "a00c3f3cd891b014",
        "name": "Extraire la vigilance orage du jour pour le département",
        "func": "var json = msg.payload;\n\n// Vérifier si le JSON est valide\nif (json && json.today) {\n    // Rechercher l'élément dans le tableau \"today\" où \"phenomenon_id\" est égal à 1\n    var phenomenonItem = json.today.find(item => item.phenomenon_id === \"3\");\n    let levelNumber = '';\n    \n    if (phenomenonItem && phenomenonItem.phenomenon_max_color_id !== undefined) {\n        var phenomenonMaxColorId = phenomenonItem.phenomenon_max_color_id;\n        switch (phenomenonMaxColorId) {\n            case 1:\n                levelNumber = 0\n                break;\n            case 2:\n                levelNumber = 1\n                break;\n            case 3:\n                levelNumber = 2\n                break;\n            default:\n                levelNumber = 3\n                break;\n        }\n        return {\n            payload: levelNumber\n        };\n    } else {\n        // Si phenomenon_id n'est pas trouvé ou phenomenon_max_color_id est indéfini, renvoyer un message d'erreur\n        levelNumber = 4\n        return {\n            payload: levelNumber\n        };\n    }\n} else {\n    // Si le JSON n'est pas valide ou s'il manque des propriétés, renvoyer un message d'erreur\n    node.error('JSON invalide ou propriété manquante');\n    return null;\n}\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 940,
        "y": 1180,
        "wires": [
            [
                "190d41532a7d053a"
            ]
        ]
    },
    {
        "id": "71b8ab19ebe50be0",
        "type": "function",
        "z": "a00c3f3cd891b014",
        "name": "Extraire la vigilance neige du jour pour le département",
        "func": "var json = msg.payload;\n\n// Vérifier si le JSON est valide\nif (json && json.today) {\n    // Rechercher l'élément dans le tableau \"today\" où \"phenomenon_id\" est égal à 1\n    var phenomenonItem = json.today.find(item => item.phenomenon_id === \"5\");\n    let levelNumber = '';\n    \n    if (phenomenonItem && phenomenonItem.phenomenon_max_color_id !== undefined) {\n        var phenomenonMaxColorId = phenomenonItem.phenomenon_max_color_id;\n        switch (phenomenonMaxColorId) {\n            case 1:\n                levelNumber = 0\n                break;\n            case 2:\n                levelNumber = 1\n                break;\n            case 3:\n                levelNumber = 2\n                break;\n            default:\n                levelNumber = 3\n                break;\n        }\n        return {\n            payload: levelNumber\n        };\n    } else {\n        // Si phenomenon_id n'est pas trouvé ou phenomenon_max_color_id est indéfini, renvoyer un message d'erreur\n        levelNumber = 4\n        return {\n            payload: levelNumber\n        };\n    }\n} else {\n    // Si le JSON n'est pas valide ou s'il manque des propriétés, renvoyer un message d'erreur\n    node.error('JSON invalide ou propriété manquante');\n    return null;\n}\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 950,
        "y": 1240,
        "wires": [
            [
                "b60f77286999386e"
            ]
        ]
    },
    {
        "id": "ebf6fe7dad24d598",
        "type": "function",
        "z": "a00c3f3cd891b014",
        "name": "Extraire la vigilance neige de demain pour le département",
        "func": "var json = msg.payload;\n\n// Vérifier si le JSON est valide\nif (json && json.tomorrow) {\n    // Rechercher l'élément dans le tableau \"tomorrow\" où \"phenomenon_id\" est égal à 1\n    var phenomenonItem = json.tomorrow.find(item => item.phenomenon_id === \"5\");\n    let levelNumber = '';\n    \n    if (phenomenonItem && phenomenonItem.phenomenon_max_color_id !== undefined) {\n        var phenomenonMaxColorId = phenomenonItem.phenomenon_max_color_id;\n        switch (phenomenonMaxColorId) {\n            case 1:\n                levelNumber = 0\n                break;\n            case 2:\n                levelNumber = 1\n                break;\n            case 3:\n                levelNumber = 2\n                break;\n            default:\n                levelNumber = 3\n                break;\n        }\n        return {\n            payload: levelNumber\n        };\n    } else {\n        // Si phenomenon_id n'est pas trouvé ou phenomenon_max_color_id est indéfini, renvoyer un message d'erreur\n        levelNumber = 4\n        return {\n            payload: levelNumber\n        };\n    }\n} else {\n    // Si le JSON n'est pas valide ou s'il manque des propriétés, renvoyer un message d'erreur\n    node.error('JSON invalide ou propriété manquante');\n    return null;\n}\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 960,
        "y": 1300,
        "wires": [
            [
                "b60f77286999386e"
            ]
        ]
    },
    {
        "id": "02cca03af935dd58",
        "type": "function",
        "z": "a00c3f3cd891b014",
        "name": "Extraire la vigilance neige du jour pour le département",
        "func": "var json = msg.payload;\n\n// Vérifier si le JSON est valide\nif (json && json.today) {\n    // Rechercher l'élément dans le tableau \"today\" où \"phenomenon_id\" est égal à 1\n    var phenomenonItem = json.today.find(item => item.phenomenon_id === \"5\");\n    let levelNumber = '';\n    \n    if (phenomenonItem && phenomenonItem.phenomenon_max_color_id !== undefined) {\n        var phenomenonMaxColorId = phenomenonItem.phenomenon_max_color_id;\n        switch (phenomenonMaxColorId) {\n            case 1:\n                levelNumber = 0\n                break;\n            case 2:\n                levelNumber = 1\n                break;\n            case 3:\n                levelNumber = 2\n                break;\n            default:\n                levelNumber = 3\n                break;\n        }\n        return {\n            payload: levelNumber\n        };\n    } else {\n        // Si phenomenon_id n'est pas trouvé ou phenomenon_max_color_id est indéfini, renvoyer un message d'erreur\n        levelNumber = 4\n        return {\n            payload: levelNumber\n        };\n    }\n} else {\n    // Si le JSON n'est pas valide ou s'il manque des propriétés, renvoyer un message d'erreur\n    node.error('JSON invalide ou propriété manquante');\n    return null;\n}\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 970,
        "y": 1360,
        "wires": [
            [
                "b60f77286999386e"
            ]
        ]
    },
    {
        "id": "b60f77286999386e",
        "type": "function",
        "z": "a00c3f3cd891b014",
        "name": "Extraire la vigilance neige de demain pour le département",
        "func": "var json = msg.payload;\n\n// Vérifier si le JSON est valide\nif (json && json.tomorrow) {\n    // Rechercher l'élément dans le tableau \"tomorrow\" où \"phenomenon_id\" est égal à 1\n    var phenomenonItem = json.tomorrow.find(item => item.phenomenon_id === \"5\");\n    let levelNumber = '';\n    \n    if (phenomenonItem && phenomenonItem.phenomenon_max_color_id !== undefined) {\n        var phenomenonMaxColorId = phenomenonItem.phenomenon_max_color_id;\n        switch (phenomenonMaxColorId) {\n            case 1:\n                levelNumber = 0\n                break;\n            case 2:\n                levelNumber = 1\n                break;\n            case 3:\n                levelNumber = 2\n                break;\n            default:\n                levelNumber = 3\n                break;\n        }\n        return {\n            payload: levelNumber\n        };\n    } else {\n        // Si phenomenon_id n'est pas trouvé ou phenomenon_max_color_id est indéfini, renvoyer un message d'erreur\n        levelNumber = 4\n        return {\n            payload: levelNumber\n        };\n    }\n} else {\n    // Si le JSON n'est pas valide ou s'il manque des propriétés, renvoyer un message d'erreur\n    node.error('JSON invalide ou propriété manquante');\n    return null;\n}\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 980,
        "y": 1420,
        "wires": [
            [
                "b60f77286999386e"
            ]
        ]
    }        "func": "var json = msg.payload;\n\n// Check if the JSON is valid\nif (json && json.tomorrow) {\n    // Search for the element in the \"tomorrow\" array where \"phenomenon_id\" is equal to 1\n    var phenomenonItem = json.tomorrow.find(item => item.phenomenon_id === \"5\");\n    let levelNumber = '';\n    \n    if (phenomenonItem && phenomenonItem.phenomenon_max_color_id !== undefined) {\n        var phenomenonMaxColorId = phenomenonItem.phenomenon_max_color_id;\n        switch (phenomenonMaxColorId) {\n            case 1:\n                levelNumber = 0\n                break;\n            case 2:\n                levelNumber = 1\n                break;\n            case 3:\n                levelNumber = 2\n                break;\n            default:\n                levelNumber = 3\n                break;\n        }\n        return {\n            payload: levelNumber\n        };\n    } else {\n        // If phenomenon_id is not found or phenomenon_max_color_id is undefined, return an error message\n        levelNumber = 4\n        return {\n            payload: levelNumber\n        };\n    }\n} else {\n    // If the JSON is not valid or properties are missing, return an error message\n    node.error('Invalid JSON or missing property');\n    return null;\n}\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 930,
        "y": 1120,
        "wires": [
            [
                "94caac6fd627a4b8"
            ]
        ]
    },
    {
        "id": "8ded2eea3075dbe6",
        "type": "function",
        "z": "a00c3f3cd891b014",
        "name": "Extract today's heatwave alert for the department",
        "func": "var json = msg.payload;\n\n// Check if the JSON is valid\nif (json && json.today) {\n    // Search for the element in the \"today\" array where \"phenomenon_id\" is equal to 1\n    var phenomenonItem = json.today.find(item => item.phenomenon_id === \"6\");\n    let levelNumber = '';\n    if (phenomenonItem && phenomenonItem.phenomenon_max_color_id !== undefined) {\n        var phenomenonMaxColorId = phenomenonItem.phenomenon_max_color_id;\n        switch (phenomenonMaxColorId) {\n            case 1:\n                levelNumber = 0\n                break;\n            case 2:\n                levelNumber = 1\n                break;\n            case 3:\n                levelNumber = 2\n                break;\n            default:\n                levelNumber = 3\n                break;\n        }\n        return {\n            payload: levelNumber\n        };\n    } else {\n        // If phenomenon_id is not found or phenomenon_max_color_id is undefined, return an error message\n        levelNumber = 4\n        return {\n            payload: levelNumber\n        };\n    }\n} else {\n    // If the JSON is not valid or properties are missing, return an error message\n    node.error('Invalid JSON or missing property');\n    return null;\n}\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 930,
        "y": 1180,
        "wires": [
            [
                "178b6d246da2b081"
            ]
        ]
    },
    {
        "id": "d1ad6fe78c581801",
        "type": "function",
        "z": "a00c3f3cd891b014",
        "name": "Extract tomorrow's heatwave alert for the department",
        "func": "var json = msg.payload;\n\n// Check if the JSON is valid\nif (json && json.tomorrow) {\n    // Search for the element in the \"tomorrow\" array where \"phenomenon_id\" is equal to 1\n    var phenomenonItem = json.tomorrow.find(item => item.phenomenon_id === \"6\");\n    let levelNumber = '';\n    \n    if (phenomenonItem && phenomenonItem.phenomenon_max_color_id !== undefined) {\n        var phenomenonMaxColorId = phenomenonItem.phenomenon_max_color_id;\n        switch (phenomenonMaxColorId) {\n            case 1:\n                levelNumber = 0\n                break;\n            case 2:\n                levelNumber = 1\n                break;\n            case 3:\n                levelNumber = 2\n                break;\n            default:\n                levelNumber = 3\n                break;\n        }\n        return {\n            payload: levelNumber\n        };\n    } else {\n        // If phenomenon_id is not found or phenomenon_max_color_id is undefined, return an error message\n        levelNumber = 4\n        return {\n            payload: levelNumber\n        };\n    }\n} else {\n    // If the JSON is not valid or properties are missing, return an error message\n    node.error('Invalid JSON or missing property');\n    return null;\n}\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 940,
        "y": 1240,
        "wires": [
            [
                "a90b86c62c1e080c"
            ]
        ]
    },
    {
        "id": "3d49197f8d7f40e7",
        "type": "mqtt out",
        "z": "a00c3f3cd891b014",
        "name": "Department alert today",
        "topic": "gladys/master/device/mqtt:vigilance-meteo/feature/mqtt:vigilance-departement-today/state",
        "qos": "",
        "retain": "",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "0ee77e0f90aa9681",
        "x": 1290,
        "y": 400,
        "wires": []
    },
    {
        "id": "6e3d0819638abd47",
        "type": "mqtt out",
        "z": "a00c3f3cd891b014",
        "name": "Department alert tomorrow",
        "topic": "gladys/master/device/mqtt:vigilance-meteo/feature/mqtt:vigilance-departement-tomorrow/state",
        "qos": "",
        "retain": "",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "0ee77e0f90aa9681",
        "x": 1300,
        "y": 460,
        "wires": []
    },
    {
        "id": "365325afee9a62cc",
        "type": "mqtt out",
        "z": "a00c3f3cd891b014",
        "name": "Department alert update date",
        "topic": "gladys/master/device/mqtt:vigilance-meteo/feature/mqtt:vigilance-departement-date-maj/text",
        "qos": "",
        "retain": "",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "0ee77e0f90aa9681",
        "x": 1290,
        "y": 520,
        "wires": []
    },
    {
        "id": "b382a4d0eece6e71",
        "type": "mqtt out",
        "z": "a00c3f3cd891b014",
        "name": "Department rain alert today",
        "topic": "gladys/master/device/mqtt:vigilance-meteo/feature/mqtt:vigilance-departement-pluie-today/state",
        "qos": "",
        "retain": "",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "0ee77e0f90aa9681",
        "x": 1360,
        "y": 700,
        "wires": []
    },
    {
        "id": "1a10594d3e2331a9",
        "type": "mqtt out",
        "z": "a00c3f3cd891b014",
        "name": "Department rain alert today",
        "topic": "gladys/master/device/mqtt:vigilance-meteo/feature/mqtt:vigilance-departement-pluie-tomorrow/state",
        "qos": "",
        "retain": "",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "0ee77e0f90aa9681",
        "x": 1360,
        "y": 760,
        "wires": []
    },
    {
        "id": "6f61d33cbc59185b",
        "type": "mqtt out",
        "z": "a00c3f3cd891b014",
        "name": "Department wind alert today",
        "topic": "gladys/master/device/mqtt:vigilance-meteo/feature/mqtt:vigilance-departement-vent-today/state",
        "qos": "",
        "retain": "",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": ""} ,
        "expiry": "",
        "broker": "0ee77e0f90aa9681",
        "x": 1300,
        "y": 580,
        "wires": []
    },
    {
        "id": "cf5ea98b3dfcd0b1",
        "type": "mqtt out",
        "z": "a00c3f3cd891b014",
        "name": "Department wind vigilance for tomorrow",
        "topic": "gladys/master/device/mqtt:vigilance-meteo/feature/mqtt:vigilance-departement-vent-tomorrow/state",
        "qos": "",
        "retain": "",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "0ee77e0f90aa9681",
        "x": 1350,
        "y": 640,
        "wires": []
    },
    {
        "id": "500c995ef4d9dcf5",
        "type": "mqtt out",
        "z": "a00c3f3cd891b014",
        "name": "Department thunderstorm vigilance for today",
        "topic": "gladys/master/device/mqtt:vigilance-meteo/feature/mqtt:vigilance-departement-orage-today/state",
        "qos": "",
        "retain": "",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "0ee77e0f90aa9681",
        "x": 1310,
        "y": 820,
        "wires": []
    },
    {
        "id": "71b8ab19ebe50be0",
        "type": "mqtt out",
        "z": "a00c3f3cd891b014",
        "name": "Department thunderstorm vigilance for tomorrow",
        "topic": "gladys/master/device/mqtt:vigilance-meteo/feature/mqtt:vigilance-departement-orage-tomorrow/state",
        "qos": "",
        "retain": "",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "0ee77e0f90aa9681",
        "x": 1340,
        "y": 880,
        "wires": []
    },
    {
        "id": "ebf6fe7dad24d598",
        "type": "mqtt out",
        "z": "a00c3f3cd891b014",
        "name": "Department flood vigilance for today",
        "topic": "gladys/master/device/mqtt:vigilance-meteo/feature/mqtt:vigilance-departement-inondation-today/state",
        "qos": "",
        "retain": "",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "0ee77e0f90aa9681",
        "x": 1360,
        "y": 940,
        "wires": []
    },
    {
        "id": "02cca03af935dd58",
        "type": "mqtt out",
        "z": "a00c3f3cd891b014",
        "name": "Department flood vigilance for tomorrow",
        "topic": "gladys/master/device/mqtt:vigilance-meteo/feature/mqtt:vigilance-departement-inondation-tomorrow/state",
        "qos": "",
        "retain": "",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "0ee77e0f90aa9681",
        "x": 1390,
        "y": 1000,
        "wires": []
    },
    {
        "id": "190d41532a7d053a",
        "type": "mqtt out",
        "z": "a00c3f3cd891b014",
        "name": "Department snow vigilance for today",
        "topic": "gladys/master/device/mqtt:vigilance-meteo/feature/mqtt:vigilance-departement-neige-today/state",
        "qos": "",
        "retain": "",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "0ee77e0f90aa9681",
        "x": 1310,
        "y": 1060,
        "wires": []
    },
    {
        "id": "94caac6fd627a4b8",
        "type": "mqtt out",
        "z": "a00c3f3cd891b014",
        "name": "Department snow vigilance for tomorrow",
        "topic": "gladys/master/device/mqtt:vigilance-meteo/feature/mqtt:vigilance-departement-neige-tomorrow/state",
        "qos": "",
        "retain": "",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "0ee77e0f90aa9681",
        "x": 1320,
        "y": 1120,
        "wires": []
    },
    {
        "id": "178b6d246da2b081",
        "type": "mqtt out",
        "z": "a00c3f3cd891b014",
        "name": "Department heatwave vigilance for today",
        "topic": "gladys/master/device/mqtt:vigilance-meteo/feature/mqtt:vigilance-departement-canicule-today/state",
        "qos": "",
        "retain": "",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "0ee77e0f90aa9681",
        "x": 1330,
        "y": 1180,
        "wires": []
    },
    {
        "id": "a90b86c62c1e080c",
        "type": "mqtt out",
        "z": "a00c3f3cd891b014",
        "name": "Department heatwave vigilance for tomorrow",
        "topic": "gladys/master/device/mqtt:vigilance-meteo/feature/mqtt:vigilance-departement-canicule-tomorrow/state",
        "qos": "",
        "retain": "",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "0ee77e0f90aa9681",
        "x": 1370,
        "y": 1240,
        "wires": []
    },
    {
        "id": "a8b9b28189313a53",
        "type": "catch",
        "z": "a00c3f3cd891b014",
        "name": "Errors",
        "scope": null,
        "uncaught": false,
        "x": 70,
        "y": 620,
        "wires": [
            [
                "01d92082199d2fbb"
            ]
        ]
    },
    {
        "id": "01d92082199d2fbb",
        "type": "e-mail",
        "z": "a00c3f3cd891b014",
        "server": "monserveuremail",
        "port": "465",
        "authtype": "BASIC",
        "saslformat": false,
        "token": "oauth2Response.access_token",
        "secure": true,
        "tls": true,
        "name": "aremplacer@monmail.fr",
        "dname": "Mail",
        "x": 250,
        "y": 620,
        "wires": []
    },
    {
        "id": "0ee77e0f90aa9681",
        "type": "mqtt-broker",
        "name": "Gladys",
        "broker": "mqtt://192.168.xx.xx",
        "port": "1883",
        "clientid": "",
        "autoConnect": true,
        "usetls": false,
        "protocolVersion": "4",
        "keepalive": "60",
        "cleansession": true,
        "autoUnsubscribe": true,
        "birthTopic": "",
        "birthQos": "0",
        "birthRetain": "false",
        "birthPayload": "",
        "birthMsg": {},
        "closeTopic": "",
        "closeQos": "0",
        "closeRetain": "false",
        "closePayload": "",
        "closeMsg": {},
        "willTopic": "",
        "willQos": "0",
        "willRetain": "false",
        "willPayload": "",
        "willMsg": {},
        "userProps": "",
        "sessionExpiry": ""
    }
]

Don’t forget to modify your department number in the « Extract department data » node
And also the IP address of your MQTT broker
And then the apikey in the « http request » node

To be able to retrieve your department number it’s a bit complicated but I found the info on the HACF forum: (In the tutorial the value is for Rhône)
You need to take the domain_ids next to your department and replace it:

domain_id (departement)		domain_ids
01		                    97
02		                    98
03		                    65
04		                    66
05		                    67
06		                    68
07		                    69
08		                    70
09		                    71
10		                    0
11		                    1
12		                    2
13		                    3
14		                    4
15		                    5
16		                    6
17		                    7
18		                    8
19		                    9
21		                    10
22		                    11
23		                    12
24		                    13
25		                    14
26		                    15
27		                    16
28		                    17
29		                    18
30		                    19
31		                    20
32		                    21
33		                    22
34		                    23
35		                    24
36		                    25
37		                    26
38		                    27
39		                    28
40		                    29
41		                    30
42		                    31
43		                    32
44		                    33
45		                    34
46		                    35
47		                    36
48		                    37
49		                    38
50		                    39
51		                    40
52		                    41
53		                    42
54		                    43
55		                    44
56		                    45
57		                    46
58		                    47
59		                    48
60		                    49
61		                    50
62		                    51
63		                    52
64		                    53
65		                    54
66		                    55
67		                    56
68		                    57
69		                    63
70		                    58
71		                    59
72		                    60
73		                    61
74		                    62
75		                    73
76		                    74
77		                    75
78		                    76
79		                    77
80		                    78
81		                    79
82		                    80
83		                    81
84		                    82
85		                    83
86		                    84
87		                    85
88		                    86
89		                    87
90		                    88
91		                    89
92		                    92
93		                    93
94		                    94
95		                    95
99		                    96
0610		                114
1110			            121
1310		                122
1410		                105
1710		                99
2210		                104
2910		                109
3010		                108
3310		                102
3410		                107
3510		                100
4010		                101
4410		                112
5010		                118
5610		                120
5910		                64
6210		                103
6410		                106
6610		                110
7610		                111
8010		                113
8310		                117
8510		                119
2A		                    72
2A10		                115
2B		                    91
2B10		                116
FRA		                    90

Values to modify if you are not from Rhône :

1. Creating the weather vigilance device on the MQTT integration :









You just have to display this on the dashboard :slight_smile:
And you can also use it in your scenes as you wish :wink:

Changelog to come :

  • None (Your comments :slight_smile: )

Edit 13/05/2024 :

  • Modification of feature types to risk level with the release of Gladys 4.41.0

Edit 15/05/2024 :

  • Modification of crons

Tutorial update :slight_smile:
See the changelog in the first post.
Thanks :wink:

Tutorial update :slight_smile:
See the changelog in the

Good evening @prohand
Which palette are you using for email?

Good evening,

I’m using node-red-node-email

Good evening @prohand
Thank you for the response,
Have a good evening