|
[ |
|
{ |
|
"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": [ |
|
[] |
|
] |
|
} |
|
] |
@killamilla0815
Thank you for using the flow and contributing!
Indeed the password should be SHA256 encrypted. I am not sure how it was working for me before. I added this requirement to the instructions. Great feedback!
This sounds like a Node-RED issue/limitation. I am not running Node-RED within a docker and debugging has never been a problem for me. Not sure what the solution would be. It might also limit Node-RED nodes.
But I have several functions to format the SolarMAN response into chart data. I can share some to help you. What data specifically are you trying to get from which response?
Also, the SolarMAN API documentation of course has an example response for each request, maybe that can help.