Created
October 2, 2025 17:35
-
-
Save epaulsen/9dcae3a7ad17a127ea35efd92ec410fa to your computer and use it in GitHub Desktop.
Hack for å få timespris ut fra nordpool-sensoren.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| mqtt: | |
| sensor: | |
| - name: "Nordpool Spot Timespris Kr.Sand" | |
| unique_id: "sensor.nordpool_spot_timespris_krsand" | |
| state_topic: "Nordpool/Spot_Timespris/value" | |
| unit_of_measurement: "NOK/kWh" | |
| value_template: "{{ value_json | float(0) }}" | |
| json_attributes_topic: "Nordpool/Spot_Timespris/attributes" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| [{"id":"c7e13d35b37b1a11","type":"inject","z":"c47a770c26e3be71","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":80,"y":1560,"wires":[["be9c0199d1412355"]]},{"id":"be9c0199d1412355","type":"api-current-state","z":"c47a770c26e3be71","name":"","server":"72b5aa9aa9eb914e","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.nordpool_kwh_no2_nok_3_095_025","state_type":"str","blockInputOverrides":true,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":410,"y":1560,"wires":[["ad7f9e243bd10930","a51ddd79662f2acf"]]},{"id":"a1a407acab9df560","type":"server-state-changed","z":"c47a770c26e3be71","name":"","server":"72b5aa9aa9eb914e","version":6,"outputs":1,"exposeAsEntityConfig":"","entities":{"entity":["sensor.nordpool_kwh_no2_nok_3_095_025"],"substring":[],"regex":[]},"outputInitially":false,"stateType":"str","ifState":"","ifStateType":"str","ifStateOperator":"is","outputOnlyOnStateChange":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"x":400,"y":1620,"wires":[["ad7f9e243bd10930","a51ddd79662f2acf"]]},{"id":"ad7f9e243bd10930","type":"function","z":"c47a770c26e3be71","name":"Parse timepris","func":"function calculateHourlyAverages(inputArray) {\n const hourlyMap = {};\n\n inputArray.forEach(entry => {\n const start = new Date(entry.start);\n const hourKey = new Date(\n start.getFullYear(),\n start.getMonth(),\n start.getDate(),\n start.getHours(),\n 0, 0\n ).getTime(); // Bruk timestamp som nøkkel\n if (!hourlyMap[hourKey]) {\n hourlyMap[hourKey] = [];\n }\n hourlyMap[hourKey].push(entry.value);\n });\n\n const toIsoWithOffset = (date) => {\n const pad = (n) => n.toString().padStart(2, '0');\n const yyyy = date.getFullYear();\n const mm = pad(date.getMonth() + 1);\n const dd = pad(date.getDate());\n const hh = pad(date.getHours());\n const min = pad(date.getMinutes());\n const ss = pad(date.getSeconds());\n const offset = -date.getTimezoneOffset(); // i minutter\n const sign = offset >= 0 ? '+' : '-';\n const offsetHours = pad(Math.floor(Math.abs(offset) / 60));\n const offsetMinutes = pad(Math.abs(offset) % 60);\n return `${yyyy}-${mm}-${dd}T${hh}:${min}:${ss}${sign}${offsetHours}:${offsetMinutes}`;\n };\n\n const result = Object.entries(hourlyMap).map(([timestamp, values]) => {\n const startDate = new Date(parseInt(timestamp));\n const endDate = new Date(startDate.getTime() + 60 * 60 * 1000);\n const avg = values.reduce((sum, val) => sum + val, 0) / values.length;\n\n return {\n start: toIsoWithOffset(startDate),\n end: toIsoWithOffset(endDate),\n value: Math.round(avg * 1000) / 1000\n };\n });\n\n return result;\n}\n\nfunction calculateCurrentHourAverage(inputArray) {\n const now = new Date();\n const currentHourStart = new Date(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), 0, 0);\n const currentHourEnd = new Date(currentHourStart.getTime() + 60 * 60 * 1000);\n\n const currentHourValues = inputArray.filter(entry => {\n const start = new Date(entry.start);\n return start >= currentHourStart && start < currentHourEnd;\n }).map(entry => entry.value);\n\n if (currentHourValues.length === 0) {\n return null;\n }\n\n const avg = currentHourValues.reduce((sum, val) => sum + val, 0) / currentHourValues.length;\n return Math.round(avg * 1000) / 1000;\n}\n\nconst raw_today = calculateHourlyAverages(msg.data.attributes.raw_today);\nconst raw_tomorrow = calculateHourlyAverages(msg.data.attributes.raw_tomorrow);\n\nconst currentValue = calculateCurrentHourAverage(msg.data.attributes.raw_today);\n\n// var payload = \n// {\n// currentValue, // TODO: Beregn snitt for alle verdier i timen vi er inne i,\n// \"attributes\": {\n// \"raw_today\" : raw_today,\n// \"raw_tomorrow\": raw_tomorrow\n// }\n// };\n\nmsg.payload = currentValue;\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":820,"y":1580,"wires":[["521719d0f1642c01"]]},{"id":"a51ddd79662f2acf","type":"function","z":"c47a770c26e3be71","name":"Parse attributes","func":"function calculateHourlyAverages(inputArray) {\n const hourlyMap = {};\n\n inputArray.forEach(entry => {\n const start = new Date(entry.start);\n const hourKey = new Date(\n start.getFullYear(),\n start.getMonth(),\n start.getDate(),\n start.getHours(),\n 0, 0\n ).getTime(); // Bruk timestamp som nøkkel\n if (!hourlyMap[hourKey]) {\n hourlyMap[hourKey] = [];\n }\n hourlyMap[hourKey].push(entry.value);\n });\n\n const toIsoWithOffset = (date) => {\n const pad = (n) => n.toString().padStart(2, '0');\n const yyyy = date.getFullYear();\n const mm = pad(date.getMonth() + 1);\n const dd = pad(date.getDate());\n const hh = pad(date.getHours());\n const min = pad(date.getMinutes());\n const ss = pad(date.getSeconds());\n const offset = -date.getTimezoneOffset(); // i minutter\n const sign = offset >= 0 ? '+' : '-';\n const offsetHours = pad(Math.floor(Math.abs(offset) / 60));\n const offsetMinutes = pad(Math.abs(offset) % 60);\n return `${yyyy}-${mm}-${dd}T${hh}:${min}:${ss}${sign}${offsetHours}:${offsetMinutes}`;\n };\n\n const result = Object.entries(hourlyMap).map(([timestamp, values]) => {\n const startDate = new Date(parseInt(timestamp));\n const endDate = new Date(startDate.getTime() + 60 * 60 * 1000);\n const avg = values.reduce((sum, val) => sum + val, 0) / values.length;\n\n return {\n start: toIsoWithOffset(startDate),\n end: toIsoWithOffset(endDate),\n value: Math.round(avg * 1000) / 1000\n };\n });\n\n return result;\n}\n\nconst raw_today = calculateHourlyAverages(msg.data.attributes.raw_today);\nconst raw_tomorrow = calculateHourlyAverages(msg.data.attributes.raw_tomorrow);\n\n\nvar payload = \n{ \n \"attributes\": {\n \"raw_today\" : raw_today,\n \"raw_tomorrow\": raw_tomorrow\n }\n};\n\nmsg.payload = payload;\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":820,"y":1620,"wires":[["2d4835965d52cc02"]]},{"id":"521719d0f1642c01","type":"mqtt out","z":"c47a770c26e3be71","name":"Publish Timepris","topic":"Nordpool/Spot_Timespris/value","qos":"1","retain":"true","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"210b8811ec1781ab","x":1160,"y":1560,"wires":[]},{"id":"2d4835965d52cc02","type":"mqtt out","z":"c47a770c26e3be71","name":"Publish Timepris","topic":"Nordpool/Spot_Timespris/attributes","qos":"1","retain":"true","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"210b8811ec1781ab","x":1160,"y":1640,"wires":[]},{"id":"72b5aa9aa9eb914e","type":"server","name":"Home Assistant","version":5,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":true,"heartbeatInterval":"30","areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":": ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true},{"id":"210b8811ec1781ab","type":"mqtt-broker","name":"z2m","broker":"192.168.1.226","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"autoUnsubscribe":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""}] |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Fremgangsmåte:
Tilpass på sensoren til hva enn du ønsker.