Skip to content

Instantly share code, notes, and snippets.

@esbenr
Created April 30, 2021 10:13
Show Gist options
  • Save esbenr/39d7ec67533e9a5fa8c12029ce88b2d2 to your computer and use it in GitHub Desktop.
Save esbenr/39d7ec67533e9a5fa8c12029ce88b2d2 to your computer and use it in GitHub Desktop.
Mapping the data from my NR subflow to a device_tracker in HA
[
{
"id": "5702eca4.c373e4",
"type": "api-call-service",
"z": "93e5dfe8.6683b",
"name": "Device tracker",
"server": "84d7c1be.d21e3",
"version": 1,
"debugenabled": false,
"service_domain": "device_tracker",
"service": "see",
"entityId": "",
"data": "{}",
"dataType": "json",
"mergecontext": "",
"output_location": "",
"output_location_type": "none",
"mustacheAltTags": false,
"x": 1040,
"y": 180,
"wires": [
[]
]
},
{
"id": "d6602e99.4c146",
"type": "function",
"z": "93e5dfe8.6683b",
"name": "Create data for car",
"func": "var adblue = msg.payload.adblueRemainingKm[0]\nvar model = msg.payload.model.toLowerCase();\nmsg.payload = {\n \"data\": {\n \"dev_id\": \"vw_\" + model,\n \"gps\": [\n msg.payload.position.latitude,\n msg.payload.position.longitude\n ],\n \"attributes\": {\n \"license_plate\": msg.payload.licensePlate,\n \"friendly_name\": msg.payload.model,\n \"vin\": msg.payload.vin,\n \"name\": msg.payload.name,\n \"brand\": msg.payload.brand,\n \"make\": msg.payload.make,\n \"model\": msg.payload.model,\n \"year\": msg.payload.year,\n \"engine_size\": msg.payload.engineSize,\n \"fuel_economy\": msg.payload.fuelEconomy,\n \"fuel_type\": msg.payload.fuelType,\n \"fuel_percentage\": msg.payload.fuelPercentage,\n \"fuel_level\": msg.payload.fuelLevel.liter,\n \"fuel_level_time\": msg.payload.fuelLevel.time,\n \"fuel_tank_size\": msg.payload.fuelTankSize,\n \"ignition\": msg.payload.ignition.on,\n \"ignition_time\": msg.payload.ignition.time,\n \"odometer\": msg.payload.odometer.odometer,\n \"odometer_time\": msg.payload.odometer.time,\n \"outdoor_temperature\": msg.payload.outdoorTemperatures[0].celsius,\n \"outdoor_temperature_time\": msg.payload.outdoorTemperatures[0].time,\n \"location_time\": msg.payload.position.time,\n \"health_ok\": msg.payload.health.ok,\n \"health_recommendation\": msg.payload.health.recommendation,\n \"latest_battery_voltage\": msg.payload.latestBatteryVoltage.voltage,\n \"latest_battery_voltage_time\": msg.payload.latestBatteryVoltage.time,\n \"service_predicted_date\": msg.payload.service.predictedDate,\n \"service_predicted_next_oilchange_in_km_date\": msg.payload.service.nextOilChangeInKmPredictedDate,\n \"service_predicted_next_oilchange_in_days_date\": msg.payload.service.nextOilChangeInDaysPredictedDate,\n \"service_predicted_next_interval_service_in_km_date\": msg.payload.service.nextIntervalServiceInKmPredictedDate,\n \"service_predicted_next_interval_service_in_days_date\": msg.payload.service.nextIntervalServiceInDaysPredictedDate,\n }\n }\n}\n\nif (adblue !== undefined) {\n msg.payload.data.attributes.adblue_remaining_km = adblue.km\n msg.payload.data.attributes.adblue_remaining_km_time = adblue.time\n}\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"x": 790,
"y": 180,
"wires": [
[
"5702eca4.c373e4"
]
]
},
{
"id": "84d7c1be.d21e3",
"type": "server",
"name": "Home Assistant",
"addon": true
}
]
@esbenr
Copy link
Author

esbenr commented Apr 30, 2021

Mange spørger hvordan man mapper data fra mit connectedcars.io-subflow til en egentlig device_tracker i HA.
Jeg gør det med 1) en function-node til at formattere/mappe dataene fra connectedcars.io-subflow'ets json-output til et objekt i msg.payload, som jeg så sender til 2) en call-service HA-node, der kalder servicen device_tracker.see.

Magien sker når man kalder device_tracker.see. Hvis HA ikke allerede har en device_tracker tilknyttet NR-flowet, så opretter den en ny og sender dataene til den. Når den så kaldes igen og device trackeren allerede findes efterfølgende, opdaterer den blot dataene.

Mit flow ser ud som følger:
image

Vær opmærksom på at du meget vel skal in tur forbi known_devices.yaml når device_tracker.see er kørt første gang og sætte tracking: true, for at den opdaterer data på device_trackeren.

@DIYtechie
Copy link

Få forslag til tilføjelser indsat i nedenstående (tusindtalsseparator, beregnet rækkevidde og afrunding af liter i tanken):

[ { "id": "19d4699.ad77196", "type": "subflow", "name": "Get cars", "info": "", "category": "", "in": [ { "x": 260, "y": 180, "wires": [ { "id": "610bb11a.69b7e" } ] } ], "out": [ { "x": 1540, "y": 120, "wires": [ { "id": "f3c111e0.bcf8d", "port": 0 } ] }, { "x": 940, "y": 240, "wires": [ { "id": "7f25adb3.8ab454", "port": 1 } ] } ], "env": [ { "name": "Namespace", "type": "str", "value": "" } ], "color": "#DDAA99" }, { "id": "610bb11a.69b7e", "type": "function", "z": "19d4699.ad77196", "name": "Cars request", "func": "let namespace = env.get(\"Namespace\");\nmsg.headers = {\n \"Content-Type\": \"application/json\",\n \"Accept\": \"application/json\",\n \"x-organization-namespace\": \"semler:\" + namespace,\n \"User-Agent\": \"ConnectedCars/360 CFNetwork/978.0.7 Darwin/18.7.0\",\n \"Authorization\": \"Bearer \" + msg.payload\n}\nvar last = new Date().toISOString();\nvar firstDate = new Date();\nfirstDate.setYear(firstDate.getFullYear() - 1);\nvar first = firstDate.toISOString();\nconsole.log(last)\nconsole.log(first)\nmsg.payload = { \"query\": \"query User { viewer { vehicles { vehicle { vin licensePlate name brand make model year engineSize avgCO2EmissionKm fuelEconomy fuelType fuelLevel { time liter } fuelTankSize(limit: 1) fuelPercentage { percent time } fuelPercentages(limit: 1) { percent time } adblueRemainingKm(limit: 1) { km time } ignition { time on } lampStates { type time lampDetails { title subtitle } } totalTripStatistics(period: {first: \\\"\"+first+\"\\\", last: \\\"\"+last+\"\\\"}) { mileageInKm } odometer { time odometer } outdoorTemperatures(limit: 1) { celsius time } position { time latitude longitude speed direction } service { predictedDate nextOilChangeInKm nextOilChangeInDays nextIntervalServiceInKm nextIntervalServiceInDays nextOilChangeInKmPredictedDate nextOilChangeInDaysPredictedDate nextIntervalServiceInKmPredictedDate nextIntervalServiceInDaysPredictedDate } latestBatteryVoltage { voltage time } health { ok recommendation } } } } }\" }\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 410, "y": 180, "wires": [ [ "cf34a858.7a6a18" ] ] }, { "id": "cf34a858.7a6a18", "type": "http request", "z": "19d4699.ad77196", "name": "", "method": "POST", "ret": "obj", "paytoqs": "ignore", "url": "https://api.connectedcars.io/graphql", "tls": "", "persist": false, "proxy": "", "authType": "", "x": 610, "y": 180, "wires": [ [ "7f25adb3.8ab454" ] ] }, { "id": "942754ae.c75a68", "type": "split", "z": "19d4699.ad77196", "name": "", "splt": "\\n", "spltType": "str", "arraySplt": 1, "arraySpltType": "len", "stream": false, "addname": "", "x": 1150, "y": 120, "wires": [ [ "f3c111e0.bcf8d" ] ] }, { "id": "97be1854.7df998", "type": "function", "z": "19d4699.ad77196", "name": "Vehicles", "func": "msg.payload = msg.payload.data.viewer.vehicles\nreturn msg", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "x": 980, "y": 120, "wires": [ [ "942754ae.c75a68" ] ] }, { "id": "f3c111e0.bcf8d", "type": "function", "z": "19d4699.ad77196", "name": "Create data for vehicle", "func": "msg.payload = msg.payload.vehicle\nreturn msg", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "x": 1360, "y": 120, "wires": [ [] ] }, { "id": "7f25adb3.8ab454", "type": "switch", "z": "19d4699.ad77196", "name": "if vehicles", "property": "payload.data.viewer.vehicles", "propertyType": "msg", "rules": [ { "t": "nnull" }, { "t": "null" } ], "checkall": "true", "repair": false, "outputs": 2, "x": 800, "y": 180, "wires": [ [ "97be1854.7df998" ], [] ] }, { "id": "b53a0294.888cc", "type": "subflow", "name": "Get token", "info": "", "category": "", "in": [ { "x": 280, "y": 260, "wires": [ { "id": "10d21e55.83aea2" } ] } ], "out": [ { "x": 1440, "y": 220, "wires": [ { "id": "d22669c0.7273c8", "port": 0 }, { "id": "2a805c70.b8cd74", "port": 0 } ] } ], "env": [ { "name": "Email", "type": "str", "value": "" }, { "name": "Password", "type": "str", "value": "" }, { "name": "Namespace", "type": "str", "value": "" } ], "color": "#DDAA99" }, { "id": "3544a438.2e944c", "type": "http request", "z": "b53a0294.888cc", "name": "Get token", "method": "POST", "ret": "obj", "paytoqs": "ignore", "url": "https://auth-api.connectedcars.io/auth/login/email/password", "tls": "", "persist": false, "proxy": "", "authType": "", "x": 920, "y": 260, "wires": [ [ "d22669c0.7273c8" ] ] }, { "id": "e12195f1.74fb18", "type": "function", "z": "b53a0294.888cc", "name": "Token request", "func": "let email = env.get(\"Email\");\nlet password = env.get(\"Password\");\nlet namespace = env.get(\"Namespace\");\nmsg.payload = {\n\t\"email\": email,\n\t\"password\": password\n}\nmsg.headers = {\n \"Content-Type\": \"application/json\",\n \"Accept\": \"application/json\",\n \"x-organization-namespace\": \"semler:\" + namespace,\n \"User-Agent\": \"ConnectedCars/360 CFNetwork/978.0.7 Darwin/18.7.0\"\n}\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "x": 740, "y": 260, "wires": [ [ "3544a438.2e944c" ] ] }, { "id": "d22669c0.7273c8", "type": "change", "z": "b53a0294.888cc", "name": "store and output new token as payload", "rules": [ { "t": "set", "p": "payload", "pt": "msg", "to": "payload.token", "tot": "msg" }, { "t": "set", "p": "token", "pt": "flow", "to": "payload.token", "tot": "msg" }, { "t": "set", "p": "expiry", "pt": "flow", "to": "$millis() + $$.payload.expires", "tot": "jsonata" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 1190, "y": 260, "wires": [ [] ] }, { "id": "10d21e55.83aea2", "type": "switch", "z": "b53a0294.888cc", "name": "flow token is valid", "property": "expiry", "propertyType": "flow", "rules": [ { "t": "lt", "v": "$millis()", "vt": "jsonata" }, { "t": "else" } ], "checkall": "true", "repair": false, "outputs": 2, "x": 510, "y": 180, "wires": [ [ "2a805c70.b8cd74" ], [ "e12195f1.74fb18" ] ] }, { "id": "2a805c70.b8cd74", "type": "change", "z": "b53a0294.888cc", "name": "output flow token as payload", "rules": [ { "t": "set", "p": "payload", "pt": "msg", "to": "token", "tot": "flow" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 1220, "y": 180, "wires": [ [] ] }, { "id": "853ada47.50a498", "type": "subflow", "name": "ConnectedCars.io", "info": "", "category": "", "in": [ { "x": 220, "y": 280, "wires": [ { "id": "6efa8ed6.b5f01" } ] } ], "out": [ { "x": 740, "y": 80, "wires": [ { "id": "72c0ab7a.29c214", "port": 0 } ] }, { "x": 1020, "y": 140, "wires": [ { "id": "ce13bc8f.5745c", "port": 0 } ] } ], "env": [ { "name": "Email", "type": "str", "value": "" }, { "name": "Password", "type": "str", "value": "" }, { "name": "Namespace", "type": "str", "value": "" } ], "color": "#DDAA99" }, { "id": "6efa8ed6.b5f01", "type": "subflow:b53a0294.888cc", "z": "853ada47.50a498", "name": "Get token", "env": [ { "name": "Email", "value": "Email", "type": "env" }, { "name": "Password", "value": "Password", "type": "env" }, { "name": "Namespace", "value": "Namespace", "type": "env" } ], "x": 400, "y": 280, "wires": [ [ "72c0ab7a.29c214" ] ] }, { "id": "72c0ab7a.29c214", "type": "subflow:19d4699.ad77196", "z": "853ada47.50a498", "name": "Get cars", "env": [ { "name": "Namespace", "value": "Namespace", "type": "env" } ], "x": 580, "y": 140, "wires": [ [], [ "ce13bc8f.5745c" ] ] }, { "id": "ce13bc8f.5745c", "type": "switch", "z": "853ada47.50a498", "name": "error token expired", "property": "payload.errors[0].message", "propertyType": "msg", "rules": [ { "t": "else" }, { "t": "eq", "v": "Failed with: Token has expired", "vt": "str" } ], "checkall": "true", "repair": false, "outputs": 2, "x": 830, "y": 140, "wires": [ [], [ "6efa8ed6.b5f01" ] ] }, { "id": "0ddc65f2a561f303", "type": "tab", "label": "MinVolkswagen", "disabled": false, "info": "", "env": [] }, { "id": "e3e6d0eb3c86821c", "type": "inject", "z": "0ddc65f2a561f303", "name": "", "props": [], "repeat": "600", "crontab": "", "once": true, "onceDelay": 0.1, "topic": "", "x": 120, "y": 100, "wires": [ [ "bd7de1d8.18" ] ] }, { "id": "4a3faf09d45b5fc9", "type": "debug", "z": "0ddc65f2a561f303", "name": "", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "false", "statusVal": "", "statusType": "auto", "x": 440, "y": 150, "wires": [] }, { "id": "5702eca4.c373e4", "type": "api-call-service", "z": "0ddc65f2a561f303", "name": "Device tracker", "server": "", "version": 4, "debugenabled": false, "domain": "device_tracker", "service": "see", "target": { "entityId": [], "areaId": [], "deviceId": [] }, "data": "{}", "dataType": "json", "mergeContext": "", "mustacheAltTags": false, "outputProperties": [], "queue": "none", "output_location": "payload", "output_location_type": "none", "x": 670, "y": 100, "wires": [ [] ] }, { "id": "d6602e99.4c146", "type": "function", "z": "0ddc65f2a561f303", "name": "Create data for car", "func": "var adblue = msg.payload.adblueRemainingKm[0]\nvar model = msg.payload.model.toLowerCase();\nmsg.payload = {\n \"data\": {\n \"dev_id\": \"vw_\" + model,\n \"gps\": [\n msg.payload.position.latitude,\n msg.payload.position.longitude\n ],\n \"attributes\": {\n \"license_plate\": msg.payload.licensePlate,\n \"friendly_name\": msg.payload.model,\n \"vin\": msg.payload.vin,\n \"name\": msg.payload.name,\n \"brand\": msg.payload.brand,\n \"make\": msg.payload.make,\n \"model\": msg.payload.model,\n \"year\": msg.payload.year,\n \"engine_size\": msg.payload.engineSize,\n \"fuel_economy\": msg.payload.fuelEconomy,\n \"fuel_type\": msg.payload.fuelType,\n \"fuel_percentage\": msg.payload.fuelPercentage,\n \"fuel_level\": msg.payload.fuelLevel.liter,\n \"fuel_range\": (msg.payload.fuelLevel.liter * msg.payload.fuelEconomy).toFixed(),\n \"fuel_level_time\": msg.payload.fuelLevel.time,\n \"fuel_tank_size\": msg.payload.fuelTankSize,\n \"ignition\": msg.payload.ignition.on,\n \"ignition_time\": msg.payload.ignition.time,\n \"odometer\": msg.payload.odometer.odometer.toLocaleString().replace(/\\,/g, \".\"),\n \"odometer_time\": msg.payload.odometer.time,\n \"location_time\": msg.payload.position.time,\n \"health_ok\": msg.payload.health.ok,\n \"health_recommendation\": msg.payload.health.recommendation,\n \"latest_battery_voltage\": msg.payload.latestBatteryVoltage.voltage,\n \"latest_battery_voltage_time\": msg.payload.latestBatteryVoltage.time,\n \"service_predicted_date\": msg.payload.service.predictedDate,\n \"next_service_days\": msg.payload.service.nextIntervalServiceInDays,\n \"next_service_km\": msg.payload.service.nextIntervalServiceInKm.toLocaleString().replace(/\\,/g, \".\"),\n \"next_oilchange_km\": msg.payload.service.nextOilChangeInKm.toLocaleString().replace(/\\,/g, \".\"),\n \"next_oilchange_days\": msg.payload.service.nextOilChangeInDays,\n \"service_predicted_next_oilchange_in_km_date\": msg.payload.service.nextOilChangeInKmPredictedDate,\n \"service_predicted_next_oilchange_in_days_date\": msg.payload.service.nextOilChangeInDaysPredictedDate,\n \"service_predicted_next_interval_service_in_km_date\": msg.payload.service.nextIntervalServiceInKmPredictedDate,\n \"service_predicted_next_interval_service_in_days_date\": msg.payload.service.nextIntervalServiceInDaysPredictedDate,\n }\n }\n}\n\nif (adblue !== undefined) {\n msg.payload.data.attributes.adblue_remaining_km = adblue.km\n msg.payload.data.attributes.adblue_remaining_km_time = adblue.time\n}\n\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 460, "y": 100, "wires": [ [ "5702eca4.c373e4", "02f1b619afb13a7b" ] ] }, { "id": "bd7de1d8.18", "type": "subflow:853ada47.50a498", "z": "0ddc65f2a561f303", "name": "Min bil", "env": [ { "name": "Namespace", "value": "minvolkswagen", "type": "str" } ], "x": 260, "y": 100, "wires": [ [ "4a3faf09d45b5fc9", "d6602e99.4c146" ], [ "4a3faf09d45b5fc9" ] ], "inputLabels": [ "Any message to trigger the component" ], "outputLabels": [ "JSON response as payload for each vehicle", "JSON response as payload with errors" ], "info": "Subflow that fetches cars from MinVolkswagen.\nMinVolkswagen is the danish app for integrating with your danish Volkswagen.\n\nJust enter your login information - the same that you use in the MinVolkswagen app." }, { "id": "02f1b619afb13a7b", "type": "debug", "z": "0ddc65f2a561f303", "name": "", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "false", "statusVal": "", "statusType": "auto", "x": 650, "y": 200, "wires": [] } ]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment