[
    {
        "id": "6eda76ddd54bb83d",
        "type": "tab",
        "label": "Flow 1",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "3e8d1dd2863b1835",
        "type": "ui_tab",
        "name": "RDM",
        "icon": "dashboard",
        "order": 2,
        "disabled": false,
        "hidden": false
    },
    {
        "id": "98b662b36bdd06d8",
        "type": "ui_base",
        "theme": {
            "name": "theme-light",
            "lightTheme": {
                "default": "#0094CE",
                "baseColor": "#0094CE",
                "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif",
                "edited": true,
                "reset": false
            },
            "darkTheme": {
                "default": "#097479",
                "baseColor": "#097479",
                "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif",
                "edited": false
            },
            "customTheme": {
                "name": "Untitled Theme 1",
                "default": "#4B7930",
                "baseColor": "#4B7930",
                "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif"
            },
            "themeState": {
                "base-color": {
                    "default": "#0094CE",
                    "value": "#0094CE",
                    "edited": false
                },
                "page-titlebar-backgroundColor": {
                    "value": "#0094CE",
                    "edited": false
                },
                "page-backgroundColor": {
                    "value": "#fafafa",
                    "edited": false
                },
                "page-sidebar-backgroundColor": {
                    "value": "#ffffff",
                    "edited": false
                },
                "group-textColor": {
                    "value": "#1bbfff",
                    "edited": false
                },
                "group-borderColor": {
                    "value": "#ffffff",
                    "edited": false
                },
                "group-backgroundColor": {
                    "value": "#ffffff",
                    "edited": false
                },
                "widget-textColor": {
                    "value": "#111111",
                    "edited": false
                },
                "widget-backgroundColor": {
                    "value": "#0094ce",
                    "edited": false
                },
                "widget-borderColor": {
                    "value": "#ffffff",
                    "edited": false
                },
                "base-font": {
                    "value": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif"
                }
            },
            "angularTheme": {
                "primary": "indigo",
                "accents": "blue",
                "warn": "red",
                "background": "grey",
                "palette": "light"
            }
        },
        "site": {
            "name": "Node-RED Dashboard",
            "hideToolbar": "false",
            "allowSwipe": "false",
            "lockMenu": "false",
            "allowTempTheme": "true",
            "dateFormat": "DD/MM/YYYY",
            "sizes": {
                "sx": 48,
                "sy": 48,
                "gx": 6,
                "gy": 6,
                "cx": 6,
                "cy": 6,
                "px": 0,
                "py": 0
            }
        }
    },
    {
        "id": "c44a492db6e067ea",
        "type": "ui_group",
        "name": "EDID",
        "tab": "3e8d1dd2863b1835",
        "order": 1,
        "disp": true,
        "width": "6",
        "collapse": false,
        "className": ""
    },
    {
        "id": "fdc03d2bcc088a70",
        "type": "ui_tab",
        "name": "Monitoring",
        "icon": "dashboard",
        "order": 1,
        "disabled": false,
        "hidden": false
    },
    {
        "id": "2a0da9646edd80ab",
        "type": "ui_group",
        "name": "Default",
        "tab": "fdc03d2bcc088a70",
        "order": 1,
        "disp": true,
        "width": "6",
        "collapse": false,
        "className": ""
    },
    {
        "id": "7e4c65d6.0419cc",
        "type": "ui_group",
        "name": "Default",
        "tab": "",
        "order": 1,
        "disp": true,
        "width": "12",
        "collapse": false
    },
    {
        "id": "f78b45f4d75d0c20",
        "type": "ui_group",
        "name": "MCU",
        "tab": "3e8d1dd2863b1835",
        "order": 2,
        "disp": true,
        "width": "6",
        "collapse": false,
        "className": ""
    },
    {
        "id": "22c5af973bab020e",
        "type": "ui_group",
        "name": "Schedule",
        "tab": "3e8d1dd2863b1835",
        "order": 3,
        "disp": true,
        "width": "6",
        "collapse": false,
        "className": ""
    },
    {
        "id": "ae5ac26d780aecba",
        "type": "ui_group",
        "name": "Devices",
        "tab": "3e8d1dd2863b1835",
        "order": 4,
        "disp": true,
        "width": "6",
        "collapse": false,
        "className": ""
    },
    {
        "id": "4510203f.79061",
        "type": "ui_group",
        "name": "dialog",
        "tab": "3e8d1dd2863b1835",
        "order": 5,
        "disp": false,
        "width": "1",
        "collapse": false,
        "className": ""
    },
    {
        "id": "c9307d81dd3ec5d6",
        "type": "ui_group",
        "name": "Group 1",
        "tab": "",
        "order": 1,
        "disp": true,
        "width": 6
    },
    {
        "id": "9ceeb9d18bc9ed05",
        "type": "ui_group",
        "name": "dialog2",
        "tab": "3e8d1dd2863b1835",
        "order": 6,
        "disp": false,
        "width": "8",
        "collapse": false,
        "className": ""
    },
    {
        "id": "8f574330195a2854",
        "type": "function",
        "z": "6eda76ddd54bb83d",
        "name": "monitor_input_func",
        "func": "const cyrb53 = function(str, seed = 0) {\n    let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;\n    for (let i = 0, ch; i < str.length; i++) {\n        ch = str.charCodeAt(i);\n        h1 = Math.imul(h1 ^ ch, 2654435761);\n        h2 = Math.imul(h2 ^ ch, 1597334677);\n    }\n    h1 = Math.imul(h1 ^ (h1>>>16), 2246822507) ^ Math.imul(h2 ^ (h2>>>13), 3266489909);\n    h2 = Math.imul(h2 ^ (h2>>>16), 2246822507) ^ Math.imul(h1 ^ (h1>>>13), 3266489909);\n    return 4294967296 * (2097151 & h2) + (h1>>>0);\n};\n\n\nvar g_init = global.get(\"monitor_init\");\nvar g_hash = global.get(\"monitor_hash\");\nvar hash = cyrb53(JSON.stringify(msg.payload), 1);\n\n\nif ((g_init < 1) || (g_hash != hash)) {\n    if (g_init < 1) {\n        global.set(\"monitor_init\", 1);\n    }\n    if (g_hash != hash) {\n        global.set(\"monitor_hash\", hash);\n    }\n    return msg;\n}",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 730,
        "y": 580,
        "wires": [
            [
                "79eff73203564295"
            ]
        ]
    },
    {
        "id": "a2ea9ed3e93fba90",
        "type": "ui_list",
        "z": "6eda76ddd54bb83d",
        "group": "c44a492db6e067ea",
        "name": "edid_list",
        "order": 3,
        "width": "5",
        "height": "7",
        "lineType": "one",
        "actionType": "check",
        "allowHTML": false,
        "outputs": 1,
        "topic": "",
        "x": 940,
        "y": 800,
        "wires": [
            [
                "f20d6690aca9a19f"
            ]
        ]
    },
    {
        "id": "1e8c5c40e246a559",
        "type": "ui_timeline",
        "z": "6eda76ddd54bb83d",
        "name": "timeline",
        "label": "",
        "group": "22c5af973bab020e",
        "order": 3,
        "showText": false,
        "textPadding": "1",
        "responsive": true,
        "backgroundColorRepeat": true,
        "width": 0,
        "height": 0,
        "bgColor1": "rgb(255,255,255, 0.2)",
        "bgColor2": "rgb(205,203,205, 0.2)",
        "colorCodes": [
            "rgb(66, 133, 244)",
            "rgb(128,0,0)",
            "rgb(15, 157, 88)",
            "rgb(0,128,0)",
            "rgb(158, 157, 36)",
            "rgb(240, 98, 146)",
            "rgb(92, 107, 192)",
            "rgb(255,0,255)",
            "rgb(219, 68, 55)",
            "rgb(244, 180, 0)",
            "rgb(128,128,0)",
            "rgb(171, 71, 188)",
            "rgb(0, 172, 193)",
            "rgb(255, 112, 67)",
            "rgb(192,192,192)",
            "rgb(128,0,128)",
            "rgb(0,128,128)",
            "rgb(128,128,128)",
            "rgb(0,0,128)",
            "rgb(77, 77, 77)"
        ],
        "x": 1100,
        "y": 1380,
        "wires": [
            []
        ]
    },
    {
        "id": "7f4aeb5a178cb809",
        "type": "ui_list",
        "z": "6eda76ddd54bb83d",
        "group": "ae5ac26d780aecba",
        "name": "device_list",
        "order": 3,
        "width": "5",
        "height": "7",
        "lineType": "one",
        "actionType": "check",
        "allowHTML": false,
        "outputs": 1,
        "topic": "",
        "x": 950,
        "y": 1780,
        "wires": [
            [
                "63b3ce39908ae23c"
            ]
        ]
    },
    {
        "id": "2317e94f40d3e412",
        "type": "comment",
        "z": "6eda76ddd54bb83d",
        "name": "RDM Tab --> EDID Group",
        "info": "",
        "x": 750,
        "y": 680,
        "wires": []
    },
    {
        "id": "820ca77f0adc50c1",
        "type": "comment",
        "z": "6eda76ddd54bb83d",
        "name": "RDM Tab --> MCU Group",
        "info": "",
        "x": 750,
        "y": 940,
        "wires": []
    },
    {
        "id": "84159bb44cbe55f0",
        "type": "comment",
        "z": "6eda76ddd54bb83d",
        "name": "RDM Tab --> Schedule Group",
        "info": "",
        "x": 760,
        "y": 1280,
        "wires": []
    },
    {
        "id": "27aa103857de17cc",
        "type": "comment",
        "z": "6eda76ddd54bb83d",
        "name": "RDM Tab --> Devices Group",
        "info": "",
        "x": 760,
        "y": 1700,
        "wires": []
    },
    {
        "id": "16ea0c0fd98b691b",
        "type": "comment",
        "z": "6eda76ddd54bb83d",
        "name": "Monitoring Tab",
        "info": "",
        "x": 720,
        "y": 480,
        "wires": []
    },
    {
        "id": "24e64ce416d5eafe",
        "type": "ui_ui_control",
        "z": "6eda76ddd54bb83d",
        "name": "tab_detect",
        "events": "all",
        "x": 90,
        "y": 480,
        "wires": [
            [
                "e9132142fc0ef6d2"
            ]
        ]
    },
    {
        "id": "2b0c933a98cc2c74",
        "type": "controltimer",
        "z": "6eda76ddd54bb83d",
        "name": "monitor_timer",
        "timerType": "loop",
        "timerDurationUnit": "second",
        "timerDurationType": "num",
        "timerDuration": 1,
        "timerLoopTimeoutUnit": "second",
        "timerLoopTimeoutType": "num",
        "timerLoopTimeout": 0,
        "loopTimeoutMessageType": "str",
        "loopTimeoutMessage": "LOOP_TIMEOUT",
        "timerMaxLoopIterationsType": "num",
        "timerMaxLoopIterations": 0,
        "loopMaxIterationsMessageType": "str",
        "loopMaxIterationsMessage": "MAX_LOOP_ITERATIONS",
        "isConsecutiveStartActionTimerResetAllowed": false,
        "isRunningTimerProgressVisible": false,
        "outputReceivedMessageOnTimerTrigger": true,
        "outputReceivedMessageOnTimerHalt": true,
        "startTimerOnReceivalOfUnknownMessage": false,
        "resetTimerOnReceivalOfUnknownMessage": false,
        "isDebugModeEnabled": false,
        "timerTriggeredMessageType": "str",
        "timerTriggeredMessage": "TIMER_TRIGGERED",
        "timerHaltedMessageType": "str",
        "timerHaltedMessage": "TIMER_HALTED",
        "isStartActionEnabled": true,
        "isStopActionEnabled": true,
        "isResetActionEnabled": true,
        "isPauseActionEnabled": true,
        "isContinueActionEnabled": true,
        "actionPropertyNameType": "str",
        "actionPropertyName": "monitor",
        "startActionNameType": "str",
        "startActionName": "START",
        "stopActionNameType": "str",
        "stopActionName": "STOP",
        "resetActionNameType": "str",
        "resetActionName": "RESET",
        "pauseActionNameType": "str",
        "pauseActionName": "PAUSE",
        "continueActionNameType": "str",
        "continueActionName": "CONTINUE",
        "x": 500,
        "y": 480,
        "wires": [
            [
                "5e61a36eda8b4a99"
            ],
            []
        ]
    },
    {
        "id": "e9132142fc0ef6d2",
        "type": "function",
        "z": "6eda76ddd54bb83d",
        "name": "tab_func",
        "func": "if (msg.tab == 0) {\n    monitor = \"START\";\n    rdm = \"STOP\";\n    global.set(\"monitor_init\", 0);\n    global.set(\"monitor_hash\", 0);\n} else if (msg.tab == 1) {\n    monitor = \"STOP\";\n    rdm = \"START\";\n    global.set(\"edid_init\", 0);\n    global.set(\"edid_hash\", 0);\n    global.set(\"mcu_init\", 0);\n    global.set(\"mcu_hash\", 0);\n    global.set(\"schedule_init\", 0);\n    global.set(\"schedule_hash\", 0);\n    global.set(\"device_init\", 0);\n    global.set(\"device_hash\", 0);\n} else {\n    monitor = \"STOP\";\n    rdm = \"STOP\";\n}\nreturn {monitor: monitor, rdm: rdm};",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 260,
        "y": 480,
        "wires": [
            [
                "2b0c933a98cc2c74",
                "9cfb35ba1a8ca15f"
            ]
        ]
    },
    {
        "id": "9cfb35ba1a8ca15f",
        "type": "controltimer",
        "z": "6eda76ddd54bb83d",
        "name": "rdm_timer",
        "timerType": "loop",
        "timerDurationUnit": "second",
        "timerDurationType": "num",
        "timerDuration": 2,
        "timerLoopTimeoutUnit": "second",
        "timerLoopTimeoutType": "num",
        "timerLoopTimeout": 0,
        "loopTimeoutMessageType": "str",
        "loopTimeoutMessage": "LOOP_TIMEOUT",
        "timerMaxLoopIterationsType": "num",
        "timerMaxLoopIterations": 0,
        "loopMaxIterationsMessageType": "str",
        "loopMaxIterationsMessage": "MAX_LOOP_ITERATIONS",
        "isConsecutiveStartActionTimerResetAllowed": false,
        "isRunningTimerProgressVisible": false,
        "outputReceivedMessageOnTimerTrigger": true,
        "outputReceivedMessageOnTimerHalt": true,
        "startTimerOnReceivalOfUnknownMessage": false,
        "resetTimerOnReceivalOfUnknownMessage": false,
        "isDebugModeEnabled": false,
        "timerTriggeredMessageType": "str",
        "timerTriggeredMessage": "TIMER_TRIGGERED",
        "timerHaltedMessageType": "str",
        "timerHaltedMessage": "TIMER_HALTED",
        "isStartActionEnabled": true,
        "isStopActionEnabled": true,
        "isResetActionEnabled": true,
        "isPauseActionEnabled": true,
        "isContinueActionEnabled": true,
        "actionPropertyNameType": "str",
        "actionPropertyName": "rdm",
        "startActionNameType": "str",
        "startActionName": "START",
        "stopActionNameType": "str",
        "stopActionName": "STOP",
        "resetActionNameType": "str",
        "resetActionName": "RESET",
        "pauseActionNameType": "str",
        "pauseActionName": "PAUSE",
        "continueActionNameType": "str",
        "continueActionName": "CONTINUE",
        "x": 480,
        "y": 640,
        "wires": [
            [
                "be935622b91b8e80",
                "869a1dd2acf18357",
                "e2a0f7874179c0f8",
                "c0178408ce11cd9e"
            ],
            []
        ]
    },
    {
        "id": "6a12c9e182bbc34a",
        "type": "function",
        "z": "6eda76ddd54bb83d",
        "name": "edid_input_func",
        "func": "const cyrb53 = function(str, seed = 0) {\n    let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;\n    for (let i = 0, ch; i < str.length; i++) {\n        ch = str.charCodeAt(i);\n        h1 = Math.imul(h1 ^ ch, 2654435761);\n        h2 = Math.imul(h2 ^ ch, 1597334677);\n    }\n    h1 = Math.imul(h1 ^ (h1>>>16), 2246822507) ^ Math.imul(h2 ^ (h2>>>13), 3266489909);\n    h2 = Math.imul(h2 ^ (h2>>>16), 2246822507) ^ Math.imul(h1 ^ (h1>>>13), 3266489909);\n    return 4294967296 * (2097151 & h2) + (h1>>>0);\n};\n\n\nvar g_init = global.get(\"edid_init\");\nvar g_hash = global.get(\"edid_hash\");\nvar edid_status = msg.payload.Edid_Status\nvar hdmi_plugin_status = msg.payload.Hdmi_Plugin_Status\nvar hash = cyrb53(JSON.stringify(edid_status)+JSON.stringify(hdmi_plugin_status), 1);\nvar i;\n\nif ((g_init < 1) || (g_hash != hash)) {\n    var edid_payload = []\n    for (i = 0; i < hdmi_plugin_status.length; i++) {\n        var item = {\n            \"index\": i.toString(),\n            \"edid_status\": edid_status,\n            \"title\": \"HDMI\" + (i + 1).toString(),\n            \"icon\": \"/gray.jpg\",\n            \"isChecked\": edid_status[i]\n        }\n\n        if (hdmi_plugin_status[i]) {\n            item[\"icon\"] = \"/blue.jpg\"\n        }\n        edid_payload.push (item)\n    }\n\n    if (g_init < 1) {\n        global.set(\"edid_init\", 1);\n    }\n    if (g_hash != hash) {\n        global.set(\"edid_hash\", hash);\n    }\n    return {payload: edid_payload};\n}",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 720,
        "y": 800,
        "wires": [
            [
                "a2ea9ed3e93fba90"
            ]
        ]
    },
    {
        "id": "ffe0edaabaa06abe",
        "type": "function",
        "z": "6eda76ddd54bb83d",
        "name": "schedule_input_func",
        "func": "const cyrb53 = function(str, seed = 0) {\n    let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;\n    for (let i = 0, ch; i < str.length; i++) {\n        ch = str.charCodeAt(i);\n        h1 = Math.imul(h1 ^ ch, 2654435761);\n        h2 = Math.imul(h2 ^ ch, 1597334677);\n    }\n    h1 = Math.imul(h1 ^ (h1>>>16), 2246822507) ^ Math.imul(h2 ^ (h2>>>13), 3266489909);\n    h2 = Math.imul(h2 ^ (h2>>>16), 2246822507) ^ Math.imul(h1 ^ (h1>>>13), 3266489909);\n    return 4294967296 * (2097151 & h2) + (h1>>>0);\n};\n\nconst to_timestamp = function(str) {\n    var date = new Date();\n    var arr = str.split(':');\n    date.setHours(arr[0]);\n    date.setMinutes(arr[1]);\n    date.setSeconds(0);\n    return date.getTime();\n}\n\nconst labels = [\n    \"First\",\n    \"Second\",\n    \"Third\",\n    \"Forth\",\n    \"Fifth\",\n    \"Sixth\",\n    \"Seventh\"\n]\n\n\nvar g_init = global.get(\"schedule_init\");\nvar g_hash = global.get(\"schedule_hash\");\nvar g_json = global.get(\"json\");\nvar hash = cyrb53(JSON.stringify(msg.payload), 1);\n\nif (g_json && ((g_init < 1) || (g_hash != hash))) {\n    var timeline_msg = {};\n    var timeline_payload = [\n        [\n            \"Monday\",\n            0,\n            0\n        ],\n        [\n            \"Tuesday\",\n            0,\n            0\n        ],\n        [\n            \"Wednesday\",\n            0,\n            0\n        ],\n        [\n            \"Thursday\",\n            0,\n            0\n        ],\n        [\n            \"Friday\",\n            0,\n            0\n        ],\n        [\n            \"Saturday\",\n            0,\n            0\n        ],\n        [\n            \"Sunday\",\n            0,\n            0\n        ]\n    ]\n\n    if (g_init < 1) {\n        global.set(\"schedule_init\", 1);\n    }\n    if (g_hash != hash) {\n        global.set(\"schedule_hash\", hash);\n    }\n\n    if (!g_json.isEveryday) {\n        var schedule = [];\n        schedule.push({on: msg.payload.Sunday_On, off: msg.payload.Sunday_Off});\n        schedule.push({on: msg.payload.Monday_On, off: msg.payload.Monday_Off});\n        schedule.push({on: msg.payload.Tuesday_On, off: msg.payload.Tuesday_Off});\n        schedule.push({on: msg.payload.Wednesday_On, off: msg.payload.Wednesday_Off});\n        schedule.push({on: msg.payload.Thursday_On, off: msg.payload.Thursday_Off});\n        schedule.push({on: msg.payload.Friday_On, off: msg.payload.Friday_Off});\n        schedule.push({on: msg.payload.Saturday_On, off: msg.payload.Saturday_Off});\n        g_json.schedule = schedule;\n        if (g_json.schedule[0].on !== \"\") {\n            timeline_payload[0][1] = to_timestamp(g_json.schedule[0].on);\n        }\n        if (g_json.schedule[0].off !== \"\") {\n            timeline_payload[0][2] = to_timestamp(g_json.schedule[0].off);\n        }\n        if (g_json.schedule[1].on !== \"\") {\n            timeline_payload[1][1] = to_timestamp(g_json.schedule[1].on);\n        }\n        if (g_json.schedule[1].off !== \"\") {\n            timeline_payload[1][2] = to_timestamp(g_json.schedule[1].off);\n        }\n        if (g_json.schedule[2].on !== \"\") {\n            timeline_payload[2][1] = to_timestamp(g_json.schedule[2].on);\n        }\n        if (g_json.schedule[2].off !== \"\") {\n            timeline_payload[2][2] = to_timestamp(g_json.schedule[2].off);\n        }\n        if (g_json.schedule[3].on !== \"\") {\n            timeline_payload[3][1] = to_timestamp(g_json.schedule[3].on);\n        }\n        if (g_json.schedule[3].off !== \"\") {\n            timeline_payload[3][2] = to_timestamp(g_json.schedule[3].off);\n        }\n        if (g_json.schedule[4].on !== \"\") {\n            timeline_payload[4][1] = to_timestamp(g_json.schedule[4].on);\n        }\n        if (g_json.schedule[4].off !== \"\") {\n            timeline_payload[4][2] = to_timestamp(g_json.schedule[4].off);\n        }\n        if (g_json.schedule[5].on !== \"\") {\n            timeline_payload[5][1] = to_timestamp(g_json.schedule[5].on);\n        }\n        if (g_json.schedule[5].off !== \"\") {\n            timeline_payload[5][2] = to_timestamp(g_json.schedule[5].off);\n        }\n        if (g_json.schedule[6].on !== \"\") {\n            timeline_payload[6][1] = to_timestamp(g_json.schedule[6].on);\n        }\n        if (g_json.schedule[6].off !== \"\") {\n            timeline_payload[6][2] = to_timestamp(g_json.schedule[6].off);\n        }\n    } else {\n        var sch;\n        var i;\n        var j = 0;\n\n        for (i = 0; i < timeline_payload.length; i++) {\n            timeline_payload[i][0] = labels[i];\n        }\n\n        // search the closest off time, greater than current time\n        for (i = 0; i < g_json.schedule.length; i++) {\n            sch = g_json.schedule[i];\n            if (sch.on !== \"\" && sch.off !== \"\") {\n                timeline_payload[j][1] = to_timestamp(sch.on);\n                timeline_payload[j][2] = to_timestamp(sch.off);\n                j++;\n            }\n        }\n    }\n\n    return [{payload: timeline_payload}, {json: g_json}];\n}",
        "outputs": 2,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 740,
        "y": 1380,
        "wires": [
            [
                "e4a998efea1e761e"
            ],
            [
                "b4dc8a0a2624097e"
            ]
        ]
    },
    {
        "id": "0c3ce6877a3249e4",
        "type": "function",
        "z": "6eda76ddd54bb83d",
        "name": "mcu_input_func",
        "func": "const cyrb53 = function(str, seed = 0) {\n    let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;\n    for (let i = 0, ch; i < str.length; i++) {\n        ch = str.charCodeAt(i);\n        h1 = Math.imul(h1 ^ ch, 2654435761);\n        h2 = Math.imul(h2 ^ ch, 1597334677);\n    }\n    h1 = Math.imul(h1 ^ (h1>>>16), 2246822507) ^ Math.imul(h2 ^ (h2>>>13), 3266489909);\n    h2 = Math.imul(h2 ^ (h2>>>16), 2246822507) ^ Math.imul(h1 ^ (h1>>>13), 3266489909);\n    return 4294967296 * (2097151 & h2) + (h1>>>0);\n};\n\nvar g_init = global.get(\"mcu_init\");\nvar g_hash = global.get(\"mcu_hash\");\nvar hash = cyrb53(JSON.stringify(msg.payload), 1);\n\nif ((g_init < 1) || (g_hash != hash)) {\n    if (g_init < 1) {\n        global.set(\"mcu_init\", 1);\n    }\n    if (g_hash != hash) {\n        global.set(\"mcu_hash\", hash);\n    }\n    return msg;\n}",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 720,
        "y": 1080,
        "wires": [
            [
                "19e7dd6cd34d2408"
            ]
        ]
    },
    {
        "id": "7b2f639da5314526",
        "type": "function",
        "z": "6eda76ddd54bb83d",
        "name": "device_input_func",
        "func": "var g_init = global.get(\"device_init\");\nvar g_hash = global.get(\"device_hash\");\nvar usb_power_states = msg.payload.Usb_Power_States\nvar hash = 0;\nvar i;\n\nfor (i = 0; i < usb_power_states.length; i++) {\n    if (usb_power_states[i]) {\n        hash++;\n    }\n}\n\nif ((g_init < 1) || (g_hash != hash)) {\n    var device_payload = []\n    for (i = 0; i < usb_power_states.length; i++) {\n        var item = {\n            \"index\": i.toString(),\n            \"usb_power_states\": usb_power_states,\n            \"title\": \"USB\" + (i + 1).toString(),\n            \"icon\": \"/usb.png\",\n            \"isChecked\": usb_power_states[i]\n        }\n        device_payload.push (item)\n    }\n\n    if (g_init < 1) {\n        global.set(\"device_init\", 1);\n    }\n    if (g_hash != hash) {\n        global.set(\"device_hash\", hash);\n    }\n    return {payload: device_payload};\n}",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 730,
        "y": 1780,
        "wires": [
            [
                "7f4aeb5a178cb809"
            ]
        ]
    },
    {
        "id": "f20d6690aca9a19f",
        "type": "function",
        "z": "6eda76ddd54bb83d",
        "name": "edid_output_func",
        "func": "var edid_msg = {command: \"set\", payload: []};\nvar save_msg = {command: \"set\", topic: \"save-config\"};\nvar item = msg.payload\nvar i\n\nfor (i = 0; i < item.edid_status.length; i++) {\n    if (i == parseInt(item.index)) {\n        if (item.isChecked) {\n            item.edid_status[i] = true;\n        } else {\n            item.edid_status[i] = false;\n        }\n    }\n}\n\nedid_msg.payload = item.edid_status;\n\n// force to refresh edid\nglobal.set(\"edid_init\", 0);\n\nreturn [edid_msg, save_msg];",
        "outputs": 2,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1150,
        "y": 800,
        "wires": [
            [
                "bd04967050913cce"
            ],
            [
                "be7b670ada82ded8"
            ]
        ]
    },
    {
        "id": "23ba9c14f7c560c5",
        "type": "function",
        "z": "6eda76ddd54bb83d",
        "name": "mcu_output_func",
        "func": "var dhcp_msg = { command: \"set\", topic: \"dhcp\", payload: false};\nvar ip_msg = { command: \"set\", topic: \"ip-address\", payload: \"\"};\nvar mask_msg = { command: \"set\", topic: \"ip-mask\", payload: \"\"};\nvar gateway_msg = { command: \"set\", topic: \"default-gateway\", payload: \"\"};\nvar dns_msg = { command: \"set\", topic: \"dns\", payload: [\"\", \"\"]};\nvar save_msg = {command: \"set\", topic: \"save-config\"};\nvar item = msg.payload\n\nif (item.Dhcp_Client) {\n    dhcp_msg.payload = item.Dhcp_Client\n    ip_msg = {};\n    mask_msg = {};\n    gateway_msg = {};\n    dns_msg = {};\n} else {\n    ip_msg.payload = item.Ip_Address\n    mask_msg.payload = item.Ip_Mask\n    gateway_msg.payload = item.Default_Gateway\n    dns_msg.payload = [item.Primary_Dns, item.Secondary_Dns]\n}\n\n// force to refresh mcu\nglobal.set(\"mcu_init\", 0);\n\nreturn [dhcp_msg, ip_msg, mask_msg, gateway_msg, dns_msg, save_msg];",
        "outputs": 6,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1150,
        "y": 1080,
        "wires": [
            [
                "137b396857c3ed72"
            ],
            [
                "137b396857c3ed72"
            ],
            [
                "137b396857c3ed72"
            ],
            [
                "66d58672ba92ebea"
            ],
            [
                "66d58672ba92ebea"
            ],
            [
                "be7b670ada82ded8"
            ]
        ]
    },
    {
        "id": "e6b3878f0231c0aa",
        "type": "function",
        "z": "6eda76ddd54bb83d",
        "name": "schedule_output_func",
        "func": "function zeroPad(nr,base){\n  var len = (String(base).length - String(nr).length)+1;\n  return len > 0? new Array(len).join('0')+nr : nr;\n}\n\nvar sunday_msg = { command: \"set\", topic: \"sunday\", payload: {}};\nvar monday_msg = { command: \"set\", topic: \"monday\", payload: {}};\nvar tuesday_msg = { command: \"set\", topic: \"tuesday\", payload: {}};\nvar wednesday_msg = { command: \"set\", topic: \"wednesday\", payload: {}};\nvar thursday_msg = { command: \"set\", topic: \"thursday\", payload: {}};\nvar friday_msg = { command: \"set\", topic: \"friday\", payload: {}};\nvar saturday_msg = { command: \"set\", topic: \"saturday\", payload: {}};\nvar json_msg = {payload: \"\"};\nvar save_msg = {command: \"set\", topic: \"save-config\"};\nvar json = msg.json;\n\nif (json.isEveryday) {\n    var schedule_off = json.schedule.concat();\n    schedule_off.sort(\n        function(a, b) {\n            if (a.off === \"\" && b.off === \"\") {\n                return 0;\n            }\n\n            if (b.off === \"\") {\n                return -1;\n            }\n\n            if (a.off === \"\") {\n                return 1;\n            }\n    \n            if (a.off < b.off) {\n                return -1;\n            }\n            if (a.off > b.off) {\n                return 1;\n            }\n            \n            // names must be equal\n            return 0;\n        }\n    );\n    var schedule_on = json.schedule.concat();\n    schedule_on.sort(\n        function(a, b) {\n            if (a.on === \"\" && b.on === \"\") {\n                return 0;\n            }\n\n            if (b.on === \"\") {\n                return -1;\n            }\n\n            if (a.on === \"\") {\n                return 1;\n            }\n\n            if (a.on < b.on) {\n                return -1;\n            }\n            if (a.on > b.on) {\n                return 1;\n            }\n            \n            // names must be equal\n            return 0;\n        }\n    );\n\n    var date = new Date();\n    var dateTime = zeroPad(date.getHours(), 10) + \":\" + zeroPad(date.getMinutes(), 10);\n    var sch_off = \"\";\n    var sch_on = \"\";\n    var sch;\n    var i;\n\n    // search the closest off time, greater than current time\n    for (i = 0; i < schedule_off.length; i++) {\n        sch = schedule_off[i];\n        if (sch.off !== \"\" && sch_off === \"\") {\n            if (sch.off > dateTime) {\n                sch_off = sch.off;\n                break;\n            }\n        }\n    }\n    \n    // if not found assign to the first time to it\n    if (sch_off === \"\") {\n        for (i = 0; i < schedule_off.length; i++) {\n            sch = schedule_off[i];\n            if (sch.off !== \"\") {\n                sch_off = sch.off;\n                break;\n            }\n        }\n    }\n\n    // search the closest on time, greater than off time\n    for (i = 0; i < schedule_on.length; i++) {\n        sch = schedule_on[i];\n        if (sch.on !== \"\" && sch_on === \"\") {\n            if (sch.on > sch_off) {\n                sch_on = sch.on;\n                break;\n            }\n        }\n    }\n\n    // if not found assign to the first time to it\n    if (sch_on === \"\") {\n        for (i = 0; i < schedule_on.length; i++) {\n            sch = schedule_on[i];\n            if (sch.on !== \"\") {\n                sch_on = sch.on;\n                break;\n            }\n        }\n    }\n    \n    json.schedule = schedule_on;\n\n    sunday_msg.payload = {on: sch_on, off: sch_off};\n    monday_msg.payload = {on: sch_on, off: sch_off};\n    tuesday_msg.payload = {on: sch_on, off: sch_off};\n    wednesday_msg.payload = {on: sch_on, off: sch_off};\n    thursday_msg.payload = {on: sch_on, off: sch_off};\n    friday_msg.payload = {on: sch_on, off: sch_off};\n    saturday_msg.payload = {on: sch_on, off: sch_off};\n} else {\n    sunday_msg.payload = {on: json.schedule[0].on, off: json.schedule[0].off};\n    monday_msg.payload = {on: json.schedule[1].on, off: json.schedule[1].off};\n    tuesday_msg.payload = {on: json.schedule[2].on, off: json.schedule[2].off};\n    wednesday_msg.payload = {on: json.schedule[3].on, off: json.schedule[3].off};\n    thursday_msg.payload = {on: json.schedule[4].on, off: json.schedule[4].off};\n    friday_msg.payload = {on: json.schedule[5].on, off: json.schedule[5].off};\n    saturday_msg.payload = {on: json.schedule[6].on, off: json.schedule[6].off};\n}\n\njson_msg.payload = JSON.stringify(json);\n\n// force to refresh mcu\nglobal.set(\"schedule_init\", 0);\n\nreturn [\n    sunday_msg,\n    monday_msg,\n    tuesday_msg,\n    wednesday_msg,\n    thursday_msg,\n    friday_msg,\n    saturday_msg,\n    json_msg,\n    save_msg\n];",
        "outputs": 9,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1160,
        "y": 1480,
        "wires": [
            [
                "4b47347a5a43039b"
            ],
            [
                "4b47347a5a43039b"
            ],
            [
                "4b47347a5a43039b"
            ],
            [
                "4b47347a5a43039b"
            ],
            [
                "4b47347a5a43039b"
            ],
            [
                "4b47347a5a43039b"
            ],
            [
                "4b47347a5a43039b"
            ],
            [
                "8c6d0ec497bc2aca"
            ],
            [
                "be7b670ada82ded8"
            ]
        ]
    },
    {
        "id": "63b3ce39908ae23c",
        "type": "function",
        "z": "6eda76ddd54bb83d",
        "name": "device_output_func",
        "func": "var device_msg = {command: \"set\", payload: []}\nvar save_msg = {command: \"set\", topic: \"save-config\"};\nvar item = msg.payload\nvar i\n\nfor (i = 0; i < item.usb_power_states.length; i++) {\n    if (i == parseInt(item.index)) {\n        if (item.isChecked) {\n            item.usb_power_states[i] = true;\n        } else {\n            item.usb_power_states[i] = false;\n        }\n    }\n}\n\ndevice_msg.payload = item.usb_power_states;\n\n// force to refresh edid\nglobal.set(\"device_init\", 0);\n\nreturn [device_msg, save_msg];",
        "outputs": 2,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1150,
        "y": 1780,
        "wires": [
            [
                "c5d0d7d4be09652e"
            ],
            [
                "be7b670ada82ded8"
            ]
        ]
    },
    {
        "id": "19e7dd6cd34d2408",
        "type": "ui_template",
        "z": "6eda76ddd54bb83d",
        "group": "f78b45f4d75d0c20",
        "name": "mcu_table",
        "order": 0,
        "width": "0",
        "height": "0",
        "format": "<style>\n.dot {\n    height: 20px;\n    width: 20px;\n    background-color: #bbb;\n    border-radius: 50%;\n    display: inline-block;\n}\n\n.dot.false {\n    background-color: red;\n}\n\n.dot.true {\n    background-color: green;\n}\n\n/* The Dialog (background) */\n.dialog {\n    display: none; /* Hidden by default */\n    position: fixed; /* Stay in place */\n    z-index: 9999; /* Sit on top */\n    left: 0;\n    top: 0;\n    width: 100%; /* Full width */\n    height: 100%; /* Full height */\n    overflow: auto; /* Enable scroll if needed */\n    -webkit-transform: translateZ(0px);\n    -webkit-transform: translate3d(0,0,0);\n    -webkit-perspective: 1000;\n}\n\n.dialog_content {\n    position: absolute;\n    background-color: #fff;\n    left: calc(50% - 170px);\n    top: 30px;\n    border-radius: 10px;\n    padding: 0;\n    box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19);\n    -webkit-animation-name: animatetop;\n    animation-name: animatetop;\n    animation-duration: 0.4s;\n}\ntitle {\n    margin:10px;\n    font-size: 20px;\n}\n/* Media query for smartphones (to Fix?) */\n@media only screen and (min-device-width : 375px) and (max-device-width : 667px) { \n    .dialog_content {\n    margin-top: 5%;\n    margin-left: 5%;\n}\n}\n\n/* Add Animation */\n@-webkit-keyframes animatetop {\n    from {top: -300px; opacity: 0} \n    to {top: 0; opacity: 1}\n}\n\n@keyframes animatetop {\n    from {top: -300px; opacity: 0}\n    to {top: 0; opacity: 1}\n}\n\n/* Dialog Header */\n.dialog_header {\n    padding: 2px 16px;\n    background-color: #03A9F4;\n    border-radius: 10px 10px 0 0;\n    color: white;\n    height: 40px;\n}\n\n/* Dialog Body */\n.dialog_body {padding: 5px;}\n\n/* The Close Button */\n.close {\n    color: #fff;\n    float: right;\n    font-size: 28px;\n    font-weight: bold;\n    cursor: pointer;\n}\n\n.close:hover,\n.close:focus {\n    color: #1565C0;\n    text-decoration: none;\n    cursor: pointer;\n}\n\n/* Number container */\n.btn_box{\n    margin: 5px;\n}\n\n/* Buttons style */\n.btn {\n    min-height: 40px;\n    min-width: 80px;\n    font-weight: bold;\n    margin: 0px 10px 10px 0px;\n    box-shadow: 4px 4px 6px 0 #dadada;\n    background-color: #29B6F6;\n    color: #29B6F6;\n}\n\n.btn:not([disabled]):hover {\n    background-color: #03A9F4;\n}\n</style>\n\n\n<div >\n    <table style=\"width: 100%;\">\n        <tr>\n            <td colspan=2>\n                <md-button class=\"btn\" style=\"color:#2980b9; background-color:#d6eaf8;\" ng-click=\"openDialog()\">\n                    <ng-md-icon icon=\"settings\"></ng-md-icon>\n                </md-button>\n                <br/>&nbsp;\n            </td>\n        </tr>\n        <tr>\n            <td style=\"width: 50%\">\n                DHCP:\n            </td>\n            <td align=\"left\">\n                <span class=\"dot {{isDHCP}}\"></span>\n            </td>\n        </tr>\n        <tr>\n            <td style=\"width: 50%\">\n                IP:\n            </td>\n            <td align=\"left\">\n                {{ipAddress}}\n            </td>\n        </tr>\n        <tr>\n            <td style=\"width: 50%\">\n                Mask:\n            </td>\n            <td align=\"left\">\n                {{ipMask}}\n            </td>\n        </tr>\n        <tr>\n            <td style=\"width: 50%\">\n                Gateway:\n            </td>\n            <td align=\"left\">\n                {{ipGateway}}\n            </td>\n        </tr>\n        <tr>\n            <td style=\"width: 50%\">\n                Primary DNS:\n            </td>\n            <td align=\"left\">\n                {{ipPdns}}\n            </td>\n        </tr>\n        <tr>\n            <td style=\"width: 50%\">\n                Secondary DNS:\n            </td>\n            <td align=\"left\">\n                {{ipSdns}}\n            </td>\n        </tr>\n    </table>\n</div>\n\n\n<!-- The Modal -->\n<div id=\"mcu_dialog\" class=\"dialog\">\n    <div class=\"dialog_content\" style=\"width: 360px;\">\n        \n        <div class=\"dialog_header\">\n            <span ng-click=\"closeDialog()\" class=\"close\">&times;</span>\n            <span class=\"title\">Internet Settings</span>\n        </div>\n        \n        <div class=\"dialog_body\">\n            <div slayout=\"column\" layout-align=\"left\" style=\"margin-left: 10px;\">\n                <md-switch ng-model=\"isDHCP\" aria-label=\"DHCP\">\n                  DHCP\n                </md-switch>\n                <md-input-container>\n                    <label>IP</label>\n                    <input ng-model=\"ipAddress\" ng-disabled=\"isDHCP\" required pattern=\"^([0-9]{1,3}\\.){3}[0-9]{1,3}$\">\n                </md-input-container>\n                <md-input-container>\n                    <label>Mask</label>\n                    <input ng-model=\"ipMask\" ng-disabled=\"isDHCP\" required pattern=\"^([0-9]{1,3}\\.){3}[0-9]{1,3}$\">\n                </md-input-container>\n                <md-input-container>\n                    <label>Gateway</label>\n                    <input ng-model=\"ipGateway\" ng-disabled=\"isDHCP\" required pattern=\"^([0-9]{1,3}\\.){3}[0-9]{1,3}$\">\n                </md-input-container>\n                <md-input-container>\n                    <label>Primary DNS</label>\n                    <input ng-model=\"ipPdns\" ng-disabled=\"isDHCP\" required pattern=\"^([0-9]{1,3}\\.){3}[0-9]{1,3}$\">\n                </md-input-container>\n                <md-input-container>\n                    <label>Secondary DNS</label>\n                    <input ng-model=\"ipSdns\" ng-disabled=\"isDHCP\" required pattern=\"^([0-9]{1,3}\\.){3}[0-9]{1,3}$\">\n                </md-input-container>\n\n                <div layout=\"row\" layout-align=\"center\">\n                    <div class=\"btn_box\">\n                        <md-button class=\"btn\" style=\"color:#2980b9; background-color:#d6eaf8;\" ng-click=\"confirm()\">\n                            <ng-md-icon icon=\"done\" style=\"color:#fff;\"></ng-md-icon> OK\n                        </md-button>\n                    </div>\n                    <div class=\"btn_box\">\n                        <md-button class=\"btn\" style=\"color:#2980b9; background-color:#d6eaf8;\" ng-click=\"closeDialog()\">\n                            <ng-md-icon icon=\"close\" style=\"color:#fff;\"></ng-md-icon> Cancel\n                        </md-button>\n                    </div>\n                </div>\n            </div> \n        </div> <!--dialog_body-->\n    </div> <!--dialog_content-->\n</div>\n\n\n<script>\n\n(function(scope) {\n    scope.isDHCP = true;\n    scope.ipAddress = \"\";\n    scope.ipMask = \"\";\n    scope.ipGateway = \"\";\n    scope.ipPdns = \"\";\n    scope.ipSdns = \"\";\n\n    var modal = document.getElementById('mcu_dialog');\n    \n    // When the user clicks anywhere outside of the modal, close it\n    window.onclick = function(event) {\n        if (event.target == modal) {\n            modal.style.display = \"none\";\n        }\n    }\n\n\n    scope.$watch('msg', function(msg) {\n        if (msg && msg.payload) {\n            scope.isDHCP = msg.payload.Dhcp_Client;\n            scope.ipAddress = msg.payload.Ip_Address;\n            scope.ipMask = msg.payload.Ip_Mask;\n            scope.ipGateway = msg.payload.Default_Gateway;\n            scope.ipPdns = msg.payload.Primary_Dns;\n            scope.ipSdns = msg.payload.Secondary_Dns;\n        }\n    });\n\n    scope.openDialog = function(){\n        scope.isDHCP_Backup = scope.isDHCP;\n        scope.ipAddress_Backup = scope.ipAddress;\n        scope.ipMask_Backup = scope.ipMask;\n        scope.ipGateway_Backup = scope.ipGateway;\n        scope.ipPdns_Backup = scope.ipPdns;\n        scope.ipSdns_Backup = scope.ipSdns;\n        modal.style.display = \"block\";\n    }\n\n    scope.closeDialog = function(){\n        scope.isDHCP = scope.isDHCP_Backup;\n        scope.ipAddress = scope.ipAddress_Backup;\n        scope.ipMask = scope.ipMask_Backup;\n        scope.ipGateway = scope.ipGateway_Backup;\n        scope.ipPdns = scope.ipPdns_Backup;\n        scope.ipSdns = scope.ipSdns_Backup;\n        modal.style.display = \"none\";\n    }\n\n    scope.confirm = function() {\n        var item = {\n            Dhcp_Client: scope.isDHCP,\n            Ip_Address: scope.ipAddress,\n            Ip_Mask: scope.ipMask,\n            Default_Gateway: scope.ipGateway,\n            Primary_Dns: scope.ipPdns,\n            Secondary_Dns: scope.ipSdns\n        }\n        scope.send({payload: item});\n        scope.closeDialog();\n    }\n\n})(scope);\n</script>\n",
        "storeOutMessages": false,
        "fwdInMessages": false,
        "resendOnRefresh": false,
        "templateScope": "local",
        "className": "",
        "x": 950,
        "y": 1080,
        "wires": [
            [
                "23ba9c14f7c560c5"
            ]
        ]
    },
    {
        "id": "b4dc8a0a2624097e",
        "type": "ui_template",
        "z": "6eda76ddd54bb83d",
        "group": "9ceeb9d18bc9ed05",
        "name": "schedule_dialog",
        "order": 0,
        "width": "0",
        "height": "0",
        "format": "<div ng-init=\"init()\" id=\"schedule_dialog\" class=\"dialog\">\n    <div class=\"dialog_content\" style=\"width: 640px;\">\n        \n        <div class=\"dialog_header\">\n            <span ng-click=\"closeDialog()\" class=\"close\">&times;</span>\n            <h2 class=\"title\">Schedule Settings</h2>\n        </div>\n        \n        <div class=\"dialog_body\">\n            <div slayout=\"column\" layout-align=\"left\">\n                <md-switch ng-model=\"isEveryday\">\n                  Everyday\n                </md-switch>\n                <hr />\n                <table cellspacing=\"0\" cellpadding=\"0\">\n                    <tr>\n                        <td style=\"border-right: 1px dashed\">\n                            <table>\n                                <tr>\n                                    <td></td>\n                                    <td>PowerOn Time</td>\n                                </tr>\n                                <tr>\n                                    <td>\n                                        <span ng-show=\"!isEveryday\" id=\"wdate0\">Sunday</span>\n                                    </td>\n                                    <td>\n                                        <md-input-container>\n                                            <label>1st On</label>\n                                            <input ng-model=\"onTime0\" pattern=\"(([0-9]{2}):([0-9]{2}))\">\n                                        </md-input-container>\n                                    <td>\n                                </tr>\n                                <tr>\n                                    <td>\n                                        <span ng-show=\"!isEveryday\" id=\"wdate1\">Monday</span>\n                                    </td>\n                                    <td>\n                                        <md-input-container>\n                                            <label>2nd On</label>\n                                            <input ng-model=\"onTime1\" pattern=\"(([0-9]{2}):([0-9]{2}))\">\n                                        </md-input-container>\n                                    <td>\n                                </tr>\n                                <tr>\n                                    <td>\n                                        <span ng-show=\"!isEveryday\" id=\"wdate2\">Tuesday</span>\n                                    </td>\n                                    <td>\n                                        <md-input-container>\n                                            <label>3rd On</label>\n                                            <input ng-model=\"onTime2\" pattern=\"(([0-9]{2}):([0-9]{2}))\">\n                                        </md-input-container>\n                                    <td>\n                                </tr>\n                                <tr>\n                                    <td>\n                                        <span ng-show=\"!isEveryday\" id=\"wdate3\">Wednesday</span>\n                                    </td>\n                                    <td>\n                                        <md-input-container>\n                                            <label>4th On</label>\n                                            <input ng-model=\"onTime3\" pattern=\"(([0-9]{2}):([0-9]{2}))\">\n                                        </md-input-container>\n                                    <td>\n                                </tr>\n                                <tr>\n                                    <td>\n                                        <span ng-show=\"!isEveryday\" id=\"wdate4\">Thursday</span>\n                                    </td>\n                                    <td>\n                                        <md-input-container>\n                                            <label>5th On</label>\n                                            <input ng-model=\"onTime4\" pattern=\"(([0-9]{2}):([0-9]{2}))\">\n                                        </md-input-container>\n                                    <td>\n                                </tr>\n                                <tr>\n                                    <td>\n                                        <span ng-show=\"!isEveryday\" id=\"wdate5\">Friday</span>\n                                    </td>\n                                    <td>\n                                        <md-input-container>\n                                            <label>6th On</label>\n                                            <input ng-model=\"onTime5\" pattern=\"(([0-9]{2}):([0-9]{2}))\">\n                                        </md-input-container>\n                                    <td>\n                                </tr>\n                                <tr>\n                                    <td>\n                                        <span ng-show=\"!isEveryday\" id=\"wdate6\">Saturday</span>\n                                    </td>\n                                    <td>\n                                        <md-input-container>\n                                            <label>7th On</label>\n                                            <input ng-model=\"onTime6\" pattern=\"(([0-9]{2}):([0-9]{2}))\">\n                                        </md-input-container>\n                                    <td>\n                                </tr>\n                            </table>\n                        <td>\n                        <td>\n                            <table>\n                                <tr>\n                                    <td>PowerOff Time</td>\n                                </tr>\n                                <tr>\n                                    <td>\n                                        <md-input-container>\n                                            <label>1st Off</label>\n                                            <input ng-model=\"offTime0\" pattern=\"(([0-9]{2}):([0-9]{2}))\">\n                                        </md-input-container>\n                                    <td>\n                                </tr>\n                                <tr>\n                                    <td>\n                                        <md-input-container>\n                                            <label>2nd Off</label>\n                                            <input ng-model=\"offTime1\" pattern=\"(([0-9]{2}):([0-9]{2}))\">\n                                        </md-input-container>\n                                    <td>\n                                </tr>\n                                <tr>\n                                    <td>\n                                        <md-input-container>\n                                            <label>3rd Off</label>\n                                            <input ng-model=\"offTime2\" pattern=\"(([0-9]{2}):([0-9]{2}))\">\n                                        </md-input-container>\n                                    <td>\n                                </tr>\n                                <tr>\n                                    <td>\n                                        <md-input-container>\n                                            <label>4th Off</label>\n                                            <input ng-model=\"offTime3\" pattern=\"(([0-9]{2}):([0-9]{2}))\">\n                                        </md-input-container>\n                                    <td>\n                                </tr>\n                                <tr>\n                                    <td>\n                                        <md-input-container>\n                                            <label>5th Off</label>\n                                            <input ng-model=\"offTime4\" pattern=\"(([0-9]{2}):([0-9]{2}))\">\n                                        </md-input-container>\n                                    <td>\n                                </tr>\n                                <tr>\n                                    <td>\n                                        <md-input-container>\n                                            <label>6th Off</label>\n                                            <input ng-model=\"offTime5\" pattern=\"(([0-9]{2}):([0-9]{2}))\">\n                                        </md-input-container>\n                                    <td>\n                                </tr>\n                                <tr>\n                                    <td>\n                                        <md-input-container>\n                                            <label>7th Off</label>\n                                            <input ng-model=\"offTime6\" pattern=\"(([0-9]{2}):([0-9]{2}))\">\n                                        </md-input-container>\n                                    <td>\n                                </tr>\n                            </table>\n                        </td>\n                    <tr>\n                </table>\n\n                <div layout=\"row\" layout-align=\"center\">\n                    <div class=\"btn_box\">\n                        <md-button class=\"btn\" ng-click=\"confirm()\">\n                            <ng-md-icon icon=\"done\" style=\"color:#fff;\"></ng-md-icon> OK\n                        </md-button>\n                    </div>\n                    <div class=\"btn_box\">\n                        <md-button class=\"btn\" ng-click=\"closeDialog()\">\n                            <ng-md-icon icon=\"close\" style=\"color:#fff;\"></ng-md-icon> Cancel\n                        </md-button>\n                    </div>\n                </div>\n            </div> \n        </div> <!--dialog_body-->\n    </div> <!--dialog_content-->\n</div>  <!--dialog-->\n\n\n<style>\n\n/* The Dialog (background) */\n.dialog {\n    display: none; /* Hidden by default */\n    position: fixed; /* Stay in place */\n    z-index: 9999; /* Sit on top */\n    left: 0;\n    top: 0;\n    width: 100%; /* Full width */\n    height: 100%; /* Full height */\n    overflow: auto; /* Enable scroll if needed */\n    background-color: rgb(0,0,0); /* Fallback color */\n    background-color: rgba(0,0,0,0.4); /* Black w/ opacity */\n    -webkit-transform: translateZ(0px);\n    -webkit-transform: translate3d(0,0,0);\n    -webkit-perspective: 1000;\n}\n\n.dialog_content {\n    position: absolute;\n    background-color: #fff;\n    left: calc(50% - 170px);\n    top: 30px;\n    border-radius: 10px;\n    padding: 0;\n    box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19);\n    -webkit-animation-name: animatetop;\n    animation-name: animatetop;\n    animation-duration: 0.4s;\n}\nh2.title {\n    margin:10px;\n    font-size: 20px;\n}\n/* Media query for smartphones (to Fix?) */\n@media only screen and (min-device-width : 375px) and (max-device-width : 667px) { \n    .dialog_content {\n    margin-top: 5%;\n    margin-left: 5%;\n}\n}\n\n/* Add Animation */\n@-webkit-keyframes animatetop {\n    from {top: -300px; opacity: 0} \n    to {top: 0; opacity: 1}\n}\n\n@keyframes animatetop {\n    from {top: -300px; opacity: 0}\n    to {top: 0; opacity: 1}\n}\n\n/* Dialog Header */\n.dialog_header {\n    padding: 2px 16px;\n    background-color: #03A9F4;\n    border-radius: 10px 10px 0 0;\n    color: white;\n}\n\n/* Dialog Body */\n.dialog_body {padding: 5px;}\n\n/* The Close Button */\n.close {\n    color: #fff;\n    float: right;\n    font-size: 28px;\n    font-weight: bold;\n    cursor: pointer;\n}\n\n.close:hover,\n.close:focus {\n    color: #1565C0;\n    text-decoration: none;\n    cursor: pointer;\n}\n\n/* Number container */\n.btn_box{\n    margin: 5px;\n}\n\n/* Buttons style */\n.btn {\n    min-height: 40px;\n    min-width: 80px;\n    font-weight: bold;\n    margin: 0px 10px 10px 0px;\n    box-shadow: 4px 4px 6px 0 #dadada;\n    background-color: #29B6F6;\n    color: #fff;\n}\n\n.btn:not([disabled]):hover {\n    background-color: #03A9F4;\n}\n\n\n</style>\n\n<script>\n\n/**\n * Steve-Mcl 2020-03-30\n * Adapated from the excellent work by Daniel Lando, https://github.com/robertsLando\n * to be the basis of a user input popup form\n * Original licence below...\n * *********************************************************************************\n * pin_dialog.js\n * Node-Red UI template for Node-Red Dashboard. \n * Custom dialog that asks for a PIN to allow actions\n * Enjoy it :). \n * -- Daniel\n *\n *\n * @license The Unlicense, http://unlicense.org/\n * @version 0.2\n * @author  Daniel Lando, https://github.com/robertsLando\n * @updated 2019-03-18\n * @link    ----\n * **********************************************************************************\n *\n */\n\nvar schedule_dialog;\n\n/* ==== */\n(function(scope) {\n    scope.inited = false;\n    scope.isEveryday = false;\n    scope.json = {\n        isEveryday: false,\n        schedule: [\n            {on: 0, off: 0}\n        ]\n    };\n\n    scope.init = function() {\n        $('#schedule_dialog').parent().parent().css(\"display\", \"none\");\n        schedule_dialog = $('#schedule_dialog').detach();\n        scope.inited = true;\n    }\n\n    scope.showDialog = function() {\n        schedule_dialog.appendTo(document.body); // better to add the body only when the numpad is displayed (seams to be removed automatically)\n        scope.isEveryday = scope.json.isEveryday;\n        scope.onTime0 = scope.json.schedule[0].on;\n        scope.offTime0 = scope.json.schedule[0].off;\n        scope.onTime1 = scope.json.schedule[1].on;\n        scope.offTime1 = scope.json.schedule[1].off;\n        scope.onTime2 = scope.json.schedule[2].on;\n        scope.offTime2 = scope.json.schedule[2].off;\n        scope.onTime3 = scope.json.schedule[3].on;\n        scope.offTime3 = scope.json.schedule[3].off;\n        scope.onTime4 = scope.json.schedule[4].on;\n        scope.offTime4 = scope.json.schedule[4].off;\n        scope.onTime5 = scope.json.schedule[5].on;\n        scope.offTime5 = scope.json.schedule[5].off;\n        scope.onTime6 = scope.json.schedule[6].on;\n        scope.offTime6 = scope.json.schedule[6].off;           \n        schedule_dialog.css(\"display\", \"block\");\n    }\n\n    scope.closeDialog = function(){\n        schedule_dialog.css(\"display\", \"none\");\n    }\n    \n    scope.confirm = function() {\n        scope.json.isEveryday = scope.isEveryday;\n        scope.json.schedule[0].on = scope.onTime0;\n        scope.json.schedule[0].off = scope.offTime0;\n        scope.json.schedule[1].on = scope.onTime1;\n        scope.json.schedule[1].off = scope.offTime1;\n        scope.json.schedule[2].on = scope.onTime2;\n        scope.json.schedule[2].off = scope.offTime2;\n        scope.json.schedule[3].on = scope.onTime3;\n        scope.json.schedule[3].off = scope.offTime3;\n        scope.json.schedule[4].on = scope.onTime4;\n        scope.json.schedule[4].off = scope.offTime4;\n        scope.json.schedule[5].on = scope.onTime5;\n        scope.json.schedule[5].off = scope.offTime5;\n        scope.json.schedule[6].on = scope.onTime6;\n        scope.json.schedule[6].off = scope.offTime6;           \n        scope.send({json: scope.json});\n        scope.closeDialog();\n    }\n\n    scope.$watch('msg', function(msg) {\n        if (msg) {\n            if (msg.json) {\n                scope.json = msg.json;\n            }\n            if (msg.topic) {\n                switch(msg.topic) {\n                   case \"show\":\n                       if(scope.inited){\n                            scope.showDialog();\n                       }\n                    break;\n                    case \"close\": \n                        scope.closeDialog(); \n                    break;\n                }\n            }\n            if (msg.schedule) {\n                scope.onTime0_Backup = msg.schedule.Sunday_On;\n                scope.offTime0_Backup = msg.schedule.Sunday_Off;\n                scope.onTime1_Backup = msg.schedule.Monday_On;\n                scope.offTime1_Backup = msg.schedule.Monday_Off;\n                scope.onTime2_Backup = msg.schedule.Tuesday_On;\n                scope.offTime2_Backup = msg.schedule.Tuesday_Off;\n                scope.onTime3_Backup = msg.schedule.Wednesday_On;\n                scope.offTime3_Backup = msg.schedule.Wednesday_Off;\n                scope.onTime4_Backup = msg.schedule.Thursday_On;\n                scope.offTime4_Backup = msg.schedule.Thursday_Off;\n                scope.onTime5_Backup = msg.schedule.Friday_On;\n                scope.offTime5_Backup = msg.schedule.Friday_Off;\n                scope.onTime6_Backup = msg.schedule.Saturday_On;\n                scope.offTime6_Backup = msg.schedule.Saturday_Off;\n            }\n        }\n    });\n})(scope);\n\n</script>\n",
        "storeOutMessages": false,
        "fwdInMessages": false,
        "resendOnRefresh": false,
        "templateScope": "local",
        "className": "",
        "x": 960,
        "y": 1420,
        "wires": [
            [
                "e6b3878f0231c0aa"
            ]
        ]
    },
    {
        "id": "4604958362d86857",
        "type": "rdm-hdmi",
        "z": "6eda76ddd54bb83d",
        "name": "",
        "x": 950,
        "y": 760,
        "wires": [
            [
                "70902c943ef66c58"
            ]
        ]
    },
    {
        "id": "07186639a17e13d7",
        "type": "rdm-edidemu",
        "z": "6eda76ddd54bb83d",
        "name": "",
        "x": 980,
        "y": 720,
        "wires": [
            [
                "70902c943ef66c58"
            ]
        ]
    },
    {
        "id": "70902c943ef66c58",
        "type": "join",
        "z": "6eda76ddd54bb83d",
        "name": "",
        "mode": "custom",
        "build": "merged",
        "property": "payload",
        "propertyType": "msg",
        "key": "topic",
        "joiner": "\\n",
        "joinerType": "str",
        "accumulate": false,
        "timeout": "",
        "count": "2",
        "reduceRight": false,
        "reduceExp": "",
        "reduceInit": "",
        "reduceInitType": "",
        "reduceFixup": "",
        "x": 1170,
        "y": 740,
        "wires": [
            [
                "6a12c9e182bbc34a"
            ]
        ]
    },
    {
        "id": "be935622b91b8e80",
        "type": "function",
        "z": "6eda76ddd54bb83d",
        "name": "edid_trigger",
        "func": "return {command: \"get\"};",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 710,
        "y": 720,
        "wires": [
            [
                "07186639a17e13d7",
                "4604958362d86857"
            ]
        ]
    },
    {
        "id": "869a1dd2acf18357",
        "type": "function",
        "z": "6eda76ddd54bb83d",
        "name": "mcu_dhcp_trigger",
        "func": "var dhcp_msg = { command: \"get\", topic: \"dhcp\"};\nvar ip_msg = { command: \"get\", topic: \"ip-address\"};\nvar mask_msg = { command: \"get\", topic: \"ip-mask\"};\nvar gateway_msg = { command: \"get\", topic: \"default-gateway\"};\nvar dns_msg = { command: \"get\", topic: \"dns\"};\n\nreturn [dhcp_msg, ip_msg, mask_msg, gateway_msg, dns_msg]",
        "outputs": 5,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 730,
        "y": 1000,
        "wires": [
            [
                "b8f59df111f6fdf1"
            ],
            [
                "b8f59df111f6fdf1"
            ],
            [
                "b8f59df111f6fdf1"
            ],
            [
                "36cfde8b161f1e71"
            ],
            [
                "36cfde8b161f1e71"
            ]
        ]
    },
    {
        "id": "b8f59df111f6fdf1",
        "type": "rdm-lan",
        "z": "6eda76ddd54bb83d",
        "name": "",
        "x": 940,
        "y": 980,
        "wires": [
            [
                "2c1f785637dced62"
            ]
        ]
    },
    {
        "id": "36cfde8b161f1e71",
        "type": "rdm-system",
        "z": "6eda76ddd54bb83d",
        "name": "",
        "x": 950,
        "y": 1020,
        "wires": [
            [
                "2c1f785637dced62"
            ]
        ]
    },
    {
        "id": "2c1f785637dced62",
        "type": "join",
        "z": "6eda76ddd54bb83d",
        "name": "",
        "mode": "custom",
        "build": "merged",
        "property": "payload",
        "propertyType": "msg",
        "key": "topic",
        "joiner": "\\n",
        "joinerType": "str",
        "accumulate": false,
        "timeout": "",
        "count": "5",
        "reduceRight": false,
        "reduceExp": "",
        "reduceInit": "",
        "reduceInitType": "",
        "reduceFixup": "",
        "x": 1110,
        "y": 1000,
        "wires": [
            [
                "0c3ce6877a3249e4"
            ]
        ]
    },
    {
        "id": "bd04967050913cce",
        "type": "rdm-edidemu",
        "z": "6eda76ddd54bb83d",
        "name": "",
        "x": 980,
        "y": 840,
        "wires": [
            []
        ]
    },
    {
        "id": "d5f5d2432f2abdac",
        "type": "ui_template",
        "z": "6eda76ddd54bb83d",
        "group": "22c5af973bab020e",
        "name": "schedule_table",
        "order": 1,
        "width": 0,
        "height": 0,
        "format": "<div>\n    <table style=\"width: 100%;\">\n        <tr>\n            <td>\n                <md-button class=\"btn\" style=\"color:#2980b9; background-color:#d6eaf8;\" ng-click=\"openDialog()\">\n                    <ng-md-icon icon=\"settings\"></ng-md-icon>\n                </md-button>\n            </td>\n        </tr>\n    </table>\n</div>\n\n<script>\n\n(function(scope) {\n    scope.openDialog = function(){\n        scope.send({topic: \"show\"});\n    }\n})(scope);\n</script>\n",
        "storeOutMessages": true,
        "fwdInMessages": true,
        "resendOnRefresh": true,
        "templateScope": "local",
        "className": "",
        "x": 720,
        "y": 1420,
        "wires": [
            [
                "b4dc8a0a2624097e"
            ]
        ]
    },
    {
        "id": "137b396857c3ed72",
        "type": "rdm-lan",
        "z": "6eda76ddd54bb83d",
        "name": "",
        "x": 940,
        "y": 1140,
        "wires": [
            []
        ]
    },
    {
        "id": "66d58672ba92ebea",
        "type": "rdm-system",
        "z": "6eda76ddd54bb83d",
        "name": "",
        "x": 950,
        "y": 1180,
        "wires": [
            []
        ]
    },
    {
        "id": "e2a0f7874179c0f8",
        "type": "function",
        "z": "6eda76ddd54bb83d",
        "name": "device_trigger",
        "func": "return {command: \"get\"};",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 720,
        "y": 1740,
        "wires": [
            [
                "6845d710e6858613"
            ]
        ]
    },
    {
        "id": "6845d710e6858613",
        "type": "rdm-usb",
        "z": "6eda76ddd54bb83d",
        "name": "",
        "x": 950,
        "y": 1740,
        "wires": [
            [
                "7b2f639da5314526"
            ]
        ]
    },
    {
        "id": "c5d0d7d4be09652e",
        "type": "rdm-usb",
        "z": "6eda76ddd54bb83d",
        "name": "",
        "x": 950,
        "y": 1820,
        "wires": [
            []
        ]
    },
    {
        "id": "c0178408ce11cd9e",
        "type": "function",
        "z": "6eda76ddd54bb83d",
        "name": "schedule_trigger",
        "func": "return {command: \"get\", topic: \"all\"};",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 730,
        "y": 1320,
        "wires": [
            [
                "eae51452cf435553"
            ]
        ]
    },
    {
        "id": "eae51452cf435553",
        "type": "rdm-schedule",
        "z": "6eda76ddd54bb83d",
        "name": "",
        "x": 960,
        "y": 1320,
        "wires": [
            [
                "ffe0edaabaa06abe"
            ]
        ]
    },
    {
        "id": "e4a998efea1e761e",
        "type": "delay",
        "z": "6eda76ddd54bb83d",
        "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": 940,
        "y": 1380,
        "wires": [
            [
                "1e8c5c40e246a559"
            ]
        ]
    },
    {
        "id": "4a1fc19db287f3c0",
        "type": "rdm-system",
        "z": "6eda76ddd54bb83d",
        "name": "",
        "x": 470,
        "y": 80,
        "wires": [
            []
        ]
    },
    {
        "id": "81cc20cc72c28bd0",
        "type": "function",
        "z": "6eda76ddd54bb83d",
        "name": "rtc_calibrate",
        "func": "var date = new Date();\nvar userTimezoneOffset = 0;\n//userTimezoneOffset -= date.getTimezoneOffset() * 60000;\nvar utc_date = new Date (date.getTime() - userTimezoneOffset);\nvar dateTime = \n    utc_date.getFullYear() + '.' + (utc_date.getMonth()+1) + '.' + utc_date.getDate() + ' ' +\n    utc_date.getHours() + \":\" + utc_date.getMinutes() + \":\" + utc_date.getSeconds();\n\nreturn {command: \"set\", topic: \"rtc\", payload: dateTime};",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 310,
        "y": 80,
        "wires": [
            [
                "4a1fc19db287f3c0"
            ]
        ]
    },
    {
        "id": "bdf8ea9df85c7aaf",
        "type": "inject",
        "z": "6eda76ddd54bb83d",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": "1",
        "topic": "",
        "payloadType": "date",
        "x": 110,
        "y": 80,
        "wires": [
            [
                "81cc20cc72c28bd0",
                "169be247b1f32bcd"
            ]
        ]
    },
    {
        "id": "6f0657966526deac",
        "type": "comment",
        "z": "6eda76ddd54bb83d",
        "name": "System Calibration",
        "info": "",
        "x": 110,
        "y": 40,
        "wires": []
    },
    {
        "id": "4b47347a5a43039b",
        "type": "rdm-schedule",
        "z": "6eda76ddd54bb83d",
        "name": "",
        "x": 960,
        "y": 1560,
        "wires": [
            []
        ]
    },
    {
        "id": "e32d993ece3b9637",
        "type": "rdm-system",
        "z": "6eda76ddd54bb83d",
        "name": "",
        "x": 1610,
        "y": 1060,
        "wires": [
            []
        ]
    },
    {
        "id": "be7b670ada82ded8",
        "type": "delay",
        "z": "6eda76ddd54bb83d",
        "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": 1460,
        "y": 1060,
        "wires": [
            [
                "e32d993ece3b9637"
            ]
        ]
    },
    {
        "id": "169be247b1f32bcd",
        "type": "file in",
        "z": "6eda76ddd54bb83d",
        "name": "check_schedule_file",
        "filename": "schedule.json",
        "format": "utf8",
        "chunk": false,
        "sendError": false,
        "encoding": "none",
        "allProps": false,
        "x": 320,
        "y": 120,
        "wires": [
            [
                "b721860c9b5d471c"
            ]
        ]
    },
    {
        "id": "e7cb16c0933208d2",
        "type": "catch",
        "z": "6eda76ddd54bb83d",
        "name": "",
        "scope": [
            "169be247b1f32bcd"
        ],
        "uncaught": false,
        "x": 90,
        "y": 160,
        "wires": [
            [
                "d4372b1e6323df03"
            ]
        ]
    },
    {
        "id": "1149745d4884b8d5",
        "type": "file",
        "z": "6eda76ddd54bb83d",
        "name": "create_schedule_file",
        "filename": "schedule.json",
        "appendNewline": false,
        "createDir": true,
        "overwriteFile": "true",
        "encoding": "utf8",
        "x": 520,
        "y": 160,
        "wires": [
            []
        ]
    },
    {
        "id": "d4372b1e6323df03",
        "type": "function",
        "z": "6eda76ddd54bb83d",
        "name": "create_schedule_file",
        "func": "var json = {\n    isEveryday: false,\n    schedule: [\n        {on: 0, off: 0}\n    ]\n};\n\nglobal.set(\"json\", json);\n\nreturn {payload: \"\"};",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 280,
        "y": 160,
        "wires": [
            [
                "1149745d4884b8d5"
            ]
        ]
    },
    {
        "id": "8c6d0ec497bc2aca",
        "type": "file",
        "z": "6eda76ddd54bb83d",
        "name": "write_empty_schedule_file",
        "filename": "schedule.json",
        "appendNewline": false,
        "createDir": true,
        "overwriteFile": "true",
        "encoding": "utf8",
        "x": 1000,
        "y": 1600,
        "wires": [
            []
        ]
    },
    {
        "id": "b721860c9b5d471c",
        "type": "function",
        "z": "6eda76ddd54bb83d",
        "name": "check_schedule_file",
        "func": "const cyrb53 = function(str, seed = 0) {\n    let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;\n    for (let i = 0, ch; i < str.length; i++) {\n        ch = str.charCodeAt(i);\n        h1 = Math.imul(h1 ^ ch, 2654435761);\n        h2 = Math.imul(h2 ^ ch, 1597334677);\n    }\n    h1 = Math.imul(h1 ^ (h1>>>16), 2246822507) ^ Math.imul(h2 ^ (h2>>>13), 3266489909);\n    h2 = Math.imul(h2 ^ (h2>>>16), 2246822507) ^ Math.imul(h1 ^ (h1>>>13), 3266489909);\n    return 4294967296 * (2097151 & h2) + (h1>>>0);\n};\n\nvar json = {\n    isEveryday: false,\n    schedule: [\n        {on: 0, off: 0}\n    ]\n};\n\nif (msg.payload !== \"\") {\n    json = JSON.parse(msg.payload);\n}\n\nglobal.set(\"json\", json);\n\nif (json.isEveryday) {\n    var g_init = global.get(\"json_init\");\n    var g_hash = global.get(\"json_hash\");\n    var hash = cyrb53(msg.payload, 1);\n    \n    if ((g_init < 1) || (g_hash != hash)) {\n        if (g_init < 1) {\n            global.set(\"json_init\", 1);\n        }\n        if (g_hash != hash) {\n            global.set(\"json_hash\", hash);\n        }\n\n        // if everyday, set next on/off time\n        return {json: json};\n    }\n}",
        "outputs": 1,
        "noerr": 0,
        "initialize": "global.set(\"json_init\", 0);\nglobal.set(\"json_hash\", 0);",
        "finalize": "",
        "libs": [],
        "x": 560,
        "y": 120,
        "wires": [
            [
                "e6b3878f0231c0aa"
            ]
        ]
    },
    {
        "id": "ecce892ed85606dd",
        "type": "watch",
        "z": "6eda76ddd54bb83d",
        "name": "",
        "files": "schedule.json",
        "recursive": "",
        "x": 110,
        "y": 120,
        "wires": [
            [
                "169be247b1f32bcd"
            ]
        ]
    },
    {
        "id": "666082da419756c0",
        "type": "ax-hwmon",
        "z": "6eda76ddd54bb83d",
        "name": "",
        "x": 950,
        "y": 520,
        "wires": [
            [
                "678ebb8204b7e79e"
            ]
        ]
    },
    {
        "id": "5e61a36eda8b4a99",
        "type": "function",
        "z": "6eda76ddd54bb83d",
        "name": "monitor_trigger",
        "func": "var temp_msg = {command: \"get\", topic: \"temperature\"};\nvar volt_msg = {command: \"get\", topic: \"voltage\"};\n\nreturn [temp_msg, volt_msg];",
        "outputs": 2,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 720,
        "y": 520,
        "wires": [
            [
                "666082da419756c0"
            ],
            [
                "666082da419756c0"
            ]
        ]
    },
    {
        "id": "678ebb8204b7e79e",
        "type": "join",
        "z": "6eda76ddd54bb83d",
        "name": "",
        "mode": "custom",
        "build": "object",
        "property": "payload",
        "propertyType": "msg",
        "key": "topic",
        "joiner": "\\n",
        "joinerType": "str",
        "accumulate": false,
        "timeout": "",
        "count": "2",
        "reduceRight": false,
        "reduceExp": "",
        "reduceInit": "",
        "reduceInitType": "",
        "reduceFixup": "",
        "x": 1130,
        "y": 520,
        "wires": [
            [
                "8f574330195a2854"
            ]
        ]
    },
    {
        "id": "79eff73203564295",
        "type": "ui_template",
        "z": "6eda76ddd54bb83d",
        "group": "2a0da9646edd80ab",
        "name": "monitor_table",
        "order": 0,
        "width": "0",
        "height": "0",
        "format": "<style>\n.dot {\n    height: 20px;\n    width: 20px;\n    background-color: #bbb;\n    border-radius: 50%;\n    display: inline-block;\n}\n\n.dot.false {\n    background-color: red;\n}\n\n.dot.true {\n    background-color: green;\n}\n\n/* The Dialog (background) */\n.dialog {\n    display: none; /* Hidden by default */\n    position: fixed; /* Stay in place */\n    z-index: 9999; /* Sit on top */\n    left: 0;\n    top: 0;\n    width: 100%; /* Full width */\n    height: 100%; /* Full height */\n    overflow: auto; /* Enable scroll if needed */\n    -webkit-transform: translateZ(0px);\n    -webkit-transform: translate3d(0,0,0);\n    -webkit-perspective: 1000;\n}\n\n.dialog_content {\n    position: absolute;\n    background-color: #fff;\n    left: calc(50% - 170px);\n    top: 30px;\n    border-radius: 10px;\n    padding: 0;\n    box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19);\n    -webkit-animation-name: animatetop;\n    animation-name: animatetop;\n    animation-duration: 0.4s;\n}\ntitle {\n    margin:10px;\n    font-size: 20px;\n}\n/* Media query for smartphones (to Fix?) */\n@media only screen and (min-device-width : 375px) and (max-device-width : 667px) { \n    .dialog_content {\n    margin-top: 5%;\n    margin-left: 5%;\n}\n}\n\n/* Add Animation */\n@-webkit-keyframes animatetop {\n    from {top: -300px; opacity: 0} \n    to {top: 0; opacity: 1}\n}\n\n@keyframes animatetop {\n    from {top: -300px; opacity: 0}\n    to {top: 0; opacity: 1}\n}\n\n/* Dialog Header */\n.dialog_header {\n    padding: 2px 16px;\n    background-color: #03A9F4;\n    border-radius: 10px 10px 0 0;\n    color: white;\n    height: 40px;\n}\n\n/* Dialog Body */\n.dialog_body {padding: 5px;}\n\n/* The Close Button */\n.close {\n    color: #fff;\n    float: right;\n    font-size: 28px;\n    font-weight: bold;\n    cursor: pointer;\n}\n\n.close:hover,\n.close:focus {\n    color: #1565C0;\n    text-decoration: none;\n    cursor: pointer;\n}\n\n/* Number container */\n.btn_box{\n    margin: 5px;\n}\n\n/* Buttons style */\n.btn {\n    min-height: 40px;\n    min-width: 80px;\n    font-weight: bold;\n    margin: 0px 10px 10px 0px;\n    box-shadow: 4px 4px 6px 0 #dadada;\n    background-color: #29B6F6;\n    color: #29B6F6;\n}\n\n.btn:not([disabled]):hover {\n    background-color: #03A9F4;\n}\n</style>\n\n\n<div >\n    <table style=\"width: 100%;\">\n        <tr>\n            <td style=\"width: 50%\">\n                CPU Temp.:\n            </td>\n            <td align=\"left\">\n                {{tempCpu}}\n            </td>\n        </tr>\n        <tr>\n            <td style=\"width: 50%\">\n                System Temp.:\n            </td>\n            <td align=\"left\">\n                {{tempSystem}}\n            </td>\n        </tr>\n        <tr>\n            <td style=\"width: 50%\">\n                3.3V:\n            </td>\n            <td align=\"left\">\n                {{v33}}\n            </td>\n        </tr>\n        <tr>\n            <td style=\"width: 50%\">\n                +3.3V:\n            </td>\n            <td align=\"left\">\n                {{v33sb}}\n            </td>\n        </tr>\n        <tr>\n            <td style=\"width: 50%\">\n                5V:\n            </td>\n            <td align=\"left\">\n                {{v5}}\n            </td>\n        </tr>\n        <tr>\n            <td style=\"width: 50%\">\n                +5V:\n            </td>\n            <td align=\"left\">\n                {{v5sb}}\n            </td>\n        </tr>\n        <tr>\n            <td style=\"width: 50%\">\n                VBAT:\n            </td>\n            <td align=\"left\">\n                {{vbat}}\n            </td>\n        </tr>\n    </table>\n</div>\n\n\n<script>\n\n(function(scope) {\n    scope.tempCpu = \"\";\n    scope.tempSystem = \"\";\n    scope.v33 = \"\";\n    scope.v33sb = \"\";\n    scope.v5 = \"\";\n    scope.v5sb = \"\";\n    scope.vbat = \"\";\n\n    scope.$watch('msg', function(msg) {\n        if (msg && msg.payload) {\n            scope.tempCpu = msg.payload.temperature.Temp_Cpu;\n            scope.tempSystem = msg.payload.temperature.Temp_System;\n            scope.v33 = msg.payload.voltage.Voltage_3V3;\n            scope.v33sb = msg.payload.voltage.Voltage_3V3VSB;\n            scope.v5 = msg.payload.voltage.Voltage_5V;\n            scope.v5sb = msg.payload.voltage.Voltage_5VSB;\n            scope.vbat = msg.payload.voltage.Voltage_VBAT;\n        }\n    });\n})(scope);\n</script>\n",
        "storeOutMessages": false,
        "fwdInMessages": false,
        "resendOnRefresh": false,
        "templateScope": "local",
        "className": "",
        "x": 940,
        "y": 580,
        "wires": [
            []
        ]
    }
]