Read Aiways U5 State of Charge

The Aiways U5 is a battery electric vehicle (BEV) produced in China and sold in several European countries.

This guide shows how to read the battery charge state (SOC, State of Charge) and other car status data of the U5 into Home Assistant entities. The data is fetched from the unofficial API that is used by the Aiways mobile app. The whole logic is created in Node-RED under Home Assistant.

Disclaimer

Preconditions

  • You must be able to read your car’s data in the Aiways mobile app.
    This requires the U5 software to be updated to version 1.7.0 or higher and the corresponding hardware update must be installed in the car.
  • Add-on Node-RED installed in Home Assistant.

Steps

  • The following Node-RED flows need the capability to do MD5 encoding. This can be done with the JS Crypto library, which is already part of Node.js (the server layer under Node-RED). But it must first be imported so you can really use it in function nodes:

    Edit /config/node-red/settings.js,
    locate the property functionGlobalContext and
    insert an additional line to load the crypto lib:

      functionGlobalContext: {
          crypto:require("crypto")
      },
    

    You can use the HA file editor for this step.
    When done restart Node-RED (HA → Settings → Add-Ons → Node-RED → Restart)

  • Edit /config/secrets.yaml and add your Aiways app account credentials and vehicle identification number like this:

    aiways_user:  YOUR_APP_USER_NAME
    aiways_pwd :  YOUR_APP_PASSWORD
    aiways_vin :  YOUR_CAR_VIN
    
  • Now import this flow into Node-RED:

    [{"id":"24ebb2e2.2f6ffe","type":"file in","z":"9d7cd8ae.f2fe48","name":"Read secrets.yaml","filename":"/config/secrets.yaml","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","x":650,"y":120,"wires":[["2c59ff99.2affc"]]},{"id":"2c59ff99.2affc","type":"yaml","z":"9d7cd8ae.f2fe48","property":"payload","name":"Parse yaml","x":850,"y":120,"wires":[["9e7c7d2d.fdeb8","3fa027e1321af0da"]]},{"id":"9e7c7d2d.fdeb8","type":"function","z":"9d7cd8ae.f2fe48","name":"Set global config vars","func":"global.set(\"ha_secrets\", msg.payload);\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1060,"y":120,"wires":[[]]},{"id":"563db3d3.d3e3ac","type":"server-events","z":"9d7cd8ae.f2fe48","name":"Run on HA startup","server":"bde4b68e.528848","version":1,"event_type":"home_assistant_client","exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"waitForRunning":true,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"$outputData(\"eventData\").event_type","valueType":"jsonata"},{"property":"event_type","propertyType":"msg","value":"$outputData(\"eventData\").event_type","valueType":"jsonata"}],"x":170,"y":120,"wires":[["6a8306b8e732392c"]]},{"id":"3a583032.2662b","type":"comment","z":"9d7cd8ae.f2fe48","name":"Set global config var with secrets.yaml entries...","info":"Usage example in functions:\n    let fritzbox_pwd = global.get(\"ha_secrets\").fritzbox_pwd\n","x":220,"y":60,"wires":[]},{"id":"2cccdc63.dbb784","type":"inject","z":"9d7cd8ae.f2fe48","name":"Trigger now","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":450,"y":160,"wires":[["24ebb2e2.2f6ffe"]]},{"id":"3fa027e1321af0da","type":"debug","z":"9d7cd8ae.f2fe48","name":"debug","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1010,"y":160,"wires":[]},{"id":"6a8306b8e732392c","type":"switch","z":"9d7cd8ae.f2fe48","name":"payload == \"running\" ?","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"running","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":410,"y":120,"wires":[["24ebb2e2.2f6ffe"]]},{"id":"bde4b68e.528848","type":"server","name":"Home Assistant","version":2,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":false,"cacheJson":true,"heartbeat":false,"heartbeatInterval":30}]
    

    This flow will read the HA secrets.yaml file into a global Node-RED variable, so you can use your secrets in Node-RED too.
    Hit the “Trigger now” inject button once to make this happen. In the future this flow will automatically be run whenever HA is startet. So you only need to hit this button once.

  • Import the second flow which does all the heavy lifting of polling the API to get your car’s status data into HA:

    [{"id":"e5afc16c4577b23c","type":"inject","z":"c6ce30da03615610","name":"15 min","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"900","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":140,"y":4060,"wires":[["11644ec37221ea4b"]]},{"id":"213e47e34e291c5e","type":"comment","z":"c6ce30da03615610","name":"Lese Aiways-API","info":"","x":100,"y":4000,"wires":[]},{"id":"64c90bbe16dd829a","type":"function","z":"c6ce30da03615610","name":"Prep first request:  POST Login","func":"// Based on: OpenWB-Module Aiways SOC:\n// https://github.com/snaptec/openWB/blob/9a955f00d4c84f038859b797002bc49cea1081b9/modules/soc_aiways/aiways_get_soc.py\n\n\n/*\n    ############################################################# \n    # Request1: aiways - passport - service / passport / login / password #\n    # Login with accountname and password                       #\n    # Also here we get the value for \"token\"                    #\n    # This value is changing for each session                   #\n    #############################################################\n*/\n\nlet PATH = \"aiways-passport-service/passport/login/password\"\n\nlet headers = {\n    \"apptimezone\": msg.config.apptimezone,\n    \"apptimezoneid\": msg.config.apptimezoneid,\n    \"content-type\": \"application/json; charset=utf-8\",\n    //\"accept-encoding\": \"gzip\",\n    \"user-agent\": msg.config.user_agent\n}\n\n//encoded = password.encode()\n//passwordmd5 = hashlib.md5(encoded)\n\nlet LOGIN_PAYLOAD = { \n    \"account\": msg.config.account, \n    \"password\": msg.config.passwordmd5 \n}\n\n\n// Eingangsdaten\n//resp = requests.post(CS_URL + PATH, headers = headers, data = json.dumps(LOGIN_PAYLOAD))\nmsg.url = msg.config.CS_URL + PATH;\nmsg.method= \"POST\";\nmsg.headers= headers;\n//msg.cookies= \"\";\nmsg.payload = JSON.stringify(LOGIN_PAYLOAD)\n\nreturn msg;\n\n/*\ndata = resp.json()[\"data\"]\ntoken = data[\"token\"]\nuserId = data[\"userId\"]\n*/","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":570,"y":4060,"wires":[["80afdb92a51804d2","dbc0484b646aed93"]]},{"id":"80afdb92a51804d2","type":"http request","z":"c6ce30da03615610","name":"","method":"use","ret":"obj","paytoqs":"ignore","url":"","tls":"7b79ba19.4d8194","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":850,"y":4060,"wires":[["7d5aa53b56dfbf3c","446a56759e541749"]]},{"id":"7d5aa53b56dfbf3c","type":"debug","z":"c6ce30da03615610","name":"debug 2","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1040,"y":4060,"wires":[]},{"id":"dbc0484b646aed93","type":"debug","z":"c6ce30da03615610","name":"debug 1","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":840,"y":4020,"wires":[]},{"id":"11644ec37221ea4b","type":"function","z":"c6ce30da03615610","name":"Prep msg.config","func":"\n/* \n* IMPORTANT:\n* The NPM package \"crypto\" is already part of Node.js \n* but it must be activated for Node RED in /config/node-red/settings.js:\n*    functionGlobalContext: {\n*        crypto:require(\"crypto\")\n*    },\n*/\nlet crypto = global.get(\"crypto\");\n\n// Date().toString() = i.e. 'Mon Sep 26 2022 16:51:05 GMT+0200 (Mitteleuropäische Sommerzeit)'\n// timeZoneParts = i.e. [ \"GMT+0200, \"GMT+02\", \"00\" ]\nlet timeZoneParts = Date().toString().match(/(GMT[\\+\\-]\\d\\d)(\\d\\d)/);\n\nmsg.config = {\n    account: global.get(\"ha_secrets\").aiways_user || \"\",\n    passwordmd5: crypto.createHash('md5').update(global.get(\"ha_secrets\").aiways_pwd || \"\").digest('hex'),\n    vin: global.get(\"ha_secrets\").aiways_vin || \"\",\n\n    // apptimezone = i.e.: \"GMT+02:00\"\n    apptimezone: `${timeZoneParts[1]}:${timeZoneParts[2]}`,\n    // apptimezoneid = i.e.: \"Europe/Berlin\"\n    apptimezoneid: Intl.DateTimeFormat().resolvedOptions().timeZone,\n\n    user_agent: \"okhttp/4.3.1\",\n\n    CS_URL: \"https://coiapp-api-eu.ai-ways.com:10443/\"\n}\n\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":320,"y":4060,"wires":[["64c90bbe16dd829a"]]},{"id":"9f5c32232cf662a0","type":"function","z":"c6ce30da03615610","name":"Prep second request:  POST Get Data","func":"// Based on: OpenWB-Module Aiways SOC:\n// https://github.com/snaptec/openWB/blob/9a955f00d4c84f038859b797002bc49cea1081b9/modules/soc_aiways/aiways_get_soc.py\n\n\n// data = resp.json()[\"data\"]\n// token = data[\"token\"]\n// userId = data[\"userId\"]\nlet data = msg.payload.data;\nmsg.config.token = data.token;\nmsg.config.userId = data.userId;\nmsg.config.userEmail = data.email;\nmsg.config.userType = data.userType;\n\n\n/*\n    #########################################################################\n    # Request2 \"app/vc/getCondition\"                                        #\n    # Get the current Condition of the car                                  #\n    # The data are located in data / vc                                       #\n    # \"soc\" contains the value for the current State of Charge)             #\n    #########################################################################\n*/\n\nlet PATH = \"app/vc/getCondition\"\n\nlet headers = {\n    \"token\": msg.config.token,\n    \"apptimezone\": msg.config.apptimezone,\n    \"apptimezoneid\": msg.config.apptimezoneid,\n    \"content-type\": \"application/json; charset=utf-8\",\n    //\"accept-encoding\": \"gzip\",\n    \"user-agent\": msg.config.user_agent\n}\n\n//PAYLOAD = {'userId': userId,'vin': vin}\nlet PAYLOAD = { \n    \"userId\": msg.config.userId, \n    \"vin\": msg.config.vin\n}\n\n//resp = requests.post(CS_URL + PATH, headers = headers, data = json.dumps(PAYLOAD))\nmsg.url = msg.config.CS_URL + PATH;\nmsg.method= \"POST\";\nmsg.headers= headers;\n//msg.cookies= \"\";\nmsg.payload = JSON.stringify(PAYLOAD)\n\nreturn msg;\n\n/*\ndata = resp.json()[\"data\"]\nvc = data[\"vc\"]\nsoc = vc[\"soc\"]\nchargeSts = vc[\"chargeSts\"]\n*/\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":590,"y":4120,"wires":[["a21da7070dea1596"]]},{"id":"446a56759e541749","type":"switch","z":"c6ce30da03615610","name":"HTTP 200 ?","property":"statusCode","propertyType":"msg","rules":[{"t":"eq","v":"200","vt":"num"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":330,"y":4120,"wires":[["9f5c32232cf662a0"],[]]},{"id":"d512972e991404f7","type":"debug","z":"c6ce30da03615610","name":"debug 3","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1040,"y":4120,"wires":[]},{"id":"de66356dc0887ec6","type":"switch","z":"c6ce30da03615610","name":"HTTP 200 ?","property":"statusCode","propertyType":"msg","rules":[{"t":"eq","v":"200","vt":"num"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":330,"y":4180,"wires":[["093bdd3374adf214"],[]]},{"id":"a21da7070dea1596","type":"http request","z":"c6ce30da03615610","name":"","method":"use","ret":"obj","paytoqs":"ignore","url":"","tls":"7b79ba19.4d8194","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":850,"y":4120,"wires":[["d512972e991404f7","de66356dc0887ec6"]]},{"id":"093bdd3374adf214","type":"function","z":"c6ce30da03615610","name":"Prep third request:  GET Logout","func":"// Based on: OpenWB-Module Aiways SOC:\n// https://github.com/snaptec/openWB/blob/9a955f00d4c84f038859b797002bc49cea1081b9/modules/soc_aiways/aiways_get_soc.py\n\n\n// data = resp.json()[\"data\"]\n// vc = data[\"vc\"]\n// soc = vc[\"soc\"]\n// chargeSts = vc[\"chargeSts\"]\nlet data = msg.payload.data;\nmsg.cardata = data.vc;\n\n\n/*\n    #########################################################################\n    # Request3 \"aiways-passport-service/passport/logout\"                    #\n    # Makes a logout                                                        #\n    #########################################################################\n*/\n\nlet PATH = \"aiways-passport-service/passport/logout\"\n\nlet headers = {\n    \"token\": msg.config.token,\n    \"apptimezone\": msg.config.apptimezone,\n    \"apptimezoneid\": msg.config.apptimezoneid,\n    //\"accept-encoding\": \"gzip\",\n    \"user-agent\": msg.config.user_agent\n}\n\n//resp = requests.get(CS_URL + PATH, headers = headers)\nmsg.url = msg.config.CS_URL + PATH;\nmsg.method= \"GET\";\nmsg.headers= headers;\n//msg.cookies= \"\";\nmsg.payload = \"\";\n\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":570,"y":4180,"wires":[["83567f6fd0f4c7ae"]]},{"id":"c57cbffde6889c06","type":"debug","z":"c6ce30da03615610","name":"debug 4","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1040,"y":4180,"wires":[]},{"id":"83567f6fd0f4c7ae","type":"http request","z":"c6ce30da03615610","name":"","method":"use","ret":"obj","paytoqs":"ignore","url":"","tls":"7b79ba19.4d8194","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":850,"y":4180,"wires":[["c57cbffde6889c06","7533790f9646c24f"]]},{"id":"7533790f9646c24f","type":"switch","z":"c6ce30da03615610","name":"HTTP 200 ?","property":"statusCode","propertyType":"msg","rules":[{"t":"eq","v":"200","vt":"num"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":330,"y":4240,"wires":[["f71413d712d057df"],[]]},{"id":"3f65a91212b7c412","type":"ha-entity","z":"c6ce30da03615610","name":"car_state_of_charge","server":"cb38d2a3.10198","version":2,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"car_state_of_charge"},{"property":"device_class","value":"battery"},{"property":"icon","value":"mdi:ev-station"},{"property":"unit_of_measurement","value":"%"},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"state":"cardata.soc","stateType":"msg","attributes":[],"resend":true,"outputLocation":"payload","outputLocationType":"none","inputOverride":"allow","outputOnStateChange":false,"outputPayload":"$entity().state ? \"on\": \"off\"","outputPayloadType":"jsonata","x":600,"y":4240,"wires":[[]]},{"id":"b28c9b9f47bc2085","type":"ha-entity","z":"c6ce30da03615610","name":"car_charge_status","server":"cb38d2a3.10198","version":2,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"car_charge_status"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:ev-station"},{"property":"unit_of_measurement","value":""},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"state":"cardata.chargeSts","stateType":"msg","attributes":[],"resend":true,"outputLocation":"payload","outputLocationType":"none","inputOverride":"allow","outputOnStateChange":false,"outputPayload":"$entity().state ? \"on\": \"off\"","outputPayloadType":"jsonata","x":590,"y":4300,"wires":[[]]},{"id":"f71413d712d057df","type":"junction","z":"c6ce30da03615610","x":460,"y":4240,"wires":[["b28c9b9f47bc2085","3f65a91212b7c412"]]},{"id":"7b79ba19.4d8194","type":"tls-config","name":"Ignore Invalid Cert","cert":"","key":"","ca":"","certname":"","keyname":"","caname":"","servername":"","verifyservercert":false},{"id":"cb38d2a3.10198","type":"server","name":"Home Assistant","version":2,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":"30"}]
    

    This flow will read the current status every 15 minutes.
    You can hit the “15 min” inject button at any time to force an API poll for testing. Check the debug window to analyze any problems. Activate the debug nodes for more info.

    Currently the flow exposes only sensor.state_of_charge (= battery level) and sensor.car_charge_status as HA entities. But there is much more to exploit. Just activate the last debug node, poll the API and check the debug output pane for all the data that the API returns.

Enjoy!

thanks *

but its not working for me
i get a

code: 401

message: “Invalid login status, please log in again”
no matter what i try.
i can log in to the app with no problems.
so its not a credentials problem

do you have any idea how to get i to work ?

Yes you are right.
Aiways has changed the API just days ago.
My solution as well as the OpenWB module it is based on have stopped working.
If a new solution is found I will post it here.

2 Likes

Have you found the new authentication endpoint? I am getting the same error “Invalid login status, please log in again”
Thank you.

Unfortunately there isn’t an easy way.
Here is, what worked for me. But it is not for the faint hearted:

  • Use PCAPdroid on Android to capture the communication of the Aiways app.
    This helper app does NOT require root access.
  • Activate TLS-Decryption in PCAPdroid and follow the wizard to generate a certificate and install it in Android. The guide can help you to test the decryption.
  • Choose HTTP-Server as traffic dump and the Aiways app as the target app.
    Start the dump with the play icon.
  • Open the Aiways app and navigate to the car data.
  • Back in PCAPdroid stop the dump and check the registered traffic. There should be a bunch of requests. Most of them contain the header data that you are interested in:
    • token
    • registerid
    • deviceid
  • These three can possible expire at any time (though they were stable for me for quite some time now. If they expire you have to capture them again for an update.
  • Use the Node RED flow to run your request.
    You MUST edit the node “Prep msg.config” and add your userid, vin, token, registerid, deviceid.
  • If all goes well, the result of the flow is the car data stored in msg.cardata at the output of the last node.

[{"id":"e5afc16c4577b23c","type":"inject","z":"c6ce30da03615610","name":"15 min","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"900","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":140,"y":4380,"wires":[["11644ec37221ea4b","de4928d8bfc625c1","bc00432297bace86"]]},{"id":"bc00432297bace86","type":"function","z":"c6ce30da03615610","name":"Prep msg.config","func":"\n/* \n* IMPORTANT:\n* The NPM package \"crypto\" is already part of Node.js \n* but it must be activated for Node RED in /config/node-red/settings.js:\n*    functionGlobalContext: {\n*        crypto:require(\"crypto\")\n*    },\n*/\nlet crypto = global.get(\"crypto\");\n\n// Date().toString() = i.e. 'Mon Sep 26 2022 16:51:05 GMT+0200 (Mitteleuropäische Sommerzeit)'\n// timeZoneParts = i.e. [ \"GMT+0200, \"GMT+02\", \"00\" ]\nlet timeZoneParts = Date().toString().match(/(GMT[\\+\\-]\\d\\d)(\\d\\d)/);\n\nmsg.config = {\n    userid: global.get(\"ha_secrets\").aiways_userid || \"\",\n    vin: global.get(\"ha_secrets\").aiways_vin || \"\",\n    // ALT:\n    // passwordmd5: crypto.createHash('md5').update(global.get(\"ha_secrets\").aiways_pwd || \"\").digest('hex'),\n    \n    // TEMPORÄRER HACK: Aus App-Request per PCAPdroid ermittelt\n    token: global.get(\"ha_secrets\").aiways_token || \"\",\n    registerid: global.get(\"ha_secrets\").aiways_registerid || \"\",\n    deviceid: global.get(\"ha_secrets\").aiways_deviceid || \"\",\n\n    language: \"de\",\n    version: \"1.3.0\",\n    platform: \"android\",\n    user_agent: \"okhttp/4.3.1\",\n\n    // apptimezone = i.e.: \"GMT+02:00\"\n    apptimezone: `${timeZoneParts[1]}:${timeZoneParts[2]}`,\n    // apptimezoneid = i.e.: \"Europe/Berlin\"\n    apptimezoneid: Intl.DateTimeFormat().resolvedOptions().timeZone,\n\n    contentType: \"application/json; charset=utf-8\",\n    acceptEncoding: \"gzip\",\n    CS_URL: \"https://coiapp-api-eu.ai-ways.com:10443/\",\n}\n\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":320,"y":4380,"wires":[["36ad1f6c6a1dd148","1fbeeb7a032e8871"]]},{"id":"36ad1f6c6a1dd148","type":"function","z":"c6ce30da03615610","name":"Prep second request:  POST Get Data","func":"// Based on: OpenWB-Module Aiways SOC:\n// https://github.com/snaptec/openWB/blob/bcb16dcb2902ca6ce21cd1036933a712d73bd44c/modules/soc_aiways/aiways_get_soc.py\n\n\n/*\n    #########################################################################\n    # Request2 \"app/vc/getCondition\"                                        #\n    # Get the current Condition of the car                                  #\n    # The data are located in data / vc                                       #\n    # \"soc\" contains the value for the current State of Charge)             #\n    #########################################################################\n*/\n\nlet PATH = \"app/vc/getCondition\"\n\nlet oHeaders = {\n    \"language\": msg.config.language,\n    \"token\": msg.config.token,\n    \"registerid\": msg.config.registerid,\n    \"deviceid\": msg.config.deviceid,\n    \"version\": msg.config.version,\n    \"platform\": msg.config.platform,\n    \"apptimezone\": msg.config.apptimezone,\n    \"apptimezoneid\": msg.config.apptimezoneid,\n    \"content-type\": msg.config.contentType,\n    \"accept-encoding\": msg.config.acceptEncoding,\n    \"user-agent\": msg.config.user_agent,\n}\n\n//PAYLOAD = {'userId': userId,'vin': vin}\nlet PAYLOAD = { \n    \"userId\": msg.config.userid, \n    \"vin\": msg.config.vin\n}\n\n//resp = requests.post(CS_URL + PATH, headers = headers, data = json.dumps(PAYLOAD))\nmsg.url = msg.config.CS_URL + PATH;\nmsg.method= \"POST\";\nmsg.headers = oHeaders;\n//msg.cookies= \"\";\nmsg.payload = JSON.stringify(PAYLOAD)\n\nreturn msg;\n\n/*\ndata = resp.json()[\"data\"]\nvc = data[\"vc\"]\nsoc = vc[\"soc\"]\nchargeSts = vc[\"chargeSts\"]\n*/\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":590,"y":4380,"wires":[["7384c89403b9de48","f54cd7fcb6559682"]]},{"id":"4d685491d9e3a5a1","type":"debug","z":"c6ce30da03615610","name":"debug 10","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1040,"y":4380,"wires":[]},{"id":"1b0e67c3467ab9d8","type":"switch","z":"c6ce30da03615610","name":"HTTP 200 ?","property":"statusCode","propertyType":"msg","rules":[{"t":"eq","v":"200","vt":"num"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":330,"y":4440,"wires":[["a446cc15c19d34ca"],[]]},{"id":"7384c89403b9de48","type":"http request","z":"c6ce30da03615610","name":"","method":"use","ret":"obj","paytoqs":"ignore","url":"","tls":"7b79ba19.4d8194","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":850,"y":4380,"wires":[["4d685491d9e3a5a1","1b0e67c3467ab9d8"]]},{"id":"1fbeeb7a032e8871","type":"debug","z":"c6ce30da03615610","name":"debug 13","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":500,"y":4340,"wires":[]},{"id":"f54cd7fcb6559682","type":"debug","z":"c6ce30da03615610","name":"debug 14","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":840,"y":4340,"wires":[]},{"id":"7287ba84c0c8172a","type":"change","z":"c6ce30da03615610","name":"","rules":[{"t":"set","p":"cardata","pt":"msg","to":"payload.data.vc","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":770,"y":4440,"wires":[["f71413d712d057df","03a2f2c364f55bac"]]},{"id":"a446cc15c19d34ca","type":"switch","z":"c6ce30da03615610","name":"payload.code == 0 ?","property":"payload.code","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"num"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":540,"y":4440,"wires":[["7287ba84c0c8172a"],[]]},{"id":"03a2f2c364f55bac","type":"debug","z":"c6ce30da03615610","name":"debug 19","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":980,"y":4440,"wires":[]},{"id":"7b79ba19.4d8194","type":"tls-config","name":"Ignore Invalid Cert","cert":"","key":"","ca":"","certname":"","keyname":"","caname":"","servername":"","verifyservercert":false}]

Good luck.

Since the Aiways app unfortunately doesn’t work, we could still use the IOS PUMP app that always works correctly. We could only see some data such as load percentage, total kilometers, if the vehicle is charging, temperature and not much more.

Found anywhere what each attribute means? And what the status number means.
so far just going trial and error and mapping the numbers :stuck_out_tongue:
And thanks for this, works really good.

Nope, no such list. You’ll have to find out.

1 Like

Is PUMP working with Home Assistant and is there an official integration for it ?

not that i have found… but what do you want from pump that you can not get from this?

I don’t have an android only iPhone :unamused:

MAybe use an android emulator to get the credentials? HAve not tried it, but might work

Hi Jpsy
Last days I learned a lot about Node Red- first time I used it.
But now it is working and I can see Aiways-SOC in HA and can send it via mqtt to openwb.
Thanks a lot. :+1:
Btw: I had to add sensor sfor soc and charging state manually - They were not part of the imported node-red flow?
For people that do not use android (like me :wink: ), You also can use mitmproxy to get token, registerid and deviceid.

1 Like