Categories
Uncategorized

Batrium node-red JSON

For use with ingesting Batrium UDP data into node-red

[
    {
        "id": "383cb2f7.2caede",
        "type": "udp in",
        "z": "e6fd3a1c.5e9548",
        "name": "listener",
        "iface": "",
        "port": "18542",
        "ipv": "udp4",
        "multicast": "false",
        "group": "",
        "datatype": "buffer",
        "x": 50,
        "y": 40,
        "wires": [
            [
                "1454f5c0.1322ca"
            ]
        ]
    },
    {
        "id": "1454f5c0.1322ca",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "All Message Type numbers to Topic",
        "func": "msg.Topic = (msg.payload[2].toString(16).toUpperCase() + msg.payload[1].toString(16).toUpperCase())\nreturn\tmsg;\t\t\n\t\t\t\n",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "x": 280,
        "y": 40,
        "wires": [
            [
                "d1a55ffb.c877a",
                "2af1bf8b.3e7b5"
            ]
        ]
    },
    {
        "id": "d1a55ffb.c877a",
        "type": "switch",
        "z": "e6fd3a1c.5e9548",
        "name": "Split the messages by type",
        "property": "Topic",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "415A",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "4232",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "3E32",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "3F33",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "4732",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "4932",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "6131",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "5732",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "4032",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "5432",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "7857",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "5632",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "4A35",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "4B35",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "4C33",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "4D33",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "5334",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "4F33",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "5033",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "5158",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "5258",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "4E58",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "5831",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "6831",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "5431",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "4732",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "4d34",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "6132",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 28,
        "x": 160,
        "y": 320,
        "wires": [
            [
                "9781b06a.53081"
            ],
            [
                "86897149.75de7"
            ],
            [
                "8f7d9f6b.5e7fa"
            ],
            [
                "7c28d81b.c0dd38"
            ],
            [],
            [
                "d1133f4a.3ef44"
            ],
            [
                "d2fa3827.0fb158"
            ],
            [
                "40d3fdc.2a54504"
            ],
            [
                "6ba51319.a7a48c"
            ],
            [
                "1704d7ce.245b58"
            ],
            [
                "aeea1ecd.3c858"
            ],
            [
                "122c8b3f.160005"
            ],
            [
                "bc35aeeb.93ab7"
            ],
            [
                "31f8d71a.f97f68"
            ],
            [
                "6bbf2b60.9ce744"
            ],
            [
                "a7cdb5ee.7c66c8"
            ],
            [
                "bc74a308.cfe11"
            ],
            [
                "a3320528.870448"
            ],
            [
                "84398b42.b2f578"
            ],
            [
                "66113e17.06931"
            ],
            [
                "d0a120ad.f8edd"
            ],
            [
                "3f60dd09.a9d822"
            ],
            [
                "672f0abe.f9af24"
            ],
            [
                "fa326eca.690b8"
            ],
            [
                "15f71030.bd9eb"
            ],
            [
                "34dd4fa2.32065"
            ],
            [
                "17a67e5b.e13952"
            ],
            [
                "e69dec4b.f16a1"
            ]
        ]
    },
    {
        "id": "ca12341f.fde6e8",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 1650,
        "y": 640,
        "wires": []
    },
    {
        "id": "fbba11c0.1f358",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 390,
        "y": 700,
        "wires": []
    },
    {
        "id": "bfddb91d.2b2a98",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 1650,
        "y": 140,
        "wires": []
    },
    {
        "id": "5feebe37.b27b2",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 1650,
        "y": 880,
        "wires": []
    },
    {
        "id": "49be9953.d21e48",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "d": true,
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 390,
        "y": 1140,
        "wires": []
    },
    {
        "id": "22e7b26a.4c54ae",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 390,
        "y": 740,
        "wires": []
    },
    {
        "id": "ea787f02.584ab",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "d": true,
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 390,
        "y": 1100,
        "wires": []
    },
    {
        "id": "aeea1ecd.3c858",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Msg_7857_HwShuntMetrics",
        "func": "var Packet = global.get('binary_parser');\nvar buf = msg.payload;\n\nvar typea = new Packet()\n\t\t.skip(8)\n\t\t.uint8('ShuntSocCycles')  \n\t\t.uint32le('RecentTimeAcculmSave') \t// Epoch\n\t\t.uint32le('RecentTimeSocLoRecal') \t// Epoch\n\t\t.uint32le('RecentTimeSocHiRecal') \t// Epoch\n\t\t.uint32le('RecentTimeSocCountLo') \t// Epoch\n\t\t.uint32le('RecentTimeSocCountHi') \t// Epoch\n\t\t.uint8(  'hasShuntSocCountLo') \t\t// boolean 0 = Off , 1 = On\n\t\t.uint8(  'hasShuntSocCountHi') \t\t// boolean 0 = Off , 1 = On\n\t\t.int16le('EstDurationToFullmins') \n\t\t.int16le('EstDurationToEmptymins') \n\t\t.floatle('ShuntAcculmAvgCharge',\t{ formatter: (x) => {return x/1000;}})\t// Ah\n\t\t.floatle('ShuntAcculmAvgDischg',\t{ formatter: (x) => {return x/1000;}})\t// Ah\n\t\t.floatle('ShuntAcculmAvgNett',\t\t{ formatter: (x) => {return x/1000;}})\t// Ah\n\t\t.uint32le('ShuntSerialNo') \n\t\t.uint32le('ShuntManuCode') \n\t\t.int16le('ShuntPartNum')\n\t\t.int16le('ShuntVersCode')\n\t\t\n\n  \nmsg.payload = typea.parse(buf);\n\n// convert date(s)\nmsg.payload.RecentTimeAcculmSave = new Date(msg.payload.RecentTimeAcculmSave*1000);\nmsg.payload.RecentTimeSocLoRecal = new Date(msg.payload.RecentTimeSocLoRecal*1000);\nmsg.payload.RecentTimeSocHiRecal = new Date(msg.payload.RecentTimeSocHiRecal*1000);\nmsg.payload.RecentTimeSocCountLo = new Date(msg.payload.RecentTimeSocCountLo*1000);\nmsg.payload.RecentTimeSocCountHi = new Date(msg.payload.RecentTimeSocCountHi*1000);\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 860,
        "y": 840,
        "wires": [
            [
                "90437fe0.fcd83"
            ]
        ]
    },
    {
        "id": "df5c7d37.bd20b",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 1650,
        "y": 840,
        "wires": []
    },
    {
        "id": "7c28d81b.c0dd38",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Msg_3f33_StatusFast",
        "func": "var Packet = global.get('binary_parser');\nvar buf = msg.payload;\n\nvar typea = new Packet()\n\t\t.skip(8)\n\t\t.uint8('CmuPollerMode') \t    \n\t\t.uint8('CmuTxAckCount')            // Cellmon TX Acknowledgement Count\n\t\t.uint8('CmuTxOpStatusNodeId')      // Cellmon TX Operating Status Node ID\n\t\t.uint8('CmuTxOpStatusUSN')         // Cellmon TX Operating Status Universal Serial Number\n\t\t.uint8('CmuTxOpParamNodeId')       // Cellmon TX Parameter Node ID\n\t\t.int16le('GroupMinCellVolt',\t\t{ formatter: (x) => {return x/1000;}})\n\t\t.int16le('GroupMaxCellVolt',\t\t{ formatter: (x) => {return x/1000;}})\t\t\n\t\t.uint8('GroupMinCellTemp',\t\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint8('GroupMaxCellTemp',\t\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint8('CmuRxOpStatusNodeId')\n\t\t.uint8('CmuRxOpStatusGroupAck')\n\t\t.uint8('CmuRxOpStatusUSN')\n\t\t.uint8('CmuRxOpParamNodeId')\n\t\t.uint8('SystemOpStatus') \n\t\t.uint8('SystemAuthMode') \n\t\t.int16le('SupplyVolt',\t\t\t\t{ formatter: (x) => {return x/100;}})\n\t\t.uint8('AmbientTemp',\t\t\t\t{ formatter: (x) => {return x-40;}})   // temperature ºC\n\t\t.uint32le('SystemTime') // Epoch\n\t\t.uint8('ShuntSOC', \t\t\t\t\t{ formatter: (x) => {return x/2-5;}})  // percent\n\t\t.uint8('ShuntTemp',\t\t\t\t\t{ formatter: (x) => {return x-40;}})   // temperature ºC\n\t\t.floatle('NomCapacityToFull',\t\t{ formatter: (x) => {return x/1000;}}) // Ah\n\t\t.floatle('NomCapacityToEmpty',\t\t{ formatter: (x) => {return x/1000;}}) // Ah\n\t\t.uint8('ShuntPollerMode') \n\t\t.uint8('ShuntStatus') /* Choices\n\t\t\t\tIdle Start = 0,\n\t\t\t\tIdle = 1,\n\t\t\t\tSync Start = 2,\n\t\t\t\tSync Running = 3,\n\t\t\t\tNormal = 4,\n\t\t\t\tShuntMon2 SetupStart = 5,\n\t\t\t\tShuntMon2 SetupRunning = 6,\n\t\t\t\tShuntMon2 Normal = 7, */\n\t\t.uint8('hasShuntLoSocRecal')\t\t// boolean 0 = Off , 1 = On\n\t\t.uint8('hasShuntHiSocRecal') \t\t// boolean 0 = Off , 1 = On\n\t\t//  shunt.hasShuntOkSocRange = !(shunt.hasShuntLoSocRecal || shunt.hasShuntHiSocRecal);\n\t\t.uint8('ExpansionOutputFet5') \t\t// boolean 0 = Off , 1 = On\n\t\t.uint8('ExpansionOutputFet6') \t\t// boolean 0 = Off , 1 = On\n\t\t.uint8('ExpansionOutputFet7') \t\t// boolean 0 = Off , 1 = On\n\t\t.uint8('ExpansionOutputFet8') \t\t// boolean 0 = Off , 1 = On\n\t\t.uint8('ExpansionOutputRelay1') \t// boolean 0 = Off , 1 = On\n\t\t.uint8('ExpansionOutputRelay2') \t// boolean 0 = Off , 1 = On\n\t\t.uint8('ExpansionOutputRelay3') \t// boolean 0 = Off , 1 = On\n\t\t.uint8('ExpansionOutputRelay4') \t// boolean 0 = Off , 1 = On\n\t\t.int16le('ExpansionOutputPwm1') \n\t\t.int16le('ExpansionOutputPwm2') \n\t\t.uint8('ExpansionInput1') \t\t\t// boolean 0 = Off , 1 = On\n\t\t.uint8('ExpansionInput2') \t\t\t// boolean 0 = Off , 1 = On\n\t\t.uint8('ExpansionInput3') \t\t\t// boolean 0 = Off , 1 = On\n\t\t.uint8('ExpansionInput4') \t\t\t// boolean 0 = Off , 1 = On\n\t\t.uint8('ExpansionInput5') \n\t\t.int16le('ExpansionInputAIN1') \n\t\t.int16le('ExpansionInputAIN2') \n\t\t.floatle('MinBypassSession', \t\t{ formatter: (x) => {return x/1000;}}) // Ah\n\t\t.floatle('MaxBypassSession', \t\t{ formatter: (x) => {return x/1000;}}) // Ah\n\t\t.uint8('MinBypassSessionID')\n\t\t.uint8('MaxBypassSessionID')\n\t\t.uint8('RebalanceBypassExtra')  \t// boolean 0 = Off , 1 = On\n\t\t.int16le('RepeatCellVoltCounter') \n\n  \nmsg.payload = typea.parse(buf);\n\n// convert date(s)\nmsg.payload.SystemTime = new Date(msg.payload.SystemTime*1000);\n\n\nswitch(msg.payload.CmuPollerMode) {\n    case 0:\n        msg.payload.CmuPollerMode = \"Idle\";\n        break;\n    case 1:\n        msg.payload.CmuPollerMode = \"Normal\";\n        break;\n    case 2:\n        msg.payload.CmuPollerMode = \" Start collection\";\n        break;\n    case 3:\n        msg.payload.CmuPollerMode = \"Collection running\";\n        break;\n    case 4:\n        msg.payload.CmuPollerMode = \"Start synchronisation\";\n        break;\n    case 5:\n        msg.payload.CmuPollerMode = \"Sync Running\";\n        break;\n    case 6:\n        msg.payload.CmuPollerMode = \"Start NetworkTest\";\n        break;\n    case 7:\n        msg.payload.CmuPollerMode = \"NetworkTest running\";\n        break;\n    case 8:\n        msg.payload.CmuPollerMode = \"Start BypassTest\";\n        break;\n    case 9:\n        msg.payload.CmuPollerMode = \"BypassTest running\";\n        break;\n    case 10:\n        msg.payload.CmuPollerMode = \"Start Reboot All\";\n        break;\n    case 11:\n        msg.payload.CmuPollerMode = \" Reboot All devices\";\n        break;\n    case 12:\n        msg.payload.CmuPollerMode = \" Start Simulator\";\n        break;\n    case 13:\n        msg.payload.CmuPollerMode = \"Simulator running\";\n        break;\n    default:\n        msg.payload.CmuPollerMode = \"Buggered\";\n}\n\nswitch(msg.payload.SystemOpStatus) {\n    case 0:\n        msg.payload.SystemOpStatus = \"Timeout\";\n        break;\n    case 1:\n        msg.payload.SystemOpStatus = \"Idle\";\n        break;\n    case 2:\n        msg.payload.SystemOpStatus = \"Charging\";\n        break;\n    case 3:\n        msg.payload.SystemOpStatus = \"Discharging\";\n        break;\n    case 4:\n        msg.payload.SystemOpStatus = \"Full\";\n        break;\n    case 5:\n        msg.payload.SystemOpStatus = \"Empty\";\n        break;\n    case 6:\n        msg.payload.SystemOpStatus = \"Simulator\";\n        break;\n    case 7:\n        msg.payload.SystemOpStatus = \"CriticalPending\";\n        break;\n    case 8:\n        msg.payload.SystemOpStatus = \"CriticalOffline\";\n        break;\n    case 9:\n        msg.payload.SystemOpStatus = \"MqttOffline\";\n        break;\n    case 10:\n        msg.payload.SystemOpStatus = \"AuthSetup\";\n        break;\n    case 11:\n        msg.payload.SystemOpStatus = \"Shunt Timeout\";\n        break;\n    default:\n        msg.payload.SystemOpStatus = \"Buggered\";\n}\n\nswitch(msg.payload.SystemAuthMode) {\n    case 0:\n        msg.payload.SystemAuthMode = \"Default\";\n        break;\n    case 1:\n        msg.payload.SystemAuthMode = \"Technician\";\n        break;\n    case 2:\n        msg.payload.SystemAuthMode = \"Factory\";\n        break;\n    default:\n        msg.payload.SystemAuthMode = \"Buggered\";\n}\n\nswitch(msg.payload.ShuntPollerMode) {\n    case 0:\n        msg.payload.ShuntPollerMode = \"Idle Start\";\n        break;\n    case 1:\n        msg.payload.ShuntPollerMode = \"Idle\";\n        break;\n    case 2:\n        msg.payload.ShuntPollerMode = \"Sync Start\";\n        break;\n    case 3:\n        msg.payload.ShuntPollerMode = \"Sync Running\";\n        break;\n    case 4:\n        msg.payload.ShuntPollerMode = \"Normal\";\n        break;\n    case 5:\n        msg.payload.ShuntPollerMode = \"ShuntMon2 SetupStart\";\n        break;\n    case 6:\n        msg.payload.ShuntPollerMode = \"ShuntMon2 SetupRunning\";\n        break;\n    case 7:\n        msg.payload.ShuntPollerMode = \"ShuntMon2 Normal\";\n        break;\n    default:\n        msg.payload.ShuntPollerMode = \"Buggered\";\n}\n\nswitch(msg.payload.ShuntStatus) {\n    case 0:\n        msg.payload.ShuntStatus = \"Timeout\";\n        break;\n    case 1:\n        msg.payload.ShuntStatus = \"Discharging\";\n        break;\n    case 2:\n        msg.payload.ShuntStatus = \"Idle\";\n        break;\n    case 4:\n        msg.payload.ShuntStatus = \"Charging\";\n        break;\n    default:\n        msg.payload.ShuntStatus = \"Buggered\";\n}\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "x": 840,
        "y": 640,
        "wires": [
            [
                "ca12341f.fde6e8",
                "8445ce7c.09028",
                "b2ab7d4c.b3ddd",
                "6476769.7ee5988",
                "63dc95b5.2a2dcc",
                "68635fb7.0529d"
            ]
        ]
    },
    {
        "id": "9781b06a.53081",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Msg_415a_CellNodeStatus",
        "func": "var Packet = global.get('binary_parser');\nvar buf = msg.payload;\n\nvar typea = new Packet()\n\t\t.uint8('ID')\n                .uint8('USN')\n                .int16le('MinCellVolt',                 { formatter: (x) => {return x/1000;}})\n                .int16le('MaxCellVolt',                 { formatter: (x) => {return x/1000;}})\n                .uint8('MinCellTemp',                   { formatter: (x) => {return x-40;}}) // temperature ºC\n                .uint8('BypassTemp',                    { formatter: (x) => {return x-40;}}) // temperature ºC\n                .int16le('BypassAmp',                   { formatter: (x) => {return x/1000;}})\n                .uint8('Status'); /* Choices NodeStatuses\n\t\t\t\t\t\tNone = 0,\n\t\t\t\t\t\tHighVolt = 1,\n\t\t\t\t\t\tHighTemp = 2,\n\t\t\t\t\t\tOk = 3,\n\t\t\t\t\t\tTimeout = 4,\n\t\t\t\t\t\tLowVolt = 5,\n\t\t\t\t\t\tDisabled = 6,\n\t\t\t\t\t\tInBypass = 7,\n\t\t\t\t\t\tInitialBypass = 8,\n\t\t\t\t\t\tFinalBypass = 9,\n\t\t\t\t\t\tMissingSetup = 10,\n\t\t\t\t\t\tNoConfig = 11,\n\t\t\t\t\t\tCellOutLimits = 12, */\n/*\n\t\tvar status = new Packet()\n\t\t.skip(8)\n\t\t.uint8('CmuRxOpStatusNodeID')\n\t\t.uint8('Records')\n\t\t.uint8('FirstNodeID')\n\t\t.uint8('LastNodeID')\n\t\t.array('nodes', {\n\t\t\ttype : Packet(),\n\t\t\tlength : 'Records'\n\t\t})\n*/\n  \nmsg.payload = typea.parse(buf);\n\nswitch(msg.payload.Status) {\n    case 0:\n        msg.payload.Status = \"None\";\n        break;\n    case 1:\n        msg.payload.Status = \"HighVolt\";\n        break;\n    case 2:\n        msg.payload.Status = \"HighTemp\";\n        break;\n    case 3:\n        msg.payload.Status = \"Ok\";\n        break;\n    case 4:\n        msg.payload.Status = \"Timeout\";\n        break;\n    case 5:\n        msg.payload.Status = \"LowVolt\";\n        break;\n    case 6:\n        msg.payload.Status = \"Disabled\";\n        break;\n    case 7:\n        msg.payload.Status = \"InBypass\";\n        break;\n    case 8:\n        msg.payload.Status = \"InitialBypass\";\n        break;\n    case 9:\n        msg.payload.Status = \"FinalBypass\";\n        break;\n    case 10:\n        msg.payload.Status = \"MissingSetup\";\n        break;\n    case 11:\n        msg.payload.Status = \"NoConfig\";\n        break;\n    case 12:\n        msg.payload.Status = \"CellOutLimits\";\n        break;\n    default:\n        msg.payload.Status = \"Buggered\";\n}\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "x": 860,
        "y": 880,
        "wires": [
            [
                "5feebe37.b27b2"
            ]
        ]
    },
    {
        "id": "ad8acc8c.9a174",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 1650,
        "y": 960,
        "wires": []
    },
    {
        "id": "8f7d9f6b.5e7fa",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Msg_3e32_StatusRapid",
        "func": "var Packet = global.get('binary_parser');\nvar buf = msg.payload;\n\nvar typea = new Packet()\n\t\t.skip(8)\n\t\t.int16le('MinCellVolt',\t\t{ formatter: (x) => {return x/1000;}})\n\t\t.int16le('MaxCellVolt',\t\t{ formatter: (x) => {return x/1000;}})\n\t\t.uint8('MinCellVoltId')\n\t\t.uint8('MaxCellVoltId')\n\t\t.uint8('MinCellTemp',\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint8('MaxCellTemp',\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint8('MinCellTempId')\n\t\t.uint8('MaxCellTempId')\n\t\t.int16le('MinBypassAmp', \t{ formatter: (x) => {return x/1000;}})\n\t\t.int16le('MaxBypassAmp', \t{ formatter: (x) => {return x/1000;}})\n\t\t.uint8('MinBypassAmpId')\n\t\t.uint8('MaxBypassAmpId')\n\t\t.uint8('MinBypassTemp',\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint8('MaxBypassTemp',\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint8('MinBypassTempId',\t{ formatter: (x) => {return x-40;}})\n\t\t.uint8('MaxBypassTempId',\t{ formatter: (x) => {return x-40;}})\n\t\t.int16le('AvgCellVolt',   \t{ formatter: (x) => {return x/1000;}})\n\t\t.uint8('AvgCellTemp',    \t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint8('NumOfCellsAboveInitialBypass')\n\t\t.uint8('NumOfCellsAboveFinalBypass')\n\t\t.uint8('NumOfCellsInBypass')\n\t\t.uint8('NumOfCellsOverdue')\n\t\t.uint8('NumOfCellsActive')\n\t\t.uint8('NumOfCellsInSystem')\n\t\t.uint8('CmuTxOpStatusId')\n\t\t.uint8('CmuRxOpStatusId')\n\t\t.uint8('CmuRxOpStatusUSN')\n\t\t.int16le('ShuntVoltage',\t{ formatter: (x) => {return x/100;}})  // voltage\n\t\t.floatle('ShuntCurrent',\t{ formatter: (x) => {return x/1000;}}) // amp\n\t\t.floatle('ShuntPowerVA',\t{ formatter: (x) => {return x/1000;}}) // kW \n\n  \nmsg.payload = typea.parse(buf);\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 850,
        "y": 140,
        "wires": [
            [
                "bfddb91d.2b2a98",
                "b7222b59.93edf8",
                "76bfaed9.eb6",
                "8fce0a5e.09d718",
                "ab145d35.a525d",
                "739bdfbd.80809"
            ]
        ]
    },
    {
        "id": "86897149.75de7",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Msg_4232_CellNodeFull",
        "func": "var Packet = global.get('binary_parser');\nvar buf = msg.payload;\n\nvar typea = new Packet()\n\t\t.skip(8)\n\t\t.uint8('ID')\n\t\t.uint8('USN')\n\t\t.int16le('MinCellVolt',\t\t\t{ formatter: (x) => {return x/1000;}})\n\t\t.int16le('MaxCellVolt',\t\t\t{ formatter: (x) => {return x/1000;}})\n\t\t.uint8('MinCellTemp',\t\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint8('BypassTemp',\t\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.int16le('BypassAmp', \t\t\t{ formatter: (x) => {return x/1000;}})\n\t\t.uint8('DataErrorCounter')\n\t\t.uint8('ResetCounter')\n\t\t.uint8('Status') /* Choices NodeStatuses\n\t\t\t\tNone = 0,\n\t\t\t\tHighVolt = 1,\n\t\t\t\tHighTemp = 2,\n\t\t\t\tOk = 3,\n\t\t\t\tTimeout = 4,\n\t\t\t\tLowVolt = 5,\n\t\t\t\tDisabled = 6,\n\t\t\t\tInBypass = 7,\n\t\t\t\tInitialBypass = 8,\n\t\t\t\tFinalBypass = 9,\n\t\t\t\tMissingSetup = 10,\n\t\t\t\tNoConfig = 11,\n\t\t\t\tCellOutLimits = 12, */\t\n\t\t.uint8('IsOverdue')\t\t\t\t// boolean 0 = Off , 1 = On\n\n\t\t.int16le('LoCellVoltAlert',\t\t{ formatter: (x) => {return x/1000;}})\n\t\t.int16le('HiCellVoltAlert',\t\t{ formatter: (x) => {return x/1000;}})\n\t\t.int16le('BypassVoltLevel',\t\t{ formatter: (x) => {return x/1000;}})\n\t\t.int16le('BypassAmpLimit',\t\t{ formatter: (x) => {return x/1000;}})\n\t\t.uint8('BypassTempLimit',\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint8('HiCellTempAlert',\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint8('RawVoltCalOffset')\n\t\t.int16le('FwVers')\n\t\t.int16le('HwVers')\n\t\t.int16le('BootVers')\n\t\t.uint32le('SerialNo')\t\n\t\t.uint32le('BypassInitialDate') \t// Epoch\n\t\t.floatle('BypassSessionAh',\t\t{ formatter: (x) => {return x/1000;}}) // Ah\n\t\t.uint8('RepeatCellV')\n\n  \nmsg.payload = typea.parse(buf);\n\n// convert date(s)\nmsg.payload.BypassInitialDate = new Date(msg.payload.BypassInitialDate*1000);\n\n\nswitch(msg.payload.Status) {\n    case 0:\n        msg.payload.Status = \"None\";\n        break;\n    case 1:\n        msg.payload.Status = \"HighVolt\";\n        break;\n    case 2:\n        msg.payload.Status = \"HighTemp\";\n        break;\n    case 3:\n        msg.payload.Status = \"Ok\";\n        break;\n    case 4:\n        msg.payload.Status = \"Timeout\";\n        break;\n    case 5:\n        msg.payload.Status = \"LowVolt\";\n        break;\n    case 6:\n        msg.payload.Status = \"Disabled\";\n        break;\n    case 7:\n        msg.payload.Status = \"InBypass\";\n        break;\n    case 8:\n        msg.payload.Status = \"InitialBypass\";\n        break;\n    case 9:\n        msg.payload.Status = \"FinalBypass\";\n        break;\n    case 10:\n        msg.payload.Status = \"MissingSetup\";\n        break;\n    case 11:\n        msg.payload.Status = \"NoConfig\";\n        break;\n    case 12:\n        msg.payload.Status = \"CellOutLimits\";\n        break;\n    default:\n        msg.payload.Status = \"Buggered\";\n}\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 850,
        "y": 920,
        "wires": [
            [
                "ad8acc8c.9a174",
                "b56a71fb.69c95"
            ]
        ]
    },
    {
        "id": "f29277f6.daa798",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 1650,
        "y": 760,
        "wires": []
    },
    {
        "id": "d1133f4a.3ef44",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Msg_4932_ControlRemoteStatus",
        "func": "var Packet = global.get('binary_parser');\nvar buf = msg.payload;\n\nvar typea = new Packet()\n\t\t.skip(8)\n\t\t.uint8('CanbusRxStatusTicks')  \n\t\t.uint8('CanbusRxUnknownTicks')  \n\t\t.uint8('CanbusTxCmdTicks')  \n\t\t.uint8(  'RemoteChargeActualCelcius', \t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.int16le('RemoteChargeTargetVolt')\n\t\t.int16le('RemoteChargeTargetAmp')\n\t\t.int16le('RemoteChargeTargetVA')\n\t\t.int16le('RemoteChargeActualVolt')\n\t\t.int16le('RemoteChargeActualAmp')\n\t\t.int16le('RemoteChargeActualVA')\n\t\t.uint32le('RemoteChargeActualFlag1')\n\t\t.uint32le('RemoteChargeActualFlag2')\n\t\t.uint32le('RemoteChargeActualRxTime') // Epoch\n\t\t.skip(1)\n\t\t.uint8(  'RemoteDishargeActualCelcius', \t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.int16le('RemoteDischargeTargetVolt')\n\t\t.int16le('RemoteDischargeTargetAmp')\n\t\t.int16le('RemoteDischargeTargetVA')\n\t\t.int16le('RemoteDischargeActualVolt')\n\t\t.int16le('RemoteDischargeActualAmp')\n\t\t.int16le('RemoteDischargeActualVA')\n\t\t.uint32le('RemoteDischargeActualFlag1')\n\t\t.uint32le('RemoteDischargeActualFlag2')\n\t\t.uint32le('RemoteDischargeActualRxTime') // Epoch\n  \nmsg.payload = typea.parse(buf);\n\n// convert date(s)\nmsg.payload.RemoteChargeActualRxTime = new Date(msg.payload.RemoteChargeActualRxTime*1000);\nmsg.payload.RemoteDischargeActualRxTime = new Date(msg.payload.RemoteDischargeActualRxTime*1000);\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 880,
        "y": 760,
        "wires": [
            [
                "f29277f6.daa798"
            ]
        ]
    },
    {
        "id": "10983267.223e1e",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 1650,
        "y": 800,
        "wires": []
    },
    {
        "id": "d2fa3827.0fb158",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Msg_6131_StatusComms",
        "func": "var Packet = global.get('binary_parser');\nvar buf = msg.payload;\n\nvar typea = new Packet()\n\t\t.skip(8)\n\t\t.uint32le('SystemTime') // Epoch\n\t\t.uint8('SystemOpStatus') /* Choices\n\t\t\t\tSimulator = 0,   \t  // LED = rainbow pulse\n\t\t\t\tIdle = 1,        \t  // LED = green slow pulse\n\t\t\t\tDischarging = 2, \t  // LED = green solid \n\t\t\t\tSoC Empty = 3,   \t  // LED = green double blink\n\t\t\t\tCharging = 4,    \t  // LED = blue slow pulse\n\t\t\t\tFull = 5,        \t  // LED = blue double blink\n\t\t\t\tTimeout = 6,     \t  // LED = red solid\n\t\t\t\tCritical Pending = 7, // LED = red fast pulse\n\t\t\t\tCritical Offline = 8, // LED = red slow pulse\n\t\t\t\tMqtt Offline = 9,     // LED = white blink\n\t\t\t\tAuth Setup = 10,      // LED = white solid\n\t\t\t\tShunt Timeout = 11,   // LED = red solid  \t*/\n\t\t.uint8('SystemAuthMode') /* Choices\n\t\t\t\tDefault = 0,\n\t\t\t\tTechnician = 1,\n\t\t\t\tFactory = 2, */\n\t\t.int16le('SystemAuthToken')\n\t\t.int16le('SystemAuthRejectTicks')\n\t\t.uint8('WifiState') /* Choices WifiOpStates\n\t\t\t\tBroadcast Start = 0,\n\t\t\t\tBroadcast Prep = 1,\n\t\t\t\tBroadcast TxSetup = 2,\n\t\t\t\tBroadcast Running = 3,\n\t\t\t\tUsbCmd Start = 4,\n\t\t\t\tUsbCmd Running = 5,\n\t\t\t\tUsbCmd PassThru = 6,\n\t\t\t\tUsbProg Start = 7,\n\t\t\t\tUsbProg Running = 8,\n\t\t\t\tUsbProg PassThru = 9,\n\t\t\t\tOffline Start = 10,\n\t\t\t\tOffline Running = 11,\n\t\t\t\tOffline Stop = 12,\n\t\t\t\tLimited Start = 13,\n\t\t\t\tLimited Prep = 14,\n\t\t\t\tLimited Running = 15,\n\t\t\t\tJoinAp Start = 16,\n\t\t\t\tJoinAp Running = 17,\t*/\t\t\n\t\t.uint8('WifiTxCmdTicks') \n\t\t.uint8('WifiRxCmdTicks') \n\t\t.uint8('WifiRxUnknownTicks') \n\t\t.uint8('CanbusOpStatus') /* Choices \n\t\t\t\t\n\t\t\t\t \t*/\t\t\n\t\t.uint8('CanbusRxStatusTicks')\n\t\t.uint8('CanbusRxUnknownTicks')\n\t\t.uint8('CanbusRxStatusTicks')\n\t\t.uint8('ShuntPollerMode') /* Choices ShuntPollerModes\n\t\t\t\tIdle Start = 0,\n\t\t\t\tIdle = 1,\n\t\t\t\tSync Start = 2,\n\t\t\t\tSync Running = 3,\n\t\t\t\tNormal = 4,\n\t\t\t\tShuntMon2 SetupStart = 5,\n\t\t\t\tShuntMon2 SetupRunning = 6,\n\t\t\t\tShuntMon2 Normal = 7, */\n\t\t.uint8('ShuntStatus') /* Choices  ShuntStatuses\n\t\t\t\tTimeout = 0,\n\t\t\t\tDischarging = 1,\n\t\t\t\tIdle = 2,\n\t\t\t\tCharging = 4 */\n\t\t.uint8('ShuntRxAmpTicks')\n\t\t.uint8('ShuntTxAmpTicks')\n\t\t.uint8('CmuPollerMode') \t    /* Choices\n\t\t\t\tIdle = 0,\n\t\t\t\tNormal = 1,\n\t\t\t\tCollection Start = 2,\n\t\t\t\tCollection Running = 3,\n\t\t\t\tSync Start = 4,\n\t\t\t\tSync Running = 5,\n\t\t\t\tNetworkTest Start = 6,\n\t\t\t\tNetworkTest Running = 9,\n\t\t\t\tBypassTest Start = 7,\n\t\t\t\tBypassTest Running = 8,\n\t\t\t\tRebootAll Start = 10,\n\t\t\t\tRebooting AllDevices = 11,\n\t\t\t\tSimulator Start = 12,\n\t\t\t\tSimulator Running = 13, */\n\t\t.uint8('CmuOpStatus') /* Choices */\n\t\t.uint8('CmuTxCmdTicks')\n\t\t\nmsg.payload = typea.parse(buf);\n\n\n// convert date(s)\nmsg.payload.SystemTime = new Date(msg.payload.SystemTime*1000);\n\nswitch(msg.payload.SystemOpStatus) {\n    case 0:\n        msg.payload.SystemOpStatus = \"Simulator\";\n        break;\n    case 1:\n        msg.payload.SystemOpStatus = \"Idle\";\n        break;\n    case 2:\n        msg.payload.SystemOpStatus = \"Discharging\";\n        break;\n    case 3:\n        msg.payload.SystemOpStatus = \"SoC Empty\";\n        break;\n    case 4:\n        msg.payload.SystemOpStatus = \"Charging\";\n        break;\n    case 5:\n        msg.payload.SystemOpStatus = \"Full\";\n        break;\n    case 6:\n        msg.payload.SystemOpStatus = \"Timeout\";\n        break;\n    case 7:\n        msg.payload.SystemOpStatus = \"Critical Pending\";\n        break;\n    case 8:\n        msg.payload.SystemOpStatus = \"Critical Offline\";\n        break;\n    case 9:\n        msg.payload.SystemOpStatus = \"Mqtt Offline\";\n        break;\n    case 10:\n        msg.payload.SystemOpStatus = \"Auth Setup\";\n        break;\n    case 11:\n        msg.payload.SystemOpStatus = \"Shunt Timeout\";\n        break;\n    default:\n        msg.payload.SystemOpStatus = \"Buggered\";\n}\n\nswitch(msg.payload.SystemAuthMode) {\n    case 0:\n        msg.payload.SystemAuthMode = \"Default\";\n        break;\n    case 1:\n        msg.payload.SystemAuthMode = \"Technician\";\n        break;\n    case 2:\n        msg.payload.SystemAuthMode = \"Factory\";\n        break;\n    default:\n        msg.payload.SystemAuthMode = \"Buggered\";\n}\n\nswitch(msg.payload.WifiState) {\n    case 0:\n        msg.payload.WifiState = \"Broadcast Start\";\n        break;\n    case 1:\n        msg.payload.WifiState = \"Broadcast Prep\";\n        break;\n    case 2:\n        msg.payload.WifiState = \"Broadcast TxSetup\";\n        break;\n    case 3:\n        msg.payload.WifiState = \"Broadcast Running\";\n        break;\n    case 4:\n        msg.payload.WifiState = \"UsbCmd Start\";\n        break;\n    case 5:\n        msg.payload.WifiState = \"UsbCmd Running\";\n        break;\n    case 6:\n        msg.payload.WifiState = \"UsbCmd PassThru\";\n        break;\n    case 7:\n        msg.payload.WifiState = \"UsbProg Start\";\n        break;\n    case 8:\n        msg.payload.WifiState = \"UsbProg Running\";\n        break;\n    case 9:\n        msg.payload.WifiState = \"UsbProg PassThru\";\n        break;\n    case 10:\n        msg.payload.WifiState = \"Offline Start\";\n        break;\n    case 11:\n        msg.payload.WifiState = \"Offline Running\";\n        break;\n    case 12:\n        msg.payload.WifiState = \"Offline Stop\";\n        break;\n    case 13:\n        msg.payload.WifiState = \"Limited Start\";\n        break;\n    case 14:\n        msg.payload.WifiState = \"Limited Prep\";\n        break;\n    case 15:\n        msg.payload.WifiState = \"Limited Running\";\n        break;\n    case 16:\n        msg.payload.WifiState = \"JoinAp Start\";\n        break;\n    case 17:\n        msg.payload.WifiState = \"JoinAp Running\";\n        break;\n    default:\n        msg.payload.WifiState = \"Buggered\";\n}\n\nswitch(msg.payload.ShuntPollerMode) {\n    case 0:\n        msg.payload.ShuntPollerMode = \"Idle Start\";\n        break;\n    case 1:\n        msg.payload.ShuntPollerMode = \"Idle\";\n        break;\n    case 2:\n        msg.payload.ShuntPollerMode = \"Sync Start\";\n        break;\n    case 3:\n        msg.payload.ShuntPollerMode = \"Sync Running\";\n        break;\n    case 4:\n        msg.payload.ShuntPollerMode = \"Normal\";\n        break;\n    case 5:\n        msg.payload.ShuntPollerMode = \"ShuntMon2 SetupStart\";\n        break;\n    case 6:\n        msg.payload.ShuntPollerMode = \"ShuntMon2 SetupRunning\";\n        break;\n    case 7:\n        msg.payload.ShuntPollerMode = \"ShuntMon2 Normal\";\n        break;\n    default:\n        msg.payload.ShuntPollerMode = \"Buggered\";\n}\n\nswitch(msg.payload.ShuntStatus) {\n    case 0:\n        msg.payload.ShuntStatus = \"Timeout\";\n        break;\n    case 1:\n        msg.payload.ShuntStatus = \"Discharging\";\n        break;\n    case 2:\n        msg.payload.ShuntStatus = \"Idle\";\n        break;\n    case 4:\n        msg.payload.ShuntStatus = \"Charging\";\n        break;\n    default:\n        msg.payload.ShuntStatus = \"Buggered\";\n}\n\nswitch(msg.payload.CmuPollerMode) {\n    case 0:\n        msg.payload.CmuPollerMode = \"Idle\";\n        break;\n    case 1:\n        msg.payload.CmuPollerMode = \"Normal\";\n        break;\n    case 2:\n        msg.payload.CmuPollerMode = \"Collection Start\";\n        break;\n    case 3:\n        msg.payload.CmuPollerMode = \"Collection Running\";\n        break;\n    case 4:\n        msg.payload.CmuPollerMode = \"Sync Start\";\n        break;\n    case 5:\n        msg.payload.CmuPollerMode = \"Sync Running\";\n        break;\n    case 6:\n        msg.payload.CmuPollerMode = \"NetworkTest Start\";\n        break;\n    case 7:\n        msg.payload.CmuPollerMode = \"NetworkTest Running\";\n        break;\n    case 8:\n        msg.payload.CmuPollerMode = \"BypassTest Start\";\n        break;\n    case 9:\n        msg.payload.CmuPollerMode = \"BypassTest Running\";\n        break;\n    case 10:\n        msg.payload.CmuPollerMode = \"RebootAll Start\";\n        break;\n    case 11:\n        msg.payload.CmuPollerMode = \"Rebooting AllDevices\";\n        break;\n    case 12:\n        msg.payload.CmuPollerMode = \"Simulator Start\";\n        break;\n    case 13:\n        msg.payload.CmuPollerMode = \"Simulator Running\";\n        break;\n    default:\n        msg.payload.CmuPollerMode = \"Buggered\";\n}\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 850,
        "y": 800,
        "wires": [
            [
                "10983267.223e1e"
            ]
        ]
    },
    {
        "id": "3b6043f2.c8f11c",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 1650,
        "y": 380,
        "wires": []
    },
    {
        "id": "40d3fdc.2a54504",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "d": true,
        "name": "Msg_5732_SystemDiscovery",
        "func": "var Packet = global.get('binary_parser');\nvar buf = msg.payload;\n\nvar typea = new Packet()\n\t\t.skip(8)\n\t\t.string('SystemCode', \t{ encoding: 'ascii', length: 8 })\n\t\t.int16le('SystemFirmwareVersion')\n\t\t.int16le('SystemHardwareVersion')\n\t\t.int32le('SystemTime') // Epoch\n\t\t.uint8('SystemOpStatus') /* Choices\n\t\t\t\tSimulator = 0,   \t  // LED = rainbow pulse\n\t\t\t\tIdle = 1,        \t  // LED = green slow pulse\n\t\t\t\tDischarging = 2, \t  // LED = green solid \n\t\t\t\tSoC Empty = 3,   \t  // LED = green double blink\n\t\t\t\tCharging = 4,    \t  // LED = blue slow pulse\n\t\t\t\tFull = 5,        \t  // LED = blue double blink\n\t\t\t\tTimeout = 6,     \t  // LED = red solid\n\t\t\t\tCritical Pending = 7, // LED = red fast pulse\n\t\t\t\tCritical Offline = 8, // LED = red slow pulse\n\t\t\t\tMqtt Offline = 9,     // LED = white blink\n\t\t\t\tAuth Setup = 10,      // LED = white solid\n\t\t\t\tShunt Timeout = 11,   // LED = red solid  \t*/\n\t\t.uint8('SystemAuthMode') /* Choices\n\t\t\t\tDefault \t= 0,\n\t\t\t\tTechnician \t= 1,\n\t\t\t\tFactory \t= 2, */\n\t\t.uint8('CriticalBatOkState')    // 0 = Off , 1 = On\n\t\t.uint8('ChargePowerRateState')  /* Choices\n\t\t\t\tOff \t\t\t= 0,\n\t\t\t\tLimited Power \t= 2,\n\t\t\t\tNormal Power  \t= 4, */\n\t\t.uint8('DischargePowerRateState') /* Choices\n\t\t\t\tOff \t\t\t= 0,\n\t\t\t\tLimited Power \t= 2,\n\t\t\t\tNormal Power  \t= 4, */\n\t\t.uint8('HeatOnState') \t\t\t// 0 = Off , 1 = On\n\t\t.uint8('CoolOnState') \t\t\t// 0 = Off , 1 = On\n\t\t.int16le('MinCellVolt', \t{ formatter: (x) => {return x/1000;}})\n\t\t.int16le('MaxCellVolt', \t{ formatter: (x) => {return x/1000;}})\n\t\t.int16le('AvgCellVolt', \t{ formatter: (x) => {return x/1000;}})\n\t\t.uint8('MinCellTemp', \t\t{ formatter: (x) => {return x-40;}})     // temperature ºC\n\t\t.uint8('NumOfCellsActive')\n\t\t.uint8('CmuRxOpStatusUSN')\n\t\t.uint8('CmuPollerMode')  /* Choices\n\t\t\t\tIdle = 0,\n\t\t\t\tNormal = 1,\n\t\t\t\tCollection Start = 2,\n\t\t\t\tCollection Running = 3,\n\t\t\t\tSync Start = 4,\n\t\t\t\tSync Running = 5,\n\t\t\t\tNetworkTest Start = 6,\n\t\t\t\tNetworkTest Running = 9,\n\t\t\t\tBypassTest Start = 7,\n\t\t\t\tBypassTest Running = 8,\n\t\t\t\tRebootAll Start = 10,\n\t\t\t\tRebooting AllDevices = 11,\n\t\t\t\tSimulator Start = 12,\n\t\t\t\tSimulator Running = 13, */\n\t\t.uint8('ShuntSOC',\t\t\t{ formatter: (x) => {return x/2-5;}})    // percent\n\t\t.int16le('ShuntVoltage',\t{ formatter: (x) => {return x/100;}})\n\t\t.floatle('ShuntCurrent',\t{ formatter: (x) => {return x/1000;}})\n\t\t.uint8('ShuntStatus') /* Choices\n\t\t\t\tTimeout = 0,\n\t\t\t\tDischarging = 1,\n\t\t\t\tIdle = 2,\n\t\t\t\tCharging = 4 */\n\t\t.uint8('ShuntRxAmpTicks')\n  \nmsg.payload = typea.parse(buf);\n\n// convert date(s)\nmsg.payload.SystemTime = new Date(msg.payload.SystemTime*1000);\n\nswitch(msg.payload.SystemOpStatus) {\n    case 0:\n        msg.payload.SystemOpStatus = \"Timeout\";\n        break;\n    case 1:\n        msg.payload.SystemOpStatus = \"Idle\";\n        break;\n    case 2:\n        msg.payload.SystemOpStatus = \"Charging\";\n        break;\n    case 3:\n        msg.payload.SystemOpStatus = \"Discharging\";\n        break;\n    case 4:\n        msg.payload.SystemOpStatus = \"Full\";\n        break;\n    case 5:\n        msg.payload.SystemOpStatus = \"Empty\";\n        break;\n    case 6:\n        msg.payload.SystemOpStatus = \"Simulator\";\n        break;\n    case 7:\n        msg.payload.SystemOpStatus = \"CriticalPending\";\n        break;\n    case 8:\n        msg.payload.SystemOpStatus = \"CriticalOffline\";\n        break;\n    case 9:\n        msg.payload.SystemOpStatus = \"MqttOffline\";\n        break;\n    case 10:\n        msg.payload.SystemOpStatus = \"AuthSetup\";\n        break;\n    case 11:\n        msg.payload.SystemOpStatus = \"Shunt Timeout\";\n        break;\n    default:\n        msg.payload.SystemOpStatus = \"Buggered\";\n}\n\nswitch(msg.payload.SystemAuthMode) {\n    case 0:\n        msg.payload.SystemAuthMode = \"Default\";\n        break;\n    case 1:\n        msg.payload.SystemAuthMode = \"Technician\";\n        break;\n    case 2:\n        msg.payload.SystemAuthMode = \"Factory\";\n        break;\n    default:\n        msg.payload.SystemAuthMode = \"Buggered\";\n}\n\nswitch(msg.payload.ChargePowerRateState) {\n    case 0:\n        msg.payload.ChargePowerRateState = \"Off\";\n        break;\n    case 2:\n        msg.payload.ChargePowerRateState = \"Limited Power\";\n        break;\n    case 4:\n        msg.payload.ChargePowerRateState = \"Normal Power\";\n        break;\n    default:\n        msg.payload.ChargePowerRateState = \"Buggered\";\n}\n\nswitch(msg.payload.DischargePowerRateState) {\n    case 0:\n        msg.payload.DischargePowerRateState = \"Off\";\n        break;\n    case 2:\n        msg.payload.DischargePowerRateState = \"Limited Power\";\n        break;\n    case 4:\n        msg.payload.DischargePowerRateState = \"Normal Power\";\n        break;\n    default:\n        msg.payload.DischargePowerRateState = \"Buggered\";\n}\n\nswitch(msg.payload.CmuPollerMode) {\n    case 0:\n        msg.payload.CmuPollerMode = \"Idle\";\n        break;\n    case 1:\n        msg.payload.CmuPollerMode = \"Normal\";\n        break;\n    case 2:\n        msg.payload.CmuPollerMode = \" Start collection\";\n        break;\n    case 3:\n        msg.payload.CmuPollerMode = \"Collection running\";\n        break;\n    case 4:\n        msg.payload.CmuPollerMode = \"Start synchronisation\";\n        break;\n    case 5:\n        msg.payload.CmuPollerMode = \"Sync Running\";\n        break;\n    case 6:\n        msg.payload.CmuPollerMode = \"Start NetworkTest\";\n        break;\n    case 7:\n        msg.payload.CmuPollerMode = \"NetworkTest running\";\n        break;\n    case 8:\n        msg.payload.CmuPollerMode = \"Start BypassTest\";\n        break;\n    case 9:\n        msg.payload.CmuPollerMode = \"BypassTest running\";\n        break;\n    case 10:\n        msg.payload.CmuPollerMode = \"Start Reboot All\";\n        break;\n    case 11:\n        msg.payload.CmuPollerMode = \" Reboot All devices\";\n        break;\n    case 12:\n        msg.payload.CmuPollerMode = \" Start Simulator\";\n        break;\n    case 13:\n        msg.payload.CmuPollerMode = \"Simulator running\";\n        break;\n    default:\n        msg.payload.CmuPollerMode = \"Buggered\";\n}\n\nswitch(msg.payload.ShuntStatus) {\n    case 0:\n        msg.payload.ShuntStatus = \"Timeout\";\n        break;\n    case 1:\n        msg.payload.ShuntStatus = \"Discharging\";\n        break;\n    case 2:\n        msg.payload.ShuntStatus = \"Idle\";\n        break;\n    case 4:\n        msg.payload.ShuntStatus = \"Charging\";\n        break;\n    default:\n        msg.payload.ShuntStatus = \"Buggered\";\n}\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "x": 860,
        "y": 380,
        "wires": [
            [
                "3b6043f2.c8f11c"
            ]
        ]
    },
    {
        "id": "e321fbb8.b60e48",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 1650,
        "y": 420,
        "wires": []
    },
    {
        "id": "6ba51319.a7a48c",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Msg_4032_StatusSlow",
        "func": "var Packet = global.get('binary_parser');\nvar buf = msg.payload;\n\nvar typea = new Packet()\n \t\t.skip(8)\n\t\t.uint32le('SystemTime') \t\t\t// Epoch\n\t\t.uint8('IsProcessControl') \t\t\t// boolean 0 = Off , 1 = On\n\t\t.uint8('IsInitialStartup') \t\t\t// boolean 0 = Off , 1 = On\n\t\t.uint8('IgnoreWhenCellsOverdue') \t// boolean 0 = Off , 1 = On\n\t\t.uint8('IgnoreWhenShuntsOverdue') \t// boolean 0 = Off , 1 = On\n\t\t.uint8('MonitorDailySessionStats') \t// boolean 0 = Off , 1 = On\t\t\n\t\t.uint8('HwSystemSetupVers') \n\t\t.uint8('HwCellmonSetupVers') \n\t\t.uint8('HwShuntSetupVers') \n\t\t.uint8('HwExpansionSetupVers') \n\t\t.uint8('HwIntegrationSetupVers') \n\t\t.uint8('ControlCriticalSetupVers') \n\t\t.uint8('ControlChargeSetupVers')  \n\t\t.uint8('ControlDischargeSetupVers')  \t\t\n\t\t.uint8('ControlThermalSetupVers')  \n\t\t.uint8('ControlRemoteSetupVers')  \n\t\t.uint8('ControlSchedulerSetupVers') \t\t\t\n\t\t.int16le('EstDurationToFullmins') \n\t\t.int16le('EstDurationToEmptymins') \n\t\t.floatle('ShuntAcculmAvgCharge',\t{ formatter: (x) => {return x/1000;}}) // Ah\n\t\t.floatle('ShuntAcculmAvgDischg',\t{ formatter: (x) => {return x/1000;}}) // Ah\n\t\t.floatle('ShuntAcculmAvgNett',\t\t{ formatter: (x) => {return x/1000;}}) // Ah\n\t\t.uint8(  'hasShuntSocCountLo') \t\t// boolean 0 = Off , 1 = On\n\t\t.uint8(  'hasShuntSocCountHi') \t\t// boolean 0 = Off , 1 = On\t\t\n\t\t.uint32le('QuickSessRecentTime') \t// EPOCH\n\t\t.int16le('QuickSessNumOfRecords')\n\t\t.int16le('QuickSessMaxNumOfRecords')\n\t\t.skip(8) // acculmNett ADC counter \n\t\t.floatle('NomCapacityToEmpty',\t\t{ formatter: (x) => {return x/1000;}}) // Ah\n\t\t\nmsg.payload = typea.parse(buf);\n// convert date(s)\nmsg.payload.SystemTime = new Date(msg.payload.SystemTime*1000);\nmsg.payload.QuickSessRecentTime = new Date(msg.payload.QuickSessRecentTime*1000);\n\n\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "x": 840,
        "y": 420,
        "wires": [
            [
                "e321fbb8.b60e48",
                "9a44bb7a.474bd8"
            ]
        ]
    },
    {
        "id": "9a3c0c25.d705a",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 1650,
        "y": 500,
        "wires": []
    },
    {
        "id": "1704d7ce.245b58",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Msg_5432_DailySession",
        "func": "var Packet = global.get('binary_parser');\nvar buf = msg.payload;\n\nvar typea = new Packet()\n\t\t.skip(8)\n\t\t.int16le('DailySessionMinCellVolt',\t\t{ formatter: (x) => {return x/1000;}})\n\t\t.int16le('DailySessionMaxCellVolt',\t\t{ formatter: (x) => {return x/1000;}})\n\t\t.int16le('DailySessionMinSupplyVolt',\t{ formatter: (x) => {return x/100;}})\n\t\t.int16le('DailySessionMaxSupplyVolt',\t{ formatter: (x) => {return x/100;}})\n\t\t.uint8('DailySessionMinReportTemp',\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint8('DailySessionMaxReportTemp',\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.int16le('DailySessionMinShuntVolt',\t{ formatter: (x) => {return x/100;}})\n\t\t.int16le('DailySessionMaxShuntVolt',\t{ formatter: (x) => {return x/100;}})\n\t\t.uint8('DailySessionMinShuntSoc', \t\t{ formatter: (x) => {return (x-5)/2;}}) // percent\n\t\t.uint8('DailySessionMaxShuntSoc', \t\t{ formatter: (x) => {return (x-5)/2;}}) // percent\n\t\t.uint8('DailySessionThermalBandA',\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionThermalBandB',\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionThermalBandC',\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionThermalBandD',\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionThermalBandE',\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionThermalBandF',\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionThermalBandG',\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionThermalBandH',\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionSocBandA',\t\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionSocBandB',\t\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionSocBandC',\t\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionSocBandD',\t\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionSocBandE',\t\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionSocBandF',\t\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionSocBandG',\t\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionSocBandH',\t\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.int16le('DailySessionShuntPeakCharge',{ formatter: (x) => {return x/100;}}) // amps\n\t\t.int16le('DailySessionShuntPeakDischg',{ formatter: (x) => {return x/100;}}) // amps\n\t\t.uint8('DailySessionCriticalEvents')\n\t\t.int32le('DailySessionStartTime') \t// Epoch\n\t\t.int32le('DailySessionFinishTime')  // Epoch\n\t\t.floatle('DailySessionCumulShuntAhCharge',{ formatter: (x) => {return x/1000;}})  // Ah\n\t\t.floatle('DailySessionCumulShuntAhDischg',{ formatter: (x) => {return x/1000;}})  // Ah\n\t\t.floatle('DailySessionCumulShuntkWhCharge',{ formatter: (x) => {return x/1000;}}) // kWh\n\t\t.floatle('DailySessionCumulShuntkWhDischg',{ formatter: (x) => {return x/1000;}}) // kWh\n\t\t\n  \nmsg.payload = typea.parse(buf);\n\n// convert date(s)\nmsg.payload.DailySessionStartTime = new Date(msg.payload.DailySessionStartTime*1000);\nmsg.payload.DailySessionFinishTime = new Date(msg.payload.DailySessionFinishTime*1000);\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 850,
        "y": 500,
        "wires": [
            [
                "9a3c0c25.d705a",
                "684ac7ee.c50fc8",
                "7e92a896.171e58"
            ]
        ]
    },
    {
        "id": "122c8b3f.160005",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Msg_5632_LifetimeMetrics",
        "func": "var Packet = global.get('binary_parser');\nvar buf = msg.payload;\n\nvar typea = new Packet()\n\t\t.skip(8)\n\t\t.uint32le('FirstSyncTime') \t\t\t// Epoch\n\t\t.uint32le('LifeCountStartup') \n\t\t.uint32le('LifeCountCriticalBattOk') \n\t\t.uint32le('LifeCountChargeOn') \n\t\t.uint32le('LifeCountChargeLimp') \n\t\t.uint32le('LifeCountDischgOn') \n\t\t.uint32le('LifeCountDischgLimp') \n\t\t.uint32le('LifeCountHeatOn') \n\t\t.uint32le('LifeCountCoolOn') \n\t\t.int16le( 'LifeCountDailySession') \n\t\t.uint32le('RecentTimeCriticalOn') \t// Epoch\n\t\t.uint32le('RecentTimeCriticalOff') \t// Epoch\n\t\t.uint32le('RecentTimeChargeOn') \t// Epoch\n\t\t.uint32le('RecentTimeChargeOff') \t// Epoch\n\t\t.uint32le('RecentTimeChargeLimp') \t// Epoch\n\t\t.uint32le('RecentTimeDischgOn') \t// Epoch\n\t\t.uint32le('RecentTimeDischgOff') \t// Epoch\n\t\t.uint32le('RecentTimeDischgLimp') \t// Epoch\n\t\t.uint32le('RecentTimeHeatOn') \t\t// Epoch\n\t\t.uint32le('RecentTimeHeatOff') \t\t// Epoch\n\t\t.uint32le('RecentTimeCoolOn') \t\t// Epoch\n\t\t.uint32le('RecentTimeCoolOff') \t\t// Epoch\n\t\t.uint32le('RecentTimeBypassInitial') // Epoch\n\t\t.uint32le('RecentTimeBypassComplete') // Epoch\n\t\t.uint32le('RecentTimeBypassTest') \t// Epoch\n\t\t.uint8('SystemBypassTestOutcome')  /* Choices BypassTestOutcomes\n\t\t\tNotTested = 0,\n\t\t\tPreparing = 1,\n\t\t\tTesting = 2,\n\t\t\tPassOk = 3,\n\t\t\tFailed = 4, */\n\t\t.uint32le('RecentTimeWizardSetup') // Epoch\n\t\t.uint32le('RecentTimeBypassExtra') // Epoch\n\n  \nmsg.payload = typea.parse(buf);\n\n// convert date(s)\nmsg.payload.FirstSyncTime = new Date(msg.payload.FirstSyncTime*1000);\nmsg.payload.RecentTimeCriticalOn = new Date(msg.payload.RecentTimeCriticalOn*1000);\nmsg.payload.RecentTimeCriticalOff = new Date(msg.payload.RecentTimeCriticalOff*1000);\nmsg.payload.RecentTimeChargeOn = new Date(msg.payload.RecentTimeChargeOn*1000);\nmsg.payload.RecentTimeChargeOff = new Date(msg.payload.RecentTimeChargeOff*1000);\nmsg.payload.RecentTimeChargeLimp = new Date(msg.payload.RecentTimeChargeLimp*1000);\nmsg.payload.RecentTimeDischgOn = new Date(msg.payload.RecentTimeDischgOn*1000);\nmsg.payload.RecentTimeDischgOff = new Date(msg.payload.RecentTimeDischgOff*1000);\nmsg.payload.RecentTimeDischgLimp = new Date(msg.payload.RecentTimeDischgLimp*1000);\nmsg.payload.RecentTimeHeatOn = new Date(msg.payload.RecentTimeHeatOn*1000);\nmsg.payload.RecentTimeHeatOff = new Date(msg.payload.RecentTimeHeatOff*1000);\nmsg.payload.RecentTimeCoolOn = new Date(msg.payload.RecentTimeCoolOn*1000);\nmsg.payload.RecentTimeCoolOff = new Date(msg.payload.RecentTimeCoolOff*1000);\nmsg.payload.RecentTimeBypassInitial = new Date(msg.payload.RecentTimeBypassInitial*1000);\nmsg.payload.RecentTimeBypassComplete = new Date(msg.payload.RecentTimeBypassComplete*1000);\nmsg.payload.RecentTimeBypassTest = new Date(msg.payload.RecentTimeBypassTest*1000);\nmsg.payload.RecentTimeWizardSetup = new Date(msg.payload.RecentTimeWizardSetup*1000);\nmsg.payload.RecentTimeBypassExtra = new Date(msg.payload.RecentTimeBypassExtra*1000);\n\nswitch(msg.payload.SystemBypassTestOutcome) {\n    case 0:\n        msg.payload.SystemBypassTestOutcome = \"NotTested\";\n        break;\n    case 1:\n        msg.payload.SystemBypassTestOutcome = \"Preparing\";\n        break;\n    case 2:\n        msg.payload.SystemBypassTestOutcome = \"Testing\";\n        break;\n    case 3:\n        msg.payload.SystemBypassTestOutcome = \"PassOk\";\n        break;\n    case 4:\n        msg.payload.SystemBypassTestOutcome = \"Failed\";\n        break;\n    default:\n        msg.payload.SystemBypassTestOutcome = \"Buggered\";\n}\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "x": 120,
        "y": 620,
        "wires": [
            [
                "dbbeb1bd.5221"
            ]
        ]
    },
    {
        "id": "dbbeb1bd.5221",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 390,
        "y": 620,
        "wires": []
    },
    {
        "id": "bc35aeeb.93ab7",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "d": true,
        "name": "Msg_4a35_HwSystemSetup",
        "func": "var Packet = global.get('binary_parser');\nvar buf = msg.payload;\n\nvar typea = new Packet()\n\t\t.skip(8)\n\t\t.int16le('HwSystemSetupVers')\n\t\t.string('SystemCode', \t{ encoding: 'ascii', length: 8 })\n\t\t.string('SysName', \t\t{ encoding: 'ascii', length: 20 })\n\t\t.string('AssetCode', \t{ encoding: 'ascii', length: 20 })\n\t\t.uint8('AllowTechAuth') \t\t// boolean 0 = Off , 1 = On\n\t\t.uint8('AllowQuickSession') \t// boolean 0 = Off , 1 = On\n\t\t.uint32le('QuickSessionInterval', { formatter: (x) => {return x/1000;}})  // seconds\n\t\t.int16le('SystemPresetId')\n\t\t.int16le('SystemFirmwareVersion')\n\t\t.int16le('SystemHardwareVersion')\n\t\t.uint32le('SystemSerialNo')\n\t\t.uint8('ShowScheduler') \t\t// boolean 0 = Off , 1 = On\n\t\t.uint8('ShowStripCycle') \t\t// boolean 0 = Off , 1 = On\n\t\t\nmsg.payload = typea.parse(buf);\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 120,
        "y": 660,
        "wires": [
            [
                "ecea2916.d52128"
            ]
        ]
    },
    {
        "id": "ecea2916.d52128",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 390,
        "y": 660,
        "wires": []
    },
    {
        "id": "a7cdb5ee.7c66c8",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Msg_4d33_HwExpansionSetup",
        "func": "var Packet = global.get('binary_parser');\nvar buf = msg.payload;\n\nvar typea = new Packet()\n\t\t.skip(8)\n\t\t.uint8('HwExpansionSetupVers')  \n\t\t.uint8('HwExpansionTemplate')  /* ExtensionTemplateOptions\n\t\t\t\tNone = 0,\n\t\t\t\tExpansionBoard 12v = 1,\n\t\t\t\tExpansionBoard 48v = 2,\n\t\t\t\tWatchMonCmC v2.0   = 3,\t*/\t\n\t\t.uint8('HwExpansionNeoPixelMode')  /* NeoPixelExtStatusModes\n\t\t\t\tNone \t\t\t\t= 0,\n\t\t\t\tRepeat \t\t\t\t= 1,\n\t\t\t\tStatus + 7seg SoC% \t= 2,\n\t\t\t\tSolid SoC% 8seg \t= 3,\t*/\n\t\t.uint8('HwExpansionRelay1')  /* ExpansionOutputAssignments\n\t\t\t\tNone = 0,\n\t\t\t\tManualOn = 1,\n\t\t\t\tCritical BattOk = 2,\n\t\t\t\tCharging On = 4,\n\t\t\t\tDischarging On = 5,\n\t\t\t\tHeating Required = 6,\n\t\t\t\tCooling Required = 7,\n\t\t\t\tRun / Idle input = 8,\n\t\t\t\tCharge / Normal input = 9,\n\t\t\t\tBypass Complete = 10,\n\t\t\t\tCharging Limited = 11,\n\t\t\t\tDischarging Limited = 12,\n\t\t\t\tCritical Recovery = 13,\n\t\t\t\tCritical PulseOn = 14,\n\t\t\t\tCritical PulseOff = 15,\n\t\t\t\tCritical Fault = 16,\n\t\t\t\tCritical PrechargeTimer = 17, */\n\t\t.uint8('HwExpansionRelay2')  \t/* ExpansionOutputAssignments */\n\t\t.uint8('HwExpansionRelay3')  \t/* ExpansionOutputAssignments */\n\t\t.uint8('HwExpansionRelay4')\t\t/* ExpansionOutputAssignments */\n\t\t.uint8('HwExpansionOutput5')  \t/* ExpansionOutputAssignments */\n\t\t.uint8('HwExpansionOutput5')  \t/* ExpansionOutputAssignments */\n\t\t.uint8('HwExpansionOutput7')  \t/* ExpansionOutputAssignments */\n\t\t.uint8('HwExpansionOutput8')  \t/* ExpansionOutputAssignments */\n\t\t.uint8('HwExpansionOutput9')  \t/* ExpansionOutputAssignments */\n\t\t.uint8('HwExpansionOutput10') \t/* ExpansionOutputAssignments */\n\t\t.uint8('HwExpansionInput1')  \t/* ExtensionInputOptions\n\t\t\t\tNone \t\t\t\t\t= 0,\n\t\t\t\tRun / Idle mode \t\t= 1,\n\t\t\t\tCharge / Normal mode \t= 2,\n\t\t\t\tCritical contact sensor - On = 3,\n\t\t\t\tCritical contact sensor - Fault = 4, */\n\t\t.uint8('HwExpansionInput2')  \t/* ExtensionInputOptions */\n\t\t.uint8('HwExpansionInput3')  \t/* ExtensionInputOptions */\n\t\t.uint8('HwExpansionInput4')  \t/* ExtensionInputOptions */\n\t\t.uint8('HwExpansionInput5')  \t/* ExtensionInputOptions */\n\t\t.uint8('HwExpansionInputAIN1') \n\t\t.uint8('HwExpansionInputAIN2') \n\t\t.int16le('HwExpansionCustomFeature1')\n\t\t.int16le('HwExpansionCustomFeature2')\n\n  \nmsg.payload = typea.parse(buf);\n\n\nswitch(msg.payload.HwExpansionTemplate) {\n    case 0:\n        msg.payload.HwExpansionTemplate = \"None\";\n        break;\n    case 1:\n        msg.payload.HwExpansionTemplate = \"ExpansionBoard 12v\";\n        break;\n    case 2:\n        msg.payload.HwExpansionTemplate = \"ExpansionBoard 48v\";\n        break;\n    case 3:\n        msg.payload.HwExpansionTemplate = \"WatchMonCmC v2.0\";\n        break;\n    default:\n        msg.payload.HwExpansionTemplate = \"Buggered\";\n}\n\nswitch(msg.payload.HwExpansionNeoPixelMode) {\n    case 0:\n        msg.payload.HwExpansionNeoPixelMode = \"None\";\n        break;\n    case 1:\n        msg.payload.HwExpansionNeoPixelMode = \"Repeat\";\n        break;\n    case 2:\n        msg.payload.HwExpansionNeoPixelMode = \"Status + 7seg SoC%\";\n        break;\n    case 3:\n        msg.payload.HwExpansionNeoPixelMode = \"Solid SoC% 8seg\";\n        break;\n    default:\n        msg.payload.HwExpansionNeoPixelMode = \"Buggered\";\n}\n\nswitch(msg.payload.HwExpansionRelay1) {\n    case 0:\n        msg.payload.HwExpansionRelay1 = \"None\";\n        break;\n    case 1:\n        msg.payload.HwExpansionRelay1 = \"ManualOn\";\n        break;\n    case 2:\n        msg.payload.HwExpansionRelay1 = \"Critical BattOk\";\n        break;\n    case 3:\n        msg.payload.HwExpansionRelay1 = \"Charging On\";\n        break;\n    case 4:\n        msg.payload.HwExpansionRelay1 = \"Discharging On\";\n        break;\n    case 5:\n        msg.payload.HwExpansionRelay1 = \"Heating Required\";\n        break;\n    case 6:\n        msg.payload.HwExpansionRelay1 = \"Cooling Required\";\n        break;\n    case 7:\n        msg.payload.HwExpansionRelay1 = \"Run / Idle input\";\n        break;\n    case 8:\n        msg.payload.HwExpansionRelay1 = \"Charge / Normal input\";\n        break;\n    case 9:\n        msg.payload.HwExpansionRelay1 = \"Bypass Complete\";\n        break;\n    case 10:\n        msg.payload.HwExpansionRelay1 = \"Charging Limited\";\n        break;\n    case 11:\n        msg.payload.HwExpansionRelay1 = \"Discharging Limited\";\n        break;\n    case 12:\n        msg.payload.HwExpansionRelay1 = \"Critical Recovery\";\n        break;\n    case 13:\n        msg.payload.HwExpansionRelay1 = \"Critical PulseOn\";\n        break;\n    case 14:\n        msg.payload.HwExpansionRelay1 = \"Critical PulseOff\";\n        break;\n    case 105:\n        msg.payload.HwExpansionRelay1 = \"Critical Fault\";\n        break;\n    case 16:\n        msg.payload.HwExpansionRelay1 = \"Critical PrechargeTimer\";\n        break;\n    default:\n        msg.payload.HwExpansionRelay1 = \"Buggered\";\n}\n\nswitch(msg.payload.HwExpansionInput1) {\n    case 0:\n        msg.payload.HwExpansionInput1 = \"None\";\n        break;\n    case 1:\n        msg.payload.HwExpansionInput1 = \"Run / Idle mode\";\n        break;\n    case 2:\n        msg.payload.HwExpansionInput1 = \"Charge / Normal mode\";\n        break;\n    case 3:\n        msg.payload.HwExpansionInput1 = \"Critical contact sensor - On\";\n        break;\n    case 4:\n        msg.payload.HwExpansionInput1 = \"Critical contact sensor - Fault\";\n        break;\n    default:\n        msg.payload.HwExpansionInput1 = \"Buggered\";\n}\n\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 130,
        "y": 780,
        "wires": [
            [
                "1b2080a0.f3533f"
            ]
        ]
    },
    {
        "id": "1b2080a0.f3533f",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 390,
        "y": 780,
        "wires": []
    },
    {
        "id": "31f8d71a.f97f68",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Msg_4b35_HwCellGroupSetup",
        "func": "var Packet = global.get('binary_parser');\nvar buf = msg.payload;\n\nvar typea = new Packet()\n\t\t.skip(8)\n\t\t.uint8('HwCellmonSetupVers')  \n\t\t.uint8('HwCellmonBattTypeID')  /* BattTypes\n\t\t\t\tCustom \t\t\t\t= 0,\n\t\t\t\tLi-FePO4 Typical \t= 1,\n\t\t\t\tLi-Ion Performance \t= 2,\n\t\t\t\tLi-Ion LongLife \t= 3, \n\t\t\t\tLi-FePO4 Longlife \t= 4, */\n\t\t.uint8(  'HwCellmonFirstID')  \n\t\t.uint8(  'HwCellmonLastID')  \t\n\t\t.int16le('HwCellmonNomCellVolt', \t\t{ formatter: (x) => {return x/1000;}})\n\t\t.int16le('HwCellmonLoCellVolt', \t\t{ formatter: (x) => {return x/1000;}})\n\t\t.int16le('HwCellmonHiCellVolt',\t\t\t{ formatter: (x) => {return x/1000;}})\n\t\t.int16le('HwCellmonBypassVoltLevel',\t{ formatter: (x) => {return x/1000;}})\n\t\t.int16le('HwCellmonBypassAmpLimit', \t{ formatter: (x) => {return x/1000;}})\n\t\t.uint8( 'HwCellmonBypassTempLimit',\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint8( 'HwCellmonLoCellTemp',\t\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint8( 'HwCellmonHiCellTemp',\t\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint8( 'HwCellmonDiffNomCellsInSeries')  \t// Boolean 0 = Off , 1 = On\n\t\t.uint8( 'HwCellmonNomCellsInSeries') \n\t\t.uint8( 'HwCellmonAllowEntireRange')  \t\t// Boolean 0 = Off , 1 = On\n\t\t.uint8( 'HwCellmonEntireFirstID')  \n\t\t.uint8( 'HwCellmonEntireLastID')  \n\t\t.uint8( 'HwCellmonBypassExtraMode')  /* BypassExtraModes\n\t\t\t\tNone \t\t\t= 0,\n\t\t\t\tIdle Shunt \t\t= 1,\n\t\t\t\tSame CellVolt \t= 2,\n\t\t\t\tAutoLevel \t\t= 3, */\n\t\t.int16le('HwCellmonBypassExtraInterval',\t\t{ formatter: (x) => {return x/1000;}}) \t// seconds\n\t\t.uint8(  'HwCellmonCellMonTypeID')  /* CellMonTypes\n\t\t\t\tCustom \t\t= 0,\n\t\t\t\tGenMon 2W \t= 1,\n\t\t\t\tGenMon 8W \t= 2,\n\t\t\t\tLongMon \t= 3,\n\t\t\t\tBlockMonM8 \t= 4,\n\t\t\t\tBlockMonM14 = 5,\n\t\t\t\tEndMon \t\t= 6,\n\t\t\t\tManyMon \t= 7, */\n\t\t.floatle('HwCellmonBypassImpedance', \t\t\t{ formatter: (x) => {return x/1000;}})\n\t\t.int16le('HwCellmonBypassLoVoltCutout', \t\t{ formatter: (x) => {return x/1000;}})\n\t\t.int16le('HwCellmonBypassShuntChargeLimit', \t{ formatter: (x) => {return x/100;}}) \t// amps\n\t\t.int16le('HwCellmonBypassShuntDischgLimit', \t{ formatter: (x) => {return x/100;}}) \t// amps\n\t\t.uint8(  'HwCellmonBypassShuntSocLo', \t\t\t{ formatter: (x) => {return (x-5)/2;}}) // percent\n\t\t.int16le('HwCellmonBypassCellVoltBanding', \t\t{ formatter: (x) => {return x/1000;}})\n\t\t.int16le('HwCellmonBypassCellVoltDiff', \t\t{ formatter: (x) => {return x/1000;}})\n\t\t.int16le('HwCellmonBypassStableInterval',\t\t{ formatter: (x) => {return x/1000;}}) // seconds\n\t\t.int16le('HwCellmonBypassExtraAmpLimit', \t\t{ formatter: (x) => {return x/1000;}}) // amps\n\n  \nmsg.payload = typea.parse(buf);\n\nswitch(msg.payload.HwCellmonBattTypeID) {\n    case 0:\n        msg.payload.HwCellmonBattTypeID = \"Custom\";\n        break;\n    case 1:\n        msg.payload.HwCellmonBattTypeID = \"Li-FePO4 Typical\";\n        break;\n    case 2:\n        msg.payload.HwCellmonBattTypeID = \"Li-Ion Performance\";\n        break;\n    case 3:\n        msg.payload.HwCellmonBattTypeID = \"Li-Ion LongLife\";\n        break;\n    case 4:\n        msg.payload.HwCellmonBattTypeID = \"Li-FePO4 Longlife\";\n        break;\n    default:\n        msg.payload.HwCellmonBattTypeID = \"Buggered\";\n}\n\nswitch(msg.payload.HwCellmonBypassExtraMode) {\n    case 0:\n        msg.payload.HwCellmonBypassExtraMode = \"None\";\n        break;\n    case 1:\n        msg.payload.HwCellmonBypassExtraMode = \"Idle Shunt\";\n        break;\n    case 2:\n        msg.payload.HwCellmonBypassExtraMode = \"Same CellVolt\";\n        break;\n    case 3:\n        msg.payload.HwCellmonBypassExtraMode = \"AutoLevel\";\n        break;\n    default:\n        msg.payload.HwCellmonBypassExtraMode = \"Buggered\";\n}\n\nswitch(msg.payload.HwCellmonCellMonTypeID) {\n    case 0:\n        msg.payload.HwCellmonCellMonTypeID = \"Custom\";\n        break;\n    case 1:\n        msg.payload.HwCellmonCellMonTypeID = \"GenMon 2W\";\n        break;\n    case 2:\n        msg.payload.HwCellmonCellMonTypeID = \"GenMon 8W\";\n        break;\n    case 3:\n        msg.payload.HwCellmonCellMonTypeID = \"LongMon\";\n        break;\n    case 4:\n        msg.payload.HwCellmonCellMonTypeID = \"BlockMonM8\";\n        break;\n    case 5:\n        msg.payload.HwCellmonCellMonTypeID = \"BlockMonM14\";\n        break;\n    case 6:\n        msg.payload.HwCellmonCellMonTypeID = \"EndMon\";\n        break;\n    case 7:\n        msg.payload.HwCellmonCellMonTypeID = \"ManyMon\";\n        break;\n    default:\n        msg.payload.HwCellmonCellMonTypeID = \"Buggered\";\n}\n\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 130,
        "y": 700,
        "wires": [
            [
                "fbba11c0.1f358"
            ]
        ]
    },
    {
        "id": "6bbf2b60.9ce744",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Msg_4c33_HwShuntSetup",
        "func": "var Packet = global.get('binary_parser');\nvar buf = msg.payload;\n\nvar typea = new Packet()\n\t\t.skip(8)\n\t\t.uint8('HwShuntShuntType')  /* ShuntTypes\n\t\t\t\tNone            \t\t\t\t= 0,\n\t\t\t\tSFP102MOD 100uOhm 375A 150V \t= 1, \n\t\t\t\tSFP101EVB 72uOhm 500A 150V     \t= 2,\n\t\t\t\tSFP101EVB 25uOhm 1500A 150V \t= 3,\n\t\t\t\tSFP102MOD (4k) 375A 750V  \t\t= 4, \n\t\t\t\tSFP102MOD (3k) 375A 600V   \t\t= 5, \n\t\t\t\tSFP102MOD Negative volt sense  \t= 6,\n\t\t\t\tSFP102MOD 50uOhm 750A 150V \t\t= 7, \n\t\t\t\tShuntMon2 50uOhm 500A 650V \t\t= 16, */\n\t\t.int16le('HwShuntScale16volt')\n\t\t.int16le('HwShuntScale16amp')\n\t\t.int16le('HwShuntChargeIdle',\t{ formatter: (x) => {return x/100;}})   // amps\n\t\t.int16le('HwShuntDischgIdle',\t{ formatter: (x) => {return x/100;}})\t// amps\n\t\t.uint8( 'HwShuntSocCountLo', \t{ formatter: (x) => {return (x-5)/2;}}) // percent\n\t\t.uint8( 'HwShuntSocCountHi', \t{ formatter: (x) => {return (x-5)/2;}}) // percent\n\t\t.uint8( 'HwShuntSocLoRecal', \t{ formatter: (x) => {return (x-5)/2;}}) // percent\n\t\t.uint8( 'HwShuntSocHiRecal', \t{ formatter: (x) => {return (x-5)/2;}}) // percent\n\t\t.uint8( 'HwShuntMonitorSocLoRecal') \t// boolean 0 = Off , 1 = On\n\t\t.uint8( 'HwShuntMonitorSocHiRecal') \t// boolean 0 = Off , 1 = On\n\t\t.uint8( 'HwShuntMonitorInBypassRecal')\t// boolean 0 = Off , 1 = On\n\t\t.floatle('HwShuntNomCapacity',\t{ formatter: (x) => {return x/1000;}})\t// Ah\n\t\t.floatle('HwShuntGainVolt')\n\t\t.floatle('HwShuntGainAmp')\n\t\t.floatle('HwShuntGainAcculm')\t// mAh\n\t\t.floatle('HwShuntGainTemp') \t// temperature ºC\n\t\t.uint8( 'HwShuntReverseFlow') \t// boolean 0 = Off , 1 = On\n\t\t.uint8( 'HwShuntSetupVers') \n\t\t.floatle('HwShuntGainVA')\n\t\t.floatle('HwShuntGainVAh')\t\n\t\t.int16le('HwShuntMax16volt')\n\t\t.int16le('HwShuntMax16charge')\n\t\t.int16le('HwShuntMax16dischg')\n\n  \nmsg.payload = typea.parse(buf);\n\nswitch(msg.payload.HwShuntShuntType) {\n    case 0:\n        msg.payload.HwShuntShuntType = \"None\";\n        break;\n    case 1:\n        msg.payload.HwShuntShuntType = \"SFP102MOD 100uOhm 375A 150V\";\n        break;\n    case 2:\n        msg.payload.HwShuntShuntType = \"SFP101EVB 72uOhm 500A 150V\";\n        break;\n    case 3:\n        msg.payload.HwShuntShuntType = \"SFP101EVB 25uOhm 1500A 150V\";\n        break;\n    case 4:\n        msg.payload.HwShuntShuntType = \"SFP102MOD (4k) 375A 750V\";\n        break;\n    case 5:\n        msg.payload.HwShuntShuntType = \"SFP102MOD (3k) 375A 600V\";\n        break;\n    case 6:\n        msg.payload.HwShuntShuntType = \"SFP102MOD Negative volt sense\";\n        break;\n    case 7:\n        msg.payload.HwShuntShuntType = \"SFP102MOD 50uOhm 750A 150V\";\n        break;\n    case 16:\n        msg.payload.HwShuntShuntType = \"ShuntMon2 50uOhm 500A 650V\";\n        break;\n    default:\n        msg.payload.HwShuntShuntType = \"Buggered\";\n}\n\n\n\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 120,
        "y": 740,
        "wires": [
            [
                "22e7b26a.4c54ae"
            ]
        ]
    },
    {
        "id": "bc74a308.cfe11",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Msg_5334_HwIntegrationSetup",
        "func": "var Packet = global.get('binary_parser');\nvar buf = msg.payload;\n\nvar typea = new Packet()\n\t\t.skip(8)\n\t\t.uint8('HwIntegrationSetupVers')  \n\t\t.uint8('HwIntegrationUsbTxBroadcast')  \t\t// boolean 0 = Off , 1 = On\n\t\t.uint8('HwIntegrationWifiUdpTxBroadcast') \t// boolean 0 = Off , 1 = On\n\t\t.uint8('HwIntegrationWifiBroadcastMode') /* WifiBroadcastModes\n\t\t\t\tNone \t\t= 0,\n\t\t\t\tVerbose \t= 1,\n\t\t\t\tVerbose ReadOnly = 4,\n\t\t\t\tLimited \t= 2,\n\t\t\t\tDisabled \t= 3, */\n\t\t.uint8('HwIntegrationCanbusTxBroadcast') \t// boolean 0 = Off , 1 = On\n\t\t.uint8('HwIntegrationCanbusMode') /* CanbusModes\n\t\t\t\tNone   \t\t= 0,\n\t\t\t\tNative \t\t= 1,\n\t\t\t\tElcon TCCharger = 2,\n\t\t\t\tEnPower Charger500k = 3,\n\t\t\t\tSolax PowerSK control = 4,\n\t\t\t\tSma SunnyIsland V31 = 5,\n\t\t\t\tBrusa NLG5 \t= 6,\n\t\t\t\tEnPower Charger 250k = 7,\n\t\t\t\tSolax PowerSK Limited = 8,\n\t\t\t\tBrusa NLG6 \t= 9,\n\t\t\t\tProject Lychee = 10,\n\t\t\t\tEltek FlatPack2 HE2000/48 = 11,\n\t\t\t\tProject42 \t= 42,\t*/\n\t\t.uint32le('HwIntegrationCanbusRemoteAddr')\n\t\t.uint32le('HwIntegrationCanbusBaseAddr')\n\t\t.uint32le('HwIntegrationCanbusGroupAddr')\n  \nmsg.payload = typea.parse(buf);\n\nswitch(msg.payload.HwIntegrationWifiBroadcastMode) {\n    case 0:\n        msg.payload.HwIntegrationWifiBroadcastMode = \"None\";\n        break;\n    case 1:\n        msg.payload.HwIntegrationWifiBroadcastMode = \"Verbose\";\n        break;\n    case 2:\n        msg.payload.HwIntegrationWifiBroadcastMode = \"Limited\";\n        break;\n    case 3:\n        msg.payload.HwIntegrationWifiBroadcastMode = \"Disabled\";\n        break;\n    case 4:\n        msg.payload.HwIntegrationWifiBroadcastMode = \"Verbose ReadOnly\";\n        break;\n    default:\n        msg.payload.HwIntegrationWifiBroadcastMode = \"Buggered\";\n}\n\nswitch(msg.payload.HwExpansionRelay1) {\n    case 0:\n        msg.payload.HwExpansionRelay1 = \"None\";\n        break;\n    case 1:\n        msg.payload.HwExpansionRelay1 = \"Native\";\n        break;\n    case 2:\n        msg.payload.HwExpansionRelay1 = \"Elcon TCCharger\";\n        break;\n    case 3:\n        msg.payload.HwExpansionRelay1 = \"EnPower Charger500k\";\n        break;\n    case 4:\n        msg.payload.HwExpansionRelay1 = \"Solax PowerSK control\";\n        break;\n    case 5:\n        msg.payload.HwExpansionRelay1 = \"Sma SunnyIsland V31\";\n        break;\n    case 6:\n        msg.payload.HwExpansionRelay1 = \"Brusa NLG5\";\n        break;\n    case 7:\n        msg.payload.HwExpansionRelay1 = \"EnPower Charger 250k\";\n        break;\n    case 8:\n        msg.payload.HwExpansionRelay1 = \"Solax PowerSK Limited\";\n        break;\n    case 9:\n        msg.payload.HwExpansionRelay1 = \"Brusa NLG6\";\n        break;\n    case 10:\n        msg.payload.HwExpansionRelay1 = \"Project Lychee\";\n        break;\n    case 11:\n        msg.payload.HwExpansionRelay1 = \"Eltek FlatPack2 HE2000/48\";\n        break;\n    case 42:\n        msg.payload.HwExpansionRelay1 = \"roject42\";\n        break;\n    default:\n        msg.payload.HwExpansionRelay1 = \"Buggered\";\n}\n\n\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 130,
        "y": 820,
        "wires": [
            [
                "8b53a6b9.a53688"
            ]
        ]
    },
    {
        "id": "8b53a6b9.a53688",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "d": true,
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 390,
        "y": 820,
        "wires": []
    },
    {
        "id": "a3320528.870448",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Msg_4f33_ControlCriticalSetup",
        "func": "var Packet = global.get('binary_parser');\nvar buf = msg.payload;\n\nvar typea = new Packet()\n\t\t.skip(8)\n\t\t.uint8( 'ControlCriticalMode')   /* Choices ControlCriticalModes\n\t\t\t\tAuto \t\t\t= 0,\n\t\t\t\tManually On \t= 1,\n\t\t\t\tManually Off  \t= 2, */\t\n\t\t.uint8( 'ControlCriticalAutoRecovery')  \t\t\t// boolean 0 = Off , 1 = On\n\t\t.uint8( 'ControlCriticalIgnoreCellsOverdue') \t\t// boolean 0 = Off , 1 = On\n\t\t.uint8( 'ControlCriticalMonitorCellVoltLo') \t\t// boolean 0 = Off , 1 = On\n\t\t.uint8( 'ControlCriticalMonitorCellVoltHi') \t\t// boolean 0 = Off , 1 = On\n\t\t.int16le('ControlCriticalCellVoltLo',\t\t\t\t{ formatter: (x) => {return x/1000;}})\n\t\t.int16le('ControlCriticalCellVoltHi',\t\t\t\t{ formatter: (x) => {return x/1000;}})\n\t\t.uint8( 'ControlCriticalMonitorCellTempLo') \t\t// boolean 0 = Off , 1 = On\n\t\t.uint8( 'ControlCriticalMonitorCellTempHi') \t\t// boolean 0 = Off , 1 = On\n\t\t.uint8( 'ControlCriticalCellTempLo',\t\t\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint8( 'ControlCriticalCellTempHi',\t\t\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint8( 'ControlCriticalMonitorSupplyLo') \t\t\t// boolean 0 = Off , 1 = On\n\t\t.uint8( 'ControlCriticalMonitorSupplyHi') \t\t\t// boolean 0 = Off , 1 = On\n\t\t.int16le('ControlCriticalSupplyVoltLo',\t\t\t\t{ formatter: (x) => {return x/100;}})\n\t\t.int16le('ControlCriticalSupplyVoltHi',\t\t\t\t{ formatter: (x) => {return x/100;}})\n\t\t.uint8( 'ControlCriticalMonitorAmbientLo') \t\t\t// boolean 0 = Off , 1 = On\n\t\t.uint8( 'ControlCriticalMonitorAmbientHi') \t\t\t// boolean 0 = Off , 1 = On\n\t\t.uint8( 'ControlCriticalAmbientTempLo',\t\t\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint8( 'ControlCriticalAmbientTempHi',\t\t\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint8( 'ControlCriticalMonitorShuntVoltLo') \t\t// boolean 0 = Off , 1 = On\n\t\t.uint8( 'ControlCriticalMonitorShuntVoltHi') \t\t// boolean 0 = Off , 1 = On\n\t\t.uint8( 'ControlCriticalMonitorShuntVoltLoIdle') \t// boolean 0 = Off , 1 = On\n\t\t.int16le('ControlCriticalShuntVoltLo',\t\t\t\t{ formatter: (x) => {return x/100;}})\n\t\t.int16le('ControlCriticalShuntVoltHi',\t\t\t\t{ formatter: (x) => {return x/100;}})\n\t\t.int16le('ControlCriticalShuntVoltLoIdle',\t\t\t{ formatter: (x) => {return x/100;}})\n\t\t.uint8(  'ControlCriticalMonitorShuntPeakCharge') \t// boolean 0 = Off , 1 = On\n\t\t.int16le('ControlCriticalShuntPeakCharge',\t\t\t{ formatter: (x) => {return x/100;}}) // amps\n\t\t.int16le('ControlCriticalShuntCrateCharge',\t\t\t{ formatter: (x) => {return x/100;}}) // ratio\n\t\t.uint8(  'ControlCriticalMonitorShuntPeakDischg') \t// boolean 0 = Off , 1 = On\n\t\t.int16le('ControlCriticalShuntPeakDischg',\t\t\t{ formatter: (x) => {return x/100;}}) // amps\n\t\t.int16le('ControlCriticalShuntCrateDischg',\t\t\t{ formatter: (x) => {return x/100;}}) // ratio\n\t\t.uint32le('ControlCriticalStopInterval',\t\t\t{ formatter: (x) => {return x/1000;}}) // seconds\n\t\t.uint32le('ControlCriticalStartInterval',\t\t\t{ formatter: (x) => {return x/1000;}}) // seconds\n\t\t.uint32le('ControlCriticalTimeoutManualOverride',\t{ formatter: (x) => {return x/1000;}}) // seconds\n\t\t.uint32le('ControlCriticalPrechargeTimeInterval',\t{ formatter: (x) => {return x/1000;}}) // seconds\n\t\t.uint8(  'ControlCriticalIgnoreShuntOverdue') \t\t// boolean 0 = Off , 1 = On\n\t\t.uint8(  'ControlCriticalIgnoreRemoteOverdue') \t\t// boolean 0 = Off , 1 = On\n\t\t.int16le('ControlCriticalRecoverSupplyGapVolt',\t\t{ formatter: (x) => {return x/100;}})\n\t\t.int16le('ControlCriticalRecoverShuntChargeLimit',\t{ formatter: (x) => {return x/100;}}) // amps\n\t\t.int16le('ControlCriticalRecoverShuntDischgLimit',\t{ formatter: (x) => {return x/100;}}) // amps\n\t\t.uint8(  'ControlCriticalSetupVers') \n\n  \nmsg.payload = typea.parse(buf);\n\nswitch(msg.payload.ControlCriticalMode) {\n    case 0:\n        msg.payload.ControlCriticalMode = \"Auto\";\n        break;\n    case 1:\n        msg.payload.ControlCriticalMode = \"Manually On\";\n        break;\n    case 2:\n        msg.payload.ControlCriticalMode = \"Manually Off\";\n        break;\n    default:\n        msg.payload.ControlCriticalMode = \"Buggered\";\n}\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 130,
        "y": 860,
        "wires": [
            [
                "86100b5d.5d6998"
            ]
        ]
    },
    {
        "id": "86100b5d.5d6998",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 390,
        "y": 860,
        "wires": []
    },
    {
        "id": "84398b42.b2f578",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Msg_5033_ControlChargeSetup",
        "func": "var Packet = global.get('binary_parser');\nvar buf = msg.payload;\n\nvar typea = new Packet()\n\t\t.skip(8)\n\t\t.uint8( 'ControlChargeMode')  /* Choices ControlChargeModes\n\t\t\t\tAuto\t\t  \t = 0,\n\t\t\t\tManually On      = 1,\n\t\t\t\tManually Off     = 2,\n\t\t\t\tManually Limited = 3, */\t\n\t\t.uint8(  'ControlChargeAllowLimPowerStage')  \t// boolean 0 = Off , 1 = On\n\t\t.uint8(  'ControlChargeAllowBypassLimPower') \t// boolean 0 = Off , 1 = On\n\t\t.uint8(  'ControlChargeAllowBypassComplete') \t// boolean 0 = Off , 1 = On\n\t\t.int16le('ControlChargeInitalBypassAmp',\t\t{ formatter: (x) => {return x/1000;}})\n\t\t.int16le('ControlChargeFinalBypassAmp',\t\t\t{ formatter: (x) => {return x/1000;}})\n\t\t.uint8(  'ControlChargeMonitorCellTempLo') \t\t// boolean 0 = Off , 1 = On\n\t\t.uint8(  'ControlChargeMonitorCellTempHi') \t\t// boolean 0 = Off , 1 = On\n\t\t.uint8(  'ControlChargeCellTempLo',\t\t\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint8(  'ControlChargeCellTempHi',\t\t\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint8(  'ControlChargeMonitorAmbientLo') \t\t// boolean 0 = Off , 1 = On\n\t\t.uint8(  'ControlChargeMonitorAmbientHi') \t\t// boolean 0 = Off , 1 = On\n\t\t.uint8(  'ControlChargeAmbientTempLo',\t\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint8(  'ControlChargeAmbientTempHi',\t\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint8(  'ControlChargeMonitorSupplyHi') \t\t// boolean 0 = Off , 1 = On\n\t\t.int16le('ControlChargeSupplyVoltHi',\t\t\t{ formatter: (x) => {return x/100;}})\n\t\t.int16le('ControlChargeSupplyVoltResume',\t\t{ formatter: (x) => {return x/100;}})\n\t\t.uint8(  'ControlChargeMonitorCellVoltHi') \t\t// boolean 0 = Off , 1 = On\n\t\t.int16le('ControlChargeCellVoltHi',\t\t\t\t{ formatter: (x) => {return x/1000;}})\n\t\t.int16le('ControlChargeCellVoltResume',\t\t\t{ formatter: (x) => {return x/1000;}})\n\t\t.int16le('ControlChargeCellVoltLimPower',\t\t{ formatter: (x) => {return x/1000;}})\n\t\t.uint8(  'ControlChargeMonitorShuntVoltHi') \t// boolean 0 = Off , 1 = On\n\t\t.int16le('ControlChargeShuntVoltHi',\t\t\t{ formatter: (x) => {return x/100;}})\n\t\t.int16le('ControlChargeShuntVoltResume',\t\t{ formatter: (x) => {return x/100;}})\n\t\t.int16le('ControlChargeShuntVoltLimPower',\t\t{ formatter: (x) => {return x/100;}})\n\t\t.uint8(  'ControlChargeMonitorShuntSocHi') \t\t// boolean 0 = Off , 1 = On\n\t\t.uint8(  'ControlChargeShuntSocHi', \t\t\t{ formatter: (x) => {return (x-5)/2;}}) // percent\n\t\t.uint8(  'ControlChargeShuntSocResume', \t\t{ formatter: (x) => {return (x-5)/2;}}) // percent\n\t\t.uint32le('ControlChargeStopInterval',\t\t\t{ formatter: (x) => {return x/1000;}}) // seconds\n\t\t.uint32le('ControlChargeStartInterval',\t\t\t{ formatter: (x) => {return x/1000;}}) // seconds\n\t\t.uint8(  'ControlChargeSetupVers')  \n\t\t.floatle('ControlChargeBypassSessionLo',\t\t{ formatter: (x) => {return x/1000;}})\t// Ah\n\t\t.uint8(  'ControlChargeAllowBypassSession') \t// boolean 0 = Off , 1 = On\n\t\t\n  \nmsg.payload = typea.parse(buf);\n\nswitch(msg.payload.ControlChargeMode) {\n    case 0:\n        msg.payload.ControlChargeMode = \"Auto\";\n        break;\n    case 1:\n        msg.payload.ControlChargeMode = \"Manually On\";\n        break;\n    case 2:\n        msg.payload.ControlChargeMode = \"Manually Off\";\n        break;\n    case 3:\n        msg.payload.ControlChargeMode = \"Manually Limited\";\n        break;\n    default:\n        msg.payload.ControlChargeMode = \"Buggered\";\n}\n\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 130,
        "y": 900,
        "wires": [
            [
                "e91ed1d6.85832"
            ]
        ]
    },
    {
        "id": "e91ed1d6.85832",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "d": true,
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 390,
        "y": 900,
        "wires": []
    },
    {
        "id": "66113e17.06931",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "d": true,
        "name": "Msg_5158_ControlDischargeSetup",
        "func": "var Packet = global.get('binary_parser');\nvar buf = msg.payload;\n\nvar typea = new Packet()\n\t\t.skip(8)\n\t\t.uint8(   'ControlDischargeMode') /* Choices ControlDischgModes\n\t\t\t\tAuto\t\t  \t = 0,\n\t\t\t\tManually On      = 1,\n\t\t\t\tManually Off     = 2,\n\t\t\t\tManually Limited = 3, */\t\n\t\t.uint8(   'ControlDischargeAllowLimPowerStage')\t// boolean 0 = Off , 1 = On\n\t\t.uint8(   'ControlDischargeMonitorCellTempLo') \t// boolean 0 = Off , 1 = On\n\t\t.uint8(   'ControlDischargeMonitorCellTempHi') \t// boolean 0 = Off , 1 = On\n\t\t.uint8(   'ControlDischargeCellTempLo',\t\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint8(   'ControlDischargeCellTempHi',\t\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint8(   'ControlDischargeMonitorAmbientLo') \t// boolean 0 = Off , 1 = On\n\t\t.uint8(   'ControlDischargeMonitorAmbientHi') \t// boolean 0 = Off , 1 = On\n\t\t.uint8(   'ControlDischargeAmbientTempLo',\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint8(   'ControlDischargeAmbientTempHi',\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint8(   'ControlDischargeMonitorSupplyLo') \t// boolean 0 = Off , 1 = On\n\t\t.int16le( 'ControlDischargeSupplyVoltLo',\t\t{ formatter: (x) => {return x/100;}})\n\t\t.int16le( 'ControlDischargeSupplyVoltResume',\t{ formatter: (x) => {return x/100;}})\n\t\t.uint8(   'ControlDischargeMonitorCellVoltLo') \t// boolean 0 = Off , 1 = On\n\t\t.int16le( 'ControlDischargeCellVoltLo',\t\t\t{ formatter: (x) => {return x/1000;}})\n\t\t.int16le( 'ControlDischargeCellVoltResume',\t\t{ formatter: (x) => {return x/1000;}})\n\t\t.int16le( 'ControlDischargeCellVoltLimPower',\t{ formatter: (x) => {return x/1000;}})\n\t\t.uint8(   'ControlDischargeMonitorShuntVoltLo') // boolean 0 = Off , 1 = On\n\t\t.int16le( 'ControlDischargeShuntVoltLo',\t\t{ formatter: (x) => {return x/100;}})\n\t\t.int16le( 'ControlDischargeShuntVoltResume',\t{ formatter: (x) => {return x/100;}})\n\t\t.int16le( 'ControlDischargeShuntVoltLimPower',\t{ formatter: (x) => {return x/100;}})\n\t\t.uint8(   'ControlDischargeMonitorShuntSocLo') \t// boolean 0 = Off , 1 = On\n\t\t.uint8(   'ControlDischargeShuntSocLo', \t\t{ formatter: (x) => {return (x-5)/2;}}) // percent\n\t\t.uint8(   'ControlDischargeShuntSocResume', \t{ formatter: (x) => {return (x-5)/2;}}) // percent\n\t\t.uint32le('ControlDischargeStopInterval',\t\t{ formatter: (x) => {return x/1000;}}) // seconds\n\t\t.uint32le('ControlDischargeStartInterval',\t\t{ formatter: (x) => {return x/1000;}}) // seconds\n\t\t.uint8(   'ControlDischargeSetupVers')  \n\t\n  \nmsg.payload = typea.parse(buf);\n\nswitch(msg.payload.ControlDischargeMode) {\n    case 0:\n        msg.payload.ControlDischargeMode = \"Auto\";\n        break;\n    case 1:\n        msg.payload.ControlDischargeMode = \"Manually On\";\n        break;\n    case 2:\n        msg.payload.ControlDischargeMode = \"Manually Off\";\n        break;\n    case 3:\n        msg.payload.ControlDischargeMode = \"Manually Limited\";\n        break;\n    default:\n        msg.payload.ControlDischargeMode = \"Buggered\";\n}\n\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 140,
        "y": 940,
        "wires": [
            [
                "e0549ade.d61068"
            ]
        ]
    },
    {
        "id": "e0549ade.d61068",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "d": true,
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 390,
        "y": 940,
        "wires": []
    },
    {
        "id": "d0a120ad.f8edd",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Msg_5258_ControlThermalSetup",
        "func": "var Packet = global.get('binary_parser');\nvar buf = msg.payload;\n\nvar typea = new Packet()\n\t\t.skip(8)\n\t\t.uint8('ControlHeatMode')  /* Choices ThermalControlModes\n\t\t\t\tAuto\t\t  \t = 0,\n\t\t\t\tManually On      = 1,\n\t\t\t\tManually Off     = 2, */\t\n\t\t.uint8('ControlHeatMonitorLoCellTemp')  \t// Boolean 0 = Off , 1 = On\n\t\t.uint8('ControlHeatMonitorLoAmbient')  \t\t// Boolean 0 = Off , 1 = On\n\t\t.uint8('ControlHeatLoCellTemp', \t\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint8('ControlHeatLoAmbient',\t \t\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint32le('ControlHeatStopInterval',\t\t{ formatter: (x) => {return x/1000;}}) // seconds\n\t\t.uint32le('ControlHeatStartInterval',\t\t{ formatter: (x) => {return x/1000;}}) // seconds\n\t\t.uint8('ControlCoolMode')  \t\t\t\t\t/* Choices ThermalControlModes */\n\t\t.uint8('ControlCoolMonitorHiCellTemp')  \t// Boolean 0 = Off , 1 = On\n\t\t.uint8('ControlCoolMonitorHiAmbient')   \t// Boolean 0 = Off , 1 = On\n\t\t.uint8('ControlCoolMonitorInBypass')   \t\t// Boolean 0 = Off , 1 = On\n\t\t.uint8('ControlCoolHiCellTemp', \t\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint8('ControlCoolHiAmbient',\t \t\t\t{ formatter: (x) => {return x-40;}}) // temperature ºC\n\t\t.uint32le('ControlCoolStopInterval',\t\t{ formatter: (x) => {return x/1000;}}) // seconds\n\t\t.uint32le('ControlCoolStartInterval',\t\t{ formatter: (x) => {return x/1000;}}) // seconds\n\t\t.uint8('ControlThermalSetupVers')  \n\n  \nmsg.payload = typea.parse(buf);\n\nswitch(msg.payload.ControlHeatMode) {\n    case 0:\n        msg.payload.ControlHeatMode = \"Auto\";\n        break;\n    case 1:\n        msg.payload.ControlHeatMode = \"Manually On\";\n        break;\n    case 2:\n        msg.payload.ControlHeatMode = \"Manually Off\";\n        break;\n    default:\n        msg.payload.ControlHeatMode = \"Buggered\";\n}\n\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 140,
        "y": 980,
        "wires": [
            [
                "6bb53cb7.1587d4"
            ]
        ]
    },
    {
        "id": "6bb53cb7.1587d4",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "d": true,
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 390,
        "y": 980,
        "wires": []
    },
    {
        "id": "3f60dd09.a9d822",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Msg_4e58_ControlRemoteSetup",
        "func": "var Packet = global.get('binary_parser');\nvar buf = msg.payload;\n\nvar typea = new Packet()\n\t\t.skip(8)\n\t\t.int16le('ControlChargeTargetNormVolt')\n\t\t.int16le('ControlChargeTargetNormAmp')\n\t\t.int16le('ControlChargeTargetNormVA')\n\t\t.int16le('ControlChargeTargetLimpVolt')\n\t\t.int16le('ControlChargeTargetLimpAmp')\n\t\t.int16le('ControlChargeTargetLimpVA')\n\t\t.int16le('ControlChargeScale16volt')\n\t\t.int16le('ControlChargeScale16amp')\n\t\t.int16le('ControlChargeScale16va')\n\t\t.int16le('ControlDischargeTargetNormVolt')\n\t\t.int16le('ControlDischargeTargetNormAmp')\n\t\t.int16le('ControlDischargeTargetNormVA')\n\t\t.int16le('ControlDischargeTargetLimpVolt')\n\t\t.int16le('ControlDischargeTargetLimpAmp')\n\t\t.int16le('ControlDischargeTargetLimpVA')\n\t\t.int16le('ControlDischargeScale16volt')\n\t\t.int16le('ControlDischargeScale16amp')\n\t\t.int16le('ControlDischargeScale16va')\n\t\t.uint8('ControlRemoteSetupVers')  \n\t\t\nmsg.payload = typea.parse(buf);\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 140,
        "y": 1020,
        "wires": [
            [
                "77fa4a8.4d5f4b4"
            ]
        ]
    },
    {
        "id": "77fa4a8.4d5f4b4",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "d": true,
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 390,
        "y": 1020,
        "wires": []
    },
    {
        "id": "672f0abe.f9af24",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Msg_5831_DailySessionHist",
        "func": "var Packet = global.get('binary_parser');\nvar buf = msg.payload;\n\nvar typea = new Packet()\n\t\t.skip(8)\n\t\t.int16le('DailySessionHistId')\n\t\t.uint32le('DailySessionHistTime') \t\t// Epoch   *** log key ***\n\t\t.uint8('DailySessionHistCriticalEvents')\n\t\t.skip(1)\n\t\t.uint8('DailySessionHistMinReportTemp',\t\t\t{ formatter: (x) => {return x-40;}})\t// temperature ºC\n\t\t.uint8('DailySessionHistMaxReportTemp',\t\t\t{ formatter: (x) => {return x-40;}})\t// temperature ºC\n\t\t.uint8('DailySessionHistMinShuntSoc', \t\t\t{ formatter: (x) => {return (x-5)/2;}}) // percent\n\t\t.uint8('DailySessionHistMaxShuntSoc', \t\t\t{ formatter: (x) => {return (x-5)/2;}}) // percent\n\t\t.int16le('DailySessionHistMinCellVolt',\t\t\t{ formatter: (x) => {return x/1000;}})\n\t\t.int16le('DailySessionHistMaxCellVolt',\t\t\t{ formatter: (x) => {return x/1000;}})\n\t\t.int16le('DailySessionHistMinSupplyVolt',\t\t{ formatter: (x) => {return x/100;}})\n\t\t.int16le('DailySessionHistMaxSupplyVolt',\t\t{ formatter: (x) => {return x/100;}})\n\t\t.int16le('DailySessionHistMinShuntVolt',\t\t{ formatter: (x) => {return x/100;}})\n\t\t.int16le('DailySessionHistMaxShuntVolt',\t\t{ formatter: (x) => {return x/100;}})\n\t\t.uint8('DailySessionHistThermalBandA',\t\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionHistThermalBandB',\t\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionHistThermalBandC',\t\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionHistThermalBandD',\t\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionHistThermalBandE',\t\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionHistThermalBandF',\t\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionHistThermalBandG',\t\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionHistThermalBandH',\t\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionHistSocBandA',\t\t\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionHistSocBandB',\t\t\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionHistSocBandC',\t\t\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionHistSocBandD',\t\t\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionHistSocBandE',\t\t\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionHistSocBandF',\t\t\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionHistSocBandG',\t\t\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.uint8('DailySessionHistSocBandH',\t\t\t\t{ formatter: (x) => {return x/10;}}) // hours\n\t\t.int16le('DailySessionHistShuntPeakCharge',\t\t{ formatter: (x) => {return x/100;}})  // amp\n\t\t.int16le('DailySessionHistShuntPeakDischg',\t\t{ formatter: (x) => {return x/100;}})  // amp\n\t\t.int16le('DailySessionHistCumulShuntAhCharge',\t{ formatter: (x) => {return x/1000;}}) // Ah\n\t\t.int16le('DailySessionHistCumulShuntAhDischg',\t{ formatter: (x) => {return x/1000;}}) // Ah\n\t\t\nmsg.payload = typea.parse(buf);\n\n// convert date(s)\nmsg.payload.DailySessionHistTime = new Date(msg.payload.DailySessionHistTime*1000);\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 120,
        "y": 1060,
        "wires": [
            [
                "f82cb531.002978"
            ]
        ]
    },
    {
        "id": "f82cb531.002978",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "d": true,
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 390,
        "y": 1060,
        "wires": []
    },
    {
        "id": "fa326eca.690b8",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Msg_6831_QuickSessionHist",
        "func": "var Packet = global.get('binary_parser');\nvar buf = msg.payload;\n\nvar typea = new Packet()\n\t\t.skip(8)\n\t\t.int16le('QuickSessionHistId')\n\t\t.uint32le('QuickSessionHistTime') \t\t// Epoch  *** log key ***\n\t\t.uint8('QuickSessionHistSystemOpState') /* Choices\n\t\t\t\tSimulator = 0,   \t  // LED = rainbow pulse\n\t\t\t\tIdle = 1,        \t  // LED = green slow pulse\n\t\t\t\tDischarging = 2, \t  // LED = green solid \n\t\t\t\tSoC Empty = 3,   \t  // LED = green double blink\n\t\t\t\tCharging = 4,    \t  // LED = blue slow pulse\n\t\t\t\tFull = 5,        \t  // LED = blue double blink\n\t\t\t\tTimeout = 6,     \t  // LED = red solid\n\t\t\t\tCritical Pending = 7, // LED = red fast pulse\n\t\t\t\tCritical Offline = 8, // LED = red slow pulse\n\t\t\t\tMqtt Offline = 9,     // LED = white blink\n\t\t\t\tAuth Setup = 10,      // LED = white solid\n\t\t\t\tShunt Timeout = 11,   // LED = red solid  \t*/\n\t\t.uint8( 'QuickSessionHistControlLogic')  \n\t\t.int16le('QuickSessionHistMinCellVolt',\t\t\t{ formatter: (x) => {return x/1000;}})\n\t\t.int16le('QuickSessionHistMaxCellVolt',\t\t\t{ formatter: (x) => {return x/1000;}})\n\t\t.int16le('QuickSessionHistAvgCellVolt',\t\t\t{ formatter: (x) => {return x/1000;}})\n\t\t.uint8(  'QuickSessionHistAvgCellTemp',\t\t\t{ formatter: (x) => {return x-40;}})\t// temperature ºC\n\t\t.int16le('QuickSessionHistSocHiRes',\t\t\t{ formatter: (x) => {return x/100;}})\t// percent\n\t\t.int16le('QuickSessionHistShuntVolt',\t\t\t{ formatter: (x) => {return x/100;}})\n\t\t.floatle('QuickSessionHistShuntAmp',\t\t\t{ formatter: (x) => {return x/1000;}})  // amp\n\t\t.uint8(  'QuickSessionHistNumOfCellsInBypass')\n\n\t\nmsg.payload = typea.parse(buf);\n\n// convert date(s)\nmsg.payload.QuickSessionHistTime = new Date(msg.payload.QuickSessionHistTime*1000);\n\nswitch(msg.payload.QuickSessionHistSystemOpState) {\n    case 0:\n        msg.payload.QuickSessionHistSystemOpState = \"Simulator\";\n        break;\n    case 1:\n        msg.payload.QuickSessionHistSystemOpState = \"Idle\";\n        break;\n    case 2:\n        msg.payload.QuickSessionHistSystemOpState = \"Discharging\";\n        break;\n    case 3:\n        msg.payload.QuickSessionHistSystemOpState = \"SoC Empty\";\n        break;\n    case 4:\n        msg.payload.QuickSessionHistSystemOpState = \"Charging\";\n        break;\n    case 5:\n        msg.payload.QuickSessionHistSystemOpState = \"Full\";\n        break;\n    case 6:\n        msg.payload.QuickSessionHistSystemOpState = \"Timeout\";\n        break;\n    case 7:\n        msg.payload.QuickSessionHistSystemOpState = \"CriticalPending\";\n        break;\n    case 8:\n        msg.payload.QuickSessionHistSystemOpState = \"CriticalOffline\";\n        break;\n    case 9:\n        msg.payload.QuickSessionHistSystemOpState = \"MqttOffline\";\n        break;\n    case 10:\n        msg.payload.QuickSessionHistSystemOpState = \"AuthSetup\";\n        break;\n    case 11:\n        msg.payload.QuickSessionHistSystemOpState = \"Shunt Timeout\";\n        break;\n    default:\n        msg.payload.QuickSessionHistSystemOpState = \"Buggered\";\n}\n\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 120,
        "y": 1100,
        "wires": [
            [
                "ea787f02.584ab"
            ]
        ]
    },
    {
        "id": "15f71030.bd9eb",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Msg_5431_SessionMetrics",
        "func": "var Packet = global.get('binary_parser');\nvar buf = msg.payload;\n\nvar typea = new Packet()\n\t\t.skip(8)\n\t\t.uint32le('QuickSessRecentTime') \t\t// EPOCH\n\t\t.int16le('QuickSessNumOfRecords')\n\t\t.int16le('QuickSessMaxNumOfRecords')\n\t\t.uint32le('QuickSessionInterval',\t\t{ formatter: (x) => {return x/1000;}})\n\t\t.uint8('AllowQuickSession')  \t\t\t// boolean 0 = Off , 1 = On\n\t\t.int16le('DailySessNumOfRecords')\n\t\t.int16le('DailySessMaxNumOfRecords')\n\n\nmsg.payload = typea.parse(buf);\n\n// convert date(s)\nmsg.payload.QuickSessRecentTime = new Date(msg.payload.QuickSessRecentTime*1000);\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 120,
        "y": 1140,
        "wires": [
            [
                "49be9953.d21e48"
            ]
        ]
    },
    {
        "id": "2af1bf8b.3e7b5",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 570,
        "y": 40,
        "wires": []
    },
    {
        "id": "6c1bb0a6.cde56",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Get the set of saved global variables",
        "func": "\nvar ONE = global.get('ONE') || 0;\nvar TWO = global.get('TWO') || 0;\nvar THREE = global.get('THREE') || 0;\nvar FOUR = global.get('FOUR') || 0;\nvar FIVE = global.get('FIVE') || 0;\nvar SIX = global.get('SIX') || 0;\nvar SEVEN = global.get('SEVEN') || 0;\nvar EIGHT = global.get('EIGHT') || 0;\nvar NINE = global.get('NINE') || 0;\nvar TEN = global.get('TEN') || 0;\nvar ELEVEN = global.get('ELEVEN') || 0;\nvar TWELVE = global.get('TWELVE') || 0;\nvar THIRTEEN = global.get('THIRTEEN') || 0;\nvar FOURTEEN = global.get('FOURTEEN') || 0;\nvar FIFTEEN = global.get('FIFTEEN') || 0;\nvar SIXTEEN = global.get('SIXTEEN') || 0;\n\n\nvar m = {};\nm.labels = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16'];\nm.data = [[ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN,EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN, SIXTEEN]];\nm.series = ['Cell'];\nreturn {payload:[m],topic:msg.topic};",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "x": 890,
        "y": 20,
        "wires": [
            [
                "24fe7cc5.03a284",
                "602b821a.72b6bc"
            ]
        ]
    },
    {
        "id": "24fe7cc5.03a284",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 1650,
        "y": 20,
        "wires": []
    },
    {
        "id": "b56a71fb.69c95",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Put cell voltage into globals",
        "func": "var myLongmon;\n\nswitch(msg.payload.ID) {\n    case 1:\n        myLongmon=\"ONE\";\n        break;\n    case 2:\n        myLongmon=\"TWO\";\n        break;\n    case 3:\n        myLongmon=\"THREE\";\n        break;\n    case 4:\n        myLongmon=\"FOUR\";\n        break;\n    case 5:\n        myLongmon=\"FIVE\";\n        break;\n    case 6:\n        myLongmon=\"SIX\";\n        break;\n    case 7:\n        myLongmon=\"SEVEN\";\n        break;\n    case 8:\n        myLongmon=\"EIGHT\";\n        break;\n    case 9:\n        myLongmon=\"NINE\";\n        break;\n    case 10:\n        myLongmon=\"TEN\";\n        break;\n    case 11:\n        myLongmon=\"ELEVEN\";\n        break;\n    case 12:\n        myLongmon=\"TWELVE\";\n        break;\n    case 13:\n        myLongmon=\"THIRTEEN\";\n        break;\n    case 14:\n        myLongmon=\"FOURTEEN\";\n        break;\n    case 15:\n        myLongmon=\"FIFTEEN\";\n        break;\n    case 16:\n        myLongmon=\"SIXTEEN\";\n        break;\n}\n \nglobal.set(myLongmon,msg.payload.MaxCellVolt);    \n     \n//return msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "x": 1440,
        "y": 920,
        "wires": [
            [
                "ee919253.daba5"
            ]
        ]
    },
    {
        "id": "d9a8b490.a039d8",
        "type": "inject",
        "z": "e6fd3a1c.5e9548",
        "name": "Update the chart every 1 second",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "5",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 520,
        "y": 140,
        "wires": [
            [
                "6c1bb0a6.cde56",
                "7c2e474e.4fe348",
                "d54ad04d.f5cb8"
            ]
        ]
    },
    {
        "id": "602b821a.72b6bc",
        "type": "ui_chart",
        "z": "e6fd3a1c.5e9548",
        "name": "Realtime cell voltages",
        "group": "605bdeca.e6347",
        "order": 5,
        "width": "0",
        "height": "0",
        "label": "Cell voltages",
        "chartType": "bar",
        "legend": "false",
        "xformat": "HH:mm:ss",
        "interpolate": "linear",
        "nodata": "No Data",
        "dot": false,
        "ymin": "3",
        "ymax": "4.2",
        "removeOlder": 1,
        "removeOlderPoints": "",
        "removeOlderUnit": "3600",
        "cutout": 0,
        "useOneColor": true,
        "useUTC": false,
        "colors": [
            "#00aaff",
            "#b3dfea",
            "#ff7f0e",
            "#2ca02c",
            "#98df8a",
            "#d62728",
            "#ff9896",
            "#9467bd",
            "#c5b0d5"
        ],
        "outputs": 1,
        "x": 1400,
        "y": 60,
        "wires": [
            [
                "43701535.84212c"
            ]
        ]
    },
    {
        "id": "8445ce7c.09028",
        "type": "ui_text",
        "z": "e6fd3a1c.5e9548",
        "group": "605bdeca.e6347",
        "order": 1,
        "width": "0",
        "height": "0",
        "name": "Shunt Status: ",
        "label": "Shunt Status: ",
        "format": "{{msg.payload.ShuntStatus}}",
        "layout": "row-left",
        "x": 820,
        "y": 600,
        "wires": []
    },
    {
        "id": "34dd4fa2.32065",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "d": true,
        "name": "Msg_4732_HwSystemSetup",
        "func": "var Packet = global.get('binary_parser');\nvar buf = msg.payload;\n\nvar typea = new Packet()\n   .skip(8)\n      .uint8('isCriticalBattOkState')                 // Boolean 0 = Off , 1 = On\n      .uint8('isCriticalBattOkCalc')                          // Boolean 0 = Off , 1 = On\n      .uint8('isCriticalTransition')                          // Boolean 0 = Off , 1 = On\n      .uint8('hasCriticalCellOverdue')                // Boolean 0 = Off , 1 = On\n      .uint8('hasCriticalCellVoltLo')                 // Boolean 0 = Off , 1 = On\n      .uint8('hasCriticalCellVoltHi')                 // Boolean 0 = Off , 1 = On\n      .uint8('hasCriticalCellTempLo')                 // Boolean 0 = Off , 1 = On\n      .uint8('hasCriticalCellTempHi')                 // Boolean 0 = Off , 1 = On\n      .uint8('hasCriticalSupplyVoltLo')               // Boolean 0 = Off , 1 = On\n      .uint8('hasCriticalSupplyVoltHi')               // Boolean 0 = Off , 1 = On\n      .uint8('hasCriticalAmbientLo')                          // Boolean 0 = Off , 1 = On\n      .uint8('hasCriticalAmbientHi')                          // Boolean 0 = Off , 1 = On\n      .uint8('hasCriticalShuntVoltLo')                // Boolean 0 = Off , 1 = On\n      .uint8('hasCriticalShuntVoltHi')                // Boolean 0 = Off , 1 = On\n      .uint8('hasCriticalShuntVoltLoIdle')    // Boolean 0 = Off , 1 = On\n      .uint8('hasCriticalShuntPeakCharge')    // Boolean 0 = Off , 1 = On\n      .uint8('hasCriticalShuntPeakDischg')    // Boolean 0 = Off , 1 = On\n      .uint8('isChargeOnState')                               // Boolean 0 = Off , 1 = On\n      .uint8('isChargeLimPower')                              // Boolean 0 = Off , 1 = On\n      .uint8('isChargeTransition')                    // Boolean 0 = Off , 1 = On\n      .uint8('isChargePowerRateState') /* Choices ChargeRateStates\n                                Off                     = 0,\n                                Limited Power   = 2,\n                                Normal Power    = 4, */\n      .uint8('isChargePowerRateCalc')                 /* Choices ChargeRateStates */\n      .uint8('hasChargeCellVoltHi ')                          // Boolean 0 = Off , 1 = On\n      .uint8('hasChargeCellVoltPause ')               // Boolean 0 = Off , 1 = On\n      .uint8('hasChargeCellVoltLimPower ')    // Boolean 0 = Off , 1 = On\n      .uint8('hasChargeCellTempLo ')                          // Boolean 0 = Off , 1 = On\n      .uint8('hasChargeCellTempHi ')                          // Boolean 0 = Off , 1 = On\n      .uint8('hasChargeAmbientTempLo ')               // Boolean 0 = Off , 1 = On\n      .uint8('hasChargeAmbientTempHi ')               // Boolean 0 = Off , 1 = On\n      .uint8('hasChargeSupplyVoltHi ')                // Boolean 0 = Off , 1 = On\n      .uint8('hasChargeSupplyVoltPause ')     // Boolean 0 = Off , 1 = On\n      .uint8('hasChargeShuntVoltHi ')                 // Boolean 0 = Off , 1 = On\n      .uint8('hasChargeShuntVoltPause ')              // Boolean 0 = Off , 1 = On\n      .uint8('hasChargeShuntVoltLimPower ')   // Boolean 0 = Off , 1 = On\n      .uint8('hasChargeShuntSocHi ')                          // Boolean 0 = Off , 1 = On\n      .uint8('hasChargeShuntSocPause ')               // Boolean 0 = Off , 1 = On\n      .uint8('hasChargeAboveInitalBypass ')   // Boolean 0 = Off , 1 = On\n      .uint8('hasChargeAboveFinalBypass ')            // Boolean 0 = Off , 1 = On\n      .uint8('hasChargeInBypass ')                    // Boolean 0 = Off , 1 = On\n      .uint8('hasChargeBypassComplete ')              // Boolean 0 = Off , 1 = On\n      .uint8('hasChargeBypassTempRelief ')    // Boolean 0 = Off , 1 = On\n      .uint8('isDischgOnState ')                              // Boolean 0 = Off , 1 = On\n      .uint8('isDischgLimPower ')                     // Boolean 0 = Off , 1 = On\n      .uint8('isDischgTransition ')                   // Boolean 0 = Off , 1 = On\n      .uint8('isDischgPowerRateState ') /* Choices DischgRateStates\n                                Off                     = 0,\n                                Limited Power   = 2,\n                                Normal Power    = 4, */\n      .uint8('isDischgPowerRateCalc ')                /* Choices DischgRateStates */\n      .uint8('hasDischgCellVoltLo ')                          // Boolean 0 = Off , 1 = On\n      .uint8('hasDischgCellVoltPause ')               // Boolean 0 = Off , 1 = On\n      .uint8('hasDischgCellVoltLimPower ')    // Boolean 0 = Off , 1 = On\n      .uint8('hasDischgCellTempLo ')                          // Boolean 0 = Off , 1 = On\n      .uint8('hasDischgCellTempHi ')                          // Boolean 0 = Off , 1 = On\n      .uint8('hasDischgAmbientLo ')                   // Boolean 0 = Off , 1 = On\n      .uint8('hasDischgAmbientHi ')                   // Boolean 0 = Off , 1 = On\n      .uint8('hasDischgSupplyVoltLo ')                // Boolean 0 = Off , 1 = On\n      .uint8('hasDischgSupplyVoltPause ')     // Boolean 0 = Off , 1 = On\n      .uint8('hasDischgShuntVoltLo ')                 // Boolean 0 = Off , 1 = On\n      .uint8('hasDischgShuntVoltPause ')              // Boolean 0 = Off , 1 = On\n      .uint8('hasDischgShuntVoltLimPower ')   // Boolean 0 = Off , 1 = On\n      .uint8('hasDischgShuntSocLo ')                          // Boolean 0 = Off , 1 = On\n      .uint8('hasDischgShuntSocPause ')               // Boolean 0 = Off , 1 = On\n      .uint8('isHeatOnState ')                                // Boolean 0 = Off , 1 = On\n      .uint8('isHeatOnCalc ')                                 // Boolean 0 = Off , 1 = On\n      .uint8('isHeatTransition ')                     // Boolean 0 = Off , 1 = On\n      .uint8('hasHeatAmbientLo ')                     // Boolean 0 = Off , 1 = On\n      .uint8('hasHeatCellTempLo ')                    // Boolean 0 = Off , 1 = On\n      .uint8('isCoolOnState')                                 // Boolean 0 = Off , 1 = On\n      .uint8('isCoolOnCalc')                                          // Boolean 0 = Off , 1 = On\n      .uint8('isCoolTransition')                              // Boolean 0 = Off , 1 = On\n      .uint8('hasCoolAmbientHi ')                     // Boolean 0 = Off , 1 = On\n      .uint8('hasCoolCellTempHi ')                    // Boolean 0 = Off , 1 = On\n      .uint8('hasChargeBypassSessionLo ')    // Boolean 0 = Off , 1 = On\n\nmsg.payload = typea.parse(buf);\n\nswitch(msg.payload.isChargePowerRateState) {\n    case 0:\n        msg.payload.isChargePowerRateState = \"Off\";\n        break;\n    case 2:\n        msg.payload.isChargePowerRateState = \"Limited Power\";\n        break;\n    case 4:\n        msg.payload.isChargePowerRateState = \"Normal Power\";\n        break;\n    default:\n        msg.payload.isChargePowerRateState = \"Buggered\";\n}\n\nswitch(msg.payload.isDischgPowerRateState) {\n    case 0:\n        msg.payload.isDischgPowerRateState = \"Off\";\n        break;\n    case 2:\n        msg.payload.isDischgPowerRateState = \"Limited Power\";\n        break;\n    case 4:\n        msg.payload.isDischgPowerRateState = \"Normal Power\";\n        break;\n    default:\n        msg.payload.isDischgPowerRateState = \"Buggered\";\n}\n\n\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 120,
        "y": 1180,
        "wires": [
            [
                "e07437e.312e7c8"
            ]
        ]
    },
    {
        "id": "e07437e.312e7c8",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "d": true,
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 390,
        "y": 1180,
        "wires": []
    },
    {
        "id": "17a67e5b.e13952",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Msg_4d34_HwExpansionSetup",
        "func": "var Packet = global.get('binary_parser');\nvar buf = msg.payload;\n\nvar typea = new Packet()\n\t\t.skip(8)\n\t\t.uint8('HwExpansionSetupVers')  \n\t\t.uint8('HwExpansionTemplate')  /* ExtensionTemplateOptions\n\t\t\t\tNone = 0,\n\t\t\t\tExpansionBoard 12v = 1,\n\t\t\t\tExpansionBoard 48v = 2,\n\t\t\t\tWatchMonCmC v2.0   = 3,\t*/\t\n\t\t.uint8('HwExpansionNeoPixelMode')  /* NeoPixelExtStatusModes\n\t\t\t\tNone \t\t\t\t= 0,\n\t\t\t\tRepeat \t\t\t\t= 1,\n\t\t\t\tStatus + 7seg SoC% \t= 2,\n\t\t\t\tSolid SoC% 8seg \t= 3,\t*/\n\t\t.uint8('HwExpansionRelay1')  /* ExpansionOutputAssignments\n\t\t\t\tNone = 0,\n\t\t\t\tManualOn = 1,\n\t\t\t\tCritical BattOk = 2,\n\t\t\t\tCharging On = 4,\n\t\t\t\tDischarging On = 5,\n\t\t\t\tHeating Required = 6,\n\t\t\t\tCooling Required = 7,\n\t\t\t\tRun / Idle input = 8,\n\t\t\t\tCharge / Normal input = 9,\n\t\t\t\tBypass Complete = 10,\n\t\t\t\tCharging Limited = 11,\n\t\t\t\tDischarging Limited = 12,\n\t\t\t\tCritical Recovery = 13,\n\t\t\t\tCritical PulseOn = 14,\n\t\t\t\tCritical PulseOff = 15,\n\t\t\t\tCritical Fault = 16,\n\t\t\t\tCritical PrechargeTimer = 17, */\n\t\t.uint8('HwExpansionRelay2')  \t/* ExpansionOutputAssignments */\n\t\t.uint8('HwExpansionRelay3')  \t/* ExpansionOutputAssignments */\n\t\t.uint8('HwExpansionRelay4')\t\t/* ExpansionOutputAssignments */\n\t\t.uint8('HwExpansionOutput5')  \t/* ExpansionOutputAssignments */\n\t\t.uint8('HwExpansionOutput5')  \t/* ExpansionOutputAssignments */\n\t\t.uint8('HwExpansionOutput7')  \t/* ExpansionOutputAssignments */\n\t\t.uint8('HwExpansionOutput8')  \t/* ExpansionOutputAssignments */\n\t\t.uint8('HwExpansionOutput9')  \t/* ExpansionOutputAssignments */\n\t\t.uint8('HwExpansionOutput10') \t/* ExpansionOutputAssignments */\n\t\t.uint8('HwExpansionInput1')  \t/* ExtensionInputOptions\n\t\t\t\tNone \t\t\t\t\t= 0,\n\t\t\t\tRun / Idle mode \t\t= 1,\n\t\t\t\tCharge / Normal mode \t= 2,\n\t\t\t\tCritical contact sensor - On = 3,\n\t\t\t\tCritical contact sensor - Fault = 4, */\n\t\t.uint8('HwExpansionInput2')  \t/* ExtensionInputOptions */\n\t\t.uint8('HwExpansionInput3')  \t/* ExtensionInputOptions */\n\t\t.uint8('HwExpansionInput4')  \t/* ExtensionInputOptions */\n\t\t.uint8('HwExpansionInput5')  \t/* ExtensionInputOptions */\n\t\t.uint8('HwExpansionInputAIN1') \n\t\t.uint8('HwExpansionInputAIN2') \n\t\t.int16le('HwExpansionCustomFeature1')\n\t\t.int16le('HwExpansionCustomFeature2')\nmsg.payload = typea.parse(buf);\n\nswitch(msg.payload.HwExpansionTemplate) {\n    case 0:\n        msg.payload.HwExpansionTemplate = \"None\";\n        break;\n    case 1:\n        msg.payload.HwExpansionTemplate = \"ExpansionBoard 12v\";\n        break;\n    case 2:\n        msg.payload.HwExpansionTemplate = \"ExpansionBoard 48v\";\n        break;\n    case 3:\n        msg.payload.HwExpansionTemplate = \"WatchMonCmC v2.0\";\n        break;\n    default:\n        msg.payload.HwExpansionTemplate = \"Buggered\";\n}\n\nswitch(msg.payload.HwExpansionNeoPixelMode) {\n    case 0:\n        msg.payload.HwExpansionNeoPixelMode = \"None\";\n        break;\n    case 1:\n        msg.payload.HwExpansionNeoPixelMode = \"Repeat\";\n        break;\n    case 2:\n        msg.payload.HwExpansionNeoPixelMode = \"Status + 7seg SoC%\";\n        break;\n    case 3:\n        msg.payload.HwExpansionNeoPixelMode = \"Solid SoC% 8seg\";\n        break;\n    default:\n        msg.payload.HwExpansionNeoPixelMode = \"Buggered\";\n}\n\nswitch(msg.payload.HwExpansionRelay1) {\n    case 0:\n        msg.payload.HwExpansionRelay1 = \"None\";\n        break;\n    case 1:\n        msg.payload.HwExpansionRelay1 = \"ManualOn\";\n        break;\n    case 2:\n        msg.payload.HwExpansionRelay1 = \"Critical BattOk\";\n        break;\n    case 3:\n        msg.payload.HwExpansionRelay1 = \"Charging On\";\n        break;\n    case 4:\n        msg.payload.HwExpansionRelay1 = \"Discharging On\";\n        break;\n    case 5:\n        msg.payload.HwExpansionRelay1 = \"Heating Required\";\n        break;\n    case 6:\n        msg.payload.HwExpansionRelay1 = \"Cooling Required\";\n        break;\n    case 7:\n        msg.payload.HwExpansionRelay1 = \"Run / Idle input\";\n        break;\n    case 8:\n        msg.payload.HwExpansionRelay1 = \"Charge / Normal input\";\n        break;\n    case 9:\n        msg.payload.HwExpansionRelay1 = \"Bypass Complete\";\n        break;\n    case 10:\n        msg.payload.HwExpansionRelay1 = \"Charging Limited\";\n        break;\n    case 11:\n        msg.payload.HwExpansionRelay1 = \"Discharging Limited\";\n        break;\n    case 12:\n        msg.payload.HwExpansionRelay1 = \"Critical Recovery\";\n        break;\n    case 13:\n        msg.payload.HwExpansionRelay1 = \"Critical PulseOn\";\n        break;\n    case 14:\n        msg.payload.HwExpansionRelay1 = \"Critical PulseOff\";\n        break;\n    case 105:\n        msg.payload.HwExpansionRelay1 = \"Critical Fault\";\n        break;\n    case 16:\n        msg.payload.HwExpansionRelay1 = \"Critical PrechargeTimer\";\n        break;\n    default:\n        msg.payload.HwExpansionRelay1 = \"Buggered\";\n}\n\nswitch(msg.payload.HwExpansionInput1) {\n    case 0:\n        msg.payload.HwExpansionInput1 = \"None\";\n        break;\n    case 1:\n        msg.payload.HwExpansionInput1 = \"Run / Idle mode\";\n        break;\n    case 2:\n        msg.payload.HwExpansionInput1 = \"Charge / Normal mode\";\n        break;\n    case 3:\n        msg.payload.HwExpansionInput1 = \"Critical contact sensor - On\";\n        break;\n    case 4:\n        msg.payload.HwExpansionInput1 = \"Critical contact sensor - Fault\";\n        break;\n    default:\n        msg.payload.HwExpansionInput1 = \"Buggered\";\n}\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 130,
        "y": 1220,
        "wires": [
            [
                "d4d7f79b.18b4d8"
            ]
        ]
    },
    {
        "id": "d4d7f79b.18b4d8",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "d": true,
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 390,
        "y": 1220,
        "wires": []
    },
    {
        "id": "e69dec4b.f16a1",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "d": true,
        "name": "Msg_6132_StatusComms",
        "func": "var Packet = global.get('binary_parser');\nvar buf = msg.payload;\n\nvar typea = new Packet()\n\n\t\t.skip(8)\n\t\t.uint32le('SystemTime') // Epoch\n\t\t.uint8('SystemOpStatus') /* Choices\n\t\t\t\tSimulator = 0,   \t  // LED = rainbow pulse\n\t\t\t\tIdle = 1,        \t  // LED = green slow pulse\n\t\t\t\tDischarging = 2, \t  // LED = green solid \n\t\t\t\tSoC Empty = 3,   \t  // LED = green double blink\n\t\t\t\tCharging = 4,    \t  // LED = blue slow pulse\n\t\t\t\tFull = 5,        \t  // LED = blue double blink\n\t\t\t\tTimeout = 6,     \t  // LED = red solid\n\t\t\t\tCritical Pending = 7, // LED = red fast pulse\n\t\t\t\tCritical Offline = 8, // LED = red slow pulse\n\t\t\t\tMqtt Offline = 9,     // LED = white blink\n\t\t\t\tAuth Setup = 10,      // LED = white solid\n\t\t\t\tShunt Timeout = 11,   // LED = red solid  \t*/\n\t\t.uint8('SystemAuthMode') /* Choices\n\t\t\t\tDefault = 0,\n\t\t\t\tTechnician = 1,\n\t\t\t\tFactory = 2, */\n\t\t.int16le('SystemAuthToken')\n\t\t.int16le('SystemAuthRejectTicks')\n\t\t.uint8('WifiState') /* Choices WifiOpStates\n\t\t\t\tBroadcast Start = 0,\n\t\t\t\tBroadcast Prep = 1,\n\t\t\t\tBroadcast TxSetup = 2,\n\t\t\t\tBroadcast Running = 3,\n\t\t\t\tUsbCmd Start = 4,\n\t\t\t\tUsbCmd Running = 5,\n\t\t\t\tUsbCmd PassThru = 6,\n\t\t\t\tUsbProg Start = 7,\n\t\t\t\tUsbProg Running = 8,\n\t\t\t\tUsbProg PassThru = 9,\n\t\t\t\tOffline Start = 10,\n\t\t\t\tOffline Running = 11,\n\t\t\t\tOffline Stop = 12,\n\t\t\t\tLimited Start = 13,\n\t\t\t\tLimited Prep = 14,\n\t\t\t\tLimited Running = 15,\n\t\t\t\tJoinAp Start = 16,\n\t\t\t\tJoinAp Running = 17,\t*/\t\t\n\t\t.uint8('WifiTxCmdTicks') \n\t\t.uint8('WifiRxCmdTicks') \n\t\t.uint8('WifiRxUnknownTicks') \n\t\t.uint8('CanbusOpStatus') /* Choices \n\n\t\t\t\t \t*/\t\t\n\t\t.uint8('CanbusRxStatusTicks')\n\t\t.uint8('CanbusRxUnknownTicks')\n\t\t.uint8('CanbusRxStatusTicks')\n\t\t.uint8('ShuntPollerMode') /* Choices ShuntPollerModes\n\t\t\t\tIdle Start = 0,\n\t\t\t\tIdle = 1,\n\t\t\t\tSync Start = 2,\n\t\t\t\tSync Running = 3,\n\t\t\t\tNormal = 4,\n\t\t\t\tShuntMon2 SetupStart = 5,\n\t\t\t\tShuntMon2 SetupRunning = 6,\n\t\t\t\tShuntMon2 Normal = 7, */\n\t\t.uint8('ShuntStatus') /* Choices  ShuntStatuses\n\t\t\t\tTimeout = 0,\n\t\t\t\tDischarging = 1,\n\t\t\t\tIdle = 2,\n\t\t\t\tCharging = 4 */\n\t\t.uint8('ShuntRxAmpTicks')\n\t\t.uint8('ShuntTxAmpTicks')\n\t\t.uint8('CmuPollerMode') \t    /* Choices\n\t\t\t\tIdle = 0,\n\t\t\t\tNormal = 1,\n\t\t\t\tCollection Start = 2,\n\t\t\t\tCollection Running = 3,\n\t\t\t\tSync Start = 4,\n\t\t\t\tSync Running = 5,\n\t\t\t\tNetworkTest Start = 6,\n\t\t\t\tNetworkTest Running = 9,\n\t\t\t\tBypassTest Start = 7,\n\t\t\t\tBypassTest Running = 8,\n\t\t\t\tRebootAll Start = 10,\n\t\t\t\tRebooting AllDevices = 11,\n\t\t\t\tSimulator Start = 12,\n\t\t\t\tSimulator Running = 13, */\n\t\t\t.uint8('CmuOpStatus') /* Choices */\n\t\t\t.uint8('CmuTxCmdTicks')\n\t\t\t.uint8('CmuRxCmdTicks')\n\nmsg.payload = typea.parse(buf);\n\n// convert date(s)\nmsg.payload.SystemTime = new Date(msg.payload.SystemTime*1000);\n\nswitch(msg.payload.SystemOpStatus) {\n    case 0:\n        msg.payload.SystemOpStatus = \"Simulator\";\n        break;\n    case 1:\n        msg.payload.SystemOpStatus = \"Idle\";\n        break;\n    case 2:\n        msg.payload.SystemOpStatus = \"Discharging\";\n        break;\n    case 3:\n        msg.payload.SystemOpStatus = \"SoC Empty\";\n        break;\n    case 4:\n        msg.payload.SystemOpStatus = \"Charging\";\n        break;\n    case 5:\n        msg.payload.SystemOpStatus = \"Full\";\n        break;\n    case 6:\n        msg.payload.SystemOpStatus = \"Timeout\";\n        break;\n    case 7:\n        msg.payload.SystemOpStatus = \"Critical Pending\";\n        break;\n    case 8:\n        msg.payload.SystemOpStatus = \"Critical Offline\";\n        break;\n    case 9:\n        msg.payload.SystemOpStatus = \"Mqtt Offline\";\n        break;\n    case 10:\n        msg.payload.SystemOpStatus = \"Auth Setup\";\n        break;\n    case 11:\n        msg.payload.SystemOpStatus = \"Shunt Timeout\";\n        break;\n    default:\n        msg.payload.SystemOpStatus = \"Buggered\";\n}\n\nswitch(msg.payload.SystemAuthMode) {\n    case 0:\n        msg.payload.SystemAuthMode = \"Default\";\n        break;\n    case 1:\n        msg.payload.SystemAuthMode = \"Technician\";\n        break;\n    case 2:\n        msg.payload.SystemAuthMode = \"Factory\";\n        break;\n    default:\n        msg.payload.SystemAuthMode = \"Buggered\";\n}\n\nswitch(msg.payload.WifiState) {\n    case 0:\n        msg.payload.WifiState = \"Broadcast Start\";\n        break;\n    case 1:\n        msg.payload.WifiState = \"Broadcast Prep\";\n        break;\n    case 2:\n        msg.payload.WifiState = \"Broadcast TxSetup\";\n        break;\n    case 3:\n        msg.payload.WifiState = \"Broadcast Running\";\n        break;\n    case 4:\n        msg.payload.WifiState = \"UsbCmd Start\";\n        break;\n    case 5:\n        msg.payload.WifiState = \"UsbCmd Running\";\n        break;\n    case 6:\n        msg.payload.WifiState = \"UsbCmd PassThru\";\n        break;\n    case 7:\n        msg.payload.WifiState = \"UsbProg Start\";\n        break;\n    case 8:\n        msg.payload.WifiState = \"UsbProg Running\";\n        break;\n    case 9:\n        msg.payload.WifiState = \"UsbProg PassThru\";\n        break;\n    case 10:\n        msg.payload.WifiState = \"Offline Start\";\n        break;\n    case 11:\n        msg.payload.WifiState = \"Offline Running\";\n        break;\n    case 12:\n        msg.payload.WifiState = \"Offline Stop\";\n        break;\n    case 13:\n        msg.payload.WifiState = \"Limited Start\";\n        break;\n    case 14:\n        msg.payload.WifiState = \"Limited Prep\";\n        break;\n    case 15:\n        msg.payload.WifiState = \"Limited Running\";\n        break;\n    case 16:\n        msg.payload.WifiState = \"JoinAp Start\";\n        break;\n    case 17:\n        msg.payload.WifiState = \"JoinAp Running\";\n        break;\n    default:\n        msg.payload.WifiState = \"Buggered\";\n}\n\nswitch(msg.payload.ShuntPollerMode) {\n    case 0:\n        msg.payload.ShuntPollerMode = \"Idle Start\";\n        break;\n    case 1:\n        msg.payload.ShuntPollerMode = \"Idle\";\n        break;\n    case 2:\n        msg.payload.ShuntPollerMode = \"Sync Start\";\n        break;\n    case 3:\n        msg.payload.ShuntPollerMode = \"Sync Running\";\n        break;\n    case 4:\n        msg.payload.ShuntPollerMode = \"Normal\";\n        break;\n    case 5:\n        msg.payload.ShuntPollerMode = \"ShuntMon2 SetupStart\";\n        break;\n    case 6:\n        msg.payload.ShuntPollerMode = \"ShuntMon2 SetupRunning\";\n        break;\n    case 7:\n        msg.payload.ShuntPollerMode = \"ShuntMon2 Normal\";\n        break;\n    default:\n        msg.payload.ShuntPollerMode = \"Buggered\";\n}\n\nswitch(msg.payload.ShuntStatus) {\n    case 0:\n        msg.payload.ShuntStatus = \"Timeout\";\n        break;\n    case 1:\n        msg.payload.ShuntStatus = \"Discharging\";\n        break;\n    case 2:\n        msg.payload.ShuntStatus = \"Idle\";\n        break;\n    case 4:\n        msg.payload.ShuntStatus = \"Charging\";\n        break;\n    default:\n        msg.payload.ShuntStatus = \"Buggered\";\n}\n/*\nswitch(msg.payload.CmuPollerMode) {\n    case 0:\n        msg.payload.CmuPollerMode = \"Idle\";\n        break;\n    case 1:\n        msg.payload.CmuPollerMode = \"Normal\";\n        break;\n    case 2:\n        msg.payload.CmuPollerMode = \"Collection Start\";\n        break;\n    case 3:\n        msg.payload.CmuPollerMode = \"Collection Running\";\n        break;\n    case 4:\n        msg.payload.CmuPollerMode = \"Sync Start\";\n        break;\n    case 5:\n        msg.payload.CmuPollerMode = \"Sync Running\";\n        break;\n    case 6:\n        msg.payload.CmuPollerMode = \"NetworkTest Start\";\n        break;\n    case 7:\n        msg.payload.CmuPollerMode = \"NetworkTest Running\";\n        break;\n    case 8:\n        msg.payload.CmuPollerMode = \"BypassTest Start\";\n        break;\n    case 9:\n        msg.payload.CmuPollerMode = \"BypassTest Running\";\n        break;\n    case 10:\n        msg.payload.CmuPollerMode = \"RebootAll Start\";\n        break;\n    case 11:\n        msg.payload.CmuPollerMode = \"Rebooting AllDevices\";\n        break;\n    case 12:\n        msg.payload.CmuPollerMode = \"Simulator Start\";\n        break;\n    case 13:\n        msg.payload.CmuPollerMode = \"Simulator Running\";\n        break;\n    default:\n        msg.payload.CmuPollerMode = \"Buggered\";\n}\n*/\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 110,
        "y": 1260,
        "wires": [
            [
                "15668e4f.43b272"
            ]
        ]
    },
    {
        "id": "15668e4f.43b272",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "d": true,
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 390,
        "y": 1260,
        "wires": []
    },
    {
        "id": "1febde5.094d722",
        "type": "comment",
        "z": "e6fd3a1c.5e9548",
        "name": "Based on Watchmon SW 1.0.30 UDP Outbound protocol",
        "info": "All credit for the parsers to Daniel Römer\nBased on his grafpi project:\nhttp://diytechandrepairs.nu/raspberry-solar/\n\nBatrium WatchMon 4\n\nThe machine running node red must be able \nto acces port 18542 UDP IPv4\n\n",
        "x": 690,
        "y": 240,
        "wires": []
    },
    {
        "id": "b2ab7d4c.b3ddd",
        "type": "ui_text",
        "z": "e6fd3a1c.5e9548",
        "group": "605bdeca.e6347",
        "order": 0,
        "width": "3",
        "height": "2",
        "name": "GroupMinCellVolt",
        "label": "Min Cell Voltage",
        "format": "{{msg.payload.GroupMinCellVolt}}v",
        "layout": "col-center",
        "x": 830,
        "y": 680,
        "wires": []
    },
    {
        "id": "68635fb7.0529d",
        "type": "ui_text",
        "z": "e6fd3a1c.5e9548",
        "group": "605bdeca.e6347",
        "order": 0,
        "width": "3",
        "height": "2",
        "name": "GroupMaxCellVolt",
        "label": "Max Cell Voltage",
        "format": "{{msg.payload.GroupMaxCellVolt}}v",
        "layout": "col-center",
        "x": 830,
        "y": 560,
        "wires": []
    },
    {
        "id": "7c2e474e.4fe348",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Cells Global variables for influx",
        "func": "var ONE = global.get('ONE') || 0;\nvar TWO = global.get('TWO') || 0;\nvar THREE = global.get('THREE') || 0;\nvar FOUR = global.get('FOUR') || 0;\nvar FIVE = global.get('FIVE') || 0;\nvar SIX = global.get('SIX') || 0;\nvar SEVEN = global.get('SEVEN') || 0;\nvar EIGHT = global.get('EIGHT') || 0;\nvar NINE = global.get('NINE') || 0;\nvar TEN = global.get('TEN') || 0;\nvar ELEVEN = global.get('ELEVEN') || 0;\nvar TWELVE = global.get('TWELVE') || 0;\nvar THIRTEEN = global.get('THIRTEEN') || 0;\nvar FOURTEEN = global.get('FOURTEEN') || 0;\nvar FIFTEEN = global.get('FIFTEEN') || 0;\nvar SIXTEEN = global.get('SIXTEEN') || 0;\n\nmsg.payload =\n{\n    Cell1: ONE,\n    Cell2: TWO,\n    Cell3: THREE,\n    Cell4: FOUR,\n    Cell5: FIVE,\n    Cell6: SIX,\n    Cell7: SEVEN,\n    Cell8: EIGHT,\n    Cell9: NINE,\n    Cell10: TEN,\n    Cell11: ELEVEN,\n    Cell12: TWELVE,\n    CELL13: THIRTEEN,\n    CELL14: FOURTEEN,\n    CELL15: FIFTEEN,\n    CELL16: SIXTEEN,\n}\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "x": 870,
        "y": 100,
        "wires": [
            [
                "6d22e4f3.72c97c",
                "f27ec1c6.f257"
            ]
        ]
    },
    {
        "id": "6d22e4f3.72c97c",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 1650,
        "y": 100,
        "wires": []
    },
    {
        "id": "f27ec1c6.f257",
        "type": "influxdb out",
        "z": "e6fd3a1c.5e9548",
        "influxdb": "bafffa78.f7bbc8",
        "name": "Cell_Voltage",
        "measurement": "Cell_Voltage",
        "precision": "",
        "retentionPolicy": "",
        "database": "",
        "retentionPolicyV18Flux": "",
        "org": "",
        "bucket": "",
        "x": 1430,
        "y": 120,
        "wires": []
    },
    {
        "id": "684ac7ee.c50fc8",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "DailyCumulShuntAh_C_D Influx",
        "func": "var CSAD  = 0;\nvar CSAC  = 0;\nCSAD = Number(msg.payload.DailySessionCumulShuntAhDischg);\nCSAC = Number(msg.payload.DailySessionCumulShuntAhCharge);\nmsg.payload =\n{\n    CumulShuntAhDischg: CSAD,\n    CumulShuntAhCharge: CSAC,\n}\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 1190,
        "y": 540,
        "wires": [
            [
                "b957de47.0dd2f",
                "a2d070e7.f7336"
            ]
        ]
    },
    {
        "id": "b957de47.0dd2f",
        "type": "influxdb out",
        "z": "e6fd3a1c.5e9548",
        "influxdb": "bafffa78.f7bbc8",
        "name": "CumulShuntAh_C_D",
        "measurement": "CumulShuntAh_C_D",
        "precision": "",
        "retentionPolicy": "",
        "x": 1460,
        "y": 560,
        "wires": []
    },
    {
        "id": "a2d070e7.f7336",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "x": 1650,
        "y": 540,
        "wires": []
    },
    {
        "id": "b7222b59.93edf8",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Cell_Min_Max_Avg Influx",
        "func": "var MiCV  = 0;\nvar MaCV  = 0;\nvar AvCV  = 0;\nMiCV = Number(msg.payload.MinCellVolt);\nMaCV = Number(msg.payload.MaxCellVolt);\nAvCV = Number(msg.payload.AvgCellVolt);\nmsg.payload =\n{\n    MiCV: MiCV,\n    MaCV: MaCV,\n    AvCV: AvCV,\n}\nreturn msg;\n",
        "outputs": 1,
        "noerr": 0,
        "x": 1170,
        "y": 220,
        "wires": [
            [
                "ad2c8772.107fa8",
                "25fa4777.c5eb08"
            ]
        ]
    },
    {
        "id": "ad2c8772.107fa8",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "x": 1650,
        "y": 220,
        "wires": []
    },
    {
        "id": "76bfaed9.eb6",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Shunt_C_V_W Influx",
        "func": "var ShuntV  = 0;\nvar ShuntC  = 0;\nvar myCurrent = 0;\nvar myVoltage = 0;\nvar Watts = 0;\nShuntV = Number(msg.payload.ShuntVoltage);\nShuntC = Number(msg.payload.ShuntCurrent);\nmyCurrent = Number(msg.payload.ShuntCurrent);\nmyVoltage = Number(msg.payload.ShuntVoltage);\nWatts=myVoltage*myCurrent;\nmsg.payload =\n{\n    ShuntV: ShuntV,\n    ShuntC: ShuntC,\n    Watts: Watts,\n}\nreturn msg;\n",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "x": 1160,
        "y": 180,
        "wires": [
            [
                "71217755.f344d8",
                "c324df89.b0e6c"
            ]
        ]
    },
    {
        "id": "71217755.f344d8",
        "type": "influxdb out",
        "z": "e6fd3a1c.5e9548",
        "influxdb": "bafffa78.f7bbc8",
        "name": "Shunt_C_V_W",
        "measurement": "Shunt_C_V_W",
        "precision": "",
        "retentionPolicy": "",
        "database": "",
        "retentionPolicyV18Flux": "",
        "org": "",
        "bucket": "",
        "x": 1440,
        "y": 160,
        "wires": []
    },
    {
        "id": "c324df89.b0e6c",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "x": 1650,
        "y": 180,
        "wires": []
    },
    {
        "id": "6476769.7ee5988",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Shunt_Cap_F_E_SOC Influx",
        "func": "var CtoF  = 0;\nvar CtoE  = 0;\nvar SOC  = 0;\nCtoF = Number(msg.payload.NomCapacityToFull);\nCtoE = Number(msg.payload.NomCapacityToEmpty);\nSOC = Number(msg.payload.ShuntSOC);\nmsg.payload =\n{\n   CtoF: CtoF,\n   CtoE: CtoE,\n    SOC: SOC,\n}\nreturn msg;\n",
        "outputs": 1,
        "noerr": 0,
        "x": 1180,
        "y": 680,
        "wires": [
            [
                "2ee7190.18693e8",
                "9c618b31.f4dd78"
            ]
        ]
    },
    {
        "id": "2ee7190.18693e8",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "x": 1650,
        "y": 680,
        "wires": []
    },
    {
        "id": "9c618b31.f4dd78",
        "type": "influxdb out",
        "z": "e6fd3a1c.5e9548",
        "influxdb": "bafffa78.f7bbc8",
        "name": "Shunt_Cap_F_E_SOC",
        "measurement": "Shunt_Cap_F_E_SOC",
        "precision": "",
        "retentionPolicy": "",
        "x": 1460,
        "y": 700,
        "wires": []
    },
    {
        "id": "25fa4777.c5eb08",
        "type": "influxdb out",
        "z": "e6fd3a1c.5e9548",
        "influxdb": "bafffa78.f7bbc8",
        "name": "Cell_Min_Max_Avg",
        "measurement": "Cell_Min_Max_Avg",
        "precision": "",
        "retentionPolicy": "",
        "x": 1450,
        "y": 200,
        "wires": []
    },
    {
        "id": "63dc95b5.2a2dcc",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Shunt_Status Influx",
        "func": "var SS;\nSS = (msg.payload.ShuntStatus);\nmsg.payload =\n{\n  SS: SS,\n}\nreturn msg;\n",
        "outputs": 1,
        "noerr": 0,
        "x": 1150,
        "y": 720,
        "wires": [
            [
                "b2e669b.0600398",
                "3f760caf.ca21e4"
            ]
        ]
    },
    {
        "id": "b2e669b.0600398",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "x": 1650,
        "y": 720,
        "wires": []
    },
    {
        "id": "3f760caf.ca21e4",
        "type": "influxdb out",
        "z": "e6fd3a1c.5e9548",
        "influxdb": "bafffa78.f7bbc8",
        "name": "Shunt_Status",
        "measurement": "Shunt_Status",
        "precision": "",
        "retentionPolicy": "",
        "x": 1480,
        "y": 740,
        "wires": []
    },
    {
        "id": "7e92a896.171e58",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "DailySessionShuntPeak_C_D Influx",
        "func": "var DSSPD  = 0;\nvar DSSPC  = 0;\nDSSPC = Number(msg.payload.DailySessionShuntPeakCharge);\nDSSPD = Number(msg.payload.DailySessionShuntPeakDischg);\nmsg.payload =\n{\n    ShuntPeakCharge: DSSPC,\n    ShuntPeakDischg: DSSPD,\n}\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 1200,
        "y": 580,
        "wires": [
            [
                "f0f77762.36efe8",
                "37822374.97f4ec"
            ]
        ]
    },
    {
        "id": "f0f77762.36efe8",
        "type": "influxdb out",
        "z": "e6fd3a1c.5e9548",
        "influxdb": "bafffa78.f7bbc8",
        "name": "ShuntPeak_C_D",
        "measurement": "ShuntPeak_C_D",
        "precision": "",
        "retentionPolicy": "",
        "x": 1470,
        "y": 620,
        "wires": []
    },
    {
        "id": "37822374.97f4ec",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "x": 1650,
        "y": 580,
        "wires": []
    },
    {
        "id": "ee919253.daba5",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "x": 1650,
        "y": 920,
        "wires": []
    },
    {
        "id": "43701535.84212c",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 1650,
        "y": 60,
        "wires": []
    },
    {
        "id": "739bdfbd.80809",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "ShuntVoltage",
        "func": "var myNumber = 0;\nmyNumber = Number(msg.payload.ShuntVoltage);\nreturn { payload : myNumber.toFixed(2) };",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "x": 1130,
        "y": 260,
        "wires": [
            [
                "d29957c5.1270e8",
                "869abefc.09573",
                "51929c.16d05d64"
            ]
        ]
    },
    {
        "id": "d29957c5.1270e8",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "d": true,
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 1650,
        "y": 260,
        "wires": []
    },
    {
        "id": "8fce0a5e.09d718",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "ShuntCurrent",
        "func": "var myNumber = 0;\nmyNumber = Number(msg.payload.ShuntCurrent);\nreturn { payload : myNumber.toFixed(2) };",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "x": 1130,
        "y": 300,
        "wires": [
            [
                "8c0ce1a3.2b188",
                "5049668e.8aca08",
                "f3feb017.6f298"
            ]
        ]
    },
    {
        "id": "8c0ce1a3.2b188",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "d": true,
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 1650,
        "y": 300,
        "wires": []
    },
    {
        "id": "bdb0b97d.26f5c8",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "d": true,
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 1650,
        "y": 340,
        "wires": []
    },
    {
        "id": "ab145d35.a525d",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "ShuntWatts",
        "func": "var myCurrent = 0;\nvar myVoltage = 0;\nvar myWatts = 0;\n\nmyCurrent = Number(msg.payload.ShuntCurrent);\nmyVoltage = Number(msg.payload.ShuntVoltage);\n\nmyWatts=myVoltage*myCurrent;\n\nreturn { payload : myWatts.toFixed(2) };",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "x": 1130,
        "y": 340,
        "wires": [
            [
                "bdb0b97d.26f5c8",
                "f81ecab4.48ca38"
            ]
        ]
    },
    {
        "id": "5049668e.8aca08",
        "type": "ui_text",
        "z": "e6fd3a1c.5e9548",
        "group": "605bdeca.e6347",
        "order": 3,
        "width": "0",
        "height": "0",
        "name": "Shunt Amps: ",
        "label": "Shunt Amps: ",
        "format": "{{msg.payload}}A",
        "layout": "col-center",
        "x": 1430,
        "y": 320,
        "wires": []
    },
    {
        "id": "869abefc.09573",
        "type": "ui_text",
        "z": "e6fd3a1c.5e9548",
        "group": "605bdeca.e6347",
        "order": 2,
        "width": "0",
        "height": "0",
        "name": "Shunt Volts: ",
        "label": "Shunt Volts: ",
        "format": "{{msg.payload}}v",
        "layout": "col-center",
        "x": 1430,
        "y": 280,
        "wires": []
    },
    {
        "id": "f81ecab4.48ca38",
        "type": "ui_text",
        "z": "e6fd3a1c.5e9548",
        "group": "605bdeca.e6347",
        "order": 4,
        "width": "0",
        "height": "0",
        "name": "Shunt Watts: ",
        "label": "Shunt Watts: ",
        "format": "{{msg.payload}}W",
        "layout": "col-center",
        "x": 1430,
        "y": 360,
        "wires": []
    },
    {
        "id": "51929c.16d05d64",
        "type": "ui_gauge",
        "z": "e6fd3a1c.5e9548",
        "name": "Shunt V",
        "group": "b37bd0d4.0bb66",
        "order": 7,
        "width": 0,
        "height": 0,
        "gtype": "gage",
        "title": "Shunt V",
        "label": "units",
        "format": "{{value}}",
        "min": "40",
        "max": "60",
        "colors": [
            "#eb3d1e",
            "#e6e600",
            "#52cb3a"
        ],
        "seg1": "",
        "seg2": "",
        "x": 1280,
        "y": 280,
        "wires": []
    },
    {
        "id": "f3feb017.6f298",
        "type": "ui_gauge",
        "z": "e6fd3a1c.5e9548",
        "name": "Shunt A",
        "group": "e2c441d6.9e1ae",
        "order": 0,
        "width": 0,
        "height": 0,
        "gtype": "gage",
        "title": "Shunt A",
        "label": "units",
        "format": "{{value}}",
        "min": "-50",
        "max": "50",
        "colors": [
            "#b31200",
            "#e6e600",
            "#54c00c"
        ],
        "seg1": "",
        "seg2": "",
        "x": 1280,
        "y": 320,
        "wires": []
    },
    {
        "id": "d54ad04d.f5cb8",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "16 Cell ",
        "func": "var ONE = Number(global.get('ONE')) || 0;\nvar TWO = Number(global.get('TWO')) || 0;\nvar THREE = Number(global.get('THREE')) || 0;\nvar FOUR = Number(global.get('FOUR')) || 0;\nvar FIVE = Number(global.get('FIVE')) || 0;\nvar SIX = Number(global.get('SIX')) || 0;\nvar SEVEN = Number(global.get('SEVEN')) || 0;\nvar EIGHT = Number(global.get('EIGHT')) || 0;\nvar NINE = Number(global.get('NINE')) || 0;\nvar TEN = Number(global.get('TEN')) || 0;\nvar ELEVEN = Number(global.get('ELEVEN')) || 0;\nvar TWELVE = Number(global.get('TWELVE')) || 0;\nvar THIRTEEN = Number(global.get('THIRTEEN')) || 0;\nvar FOURTEEN = Number(global.get('FOURTEEN')) || 0;\nvar FIFTEEN = Number(global.get('FIFTEEN')) || 0;\nvar SIXTEEN = Number(global.get('SIXTEEN')) || 0;\n\nvar m = {};\nm.series = [\"B1\", \"B2\"];\nm.data = [ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELVE, THIRTEEN, FOURTEEN, FIFTEEN, SIXTEEN];\nm.labels = [\"\"];\nreturn {payload:[m],topic:msg.topic};",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "x": 800,
        "y": 60,
        "wires": [
            [
                "5c74ba3e.11c214"
            ]
        ]
    },
    {
        "id": "9a44bb7a.474bd8",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Est to full/empty min influx",
        "func": "var EDF;\nvar EDE;\nEDF = (msg.payload.EstDurationToFullmins);\nEDE = (msg.payload.EstDurationToEmptymins);\nmsg.payload =\n{\n  EDF: EDF,\n  EDE: EDE,\n}\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 1170,
        "y": 460,
        "wires": [
            [
                "b2853dfb.645d9",
                "d280fff4.b0597"
            ]
        ]
    },
    {
        "id": "b2853dfb.645d9",
        "type": "debug",
        "z": "e6fd3a1c.5e9548",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "x": 1650,
        "y": 460,
        "wires": []
    },
    {
        "id": "d280fff4.b0597",
        "type": "influxdb out",
        "z": "e6fd3a1c.5e9548",
        "influxdb": "bafffa78.f7bbc8",
        "name": "EST-Full_Empty_Min",
        "measurement": "EST-Full_Empty_Min",
        "precision": "",
        "retentionPolicy": "",
        "x": 1460,
        "y": 480,
        "wires": []
    },
    {
        "id": "90437fe0.fcd83",
        "type": "function",
        "z": "e6fd3a1c.5e9548",
        "name": "Test",
        "func": "var EDTF;\nvar EDTE;\nEDTF = (msg.payload.EstDurationToFullmins);\nEDTE = (msg.payload.EstDurationToEmptymins);\nmsg.payload =\n{\n  EDTF: EDTF,\n  EDTE: EDTE,\n}\nreturn msg;\n",
        "outputs": 1,
        "noerr": 0,
        "x": 1510,
        "y": 840,
        "wires": [
            [
                "df5c7d37.bd20b"
            ]
        ]
    },
    {
        "id": "5c74ba3e.11c214",
        "type": "ui_chart",
        "z": "e6fd3a1c.5e9548",
        "name": "",
        "group": "b0f57fc2.e496c",
        "order": 0,
        "width": 0,
        "height": 0,
        "label": "chart",
        "chartType": "bar",
        "legend": "false",
        "xformat": "HH:mm:ss",
        "interpolate": "linear",
        "nodata": "",
        "dot": false,
        "ymin": "3",
        "ymax": "4.2",
        "removeOlder": 1,
        "removeOlderPoints": "",
        "removeOlderUnit": "3600",
        "cutout": 0,
        "useOneColor": false,
        "useUTC": false,
        "colors": [
            "#1f77b4",
            "#aec7e8",
            "#ff7f0e",
            "#2ca02c",
            "#98df8a",
            "#d62728",
            "#ff9896",
            "#9467bd",
            "#c5b0d5"
        ],
        "outputs": 1,
        "x": 950,
        "y": 60,
        "wires": [
            []
        ]
    },
    {
        "id": "605bdeca.e6347",
        "type": "ui_group",
        "name": "16 Cell",
        "tab": "f3fb9943.a12128",
        "order": 2,
        "disp": true,
        "width": "6",
        "collapse": false
    },
    {
        "id": "bafffa78.f7bbc8",
        "type": "influxdb",
        "hostname": "localhost",
        "port": "8086",
        "protocol": "http",
        "database": "batrium",
        "name": "",
        "usetls": false,
        "tls": "",
        "influxdbVersion": "1.x",
        "url": "",
        "rejectUnauthorized": false
    },
    {
        "id": "b37bd0d4.0bb66",
        "type": "ui_group",
        "name": "ShuntV",
        "tab": "f3fb9943.a12128",
        "order": 3,
        "disp": true,
        "width": "6",
        "collapse": false
    },
    {
        "id": "e2c441d6.9e1ae",
        "type": "ui_group",
        "name": "Shunt A",
        "tab": "f3fb9943.a12128",
        "order": 1,
        "disp": true,
        "width": "6",
        "collapse": false
    },
    {
        "id": "b0f57fc2.e496c",
        "type": "ui_group",
        "name": "7 Cell",
        "tab": "f3fb9943.a12128",
        "order": 4,
        "disp": true,
        "width": "6",
        "collapse": false
    },
    {
        "id": "f3fb9943.a12128",
        "type": "ui_tab",
        "name": "Watchmon",
        "icon": "dashboard",
        "order": 2,
        "disabled": false,
        "hidden": false
    }
]