|
[ |
|
{ |
|
"id": "753058b1a55fbfa2", |
|
"type": "tab", |
|
"label": "Solarman PV OPEN API (v1.1.6)", |
|
"disabled": false, |
|
"info": "", |
|
"env": [] |
|
}, |
|
{ |
|
"id": "97e2b57ad550d351", |
|
"type": "catch", |
|
"z": "753058b1a55fbfa2", |
|
"name": "catch (error)", |
|
"scope": null, |
|
"uncaught": false, |
|
"x": 90, |
|
"y": 40, |
|
"wires": [ |
|
[ |
|
"929402fd6c835c5f" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "929402fd6c835c5f", |
|
"type": "debug", |
|
"z": "753058b1a55fbfa2", |
|
"name": "error", |
|
"active": true, |
|
"tosidebar": true, |
|
"console": false, |
|
"tostatus": false, |
|
"complete": "true", |
|
"targetType": "full", |
|
"statusVal": "", |
|
"statusType": "auto", |
|
"x": 290, |
|
"y": 40, |
|
"wires": [] |
|
}, |
|
{ |
|
"id": "e3e50394532dd5fc", |
|
"type": "comment", |
|
"z": "753058b1a55fbfa2", |
|
"name": "read.me", |
|
"info": "# Example of how to fetch data from Solarman PV OPEN API v1.1.6\nTo avoid unnecessarily struggling to connect Node-RED to the Solarman PV OPEN API (globalapi.solarmanpv.com). \n\n## Prerequisites\n - app ID and app secret, request by sending an email to [email protected]\n - login details, register an account with Solarman Smart (home.solarmanpv.com)\n - the password has to be SHA256 encrypted first (you can use an online convertor, crypto-js or a Node-RED package)\n\n## Set-up\n - fill in app ID, app secret, email and password (SHA256 encrypted) in the _set flow data_ node\n\n## Request steps\n - request (and store) the access token with _account token_\n - request (and store) the station ID with _station list_\n - request (and store) the device ID with _station device_\n - request historical data with _device historical_", |
|
"x": 900, |
|
"y": 40, |
|
"wires": [] |
|
}, |
|
{ |
|
"id": "1e4a47fa3de24e98", |
|
"type": "http request", |
|
"z": "753058b1a55fbfa2", |
|
"name": "account token", |
|
"method": "use", |
|
"ret": "obj", |
|
"paytoqs": "body", |
|
"url": "https://{{location}}/account/{{version}}/token?appId={{appId}}", |
|
"tls": "", |
|
"persist": false, |
|
"proxy": "", |
|
"insecureHTTPParser": false, |
|
"authType": "", |
|
"senderr": false, |
|
"headers": [], |
|
"x": 640, |
|
"y": 180, |
|
"wires": [ |
|
[ |
|
"c3a4c40f5255993e" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "f9e283500afe1c56", |
|
"type": "inject", |
|
"z": "753058b1a55fbfa2", |
|
"name": "set", |
|
"props": [], |
|
"repeat": "", |
|
"crontab": "", |
|
"once": false, |
|
"onceDelay": 0.1, |
|
"topic": "", |
|
"x": 70, |
|
"y": 100, |
|
"wires": [ |
|
[ |
|
"bb9204f882f692fe" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "bb9204f882f692fe", |
|
"type": "change", |
|
"z": "753058b1a55fbfa2", |
|
"name": "set flow data", |
|
"rules": [ |
|
{ |
|
"t": "set", |
|
"p": "headers.contentType", |
|
"pt": "flow", |
|
"to": "application/json", |
|
"tot": "str" |
|
}, |
|
{ |
|
"t": "set", |
|
"p": "location", |
|
"pt": "flow", |
|
"to": "globalapi.solarmanpv.com", |
|
"tot": "str" |
|
}, |
|
{ |
|
"t": "set", |
|
"p": "version", |
|
"pt": "flow", |
|
"to": "v1.0", |
|
"tot": "str" |
|
}, |
|
{ |
|
"t": "set", |
|
"p": "appId", |
|
"pt": "flow", |
|
"to": "APPID", |
|
"tot": "str" |
|
}, |
|
{ |
|
"t": "set", |
|
"p": "appSecret", |
|
"pt": "flow", |
|
"to": "APPSECRET", |
|
"tot": "str" |
|
}, |
|
{ |
|
"t": "set", |
|
"p": "email", |
|
"pt": "flow", |
|
"to": "EMAIL", |
|
"tot": "str" |
|
}, |
|
{ |
|
"t": "set", |
|
"p": "password", |
|
"pt": "flow", |
|
"to": "PASSWORD_SHA256", |
|
"tot": "str" |
|
} |
|
], |
|
"action": "", |
|
"property": "", |
|
"from": "", |
|
"to": "", |
|
"reg": false, |
|
"x": 310, |
|
"y": 100, |
|
"wires": [ |
|
[] |
|
] |
|
}, |
|
{ |
|
"id": "87ca417fa31eca6c", |
|
"type": "inject", |
|
"z": "753058b1a55fbfa2", |
|
"name": "set request data", |
|
"props": [ |
|
{ |
|
"p": "method", |
|
"v": "POST", |
|
"vt": "str" |
|
}, |
|
{ |
|
"p": "headers['content-type']", |
|
"v": "headers.contentType", |
|
"vt": "flow" |
|
}, |
|
{ |
|
"p": "location", |
|
"v": "location", |
|
"vt": "flow" |
|
}, |
|
{ |
|
"p": "version", |
|
"v": "version", |
|
"vt": "flow" |
|
}, |
|
{ |
|
"p": "appId", |
|
"v": "appId", |
|
"vt": "flow" |
|
}, |
|
{ |
|
"p": "payload.appSecret", |
|
"v": "appSecret", |
|
"vt": "flow" |
|
}, |
|
{ |
|
"p": "payload.email", |
|
"v": "email", |
|
"vt": "flow" |
|
}, |
|
{ |
|
"p": "payload.password", |
|
"v": "password", |
|
"vt": "flow" |
|
} |
|
], |
|
"repeat": "", |
|
"crontab": "", |
|
"once": false, |
|
"onceDelay": 0.1, |
|
"topic": "", |
|
"x": 100, |
|
"y": 180, |
|
"wires": [ |
|
[ |
|
"1e4a47fa3de24e98" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "c3a4c40f5255993e", |
|
"type": "change", |
|
"z": "753058b1a55fbfa2", |
|
"name": "store tokens in flow data", |
|
"rules": [ |
|
{ |
|
"t": "set", |
|
"p": "accessToken", |
|
"pt": "flow", |
|
"to": "payload.access_token", |
|
"tot": "msg" |
|
}, |
|
{ |
|
"t": "set", |
|
"p": "tokenType", |
|
"pt": "flow", |
|
"to": "payload.token_type", |
|
"tot": "str" |
|
}, |
|
{ |
|
"t": "set", |
|
"p": "refreshToken", |
|
"pt": "flow", |
|
"to": "payload.refresh_token", |
|
"tot": "msg" |
|
}, |
|
{ |
|
"t": "set", |
|
"p": "authorization", |
|
"pt": "flow", |
|
"to": "payload.token_type & ' ' & payload.access_token", |
|
"tot": "jsonata" |
|
} |
|
], |
|
"action": "", |
|
"property": "", |
|
"from": "", |
|
"to": "", |
|
"reg": false, |
|
"x": 850, |
|
"y": 180, |
|
"wires": [ |
|
[] |
|
] |
|
}, |
|
{ |
|
"id": "a9e64147829d42c7", |
|
"type": "http request", |
|
"z": "753058b1a55fbfa2", |
|
"name": "station list", |
|
"method": "use", |
|
"ret": "obj", |
|
"paytoqs": "body", |
|
"url": "https://{{location}}/station/{{version}}/list", |
|
"tls": "", |
|
"persist": false, |
|
"proxy": "", |
|
"insecureHTTPParser": false, |
|
"authType": "", |
|
"senderr": false, |
|
"headers": [], |
|
"x": 630, |
|
"y": 220, |
|
"wires": [ |
|
[ |
|
"32980a623324c86b" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "f086f7bea987a9c0", |
|
"type": "inject", |
|
"z": "753058b1a55fbfa2", |
|
"name": "set request data", |
|
"props": [ |
|
{ |
|
"p": "method", |
|
"v": "POST", |
|
"vt": "str" |
|
}, |
|
{ |
|
"p": "headers['content-type']", |
|
"v": "headers.contentType", |
|
"vt": "flow" |
|
}, |
|
{ |
|
"p": "headers.Authorization", |
|
"v": "authorization", |
|
"vt": "flow" |
|
}, |
|
{ |
|
"p": "location", |
|
"v": "location", |
|
"vt": "flow" |
|
}, |
|
{ |
|
"p": "version", |
|
"v": "version", |
|
"vt": "flow" |
|
}, |
|
{ |
|
"p": "payload" |
|
} |
|
], |
|
"repeat": "", |
|
"crontab": "", |
|
"once": false, |
|
"onceDelay": 0.1, |
|
"topic": "", |
|
"payload": "{}", |
|
"payloadType": "json", |
|
"x": 100, |
|
"y": 220, |
|
"wires": [ |
|
[ |
|
"a9e64147829d42c7" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "32980a623324c86b", |
|
"type": "change", |
|
"z": "753058b1a55fbfa2", |
|
"name": "store station in flow data", |
|
"rules": [ |
|
{ |
|
"t": "set", |
|
"p": "station", |
|
"pt": "flow", |
|
"to": "payload.stationList[0]", |
|
"tot": "msg" |
|
}, |
|
{ |
|
"t": "set", |
|
"p": "stationId", |
|
"pt": "flow", |
|
"to": "payload.stationList[0].id", |
|
"tot": "msg" |
|
} |
|
], |
|
"action": "", |
|
"property": "", |
|
"from": "", |
|
"to": "", |
|
"reg": false, |
|
"x": 850, |
|
"y": 220, |
|
"wires": [ |
|
[] |
|
] |
|
}, |
|
{ |
|
"id": "6f380cbadc4d7196", |
|
"type": "inject", |
|
"z": "753058b1a55fbfa2", |
|
"name": "set request data", |
|
"props": [ |
|
{ |
|
"p": "method", |
|
"v": "POST", |
|
"vt": "str" |
|
}, |
|
{ |
|
"p": "headers['content-type']", |
|
"v": "headers.contentType", |
|
"vt": "flow" |
|
}, |
|
{ |
|
"p": "headers.Authorization", |
|
"v": "authorization", |
|
"vt": "flow" |
|
}, |
|
{ |
|
"p": "location", |
|
"v": "location", |
|
"vt": "flow" |
|
}, |
|
{ |
|
"p": "version", |
|
"v": "version", |
|
"vt": "flow" |
|
}, |
|
{ |
|
"p": "payload.stationId", |
|
"v": "stationId", |
|
"vt": "flow" |
|
} |
|
], |
|
"repeat": "", |
|
"crontab": "", |
|
"once": false, |
|
"onceDelay": 0.1, |
|
"topic": "", |
|
"x": 100, |
|
"y": 260, |
|
"wires": [ |
|
[ |
|
"2bce0978628ccb5c" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "2bce0978628ccb5c", |
|
"type": "http request", |
|
"z": "753058b1a55fbfa2", |
|
"name": "station device", |
|
"method": "POST", |
|
"ret": "obj", |
|
"paytoqs": "body", |
|
"url": "https://{{location}}/station/{{version}}/device", |
|
"tls": "", |
|
"persist": false, |
|
"proxy": "", |
|
"insecureHTTPParser": false, |
|
"authType": "", |
|
"senderr": false, |
|
"headers": [], |
|
"x": 640, |
|
"y": 260, |
|
"wires": [ |
|
[ |
|
"1386834c067c1a87" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "1386834c067c1a87", |
|
"type": "change", |
|
"z": "753058b1a55fbfa2", |
|
"name": "set devices in flow data", |
|
"rules": [ |
|
{ |
|
"t": "set", |
|
"p": "devices", |
|
"pt": "flow", |
|
"to": "payload.deviceListItems", |
|
"tot": "msg" |
|
} |
|
], |
|
"action": "", |
|
"property": "", |
|
"from": "", |
|
"to": "", |
|
"reg": false, |
|
"x": 850, |
|
"y": 260, |
|
"wires": [ |
|
[] |
|
] |
|
}, |
|
{ |
|
"id": "133119fc2aef77ea", |
|
"type": "function", |
|
"z": "753058b1a55fbfa2", |
|
"name": "time type 1", |
|
"func": "const now = new Date();\nmsg.payload.endTime = now.toISOString().slice(0, 10);\nmsg.payload.startTime = msg.payload.endTime;\nmsg.payload.timeType = 1\n\nreturn msg;\n", |
|
"outputs": 1, |
|
"noerr": 0, |
|
"initialize": "", |
|
"finalize": "", |
|
"libs": [], |
|
"x": 350, |
|
"y": 300, |
|
"wires": [ |
|
[ |
|
"234d749502406d34" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "234d749502406d34", |
|
"type": "http request", |
|
"z": "753058b1a55fbfa2", |
|
"name": "device historical", |
|
"method": "use", |
|
"ret": "obj", |
|
"paytoqs": "body", |
|
"url": "https://{{location}}/device/{{version}}/historical", |
|
"tls": "", |
|
"persist": false, |
|
"proxy": "", |
|
"insecureHTTPParser": false, |
|
"authType": "", |
|
"senderr": false, |
|
"headers": [], |
|
"x": 640, |
|
"y": 300, |
|
"wires": [ |
|
[] |
|
] |
|
}, |
|
{ |
|
"id": "90b0f3605d7f5e5a", |
|
"type": "inject", |
|
"z": "753058b1a55fbfa2", |
|
"name": "set request data", |
|
"props": [ |
|
{ |
|
"p": "method", |
|
"v": "POST", |
|
"vt": "str" |
|
}, |
|
{ |
|
"p": "headers['content-type']", |
|
"v": "headers.contentType", |
|
"vt": "flow" |
|
}, |
|
{ |
|
"p": "headers.Authorization", |
|
"v": "authorization", |
|
"vt": "flow" |
|
}, |
|
{ |
|
"p": "location", |
|
"v": "location", |
|
"vt": "flow" |
|
}, |
|
{ |
|
"p": "version", |
|
"v": "version", |
|
"vt": "flow" |
|
}, |
|
{ |
|
"p": "payload.deviceId", |
|
"v": "devices[1].deviceId", |
|
"vt": "flow" |
|
}, |
|
{ |
|
"p": "payload.deviceSn", |
|
"v": "devices[1].deviceSn", |
|
"vt": "flow" |
|
} |
|
], |
|
"repeat": "", |
|
"crontab": "", |
|
"once": false, |
|
"onceDelay": 0.1, |
|
"topic": "", |
|
"x": 100, |
|
"y": 300, |
|
"wires": [ |
|
[ |
|
"bbd4c797c1cedbe5", |
|
"133119fc2aef77ea", |
|
"a0294e5a38b7b1b4", |
|
"9acfcfcc077ad513", |
|
"bffc0fd094ec04b5" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "a0294e5a38b7b1b4", |
|
"type": "function", |
|
"z": "753058b1a55fbfa2", |
|
"name": "time type 2", |
|
"func": "msg.payload.endTime = '2024-01-31';\nmsg.payload.startTime = '2024-01-01';\nmsg.payload.timeType = 2\n\nreturn msg;\n", |
|
"outputs": 1, |
|
"noerr": 0, |
|
"initialize": "", |
|
"finalize": "", |
|
"libs": [], |
|
"x": 350, |
|
"y": 340, |
|
"wires": [ |
|
[ |
|
"234d749502406d34" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "bbd4c797c1cedbe5", |
|
"type": "function", |
|
"z": "753058b1a55fbfa2", |
|
"name": "time type 3", |
|
"func": "msg.payload.endTime = '2024-01';\nmsg.payload.startTime = '2023-02';\nmsg.payload.timeType = 3\n\nreturn msg;\n", |
|
"outputs": 1, |
|
"noerr": 0, |
|
"initialize": "", |
|
"finalize": "", |
|
"libs": [], |
|
"x": 350, |
|
"y": 380, |
|
"wires": [ |
|
[ |
|
"234d749502406d34" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "9acfcfcc077ad513", |
|
"type": "function", |
|
"z": "753058b1a55fbfa2", |
|
"name": "time type 4", |
|
"func": "msg.payload.endTime = '2024';\nmsg.payload.startTime = '2000';\nmsg.payload.timeType = 4\n\nreturn msg;\n", |
|
"outputs": 1, |
|
"noerr": 0, |
|
"initialize": "", |
|
"finalize": "", |
|
"libs": [], |
|
"x": 350, |
|
"y": 420, |
|
"wires": [ |
|
[ |
|
"234d749502406d34" |
|
] |
|
] |
|
}, |
|
{ |
|
"id": "bffc0fd094ec04b5", |
|
"type": "http request", |
|
"z": "753058b1a55fbfa2", |
|
"name": "device currentData", |
|
"method": "use", |
|
"ret": "obj", |
|
"paytoqs": "body", |
|
"url": "https://{{location}}/device/{{version}}/currentData", |
|
"tls": "", |
|
"persist": false, |
|
"proxy": "", |
|
"insecureHTTPParser": false, |
|
"authType": "", |
|
"senderr": false, |
|
"headers": [], |
|
"x": 650, |
|
"y": 340, |
|
"wires": [ |
|
[] |
|
] |
|
} |
|
] |
Hello @durable-developer
I copied the flow into my Node-Red Docker on Pi application and entered the required details.
1st thing to notice is about the PW: this must not be entered in clear text but SHA256 hashed, then the API communcation worked for me.
Now I am struggling about another limitation: I've added some add. debug nodes to the flow in order to check the structure of the API output data, but the debug window is automatically wiped after around 10-15s which is far to less to go through all the data.
Google tells me that the auto wiping is probably due to limited cache memory on the instance that runs Node-Red, is there any chance to preserve the debug output ?
I was also trying to utilize the "write file" node, but this didnt work for, no file was generated.
Thanks for your support.