ABRP: abetterrouteplanner.com¶
Send live data to abetterrouteplanner.com
Overview
abetterrouteplanner is probably the best website to plan a route with an EV and optimize the number of stops needed and where to charge your vehicle.
Moreover, it has a wonderful functionality, to update your plan, taking into account your live data, to adjust with the real consumption of the vehicle, by connecting an obd device and soft like EVNotify or Torque Pro.
This plugin sends your live data from the OVMS box.
Author: | David S Arnold |
---|
New in version 1.2: Your own parameters (car model, abrp token but also api-url) are now stored as config parameters, you can consult them using the shell with config list usr
or modify with config set
command.
Installation¶
You can use the embedded website tools/shell and tools/editor of the OVMS box to create the directory and file. This editor will allow you to paste the plugin code from the documentation.
- Files to be created in /store/scripts/:
- ovmsmain.js, if not already exists
- sendlivedata2abrp.js, by copying the file below
Next, configure your car model, API URL & token:
Note
ABRP only supports live data feeds for some car models. You can request a notification when support has been added for your car. Do not feed live data using other car models! Also, ABRP has not yet added this OVMS plugin as a general data source, so you need to disguise as “Torque”.
- If using the ABRP 4 UI:
- Login to abetterrouteplanner
- Open “Settings”, enable detailed setup
- Add your car (if ABRP has no live support for your car model, it will display “Live data not available”)
- Click “Link Torque”, click “Next” 3 times
- Set the “Webserver URL” by
config set usr abrp.url "…"
* Note: according to Iternio, the URLhttp://api.iternio.com/1/tlm/send
should generally be used here instead of the Torque specific one displayed - Set the “User Email Address” (API token) by
config set usr abrp.user_token "…"
- If using ABRP classic UI:
- Login to abetterrouteplanner in classic view
- In Settings/more Settings, there’s an item ‘Live Car Connection’ with 2 buttons: ‘Setup’ and ‘View live data’
- Click on Setup (if there is no Setup button, live data support isn’t available for your car model)
- Click on Torque
- Set the “Webserver URL” by
config set usr abrp.url "…"
- Set the “User Email Address” (API token) by
config set usr abrp.user_token "…"
- Determine your car model code:
- Open API car models list
- To improve readability, optionally paste the page into JSONlint.com
- Search for your car brand and model, the code is the field following the car specification, for example
renault:zoe:20:52:r110
- Set the code by
config set usr abrp.car_model "…"
Finally reboot your OVMS module. This was a one-time configuration.
You’re now ready. Test it with the shell page in the embedded web server using the command script eval abrp.info()
and then with the command script eval abrp.onetime()
. You can also do it with the mobile app.
Script code¶
This is a javascript code, to extract in the file sendlivedata2abrp.js.
Warning
note the minimum firmware version: 3.2.008-147
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 | /** * /store/scripts/sendlivedata2abrp.js * * Module plugin: * Send live data to a better route planner * This version uses the embedded GSM of OVMS, so there's an impact on data consumption * /!\ requires OVMS firmware version 3.2.008-147 minimum (for HTTP call) * * Version 1.3 2020 inf0mike (forum https://www.openvehicles.com) * * Enable: * - install at above path * - add to /store/scripts/ovmsmain.js: * abrp = require("sendlivedata2abrp"); * - script reload * * Usage: * - script eval abrp.info() => to display vehicle data to be sent to abrp * - script eval abrp.onetime() => to launch one time the request to abrp server * - script eval abrp.send(1) => toggle send data to abrp * - (0) => stop sending data * - script eval abrp.resetConfig() => reset configuration to defaults * * Version 1.3 updates: * - Fix for rounding of fractional SOC causing abrp to report SOC off by 1 * - Fix for altitude never being sent * - New convenience method to reset config to defaults * * Version 1.2 updates: * - based now on OVMS configuration to store user token, car model and url * - review messages sent during charge * - send a message when vehicle is on before moving to update abrp * * Version 1.1 fix and update: * - fixed the utc refreshing issue * - send notifications * - send live data only if necessary **/ /* * Declarations: * CAR_MODEL: find your car model here: https://api.iternio.com/1/tlm/get_carmodels_list?api_key=32b2162f-9599-4647-8139-66e9f9528370 * OVMS_API_KEY : API_KEY to access to ABRP API, given by the developer * MY_TOKEN : Your token (corresponding to your abrp profile) * TIMER_INTERVAL : to subscribe to a ticker event * URL : url to send telemetry to abrp following: https://iternio.com/index.php/iternio-telemetry-api/ * CR : Carriage Return for console prints * * objTLM : JSON object containing data read * objTimer : timer object */ const CAR_MODEL = "@@:@@:@@:@@:@@"; const OVMS_API_KEY = "32b2162f-9599-4647-8139-66e9f9528370"; const MY_TOKEN = "@@@@@@@@-@@@@-@@@@-@@@@-@@@@@@@@@@@@"; const TIMER_INTERVAL = "ticker.60"; // every minute const EVENT_MOTORS_ON = "vehicle.on"; const URL = "http://api.iternio.com/1/tlm/send"; const DEFAULT_CFG = { "url": URL, "user_token": MY_TOKEN, "car_model": CAR_MODEL }; const CR = '\n'; var objTLM; var objTimer, objEvent; var sHasChanged = ""; var bMotorsOn = false; // initialise from default var abrp_cfg = JSON.parse(JSON.stringify(DEFAULT_CFG)); // check if json object is empty function isJsonEmpty(obj) { for(var key in obj) { if(obj.hasOwnProperty(key)) return false; } return true; } // Read & process config: function readConfig() { // check if config exist var read_cfg = OvmsConfig.GetValues("usr", "abrp."); print(JSON.stringify(read_cfg) + CR); if (isJsonEmpty(read_cfg) == true) { // no config yet, set the default values OvmsConfig.SetValues("usr","abrp.",abrp_cfg); } else { // config existing abrp_cfg.url = read_cfg.url; abrp_cfg.user_token = read_cfg.user_token; abrp_cfg.car_model = read_cfg.car_model; } } // Make json telemetry object function InitTelemetryObj() { return { "utc": 0, "soc": 0, "soh": 0, "speed": 0, "car_model": abrp_cfg.car_model, "lat": 0, "lon": 0, "alt": 0, "ext_temp": 0, "is_charging": 0, "batt_temp": 0, "voltage": 0, "current": 0, "power": 0 }; } // Fill json telemetry object function UpdateTelemetryObj(myJSON) { if(!myJSON){ // if the data object is undefined or null then return early return false; } var read_num = 0; var read_str = ""; var read_bool = false; sHasChanged = ""; if (bMotorsOn) { sHasChanged = "_MOTORS-ON"; bMotorsOn = false; } // using Math.floor avoids rounding up of .5 values to next whole number // as some vehicles report fractional values. Abrp seems to only support integer values read_num = Math.floor(Number(OvmsMetrics.Value("v.b.soc"))); if (myJSON.soc != read_num) { myJSON.soc = read_num; sHasChanged += "_SOC:" + myJSON.soc + "%"; } read_num = Number(OvmsMetrics.Value("v.b.soh")); if (myJSON.soh != read_num) { myJSON.soh = read_num; sHasChanged += "_SOH:" + myJSON.soh + "%"; } if ( (myJSON.soh + myJSON.soc) == 0 ) { // Sometimes the canbus is not readable, and abrp doesn't like 0 values print("canbus not readable: reset module and then put motors on" + CR); return false; } //myJSON.lat = OvmsMetrics.AsFloat("v.p.latitude").toFixed(3); //above code line works, except when value is undefined, after reboot read_num = OvmsMetrics.AsFloat("v.p.latitude"); read_num = read_num.toFixed(3); if (myJSON.lat != read_num) { myJSON.lat = read_num; sHasChanged += "_LAT:" + myJSON.lat + "°"; } read_num = Number(OvmsMetrics.AsFloat("v.p.longitude")); read_num = read_num.toFixed(3); if (myJSON.lon != read_num) { myJSON.lon = read_num; sHasChanged += "_LON:" + myJSON.lon + "°"; } read_num = Number(OvmsMetrics.AsFloat("v.p.altitude")); read_num = read_num.toFixed(1); if (read_num <= (myJSON.alt - 2) || read_num >= (myJSON.alt + 2)) { myJSON.alt = read_num; sHasChanged += "_ALT:" + myJSON.alt + "m"; } read_num = Number(OvmsMetrics.Value("v.b.power")); myJSON.power = read_num.toFixed(1); myJSON.speed=Number(OvmsMetrics.Value("v.p.speed")); myJSON.batt_temp=Number(OvmsMetrics.Value("v.b.temp")); myJSON.ext_temp=Number(OvmsMetrics.Value("v.e.temp")); myJSON.voltage=Number(OvmsMetrics.Value("v.b.voltage")); myJSON.current=Number(OvmsMetrics.Value("v.b.current")); myJSON.utc = Math.trunc(Date.now()/1000); //myJSON.utc = OvmsMetrics.Value("m.time.utc"); // read_bool = Boolean(OvmsMetrics.Value("v.c.charging")); // v.c.charging is also on when regen => not wanted here read_str = OvmsMetrics.Value("v.c.state"); if ( (read_str == "charging") || (read_str == "topoff") ) { myJSON.is_charging = 1; read_str = OvmsMetrics.Value("v.c.mode"); if (sHasChanged != "") { sHasChanged += "_CHRG:" + read_str + "(" + OvmsMetrics.Value("v.c.charging") + ")"; print("Charging in mode " + read_str + CR); } } else { myJSON.is_charging = 0; } myJSON.car_model = abrp_cfg.car_model; return (sHasChanged !== ""); } // Show available vehicle data function DisplayLiveData(myJSON) { var newcontent = ""; newcontent += "altitude = " + myJSON.alt + "m" + CR; //GPS altitude newcontent += "latitude = " + myJSON.lat + "°" + CR; //GPS latitude newcontent += "longitude= " + myJSON.lon + "°" + CR; //GPS longitude newcontent += "ext temp = " + myJSON.ext_temp + "°C" + CR; //Ambient temperature newcontent += "charge = " + myJSON.soc + "%" + CR; //State of charge newcontent += "health = " + myJSON.soh + "%" + CR; //State of health newcontent += "bat temp = " + myJSON.batt_temp + "°C" + CR; //Main battery momentary temperature newcontent += "voltage = " + myJSON.voltage + "V" + CR; //Main battery momentary voltage newcontent += "current = " + myJSON.current + "A" + CR; //Main battery momentary current newcontent += "power = " + myJSON.power + "kW" + CR; //Main battery momentary power newcontent += "charging = " + myJSON.is_charging + CR; //yes = currently charging print(newcontent); } function InitTelemetry() { objTLM = InitTelemetryObj(); sHasChanged = ""; } function UpdateTelemetry() { var bChanged = UpdateTelemetryObj(objTLM); if (bChanged) { DisplayLiveData(objTLM); } return bChanged; } function CloseTelemetry() { objTLM = null; sHasChanged = ""; } // http request callback if successful function OnRequestDone(resp) { print("response="+JSON.stringify(resp)+CR); //OvmsNotify.Raise("info", "usr.abrp.status", "ABRP::" + sHasChanged); } // http request callback if failed function OnRequestFail(error) { print("error="+JSON.stringify(error)+CR); OvmsNotify.Raise("info", "usr.abrp.status", "ABRP::" + JSON.stringify(error)); } // Return full url with JSON telemetry object function GetUrlABRP() { var urljson = abrp_cfg.url; urljson += "?"; urljson += "api_key=" + OVMS_API_KEY; urljson += "&"; urljson += "token=" + abrp_cfg.user_token; urljson += "&"; urljson += "tlm=" + encodeURIComponent(JSON.stringify(objTLM)); print(urljson + CR); return urljson; } // Return config object for HTTP request function GetURLcfg() { var cfg = { url: GetUrlABRP(), done: function(resp) {OnRequestDone(resp)}, fail: function(err) {OnRequestFail(err)} }; return cfg; } function SendLiveData() { if (UpdateTelemetry()) { HTTP.Request( GetURLcfg() ); } } function Reactivate_MotorsOn() { bMotorsOn = true; SendLiveData(); } function InitTimer() { objTimer = PubSub.subscribe(TIMER_INTERVAL, SendLiveData); objEvent = PubSub.subscribe(EVENT_MOTORS_ON, SendLiveData); } function CloseTimer() { PubSub.unsubscribe(objEvent); PubSub.unsubscribe(objTimer); objEvent = null; objTimer = null; } // API method abrp.onetime(): // Read and send data, but only once, no timer launched exports.onetime = function() { readConfig(); InitTelemetry(); SendLiveData(); CloseTelemetry(); } // API method abrp.info(): // Do not send any data, just read vehicle data and writes in the console exports.info = function() { readConfig(); InitTelemetry(); UpdateTelemetry(); CloseTelemetry(); } // API method abrp.resetConfig() // Resets stored config to default exports.resetConfig = function() { OvmsConfig.SetValues("usr","abrp.", DEFAULT_CFG); print(JSON.stringify(abrp_cfg)); OvmsNotify.Raise("info", "usr.abrp.status", "ABRP::config changed"); } // API method abrp.send(): // Checks every minut if important data has changed, and send it exports.send = function(onoff) { if (onoff) { readConfig(); if (objTimer != null) { print("Already running !" + CR); return; } print("Start sending data..." + CR); InitTelemetry(); SendLiveData(); InitTimer(); OvmsNotify.Raise("info", "usr.abrp.status", "ABRP::started"); } else { if (objTimer == null) { print("Already stopped !" + CR); return; } print("Stop sending data" + CR); CloseTimer(); CloseTelemetry(); OvmsNotify.Raise("info", "usr.abrp.status", "ABRP::stopped"); } } |
Usage¶
- How to make it run:
- install as described in ‘Installation’
- add to /store/scripts/ovmsmain.js:
abrp = require("sendlivedata2abrp");
- script reload
- With command lines in the OVMS android or iOS app, in the messages part:
script eval abrp.info()
=> to display vehicle data to be sent to abrpscript eval abrp.onetime()
=> to launch one time the request to abrp serverscript eval abrp.send(1)
=> toggle send data to abrpscript eval abrp.send(0)
=> stop sending datascript eval abrp.resetConfig()
=> reset configuration to defaults
- Also in the messages part, configuration can be updated with:
config set usr abrp.car_model <value>
config set usr abrp.url <value>
config set usr abrp.user_token <value>