-
Notifications
You must be signed in to change notification settings - Fork 0
/
oct-agile-v-1-0-0.json
1 lines (1 loc) · 40.1 KB
/
oct-agile-v-1-0-0.json
1
[{"id":"e42010beae8f7fa5","type":"group","z":"2dd6b0b4a5f86125","name":"Octopus Agile Prices","style":{"label":true,"stroke":"#6f2fa0","fill":"#dbcbe7","color":"#001f60"},"nodes":["2d59f743b9329794","b201872551160895","29dd2ea7557213cd","518fc65503bdfc82"],"x":28,"y":1813,"w":1064,"h":914},{"id":"2d59f743b9329794","type":"group","z":"2dd6b0b4a5f86125","g":"e42010beae8f7fa5","name":"Half-Hourly update for current price from array","style":{"label":true,"color":"#6f2fa0"},"nodes":["2bb43fc9797cb5b3","be04e63b7258b035","4430da6cfe290e39","3797b648d315c3a1","d8bb3057287698de","ee45b426f60a08a0","a9942de6076269cf","557a6128047a268e","da0c1b6c415c2734","38eb803a7413df2d","1ea33f6575c3a25e"],"x":54,"y":2019,"w":1012,"h":182},{"id":"2bb43fc9797cb5b3","type":"debug","z":"2dd6b0b4a5f86125","g":"2d59f743b9329794","name":"periods left","active":true,"tosidebar":false,"console":false,"tostatus":true,"complete":"agile.periodsleft","targetType":"msg","statusVal":"agile.periodsleft","statusType":"auto","x":750,"y":2060,"wires":[]},{"id":"be04e63b7258b035","type":"ha-sensor","z":"2dd6b0b4a5f86125","d":true,"g":"2d59f743b9329794","name":"Octopus Agile Prices","entityConfig":"0760bdebc1d4da3e","version":0,"state":"agile.now.from","stateType":"msg","attributes":[{"property":"array","value":"payload","valueType":"msg"},{"property":"import","value":"agile.now.import","valueType":"msg"},{"property":"export","value":"agile.now.export","valueType":"msg"},{"property":"import_next","value":"agile.next.import","valueType":"msg"},{"property":"export_next","value":"agile.next.export","valueType":"msg"},{"property":"periods_left","value":"agile.periodsleft","valueType":"msg"}],"inputOverride":"allow","outputProperties":[],"x":940,"y":2100,"wires":[[]],"server":""},{"id":"4430da6cfe290e39","type":"change","z":"2dd6b0b4a5f86125","g":"2d59f743b9329794","name":"Value Now","rules":[{"t":"set","p":"agile","pt":"msg","to":"(\t/* FUNCTION: add <delta> minutes to now */\t $tstep:=function($mdelta) {\t $fromMillis($toMillis($now())+$mdelta*60000)\t };\t\t/* FUNCTION: build key value from timestamp. Strip fraction */\t/* of seconds, floor minutes to 00 or 30, zero seconds */\t $keyis:=function($ts) {(\t $t:=$replace($ts, /(\\.[0-9]+)/, '');\t $m:=$substring($t,-6,2).$number()<30 ? '00': '30';\t $substring($t,0,14) & $m & \":00\" & $substring($t,-1);\t )\t };\t\t /* return object of 'now' and 'next' value objects */\t\t $keyNow:=$keyis($now());\t $keyNext:=$keyis($tstep(30));\t {\t \"now\": payload[from=$keyis($now())],\t \"next\": payload[from=$keyis($tstep(30))],\t \"periodsleft\": $count(payload[from>$keyNext])\t };\t\t\t)","tot":"jsonata"},{"t":"set","p":"payload","pt":"msg","to":"payload~>|$|{},[\"date\",\"localupto\",\"isofrom\", \"isoupto\"]|","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":550,"y":2100,"wires":[["be04e63b7258b035","2bb43fc9797cb5b3","557a6128047a268e"]]},{"id":"3797b648d315c3a1","type":"change","z":"2dd6b0b4a5f86125","g":"2d59f743b9329794","name":"Read Array","rules":[{"t":"set","p":"payload","pt":"msg","to":"OctAgileTariff","tot":"flow","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":350,"y":2100,"wires":[["4430da6cfe290e39"]]},{"id":"d8bb3057287698de","type":"link in","z":"2dd6b0b4a5f86125","g":"2d59f743b9329794","name":"Daily","links":["56dd710454ea2e25"],"x":445,"y":2060,"wires":[["4430da6cfe290e39"]]},{"id":"ee45b426f60a08a0","type":"inject","z":"2dd6b0b4a5f86125","g":"2d59f743b9329794","name":"At Half Hour","props":[{"p":"payload"}],"repeat":"","crontab":"*/30 0-23 * * *","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":180,"y":2060,"wires":[["a9942de6076269cf"]]},{"id":"a9942de6076269cf","type":"delay","z":"2dd6b0b4a5f86125","g":"2d59f743b9329794","name":"10s","pauseType":"delay","timeout":"10","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":170,"y":2100,"wires":[["3797b648d315c3a1"]]},{"id":"557a6128047a268e","type":"switch","z":"2dd6b0b4a5f86125","g":"2d59f743b9329794","name":"Periods Left <10","property":"agile.periodsleft","propertyType":"msg","rules":[{"t":"lt","v":"10","vt":"num"}],"checkall":"false","repair":false,"outputs":1,"x":500,"y":2160,"wires":[["1ea33f6575c3a25e"]]},{"id":"da0c1b6c415c2734","type":"link out","z":"2dd6b0b4a5f86125","g":"2d59f743b9329794","name":"Call Update","mode":"link","links":["32ae6a37829cd07f"],"x":1025,"y":2160,"wires":[]},{"id":"38eb803a7413df2d","type":"delay","z":"2dd6b0b4a5f86125","g":"2d59f743b9329794","name":"Once per hour - prevent looping","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"hour","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"allowrate":false,"outputs":1,"x":850,"y":2160,"wires":[["da0c1b6c415c2734"]]},{"id":"1ea33f6575c3a25e","type":"change","z":"2dd6b0b4a5f86125","g":"2d59f743b9329794","name":"clear","rules":[{"t":"delete","p":"agile","pt":"msg"},{"t":"delete","p":"payload","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":650,"y":2160,"wires":[["38eb803a7413df2d"]]},{"id":"0760bdebc1d4da3e","type":"ha-entity-config","d":true,"server":"","deviceConfig":"","name":"SC Oct Agile Prices","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"Octopus Agile Prices"},{"property":"icon","value":""},{"property":"entity_category","value":""},{"property":"entity_picture","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":""},{"property":"state_class","value":""}],"resend":true,"debugEnabled":false},{"id":"b201872551160895","type":"group","z":"2dd6b0b4a5f86125","g":"e42010beae8f7fa5","name":"Read tariffs - build and save 2-day tariff array to context","style":{"label":true,"color":"#6f2fa0"},"nodes":["db6ebccc4bb88b8d","63bba87f93e0eaae","65094b21c3938d73","22fdc0bfd7bdd329","3c0e6412766b7286","0ba1d9b378092267","56dd710454ea2e25","c3ffde5b136bf4bb","18a019dec90422b8","fa24a4b04bede5d4","32ae6a37829cd07f","f0ed3ca0e333fb3c","926c3b4f4e106744"],"x":54,"y":1839,"w":1012,"h":162},{"id":"db6ebccc4bb88b8d","type":"http request","z":"2dd6b0b4a5f86125","g":"b201872551160895","name":"Oct Export","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://api.octopus.energy/v1/products/AGILE-OUTGOING-19-05-13/electricity-tariffs/E-1R-AGILE-OUTGOING-19-05-13-L/standard-unit-rates/?page_size=96","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":350,"y":1960,"wires":[["65094b21c3938d73"]]},{"id":"63bba87f93e0eaae","type":"http request","z":"2dd6b0b4a5f86125","g":"b201872551160895","name":"Oct Import","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://api.octopus.energy/v1/products/AGILE-22-08-31/electricity-tariffs/E-1R-AGILE-22-08-31-L/standard-unit-rates/?page_size=96","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":350,"y":1920,"wires":[["22fdc0bfd7bdd329"]]},{"id":"65094b21c3938d73","type":"change","z":"2dd6b0b4a5f86125","g":"b201872551160895","name":"Value","rules":[{"t":"set","p":"payload","pt":"msg","to":"$distinct(payload.results)","tot":"jsonata"},{"t":"set","p":"topic","pt":"msg","to":"export","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":490,"y":1960,"wires":[["3c0e6412766b7286"]]},{"id":"22fdc0bfd7bdd329","type":"change","z":"2dd6b0b4a5f86125","g":"b201872551160895","name":"Value","rules":[{"t":"set","p":"payload","pt":"msg","to":"$distinct(payload.results)","tot":"jsonata"},{"t":"set","p":"topic","pt":"msg","to":"import","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":490,"y":1920,"wires":[["3c0e6412766b7286"]]},{"id":"3c0e6412766b7286","type":"join","z":"2dd6b0b4a5f86125","g":"b201872551160895","name":"Add","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"num","reduceFixup":"","x":630,"y":1920,"wires":[["18a019dec90422b8"]]},{"id":"0ba1d9b378092267","type":"inject","z":"2dd6b0b4a5f86125","d":true,"g":"b201872551160895","name":"@ 16:05","props":[{"p":"payload"}],"repeat":"","crontab":"05 16 * * *","once":true,"onceDelay":"2","topic":"","payload":"","payloadType":"date","x":160,"y":1920,"wires":[["926c3b4f4e106744"]]},{"id":"56dd710454ea2e25","type":"link out","z":"2dd6b0b4a5f86125","g":"b201872551160895","name":"Daily Update","mode":"link","links":["87bddd29d5e5ab90","d8bb3057287698de"],"x":1025,"y":1960,"wires":[]},{"id":"c3ffde5b136bf4bb","type":"comment","z":"2dd6b0b4a5f86125","g":"b201872551160895","name":"Octopus agile prices (2 days, with DST 'local time') Rev Feb 2024","info":"- Tidy, use JSONata tranform function\n- Fix (potential) issues with sorting\n- Add in determination of UK GMT/BST and\n using this include 'local time' in saved data\n (test and correct for change on new year)\n- Create a binary sensor based on\n (_n_) best prices, this will turn on/off for\n each 'best' period based on 'local time'\n WARNING: DST time changes may cause issues!\n- On each half-hour update, find index at lookup\n and use to trigger API update _post_ 17:00 (deal\n with problems from late tariff update by Octopus)\n- For each day (48 records) write the compacted date yyyymmdd\n and keep through to periods and groups. When saving groups\n to context, add/overwrite new set (tomorrow) keep today, and\n drop anything older (hence keep two days worth of groups)\n FIX: make sure singletons are kept as arrays, bug in graph if not!\n- Manage binary schedules to show array in sensor attributes\n and use to switch back on if NR restart during on-period \n (complex but it seems to work now)\n","x":550,"y":1880,"wires":[]},{"id":"18a019dec90422b8","type":"change","z":"2dd6b0b4a5f86125","g":"b201872551160895","name":"UK DST","rules":[{"t":"set","p":"dst","pt":"msg","to":"OctDST","tot":"flow","dc":true},{"t":"set","p":"dst","pt":"msg","to":"(\t/* Jan 2024: For UK only - calculate DST dates (GMT->BST, BST->GMT) */\t/* fix bug for new year change */\t\t/* $now() is evaluated once only and used throughout the expression */\t $nw:=$now();\t\t/* FUNCTION: return day of week (DOW) given 'yyyy-mm-dd' where SUN=0 */\t $dayofweek:=function($date) {(\t $y:=$number($substring($date,0,4));\t $m:=$number($substring($date,5,2));\t $d:=$number($substring($date,8,2));\t $m<3 ? $y:=$y-1;\t $t:=[0,3,2,5,0,3,5,1,4,6,2,4];\t ($y + $floor($y/4) - $floor($y/100) + $floor($y/400) + $t[$m-1] +$d)%7;\t )};\t\t/* FUNCTION: returm start and end DST timestamps for a given year yyyy (int) */\t $dstdates:=function($year) {(\t $mar:=$year & \"-03-\";\t $oct:=$year & \"-10-\";\t $dstrt:=$mar & (31-$dayofweek($mar & \"31\") & \"T01:00:00.000Z\");\t $dstop:=$oct & (31-$dayofweek($oct & \"31\") & \"T01:00:00.000Z\");\t $a:=$toMillis($dstrt);\t $b:=$toMillis($dstop);\t $n:=$toMillis($nw);\t $mp:=($a+$b)/2;\t\t {\"year\": $year,\t \"timestamp\": $nw,\t \"now\": $n,\t \"DSTstart\": $dstrt,\t \"on\": $a,\t \"DSTstop\": $dstop,\t \"off\": $b,\t \"DSToffset\": (1*60*60*1000),\t \"midpoint\": $mp\t }\t )};\t\t/* read in from context - if does not exist or if year has changed, update */\t $yearis:=$number($substringBefore($nw,\"-\"));\t $dst:= $exists(dst) ? dst : $dstdates($yearis);\t $dst:= $dst.year=$yearis ? $dst : $dstdates($yearis);\t\t/* update 'now' in record and decide if DST (GMT/BST), if 'close' to change */\t/* note which way it went/will go, and which timestamp to test against */\t\t $n:=$toMillis($nw);\t $a:=$dst.on;\t $b:=$dst.off;\t $mp:=$dst.midpoint;\t\t $tz:= $n<$a or $n>=$b ? \"GMT\" : \"BST\";\t $close:=$min([$abs($n-$a), $abs($n-$b)])/3600000<=48; /* test for 48 hours either side */\t $GMTBST:=$n<$mp;\t\t $tzfrom:= $close ? ($GMTBST ? \"GMT\" : \"BST\" ) : $tz;\t $tzgoto:= $close ? ($GMTBST ? \"BST\" : \"GMT\" ) : $tz;\t\t $update:={\t \"timestamp\": $nw,\t \"now\": $n,\t \"TZnow\": $tz,\t \"DSTon\": $tz=\"BST\", \t \"changing\": $close,\t \"toDST\": $GMTBST,\t \"TZfrom\": $tzfrom,\t \"TZtobe\": $tzgoto,\t \"testvalue\": $GMTBST ? $a:$b\t };\t $dst ~> | $ | $update |\t\t)","tot":"jsonata"},{"t":"set","p":"OctDST","pt":"flow","to":"dst","tot":"msg","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":660,"y":1960,"wires":[["fa24a4b04bede5d4"]]},{"id":"fa24a4b04bede5d4","type":"change","z":"2dd6b0b4a5f86125","g":"b201872551160895","name":"Build & Save TARIFF Array","rules":[{"t":"set","p":"payload","pt":"msg","to":"(\t/* UPDATED: June 2023 - include DST for local time */\t/* create a merged array of import & export tariffs for each time period */\t/* use DST switching timestamps to also create 'local time' and DST flag */\t\t/* FUNCTION: extract date and time from ISO timestamp, first applying offset */\t $parsets:=function($timestamp){(\t $msec:=$toMillis($timestamp);\t $utcdate:=$substringBefore($timestamp,\"T\");\t $utctime:=$substringAfter($timestamp,\"T\");\t\t $tz:= $changing ? ($msec<$test ? $tzfrom : $tznext) : $tzfrom;\t $add:= $tz=\"GMT\" ? 0 : $offset;\t $iso:= $tz=\"GMT\" ? \"+00:00\" : \"+01:00\";\t\t $local:=$fromMillis($msec+$add);\t $localdate:=$substringBefore($local,\"T\");\t $localtime:=$substringAfter($local,\"T\");\t $isotime:=$substring($localtime,0,11);\t {\"millisec\": $msec,\t \"utcdate\": $utcdate,\t \"utctime\": $substring($utctime,0,5),\t \"timezone\": $tz,\t \"localdate\": $localdate,\t \"localtime\": $substring($localtime,0,5),\t \"localiso\": $localdate & \"T\" & $isotime & $iso\t }\t\t )};\t\t $changing:=dst.changing;\t $fromGMT:=dst.toDST; \t $tzfrom:= dst.TZfrom;\t $tznext:= dst.TZtobe;\t $test:= dst.testvalue;\t $offset:=dst.DSToffset;\t\t $array:=payload.import#$i.(\t $from:=$parsets(valid_from);\t $upto:=$parsets(valid_to);\t {\t \"from\": valid_from,\t \"upto\": valid_to,\t \"import\": value_inc_vat,\t \"export\": %.export[$i].value_inc_vat, \t \"date\": $from.utcdate,\t \"timefrom\": $from.utctime,\t \"timeupto\": $upto.utctime,\t \"localdate\": $from.localdate,\t \"localfrom\": $from.localtime & \" \" & $from.timezone,\t \"localupto\": $upto.localtime & \" \" & $upto.timezone,\t \"dstchange\": $from.timezone != $upto.timezone,\t \"isofrom\": $from.localiso,\t \"isoupto\": $upto.localiso\t }\t );\t\t $array^(from)\t\t)","tot":"jsonata"},{"t":"set","p":"OctAgileTariff","pt":"flow","to":"payload","tot":"msg","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":880,"y":1920,"wires":[["56dd710454ea2e25"]]},{"id":"32ae6a37829cd07f","type":"link in","z":"2dd6b0b4a5f86125","g":"b201872551160895","name":"Call Update","links":["da0c1b6c415c2734"],"x":205,"y":1960,"wires":[["926c3b4f4e106744"]]},{"id":"f0ed3ca0e333fb3c","type":"inject","z":"2dd6b0b4a5f86125","g":"b201872551160895","name":"At Start (20s)","props":[{"p":"payload"}],"repeat":"","crontab":"","once":true,"onceDelay":"20","topic":"","payload":"","payloadType":"date","x":180,"y":1880,"wires":[["926c3b4f4e106744"]]},{"id":"926c3b4f4e106744","type":"junction","z":"2dd6b0b4a5f86125","g":"b201872551160895","x":260,"y":1940,"wires":[["63bba87f93e0eaae","db6ebccc4bb88b8d"]]},{"id":"29dd2ea7557213cd","type":"group","z":"2dd6b0b4a5f86125","g":"e42010beae8f7fa5","name":"Binary sensor - create and manage dynamic switching schedules","style":{"label":true,"color":"#6f2fa0"},"nodes":["3ba57f3b89f9766f","22d6194ce87d6071","6b85072564ab77f1","2842cbd7a62bdec3","6059b908602e5c74","a2da777d6df94115","6d225d4efd80e737","decefda660d240ee","f8ca783a52eb32d8","3d951d153239eb27","315b3d2dda9301bb","7e69c69041f64555","ed031a2fcc75c493","c284862b7284bd1d","10cb994c44d0f0de","0f2eed13f4a8fd7e","45b336c245c0c32f","c3990bf24fabec27","a4572a5e5aeda036","f7cbd2e4b217f3f1","dae9895b170ecb41","fc1bbbe76ab45649"],"x":54,"y":2419,"w":1012,"h":282},{"id":"3ba57f3b89f9766f","type":"inject","z":"2dd6b0b4a5f86125","g":"29dd2ea7557213cd","name":"Manual OFF","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":"40","topic":"OFF","x":650,"y":2640,"wires":[["45b336c245c0c32f"]]},{"id":"22d6194ce87d6071","type":"change","z":"2dd6b0b4a5f86125","g":"29dd2ea7557213cd","name":"Clear Old Inactive Schedules first","rules":[{"t":"set","p":"topic","pt":"msg","to":"remove-inactive","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":320,"y":2460,"wires":[["0f2eed13f4a8fd7e"]]},{"id":"6b85072564ab77f1","type":"delay","z":"2dd6b0b4a5f86125","g":"29dd2ea7557213cd","name":"3s","pauseType":"delay","timeout":"3","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":210,"y":2500,"wires":[["2842cbd7a62bdec3"]]},{"id":"2842cbd7a62bdec3","type":"change","z":"2dd6b0b4a5f86125","g":"29dd2ea7557213cd","name":"Binary Schedules","rules":[{"t":"set","p":"topic","pt":"msg","to":"\"\"","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"payload.import","tot":"msg"},{"t":"set","p":"periods","pt":"msg","to":"10","tot":"num"},{"t":"set","p":"adjust","pt":"msg","to":"25","tot":"num"},{"t":"set","p":"uselocal","pt":"msg","to":"true","tot":"bool"},{"t":"set","p":"payload","pt":"msg","to":"(\t/* FUNCTION: turn timestring into cron expression for schedule */\t $cronexp:=function($input, $add){(\t $tz:= $contains($input, \"Z\") ? \"+0000\" : \"+\" & $substringBefore($substringAfter($input,\"+\"),\":\") & \"00\";\t $ms:=$toMillis($input)+$add;\t $ts:=$fromMillis($ms,'[s] [m] [H01] [D01] [M01] * 20[Y02]',$tz)\t )};\t\t/* FUNCTION: get duration in minutes between on and off times */\t $dur:=function($on, $off){$round(($toMillis($off)-$toMillis($on))/60000,0)};\t\t/* FUNCTION: build CronPlus command from parameters */\t $cpcom:= function($ind, $switch, $ton, $toff, $vlist, $ymd, $dst){(\t $totval:=$sum($vlist);\t $numval:=$count($vlist);\t {\"command\": \"add\",\t \"name\": \"OctopusAgile \" & $ymd & \" \" & $switch & \" \" & $ind,\t \"topic\": $switch,\t \"expression\": $cronexp($switch=\"ON\" ? $ton : $toff, $switch=\"ON\" ? $adjust : -$adjust),\t \"limit\": 1,\t \"expressiontype\": \"cron\",\t \"payloadType\": \"json\",\t \"payload\": {\t \"switch\": $switch,\t \"event\": $ymd & \"-\" & $ind & \"/\" & $list & \"=\" & $switch,\t \"timeon\": $ton,\t \"timeoff\": $toff,\t \"duration\": $dur($ton, $toff),\t \"average\": $round($totval/$numval, 3),\t \"local\": $uselocal,\t \"dstchange\": $dst}}\t )};\t\t/* PARAMETERS */\t\t/* the 'adjust' is used to add to ON time and subtract from OFF time by <n> [0-60] seconds */\t $a:=$exists(adjust) ? adjust : 0;\t $adjust:=$a>=0 and $a<=60 ? $a*1000 : 0;\t\t/* pick <n> by value then re-sort back into time order */\t $pick:= $exists(periods) ? periods : $count(payload);\t $best:=payload^(value)[[0..$pick-1]];\t $bestbunch:=$best^(from);\t\t/* uselocal: use local time (ie BST in summer) as default otherwise use UTC time */\t/* note that 'cronplus' node requires a UTC+00:00 and DST: 0 timezone for UTC */\t $uselocal:= $exists(uselocal) ? uselocal : true;\t\t/* MAIN */\t\t/* get NEW sequence position for subset of 'best' periods & reorder index for these */\t $bestbunch:=$bestbunch#$v.(\t $last:=$v<1 ? false : from=$bestbunch[$v-1].upto;\t $next:=upto=$bestbunch[$v+1].from;\t $position:=($last ? ($next ? \"middle\" : \"end\") : ($next ? \"start\" : \"only\"));\t $~>|$|{\"index\": $v,\"position\": $position}, [\"link_last\", \"link_next\"]|;\t );\t\t/* get an array of start-end indexes and compact consecutive runs */\t $chain:=$zip($bestbunch[position=\"start\" or position=\"only\"].index, $bestbunch[position=\"end\" or position=\"only\"].index);\t $list:=$count($chain);\t\t $result:=$chain#$i.(\t $ion:=$[0];\t $recon:=$bestbunch[$ion];\t $timeon:=$lookup($recon, $uselocal ? \"isofrom\" : \"from\");\t $ioff:=$[1];\t $recoff:=$bestbunch[$ioff];\t $timeoff:=$lookup($recoff, $uselocal ? \"isoupto\" : \"upto\");\t $vallist:=($bestbunch[[$ion..$ioff]].value);\t \t $on:= $cpcom($i+1, \"ON\", $timeon, $timeoff, $vallist, $recon.ymd, $recon.dstchange);\t $of:= $cpcom($i+1, \"OFF\", $timeon, $timeoff, $vallist, $recoff.ymd, $recoff.dstchange);\t $append($on, $of);\t \t );\t\t $result:=$result[payload.dstchange=false]; /* ignore switches over DST changes */\t\t)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":370,"y":2500,"wires":[["0f2eed13f4a8fd7e"]]},{"id":"6059b908602e5c74","type":"change","z":"2dd6b0b4a5f86125","g":"29dd2ea7557213cd","name":"Read Schedules","rules":[{"t":"set","p":"topic","pt":"msg","to":"status-all","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":380,"y":2580,"wires":[["0f2eed13f4a8fd7e"]]},{"id":"a2da777d6df94115","type":"delay","z":"2dd6b0b4a5f86125","g":"29dd2ea7557213cd","name":"7s","pauseType":"delay","timeout":"7","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":230,"y":2580,"wires":[["6059b908602e5c74"]]},{"id":"6d225d4efd80e737","type":"cronplus","z":"2dd6b0b4a5f86125","g":"29dd2ea7557213cd","name":"Schedules","outputField":"payload","timeZone":"","storeName":"file","commandResponseMsgOutput":"output2","defaultLocation":"","defaultLocationType":"default","outputs":2,"options":[],"x":610,"y":2540,"wires":[["f7cbd2e4b217f3f1"],["ed031a2fcc75c493"]]},{"id":"decefda660d240ee","type":"inject","z":"2dd6b0b4a5f86125","g":"29dd2ea7557213cd","name":"Clear","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"remove-inactive","x":270,"y":2540,"wires":[["0f2eed13f4a8fd7e"]]},{"id":"f8ca783a52eb32d8","type":"inject","z":"2dd6b0b4a5f86125","g":"29dd2ea7557213cd","name":"Manual ON","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"ON","x":650,"y":2600,"wires":[["45b336c245c0c32f"]]},{"id":"3d951d153239eb27","type":"comment","z":"2dd6b0b4a5f86125","g":"29dd2ea7557213cd","name":"Binary Sensor - read me","info":"Uses the lowest 'import' prices\nSelects <n> from 'best list', eg set to 8\n for 4 hours of lowest import.\nAdjust is seconds delay (on) or advance (off)\n to avoid switching 'on the hour'\nUses 'cronplus' node, with dynamic schedules\n added from payload. Set 'Persist dynamic'\n to automatically save these to file and\n recover over NR restarts\n\nDST: will determine the start/end UTC timestamp\n for DST as GMT->BST and BST->GMT. Includes\n both UTC time and local time in arrays.\n\n For the binary sensor schedules, the 'cronplus'\n node uses the machine local timezone setting,\n so has to be provided with local not UTC times.\n\n To use UTC times, set the cronplus node timezone\n to a location with settings UTC+0 and DST:0\n\n To use local time, set the timezone to blank.\n ** IF USING LOCAL time ** note that HA must also\n change over at 01:00 UTC.\n\n ** NB ** To avoid issues, any switching period\n that spans a DST changeover will be supressed\n and ignored. The 'dstchange' field is true for\n periods that include mixed timezones at start\n and end. Also, the 'changing' field in OctDST\n will be true when a DST change time 01:00 UTC\n is within 48 hours of the tariff update (16:00)\n and this could be used to further surpress\n automations around the DST changeover day.\n\n\n","x":730,"y":2460,"wires":[]},{"id":"315b3d2dda9301bb","type":"link in","z":"2dd6b0b4a5f86125","g":"29dd2ea7557213cd","name":"Binary","links":["98266de28c6e5402","8bf35a995b07e7c0"],"x":95,"y":2500,"wires":[["22d6194ce87d6071","6b85072564ab77f1","a2da777d6df94115"]]},{"id":"7e69c69041f64555","type":"inject","z":"2dd6b0b4a5f86125","g":"29dd2ea7557213cd","name":"Read","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"status-all","x":410,"y":2540,"wires":[["0f2eed13f4a8fd7e"]]},{"id":"ed031a2fcc75c493","type":"change","z":"2dd6b0b4a5f86125","g":"29dd2ea7557213cd","name":"Save BINARY SCHEDULES","rules":[{"t":"set","p":"schedules","pt":"msg","to":"payload.result","tot":"msg","dc":true},{"t":"set","p":"OctAgileInBin","pt":"flow","to":"schedules","tot":"msg","dc":true},{"t":"set","p":"payload","pt":"msg","to":"new","tot":"str"},{"t":"set","p":"topic","pt":"msg","to":"NEW","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":860,"y":2540,"wires":[["c3990bf24fabec27"]]},{"id":"c284862b7284bd1d","type":"ha-binary-sensor","z":"2dd6b0b4a5f86125","d":true,"g":"29dd2ea7557213cd","name":"Octopus Agile Import Binary","entityConfig":"2a3c27e29918c767","version":0,"state":"topic=\"ON\"","stateType":"jsonata","attributes":[{"property":"event","value":"$exists(payload.event) ? $substringBefore(payload.event,\"=\") : \"-\"","valueType":"jsonata"},{"property":"timeOn","value":"$exists(payload.timeon) ? payload.timeon: 0","valueType":"jsonata"},{"property":"timeOff","value":"$exists(payload.timeoff) ? payload.timeoff : 0","valueType":"jsonata"},{"property":"duration","value":"$exists(payload.duration) ? payload.duration: 0","valueType":"jsonata"},{"property":"average","value":"$exists(payload.average) ? payload.average : 0","valueType":"jsonata"},{"property":"array","value":"$exists(payload.array) ? payload.array : []","valueType":"jsonata"}],"inputOverride":"block","outputProperties":[],"x":920,"y":2660,"wires":[[]],"server":""},{"id":"10cb994c44d0f0de","type":"inject","z":"2dd6b0b4a5f86125","g":"29dd2ea7557213cd","name":"Manual","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"MAN","payload":"manual","payloadType":"str","x":630,"y":2500,"wires":[["f7cbd2e4b217f3f1"]]},{"id":"0f2eed13f4a8fd7e","type":"junction","z":"2dd6b0b4a5f86125","g":"29dd2ea7557213cd","x":520,"y":2540,"wires":[["6d225d4efd80e737"]]},{"id":"45b336c245c0c32f","type":"junction","z":"2dd6b0b4a5f86125","g":"29dd2ea7557213cd","x":760,"y":2660,"wires":[["c284862b7284bd1d"]]},{"id":"c3990bf24fabec27","type":"link out","z":"2dd6b0b4a5f86125","g":"29dd2ea7557213cd","name":"Scheduled event","mode":"link","links":["a4572a5e5aeda036"],"x":1025,"y":2500,"wires":[]},{"id":"a4572a5e5aeda036","type":"link in","z":"2dd6b0b4a5f86125","g":"29dd2ea7557213cd","name":"Scheduled event","links":["c3990bf24fabec27"],"x":105,"y":2660,"wires":[["dae9895b170ecb41"]]},{"id":"f7cbd2e4b217f3f1","type":"change","z":"2dd6b0b4a5f86125","g":"29dd2ea7557213cd","name":"Read Schedules","rules":[{"t":"set","p":"schedules","pt":"msg","to":"OctAgileInBin","tot":"flow","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":820,"y":2500,"wires":[["c3990bf24fabec27"]]},{"id":"dae9895b170ecb41","type":"change","z":"2dd6b0b4a5f86125","g":"29dd2ea7557213cd","name":"Get Schedule Array","rules":[{"t":"set","p":"schedules","pt":"msg","to":"(\t/* from schedule read, get done and next */\t/* find the last and the next commands */\t \t $x:=schedules;\t $xdone:=$x[config.isRunning=false];\t $xtogo:=$x[config.isRunning];\t $xlast:=$xdone[-1];\t $xnext:=$xtogo[0];\t \t $array:=$x.(\t $c:=config;\t $s:=status;\t $p:=config.payload;\t {\t \"switch\": $c.topic,\t \"name\": $c.name,\t \"active\": $s.isRunning,\t \"event\": $p.event,\t \"timeon\": $p.timeon,\t \"timeoff\": $p.timeoff,\t \"duration\": $p.duration,\t \"average\": $p.average,\t \"description\": $s.nextDescription,\t \"UTC\": $s.nextDate,\t \"local\": $s.nextDateTZ\t });\t $array:=$array[switch=\"ON\"];\t\t {\"last\": $xlast.config.payload,\t \"next\": $xnext.config.payload,\t \"array\": $array}\t\t)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":230,"y":2660,"wires":[["fc1bbbe76ab45649"]]},{"id":"fc1bbbe76ab45649","type":"change","z":"2dd6b0b4a5f86125","g":"29dd2ea7557213cd","name":"Build message","rules":[{"t":"set","p":"result","pt":"msg","to":"(\t/* if fired by schedule: the topic and payload will already be given */\t/* if manual or update: if a 'last' event exists, lift and use that */\t/* if NR flow restart: if no 'last, 'next' exists and is \"off\" and */\t/* now' between next on & off times, use next event changed to \"ON\" */\t/* otherwise set to \"OFF\", and in all cases, patch in schedule array */\t\t $array:=schedules.array;\t $action:=$type(payload)=\"string\" ? payload : \"schedule\";\t\t $next:= $exists(schedules.next) ? schedules.next : {};\t $isON:= $next.timeon~>$toMillis()<=$millis() and $next.timeoff~>$toMillis()>$millis() and $next.switch=\"OFF\";\t $islast:= $exists(schedules.last);\t $last:= $islast ? schedules.last : {\"event\": \"=OFF\"};\t $not($islast) and $isON ? $last:= $next~>|$|{\"switch\": \"ON\", \"event\": $replace(event, \"OFF\", \"ON\")}|;\t\t $topic:=topic in [\"ON\", \"OFF\"] ? topic : $substringAfter($last.event, \"=\");\t $pload:= $type(payload)=\"object\" ? payload : $last;\t \t $pload:= $pload~>|$|{\"array\": $array}|;\t \t {\"topic\": $topic,\t \"action\": $action,\t \"isOn\": $isON,\t \"last\": $islast,\t \"payload\": $pload\t }\t\t)","tot":"jsonata"},{"t":"set","p":"payload","pt":"msg","to":"result.payload","tot":"msg","dc":true},{"t":"set","p":"topic","pt":"msg","to":"result.topic","tot":"msg","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":440,"y":2660,"wires":[["45b336c245c0c32f"]]},{"id":"2a3c27e29918c767","type":"ha-entity-config","d":true,"server":"","deviceConfig":"","name":"SC Oct Agile Imp Bin","version":"6","entityType":"binary_sensor","haConfig":[{"property":"name","value":"Octopus Agile Import Binary"},{"property":"icon","value":""},{"property":"entity_category","value":""},{"property":"entity_picture","value":""},{"property":"device_class","value":""}],"resend":true,"debugEnabled":false},{"id":"518fc65503bdfc82","type":"group","z":"2dd6b0b4a5f86125","g":"e42010beae8f7fa5","name":"Caclulate and save best times and contiguous periods","style":{"label":true,"color":"#6f2fa0"},"nodes":["7b2bfeb83135f71f","b98e955f8996efa2","c63c0e9f64999a1e","87bddd29d5e5ab90","339092c8ec953466","f78827da9d61cc5c","af230b1ce1f0097f","9d5af052c0da6b34","8ad658e6e88a7da9","115ae37f9df88633","9f49cf24a9de3b53","0b2baaea3d361864","1a455554a27f0b90","8bf35a995b07e7c0","70d7bd0a4d244b4c","5fd6c5257050028c"],"x":54,"y":2219,"w":1012,"h":182},{"id":"7b2bfeb83135f71f","type":"change","z":"2dd6b0b4a5f86125","g":"518fc65503bdfc82","name":"Import Low","rules":[{"t":"set","p":"topic","pt":"msg","to":"import","tot":"str"},{"t":"set","p":"sample","pt":"msg","to":"15","tot":"num"},{"t":"set","p":"payload","pt":"msg","to":"/* look at latest prices, sorted by ascending import cost, pick the lowest */\t/* <sample size>, set value to import and remove the import/export fields */\t\t(\t $ymd:=$replace(payload[-1].date,\"-\",\"\");\t $array:=payload[[48..95]]^(import)[[0..$$.sample-1]];\t $array:=$array~> |$| {\"value\": import, \"ymd\": $ymd}, [\"import\", \"export\"]|;\t $array^(from)\t)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":430,"y":2260,"wires":[["f78827da9d61cc5c"]]},{"id":"b98e955f8996efa2","type":"change","z":"2dd6b0b4a5f86125","g":"518fc65503bdfc82","name":"Read Array","rules":[{"t":"set","p":"payload","pt":"msg","to":"OctAgileTariff","tot":"flow","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":230,"y":2300,"wires":[["5fd6c5257050028c"]]},{"id":"c63c0e9f64999a1e","type":"inject","z":"2dd6b0b4a5f86125","g":"518fc65503bdfc82","name":"Manual","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":150,"y":2260,"wires":[["b98e955f8996efa2"]]},{"id":"87bddd29d5e5ab90","type":"link in","z":"2dd6b0b4a5f86125","g":"518fc65503bdfc82","name":"Daily","links":["56dd710454ea2e25"],"x":285,"y":2260,"wires":[["5fd6c5257050028c"]]},{"id":"339092c8ec953466","type":"ha-sensor","z":"2dd6b0b4a5f86125","d":true,"g":"518fc65503bdfc82","name":"Octopus Agile Sequences","entityConfig":"6f8158bd34274dd3","version":0,"state":"(\t $next:=payload.next;\t $count(payload.export[ymd=$next]) + $count(payload.import[ymd=$next]); )","stateType":"jsonata","attributes":[{"property":"export_array","value":"payload.export","valueType":"msg"},{"property":"import_array","value":"payload.import","valueType":"msg"},{"property":"both_array","value":"payload.both","valueType":"msg"},{"property":"bid_offer_spread","value":"(\t $next:=payload.next;\t $min(payload.import[ymd=$next].average)-$max(payload.export[ymd=$next].average); )","valueType":"jsonata"},{"property":"block_today","value":"payload.today","valueType":"msg"},{"property":"block_next","value":"payload.next","valueType":"msg"}],"inputOverride":"allow","outputProperties":[],"x":930,"y":2360,"wires":[[]],"server":""},{"id":"f78827da9d61cc5c","type":"change","z":"2dd6b0b4a5f86125","g":"518fc65503bdfc82","name":"Sequence","rules":[{"t":"set","p":"payload","pt":"msg","to":"/* note index position, and test if items */\t/* are consecutive - forwards and backwards */\t/* set position as only, start, mid, end */\t\tpayload#$v.(\t $last:=$v<1 ? false : from=%.payload[$v-1].upto;\t $next:=upto=%.payload[$v+1].from;\t $position:=(\t $last ? ($next ? \"middle\" : \"end\") : ($next ? \"start\" : \"only\")\t );\t $~>|$|{\"index\": $v, \"link_last\": $last, \"link_next\": $next, \"position\": $position}|\t)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":600,"y":2280,"wires":[["9d5af052c0da6b34","8ad658e6e88a7da9"]]},{"id":"af230b1ce1f0097f","type":"change","z":"2dd6b0b4a5f86125","g":"518fc65503bdfc82","name":"Save BEST","rules":[{"t":"set","p":"OctAgileBest","pt":"flow","to":"payload","tot":"msg","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":910,"y":2280,"wires":[["8bf35a995b07e7c0"]]},{"id":"9d5af052c0da6b34","type":"join","z":"2dd6b0b4a5f86125","g":"518fc65503bdfc82","name":"Join","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"num","reduceFixup":"","x":770,"y":2280,"wires":[["af230b1ce1f0097f"]]},{"id":"8ad658e6e88a7da9","type":"change","z":"2dd6b0b4a5f86125","g":"518fc65503bdfc82","name":"Groups","rules":[{"t":"set","p":"payload","pt":"msg","to":"/* get start and end indexes, and zip into a sequence array of [start, end] */\t/* map this array of sequences to an array of objects, one for each sequence to include */\t/* sequence number, index range, date, start time, stop time, count of half-hours */\t/* duration, and average (sum of values in sequence divided by count of items in sequence) */\t\t(\t $chain:=$zip(payload[position=\"start\"].index, payload[position=\"end\"].index);\t $array:=$map($chain, function($item, $index) {\t (\t $aa:=payload[$a:=$item[0]];\t $bb:=payload[$b:=$item[1]];\t $count:=$b-$a+1;\t {\t \"mode\": topic,\t \"sample\": sample,\t \"ymd\": $aa.ymd,\t \"sequence\": $index+1,\t \"range\": ($a+1) & \"-\" & ($b+1),\t \"from\": $aa.from,\t \"upto\": $bb.upto,\t \"date\": $aa.date,\t \"timefrom\": $aa.timefrom,\t \"timeupto\": $bb.timeupto,\t \"localfrom\": $aa.localfrom,\t \"localupto\": $bb.localupto,\t \"isofrom\": $aa.isofrom,\t \"isoupto\": $bb.isoupto,\t \"periods\": $count,\t \"duration\": $count*30,\t \"average\": $round(($sum(payload[[$a..$b]].value)/$count)*1000)/1000,\t \"DSTchange\": $substring($aa.localfrom,-3) != $substring($bb.localfrom,-3)\t })\t });\t $array^(from)[];\t)\t\t/* (>duration) gets longest periods first, however (from) sorts */\t/* chronologically, which is required for correct display on tariff graph */\t/* final [] places result into an array even if only one sequence group */","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":160,"y":2360,"wires":[["115ae37f9df88633"]]},{"id":"115ae37f9df88633","type":"join","z":"2dd6b0b4a5f86125","g":"518fc65503bdfc82","name":"Join","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"num","reduceFixup":"","x":290,"y":2360,"wires":[["0b2baaea3d361864"]]},{"id":"9f49cf24a9de3b53","type":"change","z":"2dd6b0b4a5f86125","g":"518fc65503bdfc82","name":"Save PERIODS","rules":[{"t":"set","p":"OctAgilePeriod","pt":"flow","to":"payload","tot":"msg","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":700,"y":2340,"wires":[[]]},{"id":"0b2baaea3d361864","type":"change","z":"2dd6b0b4a5f86125","g":"518fc65503bdfc82","name":"Table","rules":[{"t":"set","p":"payload.both","pt":"msg","to":"$append(payload.import, payload.export)\t","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":410,"y":2360,"wires":[["70d7bd0a4d244b4c"]]},{"id":"1a455554a27f0b90","type":"change","z":"2dd6b0b4a5f86125","g":"518fc65503bdfc82","name":"Export High","rules":[{"t":"set","p":"topic","pt":"msg","to":"export","tot":"str"},{"t":"set","p":"sample","pt":"msg","to":"15","tot":"num"},{"t":"set","p":"payload","pt":"msg","to":"/* for export values - as for import but */\t/* sorted from highest to lowest, top <n> */\t\t(\t $ymd:=$replace(payload[-1].date,\"-\",\"\");\t $array:=payload[[48..95]]^(>export)[[0..$$.sample-1]];\t $array:=$array~> |$| {\"value\": export, \"ymd\": $ymd}, [\"import\", \"export\"]|;\t $array^(from);\t)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":430,"y":2300,"wires":[["f78827da9d61cc5c"]]},{"id":"8bf35a995b07e7c0","type":"link out","z":"2dd6b0b4a5f86125","g":"518fc65503bdfc82","name":"Binary","mode":"link","links":["315b3d2dda9301bb"],"x":1025,"y":2280,"wires":[]},{"id":"70d7bd0a4d244b4c","type":"change","z":"2dd6b0b4a5f86125","g":"518fc65503bdfc82","name":"Merge","rules":[{"t":"set","p":"period","pt":"msg","to":"OctAgilePeriod","tot":"flow","dc":true},{"t":"set","p":"payload","pt":"msg","to":"(\t/* keep today from context or payload if no context */\t/* drop any older, then add new tomorrow from payload */ \t\t $today:=$replace($substringBefore($now(),\"T\"),\"-\",\"\");\t $next:= payload.import[0].ymd;\t\t {\"import\": $append(period.import, payload.import)[ymd>=$today][]~>$distinct(),\t \"export\": $append(period.export, payload.export)[ymd>=$today][]~>$distinct(),\t \"both\": $append(period.both, payload.both)[ymd>=$today][]~>$distinct(),\t \"today\": $today,\t \"next\": $next};\t\t)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":530,"y":2360,"wires":[["9f49cf24a9de3b53","339092c8ec953466"]]},{"id":"5fd6c5257050028c","type":"junction","z":"2dd6b0b4a5f86125","g":"518fc65503bdfc82","x":340,"y":2280,"wires":[["7b2bfeb83135f71f","1a455554a27f0b90"]]},{"id":"6f8158bd34274dd3","type":"ha-entity-config","d":true,"server":"","deviceConfig":"","name":"SC Oct Agile Seq","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"Octopus Agile Sequence Table"},{"property":"icon","value":""},{"property":"entity_category","value":""},{"property":"entity_picture","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":""},{"property":"state_class","value":""}],"resend":true,"debugEnabled":false}]