Context: Light programming being done in Node Red on a RIO. HMI is Ignition.
I have a Node Red where I am using the scratchpad to allow Ignition to access values that need to be read and written. The biggest problem so far is that Node Red doesn’t persist any values on power cycle.
I found this thread: Groov Rio node-red contextStore persistence it sounds like this is not really a supported method for persistence. Is there a supported method for persistence?
Alternatively I could write some default values to the scratchpad for set points and such, then update the scratch pad from Ignition with the actual values once it reconnects. Is there a way to insure that a Flow or a part of flow runs first and once on boot?
I am new to Node Red, so this feels clunky, but here is my code so far:
(I don’t think I would want to use Node Red for much programming, but CoDeSys isn’t available for the RIO (yet)…)
[{"id":"d1117df142d0a677","type":"tab","label":"Flow 1","disabled":false,"info":"","env":[]},{"id":"4da262bb925e6e4d","type":"debug","z":"d1117df142d0a677","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1270,"y":380,"wires":[]},{"id":"4ca5625dc0732e0a","type":"groov-io-write","z":"d1117df142d0a677","device":"4e9fa67a17225a9e","dataType":"channel-digital","moduleIndex":"0","channelIndex":"8","mmpAddress":"0xF0D81000","mmpType":"int32","mmpLength":"1","mmpEncoding":"ascii","value":"cmd","valueType":"msg","name":"CMD","x":710,"y":380,"wires":[["08af0b6268a9e1fc"]]},{"id":"5ce9c4b8158daf57","type":"inject","z":"d1117df142d0a677","name":"Every Second","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"1","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":120,"y":380,"wires":[["53ad6dc8c6c139c6"]]},{"id":"53ad6dc8c6c139c6","type":"groov-io-read","z":"d1117df142d0a677","device":"4e9fa67a17225a9e","dataType":"channel-analog","moduleIndex":"0","channelIndex":"3","mmpAddress":"0xF0D81004","mmpType":"int32","mmpLength":"1","mmpEncoding":"ascii","value":"","valueType":"msg.payload","itemName":"","name":"Read Well Level","x":320,"y":380,"wires":[["27b66f186e972aed"]]},{"id":"4733a47c8ab6da57","type":"inject","z":"d1117df142d0a677","name":"Every Second","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"1","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":140,"y":220,"wires":[["2b1c2d4a26d1df58"]]},{"id":"2b1c2d4a26d1df58","type":"groov-io-read","z":"d1117df142d0a677","device":"4e9fa67a17225a9e","dataType":"mmp-address","moduleIndex":"","channelIndex":"","mmpAddress":"0xF0D81000","mmpType":"int32","mmpLength":"10","mmpEncoding":"ascii","value":"","valueType":"msg.payload","itemName":"","name":"Load Scratchpad Values from HMI","x":400,"y":220,"wires":[["7dd524962a7a771d"]]},{"id":"391821a9e36324f9","type":"debug","z":"d1117df142d0a677","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1270,"y":220,"wires":[]},{"id":"57983ee5860ac6c1","type":"comment","z":"d1117df142d0a677","name":"Load Vars from Scratchpad","info":"This Flow will pull values that HMI changes in the scratchpad.","x":130,"y":160,"wires":[]},{"id":"7dd524962a7a771d","type":"function","z":"d1117df142d0a677","name":"Save HMI Values to flow.*","func":"// Functions for Bits from Stack Overflow\nfunction bit_test(num, bit){\n return ((num>>bit) % 2 != 0)\n}\n\nfunction bit_set(num, bit){\n return num | 1<<bit;\n}\n\nfunction bit_clear(num, bit){\n return num & ~(1<<bit);\n}\n\nfunction bit_toggle(num, bit){\n return bit_test(num, bit) ? bit_clear(num, bit) : bit_set(num, bit);\n}\n\n// HMI Counter:\nvar HMI_Count = flow.get('HMI_Count')||0;\nHMI_Count = msg.payload[0];\nflow.set('HMI_Count',HMI_Count);\n\n// HOA:\nvar HOA = flow.get('HOA')||1;\nHOA = msg.payload[1];\nflow.set('HOA',HOA);\n\n// ON_SP:\nvar ON_SP = flow.get('ON_SP')||17.0;\nON_SP = msg.payload[2]/10.0;\nflow.set('ON_SP',ON_SP);\n\n// OFF_SP:\nvar OFF_SP = flow.get('OFF_SP')||5.0;\nOFF_SP = msg.payload[3]/10.0;\nflow.set('OFF_SP',OFF_SP);\n\n// Speed_SP:\nvar Speed_SP = flow.get('Speed_SP')||100.0;\nSpeed_SP = msg.payload[4]/10.0;\nflow.set('Speed_SP',Speed_SP);\n\n// HMI_DI:\nvar HMI_DI = flow.get('HMI_DI')||0;\nHMI_DI = msg.payload[5];\nflow.set('HMI_DI',HMI_DI);\n\n// Reset VFD Fault\nvar VFD_Reset = flow.get('VFD_Reset')||0;\nVFD_Reset = bit_test(HMI_DI, 0);\nflow.set('VFD_Reset',VFD_Reset);\n\n// Reset Pump Runtime 1\nvar Pump_R1 = flow.get('Pump_R1')||0;\nPump_R1 = bit_test(HMI_DI, 1);\nflow.set('Pump_R1',Pump_R1);\n\n// Reset Pump Runtime 2\nvar Pump_R2 = flow.get('Pump_R2')||0;\nPump_R2 = bit_test(HMI_DI, 2);\nflow.set('Pump_R2',Pump_R2);\n\n// Reset Flow Total 1\nvar Flow_T1 = flow.get('Flow_T1')||0;\nFlow_T1 = bit_test(HMI_DI, 3);\nflow.set('Flow_T1',Flow_T1);\n\n// Reset Flow Total 2\nvar Flow_T2 = flow.get('Flow_T2')||0;\nFlow_T2 = bit_test(HMI_DI, 4);\nflow.set('Flow_T2',Flow_T2);\n\nmsg.payload = [HMI_Count,HOA,ON_SP,OFF_SP,Speed_SP,HMI_DI]\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":690,"y":220,"wires":[["391821a9e36324f9"]]},{"id":"27b66f186e972aed","type":"function","z":"d1117df142d0a677","name":"Run Pump?","func":"// Level:\nvar Level = flow.get('Level')||1.0;\nvar HOA = flow.get('HOA')||1;\nvar VFD_Fault = flow.get('VFD_Fault')||false;\nvar CMD = flow.get('CMD')||false;\nvar Call = flow.get('Call')||false;\nvar ON_SP = flow.get('ON_SP')||17.0;\nvar OFF_SP = flow.get('OFF_SP')||5.0;\nvar Speed_SP = flow.get('Speed_SP')||100.0;\nLevel = msg.payload;\nflow.set('Level',Level);\n\n\n\nif (HOA == 0) {\n CMD = false;\n} else if(VFD_Fault) {\n CMD = false;\n} else if (HOA == 2) {\n CMD = true;\n} else if (HOA == 1) {\n if (Level > ON_SP) {\n CMD = true;\n } else if (Level < OFF_SP) {\n CMD = false;\n }\n}\nif (Level > ON_SP) {\n Call = true;\n} else if (Level < OFF_SP) {\n Call = false;\n}\nflow.set('CMD',CMD);\nflow.set('Call',Call);\n\nif (CMD) { \n msg.speed = Speed_SP\n} else {\n msg.speed = 0.0\n}\n\nmsg.cmd = CMD;\nmsg.level = Level * 10;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":530,"y":380,"wires":[["4ca5625dc0732e0a"]]},{"id":"9684982098190457","type":"groov-io-read","z":"d1117df142d0a677","device":"4e9fa67a17225a9e","dataType":"channel-digital","moduleIndex":"0","channelIndex":"6","mmpAddress":"0xF0D81000","mmpType":"int32","mmpLength":"1","mmpEncoding":"ascii","value":"","valueType":"msg.payload","itemName":"","name":"Read VFD Fault","x":320,"y":300,"wires":[["cd948352edc1db67"]]},{"id":"adfc641cf5f84c6e","type":"inject","z":"d1117df142d0a677","name":"Every Second","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"1","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":120,"y":300,"wires":[["9684982098190457"]]},{"id":"3b407fce5e8fe8d2","type":"debug","z":"d1117df142d0a677","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1270,"y":300,"wires":[]},{"id":"cd948352edc1db67","type":"function","z":"d1117df142d0a677","name":"VFD Fault","func":"// Functions for Bits from Stack Overflow\nfunction bit_test(num, bit){\n return ((num>>bit) % 2 != 0)\n}\n\nfunction bit_set(num, bit){\n return num | 1<<bit;\n}\n\nfunction bit_clear(num, bit){\n return num & ~(1<<bit);\n}\n\nfunction bit_toggle(num, bit){\n return bit_test(num, bit) ? bit_clear(num, bit) : bit_set(num, bit);\n}\n\n// VFD_Fault:\nvar VFD_Fault = flow.get('VFD_Fault')||false;\nVFD_Fault = msg.payload;\nflow.set('VFD_Fault',VFD_Fault);\n\n// Pump_Info\nvar Pump_Info = flow.get('Pump_Info')||0;\nif(VFD_Fault) {\n bit_set(Pump_Info,1)\n}\nif(VFD_Fault == 0) {\n bit_clear(Pump_Info,1)\n}\n\nmsg.payload = VFD_Fault;\n\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":500,"y":300,"wires":[["3b407fce5e8fe8d2"]]},{"id":"b235b59428397b2c","type":"inject","z":"d1117df142d0a677","name":"Every Second","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"1","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":140,"y":100,"wires":[["a17a3d7e32c7aca2"]]},{"id":"d93c646640282293","type":"debug","z":"d1117df142d0a677","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1270,"y":100,"wires":[]},{"id":"97eefd31a39273e2","type":"function","z":"d1117df142d0a677","name":"PLC Counter","func":"// PLC_Count:\nvar PLC_Count = flow.get('PLC_Count')||0;\nPLC_Count = msg.payload;\n\nPLC_Count++;\n\nif (PLC_Count > 2000000000) {\n PLC_Count = 0;\n}\n\nflow.set('PLC_Count',PLC_Count);\n\nmsg.payload = PLC_Count;\n\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":530,"y":100,"wires":[["4f2732ebfca6a3f8"]]},{"id":"a17a3d7e32c7aca2","type":"groov-io-read","z":"d1117df142d0a677","device":"4e9fa67a17225a9e","dataType":"mmp-address","moduleIndex":"","channelIndex":"","mmpAddress":"0xF0D81028","mmpType":"int32","mmpLength":"1","mmpEncoding":"ascii","value":"","valueType":"msg.payload","itemName":"","name":"PLC Counter","x":330,"y":100,"wires":[["97eefd31a39273e2"]]},{"id":"4f2732ebfca6a3f8","type":"groov-io-write","z":"d1117df142d0a677","device":"4e9fa67a17225a9e","dataType":"mmp-address","moduleIndex":"","channelIndex":"","mmpAddress":"0xF0D81028","mmpType":"int32","mmpLength":"1","mmpEncoding":"ascii","value":"","valueType":"msg.payload","name":"Write PLC Count","x":730,"y":100,"wires":[["d93c646640282293"]]},{"id":"08af0b6268a9e1fc","type":"groov-io-write","z":"d1117df142d0a677","device":"4e9fa67a17225a9e","dataType":"mmp-address","moduleIndex":"","channelIndex":"","mmpAddress":"0xF0D81030","mmpType":"int32","mmpLength":"1","mmpEncoding":"ascii","value":"level","valueType":"msg","name":"Level to HMI","x":870,"y":380,"wires":[["50608db94ce33d6e"]]},{"id":"6a1a8b97793f6464","type":"inject","z":"d1117df142d0a677","name":"Every Second","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"1","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":120,"y":500,"wires":[["2e8ff1d8ac30f535"]]},{"id":"2e8ff1d8ac30f535","type":"groov-io-read","z":"d1117df142d0a677","device":"4e9fa67a17225a9e","dataType":"channel-digital","moduleIndex":"0","channelIndex":"5","mmpAddress":"0xF0D81004","mmpType":"int32","mmpLength":"1","mmpEncoding":"ascii","value":"status","valueType":"msg","itemName":"","name":"Read Pump Run Status","x":350,"y":500,"wires":[["be00435fe055d5e4"]]},{"id":"be00435fe055d5e4","type":"function","z":"d1117df142d0a677","name":"Pump Timers","func":"function bit_test(num, bit){\n return ((num>>bit) % 2 != 0)\n}\n\nfunction bit_set(num, bit){\n return num | 1<<bit;\n}\n\nfunction bit_clear(num, bit){\n return num & ~(1<<bit);\n}\n\nfunction bit_toggle(num, bit){\n return bit_test(num, bit) ? bit_clear(num, bit) : bit_set(num, bit);\n}\n\n// Status:\nvar S_Status = flow.get('Status')||false;\nvar P_Status = msg.status;\nvar Status = msg.status;\nvar StartTime = flow.get('StartTime')||0;\nvar AccTime = 0;\n\n// HMI_DI:\nvar HMI_DI = flow.get('HMI_DI')||0;\n\n// Reset Pump Runtime 1\nvar Pump_R1 = flow.get('Pump_R1')||0;\nPump_R1 = bit_test(HMI_DI, 1);\nflow.set('Pump_R1',Pump_R1);\n\n// Reset Pump Runtime 2\nvar Pump_R2 = flow.get('Pump_R2')||0;\nPump_R2 = bit_test(HMI_DI, 2);\nflow.set('Pump_R2',Pump_R2);\n\n// Other Vars\nvar P_Seconds = flow.get('P_Seconds')||0.0;\nvar THours_R0 = flow.get('Hours_R0')||0;\nvar THours_R1 = flow.get('Hours_R1')||0;\nvar THours_R2 = flow.get('Hours_R2')||0;\n\n\nif (StartTime > 0) {\n AccTime = msg.payload - StartTime\n}\n\nif (!S_Status && P_Status) {\n StartTime = msg.payload;\n S_Status = true;\n} else if (S_Status && P_Status) {\n P_Seconds = P_Seconds + AccTime / 1000;\n} else if (S_Status && !P_Status) {\n flow.set('P_Seconds',P_Seconds);\n StartTime = 0;\n S_Status = false;\n}\nif (P_Seconds > 360.0) {\n THours_R0++;\n THours_R1++;\n THours_R2++;\n P_Seconds = P_Seconds - 360.0;\n StartTime = msg.payload;\n flow.set('THours_R0',THours_R0);\n flow.set('THours_R1',THours_R1);\n flow.set('THours_R2',THours_R2);\n flow.set('P_Seconds',P_Seconds);\n flow.set('StartTime',StartTime);\n} else if (THours_R0 > 2000000000) {\n THours_R0 = 0;\n flow.set('THours_R0',THours_R0);\n} else if (Pump_R1) {\n THours_R1 = 0;\n flow.set('THours_R1',THours_R1);\n HMI_DI = bit_clear(HMI_DI, 1);\n} else if (Pump_R2) {\n THours_R2 = 0;\n flow.set('THours_R2',THours_R2);\n HMI_DI = bit_clear(HMI_DI, 2);\n}\n\nflow.set('HMI_DI',HMI_DI);\nflow.set('Status',Status);\nmsg.hours = [THours_R0, THours_R1, THours_R2]\n\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":590,"y":500,"wires":[["75461fc90b894bbd"]]},{"id":"50608db94ce33d6e","type":"groov-io-write","z":"d1117df142d0a677","device":"4e9fa67a17225a9e","dataType":"channel-analog","moduleIndex":"0","channelIndex":"4","mmpAddress":"0xF0D81000","mmpType":"int32","mmpLength":"1","mmpEncoding":"ascii","value":"speed","valueType":"msg","name":"Set Pump Speed CMD","x":1080,"y":380,"wires":[["4da262bb925e6e4d"]]},{"id":"d51e1d1ed0963045","type":"debug","z":"d1117df142d0a677","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1270,"y":500,"wires":[]},{"id":"75461fc90b894bbd","type":"groov-io-write","z":"d1117df142d0a677","device":"4e9fa67a17225a9e","dataType":"mmp-address","moduleIndex":"","channelIndex":"","mmpAddress":"0xF0D8103C","mmpType":"int32","mmpLength":"1","mmpEncoding":"ascii","value":"hours[0]","valueType":"msg","name":"Hours","x":770,"y":500,"wires":[["227b4309867593de"]]},{"id":"227b4309867593de","type":"groov-io-write","z":"d1117df142d0a677","device":"4e9fa67a17225a9e","dataType":"mmp-address","moduleIndex":"","channelIndex":"","mmpAddress":"0xF0D81040","mmpType":"int32","mmpLength":"1","mmpEncoding":"ascii","value":"hours[1]","valueType":"msg","name":"Hours","x":910,"y":500,"wires":[["cd1425aecf438fef"]]},{"id":"cd1425aecf438fef","type":"groov-io-write","z":"d1117df142d0a677","device":"4e9fa67a17225a9e","dataType":"mmp-address","moduleIndex":"","channelIndex":"","mmpAddress":"0xF0D81044","mmpType":"int32","mmpLength":"1","mmpEncoding":"ascii","value":"hours[2]","valueType":"msg","name":"Hours","x":1050,"y":500,"wires":[["d51e1d1ed0963045"]]},{"id":"c09efcbc81408815","type":"inject","z":"d1117df142d0a677","name":"Every Second","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"1","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":120,"y":560,"wires":[["fee8f16df449eb1a"]]},{"id":"fee8f16df449eb1a","type":"groov-io-read","z":"d1117df142d0a677","device":"4e9fa67a17225a9e","dataType":"channel-analog","moduleIndex":"0","channelIndex":"2","mmpAddress":"0xF0D81004","mmpType":"int32","mmpLength":"1","mmpEncoding":"ascii","value":"payload","valueType":"msg","itemName":"","name":"Read Pump Run Speed","x":350,"y":560,"wires":[["f3fa617ee9d5a10b"]]},{"id":"f3fa617ee9d5a10b","type":"function","z":"d1117df142d0a677","name":"Pump Speed","func":"// Pump_Speed:\nvar Pump_Speed = flow.get('Pump_Speed')||0;\nPump_Speed = msg.payload * 10.0;\nflow.set('Pump_Speed',Pump_Speed);\n\n\nmsg.payload\n\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":590,"y":560,"wires":[["213afdeaa99701ef"]]},{"id":"3bf722cf69a93865","type":"debug","z":"d1117df142d0a677","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1270,"y":560,"wires":[]},{"id":"213afdeaa99701ef","type":"groov-io-write","z":"d1117df142d0a677","device":"4e9fa67a17225a9e","dataType":"mmp-address","moduleIndex":"","channelIndex":"","mmpAddress":"0xF0D81034","mmpType":"int32","mmpLength":"1","mmpEncoding":"ascii","value":"","valueType":"msg.payload","name":"Pump Speed","x":790,"y":560,"wires":[["3bf722cf69a93865"]]},{"id":"b07ec93190189c83","type":"inject","z":"d1117df142d0a677","name":"Every Second","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"1","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":120,"y":620,"wires":[["2fec3772d772f4b4"]]},{"id":"2fec3772d772f4b4","type":"function","z":"d1117df142d0a677","name":"Pump Info Builder","func":"// Pump Bits:\nvar Status = flow.get('Status')||false;\nvar VFD_Fault = flow.get('VFD_Fault')||false;\nvar Call = flow.get('Call')||false;\nvar CMD = flow.get('CMD')||false;\nvar Pump_Info = 0;\n\n\nPump_Info = Status + (VFD_Fault << 1) + (Call << 2) + (CMD << 3)\n\n\nmsg.payload = Pump_Info\n\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":550,"y":620,"wires":[["9237eca872020457"]]},{"id":"4ded074277f550b8","type":"debug","z":"d1117df142d0a677","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1270,"y":620,"wires":[]},{"id":"9237eca872020457","type":"groov-io-write","z":"d1117df142d0a677","device":"4e9fa67a17225a9e","dataType":"mmp-address","moduleIndex":"","channelIndex":"","mmpAddress":"0xF0D8102C","mmpType":"int32","mmpLength":"1","mmpEncoding":"ascii","value":"","valueType":"msg.payload","name":"Pump Info","x":770,"y":620,"wires":[["4ded074277f550b8"]]},{"id":"500cf5f3f54e8142","type":"inject","z":"d1117df142d0a677","name":"Every Second","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"1","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":120,"y":680,"wires":[["3cb04f07142cac5e"]]},{"id":"3cb04f07142cac5e","type":"groov-io-read","z":"d1117df142d0a677","device":"4e9fa67a17225a9e","dataType":"channel-analog","moduleIndex":"0","channelIndex":"1","mmpAddress":"0xF0D81004","mmpType":"int32","mmpLength":"1","mmpEncoding":"ascii","value":"flow","valueType":"msg","itemName":"","name":"Read Flow Meter","x":330,"y":680,"wires":[["2b12fad40dbd568b"]]},{"id":"2b12fad40dbd568b","type":"function","z":"d1117df142d0a677","name":"Flow Totals","func":"// Functions for Bits from Stack Overflow\nfunction bit_test(num, bit){\n return ((num>>bit) % 2 != 0)\n}\n\nfunction bit_set(num, bit){\n return num | 1<<bit;\n}\n\nfunction bit_clear(num, bit){\n return num & ~(1<<bit);\n}\n\nfunction bit_toggle(num, bit){\n return bit_test(num, bit) ? bit_clear(num, bit) : bit_set(num, bit);\n}\n\n// Flow: (Assuming GPM)\nvar Flow = msg.flow;\nvar Flow_T0 = flow.get('Flow_T0')||1.0;\nvar Flow_T1 = flow.get('Flow_T1')||1.0;\nvar Flow_T2 = flow.get('Flow_T2')||1.0;\n\n// HMI_DI:\nvar HMI_DI = flow.get('HMI_DI')||0;\nvar Reset1 = bit_test(HMI_DI, 3);\nvar Reset2 = bit_test(HMI_DI, 4);\n\nvar Now = msg.payload;\nvar Last = flow.get('Last')||msg.payload;\nvar msecs = Now - Last;\nvar F_Total = flow.get('F_Total')||1.0;\nvar Counts_Total = 1000.0; // == Galons per Count.\n\nif (Flow > 5.0) {\n if (msecs > 0) {\n weight = msecs / 1000.0;\n sec_Total = GPM * weight / 60.0; // Divide by 60 because we assume GPM. Change for others.\n F_Total += secTotal; \n }\n if (F_Total > Counts_Total) {\n Flow_T0++;\n Flow_T1++;\n Flow_T2++;\n F_Total -= Counts_Total;\n }\n} \n\nif (Flow_T0 > 2000000000) {\n Flow_T0 = 0;\n}\nif (Reset1) {\n Flow_T1 = 0;\n HMI_DI = bit_clear(HMI_DI, 3);\n}\nif (Reset2) {\n Flow_T2 = 0;\n HMI_DI = bit_clear(HMI_DI, 4);\n}\n\n\n\nflow.set('F_Total',F_Total);\nflow.set('Flow_T0',Flow_T0);\nflow.set('Flow_T1',Flow_T1);\nflow.set('Flow_T2',Flow_T2);\nflow.set('HMI_DI',HMI_DI);\nmsg.totals = [Flow_T0,Flow_T1,Flow_T2]\nmsg.payload = Flow * 10;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":530,"y":680,"wires":[["1c6d3caa0ceae154"]]},{"id":"85e3d8f3a0b3c812","type":"debug","z":"d1117df142d0a677","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1270,"y":680,"wires":[]},{"id":"3210d3b5c2800cf3","type":"inject","z":"d1117df142d0a677","name":"Every Second","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"1","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":120,"y":440,"wires":[["717e17eb5f08ad65"]]},{"id":"717e17eb5f08ad65","type":"groov-io-read","z":"d1117df142d0a677","device":"4e9fa67a17225a9e","dataType":"mmp-address","moduleIndex":"","channelIndex":"","mmpAddress":"0xF0D8103C","mmpType":"int32","mmpLength":"6","mmpEncoding":"ascii","value":"","valueType":"msg.payload","itemName":"","name":"Load Scratchpad Totalizers","x":360,"y":440,"wires":[["ce95301ec25d216b"]]},{"id":"7a5515285c7a1638","type":"debug","z":"d1117df142d0a677","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1250,"y":440,"wires":[]},{"id":"ce95301ec25d216b","type":"function","z":"d1117df142d0a677","name":"Save Totals to Flow","func":"// Hours_R0:\nvar Hours_R0 = flow.get('Hours_R0')||0;\nHours_R0 = msg.payload[0];\nflow.set('Hours_R0',Hours_R0);\n\n// Hours_R1:\nvar Hours_R1 = flow.get('Hours_R1')||0;\nHours_R1 = msg.payload[1];\nflow.set('Hours_R1',Hours_R1);\n\n// Hours_R2:\nvar Hours_R2 = flow.get('Hours_R2')||0;\nHours_R2 = msg.payload[2];\nflow.set('Hours_R2',Hours_R2);\n\n// Flow_T0:\nvar Flow_T0 = flow.get('Flow_T0')||0;\nFlow_T0 = msg.payload[3];\nflow.set('Flow_T0',Flow_T0);\n\n// Flow_T1:\nvar Flow_T1 = flow.get('Flow_T1')||0;\nFlow_T1 = msg.payload[4];\nflow.set('Flow_T1',Flow_T1);\n\n// Flow_T2:\nvar Flow_T2 = flow.get('Flow_T2')||0;\nFlow_T2 = msg.payload[5];\nflow.set('Flow_T2',Flow_T2);\n\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":650,"y":440,"wires":[["7a5515285c7a1638"]]},{"id":"7924106d31c13d86","type":"groov-io-write","z":"d1117df142d0a677","device":"4e9fa67a17225a9e","dataType":"mmp-address","moduleIndex":"","channelIndex":"","mmpAddress":"0xF0D81048","mmpType":"int32","mmpLength":"1","mmpEncoding":"ascii","value":"totals[0]","valueType":"msg","name":"Totals","x":830,"y":680,"wires":[["0739e337abf25863"]]},{"id":"0739e337abf25863","type":"groov-io-write","z":"d1117df142d0a677","device":"4e9fa67a17225a9e","dataType":"mmp-address","moduleIndex":"","channelIndex":"","mmpAddress":"0xF0D8104C","mmpType":"int32","mmpLength":"1","mmpEncoding":"ascii","value":"totals[1]","valueType":"msg","name":"Totals","x":970,"y":680,"wires":[["c01866a67a2dbb25"]]},{"id":"c01866a67a2dbb25","type":"groov-io-write","z":"d1117df142d0a677","device":"4e9fa67a17225a9e","dataType":"mmp-address","moduleIndex":"","channelIndex":"","mmpAddress":"0xF0D81050","mmpType":"int32","mmpLength":"1","mmpEncoding":"ascii","value":"totals[2]","valueType":"msg","name":"Totals","x":1110,"y":680,"wires":[["85e3d8f3a0b3c812"]]},{"id":"1c6d3caa0ceae154","type":"groov-io-write","z":"d1117df142d0a677","device":"4e9fa67a17225a9e","dataType":"mmp-address","moduleIndex":"","channelIndex":"","mmpAddress":"0xF0D81038","mmpType":"int32","mmpLength":"1","mmpEncoding":"ascii","value":"","valueType":"msg.payload","name":"Flow","x":690,"y":680,"wires":[["7924106d31c13d86"]]},{"id":"4e9fa67a17225a9e","type":"groov-io-device","address":"localhost","msgQueueFullBehavior":"DROP_OLD"}]