Tesla Wall Connector Gen 3 RESTful

Hi ,
Do you plan to make a Git out all these data so we can have a “reference manual”

Thanks

I have not a plan for this, if you like go ahead :slight_smile:

Great information. Is somebody already doing an integration based on this API-call data. Neat that there is serial number for HA unique ID too.

Just adding information about TWC from pi-hole, TWC gen3 seems to talk to “maestro-prd.sn.tesla.services” DNS-name… Then it also queries pool.ntp.org for time sync.

1 Like

I saw that there is a new firmware but my charger did not auto update so I needed to do it manually. You can go to http://IP-of-charger/service and manually update the FW. After this you have power sharing as an option but to enable power sharing one would need add a second wall connecters and I don’t have that :frowning: So if one have two and can do some Wireshark between these two it would be nice!

Full Tesla Wall Charger gen 3 API taken into home assistant via configuration.yaml

#Tesla Wall Connector Gen 3
rest:
  - authentication: basic
    username: ""
    password: ""
    scan_interval: 600
    resource: http://192.168.9.129/api/1/vitals
    sensor:
      - name: "TWC session"
        value_template: "{{ value_json.session_s | int }}"
        unit_of_measurement: s
      - name: "TWC grid voltage"
        value_template: "{{ float(value_json.grid_v) }}"
        unit_of_measurement: V
        device_class: voltage
      - name: "TWC grid frequency"
        value_template: "{{ float(value_json.grid_hz) }}"
        unit_of_measurement: Hz
      - name: "TWC vehicle current"
        value_template: "{{ float(value_json.vehicle_current_a) }}"
        device_class: current
        unit_of_measurement: A
      - name: "TWC current A"
        value_template: "{{ float(value_json.currentA_a) }}"
        device_class: current
        unit_of_measurement: A
      - name: "TWC current B"
        value_template: "{{ float(value_json.currentB_a) }}"
        device_class: current
        unit_of_measurement: A
      - name: "TWC current C"
        value_template: "{{ float(value_json.currentC_a) }}"
        device_class: current
        unit_of_measurement: A
      - name: "TWC current N"
        value_template: "{{ float(value_json.currentN_a) }}"
        device_class: current
        unit_of_measurement: A
      - name: "TWC voltage A"
        value_template: "{{ float(value_json.voltageA_v) }}"
        device_class: voltage
        unit_of_measurement: V
      - name: "TWC voltage B"
        value_template: "{{ float(value_json.voltageB_v) }}"
        device_class: voltage
        unit_of_measurement: V
      - name: "TWC voltage C"
        value_template: "{{ float(value_json.voltageC_v) }}"
        device_class: voltage
        unit_of_measurement: V
      - name: "TWC relay coil"
        value_template: "{{ float(value_json.relay_coil_v) }}"
        device_class: voltage
        unit_of_measurement: V
      - name: "TWC pcba temp"
        value_template: "{{ float(value_json.pcba_temp_c) }}"
        device_class: temperature
        unit_of_measurement: C
      - name: "TWC handle temp"
        value_template: "{{ float(value_json.handle_temp_c) }}"
        device_class: temperature
        unit_of_measurement: C
      - name: "TWC mcu temp"
        value_template: "{{ float(value_json.mcu_temp_c) }}"
        device_class: temperature
        unit_of_measurement: C
      - name: "TWC uptime"
        value_template: "{{ value_json.uptime_s | int }}"
        unit_of_measurement: s
      - name: "TWC input thermopile uv"
        value_template: "{{ value_json.input_thermopile_uv | int }}"
      - name: "TWC prox"
        value_template: "{{ value_json.prox_v | int }}"
        device_class: voltage
        unit_of_measurement: V
      - name: "TWC pilot high"
        value_template: "{{ float(value_json.pilot_high_v) }}"
        device_class: voltage
        unit_of_measurement: V
      - name: "TWC pilot low"
        value_template: "{{ float(value_json.pilot_low_v) }}"
        device_class: voltage
        unit_of_measurement: V
      - name: "TWC session energy"
        value_template: "{{ float(value_json.session_energy_wh) | multiply(0.001) | round(3) }}"
        unit_of_measurement: kWh
        device_class: energy
      - name: "TWC config status"
        value_template: "{{ value_json.config_status }}"
      - name: "TWC evse state"
        value_template: "{{ value_json.evse_state }}"
      - name: "TWC current alerts"
        value_template: "{{ value_json.current_alerts }}"
      - name: "TWC charging power A"
        value_template: "{{ float(value_json.voltageA_v) * float(value_json.currentA_a) | round(0) }}"
        device_class: power
        unit_of_measurement: W
      - name: "TWC charging power B"
        value_template: "{{ float(value_json.voltageB_v) * float(value_json.currentB_a) | round(0) }}"
        device_class: power
        unit_of_measurement: W
      - name: "TWC charging power C"
        value_template: "{{ float(value_json.voltageC_v) * float(value_json.currentC_a) | round(0) }}"
        device_class: power
        unit_of_measurement: W
      - name: "TWC total charging power"
        value_template: "{{ float(value_json.voltageA_v) * float(value_json.currentA_a) + float(value_json.voltageB_v) * float(value_json.currentB_a) + float(value_json.voltageC_v) * float(value_json.currentC_a) | round(0) }}"
        device_class: power
        unit_of_measurement: W
      - name: "TWC uptime str"
        value_template: "{{ '{:d} days {:02d}:{:02d}:{:02d}'.format(value_json.uptime_s // 86400, (value_json.uptime_s % 86400) // 3600, (value_json.uptime_s % 3600) // 60, (value_json.uptime_s % 3600) % 60) }}"
      - name: "TWC session str"
        value_template: "{{ '{:d} days {:02d}:{:02d}:{:02d}'.format(value_json.session_s // 86400, (value_json.session_s % 86400) // 3600, (value_json.session_s % 3600) // 60, (value_json.session_s % 3600) % 60) }}"
    binary_sensor:
      - name: "TWC contactor closed"
        value_template: "{{ value_json.contactor_closed }}"
        device_class: opening
      - name: "TWC vehicle connected"
        value_template: "{{ value_json.vehicle_connected }}"
        device_class: plug

  - authentication: basic
    username: ""
    password: ""
    scan_interval: 600
    resource: http://192.168.9.129/api/1/lifetime
    sensor:
      - name: "TWC lifetime contactor cycles"
        value_template: "{{ value_json.contactor_cycles | int }}"
      - name: "TWC lifetime contactor cycles loaded"
        value_template: "{{ value_json.contactor_cycles_loaded | int }}"
      - name: "TWC lifetime alert count"
        value_template: "{{ value_json.alert_count | int }}"
      - name: "TWC lifetime thermal foldbacks"
        value_template: "{{ value_json.thermal_foldbacks | int }}"
      - name: "TWC lifetime avg startup temp"
        value_template: "{{ float(value_json.avg_startup_temp) }}"
      - name: "TWC lifetime charge starts"
        value_template: "{{ value_json.charge_starts | int }}"
      - name: "TWC lifetime energy kWh"
        value_template: "{{ value_json.energy_wh | multiply(0.001) | float(3) }}"
        unit_of_measurement: kWh
        device_class: energy
      - name: "TWC lifetime connector cycles"
        value_template: "{{ value_json.connector_cycles | int }}"
      - name: "TWC lifetime uptime"
        value_template: "{{ value_json.uptime_s | int }}"
        unit_of_measurement: s
      - name: "TWC lifetime charging time"
        value_template: "{{ value_json.charging_time_s | int }}"
        unit_of_measurement: s
      - name: "TWC lifetime uptime str"
        value_template: "{{ '{:d} days {:02d}:{:02d}:{:02d}'.format(value_json.uptime_s // 86400, (value_json.uptime_s % 86400) // 3600, (value_json.uptime_s % 3600) // 60, (value_json.uptime_s % 3600) % 60) }}"
      - name: "TWC lifetime charging time str"
        value_template: "{{ '{:d} days {:02d}:{:02d}:{:02d}'.format(value_json.charging_time_s // 86400, (value_json.charging_time_s % 86400) // 3600, (value_json.charging_time_s % 3600) // 60, (value_json.uptime_s % 3600) % 60) }}"

  - authentication: basic
    username: ""
    password: ""
    scan_interval: 3600
    resource: http://192.168.9.129/api/1/version
    sensor:
      - name: "TWC firmware version"
        value_template: "{{ value_json.firmware_version }}"
      - name: "TWC part number"
        value_template: "{{ value_json.part_number }}"
      - name: "TWC serial number"
        value_template: "{{ value_json.serial_number }}"

  - authentication: basic
    username: ""
    password: ""
    scan_interval: 600
    resource: http://192.168.9.129/api/1/wifi_status
    sensor:
      - name: "TWC wifi signal strength"
        value_template: "{{ value_json.wifi_signal_strength | int }}"
        device_class: signal_strength
        unit_of_measurement: dBm
      - name: "TWC wifi rssi"
        value_template: "{{ value_json.wifi_rssi | int }}"
        device_class: signal_strength
      - name: "TWC wifi snr"
        value_template: "{{ value_json.wifi_snr | int }}"
        device_class: signal_strength
      - name: "TWC wifi infra ip"
        value_template: "{{ value_json.wifi_infra_ip }}"
      - name: "TWC wifi mac"
        value_template: "{{ value_json.wifi_mac }}"
    binary_sensor:
      - name: "TWC wifi connected"
        value_template: "{{ value_json.wifi_connected }}"
        device_class: connectivity
      - name: "TWC internet"
        value_template: "{{ value_json.internet }}"
        device_class: connectivity

3 Likes

Other potential API directories and calls from firmware file…
/access
/alerts
/fwupdate
/installation
/service
/sharing, /sharing/add, /sharing/settings
/wifi

I updated to 21.29.1 fw-version of TWC and unfortunately /api/1/lifetime -stopped working. So if that data is important for you (like it would be for me) don’t upgrade.

The fault is the TWC is producing illegal JSON, as ‘nan’ is not allowed but ‘NaN’ would be.

{“contactor_cycles”:31,“contactor_cycles_loaded”:0,“alert_count”:47,“thermal_foldbacks”:0,“avg_startup_temp”:nan,“charge_starts”:31,“energy_wh”:91853,“connector_cycles”:3,“uptime_s”:566863,“charging_time_s”:32498}

I fixed the template as first solution found, using template’s regex_findall_index. But maybe rest-api “value” could be read and replaced with regex ‘nan’ to ‘NaN’ and then forward this data to template which decodes JSON as previously. That would be better solution…

sensor:
      - name: "TWC lifetime contactor cycles"
        value_template: '{{ value | regex_findall_index("contactor_cycles\":\s*(\d+)") | int }}'
      - name: "TWC lifetime contactor cycles loaded"
        value_template: '{{ value | regex_findall_index("contactor_cycles_loaded\":\s*(\d+)") | int }}'
      - name: "TWC lifetime alert count"
        value_template: '{{ value | regex_findall_index("alert_count\":\s*(\d+)") | int }}'
      - name: "TWC lifetime thermal foldbacks"
        value_template: '{{ value | regex_findall_index("thermal_foldbacks\":\s*(\d+)") | int }}'
      - name: "TWC lifetime charge starts"
        value_template: '{{ value | regex_findall_index("charge_starts\":\s*(\d+)") | int }}'
      - name: "TWC lifetime energy kWh"
        value_template: '{{ value | regex_findall_index("energy_wh\":\s*(\d+)") | multiply(0.001) | float(3) }}'
        unit_of_measurement: kWh
        device_class: energy
      - name: "TWC lifetime connector cycles"
        value_template: '{{ value | regex_findall_index("connector_cycles\":\s*(\d+)") | int }}'
      - name: "TWC lifetime uptime"
        value_template: '{{ value | regex_findall_index("uptime_s\":\s*(\d+)") | int }}'
        unit_of_measurement: s
      - name: "TWC lifetime charging time"
        value_template: '{{ value | regex_findall_index("charging_time_s\":\s*(\d+)") | int }}'
        unit_of_measurement: s
3 Likes

Hi,
I have updated to the 21.29.1 and all call works.
I tried to access /sharing, /sharing/add, /sharing/settings and it briefly display a page but does not allow to modify anything.
The pages :
/access
/alerts
/fwupdate
/installation
give an error

but /service works

Wireshark and two devices are needed in deed for current control. When adding the slave units for power sharing, master needs to know the slave unit’s SSID and WIFI password.

However Wiresharking might be difficult, as the master is connecting to slave’s own hotspot. So the obvious way would be creating your own honeypot: RPI to advertise Tesla named Wifi, configure master TWC to connect RPI, record requests and start creating responses. Eventually it should be possible to figure out how master tries to limit slave current settings…

For time being this is too much work for me, but later. Better yet, if there is someone with more experience who is willing to dig into this :slight_smile:

Easier approach might be connecting to Tesla Wifi right after power on, and keep the connection on forever… This would require a dedicated RPi. My first try with Chrome’s developer mode and copy-as-cURL failed. At least Chrome could keep the configuration state active for over 15 mins (changed succesfully the current setting after "uptime_s":2872).

I saw that in version 4.1 one can alter the charge Amp’s so I guess it will be in the API soon:) I know it’s not taking care if one would charge a non Tesla or Tesla not own by the owner of the charger but for personal use it would be perfect to change the charge Amp via the API.

As @Klangen82 pointed out, Tesla app can control only Tesla cars. We have a non-Tesla so :slight_smile:
TWC gen 3 is currently the cheapest charger with fixed cable and DC-fault current measurement. And there is HW for current adjustment, so I want to use it.

I did a small try out with the TWC:

  1. I added a new SSID to my WIFI: TeslaWallConnector_001122, password must be 12 characters, with capital letters (numbers were not accepted by TWC)
  2. Rebooted TWC
  3. Started capture in LAN
  4. Joined to TWC’s own WIFI, with a laptop
  5. Selected Add second TWC

Capture did show just some mDNS messages (pcap -file here:
MDNS.pcapng - Google Drive ). To me it looks pretty much the same as in normal startup (mDNS sent to normal WIFI network).

The next step would be creating a Python script that sends back something similar, so that TWC believes it has found a friendly neighbour… What would be an easy way of creating random mDNS messages?

I’ve got an old version of the firmware, don’t want to manually update it so I’ve come up with my own command_line and template integration:

Add more template sensor/binary_sensor entries if you want to expand the sensor list - just pull the values from the sensor.twc_lifetime or sensor.twc_vitals sensor attributes as I have done with the mine.

The idea is that you dont want to be polling the endpoints separately for each value, but instead poll once to extract all the info into a single sensor w/attributes then split those out to separate sensors using template sensors.

sensor:
  - platform: command_line
    name: "TWC lifetime"
    unit_of_measurement: "kWh"
    json_attributes:
      - contactor_cycles
      - contactor_cycles_loaded
      - alert_count
      - thermal_foldbacks
      - charge_starts
      - connector_cycles
      - uptime_s
      - charging_time_s
      - energy_wh
    command: "curl -s 'http://192.168.4.22/api/1/lifetime' | sed 's/:nan/:NaN/g'"
    value_template: "{{ value_json.energy_wh | multiply(0.001) | round(1) }}"
  - platform: command_line
    name: "TWC vitals"
    unit_of_measurement: "A"
    json_attributes:
      - contactor_closed
      - vehicle_connected
      - session_s
      - grid_v
      - grid_hz
      - vehicle_current_a
      - currentA_a
      - currentB_a
      - currentC_a
      - currentN_a
      - voltageA_v
      - voltageB_v
      - voltageC_v
      - relay_coil_v
      - pcba_temp_c
      - handle_temp_c
      - mcu_temp_c
      - uptime_s
      - input_thermopile_uv
      - prox_v
      - pilot_high_v
      - pilot_low_v
      - session_energy_wh
      - config_status
      - evse_state
    command: "curl -s 'http://192.168.4.22/api/1/vitals' | sed 's/:nan/:NaN/g'"
    value_template: "{{ value_json.vehicle_current_a | round(1) }}"

  - platform: statistics
    entity_id: sensor.twc_lifetime

template:
  - sensor:
      - name: "TWC Delivery Current"
        unit_of_measurement: "A"
        device_class: current
        state: >
          {{ state_attr('sensor.twc_vitals', 'vehicle_current_a') }}
      - name: "TWC Delivery Power"
        unit_of_measurement: "kW"
        device_class: power
        state: >
          {{ (state_attr('sensor.twc_vitals', 'vehicle_current_a') * state_attr('sensor.twc_vitals', 'voltageA_v')) | multiply(0.001) | round(1) }}
      - name: "TWC Session kWh"
        unit_of_measurement: "kWh"
        device_class: energy
        state: >
          {{ state_attr('sensor.twc_vitals', 'session_energy_wh') | multiply(0.001) | round(1) }}
      - name: "TWC Handle Temperature"
        unit_of_measurement: "°C"
        device_class: temperature
        state: >
          {{ state_attr('sensor.twc_vitals', 'handle_temp_c') }}
      - name: "TWC MCU Temperature"
        unit_of_measurement: "°C"
        device_class: temperature
        state: >
          {{ state_attr('sensor.twc_vitals', 'mcu_temp_c') }}
      - name: "TWC PCBA Temperature"
        unit_of_measurement: "°C"
        device_class: temperature
        state: >
          {{ state_attr('sensor.twc_vitals', 'pcba_temp_c') }}

  - binary_sensor:
      - name: "TWC Vehicle Charging"
        device_class: battery_charging
        state: >
          {{ is_state_attr('sensor.twc_vitals', 'contactor_closed', true) }}
      - name: "TWC Vehicle Connected"
        device_class: connectivity
        state: >
          {{ is_state_attr('sensor.twc_vitals', 'vehicle_connected', true) }}



homeassistant:
  customize:
    sensor.twc_lifetime:
      device_class: energy
      state_class: total_increasing

Just to let people know on this thread that there is a Gen 3 integration coming with the 2021.12 release:

I tested it but it will no connect to my wall connector :frowning: I can access the web interface from my laptop and from HA.

image

Perhaps raise a bug report on GitHub?

Done Can add the Tesla Wall Connector but not able to get any data · Issue #61150 · home-assistant/core · GitHub

1 Like

This is a great integration so thanks for finding these API calls. One question I had though, is what do the numbers for ease_state mean? When my car is idle it seems to be 4, but when charging it seems to change from 1 to 11 to 9. Just curious if there is a mapping for what those numbers mean.

Thanks

3 Likes

I found out that a long press on the Tesla charging port button can enable the maintenance mode on gen 3 TWC (SSID advertisement and changing charging current is possible.
According to some teardown videos there are 4 thinner wires connected to charging port. One or more likely two wires are connected to the button. So it would be possible to install there some wireless relay to enable the maintenance mode one-the-fly. By default this would stop any Tesla charging for the time when button is pressed, but charge does resume immediately. Another option is to disable the actual button by leaving the wires unconnected.

Has anybody tried this yet?

Hi,
i tried the Lifetime api but the Wh values it returns are a bit strange. I made a simple test, used the Lifetime api before a charging session and again right after the charging is ready. The delta between these two Wh readings was aroun 120000 Wh, e.g. about 120 kWh. The actual energy charged was about 36 kWh based on the info from the car. Any idea what unit the claimed Wh provided by Lifetime is?

Can anyone advise on how to interpret this data? I’m surprised to see current & voltage for 3 phases, even though I am using standard US 240 split-phase power. All three are reporting current & voltage during charging. What’s the meaning of Phase A,B, and C?

I’d like to chart KW in use but am unclear which values I should be using.