hi there,
I have been experimenting with node red for a while and I love it. My javascript and HTML programming skills however are rudimentary and I am thus asking for your help (or pointers).
I found a python library that allows me to interface with the web API of my EV car charger (wallbox brand).
When I run the python script on my Raspberry Pi (that also hosts my node red installation), I have no problem in locking and unlocking the car charger with the API calls. I now try to recreate that using node red's https request nodes.
With the python library as guide, I was able to get Authentication followed by "reading" values (https get requests) working fine, no problem!
However, I have not managed to "recreate" the python script put request, that e.g. locks or unlocks the car charger.
I somehow can't figure out how to "add" data (the lock / unlock command - data='{"locked":1}') to my put request.
Here is the python library excerpt that shows the put request, e.g. the lockCharger function (I don't have any documentation of the API, only script sample):
Python library
"""
Wallbox class
"""
from requests.auth import HTTPBasicAuth
import requests
import json
class Wallbox:
def __init__(self, username, password):
self.username = username
self.password = password
self.baseUrl = "https://api.wall-box.com/"
self.jwtToken = ""
self.headers = {
"Accept": "application/json",
"Content-Type": "application/json;charset=UTF-8",
}
def authenticate(self):
try:
response = requests.get(
f"{self.baseUrl}auth/token/user",
auth=HTTPBasicAuth(self.username, self.password),
)
response.raise_for_status()
except requests.exceptions.HTTPError as err:
raise (err)
self.jwtToken = json.loads(response.text)["jwt"]
self.headers["Authorization"] = f"Bearer {self.jwtToken}"
def lockCharger(self, chargerId):
try:
response = requests.put(
f"{self.baseUrl}v2/charger/{chargerId}",
headers=self.headers,
data='{"locked":1}',
)
response.raise_for_status()
except requests.exceptions.HTTPError as err:
raise (err)
return json.loads(response.text)
def setMaxChargingCurrent(self, chargerId, newMaxChargingCurrentValue):
try:
response = requests.put(
f"{self.baseUrl}v2/charger/{chargerId}",
headers=self.headers,
data=f'{{ "maxChargingCurrent":{newMaxChargingCurrentValue}}}',
)
response.raise_for_status()
except requests.exceptions.HTTPError as err:
raise (err)
return json.loads(response.text)
As I said, the authentication part, generating the header for the put request works fine. Here is one of the many iterations I have tried:
My sample flow:
with the https request configuration:
And my function:
var payload = msg.payload;
var topic = msg.topic;
var chargerID = global.get('chargerID') || "";
var jwt = global.get('jwt') || "";
var data = {};
var newMsg = {};
// data = {"data": [{"locked": payload}]};
data = {"locked": payload};
// data["data"].push({"chargerData":[{"locked": payload}]});
// data["locked"] = payload;
newMsg.method = "PUT";
newMsg.headers = {'Authorization': "Bearer " + jwt};
//newMsg.payload = data;
newMsg.data = {"locked": payload};
newMsg.url = "https://api.wall-box.com/v2/charger" + "/" + chargerID;
return newMsg;
And the flow:
[
{
"id": "84201fb6.ff6cc",
"type": "function",
"z": "fe4bc38e.d4da3",
"name": "wallbox API",
"func": "var payload = msg.payload;\nvar topic = msg.topic;\n\nvar chargerID = global.get('chargerID') || \"\";\nvar jwt = global.get('jwt') || \"\";\n\nvar data = {};\nvar newMsg = {};\n\n// data = {\"data\": [{\"locked\": payload}]};\ndata = {\"locked\": payload};\n// data[\"data\"].push({\"chargerData\":[{\"locked\": payload}]});\n//data[\"datastreams\"].push({\"id\":\"one\", \"current_value\":\"100.00\"});\n\n// data[\"locked\"] = payload;\n\nnewMsg.method = \"PUT\";\nnewMsg.headers = {'Authorization': \"Bearer \" + jwt};\n//newMsg.payload = data;\nnewMsg.data = {\"locked\": payload};\nnewMsg.url = \"https://api.wall-box.com/v2/charger\" + \"/\" + chargerID;\n\nreturn newMsg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"x": 377.5,
"y": 1095,
"wires": [
[
"def8a5fc.0ca618",
"62eeaa05.e79244",
"58ee2ce.abb36d4"
]
]
},
{
"id": "f5331864.387788",
"type": "inject",
"z": "fe4bc38e.d4da3",
"name": "lock",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "locked",
"payload": "1",
"payloadType": "num",
"x": 179,
"y": 1094,
"wires": [
[
"84201fb6.ff6cc"
]
]
},
{
"id": "8a13cc2d.4d5ae",
"type": "debug",
"z": "fe4bc38e.d4da3",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 811,
"y": 1098,
"wires": []
},
{
"id": "58ee2ce.abb36d4",
"type": "http request",
"z": "fe4bc38e.d4da3",
"name": "Put sample",
"method": "use",
"ret": "obj",
"paytoqs": "ignore",
"url": "",
"tls": "",
"persist": false,
"proxy": "",
"authType": "",
"x": 560,
"y": 1100,
"wires": [
[
"8a13cc2d.4d5ae"
]
]
},
{
"id": "def8a5fc.0ca618",
"type": "debug",
"z": "fe4bc38e.d4da3",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 542,
"y": 1053,
"wires": []
},
{
"id": "9bcdd543.5dab18",
"type": "inject",
"z": "fe4bc38e.d4da3",
"name": "unlock",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "locked",
"payload": "0",
"payloadType": "num",
"x": 179,
"y": 1136,
"wires": [
[
"84201fb6.ff6cc"
]
]
},
{
"id": "62eeaa05.e79244",
"type": "json",
"z": "fe4bc38e.d4da3",
"name": "",
"property": "payload",
"action": "",
"pretty": false,
"x": 507,
"y": 1151,
"wires": [
[
"5318996e.6b3c18"
]
]
},
{
"id": "5318996e.6b3c18",
"type": "debug",
"z": "fe4bc38e.d4da3",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 646,
"y": 1145,
"wires": []
}
]
I have tried adding the "data" to msg.payload, msg.data, msg.payload.data etc. but it just does not seem to work ... in everyone of these instances, I get a statusCode = 200 reply with the complete car charger status information but the locked state does not change ...
What have I missed!?
THANKS