Import flow
Flow níže vytvoří novou záložku spotovky.cz se třemi větvemi:
- MQTT JSON — uzel
mqtt inodebíráv2/current/jsona předává objekt s cenou, začátkem a koncem intervalu a pořadím. - MQTT binárně — odebírá
v2/current/bin(16 bytů) a funkce ho dekóduje na stejný objekt. Ukazuje práci s binárním formátem v2. - REST — každých 15 minut stáhne
/v2/prices/todaya funkce vybere aktuální interval.
V Node-RED otevřete menu vpravo nahoře → Import, vložte JSON a potvrďte. Pak klikněte na Deploy. Výsledky se ukážou v postranním panelu Debug a cena ve stavu uzlů debug.
Node-RED flow (JSON)
[
{
"id": "spotovky_tab",
"type": "tab",
"label": "spotovky.cz",
"disabled": false,
"info": "Spotové ceny elektřiny z API spotovky.cz"
},
{
"id": "spotovky_broker",
"type": "mqtt-broker",
"name": "spotovky.cz",
"broker": "spotovky.cz",
"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": ""
},
{
"id": "spotovky_mqtt_json",
"type": "mqtt in",
"z": "spotovky_tab",
"name": "v2/current/json",
"topic": "v2/current/json",
"qos": "1",
"datatype": "json",
"broker": "spotovky_broker",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 140,
"y": 80,
"wires": [
[
"spotovky_dbg_json"
]
]
},
{
"id": "spotovky_dbg_json",
"type": "debug",
"z": "spotovky_tab",
"name": "Aktuální cena (JSON)",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": true,
"complete": "payload",
"targetType": "msg",
"statusVal": "payload.czk",
"statusType": "msg",
"x": 420,
"y": 80,
"wires": []
},
{
"id": "spotovky_mqtt_bin",
"type": "mqtt in",
"z": "spotovky_tab",
"name": "v2/current/bin",
"topic": "v2/current/bin",
"qos": "1",
"datatype": "buffer",
"broker": "spotovky_broker",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 140,
"y": 160,
"wires": [
[
"spotovky_fn_bin"
]
]
},
{
"id": "spotovky_fn_bin",
"type": "function",
"z": "spotovky_tab",
"name": "Dekódovat binární v2",
"func": "// v2/current/bin: 16 bytů, little-endian\nconst b = msg.payload;\nif (!Buffer.isBuffer(b) || b.length < 16 || b[0] !== 2) return null;\nmsg.payload = {\n start: new Date(Number(b.readBigUInt64LE(2)) * 1000).toISOString(),\n czk: b.readInt16LE(10) / 100, // Kč/kWh, může být záporná\n rank: b.readUInt8(12), // 1 = nejlevnější\n rate: b.readUInt16LE(13) / 1000, // kurz EUR/CZK\n periods: b.readUInt8(15), // 92, 96 nebo 100\n complete: (b[1] & 0x01) !== 0,\n negative_day: (b[1] & 0x02) !== 0\n};\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 380,
"y": 160,
"wires": [
[
"spotovky_dbg_bin"
]
]
},
{
"id": "spotovky_dbg_bin",
"type": "debug",
"z": "spotovky_tab",
"name": "Aktuální cena (binárně)",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": true,
"complete": "payload",
"targetType": "msg",
"statusVal": "payload.czk",
"statusType": "msg",
"x": 640,
"y": 160,
"wires": []
},
{
"id": "spotovky_inject",
"type": "inject",
"z": "spotovky_tab",
"name": "Každých 15 min",
"props": [
{
"p": "payload"
}
],
"repeat": "900",
"crontab": "",
"once": true,
"onceDelay": "2",
"topic": "",
"payload": "",
"payloadType": "date",
"x": 150,
"y": 240,
"wires": [
[
"spotovky_http"
]
]
},
{
"id": "spotovky_http",
"type": "http request",
"z": "spotovky_tab",
"name": "GET /v2/prices/today",
"method": "GET",
"ret": "obj",
"paytoqs": "ignore",
"url": "https://api.spotovky.cz/v2/prices/today",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [],
"x": 380,
"y": 240,
"wires": [
[
"spotovky_fn_rest"
]
]
},
{
"id": "spotovky_fn_rest",
"type": "function",
"z": "spotovky_tab",
"name": "Aktuální interval",
"func": "// Najde aktuální 15minutový interval v odpovědi /v2/prices/today\nif (msg.statusCode !== 200) {\n node.warn(\"API vrátilo HTTP \" + msg.statusCode);\n return null;\n}\nconst now = Date.now();\nconst slots = msg.payload.slots || [];\nconst cur = slots.find(s => {\n const t = Date.parse(s.start);\n return t <= now && now < t + 15 * 60 * 1000;\n});\nif (!cur) return null;\nmsg.payload = {\n date: msg.payload.date,\n start: cur.start,\n czk: cur.czk,\n eur: cur.eur,\n rank: cur.rank,\n periods: slots.length\n};\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 600,
"y": 240,
"wires": [
[
"spotovky_dbg_rest"
]
]
},
{
"id": "spotovky_dbg_rest",
"type": "debug",
"z": "spotovky_tab",
"name": "Aktuální cena (REST)",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": true,
"complete": "payload",
"targetType": "msg",
"statusVal": "payload.czk",
"statusType": "msg",
"x": 830,
"y": 240,
"wires": []
}
]
Konfigurační uzel brokeru má prázdné zprávy birth, close i will: broker spotovky.cz přijímá jen subscribe a publish odmítá. Na tento broker nepřipojujte uzel mqtt out.
Co dál
- Ceny celého dne odebírejte z
v2/today/jsonav2/tomorrow/json(stejný formát jako REST/v2/prices/…). Zpráva pro zítřek přichází obvykle po 13:05 a po půlnoci se maže prázdnou retain zprávou, kterou je dobré ve flow ignorovat. - Pole
rank(1 = nejlevnější) se hodí pro uzelswitch: např. „rank ≤ 16“ znamená 16 nejlevnějších čtvrthodin dne. - Počet intervalů dne není vždy 96: v den změny času je 92 nebo 100. Používejte
periodsnebo délku poleslots.