[
    {
        "id": "60d59772.e5b728",
        "type": "tab",
        "label": "Heater Autoterm",
        "disabled": false,
        "info": ""
    },
    {
        "id": "0277bccc0f7ac04b",
        "type": "group",
        "z": "60d59772.e5b728",
        "name": "Autoterm 1",
        "style": {
            "fill": "#bfdbef",
            "label": true
        },
        "nodes": [
            "8be7d180bf46239a",
            "21768a196e1aa8d1",
            "d00957b7fee7e372",
            "4da43b3032e8195a",
            "51e5c09429bd8070",
            "5c9258d63cbcec5a",
            "37e2b27535f6513b",
            "f98158756d3c2ae3",
            "ddab9938c2092d1a",
            "9100d12ac001b9d6",
            "047c9962b8d65034",
            "e82315d8a6dff27f",
            "e9d5465bd3059666",
            "3791111c48ce0b47",
            "961e743805f7f454",
            "a4ec456aeab1f088",
            "27f98a6bfa3f4415",
            "5cf5504a9e98cac1",
            "7f5ac5a021cbcf87",
            "b5c3484c47dc488f",
            "75a7ac7935c6fd8f",
            "58ae1cab5a2899c8",
            "641d1f9d168cd72d",
            "1673e9f0acf90a40",
            "8f3914632acb71bc",
            "d8e1dbe45fc4ce60",
            "402dfd39c17d608a",
            "bc2980567dcb074f",
            "ab88d75f9b3df89b",
            "d3ae57a14d16dd42",
            "46e9093736ec7d60",
            "d9601d02c048d12b",
            "aa5d16ef2f74c1cf",
            "eb56a5c5b8731957",
            "4edc3ee18e23dfb1",
            "39a94ca39c139c8c",
            "2faa065663792e53",
            "f0f0281e1bf304c8",
            "83c9574d3fdf8e88",
            "bf6ffdeadf8b1e37",
            "559fb2d1ec77b59b",
            "0b706c23cace41ac",
            "d1d930ab7caac131",
            "373a264d5f977e5c",
            "038273fcffbf91eb",
            "cb73a3e9d22ca4c2",
            "822f6f216f24cd12",
            "6762b5adb3de295d",
            "0654188912b71433",
            "9b4d689588a8461a",
            "eae168eb6c28f675",
            "f43f06187e7d7382",
            "359f967be483891b",
            "f3c7a7fb9740141b",
            "d9e43edf7ee3ba38",
            "7279b91fb3ddc1b8",
            "f549c476aa58ecff",
            "d6a3e402307f4de9",
            "b1126dc251e093a3",
            "0a96894d963eb5ec",
            "e0273919c3207c98",
            "962ae611768ff46d",
            "328c5cf6cbe66606",
            "8a9d3aea75c1dae8",
            "b68ce0e97cd9cb49",
            "f0b04de6a7496e24",
            "08507eab2b753939",
            "07e7560111d4b9b8",
            "55c87fa729fb0216",
            "72e436c2865ef429",
            "a76968875489ba69",
            "c2a3be85cbfb0cee",
            "6ec2244d9dad06ed",
            "e99e731a5b3d270d",
            "fd42660d236e32a4",
            "3243f239d8bbb530",
            "a3ed55e98afb7f79",
            "f9cba29e9f4e414a",
            "5cff12844a2f3f5e",
            "406e545efabf0947",
            "ab101e3a7245d2a6",
            "ab5f9a530f57530b",
            "ead09df0cdb6fbc8",
            "6e4881f10b1c373c",
            "8ac3efa188eb7f30",
            "2a85c1ea1f5bc3b6",
            "810f5bee4633d6f1",
            "8a99b49ad7859cf0",
            "398727a635c332c4",
            "8247959bc02cbc35",
            "b8983a59fc585658",
            "99a63809e555bbf6",
            "630b58df3c363da9",
            "a59d3296db090be0",
            "6ba18920833953ce",
            "079d9f94f9af262d",
            "bc97c69199889c73",
            "7343fe0cf4c81fa5",
            "e46adda839a9fb79",
            "1de25423613c1f74",
            "7fd51a79c0da7c01",
            "fdbdb8a48e03b4c5",
            "2a0aa498c2d5b820",
            "4710f8abd22f9699",
            "2193429d5871fd26",
            "bfcccc9873061f78",
            "fc63829ed2b879cc",
            "8a0cf3cdad1bcf31",
            "7805c30b88c02cca",
            "c4651edcaaf39001",
            "54b148df80d4c8bb",
            "0e3458ee6f4e839f",
            "39f0d5a8e1664c66",
            "a2753fc4bdcfb753",
            "28ae88ef85dea3ec",
            "89786e3e0efa5193",
            "c4a29aef719b60e9",
            "a8b6acc5c5917ef3",
            "6f0c393d70e54938",
            "f1d14a13e9c7d434",
            "31ea03578920c642",
            "402b2bb60d6420b3",
            "692b067e5563fdde",
            "37bb945e4e90e73f",
            "b9a005820d1c6844",
            "7c089d13b53cb26c",
            "dcf7fa854b924f67",
            "38523125b8085c8b",
            "e7b1551b5bec695b",
            "be5f17d1f0080e0e",
            "bf0390aa851bab6f",
            "eb20e2f9d18f3fc8"
        ],
        "x": 74,
        "y": 39,
        "w": 1952,
        "h": 1542
    },
    {
        "id": "fd0a1dcd80269338",
        "type": "group",
        "z": "60d59772.e5b728",
        "name": "Autoterm 2",
        "style": {
            "fill": "#dbcbe7",
            "label": true
        },
        "nodes": [
            "37f01b6c70b7ae7c",
            "e4749746d3a99c98",
            "8471d5f10b22fa0a",
            "b026ce6eba6f9a87",
            "e39397e4f40cebc5",
            "3d1b08287de7c95c",
            "35768db845a8f4bf",
            "26d3c76c570978a0",
            "7fe904fa8219f10a",
            "971075701d10b8ba",
            "31de8194d70c710c",
            "b470b3a5f5858bb2",
            "e80635277c66ade1",
            "03820fcd94da7f59",
            "c64c0da0ce9bde09",
            "20e60978f3931872",
            "aa9228b751c585dd",
            "1399b6ccc35e59ae",
            "63645741f51056bf",
            "59c1708fdb7ca3dc",
            "8bda59cdebebee24",
            "751f75fbfd5ea754",
            "ca9ea12469f74a1b",
            "834763b5e6807c9a",
            "1a362185d4de590a",
            "fe9a84e9e99fb913",
            "e4a11721808db0b1",
            "9aee726329c401e9",
            "1a8990ee345dec1e",
            "a05188f6c0ef8ad7",
            "7c2a459ff88c8dfa",
            "823e3ad1a06ac715",
            "631e359c6462aeec",
            "fa65cb7d36d9fe58",
            "9132acf748a0b437",
            "0441d4ad2b9c1276",
            "7359b2da34960315",
            "cf7ebd6dd215c56a",
            "ba751d788217e26a",
            "53a630b93e9f459f",
            "201a09f3ae88f0a6",
            "dc737ebc7fa97a43",
            "1471f2bb6c7ca3e4",
            "60e60a85b1fcc4d9",
            "3aa8d4a40cecc839",
            "79706501e55433cf",
            "d66f1c556e19cbfc",
            "ee9a864f5883a4ca",
            "38ae6960a29fb317",
            "e8ab7963bf895644",
            "f7f5f9658091d726",
            "9aee63f93ec0283e",
            "ed37acc0f9fb910c",
            "eecf6cf101cbbc23",
            "27f1fd15106cb875",
            "e204ef3fc9dd1b9a",
            "04a44d5b764d0bcb",
            "00450dfaf4263e44",
            "d4f8519a849964bf",
            "049552aa8bef72b6",
            "2f97b7cf423ad856",
            "6a77d532c654d677",
            "0dd7f84e43dd4fbc",
            "7ce849761c7fffc6",
            "f5243159fd127654",
            "ce12876b0dd7af8e",
            "efd49bd71fddc65b",
            "1c1586a28680f628",
            "1f1e470952e7a61b",
            "854c44a74f71838c",
            "f25930dd8526d2c9",
            "d37d614f33c57150",
            "8c1c86bc95a5b312",
            "4629e8a049ed50d5",
            "c7991555da2cfc3b",
            "959622e729ad8a22",
            "3094087f26dd2c66",
            "a0983250bb9fe654",
            "3a3ca0bd5d4fd983",
            "8c85cdd689ce2643",
            "630257cf20439718",
            "e23a935b5d5fba5b",
            "17aff29b52d75558",
            "6d70b29b03c32fd0",
            "86392067b684886c",
            "272b5c1972df2b07",
            "659d9836a1950609",
            "bff33215cf36a5d4",
            "1e6cab4a1dcf0b81",
            "17bc994c48ef15a7",
            "1f6ecd32d9cc8d27",
            "b6f99b203b35753d",
            "20d7d8610792929b",
            "c42af9e324f834bc",
            "f220951af3ebef23",
            "0934a5c6a76be1a8",
            "da652ce989439669",
            "0471b3d1c34a252f",
            "349d6ee22ce2a82c",
            "452e95e669371e11",
            "beba3e63965374aa",
            "954124c1c5f5d203",
            "3a4d9331370d75a3",
            "1642e2e3f36559b2",
            "6d16441cb6c88add",
            "4177006a5b5dc2aa",
            "4f99d551f8bcef8f",
            "016f3a3887cb7a2f",
            "77c73221521511f6",
            "524de6910c56e907",
            "96007a80ca96f985",
            "51cbcc9df0ed9de5",
            "25f6a071893a1bd8",
            "dae6751c69f1d7dc",
            "ce77c805fd6f375d",
            "62a00a20dca1d386",
            "b98a68a6de01af38",
            "ad79043cc5c554d5",
            "b71e5390f1a13c55",
            "7ed5ad65c02cd406",
            "6a765babb1382104",
            "e0f2150a33778a93",
            "7c825eee5dde7de2",
            "4bafa884adfb8089",
            "b6a317f071b7fc52",
            "484f4295724356ec",
            "7b8f65b694673686",
            "691fc19f20cd8692",
            "8e60eb211ba64487",
            "3e4662433f6ea83c",
            "f293282ea9e39f06",
            "0283d7ad9fd38d63",
            "b7da8b947bc45c36",
            "5035d35ad5ef565d",
            "09da66e7f6d79d40",
            "e814b275717f0b5b",
            "7c8d771865836729",
            "7cc256d744493e75",
            "f54a4281fcefc938",
            "a31f71ad95945e05",
            "d5daa550215c84c7"
        ],
        "x": 74,
        "y": 1699,
        "w": 1952,
        "h": 1602
    },
    {
        "id": "63dd5420c407b743",
        "type": "group",
        "z": "60d59772.e5b728",
        "name": "Heater Timer Autoterm1",
        "style": {
            "label": true,
            "fill": "#e3f3d3"
        },
        "nodes": [
            "ba59632bf01d8d4a",
            "9e70e22a49a978e9",
            "2fbb1298cb7fe4e4",
            "f59532fe53c51719",
            "51e74ef86604a8d6",
            "773d9bfdbb55d26d",
            "45d0348ba75e6f45",
            "391c9825ca6fe36e",
            "99e9ebc5018ae901",
            "0fc5e8b0fc31cba2",
            "a96d4bf95593a9fc",
            "f215fb8b70a91e89",
            "d0e044ed2e915498",
            "df986e6a5787d93e",
            "b59b4091e7c63391",
            "de01e3e08fb2b8f4",
            "c746536029ca452d",
            "fc6c4c72faa20c0e",
            "7e86a6b3c0df19c7"
        ],
        "x": 2054,
        "y": 39,
        "w": 1352,
        "h": 242
    },
    {
        "id": "45190ef2a22a605b",
        "type": "group",
        "z": "60d59772.e5b728",
        "name": "Heater Timer Autoterm2",
        "style": {
            "label": true,
            "fill": "#e3f3d3"
        },
        "nodes": [
            "c64857dd22909bbe",
            "9c82e4ef3d7bb1bc",
            "29daf43518bb70e5",
            "2e260934bf2f0dbd",
            "3e1a9b5fd994eac7",
            "a2c62f8cc4cf44dd",
            "c67d15761a7a0109",
            "bdefae9ccda6d046",
            "6777db2954efb933",
            "cc1ee79f625c655d",
            "584daee584c89851",
            "3d04165bcf52b546",
            "363f534a6a534d11",
            "1118365a2f4915bf",
            "87361b73a8a8a708",
            "223294cefd2aeab1",
            "0eee798b1addbf8a",
            "a0aa3292c3439feb",
            "b4ee31e0ade8dfd4"
        ],
        "x": 2054,
        "y": 1459,
        "w": 1352,
        "h": 242
    },
    {
        "id": "8be7d180bf46239a",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "autoterm1 start ",
        "links": [],
        "x": 305,
        "y": 520,
        "wires": [
            [
                "e99e731a5b3d270d",
                "a3ed55e98afb7f79"
            ]
        ]
    },
    {
        "id": "21768a196e1aa8d1",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "autoterm1 in",
        "links": [
            "364010e3c3bb676b",
            "51a6a2320386c92b",
            "68309d30d74db678",
            "df2d1e216890ab1e"
        ],
        "x": 485,
        "y": 1240,
        "wires": [
            [
                "0a96894d963eb5ec"
            ]
        ]
    },
    {
        "id": "d00957b7fee7e372",
        "type": "binary",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "buffer split",
        "property": "payload",
        "pattern": "x8,\nx8,\nx8,\nx8,\nx8,\nb8 => USEworktime,\nb8 => worktime,\nb8 => tempsource,\nb8 => temperatur,\nb8 => waitmode,\nb8 => level\n\n",
        "x": 1040,
        "y": 1280,
        "wires": [
            []
        ]
    },
    {
        "id": "4da43b3032e8195a",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "Check settings?",
        "func": "if(msg.payload[4] == 0x02)\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 830,
        "y": 1280,
        "wires": [
            [
                "d00957b7fee7e372"
            ]
        ]
    },
    {
        "id": "51e5c09429bd8070",
        "type": "function",
        "z": "60d59772.e5b728",
        "d": true,
        "g": "0277bccc0f7ac04b",
        "name": "Check Version?",
        "func": "if(msg.payload[4] == 0x06) {\n    // Extract version numbers from msg.payload\n    const versionParts = msg.payload.slice(5, 9).map(part => parseInt(part).toString());\n\n    // Join the version parts with a dot (.)\n    const version = versionParts.join('.');\n\n    // Set the formatted version string to msg.payload\n    msg.payload = version;\n    return msg;\n}",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 830,
        "y": 1240,
        "wires": [
            [
                "e9d5465bd3059666"
            ]
        ]
    },
    {
        "id": "5c9258d63cbcec5a",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "Check Status",
        "func": "if(msg.payload[4] == 0x0F)\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 830,
        "y": 1320,
        "wires": [
            [
                "37e2b27535f6513b"
            ]
        ]
    },
    {
        "id": "37e2b27535f6513b",
        "type": "binary",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "buffer split",
        "property": "payload",
        "pattern": "x8,\nx8,\nx8,\nx8,\nx8,\nb8 => statuscode1,\nb8 => statuscode2,\nx8,\nb8 => internaltemp,\nb8 => externaltemp,\nx8,\nb8 => voltage, \nx8, \nb8 => heatertemp,\nx8,\nx8,\nb8 => fanrpmset,\nb8 => fanrpmactual,\nx8,\nb8 => frequencyfuelpump,\nx8,\nx8,\nx8,\nx8\n\n",
        "x": 1040,
        "y": 1320,
        "wires": [
            [
                "f98158756d3c2ae3",
                "ddab9938c2092d1a",
                "047c9962b8d65034",
                "9100d12ac001b9d6",
                "e82315d8a6dff27f"
            ]
        ]
    },
    {
        "id": "f98158756d3c2ae3",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "state",
        "func": "// Define a mapping for status codes\nconst statusMessages = {\n    \"0-1\": \"standby\",\n    \"1-0\": \"cooling flame sensor\",\n    \"1-1\": \"ventilation\",\n    \"2-0\": \"heating glow plug2\",\n    \"2-1\": \"heating glow plug1\",\n    \"2-2\": \"ignition 1\",\n    \"2-3\": \"ignition 2\",\n    \"2-4\": \"heating\",\n    \"2-5\": \"no ignition error\",\n    \"2-6\": \"no fuel? retry\",\n    \"3-0\": \"heating\",\n    \"3-35\": \"only fan\",\n    \"3-4\": \"cooling down\",\n    \"1-12\": \"flame-out\",\n    \"4-0\": \"shutting down\"\n};\n\n// Create a key based on status codes\nconst key = `${msg.payload.statuscode1}-${msg.payload.statuscode2}`;\n\n//Check, if an error exists. If it exists give the code out\nif (msg.payload.error==0){\n\t// Set the corresponding message if the key exists\n\tif (statusMessages[key]) {\n\t\tmsg.payload = statusMessages[key];\n\t} else {\n\t\tmsg.payload = \"unknown status\"; // Handle unexpected status codes\n\t}\n}else{\n    msg.payload = statusMessages[key] + \" Error: \" + msg.payload.error || \"unknown status Error:\" + msg.payload.error;    \n}\n\n// Store the heat status globally\nglobal.set(\"heatstatus_autoterm1\", msg.payload);\n\nreturn msg;\n",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1230,
        "y": 1360,
        "wires": [
            [
                "0b706c23cace41ac",
                "8a99b49ad7859cf0"
            ]
        ]
    },
    {
        "id": "ddab9938c2092d1a",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "voltage",
        "func": "msg.payload = msg.payload.voltage/10;\nif (msg.payload > 17) {\n    msg.payload=0;\n}\nglobal.set(\"heatvolt_autoterm1\", msg.payload)\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1240,
        "y": 1400,
        "wires": [
            [
                "6e4881f10b1c373c"
            ]
        ]
    },
    {
        "id": "9100d12ac001b9d6",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "fuelpump",
        "func": "msg.payload = msg.payload.frequencyfuelpump/100;\nglobal.set(\"heatpump_autoterm1\",msg.payload);\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1240,
        "y": 1240,
        "wires": [
            [
                "810f5bee4633d6f1"
            ]
        ]
    },
    {
        "id": "047c9962b8d65034",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "fan",
        "func": "msg.payload = msg.payload.fanrpmactual*60;\nglobal.set(\"heatfan_autoterm1\",msg.payload);\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1230,
        "y": 1280,
        "wires": [
            [
                "2a85c1ea1f5bc3b6"
            ]
        ]
    },
    {
        "id": "e82315d8a6dff27f",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "heater temp",
        "func": "msg.payload = msg.payload.heatertemp-15;\nglobal.set(\"heattemp_autoterm1\",msg.payload);\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1250,
        "y": 1320,
        "wires": [
            [
                "8ac3efa188eb7f30"
            ]
        ]
    },
    {
        "id": "e9d5465bd3059666",
        "type": "ui_text",
        "z": "60d59772.e5b728",
        "d": true,
        "g": "0277bccc0f7ac04b",
        "group": "4373a7f49bda8706",
        "order": 15,
        "width": 0,
        "height": 0,
        "name": "",
        "label": "Version",
        "format": "{{msg.payload}}",
        "layout": "row-spread",
        "className": "",
        "style": false,
        "font": "",
        "fontSize": "",
        "color": "#000000",
        "x": 1030,
        "y": 1240,
        "wires": []
    },
    {
        "id": "3791111c48ce0b47",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "set ventilation 0",
        "func": "// Set initial payload to 0\nmsg.payload = 1;\nnode.send(msg); // Send the first message immediately\n\n// Wait 2 seconds, then send the new payload\nsetTimeout(() => {\n    msg.payload = 0; // Change to desired payload value\n    node.send(msg); // Send the message after the delay\n}, 300); // 300 milliseconds = 0.3 seconds\n\n// Return null to prevent Node-RED from sending an output immediately\nreturn null;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 620,
        "y": 320,
        "wires": [
            [
                "ab5f9a530f57530b"
            ]
        ]
    },
    {
        "id": "961e743805f7f454",
        "type": "ui_button",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "",
        "group": "4373a7f49bda8706",
        "order": 5,
        "width": "6",
        "height": "1",
        "passthru": true,
        "label": "Start Tempmode",
        "tooltip": "heater tries to hold set temp without turning off",
        "color": "",
        "bgcolor": "",
        "className": "",
        "icon": "",
        "payload": "9",
        "payloadType": "num",
        "topic": "",
        "topicType": "str",
        "x": 440,
        "y": 720,
        "wires": [
            [
                "58ae1cab5a2899c8"
            ]
        ]
    },
    {
        "id": "a4ec456aeab1f088",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "autoterm1 stop",
        "links": [
            "d0e044ed2e915498",
            "b59b4091e7c63391",
            "841be0b2356b18c1"
        ],
        "x": 265,
        "y": 320,
        "wires": [
            [
                "3791111c48ce0b47",
                "c4651edcaaf39001",
                "be5f17d1f0080e0e"
            ]
        ]
    },
    {
        "id": "27f98a6bfa3f4415",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "send request frames",
        "info": "",
        "x": 550,
        "y": 120,
        "wires": []
    },
    {
        "id": "5cf5504a9e98cac1",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "turn off 4D and 2D",
        "func": "const buf = Buffer.from([\n0xAA,\n0x03,\n0x00,\n0x00,\n0x03,\n0x5D,\n0x7C\n]);\n\nmsg.payload = buf;\n\nreturn msg\n\n/*\nD2 is the read command from the machine address,\n03 is the read command, \n02 is the length of the read data, \n0001 means to read the value of the first register, that is, the host command is discharged\nFC56 is the CRC check code.\n*/\n\n",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1030,
        "y": 360,
        "wires": [
            [
                "f43f06187e7d7382"
            ]
        ]
    },
    {
        "id": "7f5ac5a021cbcf87",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "ventilation",
        "info": "",
        "x": 440,
        "y": 240,
        "wires": []
    },
    {
        "id": "b5c3484c47dc488f",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "OFF",
        "info": "",
        "x": 430,
        "y": 300,
        "wires": []
    },
    {
        "id": "75a7ac7935c6fd8f",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "2D",
        "info": "",
        "x": 590,
        "y": 1200,
        "wires": []
    },
    {
        "id": "58ae1cab5a2899c8",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "check sensor",
        "func": "// Retrieve the temperature sensor value\nmsg.payload = global.get(\"heattempsensor\");\n\n// Parse USB UART values\nconst usbValues = [\n    parseInt(global.get(\"usb1uart\")),\n    parseInt(global.get(\"usb2uart\")),\n    parseInt(global.get(\"usb3uart\")),\n    parseInt(global.get(\"usb4uart\"))\n];\n\n// Check if none of the USB values are 5 or 8\nif (!usbValues.includes(5) && !usbValues.includes(8)) {\n    return null; // No valid USB value found, exit\n}\n\n// Define a mapping for heat sensor values\nconst tempSensorMapping = {\n    1: global.get(\"temp1\"),\n    2: global.get(\"temp2\"),\n    3: global.get(\"temp3\"),\n    4: global.get(\"temp4\"),\n    5: global.get(\"dimmytemp1\"),\n    6: global.get(\"dimmytemp2\"),\n    7: global.get(\"ruuvitag_0\")?.temp ?? \"\",\n    8: global.get(\"ruuvitag_1\")?.temp ?? \"\",\n    9: global.get(\"ruuvitag_2\")?.temp ?? \"\"\n};\n\n// Check if the payload corresponds to a valid sensor\nif (tempSensorMapping[msg.payload] !== undefined) {\n    msg.payload = tempSensorMapping[msg.payload];\n} else {\n    msg.payload = \"no sensor\"; // Invalid sensor number\n}\n\n// Check if all sensors return empty values\nconst allSensorsEmpty = Object.values(tempSensorMapping).every(sensor => sensor === \"\");\nif (allSensorsEmpty) {\n    msg.payload = \"no TempSensor\"; // No temperature sensor detected\n}\n\n// Handle message return logic\nif (msg.payload === \"no TempSensor\") {\n    msg.payload = \"TempMode not available, no InsideTempSensor set\";\n    return [msg, null]; // Return the error message\n} else {\n    msg.topic = \"setpoint\"; // Set the topic\n    flow.set(\"autoterm1_mode\", \"temp mode\")\n    return [null, msg]; // Return the valid message\n}\n",
        "outputs": 2,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 660,
        "y": 720,
        "wires": [
            [
                "641d1f9d168cd72d"
            ],
            [
                "d6a3e402307f4de9"
            ]
        ]
    },
    {
        "id": "641d1f9d168cd72d",
        "type": "ui_toast",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "position": "dialog",
        "displayTime": "3",
        "highlight": "",
        "sendall": false,
        "outputs": 1,
        "ok": "OK",
        "cancel": "",
        "raw": false,
        "className": "",
        "topic": "",
        "name": "",
        "x": 850,
        "y": 700,
        "wires": [
            []
        ]
    },
    {
        "id": "1673e9f0acf90a40",
        "type": "switch",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "ROUTER",
        "property": "usbPort",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "1",
                "vt": "num"
            },
            {
                "t": "eq",
                "v": "2",
                "vt": "num"
            },
            {
                "t": "eq",
                "v": "3",
                "vt": "num"
            },
            {
                "t": "eq",
                "v": "4",
                "vt": "num"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 4,
        "x": 1380,
        "y": 160,
        "wires": [
            [
                "8f3914632acb71bc"
            ],
            [
                "d8e1dbe45fc4ce60"
            ],
            [
                "402dfd39c17d608a"
            ],
            [
                "bc2980567dcb074f"
            ]
        ]
    },
    {
        "id": "8f3914632acb71bc",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "autoterm out",
        "mode": "link",
        "links": [
            "631e04e732bc5864"
        ],
        "x": 1605,
        "y": 120,
        "wires": []
    },
    {
        "id": "d8e1dbe45fc4ce60",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "autoterm out",
        "mode": "link",
        "links": [
            "e1b033b72073b492"
        ],
        "x": 1605,
        "y": 160,
        "wires": []
    },
    {
        "id": "402dfd39c17d608a",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "autoterm out",
        "mode": "link",
        "links": [
            "1b1168f8607d8205"
        ],
        "x": 1605,
        "y": 200,
        "wires": []
    },
    {
        "id": "bc2980567dcb074f",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "autoterm out",
        "mode": "link",
        "links": [
            "38cb32c06a098f9e"
        ],
        "x": 1605,
        "y": 240,
        "wires": []
    },
    {
        "id": "ab88d75f9b3df89b",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "autoterm1 HeatingPower",
        "links": [
            "572f63b680e321fc",
            "691499b994b1afc9",
            "7783954d640394b6",
            "c345988f33d4ee88"
        ],
        "x": 665,
        "y": 440,
        "wires": [
            [
                "ead09df0cdb6fbc8"
            ]
        ]
    },
    {
        "id": "d3ae57a14d16dd42",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "autoterm1 temp mode in",
        "links": [
            "17e04e0bada4e104",
            "4815d5db8374c57d",
            "df986e6a5787d93e"
        ],
        "x": 305,
        "y": 720,
        "wires": [
            [
                "961e743805f7f454"
            ]
        ]
    },
    {
        "id": "46e9093736ec7d60",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "autoterm1 in",
        "links": [
            "364010e3c3bb676b",
            "51a6a2320386c92b",
            "68309d30d74db678",
            "df2d1e216890ab1e"
        ],
        "x": 485,
        "y": 1400,
        "wires": [
            [
                "e0273919c3207c98"
            ]
        ]
    },
    {
        "id": "d9601d02c048d12b",
        "type": "inject",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "6",
        "crontab": "",
        "once": true,
        "onceDelay": "1",
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 310,
        "y": 160,
        "wires": [
            [
                "ab101e3a7245d2a6"
            ]
        ]
    },
    {
        "id": "aa5d16ef2f74c1cf",
        "type": "binary",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "buffer split",
        "property": "payload",
        "pattern": "b8 => Test1,\nb8 => Test2,\nb8 => Test3,\nb8 => Test4,\nb8 => Test5,\nb8 => Status,\nb8 => Status2,\nb8 => error,\nb8 => heaterTemp,\nb8 => externTemp,\nx8,\nb8 => batteryVoltage,\nb16 => flameTempK,\nx8,\nx8\n\n\n",
        "x": 1040,
        "y": 1400,
        "wires": [
            [
                "f0f0281e1bf304c8",
                "8a9d3aea75c1dae8",
                "eb20e2f9d18f3fc8"
            ]
        ]
    },
    {
        "id": "eb56a5c5b8731957",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "Check Status",
        "func": "if(msg.payload[4] == 0x0F)\nreturn msg;\n\n /*\n\nStatus:\nController asks for heater status, polls this one periodically.\n\nC >> H aa 03 00 00 0f | 58 7c\nH >> C aa 04 0a 00 0f | 00 01 00 1a 7f 00 7b 01 2b 00 | 50 ad\n                        s1 s2 er ht et    bv ft ft\ns1: Status\n00: Heater off\n01: Starting\n02: Warming up\n03: Running\n04: Shutting down\ner: Heater errors\nht: Heater temperature (as single byte in °C)\net: External temperature (as single byte in °C, 7f when disconnected)\nbv: Battery voltage (as voltage * 10)\nft: Heater flame temperature (as two bytes, big endian, in Kelvin)\n\n*/",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 830,
        "y": 1400,
        "wires": [
            [
                "aa5d16ef2f74c1cf"
            ]
        ]
    },
    {
        "id": "4edc3ee18e23dfb1",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "request settings",
        "func": "// Request settings\nconst buf1 = Buffer.from([\n    0xAA,  // Start byte\n    0x03,  // Read command\n    0x00,  // Address high byte\n    0x00,  // Address low byte\n    0x02,  // Length of the read data\n    0x9d,  // Checksum byte 1\n    0xbd   // Checksum byte 2\n]);\n\n/*\nD2 is the read command from the machine address,\n03 is the read command,\n02 is the length of the read data,\n0001 means to read the value of the first register, that is, the host command is discharged\nFC56 is the CRC check code.\n*/\n\n// Send first message\nmsg.payload = buf1;\nnode.send(msg);\n\n// Delay of 2 seconds before sending the second message\nsetTimeout(function() {\n    // Request status\n    const buf2 = Buffer.from([\n        0xAA,  // Start byte\n        0x03,  // Read command\n        0x00,  // Address high byte\n        0x00,  // Address low byte\n        0x0f,  // Length of the read data\n        0x58,  // Checksum byte 1\n        0x7C   // Checksum byte 2\n    ]);\n\n    /*\n    D2 is the read command from the machine address,\n    03 is the read command,\n    02 is the length of the read data,\n    0001 means to read the value of the first register, that is, the host command is discharged\n    FC56 is the CRC check code.\n    */\n\n    // Create a new message object for the second payload\n    let newMsg = { ...msg }; \n    newMsg.payload = buf2;\n\n    // Send second message after delay\n    node.send(newMsg);\n}, 2000); // 2000 milliseconds = 2 second delay\n\n// Do not return `msg` here, as we already sent it\nreturn null;\n",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 800,
        "y": 160,
        "wires": [
            [
                "1673e9f0acf90a40"
            ]
        ]
    },
    {
        "id": "39a94ca39c139c8c",
        "type": "function",
        "z": "60d59772.e5b728",
        "d": true,
        "g": "0277bccc0f7ac04b",
        "name": "Check Seetings?",
        "func": "if(msg.payload[4] == 0x02)\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 840,
        "y": 1440,
        "wires": [
            [
                "2faa065663792e53"
            ]
        ]
    },
    {
        "id": "2faa065663792e53",
        "type": "binary",
        "z": "60d59772.e5b728",
        "d": true,
        "g": "0277bccc0f7ac04b",
        "name": "buffer split",
        "property": "payload",
        "pattern": "x8,\nx8,\nx8,\nx8,\nx8,\nx8,\nx8,\nb8 => Mode,\nb8 => TempSetpoint,\nb8 => Ventilation,\nb8 => Powerlevel,\nx8,\nx8\n\n\n",
        "x": 1040,
        "y": 1440,
        "wires": [
            []
        ]
    },
    {
        "id": "f0f0281e1bf304c8",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "status",
        "func": "// Define a mapping for status codes\nconst statusMessages = {\n    \"0-1\": \"standby\",\n    \"1-0\": \"cooling flame sensor\",\n    \"1-1\": \"ventilation\",\n    \"2-0\": \"heating glow plug 1\",\n    \"2-1\": \"heating glow plug 2\",\n    \"2-2\": \"ignition 1\",\n    \"2-3\": \"ignition 2\",\n    \"2-4\": \"warming up\",\n    \"2-5\": \"no ignition error\",\n    \"2-6\": \"no fuel? retry\",\n    \"3-0\": \"heating\",\n    \"3-35\": \"only fan\",\n    \"3-4\": \"cooling down\",\n    \"1-12\": \"flame-out\",\n    \"4-0\": \"shutting down\"\n};\n\n// Create a key based on status codes\nconst key = `${msg.payload.Status}-${msg.payload.Status2}`;\n\n//Check, if an error exists. If it exists give the code out\nif (msg.payload.error==0){\n\t// Set the corresponding message if the key exists\n\tif (statusMessages[key]) {\n\t\tmsg.payload = statusMessages[key];\n\t} else {\n\t\tmsg.payload = \"unknown status\"; // Handle unexpected status codes\n\t}\n}else{\n    if (statusMessages[key]) {\n        msg.payload = statusMessages[key] + \" Error: \" + msg.payload.error \n    } else {\n        msg.payload = \"unknown status Error:\" + msg.payload.error; \n    }  \n}\n\n// Store the heat status globally\nglobal.set(\"heatstatus_autoterm1\", msg.payload);\n\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1230,
        "y": 1460,
        "wires": [
            [
                "0b706c23cace41ac",
                "8a99b49ad7859cf0"
            ]
        ]
    },
    {
        "id": "83c9574d3fdf8e88",
        "type": "function",
        "z": "60d59772.e5b728",
        "d": true,
        "g": "0277bccc0f7ac04b",
        "name": "Check Diagnose",
        "func": "if(msg.payload[2] == 0x48)\nreturn msg;\n\n",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 840,
        "y": 1480,
        "wires": [
            [
                "bf6ffdeadf8b1e37"
            ]
        ]
    },
    {
        "id": "bf6ffdeadf8b1e37",
        "type": "binary",
        "z": "60d59772.e5b728",
        "d": true,
        "g": "0277bccc0f7ac04b",
        "name": "buffer split",
        "property": "payload",
        "pattern": "x8,\nx8,\nx8,\nx8,\nx8,\n\nb8 => Mode,\nb8 => TempSetpoint,\nb8 => Ventilation,\nb8 => Powerlevel,\nx8,\nx8\n\n\n",
        "x": 1040,
        "y": 1480,
        "wires": [
            []
        ]
    },
    {
        "id": "559fb2d1ec77b59b",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "Diagnostic mode",
        "info": "Diagnostic mode:\nPC sends this message to turn on the diagnostic mode on the heater.\n\nPC >> H   aa 03 01 00 07 | 01 | 1d 9e\n H >> PC  aa 04 01 00 07 | 01 | dd 2b\nAfter the diagnostic mode is switched on, the heater periodically sends messages that contain a lot of information.\n\n H >> PC  aa 02 48 00 01 | 000100000000049200000400000000000000012a012b00027f19007a00350244032803ff026201f8016b003d003403ff0000200000040f05000000000000000003ff000062000000 | 51 06\n H >> PC  aa 02 48 00 01 | 000100000000049300000500000000000000012a012b00027f19007a00350244032803ff026301f9016a003d003403ff0000200000040f05000000000000000003ff000062000000 | 80 e6\n H >> PC  aa 02 48 00 01 | 000100000000049400000600000000000000012a012b00027f19007a00350244032803ff026201f9016a003d003403ff0000200000040f05000000000000000003ff000062000000 | b3 58\n H >> PC  aa 02 48 00 01 | 000200000000056700000760600000000000012a012afe007f19007500350228032803ff026301f6016c003c003403fe0000200000040f0500000000000000000074000062000000 | 56 69\n H >> PC  aa 02 48 00 01 | 000200000000056800000860610000000000012a012a00fe7f1900750035022a032a03ff026301fd016a003c003403ff0000200000040f0500000000000000000074000063000000 | 53 39\n H >> PC  aa 02 48 00 01 | 000200000000056900000960600000000000012a012afefe7f19007500350228032903ff026301f8016b003c003403fe0000200000040f0500000000000000000074000063000000 | 05 ab\n                           s1s2        c1c1  c2c2drmr          ctctftft    etht  bv\ns1: Status 1\ns2: Status 2\n00: Heater off\n01: Starting\n02: Warming up\n03: Running\n04: Shutting down\nc1: Counter 1\nc2: Counter 2\ndr: Defined RPM\nmr: Measured RPM\nct: Heater chamber temperature (as two bytes, big endian, in Kelvin)\nft: Flame temperature (as two bytes, big endian, in Kelvin)\net: External temperature (as single byte in °C, 7f when disconnected)\nht: Heater temperature (as single byte in °C)\nbv: Battery voltage (as voltage * 10)\nDiagnostic mode could be switch off with this message.\n\nPC >> H   aa 03 01 00 07 | 00 | dd 5f\n H >> PC  aa 04 01 00 07 | 00 | 1d ea",
        "x": 840,
        "y": 1520,
        "wires": []
    },
    {
        "id": "0b706c23cace41ac",
        "type": "ui_text",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "group": "4373a7f49bda8706",
        "order": 4,
        "width": 0,
        "height": 0,
        "name": "",
        "label": "State",
        "format": "{{msg.payload}}",
        "layout": "row-spread",
        "className": "",
        "style": false,
        "font": "",
        "fontSize": "",
        "color": "#000000",
        "x": 1590,
        "y": 1460,
        "wires": []
    },
    {
        "id": "d1d930ab7caac131",
        "type": "delay",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "",
        "pauseType": "delay",
        "timeout": "2",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 580,
        "y": 200,
        "wires": [
            [
                "373a264d5f977e5c"
            ]
        ]
    },
    {
        "id": "373a264d5f977e5c",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "Send Temperature Value to Heater",
        "func": "// Get the heat temperature sensor number\nmsg.payload = Number(global.get(\"heattempsensor\"));\n\nlet sensorMap = {\n    1: global.get(\"temp1\"),\n    2: global.get(\"temp2\"),\n    3: global.get(\"temp3\"),\n    4: global.get(\"temp4\"),\n    5: global.get(\"dimmytemp1\"),\n    6: global.get(\"dimmytemp2\"),\n    7: global.get(\"ruuvitag_0\")?.temp ?? \"\",\n    8: global.get(\"ruuvitag_1\")?.temp ?? \"\",\n    9: global.get(\"ruuvitag_2\")?.temp ?? \"\"\n};\n\n// Default value for no sensor\nif (!(msg.payload in sensorMap)) {\n    msg.info = \"no Sensor\";\n    msg.payload = 22;  // Default value when no sensor is present\n} else {\n    msg.payload = sensorMap[msg.payload];  // Retrieve sensor value\n}\n\n// Convert payload to hexadecimal and format message\nlet ctemp = toHex(Number(msg.payload).toFixed(0));\nmsg.ctemp = ctemp;\nmsg.payload = \"AA03010011\" + ctemp;\n\nreturn msg;\n\n/**\n * Convert a number to a two-character uppercase hexadecimal string\n * @param {number} d - The number to convert\n * @returns {string} - The hexadecimal string\n */\nfunction toHex(d) {\n    return (\"0\" + (Number(d).toString(16))).slice(-2).toUpperCase();\n}\n\n/*\nSent Temp from controller to heater:\nC >> H  aa 03 01 00 11 | 1a | 76 d0\nH >> C  aa 04 01 00 11 | 1a | b6 65\n                          ct\n*/\n",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 860,
        "y": 200,
        "wires": [
            [
                "cb73a3e9d22ca4c2"
            ]
        ]
    },
    {
        "id": "038273fcffbf91eb",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "send request frames 4D",
        "info": "",
        "x": 330,
        "y": 120,
        "wires": []
    },
    {
        "id": "cb73a3e9d22ca4c2",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "CRC16-modbus",
        "func": "var CRCMaster = {\n    StringToCheck: \"\",\n    CleanedString: \"\",\n    CRCTableDNP: [],\n    init: function() {\n        this.CRCDNPInit();\n    },\n    CleanString: function(inputType) {\n        if (inputType == \"ASCII\") {\n            this.CleanedString = this.StringToCheck;\n        } else {\n            if (this.StringToCheck.match(/^[0-9A-F \\t]+$/gi) !== null) {\n                this.CleanedString = this._hexStringToString(this.StringToCheck.toUpperCase().replace(/[\\t ]/g, ''));\n            } else {\n                //String doesn't seem to be a valid Hex input\n                return false;\n            }\n        }\n        return true;\n    },\n    CRCDNPInit: function() {\n        var i, j, crc, c;\n        for (i = 0; i < 256; i++) {\n            crc = 0;\n            c = i;\n            for (j = 0; j < 8; j++) {\n                if ((crc ^ c) & 0x0001) crc = (crc >> 1) ^ 0xA6BC;\n                else crc = crc >> 1;\n                c = c >> 1;\n            }\n            this.CRCTableDNP[i] = crc;\n        }\n    },\n    CRC16Modbus: function() {\n        var crc = 0xFFFF;\n        var str = this.CleanedString;\n        for (var pos = 0; pos < str.length; pos++) {\n            crc ^= str.charCodeAt(pos);\n            for (var i = 8; i !== 0; i--) {\n                if ((crc & 0x0001) !== 0) {\n                    crc >>= 1;\n                    crc ^= 0xA001;\n                } else\n                    crc >>= 1;\n            }\n        }\n        return crc;\n    },\n    _stringToBytes: function(str) {\n        var ch, st, re = [];\n        for (var i = 0; i < str.length; i++) {\n            ch = str.charCodeAt(i); // get char\n            st = []; // set up \"stack\"\n            do {\n                st.push(ch & 0xFF); // push byte to stack\n                ch = ch >> 8; // shift value down by 1 byte\n            }\n            while (ch);\n            // add stack contents to result\n            // done because chars have \"wrong\" endianness\n            re = re.concat(st.reverse());\n        }\n        // return an array of bytes\n        return re;\n    },\n    _hexStringToString: function(inputstr) {\n        var hex = inputstr.toString(); //force conversion\n        var str = '';\n        for (var i = 0; i < hex.length; i += 2)\n            str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));\n        return str;\n    },\n    Calculate: function(str, inputType) {\n        this.StringToCheck = str;\n        if (this.CleanString(inputType)) {\n            crcinputcrc16modbus=this.CRC16Modbus().toString(16).toUpperCase();\n            //crcinputcrc16modbus=crcinputcrc16modbus.substr(2) + crcinputcrc16modbus.substr(0, 2); //swap bytes\n   \n        }\n    }\n};\n\nCRCMaster.init();\n\nvar inputType = \"HEX\";\nvar crcinputcrc16modbus;\nvar crcinput = msg.payload;\n\nCRCMaster.Calculate(crcinput, inputType);\n\nmsg.payload = crcinput + crcinputcrc16modbus;\n\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1680,
        "y": 500,
        "wires": [
            [
                "822f6f216f24cd12"
            ]
        ]
    },
    {
        "id": "822f6f216f24cd12",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "buffer it",
        "func": "var buf = Buffer.from(msg.payload,\"hex\");\nmsg.payload=buf;\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1700,
        "y": 540,
        "wires": [
            [
                "6762b5adb3de295d"
            ]
        ]
    },
    {
        "id": "6762b5adb3de295d",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "check usb port",
        "func": "let autoterm1 = global.get(\"usbport_autoterm1\");\nif (autoterm1 == null) {\n    return null\n}\nelse {\n    // check if 2 autoterms connected and set to parallel mode\n    if (global.get(\"usbport_autoterm2\") != null && global.get(\"autoterm2_mode\") == true) {\n        msg.usbPort = global.get(\"usbport_autoterm2\")\n        global.set(\"HeaterToggle_autoterm2\", global.get(\"HeaterToggle_autoterm1\"))\n        node.send(msg)\n    }\n    msg.usbPort = autoterm1\n    return msg\n}",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1920,
        "y": 500,
        "wires": [
            [
                "1673e9f0acf90a40"
            ]
        ]
    },
    {
        "id": "0654188912b71433",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "REQUESTS",
        "info": "",
        "x": 290,
        "y": 80,
        "wires": []
    },
    {
        "id": "9b4d689588a8461a",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "UART    ------  2D = 5        -------   4D = 8",
        "info": "",
        "x": 790,
        "y": 120,
        "wires": []
    },
    {
        "id": "eae168eb6c28f675",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "TO ROUTER autoterm1",
        "links": [
            "f43f06187e7d7382"
        ],
        "x": 1745,
        "y": 460,
        "wires": [
            [
                "6762b5adb3de295d"
            ]
        ]
    },
    {
        "id": "f43f06187e7d7382",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "TO ROUTER",
        "mode": "link",
        "links": [
            "eae168eb6c28f675"
        ],
        "x": 1155,
        "y": 360,
        "wires": []
    },
    {
        "id": "359f967be483891b",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "STATUS RECEIVE",
        "info": "",
        "x": 580,
        "y": 1160,
        "wires": []
    },
    {
        "id": "f3c7a7fb9740141b",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "Start Tempmode",
        "info": "",
        "x": 440,
        "y": 680,
        "wires": []
    },
    {
        "id": "d9e43edf7ee3ba38",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "Start Powermode",
        "info": "",
        "x": 440,
        "y": 520,
        "wires": []
    },
    {
        "id": "7279b91fb3ddc1b8",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "set heating & global var",
        "func": "msg.payload = 0;\nglobal.set(\"HeaterToggle_autoterm1\",false);\nflow.set(\"autoterm1_mode\", \"\")\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 650,
        "y": 400,
        "wires": [
            [
                "ead09df0cdb6fbc8"
            ]
        ]
    },
    {
        "id": "f549c476aa58ecff",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "set heating power",
        "func": "var heatingpower = flow.get(\"heatingpower_autoterm1\");\nmsg.payload = \"AA03060001FFFF04FF020\" + heatingpower;\nreturn msg",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1130,
        "y": 520,
        "wires": [
            [
                "cb73a3e9d22ca4c2"
            ]
        ]
    },
    {
        "id": "d6a3e402307f4de9",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "Start tempmode",
        "func": "global.set(\"HeaterToggle_autoterm1\", true);\nlet settemp = Number(global.get(\"settemp_autoterm1\"));\nsettemp = toHex(settemp)\nflow.set(\"updateFromDisplay\", msg.display ?? false)\nmsg.payload = \"AA03060001FFFF02\" + settemp +\"02FF\";\nreturn msg\n\nfunction toHex(d) {\n    return (\"0\" + (Number(d).toString(16))).slice(-2).toUpperCase()\n}",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1060,
        "y": 720,
        "wires": [
            [
                "cb73a3e9d22ca4c2",
                "bfcccc9873061f78"
            ]
        ]
    },
    {
        "id": "b1126dc251e093a3",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "4D",
        "info": "",
        "x": 580,
        "y": 1360,
        "wires": []
    },
    {
        "id": "0a96894d963eb5ec",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "check usb port",
        "func": "let autoterm1 = global.get(\"usbport_autoterm1\"); // Value can be null, 1, 2, 3, or 4\n\nconst usb1 = 1\nconst usb2 = 2\nconst usb3 = 3\nconst usb4 = 4\n\nlet incomingPort = msg.port\nincomingPort = Number(incomingPort.slice(-1));\n// Create an array of USB sources\nconst usbSources = [\n    global.get(\"usb1uart\"),\n    global.get(\"usb2uart\"),\n    global.get(\"usb3uart\"),\n    global.get(\"usb4uart\")\n];\n\n// Check if autoterm1 is not null, and the corresponding usbSource equals 5\nif (autoterm1 !== null && Number(usbSources[autoterm1 - 1]) === 5 && autoterm1 == incomingPort) {\n    msg.usbPort = autoterm1;\n    return msg;\n}",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 600,
        "y": 1240,
        "wires": [
            [
                "4da43b3032e8195a",
                "51e5c09429bd8070",
                "5c9258d63cbcec5a"
            ]
        ]
    },
    {
        "id": "e0273919c3207c98",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "check usb port",
        "func": "let autoterm1 = global.get(\"usbport_autoterm1\"); // Value can be null, 1, 2, 3, or 4\n\nconst usb1 = 1\nconst usb2 = 2\nconst usb3 = 3\nconst usb4 = 4\n\nlet incomingPort = msg.port\nincomingPort = Number(incomingPort.slice(-1));\n// Create an array of USB sources\nconst usbSources = [\n    global.get(\"usb1uart\"),\n    global.get(\"usb2uart\"),\n    global.get(\"usb3uart\"),\n    global.get(\"usb4uart\")\n];\n\n// Check if autoterm1 is not null, and the corresponding usbSource equals 8\nif (autoterm1 !== null && Number(usbSources[autoterm1 - 1]) === 8 && autoterm1 == incomingPort) {\n    msg.usbPort = autoterm1;\n    return msg;\n}",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 600,
        "y": 1400,
        "wires": [
            [
                "eb56a5c5b8731957",
                "39a94ca39c139c8c",
                "83c9574d3fdf8e88"
            ]
        ]
    },
    {
        "id": "962ae611768ff46d",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "scale to 0-9",
        "func": "global.set(\"autoterm1_fanspeed\", msg.payload)\nif(msg.payload == 0) {\n    flow.set(\"autoterm1_mode\", \"\")\n    return null;\n}\n\nmsg.payload = (msg.payload -1).toString()\nmsg.payload = \"AA03040023FFFF0\" + msg.payload + \"FF\";\nif (flow.get(\"autoterm1_mode\") == \"\") {flow.set(\"autoterm1_mode\", \"fan only\")}\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1010,
        "y": 280,
        "wires": [
            [
                "cb73a3e9d22ca4c2"
            ]
        ]
    },
    {
        "id": "328c5cf6cbe66606",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "scale to 0-9",
        "func": "global.set(\"heatingpower_autoterm1\", msg.payload);\nif(msg.payload == 0) {\n    flow.set(\"heatingpower_autoterm1\",msg.payload);\n    global.set(\"Autotermheatingpower\",msg.payload);\n    global.set(\"HeaterToggle_autoterm1\",false)\n    flow.set(\"autoterm1_mode\", \"\")\n    return null;\n}\n\nflow.set(\"heatingpower_autoterm1\",msg.payload);\nglobal.set(\"Autotermheatingpower\",msg.payload);\nglobal.set(\"HeaterToggle_autoterm1\",true);\nflow.set(\"autoterm1_mode\", \"power mode\")\nmsg.payload = msg.payload -1\nreturn msg;\n",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1010,
        "y": 440,
        "wires": [
            [
                "c2a3be85cbfb0cee",
                "6ec2244d9dad06ed"
            ]
        ]
    },
    {
        "id": "8a9d3aea75c1dae8",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "voltage",
        "func": "msg.payload= msg.payload.batteryVoltage/10;\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1240,
        "y": 1500,
        "wires": [
            [
                "6e4881f10b1c373c"
            ]
        ]
    },
    {
        "id": "b68ce0e97cd9cb49",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "Update Tempmode autoterm1",
        "links": [
            "a59d3296db090be0"
        ],
        "x": 425,
        "y": 640,
        "wires": [
            [
                "08507eab2b753939"
            ]
        ]
    },
    {
        "id": "f0b04de6a7496e24",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "Update TempMode",
        "info": "",
        "x": 450,
        "y": 600,
        "wires": []
    },
    {
        "id": "08507eab2b753939",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "check sensor",
        "func": "// Retrieve the temperature sensor value\nmsg.payload = global.get(\"heattempsensor\");\n\n// Parse USB UART values\nconst usbValues = [\n    parseInt(global.get(\"usb1uart\")),\n    parseInt(global.get(\"usb2uart\")),\n    parseInt(global.get(\"usb3uart\")),\n    parseInt(global.get(\"usb4uart\"))\n];\n\n// Check if none of the USB values are 5 or 8\nif (!usbValues.includes(5) && !usbValues.includes(8)) {\n    return null; // No valid USB value found, exit\n}\n\n// Define a mapping for heat sensor values\nconst tempSensorMapping = {\n    1: global.get(\"temp1\"),\n    2: global.get(\"temp2\"),\n    3: global.get(\"temp3\"),\n    4: global.get(\"temp4\"),\n    5: global.get(\"dimmytemp1\"),\n    6: global.get(\"dimmytemp2\"),\n    7: global.get(\"ruuvitag_0\")?.temp ?? \"\",\n    8: global.get(\"ruuvitag_1\")?.temp ?? \"\",\n    9: global.get(\"ruuvitag_2\")?.temp ?? \"\"\n};\n\n// Check if the payload corresponds to a valid sensor\nif (tempSensorMapping[msg.payload] !== undefined) {\n    msg.payload = tempSensorMapping[msg.payload];\n} else {\n    msg.payload = \"no sensor\"; // Invalid sensor number\n}\n\n// Check if all sensors return empty values\nconst allSensorsEmpty = Object.values(tempSensorMapping).every(sensor => sensor === \"\");\nif (allSensorsEmpty) {\n    msg.payload = \"no TempSensor\"; // No temperature sensor detected\n}\n\n// Handle message return logic\nif (msg.payload === \"no TempSensor\") {\n    msg.payload = \"TempMode not available, no InsideTempSensor set\";\n    return [msg, null]; // Return the error message\n} else {\n    msg.topic = \"setpoint\"; // Set the topic\n    return [null, msg]; // Return the valid message\n}\n",
        "outputs": 2,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 620,
        "y": 640,
        "wires": [
            [
                "07e7560111d4b9b8"
            ],
            [
                "55c87fa729fb0216"
            ]
        ]
    },
    {
        "id": "07e7560111d4b9b8",
        "type": "ui_toast",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "position": "dialog",
        "displayTime": "3",
        "highlight": "",
        "sendall": false,
        "outputs": 1,
        "ok": "OK",
        "cancel": "",
        "raw": false,
        "className": "",
        "topic": "",
        "name": "",
        "x": 830,
        "y": 620,
        "wires": [
            []
        ]
    },
    {
        "id": "55c87fa729fb0216",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "Update tempmode",
        "func": "let settemp = Number(global.get(\"settemp_autoterm1\"));\nsettemp = toHex(settemp)\nmsg.payload = \"AA03060002FFFF02\" + settemp +\"02FF\";\nreturn msg\n\nfunction toHex(d) {\n    return (\"0\" + (Number(d).toString(16))).slice(-2).toUpperCase()\n}",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1050,
        "y": 640,
        "wires": [
            [
                "cb73a3e9d22ca4c2"
            ]
        ]
    },
    {
        "id": "72e436c2865ef429",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "↨ 2D + 4D ↨",
        "info": "",
        "x": 1070,
        "y": 680,
        "wires": []
    },
    {
        "id": "a76968875489ba69",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "update heating power",
        "func": "var heatingpower = flow.get(\"heatingpower_autoterm1\");\nmsg.payload = \"AA03060002FFFF04FF020\" + heatingpower;\nreturn msg",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1380,
        "y": 440,
        "wires": [
            [
                "cb73a3e9d22ca4c2"
            ]
        ]
    },
    {
        "id": "c2a3be85cbfb0cee",
        "type": "delay",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "200ms",
        "pauseType": "delay",
        "timeout": "200",
        "timeoutUnits": "milliseconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 1190,
        "y": 440,
        "wires": [
            [
                "a76968875489ba69"
            ]
        ]
    },
    {
        "id": "6ec2244d9dad06ed",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "check if heater is on",
        "func": "if(global.get(\"HeaterToggle_autoterm1\")==true)\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 900,
        "y": 520,
        "wires": [
            [
                "f549c476aa58ecff"
            ]
        ]
    },
    {
        "id": "e99e731a5b3d270d",
        "type": "delay",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "",
        "pauseType": "delay",
        "timeout": "400",
        "timeoutUnits": "milliseconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 430,
        "y": 480,
        "wires": [
            [
                "f9cba29e9f4e414a",
                "5cff12844a2f3f5e"
            ]
        ]
    },
    {
        "id": "fd42660d236e32a4",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "stopp if 0",
        "func": "if(msg.payload == 0) {\n    return msg;\n}\n",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1000,
        "y": 320,
        "wires": [
            [
                "5cf5504a9e98cac1"
            ]
        ]
    },
    {
        "id": "3243f239d8bbb530",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "stop if 0",
        "func": "if(msg.payload == 0) {\n    return msg;\n}\n",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1000,
        "y": 400,
        "wires": [
            [
                "5cf5504a9e98cac1"
            ]
        ]
    },
    {
        "id": "a3ed55e98afb7f79",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "set heater globalVal on",
        "func": "global.set(\"HeaterToggle_autoterm1\",true);\nflow.set(\"autoterm1_mode\", \"power mode\")\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 470,
        "y": 560,
        "wires": [
            [
                "8a0cf3cdad1bcf31"
            ]
        ]
    },
    {
        "id": "f9cba29e9f4e414a",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "start from display",
        "func": "if(msg.payload[0]=0xbb) {\n    msg.payload = global.get(\"heatingpower_autoterm1\");\n    return msg;\n}",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 650,
        "y": 520,
        "wires": [
            [
                "6ec2244d9dad06ed"
            ]
        ]
    },
    {
        "id": "5cff12844a2f3f5e",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "Set heating 1",
        "func": "msg.payload = 1;\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 640,
        "y": 480,
        "wires": [
            [
                "ead09df0cdb6fbc8"
            ]
        ]
    },
    {
        "id": "406e545efabf0947",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "autoterm1 ventilation",
        "links": [
            "35954fcdd8a1d948",
            "5be81bd5b43f94d0",
            "8815e1a3402dfb37",
            "daed4e8c543bea6f"
        ],
        "x": 685,
        "y": 280,
        "wires": [
            [
                "ab5f9a530f57530b"
            ]
        ]
    },
    {
        "id": "ab101e3a7245d2a6",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "check usb port",
        "func": "let autoterm1 = global.get(\"usbport_autoterm1\");\nif (autoterm1 == null) {\n    return null\n}\nelse {\n    msg.usbPort = autoterm1\n    return msg\n}",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 540,
        "y": 160,
        "wires": [
            [
                "4edc3ee18e23dfb1",
                "d1d930ab7caac131"
            ]
        ]
    },
    {
        "id": "ab5f9a530f57530b",
        "type": "ui_numeric",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "",
        "label": "Fan",
        "tooltip": "",
        "group": "4373a7f49bda8706",
        "order": 8,
        "width": "3",
        "height": "1",
        "wrap": false,
        "passthru": true,
        "topic": "topic",
        "topicType": "msg",
        "format": "{{value}}",
        "min": "1",
        "max": 10,
        "step": 1,
        "className": "",
        "x": 810,
        "y": 280,
        "wires": [
            [
                "962ae611768ff46d",
                "fd42660d236e32a4",
                "b9a005820d1c6844"
            ]
        ]
    },
    {
        "id": "ead09df0cdb6fbc8",
        "type": "ui_numeric",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "",
        "label": "Power<br>Mode",
        "tooltip": "",
        "group": "4373a7f49bda8706",
        "order": 9,
        "width": "3",
        "height": "1",
        "wrap": false,
        "passthru": true,
        "topic": "topic",
        "topicType": "msg",
        "format": "{{value}}",
        "min": "1",
        "max": 10,
        "step": 1,
        "className": "",
        "x": 820,
        "y": 440,
        "wires": [
            [
                "3243f239d8bbb530",
                "328c5cf6cbe66606",
                "7c089d13b53cb26c"
            ]
        ]
    },
    {
        "id": "6e4881f10b1c373c",
        "type": "ui_text",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "group": "4373a7f49bda8706",
        "order": 11,
        "width": 3,
        "height": 1,
        "name": "",
        "label": "Voltage",
        "format": "<center>{{msg.payload}} V",
        "layout": "row-spread",
        "className": "",
        "style": false,
        "font": "",
        "fontSize": 16,
        "color": "#000000",
        "x": 1600,
        "y": 1520,
        "wires": []
    },
    {
        "id": "8ac3efa188eb7f30",
        "type": "ui_text",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "group": "4373a7f49bda8706",
        "order": 14,
        "width": 3,
        "height": 1,
        "name": "",
        "label": "Heater",
        "format": "<center>{{msg.payload}} °C",
        "layout": "row-spread",
        "className": "",
        "style": false,
        "font": "",
        "fontSize": 16,
        "color": "#000000",
        "x": 1570,
        "y": 1320,
        "wires": []
    },
    {
        "id": "2a85c1ea1f5bc3b6",
        "type": "ui_text",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "group": "4373a7f49bda8706",
        "order": 12,
        "width": 3,
        "height": 1,
        "name": "",
        "label": "Fan",
        "format": "<center>{{msg.payload}} rpm",
        "layout": "row-spread",
        "className": "",
        "style": false,
        "font": "",
        "fontSize": 16,
        "color": "#000000",
        "x": 1570,
        "y": 1280,
        "wires": []
    },
    {
        "id": "810f5bee4633d6f1",
        "type": "ui_text",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "group": "4373a7f49bda8706",
        "order": 13,
        "width": 3,
        "height": 1,
        "name": "",
        "label": "Pump",
        "format": "<center>{{msg.payload}} Hz",
        "layout": "row-spread",
        "className": "",
        "style": false,
        "font": "",
        "fontSize": 16,
        "color": "#000000",
        "x": 1570,
        "y": 1240,
        "wires": []
    },
    {
        "id": "8a99b49ad7859cf0",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "heat status autoterm",
        "mode": "link",
        "links": [
            "0c51a82c40609692"
        ],
        "x": 1525,
        "y": 1400,
        "wires": []
    },
    {
        "id": "398727a635c332c4",
        "type": "ui_button",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "",
        "group": "4373a7f49bda8706",
        "order": 10,
        "width": "6",
        "height": "1",
        "passthru": true,
        "label": "Stop",
        "tooltip": "",
        "color": "",
        "bgcolor": "",
        "className": "",
        "icon": "",
        "payload": "settemp_autoterm1",
        "payloadType": "flow",
        "topic": "",
        "topicType": "str",
        "x": 230,
        "y": 400,
        "wires": [
            [
                "c4651edcaaf39001",
                "3791111c48ce0b47"
            ]
        ]
    },
    {
        "id": "8247959bc02cbc35",
        "type": "file",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "",
        "filename": "pekaway/settemp_autoterm1",
        "filenameType": "str",
        "appendNewline": false,
        "createDir": true,
        "overwriteFile": "true",
        "encoding": "none",
        "x": 1670,
        "y": 860,
        "wires": [
            []
        ]
    },
    {
        "id": "b8983a59fc585658",
        "type": "file in",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "",
        "filename": "pekaway/settemp_autoterm1",
        "filenameType": "str",
        "format": "utf8",
        "chunk": false,
        "sendError": false,
        "encoding": "none",
        "allProps": false,
        "x": 550,
        "y": 860,
        "wires": [
            [
                "6ba18920833953ce"
            ]
        ]
    },
    {
        "id": "99a63809e555bbf6",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "TEMPERATURE VIEW",
        "info": "",
        "x": 990,
        "y": 820,
        "wires": []
    },
    {
        "id": "630b58df3c363da9",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "autoterm1 settemp",
        "links": [
            "17e04e0bada4e104",
            "204604583c498134",
            "2193429d5871fd26",
            "2d96e8.2c96e918",
            "7805c30b88c02cca",
            "a5478aaf4daf1591",
            "fc63829ed2b879cc"
        ],
        "x": 835,
        "y": 900,
        "wires": [
            [
                "e46adda839a9fb79"
            ]
        ]
    },
    {
        "id": "a59d3296db090be0",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "Update Autoterm",
        "mode": "link",
        "links": [
            "20d7d8610792929b",
            "b68ce0e97cd9cb49"
        ],
        "x": 1775,
        "y": 820,
        "wires": []
    },
    {
        "id": "6ba18920833953ce",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "parse Number",
        "func": "msg.payload = Number(msg.payload)\nmsg.saved_settemp = msg.payload\nlet autotermPort = global.get(\"usbport_autoterm1\") || null\nif (!flow.get(\"updateFromDisplay\") && autotermPort != null) { return msg; }",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 770,
        "y": 860,
        "wires": [
            [
                "e46adda839a9fb79"
            ]
        ]
    },
    {
        "id": "079d9f94f9af262d",
        "type": "ui_button",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "set temp down",
        "group": "4373a7f49bda8706",
        "order": 1,
        "width": 1,
        "height": 2,
        "passthru": false,
        "label": "",
        "tooltip": "",
        "color": "",
        "bgcolor": "",
        "className": "",
        "icon": "chevron_left",
        "payload": "down",
        "payloadType": "str",
        "topic": "button_down_autoterm1",
        "topicType": "str",
        "x": 770,
        "y": 780,
        "wires": [
            [
                "e46adda839a9fb79"
            ]
        ]
    },
    {
        "id": "bc97c69199889c73",
        "type": "ui_text",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "group": "4373a7f49bda8706",
        "order": 2,
        "width": 4,
        "height": 2,
        "name": "show temp webinterface",
        "label": "<center>{{msg.label.trim()}}: {{msg.ambientTemp}}°C",
        "format": "{{msg.payload}}",
        "layout": "col-center",
        "className": "",
        "style": false,
        "font": "",
        "fontSize": 16,
        "color": "#000000",
        "x": 1260,
        "y": 860,
        "wires": []
    },
    {
        "id": "7343fe0cf4c81fa5",
        "type": "ui_button",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "set temp up",
        "group": "4373a7f49bda8706",
        "order": 3,
        "width": 1,
        "height": 2,
        "passthru": false,
        "label": "",
        "tooltip": "",
        "color": "",
        "bgcolor": "",
        "className": "",
        "icon": "chevron_right",
        "payload": "up",
        "payloadType": "str",
        "topic": "button_up_autoterm1",
        "topicType": "str",
        "x": 780,
        "y": 820,
        "wires": [
            [
                "e46adda839a9fb79"
            ]
        ]
    },
    {
        "id": "e46adda839a9fb79",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "get temp & buttonpress",
        "func": "let settemp = global.get(\"settemp_autoterm1\") ?? 22;\nflow.set(\"settemp_autoterm1\", settemp);\nlet heaterToggle = global.get(\"HeaterToggle_autoterm1\") || false;\nglobal.set(\"autoterm1_mode_current\", flow.get(\"autoterm1_mode\"))\n\n// settemp coming from API/Touchdisplay/Boot\n// (payload is not an object, as it is from ds18b20 script)\n// and it is a Number\nif (!isNaN(msg.payload) && typeof msg.payload != 'object' && msg.topic != \"sensor_update\" && msg.topic !== \"ui_scheduler\") {\n    settemp = msg.payload;\n} else {\n    // else get saved settemp\n    if (msg.payload == \"up\" && settemp < 35) {\n        settemp = Number(settemp) + 1;\n    } else if (msg.payload == \"down\" && settemp > 2) {\n        settemp = Number(settemp) - 1;\n    }\n}\n\nglobal.set(\"settemp_autoterm1\", settemp);\nmsg.settemp = Number(settemp);\n\n// if heater is on, change font color to orange\nlet currentMode = flow.get(\"autoterm1_mode\")\ncurrentMode = currentMode == \"\" ? \"\" : \"<center><font size='2'>(\"+currentMode+\")\"\nmsg.payload = heaterToggle === true\n    ? `<font size=\"8\" color=\"#FF5F15\">${settemp}°C</font>${currentMode}`\n    : `<font size=\"8\">${settemp}°C</font>${currentMode}`;\n\n// -----------------------------------------------------\n// Get current ambient temperature sensor and label\n// Now supports IDs 1–13 (incl. NTCs 10–13)\n// -----------------------------------------------------\nlet ambientTempSensor = Number(global.get(\"heattempsensor\"));\n\n// Helper so we don't treat 0 as \"no sensor\"\nfunction hasValue(v) {\n    return v !== undefined && v !== null && v !== \"\" && v !== \"not connected\";\n}\n\nif (![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13].includes(ambientTempSensor)) {\n    // invalid or not set -> generic\n    msg.ambientTemp = \"N/A\";\n    msg.label = \"Tempsensor:\";\n} else if (ambientTempSensor === 1) {\n    msg.ambientTemp = global.get(\"temp1\") ?? \"\";\n    msg.label = global.get(\"Ntemp1\") ?? \"Temp Sensor 1\";\n} else if (ambientTempSensor === 2) {\n    msg.ambientTemp = global.get(\"temp2\") ?? \"\";\n    msg.label = global.get(\"Ntemp2\") ?? \"Temp Sensor 2\";\n} else if (ambientTempSensor === 3) {\n    msg.ambientTemp = global.get(\"temp3\") ?? \"\";\n    msg.label = global.get(\"Ntemp3\") ?? \"Temp Sensor 3\";\n} else if (ambientTempSensor === 4) {\n    msg.ambientTemp = global.get(\"temp4\") ?? \"\";\n    msg.label = global.get(\"Ntemp4\") ?? \"Temp Sensor 4\";\n} else if (ambientTempSensor === 5) {\n    msg.ambientTemp = global.get(\"dimmytemp1\") ?? \"\";\n    msg.label = global.get(\"Ndimmytemp1\") ?? \"Dimmy Temp 1\";\n} else if (ambientTempSensor === 6) {\n    msg.ambientTemp = global.get(\"dimmytemp2\") ?? \"\";\n    msg.label = global.get(\"Ndimmytemp2\") ?? \"Dimmy Temp 2\";\n} else if (ambientTempSensor === 7) {\n    msg.ambientTemp = global.get(\"ruuvitag_0\")?.temp ?? \"\";\n    msg.label = global.get(\"ruuvitag_0_name\") ?? \"RuuviTag 1\";\n} else if (ambientTempSensor === 8) {\n    msg.ambientTemp = global.get(\"ruuvitag_1\")?.temp ?? \"\";\n    msg.label = global.get(\"ruuvitag_1_name\") ?? \"RuuviTag 2\";\n} else if (ambientTempSensor === 9) {\n    msg.ambientTemp = global.get(\"ruuvitag_2\")?.temp ?? \"\";\n    msg.label = global.get(\"ruuvitag_2_name\") ?? \"RuuviTag 3\";\n}\n\n// ------- NEW: NTCs 10–13 -------\nelse if (ambientTempSensor === 10) {\n    msg.ambientTemp = global.get(\"ntc1\") ?? \"\";\n    msg.label = global.get(\"NLevel1\") ?? \"NTC 1\";\n} else if (ambientTempSensor === 11) {\n    msg.ambientTemp = global.get(\"ntc2\") ?? \"\";\n    msg.label = global.get(\"NLevel2\") ?? \"NTC 2\";\n} else if (ambientTempSensor === 12) {\n    msg.ambientTemp = global.get(\"ntc3\") ?? \"\";\n    msg.label = global.get(\"NLevel3\") ?? \"NTC 3\";\n} else if (ambientTempSensor === 13) {\n    msg.ambientTemp = global.get(\"ntc4\") ?? \"\";\n    msg.label = global.get(\"NLevel4\") ?? \"NTC 4\";\n}\n\n// -----------------------------------------------------\n// Check if *all* sensors are effectively unavailable\n// (now including NTCs, but not treating 0 as \"no sensor\")\n// -----------------------------------------------------\nconst noSensors =\n    !hasValue(global.get(\"temp1\")) &&\n    !hasValue(global.get(\"temp2\")) &&\n    !hasValue(global.get(\"temp3\")) &&\n    !hasValue(global.get(\"temp4\")) &&\n    !hasValue(global.get(\"dimmytemp1\")) &&\n    !hasValue(global.get(\"dimmytemp2\")) &&\n    (!hasValue(global.get(\"ruuvitag_0\")?.temp)) &&\n    (!hasValue(global.get(\"ruuvitag_1\")?.temp)) &&\n    (!hasValue(global.get(\"ruuvitag_2\")?.temp)) &&\n    !hasValue(global.get(\"ntc1\")) &&\n    !hasValue(global.get(\"ntc2\")) &&\n    !hasValue(global.get(\"ntc3\")) &&\n    !hasValue(global.get(\"ntc4\"));\n\nif (noSensors) {\n    msg.ambientTemp = \"N/A\";\n    msg.label = \"No sensors available\";\n}\nif (flow.get(\"updateFromDisplay\")) { flow.set(\"updateFromDisplay\", false)}\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1000,
        "y": 860,
        "wires": [
            [
                "bc97c69199889c73",
                "2a0aa498c2d5b820"
            ]
        ]
    },
    {
        "id": "1de25423613c1f74",
        "type": "ui_ui_control",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "",
        "events": "change",
        "x": 160,
        "y": 860,
        "wires": [
            [
                "7fd51a79c0da7c01"
            ]
        ]
    },
    {
        "id": "7fd51a79c0da7c01",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "check tab",
        "func": "if (msg.payload == \"change\" && msg.name == \"Heater\") {\n    return msg;\n}",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 300,
        "y": 860,
        "wires": [
            [
                "b8983a59fc585658"
            ]
        ]
    },
    {
        "id": "fdbdb8a48e03b4c5",
        "type": "inject",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "5s",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "5",
        "crontab": "",
        "once": true,
        "onceDelay": "20",
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 170,
        "y": 820,
        "wires": [
            [
                "bf0390aa851bab6f"
            ]
        ]
    },
    {
        "id": "2a0aa498c2d5b820",
        "type": "change",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "",
        "rules": [
            {
                "t": "move",
                "p": "settemp",
                "pt": "msg",
                "to": "payload",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 1240,
        "y": 820,
        "wires": [
            [
                "4710f8abd22f9699"
            ]
        ]
    },
    {
        "id": "4710f8abd22f9699",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "write if changed",
        "func": "if (Number(flow.get(\"settemp_autoterm1\")) == msg.payload && msg.topic != \"setpoint\") {\n    return null\n}\nmsg.topic = \"autoterm1\"\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1430,
        "y": 820,
        "wires": [
            [
                "8247959bc02cbc35",
                "a59d3296db090be0"
            ]
        ]
    },
    {
        "id": "2193429d5871fd26",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "to settemp",
        "mode": "link",
        "links": [
            "630b58df3c363da9"
        ],
        "x": 1365,
        "y": 720,
        "wires": []
    },
    {
        "id": "bfcccc9873061f78",
        "type": "delay",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "",
        "pauseType": "delay",
        "timeout": "1",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 1260,
        "y": 720,
        "wires": [
            [
                "2193429d5871fd26"
            ]
        ]
    },
    {
        "id": "fc63829ed2b879cc",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "to settemp",
        "mode": "link",
        "links": [
            "630b58df3c363da9"
        ],
        "x": 815,
        "y": 560,
        "wires": []
    },
    {
        "id": "8a0cf3cdad1bcf31",
        "type": "delay",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "",
        "pauseType": "delay",
        "timeout": "1",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 680,
        "y": 560,
        "wires": [
            [
                "fc63829ed2b879cc"
            ]
        ]
    },
    {
        "id": "7805c30b88c02cca",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "to settemp",
        "mode": "link",
        "links": [
            "692b067e5563fdde",
            "630b58df3c363da9"
        ],
        "x": 615,
        "y": 440,
        "wires": []
    },
    {
        "id": "c4651edcaaf39001",
        "type": "delay",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "0.5s",
        "pauseType": "delay",
        "timeout": "0.5",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 410,
        "y": 400,
        "wires": [
            [
                "7279b91fb3ddc1b8",
                "e7b1551b5bec695b"
            ]
        ]
    },
    {
        "id": "54b148df80d4c8bb",
        "type": "countdown",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "",
        "topic": "",
        "payloadTimerStart": "true",
        "payloadTimerStartType": "bool",
        "payloadTimerStop": "false",
        "payloadTimerStopType": "bool",
        "timer": 30,
        "resetWhileRunning": true,
        "setTimeToNewWhileRunning": true,
        "startCountdownOnControlMessage": true,
        "minuteCounter": false,
        "x": 1050,
        "y": 960,
        "wires": [
            [
                "39f0d5a8e1664c66"
            ],
            [
                "39f0d5a8e1664c66",
                "a2753fc4bdcfb753"
            ]
        ]
    },
    {
        "id": "0e3458ee6f4e839f",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "set Topic to Control",
        "func": "if (msg.payload == 0) {\n    global.set(\"heater_runtime_autoterm1\", msg.payload)\n    msg.payload = \"cancel\"\n    msg.topic = \"control\"\n    return msg\n}\nelse {\n    global.set(\"heater_runtime_autoterm1\", msg.payload)\n    msg.payload = Number(msg.payload*60)\n    msg.topic=\"control\";\n    return msg;\n}",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 850,
        "y": 960,
        "wires": [
            [
                "54b148df80d4c8bb",
                "a8b6acc5c5917ef3"
            ]
        ]
    },
    {
        "id": "39f0d5a8e1664c66",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "turn heater off",
        "func": "if(msg.payload==false) {\n    msg.payload=\"Off\";\n    return msg;\n}",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1240,
        "y": 960,
        "wires": [
            [
                "f1d14a13e9c7d434"
            ]
        ]
    },
    {
        "id": "a2753fc4bdcfb753",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "remaining time",
        "func": "if (msg.payload == -1 || msg.payload == -0) {\n    global.set(\"autoterm1_remaining_runtime\", 0)\n    return null\n}\n\nif (msg.payload == \"cancel\") {\n    msg.payload = \" \"\n    msg.background = \"transparent\"\n    global.set(\"autoterm1_remaining_runtime\", 0)\n    return msg\n}\nelse {\n    let totalSeconds = msg.payload;\n    global.set(\"autoterm1_remaining_runtime\", totalSeconds)\n\n    // Calculate hours\n    let hours = Math.floor(totalSeconds / 3600);\n    hours = (hours < 10) ? \"0\" + hours : hours;\n\n    // Calculate remaining minutes\n    let minutes = Math.floor((totalSeconds % 3600) / 60);\n    minutes = (minutes < 10) ? \"0\" + minutes : minutes;\n\n    // Calculate remaining seconds\n    let seconds = totalSeconds % 60;\n    seconds = (seconds < 10) ? \"0\" + seconds : seconds;\n\n    // Format the output as hh:mm:ss\n    msg.payload = `<font color=\"#FF5F15\">${hours}:${minutes}:${seconds}</font>`;\n    msg.background = \"\"\n    return msg;\n\n}",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1240,
        "y": 1000,
        "wires": [
            [
                "402b2bb60d6420b3"
            ]
        ]
    },
    {
        "id": "28ae88ef85dea3ec",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "stop countdown",
        "func": "msg.payload = \"cancel\"\nmsg.topic = \"control\"\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 840,
        "y": 1000,
        "wires": [
            [
                "54b148df80d4c8bb",
                "89786e3e0efa5193"
            ]
        ]
    },
    {
        "id": "89786e3e0efa5193",
        "type": "delay",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "750ms",
        "pauseType": "delay",
        "timeout": "0.75",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 1030,
        "y": 1080,
        "wires": [
            [
                "c4a29aef719b60e9",
                "a2753fc4bdcfb753"
            ]
        ]
    },
    {
        "id": "c4a29aef719b60e9",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "stop countdown",
        "func": "msg.payload = 0\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 420,
        "y": 960,
        "wires": [
            [
                "31ea03578920c642"
            ]
        ]
    },
    {
        "id": "a8b6acc5c5917ef3",
        "type": "delay",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "400ms",
        "pauseType": "delay",
        "timeout": "400",
        "timeoutUnits": "milliseconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 1030,
        "y": 1000,
        "wires": [
            [
                "a2753fc4bdcfb753"
            ]
        ]
    },
    {
        "id": "6f0c393d70e54938",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "autoterm1 runtime",
        "links": [
            "204604583c498134",
            "a5478aaf4daf1591",
            "735447b9090b525b"
        ],
        "x": 485,
        "y": 920,
        "wires": [
            [
                "31ea03578920c642"
            ]
        ]
    },
    {
        "id": "f1d14a13e9c7d434",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "link out 5",
        "mode": "link",
        "links": [
            "37bb945e4e90e73f"
        ],
        "x": 1455,
        "y": 960,
        "wires": []
    },
    {
        "id": "31ea03578920c642",
        "type": "ui_numeric",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "runtime",
        "label": "<center>Runtime (min)",
        "tooltip": "",
        "group": "4373a7f49bda8706",
        "order": 17,
        "width": 4,
        "height": 1,
        "wrap": true,
        "passthru": true,
        "topic": "topic",
        "topicType": "msg",
        "format": "{{value}}",
        "min": 0,
        "max": "600",
        "step": "15",
        "className": "",
        "x": 640,
        "y": 960,
        "wires": [
            [
                "0e3458ee6f4e839f"
            ]
        ]
    },
    {
        "id": "402b2bb60d6420b3",
        "type": "ui_button",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "remaining/reset",
        "group": "4373a7f49bda8706",
        "order": 16,
        "width": 2,
        "height": 1,
        "passthru": false,
        "label": "{{payload}}",
        "tooltip": "Click to reset the timer",
        "color": "",
        "bgcolor": "{{background}}",
        "className": "",
        "icon": "",
        "payload": "reset",
        "payloadType": "str",
        "topic": "topic",
        "topicType": "msg",
        "x": 1440,
        "y": 1000,
        "wires": [
            [
                "28ae88ef85dea3ec"
            ]
        ]
    },
    {
        "id": "692b067e5563fdde",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "autoterm1 runtime stop",
        "links": [
            "7805c30b88c02cca"
        ],
        "x": 685,
        "y": 1000,
        "wires": [
            [
                "28ae88ef85dea3ec"
            ]
        ]
    },
    {
        "id": "37bb945e4e90e73f",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "autoterm1 touch stop",
        "links": [
            "7350ba757185bbc2",
            "f1d14a13e9c7d434"
        ],
        "x": 135,
        "y": 400,
        "wires": [
            [
                "398727a635c332c4"
            ]
        ]
    },
    {
        "id": "b9a005820d1c6844",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "check parallel",
        "func": "let parallel = global.get(\"autoterm2_mode\") || false\nif (parallel) {return msg;}",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1020,
        "y": 240,
        "wires": [
            [
                "dcf7fa854b924f67"
            ]
        ]
    },
    {
        "id": "7c089d13b53cb26c",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "check parallel",
        "func": "let parallel = global.get(\"autoterm2_mode\") || false\nif (parallel) {return msg;}",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1020,
        "y": 480,
        "wires": [
            [
                "38523125b8085c8b"
            ]
        ]
    },
    {
        "id": "dcf7fa854b924f67",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "TO ROUTER",
        "mode": "link",
        "links": [
            "8c85cdd689ce2643"
        ],
        "x": 1155,
        "y": 240,
        "wires": []
    },
    {
        "id": "38523125b8085c8b",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "TO ROUTER",
        "mode": "link",
        "links": [
            "9aee726329c401e9"
        ],
        "x": 1175,
        "y": 480,
        "wires": []
    },
    {
        "id": "37f01b6c70b7ae7c",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "autoterm2 start ",
        "links": [],
        "x": 375,
        "y": 2180,
        "wires": [
            [
                "4629e8a049ed50d5",
                "3094087f26dd2c66"
            ]
        ]
    },
    {
        "id": "e4749746d3a99c98",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "autoterm2 in",
        "links": [
            "364010e3c3bb676b",
            "51a6a2320386c92b",
            "68309d30d74db678",
            "df2d1e216890ab1e"
        ],
        "x": 495,
        "y": 2960,
        "wires": [
            [
                "049552aa8bef72b6"
            ]
        ]
    },
    {
        "id": "8471d5f10b22fa0a",
        "type": "binary",
        "z": "60d59772.e5b728",
        "d": true,
        "g": "fd0a1dcd80269338",
        "name": "buffer split",
        "property": "payload",
        "pattern": "x8,\nx8,\nx8,\nx8,\nx8,\nb8 => USEworktime,\nb8 => worktime,\nb8 => tempsource,\nb8 => temperatur,\nb8 => waitmode,\nb8 => level\n\n",
        "x": 1050,
        "y": 3000,
        "wires": [
            []
        ]
    },
    {
        "id": "b026ce6eba6f9a87",
        "type": "function",
        "z": "60d59772.e5b728",
        "d": true,
        "g": "fd0a1dcd80269338",
        "name": "Check settings?",
        "func": "if(msg.payload[4] == 0x02)\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 840,
        "y": 3000,
        "wires": [
            [
                "8471d5f10b22fa0a"
            ]
        ]
    },
    {
        "id": "e39397e4f40cebc5",
        "type": "function",
        "z": "60d59772.e5b728",
        "d": true,
        "g": "fd0a1dcd80269338",
        "name": "Check Version?",
        "func": "if(msg.payload[4] == 0x06) {\n    // Extract version numbers from msg.payload\n    const versionParts = msg.payload.slice(5, 9).map(part => parseInt(part).toString());\n\n    // Join the version parts with a dot (.)\n    const version = versionParts.join('.');\n\n    // Set the formatted version string to msg.payload\n    msg.payload = version;\n    return msg;\n}",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 840,
        "y": 2960,
        "wires": [
            [
                "e80635277c66ade1"
            ]
        ]
    },
    {
        "id": "3d1b08287de7c95c",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "Check Status",
        "func": "if(msg.payload[4] == 0x0F)\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 840,
        "y": 3040,
        "wires": [
            [
                "35768db845a8f4bf"
            ]
        ]
    },
    {
        "id": "35768db845a8f4bf",
        "type": "binary",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "buffer split",
        "property": "payload",
        "pattern": "x8,\nx8,\nx8,\nx8,\nx8,\nb8 => statuscode1,\nb8 => statuscode2,\nx8,\nb8 => internaltemp,\nb8 => externaltemp,\nx8,\nb8 => voltage, \nx8, \nb8 => heatertemp,\nx8,\nx8,\nb8 => fanrpmset,\nb8 => fanrpmactual,\nx8,\nb8 => frequencyfuelpump,\nx8,\nx8,\nx8,\nx8\n\n",
        "x": 1050,
        "y": 3040,
        "wires": [
            [
                "26d3c76c570978a0",
                "7fe904fa8219f10a",
                "31de8194d70c710c",
                "971075701d10b8ba",
                "b470b3a5f5858bb2"
            ]
        ]
    },
    {
        "id": "26d3c76c570978a0",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "state",
        "func": "// Define a mapping for status codes\nconst statusMessages = {\n    \"0-1\": \"standby\",\n    \"1-0\": \"cooling flame sensor\",\n    \"1-1\": \"ventilation\",\n    \"2-0\": \"heating glow plug2\",\n    \"2-1\": \"heating glow plug1\",\n    \"2-2\": \"ignition 1\",\n    \"2-3\": \"ignition 2\",\n    \"2-4\": \"heating\",\n    \"2-5\": \"no ignition error\",\n    \"2-6\": \"no fuel? retry\",\n    \"3-0\": \"heating\",\n    \"3-35\": \"only fan\",\n    \"3-4\": \"cooling down\",\n    \"1-12\": \"flame-out\",\n    \"4-0\": \"shutting down\"\n};\n\n// Create a key based on status codes\nconst key = `${msg.payload.statuscode1}-${msg.payload.statuscode2}`;\n\n//Check, if an error exists. If it exists give the code out\nif (msg.payload.error == 0) {\n    // Set the corresponding message if the key exists\n    if (statusMessages[key]) {\n        msg.payload = statusMessages[key];\n    } else {\n        msg.payload = \"unknown status\"; // Handle unexpected status codes\n    }\n} else {\n    msg.payload = statusMessages[key] + \" Error: \" + msg.payload.error || \"unknown status Error:\" + msg.payload.error;\n}\n\n// Store the heat status globally\nglobal.set(\"heatstatus_autoterm2\", msg.payload);\n\nreturn msg;\n",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1240,
        "y": 3080,
        "wires": [
            [
                "201a09f3ae88f0a6",
                "bff33215cf36a5d4"
            ]
        ]
    },
    {
        "id": "7fe904fa8219f10a",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "voltage",
        "func": "msg.payload = msg.payload.voltage/10;\nif (msg.payload > 17) {\n    msg.payload=0;\n}\nglobal.set(\"heatvolt_autoterm2\", msg.payload)\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1250,
        "y": 3120,
        "wires": [
            [
                "6d70b29b03c32fd0"
            ]
        ]
    },
    {
        "id": "971075701d10b8ba",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "fuelpump",
        "func": "msg.payload = msg.payload.frequencyfuelpump/100;\nglobal.set(\"heatpump_autoterm2\",msg.payload);\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1250,
        "y": 2960,
        "wires": [
            [
                "659d9836a1950609"
            ]
        ]
    },
    {
        "id": "31de8194d70c710c",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "fan",
        "func": "msg.payload = msg.payload.fanrpmactual*60;\nglobal.set(\"heatfan_autoterm2\",msg.payload);\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1240,
        "y": 3000,
        "wires": [
            [
                "272b5c1972df2b07"
            ]
        ]
    },
    {
        "id": "b470b3a5f5858bb2",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "heater temp",
        "func": "msg.payload = msg.payload.heatertemp-15;\nglobal.set(\"heattemp_autoterm2\",msg.payload);\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1260,
        "y": 3040,
        "wires": [
            [
                "86392067b684886c"
            ]
        ]
    },
    {
        "id": "e80635277c66ade1",
        "type": "ui_text",
        "z": "60d59772.e5b728",
        "d": true,
        "g": "fd0a1dcd80269338",
        "group": "515f29cdb93516fd",
        "order": 15,
        "width": 0,
        "height": 0,
        "name": "",
        "label": "Version",
        "format": "{{msg.payload}}",
        "layout": "row-spread",
        "className": "",
        "style": false,
        "font": "",
        "fontSize": "",
        "color": "#000000",
        "x": 1040,
        "y": 2960,
        "wires": []
    },
    {
        "id": "03820fcd94da7f59",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "set ventilation 0",
        "func": "if (msg.change == \"background\" || global.get(\"autoterm2_mode\") == true) {\n    return null\n}\nmsg.payload = 0;\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 720,
        "y": 1980,
        "wires": [
            [
                "e23a935b5d5fba5b"
            ]
        ]
    },
    {
        "id": "c64c0da0ce9bde09",
        "type": "ui_button",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "",
        "group": "515f29cdb93516fd",
        "order": 5,
        "width": "6",
        "height": "1",
        "passthru": true,
        "label": "Start Tempmode",
        "tooltip": "heater tries to hold set temp without turning off",
        "color": "{{fontcolor}}",
        "bgcolor": "{{background}}",
        "className": "autoterm2",
        "icon": "",
        "payload": "9",
        "payloadType": "num",
        "topic": "",
        "topicType": "str",
        "x": 540,
        "y": 2380,
        "wires": [
            [
                "8bda59cdebebee24"
            ]
        ]
    },
    {
        "id": "20e60978f3931872",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "autoterm2 stop",
        "links": [
            "363f534a6a534d11",
            "87361b73a8a8a708",
            "178bc6bbf51fa633"
        ],
        "x": 465,
        "y": 2020,
        "wires": [
            [
                "03820fcd94da7f59",
                "e8ab7963bf895644",
                "e204ef3fc9dd1b9a"
            ]
        ]
    },
    {
        "id": "aa9228b751c585dd",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "send request frames",
        "info": "",
        "x": 530,
        "y": 1780,
        "wires": []
    },
    {
        "id": "1399b6ccc35e59ae",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "turn off 4D and 2D",
        "func": "const buf = Buffer.from([\n0xAA,\n0x03,\n0x00,\n0x00,\n0x03,\n0x5D,\n0x7C\n]);\n\nmsg.payload = buf;\n\nreturn msg\n\n/*\nD2 is the read command from the machine address,\n03 is the read command, \n02 is the length of the read data, \n0001 means to read the value of the first register, that is, the host command is discharged\nFC56 is the CRC check code.\n*/\n\n",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1130,
        "y": 2020,
        "wires": [
            [
                "9aee63f93ec0283e"
            ]
        ]
    },
    {
        "id": "63645741f51056bf",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "ventilation",
        "info": "",
        "x": 420,
        "y": 1900,
        "wires": []
    },
    {
        "id": "59c1708fdb7ca3dc",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "2D",
        "info": "",
        "x": 590,
        "y": 2920,
        "wires": []
    },
    {
        "id": "8bda59cdebebee24",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "check sensor",
        "func": "if (msg.change == \"background\" || global.get(\"autoterm2_mode\") == true) {\n    return null\n}\n\n// Retrieve the temperature sensor value\nmsg.payload = global.get(\"heattempsensor_autoterm2\") == 0 ? global.get(\"heattempsensor\") : global.get(\"heattempsensor_autoterm2\")\n\n// Parse USB UART values\nconst usbValues = [\n    parseInt(global.get(\"usb1uart\")),\n    parseInt(global.get(\"usb2uart\")),\n    parseInt(global.get(\"usb3uart\")),\n    parseInt(global.get(\"usb4uart\"))\n];\n\n// Check if none of the USB values are 5 or 8\nif (!usbValues.includes(5) && !usbValues.includes(8)) {\n    return null; // No valid USB value found, exit\n}\n\n// Define a mapping for heat sensor values\nconst tempSensorMapping = {\n    1: global.get(\"temp1\"),\n    2: global.get(\"temp2\"),\n    3: global.get(\"temp3\"),\n    4: global.get(\"temp4\"),\n    5: global.get(\"dimmytemp1\"),\n    6: global.get(\"dimmytemp2\"),\n    7: global.get(\"ruuvitag_0\")?.temp ?? \"\",\n    8: global.get(\"ruuvitag_1\")?.temp ?? \"\",\n    9: global.get(\"ruuvitag_2\")?.temp ?? \"\"\n};\n\n// Check if the payload corresponds to a valid sensor\nif (tempSensorMapping[msg.payload] !== undefined) {\n    msg.payload = tempSensorMapping[msg.payload];\n} else {\n    msg.payload = \"no sensor\"; // Invalid sensor number\n}\n\n// Check if all sensors return empty values\nconst allSensorsEmpty = Object.values(tempSensorMapping).every(sensor => sensor === \"\");\nif (allSensorsEmpty) {\n    msg.payload = \"no TempSensor\"; // No temperature sensor detected\n}\n\n// Handle message return logic\nif (msg.payload === \"no TempSensor\") {\n    msg.payload = \"TempMode not available, no InsideTempSensor set\";\n    return [msg, null]; // Return the error message\n} else {\n    msg.topic = \"setpoint\"; // Set the topic\n    flow.set(\"autoterm2_mode\", \"temp mode\")\n    return [null, msg]; // Return the valid message\n}\n",
        "outputs": 2,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 760,
        "y": 2380,
        "wires": [
            [
                "751f75fbfd5ea754"
            ],
            [
                "00450dfaf4263e44"
            ]
        ]
    },
    {
        "id": "751f75fbfd5ea754",
        "type": "ui_toast",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "position": "dialog",
        "displayTime": "3",
        "highlight": "",
        "sendall": false,
        "outputs": 1,
        "ok": "OK",
        "cancel": "",
        "raw": false,
        "className": "",
        "topic": "",
        "name": "",
        "x": 950,
        "y": 2360,
        "wires": [
            []
        ]
    },
    {
        "id": "ca9ea12469f74a1b",
        "type": "switch",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "ROUTER",
        "property": "usbPort",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "1",
                "vt": "num"
            },
            {
                "t": "eq",
                "v": "2",
                "vt": "num"
            },
            {
                "t": "eq",
                "v": "3",
                "vt": "num"
            },
            {
                "t": "eq",
                "v": "4",
                "vt": "num"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 4,
        "x": 1360,
        "y": 1820,
        "wires": [
            [
                "834763b5e6807c9a"
            ],
            [
                "1a362185d4de590a"
            ],
            [
                "fe9a84e9e99fb913"
            ],
            [
                "e4a11721808db0b1"
            ]
        ]
    },
    {
        "id": "834763b5e6807c9a",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "autoterm out",
        "mode": "link",
        "links": [
            "631e04e732bc5864"
        ],
        "x": 1585,
        "y": 1780,
        "wires": []
    },
    {
        "id": "1a362185d4de590a",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "autoterm out",
        "mode": "link",
        "links": [
            "e1b033b72073b492"
        ],
        "x": 1585,
        "y": 1820,
        "wires": []
    },
    {
        "id": "fe9a84e9e99fb913",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "autoterm out",
        "mode": "link",
        "links": [
            "1b1168f8607d8205"
        ],
        "x": 1585,
        "y": 1860,
        "wires": []
    },
    {
        "id": "e4a11721808db0b1",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "autoterm out",
        "mode": "link",
        "links": [
            "38cb32c06a098f9e"
        ],
        "x": 1585,
        "y": 1900,
        "wires": []
    },
    {
        "id": "9aee726329c401e9",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "autoterm2 HeatingPower",
        "links": [
            "38523125b8085c8b",
            "3cfa5e2cedd3be0e",
            "572f63b680e321fc",
            "6260a11c14751b32",
            "7783954d640394b6"
        ],
        "x": 765,
        "y": 2100,
        "wires": [
            [
                "17aff29b52d75558"
            ]
        ]
    },
    {
        "id": "1a8990ee345dec1e",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "autoterm2 temp mode in",
        "links": [
            "1118365a2f4915bf",
            "3ba986a0eb794bec",
            "4ac31d079971973b"
        ],
        "x": 405,
        "y": 2380,
        "wires": [
            [
                "c64c0da0ce9bde09"
            ]
        ]
    },
    {
        "id": "a05188f6c0ef8ad7",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "autoterm2 in",
        "links": [
            "364010e3c3bb676b",
            "51a6a2320386c92b",
            "68309d30d74db678",
            "df2d1e216890ab1e"
        ],
        "x": 495,
        "y": 3120,
        "wires": [
            [
                "2f97b7cf423ad856"
            ]
        ]
    },
    {
        "id": "7c2a459ff88c8dfa",
        "type": "inject",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "6",
        "crontab": "",
        "once": true,
        "onceDelay": "1",
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 290,
        "y": 1820,
        "wires": [
            [
                "630257cf20439718"
            ]
        ]
    },
    {
        "id": "823e3ad1a06ac715",
        "type": "binary",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "buffer split",
        "property": "payload",
        "pattern": "x8,\nx8,\nx8,\nx8,\nx8,\nb8 => Status,\nb8 => Status2,\nb8 => error,\nb8 => heaterTemp,\nb8 => externTemp,\nx8,\nb8 => batteryVoltage,\nb16 => flameTempK,\nx8,\nx8\n\n\n",
        "x": 1050,
        "y": 3120,
        "wires": [
            [
                "7359b2da34960315",
                "7ce849761c7fffc6",
                "d5daa550215c84c7"
            ]
        ]
    },
    {
        "id": "631e359c6462aeec",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "Check Status",
        "func": "if(msg.payload[4] == 0x0F)\nreturn msg;\n\n /*\n\nStatus:\nController asks for heater status, polls this one periodically.\n\nC >> H aa 03 00 00 0f | 58 7c\nH >> C aa 04 0a 00 0f | 00 01 00 1a 7f 00 7b 01 2b 00 | 50 ad\n                        s1 s2 er ht et    bv ft ft\ns1: Status\n00: Heater off\n01: Starting\n02: Warming up\n03: Running\n04: Shutting down\ner: Heater errors\nht: Heater temperature (as single byte in °C)\net: External temperature (as single byte in °C, 7f when disconnected)\nbv: Battery voltage (as voltage * 10)\nft: Heater flame temperature (as two bytes, big endian, in Kelvin)\n\n*/",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 840,
        "y": 3120,
        "wires": [
            [
                "823e3ad1a06ac715"
            ]
        ]
    },
    {
        "id": "fa65cb7d36d9fe58",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "request settings",
        "func": "// Request settings\nconst buf1 = Buffer.from([\n    0xAA,  // Start byte\n    0x03,  // Read command\n    0x00,  // Address high byte\n    0x00,  // Address low byte\n    0x02,  // Length of the read data\n    0x9d,  // Checksum byte 1\n    0xbd   // Checksum byte 2\n]);\n\n/*\nD2 is the read command from the machine address,\n03 is the read command,\n02 is the length of the read data,\n0001 means to read the value of the first register, that is, the host command is discharged\nFC56 is the CRC check code.\n*/\n\n// Send first message\nmsg.payload = buf1;\nnode.send(msg);\n\n// Delay of 2 seconds before sending the second message\nsetTimeout(function() {\n    // Request status\n    const buf2 = Buffer.from([\n        0xAA,  // Start byte\n        0x03,  // Read command\n        0x00,  // Address high byte\n        0x00,  // Address low byte\n        0x0f,  // Length of the read data\n        0x58,  // Checksum byte 1\n        0x7C   // Checksum byte 2\n    ]);\n\n    /*\n    D2 is the read command from the machine address,\n    03 is the read command,\n    02 is the length of the read data,\n    0001 means to read the value of the first register, that is, the host command is discharged\n    FC56 is the CRC check code.\n    */\n\n    // Create a new message object for the second payload\n    let newMsg = { ...msg }; \n    newMsg.payload = buf2;\n\n    // Send second message after delay\n    node.send(newMsg);\n}, 2000); // 2000 milliseconds = 2 second delay\n\n// Do not return `msg` here, as we already sent it\nreturn null;\n",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 780,
        "y": 1820,
        "wires": [
            [
                "ca9ea12469f74a1b"
            ]
        ]
    },
    {
        "id": "9132acf748a0b437",
        "type": "function",
        "z": "60d59772.e5b728",
        "d": true,
        "g": "fd0a1dcd80269338",
        "name": "Check Seetings?",
        "func": "if(msg.payload[4] == 0x02)\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 850,
        "y": 3160,
        "wires": [
            [
                "0441d4ad2b9c1276"
            ]
        ]
    },
    {
        "id": "0441d4ad2b9c1276",
        "type": "binary",
        "z": "60d59772.e5b728",
        "d": true,
        "g": "fd0a1dcd80269338",
        "name": "buffer split",
        "property": "payload",
        "pattern": "x8,\nx8,\nx8,\nx8,\nx8,\nx8,\nx8,\nb8 => Mode,\nb8 => TempSetpoint,\nb8 => Ventilation,\nb8 => Powerlevel,\nx8,\nx8\n\n\n",
        "x": 1050,
        "y": 3160,
        "wires": [
            []
        ]
    },
    {
        "id": "7359b2da34960315",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "status",
        "func": "// Define a mapping for status codes\nconst statusMessages = {\n    \"0-1\": \"standby\",\n    \"1-0\": \"cooling flame sensor\",\n    \"1-1\": \"ventilation\",\n    \"2-0\": \"heating glow plug 1\",\n    \"2-1\": \"heating glow plug 2\",\n    \"2-2\": \"ignition 1\",\n    \"2-3\": \"ignition 2\",\n    \"2-4\": \"warming up\",\n    \"2-5\": \"no ignition error\",\n    \"2-6\": \"no fuel? retry\",\n    \"3-0\": \"heating\",\n    \"3-35\": \"only fan\",\n    \"3-4\": \"cooling down\",\n    \"1-12\": \"flame-out\",\n    \"4-0\": \"shutting down\"\n};\n\n// Create a key based on status codes\nconst key = `${msg.payload.Status}-${msg.payload.Status2}`;\n\n//Check, if an error exists. If it exists give the code out\nif (msg.payload.error == 0) {\n    // Set the corresponding message if the key exists\n    if (statusMessages[key]) {\n        msg.payload = statusMessages[key];\n    } else {\n        msg.payload = \"unknown status\"; // Handle unexpected status codes\n    }\n} else {\n    if (statusMessages[key]) {\n        msg.payload = statusMessages[key] + \" Error: \" + msg.payload.error\n    } else {\n        msg.payload = \"unknown status Error:\" + msg.payload.error;\n    }\n}\n\n// Store the heat status globally\nglobal.set(\"heatstatus_autoterm2\", msg.payload);\n\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1240,
        "y": 3180,
        "wires": [
            [
                "201a09f3ae88f0a6",
                "bff33215cf36a5d4"
            ]
        ]
    },
    {
        "id": "cf7ebd6dd215c56a",
        "type": "function",
        "z": "60d59772.e5b728",
        "d": true,
        "g": "fd0a1dcd80269338",
        "name": "Check Diagnose",
        "func": "if(msg.payload[2] == 0x48)\nreturn msg;\n\n",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 850,
        "y": 3200,
        "wires": [
            [
                "ba751d788217e26a"
            ]
        ]
    },
    {
        "id": "ba751d788217e26a",
        "type": "binary",
        "z": "60d59772.e5b728",
        "d": true,
        "g": "fd0a1dcd80269338",
        "name": "buffer split",
        "property": "payload",
        "pattern": "x8,\nx8,\nx8,\nx8,\nx8,\n\nb8 => Mode,\nb8 => TempSetpoint,\nb8 => Ventilation,\nb8 => Powerlevel,\nx8,\nx8\n\n\n",
        "x": 1050,
        "y": 3200,
        "wires": [
            []
        ]
    },
    {
        "id": "53a630b93e9f459f",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "Diagnostic mode",
        "info": "Diagnostic mode:\nPC sends this message to turn on the diagnostic mode on the heater.\n\nPC >> H   aa 03 01 00 07 | 01 | 1d 9e\n H >> PC  aa 04 01 00 07 | 01 | dd 2b\nAfter the diagnostic mode is switched on, the heater periodically sends messages that contain a lot of information.\n\n H >> PC  aa 02 48 00 01 | 000100000000049200000400000000000000012a012b00027f19007a00350244032803ff026201f8016b003d003403ff0000200000040f05000000000000000003ff000062000000 | 51 06\n H >> PC  aa 02 48 00 01 | 000100000000049300000500000000000000012a012b00027f19007a00350244032803ff026301f9016a003d003403ff0000200000040f05000000000000000003ff000062000000 | 80 e6\n H >> PC  aa 02 48 00 01 | 000100000000049400000600000000000000012a012b00027f19007a00350244032803ff026201f9016a003d003403ff0000200000040f05000000000000000003ff000062000000 | b3 58\n H >> PC  aa 02 48 00 01 | 000200000000056700000760600000000000012a012afe007f19007500350228032803ff026301f6016c003c003403fe0000200000040f0500000000000000000074000062000000 | 56 69\n H >> PC  aa 02 48 00 01 | 000200000000056800000860610000000000012a012a00fe7f1900750035022a032a03ff026301fd016a003c003403ff0000200000040f0500000000000000000074000063000000 | 53 39\n H >> PC  aa 02 48 00 01 | 000200000000056900000960600000000000012a012afefe7f19007500350228032903ff026301f8016b003c003403fe0000200000040f0500000000000000000074000063000000 | 05 ab\n                           s1s2        c1c1  c2c2drmr          ctctftft    etht  bv\ns1: Status 1\ns2: Status 2\n00: Heater off\n01: Starting\n02: Warming up\n03: Running\n04: Shutting down\nc1: Counter 1\nc2: Counter 2\ndr: Defined RPM\nmr: Measured RPM\nct: Heater chamber temperature (as two bytes, big endian, in Kelvin)\nft: Flame temperature (as two bytes, big endian, in Kelvin)\net: External temperature (as single byte in °C, 7f when disconnected)\nht: Heater temperature (as single byte in °C)\nbv: Battery voltage (as voltage * 10)\nDiagnostic mode could be switch off with this message.\n\nPC >> H   aa 03 01 00 07 | 00 | dd 5f\n H >> PC  aa 04 01 00 07 | 00 | 1d ea",
        "x": 850,
        "y": 3240,
        "wires": []
    },
    {
        "id": "201a09f3ae88f0a6",
        "type": "ui_text",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "group": "515f29cdb93516fd",
        "order": 4,
        "width": 0,
        "height": 0,
        "name": "",
        "label": "State",
        "format": "{{msg.payload}}",
        "layout": "row-spread",
        "className": "",
        "style": false,
        "font": "",
        "fontSize": "",
        "color": "#000000",
        "x": 1430,
        "y": 3140,
        "wires": []
    },
    {
        "id": "dc737ebc7fa97a43",
        "type": "delay",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "",
        "pauseType": "delay",
        "timeout": "2",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 560,
        "y": 1860,
        "wires": [
            [
                "1471f2bb6c7ca3e4"
            ]
        ]
    },
    {
        "id": "1471f2bb6c7ca3e4",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "Send Temperature Value to Heater",
        "func": "// Get the heat temperature sensor number\nmsg.payload = Number(global.get(\"heattempsensor_autoterm2\") == 0 ?  global.get(\"heattempsensor\") : global.get(\"heattempsensor_autoterm2\"));\n\nlet sensorMap = {\n    1: global.get(\"temp1\"),\n    2: global.get(\"temp2\"),\n    3: global.get(\"temp3\"),\n    4: global.get(\"temp4\"),\n    5: global.get(\"dimmytemp1\"),\n    6: global.get(\"dimmytemp2\"),\n    7: global.get(\"ruuvitag_0\")?.temp ?? \"\",\n    8: global.get(\"ruuvitag_1\")?.temp ?? \"\",\n    9: global.get(\"ruuvitag_2\")?.temp ?? \"\"\n};\n\n// Default value for no sensor\nif (!(msg.payload in sensorMap)) {\n    msg.info = \"no Sensor\";\n    msg.payload = 22;  // Default value when no sensor is present\n} else {\n    msg.payload = sensorMap[msg.payload];  // Retrieve sensor value\n}\n\n// Convert payload to hexadecimal and format message\nlet ctemp = toHex(Number(msg.payload).toFixed(0));\nmsg.ctemp = ctemp;\nmsg.payload = \"AA03010011\" + ctemp;\n\nreturn msg;\n\n/**\n * Convert a number to a two-character uppercase hexadecimal string\n * @param {number} d - The number to convert\n * @returns {string} - The hexadecimal string\n */\nfunction toHex(d) {\n    return (\"0\" + (Number(d).toString(16))).slice(-2).toUpperCase();\n}\n\n/*\nSent Temp from controller to heater:\nC >> H  aa 03 01 00 11 | 1a | 76 d0\nH >> C  aa 04 01 00 11 | 1a | b6 65\n                          ct\n*/\n",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 840,
        "y": 1860,
        "wires": [
            [
                "3aa8d4a40cecc839"
            ]
        ]
    },
    {
        "id": "60e60a85b1fcc4d9",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "send request frames 4D",
        "info": "",
        "x": 310,
        "y": 1780,
        "wires": []
    },
    {
        "id": "3aa8d4a40cecc839",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "CRC16-modbus",
        "func": "var CRCMaster = {\n    StringToCheck: \"\",\n    CleanedString: \"\",\n    CRCTableDNP: null,  // Initialize as null to avoid unnecessary memory use\n\n    init: function() {\n        // Initialize the DNP CRC table only if it hasn’t been initialized\n        if (!this.CRCTableDNP) {\n            this.CRCDNPInit();\n        }\n    },\n\n    CleanString: function(inputType) {\n        if (inputType === \"ASCII\") {\n            this.CleanedString = this.StringToCheck;\n        } else {\n            if (/^[0-9A-F \\t]+$/i.test(this.StringToCheck)) {\n                this.CleanedString = this._hexStringToString(\n                    this.StringToCheck.toUpperCase().replace(/[\\t ]/g, '')\n                );\n            } else {\n                //String doesn't seem to be a valid Hex input\n                return false;\n            }\n        }\n        return true;\n    },\n\n    CRCDNPInit: function() {\n        // Create the CRC DNP lookup table\n        this.CRCTableDNP = [];\n        for (let i = 0; i < 256; i++) {\n            let crc = 0;\n            let c = i;\n            for (let j = 0; j < 8; j++) {\n                if ((crc ^ c) & 0x0001) crc = (crc >> 1) ^ 0xA6BC;\n                else crc >>= 1;\n                c >>= 1;\n            }\n            this.CRCTableDNP[i] = crc;\n        }\n    },\n\n    CRC16Modbus: function() {\n        // Calculate the CRC-16 checksum\n        let crc = 0xFFFF;\n        for (let pos = 0; pos < this.CleanedString.length; pos++) {\n            crc ^= this.CleanedString.charCodeAt(pos);\n            for (let i = 8; i !== 0; i--) {\n                if ((crc & 0x0001) !== 0) {\n                    crc >>= 1;\n                    crc ^= 0xA001;\n                } else {\n                    crc >>= 1;\n                }\n            }\n        }\n        return crc;\n    },\n\n    _hexStringToString: function(inputstr) {\n        let str = '';\n        for (let i = 0; i < inputstr.length; i += 2) {\n            str += String.fromCharCode(parseInt(inputstr.substr(i, 2), 16));\n        }\n        return str;\n    },\n\n    Calculate: function(str, inputType) {\n        // Set the string to check\n        this.StringToCheck = str;\n\n        // If cleaning succeeds, calculate and return CRC\n        if (this.CleanString(inputType)) {\n            return this.CRC16Modbus().toString(16).toUpperCase();\n        }\n        return null;  // Return null if the input is invalid\n    }\n};\n\n// Initialize the CRCMaster\nCRCMaster.init();\n\nvar inputType = \"HEX\";\nvar crcinput = msg.payload;\n\n// Calculate the CRC value for the input string\nvar crcResult = CRCMaster.Calculate(crcinput, inputType);\n\n// Attach the result to the payload, or an empty string if CRC calculation failed\nmsg.payload = crcinput + (crcResult || \"\");\n\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1680,
        "y": 2180,
        "wires": [
            [
                "79706501e55433cf"
            ]
        ]
    },
    {
        "id": "79706501e55433cf",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "buffer it",
        "func": "var buf = Buffer.from(msg.payload,\"hex\");\nmsg.payload=buf;\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1700,
        "y": 2220,
        "wires": [
            [
                "d66f1c556e19cbfc"
            ]
        ]
    },
    {
        "id": "d66f1c556e19cbfc",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "check usb port",
        "func": "let autoterm2 = global.get(\"usbport_autoterm2\");\nif (autoterm2 == null) {\n    return null\n}\nelse {\n    // only return if mode for two autoteerms IS NOT set to parallel but individual mode\n    if (!global.get(\"autoterm2_mode\")) {\n    msg.usbPort = autoterm2\n    return msg\n    }\n}",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1920,
        "y": 2180,
        "wires": [
            [
                "ca9ea12469f74a1b"
            ]
        ]
    },
    {
        "id": "ee9a864f5883a4ca",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "REQUESTS",
        "info": "",
        "x": 270,
        "y": 1740,
        "wires": []
    },
    {
        "id": "38ae6960a29fb317",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "UART    ------  2D = 5        -------   4D = 8",
        "info": "",
        "x": 770,
        "y": 1780,
        "wires": []
    },
    {
        "id": "e8ab7963bf895644",
        "type": "delay",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "",
        "pauseType": "delay",
        "timeout": "1",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 720,
        "y": 2020,
        "wires": [
            [
                "1399b6ccc35e59ae"
            ]
        ]
    },
    {
        "id": "f7f5f9658091d726",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "TO ROUTER autoterm2",
        "links": [
            "9aee63f93ec0283e"
        ],
        "x": 1745,
        "y": 2140,
        "wires": [
            [
                "d66f1c556e19cbfc"
            ]
        ]
    },
    {
        "id": "9aee63f93ec0283e",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "TO ROUTER",
        "mode": "link",
        "links": [
            "f7f5f9658091d726"
        ],
        "x": 1255,
        "y": 2020,
        "wires": []
    },
    {
        "id": "ed37acc0f9fb910c",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "STATUS RECEIVE",
        "info": "",
        "x": 580,
        "y": 2880,
        "wires": []
    },
    {
        "id": "eecf6cf101cbbc23",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "Start Tempmode",
        "info": "",
        "x": 540,
        "y": 2340,
        "wires": []
    },
    {
        "id": "27f1fd15106cb875",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "Start Powermode",
        "info": "",
        "x": 540,
        "y": 2180,
        "wires": []
    },
    {
        "id": "e204ef3fc9dd1b9a",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "set heating & global var",
        "func": "if (msg.change == \"background\" || global.get(\"autoterm2_mode\") == true) {\n    return null\n}\nmsg.payload = 0;\nglobal.set(\"HeaterToggle_autoterm2\",false);\nflow.set(\"autoterm2_mode\", \"\")\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 750,
        "y": 2060,
        "wires": [
            [
                "17aff29b52d75558"
            ]
        ]
    },
    {
        "id": "04a44d5b764d0bcb",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "set heating power",
        "func": "var heatingpower = flow.get(\"heatingpower_autoterm2\");\nmsg.payload = \"AA03060001FFFF04FF020\" + heatingpower;\nreturn msg",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1230,
        "y": 2180,
        "wires": [
            [
                "3aa8d4a40cecc839"
            ]
        ]
    },
    {
        "id": "00450dfaf4263e44",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "Start tempmode",
        "func": "global.set(\"HeaterToggle_autoterm2\", true);\nlet settemp = Number(global.get(\"settemp_autoterm2\"));\nsettemp = toHex(settemp)\nflow.set(\"updateFromDisplay\", msg.display ?? false)\nmsg.payload = \"AA03060001FFFF02\" + settemp +\"02FF\";\nreturn msg\n\nfunction toHex(d) {\n    return (\"0\" + (Number(d).toString(16))).slice(-2).toUpperCase()\n}",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1160,
        "y": 2380,
        "wires": [
            [
                "3aa8d4a40cecc839",
                "4177006a5b5dc2aa"
            ]
        ]
    },
    {
        "id": "d4f8519a849964bf",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "4D",
        "info": "",
        "x": 590,
        "y": 3080,
        "wires": []
    },
    {
        "id": "049552aa8bef72b6",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "check usb port",
        "func": "let autoterm2 = global.get(\"usbport_autoterm2\"); // Value can be null, 1, 2, 3, or 4\n\nconst usb1 = 1\nconst usb2 = 2\nconst usb3 = 3\nconst usb4 = 4\n\nlet incomingPort = msg.port\nincomingPort = Number(incomingPort.slice(-1));\n// Create an array of USB sources\nconst usbSources = [\n    global.get(\"usb1uart\"),\n    global.get(\"usb2uart\"),\n    global.get(\"usb3uart\"),\n    global.get(\"usb4uart\")\n];\n\n// Check if autoterm1 is not null, and the corresponding usbSource equals 5\nif (autoterm2 !== null && Number(usbSources[autoterm2 - 1]) === 5 && autoterm2 == incomingPort) {\n    msg.usbPort = autoterm2;\n    return msg;\n}",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 610,
        "y": 2960,
        "wires": [
            [
                "b026ce6eba6f9a87",
                "e39397e4f40cebc5",
                "3d1b08287de7c95c"
            ]
        ]
    },
    {
        "id": "2f97b7cf423ad856",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "check usb port",
        "func": "let autoterm2 = global.get(\"usbport_autoterm2\"); // Value can be null, 1, 2, 3, or 4\n\nconst usb1 = 1\nconst usb2 = 2\nconst usb3 = 3\nconst usb4 = 4\n\nlet incomingPort = msg.port\nincomingPort = Number(incomingPort.slice(-1));\n// Create an array of USB sources\nconst usbSources = [\n    global.get(\"usb1uart\"),\n    global.get(\"usb2uart\"),\n    global.get(\"usb3uart\"),\n    global.get(\"usb4uart\")\n];\n\n// Check if autoterm1 is not null, and the corresponding usbSource equals 8\nif (autoterm2 !== null && Number(usbSources[autoterm2 - 1]) === 8 && autoterm2 == incomingPort) {\n    msg.usbPort = autoterm2;\n    return msg;\n}",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 610,
        "y": 3120,
        "wires": [
            [
                "631e359c6462aeec",
                "9132acf748a0b437",
                "cf7ebd6dd215c56a"
            ]
        ]
    },
    {
        "id": "6a77d532c654d677",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "scale to 0-9",
        "func": "if (msg.change == \"background\" || global.get(\"autoterm2_mode\") == true) {\n    return null\n}\nglobal.set(\"autoterm2_fanspeed\", msg.payload)\nif(msg.payload == 0) {\n    flow.set(\"autoterm2_mode\", \"\")\n    return null;\n}\nmsg.payload = (msg.payload -1).toString()\nmsg.payload = \"AA03040023FFFF0\" + msg.payload + \"FF\";\nif (flow.get(\"autoterm2_mode\") == \"\") {flow.set(\"autoterm2_mode\", \"fan only\")}\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1110,
        "y": 1940,
        "wires": [
            [
                "3aa8d4a40cecc839"
            ]
        ]
    },
    {
        "id": "0dd7f84e43dd4fbc",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "scale to 0-9",
        "func": "if (msg.change == \"background\" || global.get(\"autoterm2_mode\") == true) {\n    return null\n}\n\nglobal.set(\"heatingpower_autoterm2\", msg.payload);\nif(msg.payload == 0) {\n    flow.set(\"heatingpower_autoterm2\",msg.payload);\n    global.set(\"Autotermheatingpower2\",msg.payload);\n    global.set(\"HeaterToggle_autoterm2\",false)\n    flow.set(\"autoterm2_mode\", \"\")\n    return null;\n}\n\nflow.set(\"heatingpower_autoterm2\",msg.payload);\nglobal.set(\"Autotermheatingpower2\",msg.payload);\nglobal.set(\"HeaterToggle_autoterm2\",true);\nflow.set(\"autoterm2_mode\", \"power mode\")\nmsg.payload = msg.payload -1\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1110,
        "y": 2100,
        "wires": [
            [
                "d37d614f33c57150",
                "8c1c86bc95a5b312"
            ]
        ]
    },
    {
        "id": "7ce849761c7fffc6",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "voltage",
        "func": "msg.payload= msg.payload.batteryVoltage/10;\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1250,
        "y": 3220,
        "wires": [
            [
                "6d70b29b03c32fd0"
            ]
        ]
    },
    {
        "id": "f5243159fd127654",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "autoterm2 Update Tempmode",
        "links": [
            "c42af9e324f834bc"
        ],
        "x": 525,
        "y": 2300,
        "wires": [
            [
                "efd49bd71fddc65b"
            ]
        ]
    },
    {
        "id": "ce12876b0dd7af8e",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "Update TempMode",
        "info": "",
        "x": 550,
        "y": 2260,
        "wires": []
    },
    {
        "id": "efd49bd71fddc65b",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "check sensor",
        "func": "// Retrieve the temperature sensor value\nmsg.payload = global.get(\"heattempsensor_autoterm2\") == 0 ? global.get(\"heattempsensor\") : global.get(\"heattempsensor_autoterm2\")\n\n// Parse USB UART values\nconst usbValues = [\n    parseInt(global.get(\"usb1uart\")),\n    parseInt(global.get(\"usb2uart\")),\n    parseInt(global.get(\"usb3uart\")),\n    parseInt(global.get(\"usb4uart\"))\n];\n\n// Check if none of the USB values are 5 or 8\nif (!usbValues.includes(5) && !usbValues.includes(8)) {\n    return null; // No valid USB value found, exit\n}\n\n// Define a mapping for heat sensor values\nconst tempSensorMapping = {\n    1: global.get(\"temp1\"),\n    2: global.get(\"temp2\"),\n    3: global.get(\"temp3\"),\n    4: global.get(\"temp4\"),\n    5: global.get(\"dimmytemp1\"),\n    6: global.get(\"dimmytemp2\"),\n    7: global.get(\"ruuvitag_0\")?.temp ?? \"\",\n    8: global.get(\"ruuvitag_1\")?.temp ?? \"\",\n    9: global.get(\"ruuvitag_2\")?.temp ?? \"\"\n};\n\n// Check if the payload corresponds to a valid sensor\nif (tempSensorMapping[msg.payload] !== undefined) {\n    msg.payload = tempSensorMapping[msg.payload];\n} else {\n    msg.payload = \"no sensor\"; // Invalid sensor number\n}\n\n// Check if all sensors return empty values\nconst allSensorsEmpty = Object.values(tempSensorMapping).every(sensor => sensor === \"\");\nif (allSensorsEmpty) {\n    msg.payload = \"no TempSensor\"; // No temperature sensor detected\n}\n\n// Handle message return logic\nif (msg.payload === \"no TempSensor\") {\n    msg.payload = \"TempMode not available, no InsideTempSensor set\";\n    return [msg, null]; // Return the error message\n} else {\n    msg.topic = \"setpoint\"; // Set the topic\n    return [null, msg]; // Return the valid message\n}\n",
        "outputs": 2,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 720,
        "y": 2300,
        "wires": [
            [
                "1c1586a28680f628"
            ],
            [
                "1f1e470952e7a61b"
            ]
        ]
    },
    {
        "id": "1c1586a28680f628",
        "type": "ui_toast",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "position": "dialog",
        "displayTime": "3",
        "highlight": "",
        "sendall": false,
        "outputs": 1,
        "ok": "OK",
        "cancel": "",
        "raw": false,
        "className": "",
        "topic": "",
        "name": "",
        "x": 930,
        "y": 2280,
        "wires": [
            []
        ]
    },
    {
        "id": "1f1e470952e7a61b",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "Update tempmode",
        "func": "let settemp = Number(global.get(\"settemp_autoterm2\"));\nsettemp = toHex(settemp)\nmsg.payload = \"AA03060002FFFF02\" + settemp +\"02FF\";\nreturn msg\n\nfunction toHex(d) {\n    return (\"0\" + (Number(d).toString(16))).slice(-2).toUpperCase()\n}",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1150,
        "y": 2300,
        "wires": [
            [
                "3aa8d4a40cecc839"
            ]
        ]
    },
    {
        "id": "854c44a74f71838c",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "↨ 2D + 4D ↨",
        "info": "",
        "x": 1170,
        "y": 2340,
        "wires": []
    },
    {
        "id": "f25930dd8526d2c9",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "update heating power",
        "func": "var heatingpower = flow.get(\"heatingpower_autoterm2\");\nmsg.payload = \"AA03060002FFFF04FF020\" + heatingpower;\nreturn msg",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1440,
        "y": 2100,
        "wires": [
            [
                "3aa8d4a40cecc839"
            ]
        ]
    },
    {
        "id": "d37d614f33c57150",
        "type": "delay",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "200ms",
        "pauseType": "delay",
        "timeout": "200",
        "timeoutUnits": "milliseconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 1250,
        "y": 2100,
        "wires": [
            [
                "f25930dd8526d2c9"
            ]
        ]
    },
    {
        "id": "8c1c86bc95a5b312",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "check if heater is on",
        "func": "if (global.get(\"HeaterToggle_autoterm2\")==true)\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1000,
        "y": 2180,
        "wires": [
            [
                "04a44d5b764d0bcb"
            ]
        ]
    },
    {
        "id": "4629e8a049ed50d5",
        "type": "delay",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "",
        "pauseType": "delay",
        "timeout": "400",
        "timeoutUnits": "milliseconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 530,
        "y": 2140,
        "wires": [
            [
                "a0983250bb9fe654",
                "3a3ca0bd5d4fd983"
            ]
        ]
    },
    {
        "id": "c7991555da2cfc3b",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "stop if 0",
        "func": "if (msg.change == \"background\" || global.get(\"autoterm2_mode\") == true) {\n    return null\n}\nif(msg.payload == 0) {\n    return msg;\n}\n",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1100,
        "y": 1980,
        "wires": [
            [
                "1399b6ccc35e59ae"
            ]
        ]
    },
    {
        "id": "959622e729ad8a22",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "stop if 0",
        "func": "if (msg.change == \"background\" || global.get(\"autoterm2_mode\") == true) {\n    return null\n}\n\nif(msg.payload == 0) {\n    return msg;\n}\n",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1100,
        "y": 2060,
        "wires": [
            [
                "1399b6ccc35e59ae"
            ]
        ]
    },
    {
        "id": "3094087f26dd2c66",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "set heater globalVal on",
        "func": "if (msg.change == \"background\" || global.get(\"autoterm2_mode\") == true) {\n    return null\n}\nglobal.set(\"HeaterToggle_autoterm2\",true);\nflow.set(\"autoterm2_mode\", \"power mode\")\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 570,
        "y": 2220,
        "wires": [
            [
                "016f3a3887cb7a2f"
            ]
        ]
    },
    {
        "id": "a0983250bb9fe654",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "start from display",
        "func": "if (msg.change == \"background\" || global.get(\"autoterm2_mode\") == true) {\n    return null\n}\nif(msg.payload[0]=0xbb) {\n    msg.payload = global.get(\"heatingpower_autoterm2\");\n    return msg;\n}",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 750,
        "y": 2180,
        "wires": [
            [
                "8c1c86bc95a5b312"
            ]
        ]
    },
    {
        "id": "3a3ca0bd5d4fd983",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "Set heating 1",
        "func": "if (msg.change == \"background\" || global.get(\"autoterm2_mode\") == true) {\n    return null\n}\nmsg.payload = 1;\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 740,
        "y": 2140,
        "wires": [
            [
                "17aff29b52d75558"
            ]
        ]
    },
    {
        "id": "8c85cdd689ce2643",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "autoterm2 ventilation",
        "links": [
            "2353a47275e85e0a",
            "35954fcdd8a1d948",
            "3656cd1ecbbb7427",
            "5be81bd5b43f94d0",
            "dcf7fa854b924f67"
        ],
        "x": 785,
        "y": 1940,
        "wires": [
            [
                "e23a935b5d5fba5b"
            ]
        ]
    },
    {
        "id": "630257cf20439718",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "check usb port",
        "func": "let autoterm2 = global.get(\"usbport_autoterm2\");\nif (autoterm2 == null) {\n    return null\n}\nelse {\n    msg.usbPort = autoterm2\n    return msg\n}",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 520,
        "y": 1820,
        "wires": [
            [
                "fa65cb7d36d9fe58",
                "dc737ebc7fa97a43"
            ]
        ]
    },
    {
        "id": "e23a935b5d5fba5b",
        "type": "ui_numeric",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "",
        "label": "Fan",
        "tooltip": "",
        "group": "515f29cdb93516fd",
        "order": 8,
        "width": "3",
        "height": "1",
        "wrap": false,
        "passthru": true,
        "topic": "topic",
        "topicType": "msg",
        "format": "{{value}}",
        "min": "1",
        "max": 10,
        "step": 1,
        "className": "",
        "x": 910,
        "y": 1980,
        "wires": [
            [
                "6a77d532c654d677",
                "c7991555da2cfc3b"
            ]
        ]
    },
    {
        "id": "17aff29b52d75558",
        "type": "ui_numeric",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "",
        "label": "Power<br>Mode",
        "tooltip": "",
        "group": "515f29cdb93516fd",
        "order": 9,
        "width": "3",
        "height": "1",
        "wrap": false,
        "passthru": true,
        "topic": "topic",
        "topicType": "msg",
        "format": "{{value}}",
        "min": "1",
        "max": 10,
        "step": 1,
        "className": "",
        "x": 920,
        "y": 2100,
        "wires": [
            [
                "959622e729ad8a22",
                "0dd7f84e43dd4fbc"
            ]
        ]
    },
    {
        "id": "6d70b29b03c32fd0",
        "type": "ui_text",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "group": "515f29cdb93516fd",
        "order": 11,
        "width": 3,
        "height": 1,
        "name": "",
        "label": "Voltage",
        "format": "<center>{{msg.payload}} V",
        "layout": "row-spread",
        "className": "",
        "style": false,
        "font": "",
        "fontSize": 16,
        "color": "#000000",
        "x": 1440,
        "y": 3180,
        "wires": []
    },
    {
        "id": "86392067b684886c",
        "type": "ui_text",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "group": "515f29cdb93516fd",
        "order": 14,
        "width": 3,
        "height": 1,
        "name": "",
        "label": "Heater",
        "format": "<center>{{msg.payload}}°C",
        "layout": "row-spread",
        "className": "",
        "style": false,
        "font": "",
        "fontSize": 16,
        "color": "#000000",
        "x": 1430,
        "y": 3040,
        "wires": []
    },
    {
        "id": "272b5c1972df2b07",
        "type": "ui_text",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "group": "515f29cdb93516fd",
        "order": 12,
        "width": 3,
        "height": 1,
        "name": "",
        "label": "Fan",
        "format": "<center>{{msg.payload}} rpm",
        "layout": "row-spread",
        "className": "",
        "style": false,
        "font": "",
        "fontSize": 16,
        "color": "#000000",
        "x": 1430,
        "y": 3000,
        "wires": []
    },
    {
        "id": "659d9836a1950609",
        "type": "ui_text",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "group": "515f29cdb93516fd",
        "order": 13,
        "width": 3,
        "height": 1,
        "name": "",
        "label": "Pump",
        "format": "<center>{{msg.payload}} Hz",
        "layout": "row-spread",
        "className": "",
        "style": false,
        "font": "",
        "fontSize": 16,
        "color": "#000000",
        "x": 1430,
        "y": 2960,
        "wires": []
    },
    {
        "id": "bff33215cf36a5d4",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "heat status autoterm",
        "mode": "link",
        "links": [
            "0c51a82c40609692"
        ],
        "x": 1395,
        "y": 3100,
        "wires": []
    },
    {
        "id": "1e6cab4a1dcf0b81",
        "type": "ui_button",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "",
        "group": "515f29cdb93516fd",
        "order": 10,
        "width": "6",
        "height": "1",
        "passthru": true,
        "label": "Stop",
        "tooltip": "",
        "color": "{{fontcolor}}",
        "bgcolor": "{{background}}",
        "className": "autoterm2",
        "icon": "",
        "payload": "",
        "payloadType": "num",
        "topic": "",
        "topicType": "str",
        "x": 430,
        "y": 2060,
        "wires": [
            [
                "03820fcd94da7f59",
                "e204ef3fc9dd1b9a",
                "524de6910c56e907"
            ]
        ]
    },
    {
        "id": "17bc994c48ef15a7",
        "type": "file",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "",
        "filename": "pekaway/settemp_autoterm2",
        "filenameType": "str",
        "appendNewline": false,
        "createDir": true,
        "overwriteFile": "true",
        "encoding": "none",
        "x": 1720,
        "y": 2500,
        "wires": [
            []
        ]
    },
    {
        "id": "1f6ecd32d9cc8d27",
        "type": "file in",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "",
        "filename": "pekaway/settemp_autoterm2",
        "filenameType": "str",
        "format": "utf8",
        "chunk": false,
        "sendError": false,
        "encoding": "none",
        "allProps": false,
        "x": 540,
        "y": 2500,
        "wires": [
            [
                "f220951af3ebef23"
            ]
        ]
    },
    {
        "id": "b6f99b203b35753d",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "TEMPERATURE VIEW",
        "info": "",
        "x": 980,
        "y": 2460,
        "wires": []
    },
    {
        "id": "20d7d8610792929b",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "autoterm2 settemp",
        "links": [
            "204604583c498134",
            "2d96e8.2c96e918",
            "4f99d551f8bcef8f",
            "6d16441cb6c88add",
            "77c73221521511f6",
            "a5478aaf4daf1591",
            "a59d3296db090be0",
            "4ac31d079971973b"
        ],
        "x": 825,
        "y": 2540,
        "wires": [
            [
                "349d6ee22ce2a82c"
            ]
        ]
    },
    {
        "id": "c42af9e324f834bc",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "Update Autoterm",
        "mode": "link",
        "links": [
            "f5243159fd127654"
        ],
        "x": 1765,
        "y": 2460,
        "wires": []
    },
    {
        "id": "f220951af3ebef23",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "parse Number",
        "func": "msg.payload = Number(msg.payload)\nmsg.saved_settemp = msg.payload\nlet autotermPort = global.get(\"usbport_autoterm1\") || null\nif (!flow.get(\"updateFromDisplay\") && autotermPort != null) { return msg; }",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 760,
        "y": 2500,
        "wires": [
            [
                "349d6ee22ce2a82c"
            ]
        ]
    },
    {
        "id": "0934a5c6a76be1a8",
        "type": "ui_button",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "set temp down",
        "group": "515f29cdb93516fd",
        "order": 1,
        "width": 1,
        "height": 2,
        "passthru": false,
        "label": "",
        "tooltip": "",
        "color": "{{fontcolor}}",
        "bgcolor": "{{background}}",
        "className": "",
        "icon": "chevron_left",
        "payload": "down",
        "payloadType": "str",
        "topic": "button_down_autoterm2",
        "topicType": "str",
        "x": 760,
        "y": 2420,
        "wires": [
            [
                "349d6ee22ce2a82c"
            ]
        ]
    },
    {
        "id": "da652ce989439669",
        "type": "ui_text",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "group": "515f29cdb93516fd",
        "order": 2,
        "width": 4,
        "height": 2,
        "name": "show temp webinterface",
        "label": "<center>{{msg.label.trim()}}: {{msg.ambientTemp}}°C",
        "format": "{{msg.payload}}",
        "layout": "col-center",
        "className": "",
        "style": false,
        "font": "",
        "fontSize": 16,
        "color": "#000000",
        "x": 1250,
        "y": 2500,
        "wires": []
    },
    {
        "id": "0471b3d1c34a252f",
        "type": "ui_button",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "set temp up",
        "group": "515f29cdb93516fd",
        "order": 3,
        "width": 1,
        "height": 2,
        "passthru": false,
        "label": "",
        "tooltip": "",
        "color": "{{fontcolor}}",
        "bgcolor": "{{background}}",
        "className": "",
        "icon": "chevron_right",
        "payload": "up",
        "payloadType": "str",
        "topic": "button_up_autoterm2",
        "topicType": "str",
        "x": 770,
        "y": 2460,
        "wires": [
            [
                "349d6ee22ce2a82c"
            ]
        ]
    },
    {
        "id": "349d6ee22ce2a82c",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "get temp & buttonpress",
        "func": "//TODO: parallel mode\nlet parallel = global.get(\"autoterm2_mode\") || false\nglobal.set(\"autoterm2_mode_current\", parallel == true ? flow.get(\"autoterm1_mode\") : flow.get(\"autoterm2_mode\"))\nlet settemp = parallel == true ? global.get(\"settemp_autoterm1\") ?? 22 : global.get(\"settemp_autoterm2\") ?? 22;\nflow.set(\"settemp_autoterm2\", settemp);\nlet heaterToggle = parallel == true ? global.get(\"HeaterToggle_autoterm1\") || false : global.get(\"HeaterToggle_autoterm2\") || false;\nif (msg.topic == \"\" || msg.topic == null) { msg.topic = \"autoterm2\"}\nlet topic = msg.topic.includes(\"autoterm2\") ? \"autoterm2\" : \"autoterm1\"\n\n// settemp coming from API/Touchdisplay/Boot\n// (payload is not an object, as it is from ds18b20 script)\n// and it is a Number\nif (parallel) {\n    settemp = settemp\n}\nelse if (!isNaN(msg.payload) && typeof msg.payload != 'object' && topic != \"autoterm1\" && msg.topic != \"sensor_update\" && msg.topic !== \"ui_scheduler\") {\n    settemp = msg.payload;\n} else {\n    // else get saved settemp\n    if (msg.payload == \"up\" && settemp < 35 && !parallel && topic == \"autoterm2\") {\n        settemp = Number(settemp) + 1;\n    } else if (msg.payload == \"down\" && settemp > 2 && !parallel && topic == \"autoterm2\") {\n        settemp = Number(settemp) - 1;\n    }\n}\n\nglobal.set(\"settemp_autoterm2\", settemp);\nmsg.settemp = Number(settemp);\nlet currentMode = parallel ? flow.get(\"autoterm1_mode\") : flow.get(\"autoterm2_mode\")\ncurrentMode = currentMode == \"\" ? \"\" : \"<center><font size='2'>(\"+currentMode+\")\"\n// if heater is on, change font color to orange\nmsg.payload = heaterToggle === true\n    ? `<font size=\"8\" color=\"#FF5F15\">${settemp}°C</font>${currentMode}`\n    : `<font size=\"8\">${settemp}°C</font>${currentMode}`;\n\n    \n// -----------------------------------------------------\n// Get current ambient temperature sensor and label\n// Now supports IDs 1–13 (incl. NTCs 10–13)\n// -----------------------------------------------------\nlet ambientTempSensor = Number(global.get(\"heattempsensor\"));\n\n// Helper so we don't treat 0 as \"no sensor\"\nfunction hasValue(v) {\n    return v !== undefined && v !== null && v !== \"\" && v !== \"not connected\";\n}\n\nif (![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13].includes(ambientTempSensor)) {\n    // invalid or not set -> generic\n    msg.ambientTemp = \"N/A\";\n    msg.label = \"Tempsensor:\";\n} else if (ambientTempSensor === 1) {\n    msg.ambientTemp = global.get(\"temp1\") ?? \"\";\n    msg.label = global.get(\"Ntemp1\") ?? \"Temp Sensor 1\";\n} else if (ambientTempSensor === 2) {\n    msg.ambientTemp = global.get(\"temp2\") ?? \"\";\n    msg.label = global.get(\"Ntemp2\") ?? \"Temp Sensor 2\";\n} else if (ambientTempSensor === 3) {\n    msg.ambientTemp = global.get(\"temp3\") ?? \"\";\n    msg.label = global.get(\"Ntemp3\") ?? \"Temp Sensor 3\";\n} else if (ambientTempSensor === 4) {\n    msg.ambientTemp = global.get(\"temp4\") ?? \"\";\n    msg.label = global.get(\"Ntemp4\") ?? \"Temp Sensor 4\";\n} else if (ambientTempSensor === 5) {\n    msg.ambientTemp = global.get(\"dimmytemp1\") ?? \"\";\n    msg.label = global.get(\"Ndimmytemp1\") ?? \"Dimmy Temp 1\";\n} else if (ambientTempSensor === 6) {\n    msg.ambientTemp = global.get(\"dimmytemp2\") ?? \"\";\n    msg.label = global.get(\"Ndimmytemp2\") ?? \"Dimmy Temp 2\";\n} else if (ambientTempSensor === 7) {\n    msg.ambientTemp = global.get(\"ruuvitag_0\")?.temp ?? \"\";\n    msg.label = global.get(\"ruuvitag_0_name\") ?? \"RuuviTag 1\";\n} else if (ambientTempSensor === 8) {\n    msg.ambientTemp = global.get(\"ruuvitag_1\")?.temp ?? \"\";\n    msg.label = global.get(\"ruuvitag_1_name\") ?? \"RuuviTag 2\";\n} else if (ambientTempSensor === 9) {\n    msg.ambientTemp = global.get(\"ruuvitag_2\")?.temp ?? \"\";\n    msg.label = global.get(\"ruuvitag_2_name\") ?? \"RuuviTag 3\";\n}\n\n// ------- NEW: NTCs 10–13 -------\nelse if (ambientTempSensor === 10) {\n    msg.ambientTemp = global.get(\"ntc1\") ?? \"\";\n    msg.label = global.get(\"NLevel1\") ?? \"NTC 1\";\n} else if (ambientTempSensor === 11) {\n    msg.ambientTemp = global.get(\"ntc2\") ?? \"\";\n    msg.label = global.get(\"NLevel2\") ?? \"NTC 2\";\n} else if (ambientTempSensor === 12) {\n    msg.ambientTemp = global.get(\"ntc3\") ?? \"\";\n    msg.label = global.get(\"NLevel3\") ?? \"NTC 3\";\n} else if (ambientTempSensor === 13) {\n    msg.ambientTemp = global.get(\"ntc4\") ?? \"\";\n    msg.label = global.get(\"NLevel4\") ?? \"NTC 4\";\n}\n\n// -----------------------------------------------------\n// Check if *all* sensors are effectively unavailable\n// (now including NTCs, but not treating 0 as \"no sensor\")\n// -----------------------------------------------------\nconst noSensors =\n    !hasValue(global.get(\"temp1\")) &&\n    !hasValue(global.get(\"temp2\")) &&\n    !hasValue(global.get(\"temp3\")) &&\n    !hasValue(global.get(\"temp4\")) &&\n    !hasValue(global.get(\"dimmytemp1\")) &&\n    !hasValue(global.get(\"dimmytemp2\")) &&\n    (!hasValue(global.get(\"ruuvitag_0\")?.temp)) &&\n    (!hasValue(global.get(\"ruuvitag_1\")?.temp)) &&\n    (!hasValue(global.get(\"ruuvitag_2\")?.temp)) &&\n    !hasValue(global.get(\"ntc1\")) &&\n    !hasValue(global.get(\"ntc2\")) &&\n    !hasValue(global.get(\"ntc3\")) &&\n    !hasValue(global.get(\"ntc4\"));\n\nif (noSensors) {\n    msg.ambientTemp = \"N/A\";\n    msg.label = \"No sensors available\";\n}\nif (flow.get(\"updateFromDisplay\")) { flow.set(\"updateFromDisplay\", false)}\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 990,
        "y": 2500,
        "wires": [
            [
                "da652ce989439669",
                "3a4d9331370d75a3"
            ]
        ]
    },
    {
        "id": "452e95e669371e11",
        "type": "ui_ui_control",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "",
        "events": "change",
        "x": 160,
        "y": 2500,
        "wires": [
            [
                "beba3e63965374aa"
            ]
        ]
    },
    {
        "id": "beba3e63965374aa",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "check tab",
        "func": "if (msg.payload == \"change\" && msg.name == \"Heater\") {\n    msg.topic = \"changeTab\"\n    return msg;\n}",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 300,
        "y": 2500,
        "wires": [
            [
                "1f6ecd32d9cc8d27",
                "f293282ea9e39f06",
                "09da66e7f6d79d40"
            ]
        ]
    },
    {
        "id": "954124c1c5f5d203",
        "type": "inject",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "5s",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "5",
        "crontab": "",
        "once": true,
        "onceDelay": "20",
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 170,
        "y": 2460,
        "wires": [
            [
                "a31f71ad95945e05"
            ]
        ]
    },
    {
        "id": "3a4d9331370d75a3",
        "type": "change",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "",
        "rules": [
            {
                "t": "move",
                "p": "settemp",
                "pt": "msg",
                "to": "payload",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 1230,
        "y": 2460,
        "wires": [
            [
                "1642e2e3f36559b2"
            ]
        ]
    },
    {
        "id": "1642e2e3f36559b2",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "write if changed",
        "func": "if (Number(flow.get(\"settemp_autoterm2\")) == msg.payload && msg.topic != \"setpoint\") {\n    return null\n}\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1420,
        "y": 2460,
        "wires": [
            [
                "17bc994c48ef15a7",
                "c42af9e324f834bc"
            ]
        ]
    },
    {
        "id": "6d16441cb6c88add",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "to settemp",
        "mode": "link",
        "links": [
            "20d7d8610792929b"
        ],
        "x": 1465,
        "y": 2380,
        "wires": []
    },
    {
        "id": "4177006a5b5dc2aa",
        "type": "delay",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "",
        "pauseType": "delay",
        "timeout": "1",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 1360,
        "y": 2380,
        "wires": [
            [
                "6d16441cb6c88add"
            ]
        ]
    },
    {
        "id": "4f99d551f8bcef8f",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "to settemp",
        "mode": "link",
        "links": [
            "20d7d8610792929b"
        ],
        "x": 915,
        "y": 2220,
        "wires": []
    },
    {
        "id": "016f3a3887cb7a2f",
        "type": "delay",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "",
        "pauseType": "delay",
        "timeout": "1",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 780,
        "y": 2220,
        "wires": [
            [
                "4f99d551f8bcef8f"
            ]
        ]
    },
    {
        "id": "77c73221521511f6",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "to settemp",
        "mode": "link",
        "links": [
            "7c825eee5dde7de2",
            "20d7d8610792929b"
        ],
        "x": 715,
        "y": 2100,
        "wires": []
    },
    {
        "id": "524de6910c56e907",
        "type": "delay",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "",
        "pauseType": "delay",
        "timeout": "1",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 580,
        "y": 2100,
        "wires": [
            [
                "77c73221521511f6"
            ]
        ]
    },
    {
        "id": "96007a80ca96f985",
        "type": "countdown",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "",
        "topic": "",
        "payloadTimerStart": "true",
        "payloadTimerStartType": "bool",
        "payloadTimerStop": "false",
        "payloadTimerStopType": "bool",
        "timer": 30,
        "resetWhileRunning": true,
        "setTimeToNewWhileRunning": true,
        "startCountdownOnControlMessage": true,
        "minuteCounter": false,
        "x": 1070,
        "y": 2800,
        "wires": [
            [
                "25f6a071893a1bd8"
            ],
            [
                "25f6a071893a1bd8",
                "dae6751c69f1d7dc"
            ]
        ]
    },
    {
        "id": "51cbcc9df0ed9de5",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "set Topic to Control",
        "func": "if (msg.change == \"background\" || global.get(\"autoterm2_mode\") == true) {\n    return null\n}\n\nif (msg.payload == 0) {\n    global.set(\"heater_runtime_autoterm2\", msg.payload)\n    msg.payload = \"cancel\"\n    msg.topic = \"control\"\n    return msg\n}\nelse {\n    global.set(\"heater_runtime_autoterm2\", msg.payload)\n    msg.payload = Number(msg.payload*60)\n    msg.topic=\"control\";\n    return  msg\n}",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 850,
        "y": 2800,
        "wires": [
            [
                "ad79043cc5c554d5",
                "96007a80ca96f985"
            ]
        ]
    },
    {
        "id": "25f6a071893a1bd8",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "turn heater off",
        "func": "if (msg.change == \"background\" || global.get(\"autoterm2_mode\") == true) {\n    return null\n}\n\nif(msg.payload==false) {\n    msg.payload=\"Off\";\n    return msg;\n}",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1260,
        "y": 2800,
        "wires": [
            [
                "7ed5ad65c02cd406"
            ]
        ]
    },
    {
        "id": "dae6751c69f1d7dc",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "remaining time",
        "func": "if (msg.payload == -1 || msg.payload == -0) {\n    global.set(\"autoterm2_remaining_runtime\", 0)\n    return null\n}\n\nif (msg.payload == \"cancel\") {\n    msg.payload = \" \"\n    msg.background = \"transparent\"\n    global.set(\"autoterm2_remaining_runtime\", 0)\n    return msg\n}\nelse {\n    let totalSeconds = msg.payload;\n    global.set(\"autoterm2_remaining_runtime\", totalSeconds)\n\n    // Calculate hours\n    let hours = Math.floor(totalSeconds / 3600);\n    hours = (hours < 10) ? \"0\" + hours : hours;\n\n    // Calculate remaining minutes\n    let minutes = Math.floor((totalSeconds % 3600) / 60);\n    minutes = (minutes < 10) ? \"0\" + minutes : minutes;\n\n    // Calculate remaining seconds\n    let seconds = totalSeconds % 60;\n    seconds = (seconds < 10) ? \"0\" + seconds : seconds;\n\n    // Format the output as hh:mm:ss\n    msg.payload = `<font color=\"#FF5F15\">${hours}:${minutes}:${seconds}</font>`;\n    msg.background = \"\"\n    return msg;\n\n}",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1260,
        "y": 2840,
        "wires": [
            [
                "e0f2150a33778a93"
            ]
        ]
    },
    {
        "id": "ce77c805fd6f375d",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "stop countdown",
        "func": "msg.payload = \"cancel\"\nmsg.topic = \"control\"\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 860,
        "y": 2840,
        "wires": [
            [
                "96007a80ca96f985",
                "62a00a20dca1d386"
            ]
        ]
    },
    {
        "id": "62a00a20dca1d386",
        "type": "delay",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "750ms",
        "pauseType": "delay",
        "timeout": "0.75",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 1050,
        "y": 2920,
        "wires": [
            [
                "b98a68a6de01af38",
                "dae6751c69f1d7dc"
            ]
        ]
    },
    {
        "id": "b98a68a6de01af38",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "stop countdown",
        "func": "msg.payload = 0\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 440,
        "y": 2800,
        "wires": [
            [
                "6a765babb1382104"
            ]
        ]
    },
    {
        "id": "ad79043cc5c554d5",
        "type": "delay",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "400ms",
        "pauseType": "delay",
        "timeout": "400",
        "timeoutUnits": "milliseconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 1050,
        "y": 2860,
        "wires": [
            [
                "dae6751c69f1d7dc"
            ]
        ]
    },
    {
        "id": "b71e5390f1a13c55",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "autoterm2 runtime",
        "links": [
            "204604583c498134",
            "a5478aaf4daf1591",
            "100fd239c7f29260"
        ],
        "x": 505,
        "y": 2760,
        "wires": [
            [
                "6a765babb1382104"
            ]
        ]
    },
    {
        "id": "7ed5ad65c02cd406",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "link out 6",
        "mode": "link",
        "links": [
            "4bafa884adfb8089"
        ],
        "x": 1475,
        "y": 2800,
        "wires": []
    },
    {
        "id": "6a765babb1382104",
        "type": "ui_numeric",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "runtime",
        "label": "<center>Runtime (min)",
        "tooltip": "",
        "group": "515f29cdb93516fd",
        "order": 17,
        "width": 4,
        "height": 1,
        "wrap": true,
        "passthru": true,
        "topic": "topic",
        "topicType": "msg",
        "format": "{{value}}",
        "min": 0,
        "max": "600",
        "step": "15",
        "className": "",
        "x": 660,
        "y": 2800,
        "wires": [
            [
                "51cbcc9df0ed9de5"
            ]
        ]
    },
    {
        "id": "e0f2150a33778a93",
        "type": "ui_button",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "remaining/reset",
        "group": "515f29cdb93516fd",
        "order": 16,
        "width": 2,
        "height": 1,
        "passthru": false,
        "label": "{{payload}}",
        "tooltip": "Click to reset the timer",
        "color": "",
        "bgcolor": "{{background}}",
        "className": "",
        "icon": "",
        "payload": "reset",
        "payloadType": "str",
        "topic": "topic",
        "topicType": "msg",
        "x": 1460,
        "y": 2840,
        "wires": [
            [
                "ce77c805fd6f375d"
            ]
        ]
    },
    {
        "id": "7c825eee5dde7de2",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "autoterm2 runtime stop",
        "links": [
            "77c73221521511f6"
        ],
        "x": 705,
        "y": 2840,
        "wires": [
            [
                "ce77c805fd6f375d"
            ]
        ]
    },
    {
        "id": "4bafa884adfb8089",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "autoterm2 touch stop",
        "links": [
            "02704f818d1241aa",
            "7ed5ad65c02cd406"
        ],
        "x": 315,
        "y": 2060,
        "wires": [
            [
                "1e6cab4a1dcf0b81"
            ]
        ]
    },
    {
        "id": "b6a317f071b7fc52",
        "type": "inject",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": "2",
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 290,
        "y": 2680,
        "wires": [
            [
                "f293282ea9e39f06",
                "09da66e7f6d79d40"
            ]
        ]
    },
    {
        "id": "484f4295724356ec",
        "type": "ui_dropdown",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "Tempsensor",
        "label": "",
        "tooltip": "set sensor for heater room temperature control",
        "place": "Sensor",
        "group": "515f29cdb93516fd",
        "order": 20,
        "width": "3",
        "height": 1,
        "passthru": true,
        "multiple": false,
        "options": [],
        "payload": "",
        "topic": "",
        "topicType": "str",
        "className": "",
        "x": 970,
        "y": 2640,
        "wires": [
            [
                "7b8f65b694673686"
            ]
        ]
    },
    {
        "id": "7b8f65b694673686",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "set global",
        "func": "// Selected ID from dropdown\nconst id = Number(msg.payload);\nlet label;\n\n// Map ID → human readable label\nswitch (id) {\n    case 0:\n        label = \"same as autoterm1\";\n        break;\n\n    case 1:\n        label = global.get(\"Ntemp1\") || \"Temp Sensor 1\";\n        break;\n    case 2:\n        label = global.get(\"Ntemp2\") || \"Temp Sensor 2\";\n        break;\n    case 3:\n        label = global.get(\"Ntemp3\") || \"Temp Sensor 3\";\n        break;\n    case 4:\n        label = global.get(\"Ntemp4\") || \"Temp Sensor 4\";\n        break;\n\n    case 5:\n        label = global.get(\"Ndimmytemp1\") || \"Dimmy Temp 1\";\n        break;\n    case 6:\n        label = global.get(\"Ndimmytemp2\") || \"Dimmy Temp 2\";\n        break;\n\n    case 7:\n        label = global.get(\"ruuvitag_0_name\") || \"RuuviTag 1\";\n        break;\n    case 8:\n        label = global.get(\"ruuvitag_1_name\") || \"RuuviTag 2\";\n        break;\n    case 9:\n        label = global.get(\"ruuvitag_2_name\") || \"RuuviTag 3\";\n        break;\n\n    // NTCs (10–13)\n    case 10:\n        label = global.get(\"NLevel1\") || \"NTC 1\";\n        break;\n    case 11:\n        label = global.get(\"NLevel2\") || \"NTC 2\";\n        break;\n    case 12:\n        label = global.get(\"NLevel3\") || \"NTC 3\";\n        break;\n    case 13:\n        label = global.get(\"NLevel4\") || \"NTC 4\";\n        break;\n\n    default:\n        label = \"Tempsensor\";\n        break;\n}\n\n// expose human-readable label in msg.context\nmsg.context = label;\n\n// Only send on change + only if autoterm2 is actually present\nconst current = global.get(\"heattempsensor_autoterm2\");\nconst autoterm2Enabled = global.get(\"usbport_autoterm2\") || null;\n\nif (current === id || autoterm2Enabled == null) {\n    return null;\n}\n\n// store new selection\nglobal.set(\"heattempsensor_autoterm2\", id);\n\nreturn msg;\n",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1120,
        "y": 2640,
        "wires": [
            [
                "8e60eb211ba64487",
                "3e4662433f6ea83c"
            ]
        ]
    },
    {
        "id": "691fc19f20cd8692",
        "type": "ui_toast",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "position": "top right",
        "displayTime": "3",
        "highlight": "",
        "sendall": false,
        "outputs": 0,
        "ok": "OK",
        "cancel": "",
        "raw": false,
        "className": "",
        "topic": "",
        "name": "",
        "x": 1452,
        "y": 2681,
        "wires": []
    },
    {
        "id": "8e60eb211ba64487",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "updated",
        "func": "msg.payload =\"Autoterm 2 sensor updated to \" + msg.context\ndelete msg.topic\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1280,
        "y": 2680,
        "wires": [
            [
                "691fc19f20cd8692"
            ]
        ]
    },
    {
        "id": "3e4662433f6ea83c",
        "type": "file",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "",
        "filename": "pekaway/heattempsensor_autoterm2",
        "filenameType": "str",
        "appendNewline": false,
        "createDir": true,
        "overwriteFile": "true",
        "encoding": "none",
        "x": 1370,
        "y": 2640,
        "wires": [
            []
        ]
    },
    {
        "id": "f293282ea9e39f06",
        "type": "file in",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "",
        "filename": "pekaway/heattempsensor_autoterm2",
        "filenameType": "str",
        "format": "utf8",
        "chunk": false,
        "sendError": false,
        "encoding": "none",
        "allProps": false,
        "x": 570,
        "y": 2640,
        "wires": [
            [
                "0283d7ad9fd38d63"
            ]
        ]
    },
    {
        "id": "0283d7ad9fd38d63",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "get names",
        "func": "// Build options for Autoterm2 tempsensor selection\nlet opts = {};\n\n// helper\nfunction addOption(label, id) {\n    if (label && id != null) {\n        opts[label] = id;\n    }\n}\n\n// ------------------------------------\n// 0: Same as Autoterm1\n// ------------------------------------\naddOption(\"Same as Autoterm1\", 0);\n\n// ------------------------------------\n// 1–4: DS18B20 temp sensors\n// ------------------------------------\naddOption(global.get(\"Ntemp1\") || \"Temp Sensor 1\", 1);\naddOption(global.get(\"Ntemp2\") || \"Temp Sensor 2\", 2);\naddOption(global.get(\"Ntemp3\") || \"Temp Sensor 3\", 3);\naddOption(global.get(\"Ntemp4\") || \"Temp Sensor 4\", 4);\n\n// ------------------------------------\n// 5–6: Dimmy temps (only if feature enabled)\n// ------------------------------------\nif (global.get(\"dimmytemp\") === true) {\n    addOption(global.get(\"Ndimmytemp1\") || \"Dimmy Temp 1\", 5);\n    addOption(global.get(\"Ndimmytemp2\") || \"Dimmy Temp 2\", 6);\n}\n\n// ------------------------------------\n// 7–9: RuuviTags (only if feature enabled & data exists)\n// ------------------------------------\nif (global.get(\"ruuvitags\") === true) {\n    const rt0 = global.get(\"ruuvitag_0\");\n    const rt1 = global.get(\"ruuvitag_1\");\n    const rt2 = global.get(\"ruuvitag_2\");\n\n    if (rt0) {\n        addOption(global.get(\"ruuvitag_0_name\") || \"RuuviTag 1\", 7);\n    }\n    if (rt1) {\n        addOption(global.get(\"ruuvitag_1_name\") || \"RuuviTag 2\", 8);\n    }\n    if (rt2) {\n        addOption(global.get(\"ruuvitag_2_name\") || \"RuuviTag 3\", 9);\n    }\n}\n\n// ------------------------------------\n// 10–13: NTCs (only if active in ntcOverwrites)\n// ------------------------------------\nconst overwrites = global.get(\"ntcOverwrites\") || {};\n\nif (overwrites.ntc1 === true) {\n    addOption(global.get(\"NLevel1\") || \"NTC 1\", 10);\n}\nif (overwrites.ntc2 === true) {\n    addOption(global.get(\"NLevel2\") || \"NTC 2\", 11);\n}\nif (overwrites.ntc3 === true) {\n    addOption(global.get(\"NLevel3\") || \"NTC 3\", 12);\n}\nif (overwrites.ntc4 === true) {\n    addOption(global.get(\"NLevel4\") || \"NTC 4\", 13);\n}\n\n// ui_dropdown expects an array with one object\nmsg.options = [opts];\n\n// keep the existing behavior: cast payload to Number\nmsg.payload = Number(msg.payload);\n\nreturn msg;\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 810,
        "y": 2640,
        "wires": [
            [
                "484f4295724356ec"
            ]
        ]
    },
    {
        "id": "b7da8b947bc45c36",
        "type": "ui_text",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "group": "515f29cdb93516fd",
        "order": 18,
        "width": 0,
        "height": 0,
        "name": "",
        "label": "<u>Mode & Temp sensor:",
        "format": "",
        "layout": "col-center",
        "className": "",
        "style": false,
        "font": "",
        "fontSize": 16,
        "color": "#000000",
        "x": 530,
        "y": 2600,
        "wires": []
    },
    {
        "id": "5035d35ad5ef565d",
        "type": "ui_dropdown",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "Mode",
        "label": "",
        "tooltip": "",
        "place": "Mode",
        "group": "515f29cdb93516fd",
        "order": 19,
        "width": "3",
        "height": "1",
        "passthru": true,
        "multiple": false,
        "options": [
            {
                "label": "Mirrored Mode",
                "value": "parallel",
                "type": "str"
            },
            {
                "label": "Individual Mode",
                "value": "individual",
                "type": "str"
            }
        ],
        "payload": "",
        "topic": "topic",
        "topicType": "msg",
        "className": "",
        "x": 790,
        "y": 2720,
        "wires": [
            [
                "7c8d771865836729"
            ]
        ]
    },
    {
        "id": "09da66e7f6d79d40",
        "type": "file in",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "",
        "filename": "pekaway/autoterm2_mode",
        "filenameType": "str",
        "format": "utf8",
        "chunk": false,
        "sendError": false,
        "encoding": "none",
        "allProps": false,
        "x": 540,
        "y": 2720,
        "wires": [
            [
                "5035d35ad5ef565d"
            ]
        ]
    },
    {
        "id": "e814b275717f0b5b",
        "type": "file",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "",
        "filename": "pekaway/autoterm2_mode",
        "filenameType": "str",
        "appendNewline": false,
        "createDir": true,
        "overwriteFile": "true",
        "encoding": "none",
        "x": 1340,
        "y": 2720,
        "wires": [
            []
        ]
    },
    {
        "id": "7c8d771865836729",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "set global var & fade to grey",
        "func": "let stateBefore = global.get(\"autoterm2_mode\") || false\nlet parallel = msg.payload == \"parallel\" ? true : false\nglobal.set(\"autoterm2_mode\", parallel)\nmsg.background = parallel == true ? \"transparent\" : \"\"\nmsg.fontcolor = parallel == true ? \"grey\" : \"\"\nif (stateBefore == true && parallel == false) {\n    global.set(\"HeaterToggle_autoterm2\", global.get(\"HeaterToggle_autoterm1\"))\n}\nmsg.change = \"background\"\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1020,
        "y": 2720,
        "wires": [
            [
                "e814b275717f0b5b",
                "1e6cab4a1dcf0b81",
                "c64c0da0ce9bde09",
                "0471b3d1c34a252f",
                "0934a5c6a76be1a8"
            ]
        ]
    },
    {
        "id": "e7b1551b5bec695b",
        "type": "delay",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "0.5s",
        "pauseType": "delay",
        "timeout": "0.5",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 530,
        "y": 440,
        "wires": [
            [
                "7805c30b88c02cca"
            ]
        ]
    },
    {
        "id": "be5f17d1f0080e0e",
        "type": "delay",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "",
        "pauseType": "delay",
        "timeout": "1",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 620,
        "y": 360,
        "wires": [
            [
                "5cf5504a9e98cac1"
            ]
        ]
    },
    {
        "id": "ba59632bf01d8d4a",
        "type": "ui_time_scheduler",
        "z": "60d59772.e5b728",
        "g": "63dd5420c407b743",
        "group": "e375eeeb4bc94f3e",
        "name": "",
        "startDay": "0",
        "refresh": 60,
        "devices": [
            "Heater timer"
        ],
        "singleOff": false,
        "onlySendChange": true,
        "customPayload": false,
        "eventMode": false,
        "eventOptions": [],
        "sendTopic": false,
        "lat": "",
        "lon": "",
        "customContextStore": "",
        "outputs": 2,
        "order": 2,
        "width": 0,
        "height": 0,
        "x": 2750,
        "y": 180,
        "wires": [
            [
                "f215fb8b70a91e89"
            ],
            [
                "391c9825ca6fe36e"
            ]
        ]
    },
    {
        "id": "9e70e22a49a978e9",
        "type": "switch",
        "z": "60d59772.e5b728",
        "g": "63dd5420c407b743",
        "name": "",
        "property": "payload",
        "propertyType": "msg",
        "rules": [
            {
                "t": "true"
            },
            {
                "t": "false"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 3110,
        "y": 180,
        "wires": [
            [
                "df986e6a5787d93e"
            ],
            [
                "d0e044ed2e915498",
                "0fc5e8b0fc31cba2"
            ]
        ]
    },
    {
        "id": "2fbb1298cb7fe4e4",
        "type": "file in",
        "z": "60d59772.e5b728",
        "g": "63dd5420c407b743",
        "name": "",
        "filename": "pekaway/savetimer_autoterm1",
        "filenameType": "str",
        "format": "utf8",
        "chunk": false,
        "sendError": false,
        "encoding": "none",
        "allProps": false,
        "x": 2530,
        "y": 180,
        "wires": [
            [
                "ba59632bf01d8d4a",
                "c746536029ca452d"
            ]
        ]
    },
    {
        "id": "f59532fe53c51719",
        "type": "inject",
        "z": "60d59772.e5b728",
        "g": "63dd5420c407b743",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 2170,
        "y": 180,
        "wires": [
            [
                "51e74ef86604a8d6"
            ]
        ]
    },
    {
        "id": "51e74ef86604a8d6",
        "type": "delay",
        "z": "60d59772.e5b728",
        "g": "63dd5420c407b743",
        "name": "7s",
        "pauseType": "delay",
        "timeout": "7",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 2330,
        "y": 180,
        "wires": [
            [
                "2fbb1298cb7fe4e4"
            ]
        ]
    },
    {
        "id": "773d9bfdbb55d26d",
        "type": "ui_switch",
        "z": "60d59772.e5b728",
        "g": "63dd5420c407b743",
        "name": "",
        "label": "Timer Off/On",
        "tooltip": "",
        "group": "e375eeeb4bc94f3e",
        "order": 1,
        "width": 0,
        "height": 0,
        "passthru": true,
        "decouple": "false",
        "topic": "",
        "topicType": "str",
        "style": "",
        "onvalue": "true",
        "onvalueType": "bool",
        "onicon": "",
        "oncolor": "",
        "offvalue": "false",
        "offvalueType": "bool",
        "officon": "",
        "offcolor": "",
        "animate": true,
        "className": "",
        "x": 2290,
        "y": 80,
        "wires": [
            [
                "45d0348ba75e6f45"
            ]
        ]
    },
    {
        "id": "45d0348ba75e6f45",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "63dd5420c407b743",
        "name": "save global",
        "func": "global.set(\"heattimeronoff_autoterm1\", msg.payload)\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 2450,
        "y": 80,
        "wires": [
            []
        ]
    },
    {
        "id": "391c9825ca6fe36e",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "63dd5420c407b743",
        "name": "check timer on/off",
        "func": "var check = global.get(\"heattimeronoff_autoterm1\");\nif(check === true) {\n    msg.topic = \"ui_scheduler\"\n    return msg;\n}\n",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 2950,
        "y": 180,
        "wires": [
            [
                "9e70e22a49a978e9"
            ]
        ]
    },
    {
        "id": "99e9ebc5018ae901",
        "type": "inject",
        "z": "60d59772.e5b728",
        "g": "63dd5420c407b743",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "false",
        "payloadType": "bool",
        "x": 2150,
        "y": 80,
        "wires": [
            [
                "773d9bfdbb55d26d"
            ]
        ]
    },
    {
        "id": "0fc5e8b0fc31cba2",
        "type": "delay",
        "z": "60d59772.e5b728",
        "g": "63dd5420c407b743",
        "name": "5m",
        "pauseType": "delay",
        "timeout": "5",
        "timeoutUnits": "minutes",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 3270,
        "y": 240,
        "wires": [
            [
                "b59b4091e7c63391"
            ]
        ]
    },
    {
        "id": "a96d4bf95593a9fc",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "63dd5420c407b743",
        "name": "Timer with connect relays",
        "info": "",
        "x": 2190,
        "y": 220,
        "wires": []
    },
    {
        "id": "f215fb8b70a91e89",
        "type": "file",
        "z": "60d59772.e5b728",
        "g": "63dd5420c407b743",
        "name": "",
        "filename": "pekaway/savetimer_autoterm1",
        "filenameType": "str",
        "appendNewline": true,
        "createDir": true,
        "overwriteFile": "true",
        "encoding": "none",
        "x": 2990,
        "y": 140,
        "wires": [
            [
                "de01e3e08fb2b8f4"
            ]
        ]
    },
    {
        "id": "d0e044ed2e915498",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "63dd5420c407b743",
        "name": "autoterm1 savetimer false",
        "mode": "link",
        "links": [
            "a4ec456aeab1f088"
        ],
        "x": 3235,
        "y": 200,
        "wires": []
    },
    {
        "id": "df986e6a5787d93e",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "63dd5420c407b743",
        "name": "autoterm1 savetimer true",
        "mode": "link",
        "links": [
            "d3ae57a14d16dd42"
        ],
        "x": 3235,
        "y": 160,
        "wires": []
    },
    {
        "id": "b59b4091e7c63391",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "63dd5420c407b743",
        "name": "autoterm1 savetimer false",
        "mode": "link",
        "links": [
            "a4ec456aeab1f088"
        ],
        "x": 3365,
        "y": 240,
        "wires": []
    },
    {
        "id": "c64857dd22909bbe",
        "type": "ui_time_scheduler",
        "z": "60d59772.e5b728",
        "g": "45190ef2a22a605b",
        "group": "ce6b1d202f3d0580",
        "name": "",
        "startDay": "0",
        "refresh": 60,
        "devices": [
            "Heater timer"
        ],
        "singleOff": false,
        "onlySendChange": true,
        "customPayload": false,
        "eventMode": false,
        "eventOptions": [],
        "sendTopic": false,
        "lat": "",
        "lon": "",
        "customContextStore": "",
        "outputs": 2,
        "order": 2,
        "width": 0,
        "height": 0,
        "x": 2750,
        "y": 1600,
        "wires": [
            [
                "3d04165bcf52b546"
            ],
            [
                "bdefae9ccda6d046"
            ]
        ]
    },
    {
        "id": "9c82e4ef3d7bb1bc",
        "type": "switch",
        "z": "60d59772.e5b728",
        "g": "45190ef2a22a605b",
        "name": "",
        "property": "payload",
        "propertyType": "msg",
        "rules": [
            {
                "t": "true"
            },
            {
                "t": "false"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 3110,
        "y": 1600,
        "wires": [
            [
                "1118365a2f4915bf"
            ],
            [
                "363f534a6a534d11",
                "cc1ee79f625c655d"
            ]
        ]
    },
    {
        "id": "29daf43518bb70e5",
        "type": "file in",
        "z": "60d59772.e5b728",
        "g": "45190ef2a22a605b",
        "name": "",
        "filename": "pekaway/savetimer_autoterm2",
        "filenameType": "str",
        "format": "utf8",
        "chunk": false,
        "sendError": false,
        "encoding": "none",
        "allProps": false,
        "x": 2530,
        "y": 1600,
        "wires": [
            [
                "c64857dd22909bbe",
                "0eee798b1addbf8a"
            ]
        ]
    },
    {
        "id": "2e260934bf2f0dbd",
        "type": "inject",
        "z": "60d59772.e5b728",
        "g": "45190ef2a22a605b",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 2170,
        "y": 1600,
        "wires": [
            [
                "3e1a9b5fd994eac7"
            ]
        ]
    },
    {
        "id": "3e1a9b5fd994eac7",
        "type": "delay",
        "z": "60d59772.e5b728",
        "g": "45190ef2a22a605b",
        "name": "7s",
        "pauseType": "delay",
        "timeout": "7",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 2310,
        "y": 1600,
        "wires": [
            [
                "29daf43518bb70e5"
            ]
        ]
    },
    {
        "id": "a2c62f8cc4cf44dd",
        "type": "ui_switch",
        "z": "60d59772.e5b728",
        "g": "45190ef2a22a605b",
        "name": "",
        "label": "Timer Off/On",
        "tooltip": "",
        "group": "ce6b1d202f3d0580",
        "order": 1,
        "width": 0,
        "height": 0,
        "passthru": true,
        "decouple": "false",
        "topic": "",
        "topicType": "str",
        "style": "",
        "onvalue": "true",
        "onvalueType": "bool",
        "onicon": "",
        "oncolor": "",
        "offvalue": "false",
        "offvalueType": "bool",
        "officon": "",
        "offcolor": "",
        "animate": true,
        "className": "",
        "x": 2290,
        "y": 1500,
        "wires": [
            [
                "c67d15761a7a0109"
            ]
        ]
    },
    {
        "id": "c67d15761a7a0109",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "45190ef2a22a605b",
        "name": "save global",
        "func": "global.set(\"heattimeronoff_autoterm2\", msg.payload)\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 2450,
        "y": 1500,
        "wires": [
            []
        ]
    },
    {
        "id": "bdefae9ccda6d046",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "45190ef2a22a605b",
        "name": "check timer on/off",
        "func": "var check = global.get(\"heattimeronoff_autoterm2\");\nif(check === true) {\n    msg.topic = \"ui_scheduler\"\n    return msg;\n}\n",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 2950,
        "y": 1600,
        "wires": [
            [
                "9c82e4ef3d7bb1bc"
            ]
        ]
    },
    {
        "id": "6777db2954efb933",
        "type": "inject",
        "z": "60d59772.e5b728",
        "g": "45190ef2a22a605b",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "false",
        "payloadType": "bool",
        "x": 2150,
        "y": 1500,
        "wires": [
            [
                "a2c62f8cc4cf44dd"
            ]
        ]
    },
    {
        "id": "cc1ee79f625c655d",
        "type": "delay",
        "z": "60d59772.e5b728",
        "g": "45190ef2a22a605b",
        "name": "5m",
        "pauseType": "delay",
        "timeout": "5",
        "timeoutUnits": "minutes",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 3270,
        "y": 1660,
        "wires": [
            [
                "87361b73a8a8a708"
            ]
        ]
    },
    {
        "id": "584daee584c89851",
        "type": "comment",
        "z": "60d59772.e5b728",
        "g": "45190ef2a22a605b",
        "name": "Timer with connect relays",
        "info": "",
        "x": 2190,
        "y": 1640,
        "wires": []
    },
    {
        "id": "3d04165bcf52b546",
        "type": "file",
        "z": "60d59772.e5b728",
        "g": "45190ef2a22a605b",
        "name": "",
        "filename": "pekaway/savetimer_autoterm2",
        "filenameType": "str",
        "appendNewline": true,
        "createDir": true,
        "overwriteFile": "true",
        "encoding": "none",
        "x": 2990,
        "y": 1560,
        "wires": [
            [
                "223294cefd2aeab1"
            ]
        ]
    },
    {
        "id": "363f534a6a534d11",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "45190ef2a22a605b",
        "name": "autoterm1 savetimer false",
        "mode": "link",
        "links": [
            "20e60978f3931872"
        ],
        "x": 3235,
        "y": 1620,
        "wires": []
    },
    {
        "id": "1118365a2f4915bf",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "45190ef2a22a605b",
        "name": "autoterm1 savetimer true",
        "mode": "link",
        "links": [
            "1a8990ee345dec1e"
        ],
        "x": 3235,
        "y": 1580,
        "wires": []
    },
    {
        "id": "87361b73a8a8a708",
        "type": "link out",
        "z": "60d59772.e5b728",
        "g": "45190ef2a22a605b",
        "name": "autoterm1 savetimer false",
        "mode": "link",
        "links": [
            "20e60978f3931872"
        ],
        "x": 3365,
        "y": 1660,
        "wires": []
    },
    {
        "id": "223294cefd2aeab1",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "45190ef2a22a605b",
        "name": "compress timers",
        "func": "const zlib = global.get('zlib');\n\n// Parse the original payload JSON\nlet originalJson = JSON.parse(msg.payload);\n\n// Transform JSON for compactness\nlet compactJson = {\n    t: originalJson.timers.map(timer => [\n        timer.starttime,  // s\n        timer.days,       // d\n        timer.output,     // o\n        timer.endtime     // e\n    ])\n    // Omit settings if empty\n};\n\n// Convert compact JSON to a string\nlet jsonString = JSON.stringify(compactJson);\n\n// Set the uncompressed data in global variable\nglobal.set(\"savetimer_autoterm2\", compactJson);\n\n// Compress the JSON string\nzlib.gzip(jsonString, (err, buffer) => {\n    if (!err) {\n        // If compression is successful, set compressed data in global variable\n        global.set(\"savetimer_autoterm2_compressed\", buffer);\n        msg.payload = buffer;  // Optionally set msg.payload to compressed buffer if needed\n    } else {\n        node.error(\"Compression failed: \" + err);\n        msg.payload = 0;  // Set payload to 0 in case of compression error\n    }\n});\n\nreturn msg;\n",
        "outputs": 0,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 3300,
        "y": 1540,
        "wires": []
    },
    {
        "id": "de01e3e08fb2b8f4",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "63dd5420c407b743",
        "name": "compress timers",
        "func": "const zlib = global.get('zlib');\n\n// Parse the original payload JSON\nlet originalJson = JSON.parse(msg.payload);\n\n// Transform JSON for compactness\nlet compactJson = {\n    t: originalJson.timers.map(timer => [\n        timer.starttime,  // s\n        timer.days,       // d\n        timer.output,     // o\n        timer.endtime     // e\n    ])\n    // Omit settings if empty\n};\n\n// Convert compact JSON to a string\nlet jsonString = JSON.stringify(compactJson);\n\n// Set the uncompressed data in global variable\nglobal.set(\"savetimer_autoterm1\", compactJson);\n\n// Compress the JSON string\nzlib.gzip(jsonString, (err, buffer) => {\n    if (!err) {\n        // If compression is successful, set compressed data in global variable\n        global.set(\"savetimer_autoterm1_compressed\", buffer);\n        msg.payload = buffer;  // Optionally set msg.payload to compressed buffer if needed\n    } else {\n        node.error(\"Compression failed: \" + err);\n        msg.payload = 0;  // Set payload to 0 in case of compression error\n    }\n});\n\nreturn msg;\n",
        "outputs": 0,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 3300,
        "y": 120,
        "wires": []
    },
    {
        "id": "0eee798b1addbf8a",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "45190ef2a22a605b",
        "name": "save global var",
        "func": "global.set(\"savetimer_autoterm2\", JSON.parse(msg.payload))\nconst zlib = global.get('zlib');\n\n// Parse the original payload JSON\nlet originalJson = JSON.parse(msg.payload);\n\n// Transform JSON for compactness\nlet compactJson = {\n    t: originalJson.timers.map(timer => [\n        timer.starttime,  // s\n        timer.days,       // d\n        timer.output,     // o\n        timer.endtime     // e\n    ])\n    // Omit settings if empty\n};\n\n// Convert compact JSON to a string\nlet jsonString = JSON.stringify(compactJson);\n\n// Set the uncompressed data in global variable\nglobal.set(\"savetimer_autoterm2\", compactJson);\n\n// Do not compress if no timers are set\nif (compactJson.t.length == 0) {\n    return msg\n}\n\n// Compress the JSON string\nzlib.gzip(jsonString, (err, buffer) => {\n    if (!err) {\n        // If compression is successful, set compressed data in global variable\n        global.set(\"savetimer_autoterm2_compressed\", buffer);\n        msg.payload = buffer;  // Optionally set msg.payload to compressed buffer if needed\n    } else {\n        node.error(\"Compression failed: \" + err);\n        msg.payload = 0;  // Set payload to 0 in case of compression error\n    }\n});\n\nreturn msg;\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 2760,
        "y": 1560,
        "wires": [
            []
        ]
    },
    {
        "id": "c746536029ca452d",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "63dd5420c407b743",
        "name": "save global var",
        "func": "global.set(\"savetimer_autoterm1\", JSON.parse(msg.payload))\nconst zlib = global.get('zlib');\n\n// Parse the original payload JSON\nlet originalJson = JSON.parse(msg.payload);\n\n// Transform JSON for compactness\nlet compactJson = {\n    t: originalJson.timers.map(timer => [\n        timer.starttime,  // s\n        timer.days,       // d\n        timer.output,     // o\n        timer.endtime     // e\n    ])\n    // Omit settings if empty\n};\n\n// Convert compact JSON to a string\nlet jsonString = JSON.stringify(compactJson);\n\n// Set the uncompressed data in global variable\nglobal.set(\"savetimer_autoterm1\", compactJson);\n\n// Do not compress if no timers are set\nif (compactJson.t.length == 0) {\n    return msg\n}\n\n// Compress the JSON string\nzlib.gzip(jsonString, (err, buffer) => {\n    if (!err) {\n        // If compression is successful, set compressed data in global variable\n        global.set(\"savetimer_autoterm1_compressed\", buffer);\n        msg.payload = buffer;  // Optionally set msg.payload to compressed buffer if needed\n    } else {\n        node.error(\"Compression failed: \" + err);\n        msg.payload = 0;  // Set payload to 0 in case of compression error\n    }\n});\n\nreturn msg;\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 2760,
        "y": 140,
        "wires": [
            []
        ]
    },
    {
        "id": "7cc256d744493e75",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "autoterm2 set sensor",
        "links": [
            "8486eb65268870dd"
        ],
        "x": 705,
        "y": 2680,
        "wires": [
            [
                "0283d7ad9fd38d63"
            ]
        ]
    },
    {
        "id": "f54a4281fcefc938",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "autoterm2 set mode",
        "links": [
            "13af0b07673025a4",
            "d70daf859a1e8f21"
        ],
        "x": 695,
        "y": 2760,
        "wires": [
            [
                "5035d35ad5ef565d"
            ]
        ]
    },
    {
        "id": "fc6c4c72faa20c0e",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "63dd5420c407b743",
        "name": "set timers autoterm1",
        "links": [
            "77c64560dea67538"
        ],
        "x": 2645,
        "y": 220,
        "wires": [
            [
                "ba59632bf01d8d4a"
            ]
        ]
    },
    {
        "id": "a0aa3292c3439feb",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "45190ef2a22a605b",
        "name": "set timers autoterm1",
        "links": [
            "e3b7717b3f02a3ba"
        ],
        "x": 2645,
        "y": 1640,
        "wires": [
            [
                "c64857dd22909bbe"
            ]
        ]
    },
    {
        "id": "7e86a6b3c0df19c7",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "63dd5420c407b743",
        "name": "set timerActive autoterm1",
        "links": [
            "50911e8c1585bf9f"
        ],
        "x": 2185,
        "y": 120,
        "wires": [
            [
                "773d9bfdbb55d26d"
            ]
        ]
    },
    {
        "id": "b4ee31e0ade8dfd4",
        "type": "link in",
        "z": "60d59772.e5b728",
        "g": "45190ef2a22a605b",
        "name": "set timerActive autoterm2",
        "links": [
            "b88c98739064a375"
        ],
        "x": 2185,
        "y": 1540,
        "wires": [
            [
                "a2c62f8cc4cf44dd"
            ]
        ]
    },
    {
        "id": "a31f71ad95945e05",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "check autoterm2",
        "func": "if (global.get(\"usbport_autoterm2\") != null && global.get(\"usbport_autoterm2\") != undefined )\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 320,
        "y": 2460,
        "wires": [
            [
                "1f6ecd32d9cc8d27"
            ]
        ]
    },
    {
        "id": "bf0390aa851bab6f",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "check autoterm1",
        "func": "if (global.get(\"usbport_autoterm1\") != null && global.get(\"usbport_autoterm1\") != undefined )\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 320,
        "y": 820,
        "wires": [
            [
                "b8983a59fc585658"
            ]
        ]
    },
    {
        "id": "eb20e2f9d18f3fc8",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "0277bccc0f7ac04b",
        "name": "heater temp",
        "func": "msg.payload = Math.round(msg.payload.flameTempK-272);\nglobal.set(\"heattemp_autoterm1\",msg.payload);\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1250,
        "y": 1540,
        "wires": [
            [
                "8ac3efa188eb7f30"
            ]
        ]
    },
    {
        "id": "d5daa550215c84c7",
        "type": "function",
        "z": "60d59772.e5b728",
        "g": "fd0a1dcd80269338",
        "name": "heater temp",
        "func": "msg.payload = Math.round(msg.payload.flameTempK-272);\nglobal.set(\"heattemp_autoterm2\",msg.payload);\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1250,
        "y": 3260,
        "wires": [
            [
                "86392067b684886c"
            ]
        ]
    },
    {
        "id": "4373a7f49bda8706",
        "type": "ui_group",
        "name": "Autoterm",
        "tab": "5007f157b6c708d0",
        "order": 4,
        "disp": true,
        "width": "6",
        "collapse": true,
        "className": ""
    },
    {
        "id": "515f29cdb93516fd",
        "type": "ui_group",
        "name": "Autoterm 2",
        "tab": "5007f157b6c708d0",
        "order": 6,
        "disp": true,
        "width": "6",
        "collapse": true,
        "className": ""
    },
    {
        "id": "e375eeeb4bc94f3e",
        "type": "ui_group",
        "name": "Timer Autoterm 1",
        "tab": "5007f157b6c708d0",
        "order": 5,
        "disp": true,
        "width": "6",
        "collapse": true,
        "className": ""
    },
    {
        "id": "ce6b1d202f3d0580",
        "type": "ui_group",
        "name": "Timer Autoterm 2",
        "tab": "5007f157b6c708d0",
        "order": 7,
        "disp": true,
        "width": "6",
        "collapse": true,
        "className": ""
    },
    {
        "id": "5007f157b6c708d0",
        "type": "ui_tab",
        "name": "Heater",
        "icon": "mi-whatshot",
        "order": 3,
        "disabled": false,
        "hidden": false
    }
]