apiVersion: influxdata.com/v2alpha1 | |
kind: Variable | |
metadata: | |
name: wizardly-northcutt-83c00b | |
spec: | |
associations: | |
- kind: Label | |
name: frosty-hamilton-83c001 | |
name: kwh_price | |
description: Price per kilowatt-hour | |
selected: | |
- "0.0554" | |
type: constant | |
values: | |
- "0.0554" | |
--- | |
apiVersion: influxdata.com/v2alpha1 | |
kind: Label | |
metadata: | |
name: frosty-hamilton-83c001 | |
spec: | |
color: '#0b3a8d' | |
name: wall-connector | |
description: Tesla wall connector label used across the InfluxDB stack | |
--- | |
apiVersion: influxdata.com/v2alpha1 | |
kind: Bucket | |
metadata: | |
name: busy-bhaskara-83c005 | |
spec: | |
associations: | |
- kind: Label | |
name: frosty-hamilton-83c001 | |
name: tesla | |
description: Bucket to store the Tesla Wall Connector metrics | |
retentionRules: | |
- everySeconds: 2.592e+06 | |
type: expire | |
--- | |
apiVersion: influxdata.com/v2alpha1 | |
kind: Dashboard | |
metadata: | |
name: realistic-rosalind-83c001 | |
spec: | |
associations: | |
- kind: Label | |
name: frosty-hamilton-83c001 | |
charts: | |
- colors: | |
- hex: '#00C9FF' | |
id: base | |
name: laser | |
type: text | |
decimalPlaces: 2 | |
height: 1 | |
kind: Single_Stat | |
name: Total Energy Cost | |
prefix: $ | |
queries: | |
- query: "import \"math\"\nfrom(bucket: \"tesla\")\n |> range(start: v.timeRangeStart, | |
stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] | |
== \"http\")\n |> filter(fn: (r) => r[\"_field\"] == \"energy_wh\")\n | |
\ |> group()\n |> last()\n |> map(fn: (r) => ({ \n r with \n | |
\ _value: r._value / 1000.00 * float(v: v.kwh_price)\n })\n )" | |
staticLegend: {} | |
width: 2 | |
- colors: | |
- hex: '#00C9FF' | |
id: base | |
name: laser | |
type: text | |
decimalPlaces: 2 | |
height: 1 | |
kind: Single_Stat | |
name: Session Cost | |
prefix: $ | |
queries: | |
- query: "import \"math\"\nfrom(bucket: \"tesla\")\n |> range(start: v.timeRangeStart, | |
stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] | |
== \"http\")\n |> filter(fn: (r) => r[\"_field\"] == \"session_energy_wh\")\n | |
\ |> group()\n |> last()\n |> map(fn: (r) => ({ \n r with \n | |
\ _value: r._value / 1000.00 * float(v: v.kwh_price)\n })\n )" | |
staticLegend: {} | |
width: 2 | |
yPos: 1 | |
- colors: | |
- hex: '#00C9FF' | |
id: base | |
name: laser | |
type: text | |
decimalPlaces: 0 | |
height: 1 | |
kind: Single_Stat | |
name: PCBA Temp | |
queries: | |
- query: |- | |
from(bucket: "tesla") | |
|> range(start: v.timeRangeStart, stop: v.timeRangeStop) | |
|> filter(fn: (r) => r["_measurement"] == "http") | |
|> filter(fn: (r) => r["_field"] == "pcba_temp_c") | |
|> group() | |
|> last() | |
staticLegend: {} | |
suffix: ' C' | |
width: 2 | |
yPos: 2 | |
- axes: | |
- base: "10" | |
name: x | |
scale: linear | |
- base: "10" | |
name: "y" | |
scale: linear | |
suffix: ' amps' | |
colorizeRows: true | |
colors: | |
- hex: '#31C0F6' | |
id: d58d388e-a88c-48da-8cbf-11479103adfd | |
name: Nineteen Eighty Four | |
type: scale | |
- hex: '#A500A5' | |
id: 2be1cf43-f8c1-40a2-8c98-3ffa00de391d | |
name: Nineteen Eighty Four | |
type: scale | |
- hex: '#FF7E27' | |
id: 2e354eab-5174-421d-bac4-84cadf21c1ab | |
name: Nineteen Eighty Four | |
type: scale | |
geom: line | |
height: 5 | |
hoverDimension: auto | |
kind: Xy | |
legendColorizeRows: true | |
legendOpacity: 1 | |
legendOrientationThreshold: 1e+08 | |
name: Current | |
opacity: 1 | |
orientationThreshold: 1e+08 | |
position: overlaid | |
queries: | |
- query: |- | |
from(bucket: "tesla") | |
|> range(start: v.timeRangeStart, stop: v.timeRangeStop) | |
|> filter(fn: (r) => r["_measurement"] == "http") | |
|> filter(fn: (r) => r["_field"] == "currentA_a" or r["_field"] == "currentB_a" or r["_field"] == "currentC_a" or r["_field"] == "currentN_a") | |
staticLegend: | |
colorizeRows: true | |
opacity: 1 | |
orientationThreshold: 1e+08 | |
widthRatio: 1 | |
width: 12 | |
widthRatio: 1 | |
xCol: _time | |
yCol: _value | |
yPos: 3 | |
- axes: | |
- base: "10" | |
name: x | |
scale: linear | |
- base: "10" | |
name: "y" | |
scale: linear | |
suffix: V | |
colorizeRows: true | |
colors: | |
- hex: '#31C0F6' | |
id: d58d388e-a88c-48da-8cbf-11479103adfd | |
name: Nineteen Eighty Four | |
type: scale | |
- hex: '#A500A5' | |
id: 2be1cf43-f8c1-40a2-8c98-3ffa00de391d | |
name: Nineteen Eighty Four | |
type: scale | |
- hex: '#FF7E27' | |
id: 2e354eab-5174-421d-bac4-84cadf21c1ab | |
name: Nineteen Eighty Four | |
type: scale | |
geom: line | |
height: 5 | |
heightRatio: 0.18301435406698566 | |
hoverDimension: auto | |
kind: Xy | |
legendColorizeRows: true | |
legendOpacity: 1 | |
legendOrientationThreshold: 1e+08 | |
name: Volts | |
opacity: 1 | |
orientationThreshold: 1e+08 | |
position: overlaid | |
queries: | |
- query: |- | |
from(bucket: "tesla") | |
|> range(start: v.timeRangeStart, stop: v.timeRangeStop) | |
|> filter(fn: (r) => r["_measurement"] == "http") | |
|> filter(fn: (r) => r["_field"] == "voltageA_v" or r["_field"] == "voltageB_v" or r["_field"] == "voltageC_v") | |
staticLegend: | |
colorizeRows: true | |
heightRatio: 0.18301435406698566 | |
opacity: 1 | |
orientationThreshold: 1e+08 | |
widthRatio: 1 | |
width: 12 | |
widthRatio: 1 | |
xCol: _time | |
yCol: _value | |
yPos: 8 | |
- colors: | |
- hex: '#00C9FF' | |
id: base | |
name: laser | |
type: text | |
decimalPlaces: 2 | |
height: 1 | |
kind: Single_Stat | |
name: Total Energy KWh | |
queries: | |
- query: "from(bucket: \"tesla\")\n |> range(start: v.timeRangeStart, stop: | |
v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"http\")\n | |
\ |> filter(fn: (r) => r[\"_field\"] == \"energy_wh\")\n |> group()\n | |
\ |> last()\n |> map(fn: (r) => ({ \n r with \n _value: r._value | |
/ 1000.00\n })\n )" | |
staticLegend: {} | |
suffix: ' KWh' | |
width: 2 | |
xPos: 2 | |
- colors: | |
- hex: '#00C9FF' | |
id: base | |
name: laser | |
type: text | |
decimalPlaces: 2 | |
height: 1 | |
kind: Single_Stat | |
name: Session Energy | |
queries: | |
- query: |- | |
from(bucket: "tesla") | |
|> range(start: v.timeRangeStart, stop: v.timeRangeStop) | |
|> filter(fn: (r) => r["_measurement"] == "http") | |
|> filter(fn: (r) => r["_field"] == "session_energy_wh") | |
|> group() | |
|> last() | |
staticLegend: {} | |
suffix: ' watts' | |
width: 2 | |
xPos: 2 | |
yPos: 1 | |
- colors: | |
- hex: '#00C9FF' | |
id: base | |
name: laser | |
type: text | |
decimalPlaces: 0 | |
height: 1 | |
kind: Single_Stat | |
name: MCU Temp | |
queries: | |
- query: |- | |
from(bucket: "tesla") | |
|> range(start: v.timeRangeStart, stop: v.timeRangeStop) | |
|> filter(fn: (r) => r["_measurement"] == "http") | |
|> filter(fn: (r) => r["_field"] == "mcu_temp_c") | |
|> group() | |
|> last() | |
staticLegend: {} | |
suffix: ' C' | |
width: 2 | |
xPos: 2 | |
yPos: 2 | |
- colors: | |
- hex: '#00C9FF' | |
id: base | |
name: laser | |
type: text | |
decimalPlaces: 2 | |
height: 2 | |
kind: Single_Stat | |
name: Charging State | |
queries: | |
- query: "from(bucket: \"tesla\")\n |> range(start: v.timeRangeStart, stop: | |
v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"http\")\n | |
\ |> filter(fn: (r) => r[\"_field\"] == \"contactor_closed\")\n |> | |
group()\n |> last()\n |> map(fn: (r) => ({ \n r with \n State: | |
if r._value == true then \"Charging\" else \"Completed\"\n })\n | |
\ )\n |> keep(columns: [\"State\"])" | |
staticLegend: {} | |
width: 2 | |
xPos: 4 | |
- colors: | |
- hex: '#00C9FF' | |
id: base | |
name: laser | |
type: text | |
decimalPlaces: 0 | |
height: 1 | |
kind: Single_Stat | |
name: Handle Temp | |
queries: | |
- query: |- | |
from(bucket: "tesla") | |
|> range(start: v.timeRangeStart, stop: v.timeRangeStop) | |
|> filter(fn: (r) => r["_measurement"] == "http") | |
|> filter(fn: (r) => r["_field"] == "handle_temp_c") | |
|> group() | |
|> last() | |
staticLegend: {} | |
suffix: ' C' | |
width: 2 | |
xPos: 4 | |
yPos: 2 | |
- colors: | |
- hex: '#00C9FF' | |
id: base | |
name: laser | |
type: text | |
decimalPlaces: 2 | |
height: 2 | |
kind: Single_Stat | |
name: Connection | |
queries: | |
- query: "from(bucket: \"tesla\")\n |> range(start: v.timeRangeStart, stop: | |
v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"http\")\n | |
\ |> filter(fn: (r) => r[\"_field\"] == \"vehicle_connected\")\n |> | |
group()\n |> last()\n |> map(fn: (r) => ({ \n r with \n State: | |
if r._value == true then \"Connected\" else \"Disconnected\"\n })\n | |
\ )\n |> keep(columns: [\"State\"])" | |
staticLegend: {} | |
width: 2 | |
xPos: 6 | |
- colors: | |
- hex: '#00C9FF' | |
id: base | |
name: laser | |
type: text | |
decimalPlaces: 0 | |
height: 1 | |
kind: Single_Stat | |
name: Charging Cycles | |
queries: | |
- query: |- | |
from(bucket: "tesla") | |
|> range(start: v.timeRangeStart, stop: v.timeRangeStop) | |
|> filter(fn: (r) => r["_measurement"] == "http") | |
|> filter(fn: (r) => r["_field"] == "connector_cycles") | |
|> group() | |
|> last() | |
staticLegend: {} | |
width: 2 | |
xPos: 6 | |
yPos: 2 | |
- colors: | |
- hex: '#00C9FF' | |
id: base | |
name: laser | |
type: text | |
decimalPlaces: 2 | |
height: 2 | |
kind: Single_Stat | |
name: Current | |
queries: | |
- query: |- | |
from(bucket: "tesla") | |
|> range(start: v.timeRangeStart, stop: v.timeRangeStop) | |
|> filter(fn: (r) => r["_measurement"] == "http") | |
|> filter(fn: (r) => r["_field"] == "vehicle_current_a") | |
|> group() | |
|> last() | |
staticLegend: {} | |
suffix: ' amps' | |
width: 2 | |
xPos: 8 | |
- colors: | |
- hex: '#00C9FF' | |
id: base | |
name: laser | |
type: text | |
decimalPlaces: 0 | |
height: 1 | |
kind: Single_Stat | |
name: Alerts | |
queries: | |
- query: |- | |
from(bucket: "tesla") | |
|> range(start: v.timeRangeStart, stop: v.timeRangeStop) | |
|> filter(fn: (r) => r["_measurement"] == "http") | |
|> filter(fn: (r) => r["_field"] == "alert_count") | |
|> group() | |
|> last() | |
staticLegend: {} | |
width: 2 | |
xPos: 8 | |
yPos: 2 | |
description: Dashboard that displays the Tesla Wall Connector metrics | |
name: Tesla Wall Connector | |
--- | |
apiVersion: influxdata.com/v2alpha1 | |
kind: Telegraf | |
metadata: | |
name: teslawallconnector-telegraf | |
spec: | |
associations: | |
- kind: Label | |
name: frosty-hamilton-83c001 | |
config: | | |
[global_tags] | |
instrument = "wall-connector" | |
[agent] | |
interval = "60s" | |
round_interval = true | |
metric_batch_size = 1000 | |
metric_buffer_limit = 10000 | |
collection_jitter = "0s" | |
flush_interval = "30s" | |
flush_jitter = "0s" | |
omit_hostname = true | |
[[inputs.http]] | |
urls = ["http://$TWC_HOST/api/1/vitals", "http://$TWC_HOST/api/1/lifetime"] | |
method = "GET" | |
data_format = "json" | |
json_string_fields = ["contactor_closed", "vehicle_connected"] | |
tagexclude = ["url"] | |
[[outputs.influxdb_v2]] | |
urls = ["$INFLUX_HOST"] | |
token = "$INFLUX_TOKEN" | |
organization = "$INFLUX_ORG" | |
bucket = "tesla" | |
timeout = "10s" | |
name: TeslaWallConnector | |
description: Telegraf configuration to collect Tesla Wall Connector metrics |
Hello - I'm trying to get this working but am getting the following error when trying to start Telegraf:
plugin inputs.influxdb_listener: line 128: configuration specified the fields ["INFLUX_HOST" "INFLUX_TOKEN" "INFLUX_ORG" "TWC_HOST"], but they weren't used
@wpattison74 do you use those variables in your telegraf configuration? Do you set them in the environment/container before launching telegraf? You could hardcore these telegraf configurations instead of using variables. Let me know.
Admittedly, I've never dealt with Telegraf or InfluxDB, so there's that. I have the variables setup in my telegraf.conf file, hardcoded in there. I'm running this in a native Ubuntu server in my homelab, not a container or VM. I probably need to go search out an introduction to Telegraf video - thought this was something I could stand up over the holiday pretty quickly.
Update - Got it working. Pretty slick - thanks for posting this. I just need to rejigger the price/kWh that's defined.
@wpattison74 awesome!! Yes the price should be set under a static variable. You should see a variable page in the UI, I believe it’s in the same place as the tokens.
Hi @BondAnthony did you also manage to reliably read usage data over time? E.g. know how much kWh the TWC consumed over a month?
Hey @rubenstolk. Yes, you can calculate the increase using the energy_wh
field under the http
measurement. This will provide the total kWh
used for the period defined.
Here is an example looking back over 30 days.
from(bucket: "tesla")
|> range(start: -30d, stop: now())
|> filter(fn: (r) => r["_measurement"] == "http")
|> filter(fn: (r) => r["_field"] == "energy_wh")
|> group()
|> map(fn: (r) => ({
r with
_value: r._value / 1000.00
})
)
|> increase(columns: ["_value"])
Just want to say thank you for this. this is really great. I got this up and running (after a few false starts because i've never used influx or telegraf before) pretty quickly.
Thank you @ImAGitHubUser, I'm glad you were able to get this up and running.
I'm using InfluxDB Cloud to present and store this data. The data is gathered using Telegraf and shipped to InfluxDB Cloud every minute. Once you have an InfluxDB cloud account this template can be added. This will create the Telegraf configuration, dashboards, buckets, and variables. You should only need to run Telegraf within your network with the right environment variables set using the telegraf configuration from the stack.
Set the following environment variables or hardcode them in your Telegraf configuration.
You can start Telegraf using the following command.