From c980b81d2683c5601370ef20ff56fc96109b96eb Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Sun, 5 Jan 2025 14:03:32 +0000 Subject: [PATCH 01/75] Add polling entities --- mqtt-discovery.sh | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/mqtt-discovery.sh b/mqtt-discovery.sh index 5dbd583..9b5a5a9 100644 --- a/mqtt-discovery.sh +++ b/mqtt-discovery.sh @@ -281,6 +281,28 @@ function setupExtendedControls() { "unique_id": "'${DEVICE_ID}'_steering-wheel-heater" }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 6 10 -t homeassistant/switch/${DEVICE_ID}/steering-wheel-heater/config -l + echo '{ + "command_topic": "'${TOPIC_ROOT}'/polling", + "device": { + "identifiers": [ + "'${DEVICE_ID}'" + ], + "manufacturer": "tesla-local-control", + "model": "Tesla_BLE", + "name": "'${DEVICE_NAME}'", + "sw_version": "'${SW_VERSION}'" + }, + "icon": "mdi:car-connected", + "name": "State Polling", + "device_class": "switch", + "payload_on": "on", + "payload_off": "off", + "retain": "true", + "qos": "'${QOS_LEVEL}'", + "unique_id": "'${DEVICE_ID}'_polling", + "entity_category": "diagnostic", + }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 6 10 -t homeassistant/switch/${DEVICE_ID}/polling/config -l + # Covers echo '{ @@ -471,6 +493,30 @@ function setupExtendedControls() { }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 6 10 -t homeassistant/number/${DEVICE_ID}/climate-temp/config -l fi + echo '{ + "command_topic": "'${TOPIC_ROOT}'/polling_interval", + "device": { + "identifiers": [ + "'${DEVICE_ID}'" + ], + "manufacturer": "tesla-local-control", + "model": "Tesla_BLE", + "name": "'${DEVICE_NAME}'", + "sw_version": "'${SW_VERSION}'" + }, + "icon": "mdi:timer-sync", + "min": "1", + "max": "60", + "step": "1", + "mode": "slider", + "name": "Polling Interval", + "qos": "'${QOS_LEVEL}'", + "retain": "true", + "unique_id": "'${DEVICE_ID}'_polling_interval", + "entity_category": "diagnostic", + "unit_of_measurement": "mins" + }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 6 10 -t homeassistant/number/${DEVICE_ID}/polling_interval/config -l + # Selects echo '{ From 74c207c2942601dff480dbceb3570cc4dbe7264e Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Sun, 5 Jan 2025 14:48:58 +0000 Subject: [PATCH 02/75] Fix retain / QoS --- mqtt-discovery.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mqtt-discovery.sh b/mqtt-discovery.sh index 9b5a5a9..11a380f 100644 --- a/mqtt-discovery.sh +++ b/mqtt-discovery.sh @@ -298,9 +298,8 @@ function setupExtendedControls() { "payload_on": "on", "payload_off": "off", "retain": "true", - "qos": "'${QOS_LEVEL}'", "unique_id": "'${DEVICE_ID}'_polling", - "entity_category": "diagnostic", + "entity_category": "diagnostic" }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 6 10 -t homeassistant/switch/${DEVICE_ID}/polling/config -l # Covers @@ -510,7 +509,6 @@ function setupExtendedControls() { "step": "1", "mode": "slider", "name": "Polling Interval", - "qos": "'${QOS_LEVEL}'", "retain": "true", "unique_id": "'${DEVICE_ID}'_polling_interval", "entity_category": "diagnostic", From 1d6cabaa2a16035604b116d230fb6494c9f3e198 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Sun, 5 Jan 2025 15:20:46 +0000 Subject: [PATCH 03/75] Move Polling internal to environment --- env.sh | 4 +++- mqtt-discovery.sh | 23 ----------------------- read-state.sh | 1 + 3 files changed, 4 insertions(+), 24 deletions(-) diff --git a/env.sh b/env.sh index 70243cc..1e0b573 100755 --- a/env.sh +++ b/env.sh @@ -35,6 +35,7 @@ export PRESENCE_DETECTION_LOOP_DELAY=${PRESENCE_DETECTION_LOOP_DELAY:-120} export PRESENCE_DETECTION_TTL=${PRESENCE_DETECTION_TTL:-240} export TEMPERATURE_UNIT_FAHRENHEIT=${TEMPERATURE_UNIT_FAHRENHEIT:-false} export MAX_CURRENT=${MAX_CURRENT:-48} +export POLLING_INTERVAL=${POLLING_INTERVAL:-11} export BLE_LN_REGEX='S[0-9A-Fa-f]{16}C' export BLTCTL_COMMAND_DEVICES=false @@ -54,7 +55,8 @@ log_info "Configuration Options are: PRESENCE_DETECTION_TTL=$PRESENCE_DETECTION_TTL TEMPERATURE_UNIT_FAHRENHEIT=$TEMPERATURE_UNIT_FAHRENHEIT VIN_LIST=$VIN_LIST - MAX_CURRENT=$MAX_CURRENT" + MAX_CURRENT=$MAX_CURRENT + POLLING_INTERVAL=$POLLING_INTERVAL" [ -n "$ENABLE_HA_FEATURES" ] && log_info " ENABLE_HA_FEATURES=$ENABLE_HA_FEATURES" [ -n "$BLECTL_FILE_INPUT" ] && log_info " BLECTL_FILE_INPUT=$BLECTL_FILE_INPUT" diff --git a/mqtt-discovery.sh b/mqtt-discovery.sh index 11a380f..0e47071 100644 --- a/mqtt-discovery.sh +++ b/mqtt-discovery.sh @@ -492,29 +492,6 @@ function setupExtendedControls() { }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 6 10 -t homeassistant/number/${DEVICE_ID}/climate-temp/config -l fi - echo '{ - "command_topic": "'${TOPIC_ROOT}'/polling_interval", - "device": { - "identifiers": [ - "'${DEVICE_ID}'" - ], - "manufacturer": "tesla-local-control", - "model": "Tesla_BLE", - "name": "'${DEVICE_NAME}'", - "sw_version": "'${SW_VERSION}'" - }, - "icon": "mdi:timer-sync", - "min": "1", - "max": "60", - "step": "1", - "mode": "slider", - "name": "Polling Interval", - "retain": "true", - "unique_id": "'${DEVICE_ID}'_polling_interval", - "entity_category": "diagnostic", - "unit_of_measurement": "mins" - }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 6 10 -t homeassistant/number/${DEVICE_ID}/polling_interval/config -l - # Selects echo '{ diff --git a/read-state.sh b/read-state.sh index 7421726..63625a8 100644 --- a/read-state.sh +++ b/read-state.sh @@ -8,6 +8,7 @@ function poll_state_loop() { log_notice "Entering poll_state_loop..." + sleep 30 } From 9e2c6067e931b224577bae3c73ab0336a043c389 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Sun, 5 Jan 2025 15:45:25 +0000 Subject: [PATCH 04/75] Put polling interval back to MQTT --- env.sh | 2 -- mqtt-discovery.sh | 22 ++++++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/env.sh b/env.sh index 1e0b573..ba52764 100755 --- a/env.sh +++ b/env.sh @@ -35,7 +35,6 @@ export PRESENCE_DETECTION_LOOP_DELAY=${PRESENCE_DETECTION_LOOP_DELAY:-120} export PRESENCE_DETECTION_TTL=${PRESENCE_DETECTION_TTL:-240} export TEMPERATURE_UNIT_FAHRENHEIT=${TEMPERATURE_UNIT_FAHRENHEIT:-false} export MAX_CURRENT=${MAX_CURRENT:-48} -export POLLING_INTERVAL=${POLLING_INTERVAL:-11} export BLE_LN_REGEX='S[0-9A-Fa-f]{16}C' export BLTCTL_COMMAND_DEVICES=false @@ -56,7 +55,6 @@ log_info "Configuration Options are: TEMPERATURE_UNIT_FAHRENHEIT=$TEMPERATURE_UNIT_FAHRENHEIT VIN_LIST=$VIN_LIST MAX_CURRENT=$MAX_CURRENT - POLLING_INTERVAL=$POLLING_INTERVAL" [ -n "$ENABLE_HA_FEATURES" ] && log_info " ENABLE_HA_FEATURES=$ENABLE_HA_FEATURES" [ -n "$BLECTL_FILE_INPUT" ] && log_info " BLECTL_FILE_INPUT=$BLECTL_FILE_INPUT" diff --git a/mqtt-discovery.sh b/mqtt-discovery.sh index 0e47071..cac1f99 100644 --- a/mqtt-discovery.sh +++ b/mqtt-discovery.sh @@ -491,6 +491,28 @@ function setupExtendedControls() { "unique_id": "'${DEVICE_ID}'_climate-set-temp" }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 6 10 -t homeassistant/number/${DEVICE_ID}/climate-temp/config -l fi + echo '{ + "command_topic": "'${TOPIC_ROOT}'/polling_interval", + "device": { + "identifiers": [ + "'${DEVICE_ID}'" + ], + "manufacturer": "tesla-local-control", + "model": "Tesla_BLE", + "name": "'${DEVICE_NAME}'", + "sw_version": "'${SW_VERSION}'" + }, + "icon": "mdi:timer-sync", + "min": "1", + "max": "60", + "step": "1", + "mode": "slider", + "name": "Polling Interval", + "retain": "true", + "unique_id": "'${DEVICE_ID}'_polling_interval", + "entity_category": "diagnostic", + "unit_of_measurement": "mins" + }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 6 10 -t homeassistant/number/${DEVICE_ID}/polling_interval/config -l # Selects From bf4d0acf7b7c9613c860175e7aedd4abaf44a404 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Sun, 5 Jan 2025 15:55:15 +0000 Subject: [PATCH 05/75] Loop thru VINs --- CHANGELOG.md | 10 ++++++++++ read-state.sh | 9 ++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e5d6b25..1169e30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## 0.4.0 + +- RELEASE NEW Feature: Automatic Polling is now possible for state + +- NEW Feature: The following new states / entities are added: + - Switches: State Polling + - Numbers: Polling Interval + +- Fixes: + ## 0.3.1 - NEW Feature: The following new states / entities are added: diff --git a/read-state.sh b/read-state.sh index 63625a8..14cfd20 100644 --- a/read-state.sh +++ b/read-state.sh @@ -7,9 +7,16 @@ ## function poll_state_loop. For future implementation function poll_state_loop() { log_notice "Entering poll_state_loop..." + + # Replace | with ' ' white space + VIN_LIST=$(echo $VIN_LIST | sed -e 's/[|,;]/ /g') + # Loop through each VIN + for vin in $VIN_LIST; do + echo VIN: $vin + done - sleep 30 + sleep 60 } function stateMQTTpub() { From e3a1364bc0e47766cc2dba5648292c6b2e59afff Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Sun, 5 Jan 2025 16:00:32 +0000 Subject: [PATCH 06/75] Fix typo --- env.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/env.sh b/env.sh index ba52764..70243cc 100755 --- a/env.sh +++ b/env.sh @@ -54,7 +54,7 @@ log_info "Configuration Options are: PRESENCE_DETECTION_TTL=$PRESENCE_DETECTION_TTL TEMPERATURE_UNIT_FAHRENHEIT=$TEMPERATURE_UNIT_FAHRENHEIT VIN_LIST=$VIN_LIST - MAX_CURRENT=$MAX_CURRENT + MAX_CURRENT=$MAX_CURRENT" [ -n "$ENABLE_HA_FEATURES" ] && log_info " ENABLE_HA_FEATURES=$ENABLE_HA_FEATURES" [ -n "$BLECTL_FILE_INPUT" ] && log_info " BLECTL_FILE_INPUT=$BLECTL_FILE_INPUT" From f643f1df5bc832873b31c71e73afd1b3fab21d7b Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Sun, 5 Jan 2025 16:49:50 +0000 Subject: [PATCH 07/75] Update variables from MQTT --- mqtt-listen.sh | 10 ++++++++++ read-state.sh | 6 ++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/mqtt-listen.sh b/mqtt-listen.sh index 05063df..d91687d 100755 --- a/mqtt-listen.sh +++ b/mqtt-listen.sh @@ -216,6 +216,16 @@ listen_to_mqtt() { teslaCtrlSendCommand $vin "$cmd-$msg" "Set $cmd mode to $msg" ;; + polling) + log_notice "Updating variable $cmd=$msg for $vin" + export $vin_$cmd=$msg + ;; + + polling_interval) + log_notice "Updating variable $cmd=$msg for $vin" + export $vin_$cmd=$msg + ;; + *) log_error "Invalid request; topic:$topic vin:$vin msg:$msg" ;; diff --git a/read-state.sh b/read-state.sh index 14cfd20..c38316b 100644 --- a/read-state.sh +++ b/read-state.sh @@ -11,9 +11,11 @@ function poll_state_loop() { # Replace | with ' ' white space VIN_LIST=$(echo $VIN_LIST | sed -e 's/[|,;]/ /g') - # Loop through each VIN + # Loop through each VIN to initialise safe defaults + # These will get updated with actual values when MQTT reads the relevent retained messages for vin in $VIN_LIST; do - echo VIN: $vin + export $vin_POLLING=false + export $vin_POLLING_INTERVAL=11 done sleep 60 From 7c3779dec9effbb8f797399d98eb924b6aefa882 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Sun, 5 Jan 2025 17:03:36 +0000 Subject: [PATCH 08/75] Fix polling variables --- read-state.sh | 4 ++-- run.sh | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/read-state.sh b/read-state.sh index c38316b..8c27457 100644 --- a/read-state.sh +++ b/read-state.sh @@ -14,8 +14,8 @@ function poll_state_loop() { # Loop through each VIN to initialise safe defaults # These will get updated with actual values when MQTT reads the relevent retained messages for vin in $VIN_LIST; do - export $vin_POLLING=false - export $vin_POLLING_INTERVAL=11 + export ${vin}_polling=false + export ${vin}_polling_interval=11 done sleep 60 diff --git a/run.sh b/run.sh index 74614f9..5b91691 100755 --- a/run.sh +++ b/run.sh @@ -99,13 +99,14 @@ fi log_info "Entering main loop..." while :; do - # Launch listen_to_mqtt_loop in background - log_notice "main loop; Launching background listen_to_mqtt_loop..." - listen_to_mqtt_loop & # Launch poll_state_loop in background log_notice "main loop; Launching background poll_state_loop..." poll_state_loop & + + # Launch listen_to_mqtt_loop in background + log_notice "main loop; Launching background listen_to_mqtt_loop..." + listen_to_mqtt_loop & # Don't run presence detection if TTL is 0 # If PRESENCE_DETECTION_TTL > 0 and BLE_MAC_LIST is not empty From 870d7dadafbb4f71c9629e33ba3a0693ca2c9a63 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Sun, 5 Jan 2025 17:32:47 +0000 Subject: [PATCH 09/75] Give polling a state topic --- mqtt-discovery.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mqtt-discovery.sh b/mqtt-discovery.sh index cac1f99..9a45322 100644 --- a/mqtt-discovery.sh +++ b/mqtt-discovery.sh @@ -283,6 +283,7 @@ function setupExtendedControls() { echo '{ "command_topic": "'${TOPIC_ROOT}'/polling", + "state_topic": "'${TOPIC_ROOT}'/polling", "device": { "identifiers": [ "'${DEVICE_ID}'" @@ -297,6 +298,8 @@ function setupExtendedControls() { "device_class": "switch", "payload_on": "on", "payload_off": "off", + "state_on": "on", + "state_off": "off", "retain": "true", "unique_id": "'${DEVICE_ID}'_polling", "entity_category": "diagnostic" From 034fc79449b154c952e27b32bfb7d56a3e24a4ce Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Sun, 5 Jan 2025 17:36:11 +0000 Subject: [PATCH 10/75] Test loop for polling --- read-state.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/read-state.sh b/read-state.sh index 8c27457..a94d382 100644 --- a/read-state.sh +++ b/read-state.sh @@ -18,7 +18,11 @@ function poll_state_loop() { export ${vin}_polling_interval=11 done - sleep 60 + while :; do + sleep 60 + echo Polling ${vin}_polling + echo Intevnal ${vin}_polling_interval + done } function stateMQTTpub() { From 7581badedcf2b0b835fa494bc30954852b422a5b Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Sun, 5 Jan 2025 18:20:38 +0000 Subject: [PATCH 11/75] Fix the polling globals --- mqtt-listen.sh | 8 ++++---- read-state.sh | 14 ++------------ run.sh | 5 +++++ 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/mqtt-listen.sh b/mqtt-listen.sh index d91687d..fd986d4 100755 --- a/mqtt-listen.sh +++ b/mqtt-listen.sh @@ -217,13 +217,13 @@ listen_to_mqtt() { ;; polling) - log_notice "Updating variable $cmd=$msg for $vin" - export $vin_$cmd=$msg + log_notice "Updating variable ${vin}_${cmd}=$msg" + export ${vin}_${cmd}=$msg ;; polling_interval) - log_notice "Updating variable $cmd=$msg for $vin" - export $vin_$cmd=$msg + log_notice "Updating variable ${vin}_${cmd}=$msg" + export ${vin}_${cmd}=$msg ;; *) diff --git a/read-state.sh b/read-state.sh index a94d382..ba03cb9 100644 --- a/read-state.sh +++ b/read-state.sh @@ -7,21 +7,11 @@ ## function poll_state_loop. For future implementation function poll_state_loop() { log_notice "Entering poll_state_loop..." - - # Replace | with ' ' white space - VIN_LIST=$(echo $VIN_LIST | sed -e 's/[|,;]/ /g') - - # Loop through each VIN to initialise safe defaults - # These will get updated with actual values when MQTT reads the relevent retained messages - for vin in $VIN_LIST; do - export ${vin}_polling=false - export ${vin}_polling_interval=11 - done while :; do sleep 60 - echo Polling ${vin}_polling - echo Intevnal ${vin}_polling_interval + echo Polling ${${vin}_polling} + echo Interval ${${vin}_polling_interval} done } diff --git a/run.sh b/run.sh index 5b91691..46d08ca 100755 --- a/run.sh +++ b/run.sh @@ -14,6 +14,11 @@ VIN_LIST=$(echo $VIN_LIST | sed -e 's/[|,;]/ /g') vin_count=0 for vin in $VIN_LIST; do + + # Set defaults for MQTT derived global variables + export ${vin}_polling=false + export ${vin}_polling_interval=12 + # Populate BLE Local Names list vin_count=$((vin_count + 1)) BLE_LN=$(vinToBLEln $vin) From b71207e79ecd2a2c6e10e13b123b93dc862dd13d Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Mon, 6 Jan 2025 09:21:59 +0000 Subject: [PATCH 12/75] Use eval and global vars --- env.sh | 2 -- mqtt-listen.sh | 8 ++++++-- read-state.sh | 9 +++++++-- run.sh | 3 +++ 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/env.sh b/env.sh index 70243cc..8bc74ae 100755 --- a/env.sh +++ b/env.sh @@ -10,10 +10,8 @@ log_debug "Loading environment & functions..." for fSource in mqtt.sh \ mqtt-discovery.sh \ mqtt-discovery-sensors.sh \ - mqtt-listen.sh \ subroutines.sh \ tesla-commands.sh \ - read-state.sh \ version.sh; do if [ -f /app/$fSource ]; then diff --git a/mqtt-listen.sh b/mqtt-listen.sh index fd986d4..58f1dd4 100755 --- a/mqtt-listen.sh +++ b/mqtt-listen.sh @@ -218,12 +218,16 @@ listen_to_mqtt() { polling) log_notice "Updating variable ${vin}_${cmd}=$msg" - export ${vin}_${cmd}=$msg + # Dynamic variables in ash need to use eval + eval "$(echo ${vin}_${cmd})=$msg" + echo Now LRW3F7FS5RC036403_polling ;; polling_interval) log_notice "Updating variable ${vin}_${cmd}=$msg" - export ${vin}_${cmd}=$msg + # Dynamic variables in ash need to use eval + eval "$(echo ${vin}_${cmd})=$msg" + echo Now LRW3F7FS5RC036403_polling_interval ;; *) diff --git a/read-state.sh b/read-state.sh index ba03cb9..1bc80b6 100644 --- a/read-state.sh +++ b/read-state.sh @@ -10,8 +10,13 @@ function poll_state_loop() { while :; do sleep 60 - echo Polling ${${vin}_polling} - echo Interval ${${vin}_polling_interval} + + # Dynamic variables in ash need to use eval + eval "p=\$$(echo ${vin}_polling)" + eval "pi=\$$(echo ${vin}_polling_interval)" + echo Polling $p + echo Interval $pi + done } diff --git a/run.sh b/run.sh index 46d08ca..90cd446 100755 --- a/run.sh +++ b/run.sh @@ -88,6 +88,9 @@ log_debug "BLE_LN_LIST:$BLE_LN_LIST" log_debug "BLE_MAC_LIST:$BLE_MAC_LIST" log_debug "PRESENCE_EXPIRE_TIME_LIST:$PRESENCE_EXPIRE_TIME_LIST" +. /app/mqtt-listen.sh +. /app/read-state.sh + # Setup HA auto discovery, or skip if HA backend is disable and discard old /config MQTT messages setupHADiscoveryAllVINsMain From fc851dffd4fb6d85cd75b55dfcbef20a901e3873 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Mon, 6 Jan 2025 09:47:52 +0000 Subject: [PATCH 13/75] Global variable attempted fix --- env.sh | 2 ++ mqtt-listen.sh | 9 +++++++-- run.sh | 7 ++----- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/env.sh b/env.sh index 8bc74ae..70243cc 100755 --- a/env.sh +++ b/env.sh @@ -10,8 +10,10 @@ log_debug "Loading environment & functions..." for fSource in mqtt.sh \ mqtt-discovery.sh \ mqtt-discovery-sensors.sh \ + mqtt-listen.sh \ subroutines.sh \ tesla-commands.sh \ + read-state.sh \ version.sh; do if [ -f /app/$fSource ]; then diff --git a/mqtt-listen.sh b/mqtt-listen.sh index 58f1dd4..454068d 100755 --- a/mqtt-listen.sh +++ b/mqtt-listen.sh @@ -25,6 +25,11 @@ listen_to_mqtt_loop() { } listen_to_mqtt() { + + # Launch poll_state_loop in background. Needs to be invoked here so we can change global variables + log_notice "main loop; Launching background poll_state_loop..." + poll_state_loop & + log_info "Listening to MQTT" eval $MOSQUITTO_SUB_BASE --nodelay --disable-clean-session --qos 1 --topic tesla_ble/+/+ -F \"%t %p\" --id tesla_ble_mqtt | while read -r payload; do @@ -220,14 +225,14 @@ listen_to_mqtt() { log_notice "Updating variable ${vin}_${cmd}=$msg" # Dynamic variables in ash need to use eval eval "$(echo ${vin}_${cmd})=$msg" - echo Now LRW3F7FS5RC036403_polling + echo Now $LRW3F7FS5RC036403_polling ;; polling_interval) log_notice "Updating variable ${vin}_${cmd}=$msg" # Dynamic variables in ash need to use eval eval "$(echo ${vin}_${cmd})=$msg" - echo Now LRW3F7FS5RC036403_polling_interval + echo Now $LRW3F7FS5RC036403_polling_interval ;; *) diff --git a/run.sh b/run.sh index 90cd446..4cd3fb8 100755 --- a/run.sh +++ b/run.sh @@ -88,9 +88,6 @@ log_debug "BLE_LN_LIST:$BLE_LN_LIST" log_debug "BLE_MAC_LIST:$BLE_MAC_LIST" log_debug "PRESENCE_EXPIRE_TIME_LIST:$PRESENCE_EXPIRE_TIME_LIST" -. /app/mqtt-listen.sh -. /app/read-state.sh - # Setup HA auto discovery, or skip if HA backend is disable and discard old /config MQTT messages setupHADiscoveryAllVINsMain @@ -109,8 +106,8 @@ while :; do # Launch poll_state_loop in background - log_notice "main loop; Launching background poll_state_loop..." - poll_state_loop & + #log_notice "main loop; Launching background poll_state_loop..." + #poll_state_loop & # Launch listen_to_mqtt_loop in background log_notice "main loop; Launching background listen_to_mqtt_loop..." From b2be55d01946d9aa4e92f74b7d2739a6d250cc27 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Mon, 6 Jan 2025 09:57:12 +0000 Subject: [PATCH 14/75] Abandon using global vars --- mqtt-discovery.sh | 6 +++--- mqtt-listen.sh | 20 ++++++-------------- read-state.sh | 8 ++++---- run.sh | 9 ++++----- 4 files changed, 17 insertions(+), 26 deletions(-) diff --git a/mqtt-discovery.sh b/mqtt-discovery.sh index 9a45322..f4aef6f 100644 --- a/mqtt-discovery.sh +++ b/mqtt-discovery.sh @@ -282,8 +282,8 @@ function setupExtendedControls() { }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 6 10 -t homeassistant/switch/${DEVICE_ID}/steering-wheel-heater/config -l echo '{ - "command_topic": "'${TOPIC_ROOT}'/polling", - "state_topic": "'${TOPIC_ROOT}'/polling", + "command_topic": "'${TOPIC_ROOT}'/global_vars/polling", + "state_topic": "'${TOPIC_ROOT}'/global_vars/polling", "device": { "identifiers": [ "'${DEVICE_ID}'" @@ -495,7 +495,7 @@ function setupExtendedControls() { }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 6 10 -t homeassistant/number/${DEVICE_ID}/climate-temp/config -l fi echo '{ - "command_topic": "'${TOPIC_ROOT}'/polling_interval", + "command_topic": "'${TOPIC_ROOT}'/global_vars/polling_interval", "device": { "identifiers": [ "'${DEVICE_ID}'" diff --git a/mqtt-listen.sh b/mqtt-listen.sh index 454068d..1fa4b7f 100755 --- a/mqtt-listen.sh +++ b/mqtt-listen.sh @@ -24,12 +24,7 @@ listen_to_mqtt_loop() { } -listen_to_mqtt() { - - # Launch poll_state_loop in background. Needs to be invoked here so we can change global variables - log_notice "main loop; Launching background poll_state_loop..." - poll_state_loop & - +listen_to_mqtt() { log_info "Listening to MQTT" eval $MOSQUITTO_SUB_BASE --nodelay --disable-clean-session --qos 1 --topic tesla_ble/+/+ -F \"%t %p\" --id tesla_ble_mqtt | while read -r payload; do @@ -221,18 +216,15 @@ listen_to_mqtt() { teslaCtrlSendCommand $vin "$cmd-$msg" "Set $cmd mode to $msg" ;; - polling) - log_notice "Updating variable ${vin}_${cmd}=$msg" - # Dynamic variables in ash need to use eval - eval "$(echo ${vin}_${cmd})=$msg" - echo Now $LRW3F7FS5RC036403_polling + global_vars) + # These get handled in the subshell where they are used ;; polling_interval) - log_notice "Updating variable ${vin}_${cmd}=$msg" + #log_notice "Updating variable ${vin}_${cmd}=$msg" # Dynamic variables in ash need to use eval - eval "$(echo ${vin}_${cmd})=$msg" - echo Now $LRW3F7FS5RC036403_polling_interval + #eval "$(echo ${vin}_${cmd})=$msg" + #echo Now $LRW3F7FS5RC036403_polling_interval ;; *) diff --git a/read-state.sh b/read-state.sh index 1bc80b6..41d8af2 100644 --- a/read-state.sh +++ b/read-state.sh @@ -12,10 +12,10 @@ function poll_state_loop() { sleep 60 # Dynamic variables in ash need to use eval - eval "p=\$$(echo ${vin}_polling)" - eval "pi=\$$(echo ${vin}_polling_interval)" - echo Polling $p - echo Interval $pi + #eval "p=\$$(echo ${vin}_polling)" + #eval "pi=\$$(echo ${vin}_polling_interval)" + #echo Polling $p + #echo Interval $pi done } diff --git a/run.sh b/run.sh index 4cd3fb8..9736abf 100755 --- a/run.sh +++ b/run.sh @@ -104,15 +104,14 @@ fi log_info "Entering main loop..." while :; do - - # Launch poll_state_loop in background - #log_notice "main loop; Launching background poll_state_loop..." - #poll_state_loop & - # Launch listen_to_mqtt_loop in background log_notice "main loop; Launching background listen_to_mqtt_loop..." listen_to_mqtt_loop & + # Launch poll_state_loop in background + log_notice "main loop; Launching background poll_state_loop..." + poll_state_loop & + # Don't run presence detection if TTL is 0 # If PRESENCE_DETECTION_TTL > 0 and BLE_MAC_LIST is not empty if [ $PRESENCE_DETECTION_TTL -gt 0 ]; then From 15ef82bc85fd0788c96062eb51fc0cf368606c2b Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Mon, 6 Jan 2025 10:13:38 +0000 Subject: [PATCH 15/75] test g_vars from MQTT --- read-state.sh | 2 +- subroutines.sh | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/read-state.sh b/read-state.sh index 41d8af2..2a6e627 100644 --- a/read-state.sh +++ b/read-state.sh @@ -16,7 +16,7 @@ function poll_state_loop() { #eval "pi=\$$(echo ${vin}_polling_interval)" #echo Polling $p #echo Interval $pi - + globalVarsfromMQTT done } diff --git a/subroutines.sh b/subroutines.sh index 575e3b9..5382054 100755 --- a/subroutines.sh +++ b/subroutines.sh @@ -223,3 +223,17 @@ infoBluetoothAdapter() { fi } + +# Gets global variable values from MQTT +get globalVarsfromMQTT(){ +eval $MOSQUITTO_SUB_BASE --nodelay --topic tesla_ble/+/global_vars/+ -F \"%t %p\" | + while read -r payload; do + topic=${payload%% *} + msg=${payload#* } + topic_stripped=${topic#*/} + vin=${topic_stripped%/*} + cmd=${topic_stripped#*/} + log_info "Received global variable from MQTT; topic:$topic msg:$msg vin:$vin cmd:$cmd" + done + +} \ No newline at end of file From 1f6d3ec33c5bffbaffd637eeda35f1350d5495d4 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Mon, 6 Jan 2025 10:18:02 +0000 Subject: [PATCH 16/75] MQTT timeout --- subroutines.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subroutines.sh b/subroutines.sh index 5382054..6c5f099 100755 --- a/subroutines.sh +++ b/subroutines.sh @@ -226,7 +226,7 @@ infoBluetoothAdapter() { # Gets global variable values from MQTT get globalVarsfromMQTT(){ -eval $MOSQUITTO_SUB_BASE --nodelay --topic tesla_ble/+/global_vars/+ -F \"%t %p\" | +eval $MOSQUITTO_SUB_BASE --nodelay -W 1 --topic tesla_ble/+/global_vars/+ -F \"%t %p\" | while read -r payload; do topic=${payload%% *} msg=${payload#* } From dc7dd66ca415866744f4fa4922c3447028e1ab3c Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Mon, 6 Jan 2025 10:20:18 +0000 Subject: [PATCH 17/75] Fix comma --- subroutines.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subroutines.sh b/subroutines.sh index 6c5f099..acb8cfd 100755 --- a/subroutines.sh +++ b/subroutines.sh @@ -225,7 +225,7 @@ infoBluetoothAdapter() { } # Gets global variable values from MQTT -get globalVarsfromMQTT(){ +globalVarsfromMQTT() { eval $MOSQUITTO_SUB_BASE --nodelay -W 1 --topic tesla_ble/+/global_vars/+ -F \"%t %p\" | while read -r payload; do topic=${payload%% *} From ced1aac44355b166a6f2092fd3c92f22a1c8c0c6 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Mon, 6 Jan 2025 10:40:19 +0000 Subject: [PATCH 18/75] Mod param extensions --- subroutines.sh | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/subroutines.sh b/subroutines.sh index acb8cfd..69a8ff5 100755 --- a/subroutines.sh +++ b/subroutines.sh @@ -229,11 +229,14 @@ globalVarsfromMQTT() { eval $MOSQUITTO_SUB_BASE --nodelay -W 1 --topic tesla_ble/+/global_vars/+ -F \"%t %p\" | while read -r payload; do topic=${payload%% *} - msg=${payload#* } + val=${payload#* } topic_stripped=${topic#*/} - vin=${topic_stripped%/*} - cmd=${topic_stripped#*/} - log_info "Received global variable from MQTT; topic:$topic msg:$msg vin:$vin cmd:$cmd" - done + vin=${topic_stripped%%/*} + var=${topic##*/} + log_info "Received global variable from MQTT; topic:$topic msg:$val vin:$vin cmd:$var" -} \ No newline at end of file + # Set global variable. Note Dynamic variables in ash need to use eval + eval "$(echo ${vin}_${var})=$val" + echo Now $LRW3F7FS5RC036403_polling_interval + done +} From ff21a16e97fa8bd40284f6e19f15de84109d704e Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Mon, 6 Jan 2025 11:50:00 +0000 Subject: [PATCH 19/75] Read globals without function --- mqtt-listen.sh | 7 ------- read-state.sh | 25 +++++++++++++++++++------ subroutines.sh | 6 +++--- 3 files changed, 22 insertions(+), 16 deletions(-) diff --git a/mqtt-listen.sh b/mqtt-listen.sh index 1fa4b7f..c2541cd 100755 --- a/mqtt-listen.sh +++ b/mqtt-listen.sh @@ -220,13 +220,6 @@ listen_to_mqtt() { # These get handled in the subshell where they are used ;; - polling_interval) - #log_notice "Updating variable ${vin}_${cmd}=$msg" - # Dynamic variables in ash need to use eval - #eval "$(echo ${vin}_${cmd})=$msg" - #echo Now $LRW3F7FS5RC036403_polling_interval - ;; - *) log_error "Invalid request; topic:$topic vin:$vin msg:$msg" ;; diff --git a/read-state.sh b/read-state.sh index 2a6e627..dd9c1c2 100644 --- a/read-state.sh +++ b/read-state.sh @@ -10,13 +10,26 @@ function poll_state_loop() { while :; do sleep 60 - + + eval $MOSQUITTO_SUB_BASE --nodelay -W 1 --topic tesla_ble/+/global_vars/+ -F \"%t %p\" 2>/dev/null | + while read -r payload; do + topic=${payload%% *} + val=${payload#* } + topic_stripped=${topic#*/} + vin=${topic_stripped%%/*} + var=${topic##*/} + log_info "Received global variable from MQTT; topic:$topic msg:$val vin:$vin cmd:$var" + + # Set global variable. Note Dynamic variables in ash need to use eval + eval "export $(echo ${vin}_${var})=$val" + done + # Dynamic variables in ash need to use eval - #eval "p=\$$(echo ${vin}_polling)" - #eval "pi=\$$(echo ${vin}_polling_interval)" - #echo Polling $p - #echo Interval $pi - globalVarsfromMQTT + eval "p=\$$(echo ${vin}_polling)" + eval "pi=\$$(echo ${vin}_polling_interval)" + echo Polling $p + echo Interval $pi + done } diff --git a/subroutines.sh b/subroutines.sh index 69a8ff5..006f4cd 100755 --- a/subroutines.sh +++ b/subroutines.sh @@ -226,7 +226,7 @@ infoBluetoothAdapter() { # Gets global variable values from MQTT globalVarsfromMQTT() { -eval $MOSQUITTO_SUB_BASE --nodelay -W 1 --topic tesla_ble/+/global_vars/+ -F \"%t %p\" | +eval $MOSQUITTO_SUB_BASE --nodelay -W 1 --topic tesla_ble/+/global_vars/+ -F \"%t %p\" 2>/dev/null | while read -r payload; do topic=${payload%% *} val=${payload#* } @@ -236,7 +236,7 @@ eval $MOSQUITTO_SUB_BASE --nodelay -W 1 --topic tesla_ble/+/global_vars/+ -F \"% log_info "Received global variable from MQTT; topic:$topic msg:$val vin:$vin cmd:$var" # Set global variable. Note Dynamic variables in ash need to use eval - eval "$(echo ${vin}_${var})=$val" - echo Now $LRW3F7FS5RC036403_polling_interval + eval "export $(echo ${vin}_${var})=$val" + done } From 9bdc638f13dc31fe930093610c76c5f7ecb932b4 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Mon, 6 Jan 2025 19:42:14 +0000 Subject: [PATCH 20/75] Use for instead of while --- read-state.sh | 32 +++++++++++++------------------- subroutines.sh | 17 ----------------- 2 files changed, 13 insertions(+), 36 deletions(-) diff --git a/read-state.sh b/read-state.sh index dd9c1c2..68786ac 100644 --- a/read-state.sh +++ b/read-state.sh @@ -9,27 +9,21 @@ function poll_state_loop() { log_notice "Entering poll_state_loop..." while :; do + vin=LRW3F7FS5RC036403 sleep 60 - eval $MOSQUITTO_SUB_BASE --nodelay -W 1 --topic tesla_ble/+/global_vars/+ -F \"%t %p\" 2>/dev/null | - while read -r payload; do - topic=${payload%% *} - val=${payload#* } - topic_stripped=${topic#*/} - vin=${topic_stripped%%/*} - var=${topic##*/} - log_info "Received global variable from MQTT; topic:$topic msg:$val vin:$vin cmd:$var" - - # Set global variable. Note Dynamic variables in ash need to use eval - eval "export $(echo ${vin}_${var})=$val" - done - - # Dynamic variables in ash need to use eval - eval "p=\$$(echo ${vin}_polling)" - eval "pi=\$$(echo ${vin}_polling_interval)" - echo Polling $p - echo Interval $pi - + mqttOp=$( eval $MOSQUITTO_SUB_BASE --nodelay -W 1 --topic tesla_ble/$vin/global_vars/+ -F \"%t=%p\" + EXIT_CODE=$? + if [ $EXIT_CODE -eq 27 ]; then + for item in $mqttOp; do + assign=${item##*/} + echo $assign + eval export ${vin}_$assign + done + fi + + echo $LRW3F7FS5RC036403_polling + echo $LRW3F7FS5RC036403_polling_interval done } diff --git a/subroutines.sh b/subroutines.sh index 006f4cd..575e3b9 100755 --- a/subroutines.sh +++ b/subroutines.sh @@ -223,20 +223,3 @@ infoBluetoothAdapter() { fi } - -# Gets global variable values from MQTT -globalVarsfromMQTT() { -eval $MOSQUITTO_SUB_BASE --nodelay -W 1 --topic tesla_ble/+/global_vars/+ -F \"%t %p\" 2>/dev/null | - while read -r payload; do - topic=${payload%% *} - val=${payload#* } - topic_stripped=${topic#*/} - vin=${topic_stripped%%/*} - var=${topic##*/} - log_info "Received global variable from MQTT; topic:$topic msg:$val vin:$vin cmd:$var" - - # Set global variable. Note Dynamic variables in ash need to use eval - eval "export $(echo ${vin}_${var})=$val" - - done -} From a4ee4a0e061c322dfa0b9e81f60045de48bde203 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Mon, 6 Jan 2025 19:46:42 +0000 Subject: [PATCH 21/75] Fix missing ) --- read-state.sh | 5 +++-- run.sh | 5 ----- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/read-state.sh b/read-state.sh index 68786ac..b39d5fc 100644 --- a/read-state.sh +++ b/read-state.sh @@ -12,8 +12,9 @@ function poll_state_loop() { vin=LRW3F7FS5RC036403 sleep 60 - mqttOp=$( eval $MOSQUITTO_SUB_BASE --nodelay -W 1 --topic tesla_ble/$vin/global_vars/+ -F \"%t=%p\" + mqttOp=$( eval $MOSQUITTO_SUB_BASE --nodelay -W 1 --topic tesla_ble/$vin/global_vars/+ -F \"%t=%p\" 2>/dev/null ) EXIT_CODE=$? + if [ $EXIT_CODE -eq 27 ]; then for item in $mqttOp; do assign=${item##*/} @@ -21,7 +22,7 @@ function poll_state_loop() { eval export ${vin}_$assign done fi - + echo $LRW3F7FS5RC036403_polling echo $LRW3F7FS5RC036403_polling_interval done diff --git a/run.sh b/run.sh index 9736abf..58feb37 100755 --- a/run.sh +++ b/run.sh @@ -14,11 +14,6 @@ VIN_LIST=$(echo $VIN_LIST | sed -e 's/[|,;]/ /g') vin_count=0 for vin in $VIN_LIST; do - - # Set defaults for MQTT derived global variables - export ${vin}_polling=false - export ${vin}_polling_interval=12 - # Populate BLE Local Names list vin_count=$((vin_count + 1)) BLE_LN=$(vinToBLEln $vin) From 790cfff32c25e594a5d457732ef56e5f4b97313c Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Mon, 6 Jan 2025 20:35:34 +0000 Subject: [PATCH 22/75] set +e --- read-state.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/read-state.sh b/read-state.sh index b39d5fc..8976263 100644 --- a/read-state.sh +++ b/read-state.sh @@ -12,9 +12,10 @@ function poll_state_loop() { vin=LRW3F7FS5RC036403 sleep 60 + set +e mqttOp=$( eval $MOSQUITTO_SUB_BASE --nodelay -W 1 --topic tesla_ble/$vin/global_vars/+ -F \"%t=%p\" 2>/dev/null ) EXIT_CODE=$? - + set -e if [ $EXIT_CODE -eq 27 ]; then for item in $mqttOp; do assign=${item##*/} From a39487c0ef215b817f337bfc83f592a06c673d91 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Tue, 7 Jan 2025 07:38:50 +0000 Subject: [PATCH 23/75] Extend polling logic --- mqtt-discovery.sh | 14 ++++++------ mqtt-listen.sh | 2 +- read-state.sh | 57 ++++++++++++++++++++++++++++++++++------------- 3 files changed, 49 insertions(+), 24 deletions(-) diff --git a/mqtt-discovery.sh b/mqtt-discovery.sh index f4aef6f..2e16ab3 100644 --- a/mqtt-discovery.sh +++ b/mqtt-discovery.sh @@ -282,8 +282,8 @@ function setupExtendedControls() { }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 6 10 -t homeassistant/switch/${DEVICE_ID}/steering-wheel-heater/config -l echo '{ - "command_topic": "'${TOPIC_ROOT}'/global_vars/polling", - "state_topic": "'${TOPIC_ROOT}'/global_vars/polling", + "command_topic": "'${TOPIC_ROOT}'/variables/polling", + "state_topic": "'${TOPIC_ROOT}'/variables/polling", "device": { "identifiers": [ "'${DEVICE_ID}'" @@ -495,7 +495,7 @@ function setupExtendedControls() { }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 6 10 -t homeassistant/number/${DEVICE_ID}/climate-temp/config -l fi echo '{ - "command_topic": "'${TOPIC_ROOT}'/global_vars/polling_interval", + "command_topic": "'${TOPIC_ROOT}'/variables/polling_interval", "device": { "identifiers": [ "'${DEVICE_ID}'" @@ -506,15 +506,15 @@ function setupExtendedControls() { "sw_version": "'${SW_VERSION}'" }, "icon": "mdi:timer-sync", - "min": "1", - "max": "60", - "step": "1", + "min": "30", + "max": "3600", + "step": "30", "mode": "slider", "name": "Polling Interval", "retain": "true", "unique_id": "'${DEVICE_ID}'_polling_interval", "entity_category": "diagnostic", - "unit_of_measurement": "mins" + "unit_of_measurement": "secs" }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 6 10 -t homeassistant/number/${DEVICE_ID}/polling_interval/config -l # Selects diff --git a/mqtt-listen.sh b/mqtt-listen.sh index c2541cd..1114711 100755 --- a/mqtt-listen.sh +++ b/mqtt-listen.sh @@ -216,7 +216,7 @@ listen_to_mqtt() { teslaCtrlSendCommand $vin "$cmd-$msg" "Set $cmd mode to $msg" ;; - global_vars) + variables) # These get handled in the subshell where they are used ;; diff --git a/read-state.sh b/read-state.sh index 8976263..8c2a5c1 100644 --- a/read-state.sh +++ b/read-state.sh @@ -8,24 +8,49 @@ function poll_state_loop() { log_notice "Entering poll_state_loop..." - while :; do - vin=LRW3F7FS5RC036403 - sleep 60 + # Loop indefinitely + + # Loop for an hour (max polling interval) + i=0 + while [ $i -le 3600 ]; do + + # Repeat for each car + for vin in $VINLIST; do + + log_debug "poll_state_loop: Setting variables from MQTT for VIN: $vin" + set +e + mqttOp=$( eval $MOSQUITTO_SUB_BASE --nodelay -W 1 --topic tesla_ble/$vin/variables/+ -F \"%t=%p\" 2>/dev/null ) + EXIT_CODE=$? + set -e + if [ $EXIT_CODE -eq 27 ]; then + for item in $mqttOp; do + assign=${item##*/} + log_debug "Setting variable from MQTT: $assign" + eval export ${vin}_$assign + done + fi + + echo ${vin}_polling + echo ${vin}_polling_interval + + # Check if polling turned off for this car + if [ ${vin}_polling -ne "on" ]; then + log_debug "Polling is off for VIN: $vin, skipping" + else + log_debug "Polling is on for VIN: $vin, checking interval" + + # Is i divisible by interval with no remainder? + mod=$(( i % ${vin}_polling_interval )) + echo Remander: $mod - set +e - mqttOp=$( eval $MOSQUITTO_SUB_BASE --nodelay -W 1 --topic tesla_ble/$vin/global_vars/+ -F \"%t=%p\" 2>/dev/null ) - EXIT_CODE=$? - set -e - if [ $EXIT_CODE -eq 27 ]; then - for item in $mqttOp; do - assign=${item##*/} - echo $assign - eval export ${vin}_$assign - done - fi + fi + + done + + # Loop repeat approx every 30 secs + sleep 29 + i=$(( i + 30 )) - echo $LRW3F7FS5RC036403_polling - echo $LRW3F7FS5RC036403_polling_interval done } From 78c14a7946647c4dc04126d372f6af4e563953e2 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Tue, 7 Jan 2025 08:38:12 +0000 Subject: [PATCH 24/75] Add polling interval modulus logic --- read-state.sh | 23 ++++++++++++++--------- run.sh | 5 +++++ 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/read-state.sh b/read-state.sh index 8c2a5c1..f4983b8 100644 --- a/read-state.sh +++ b/read-state.sh @@ -15,7 +15,7 @@ function poll_state_loop() { while [ $i -le 3600 ]; do # Repeat for each car - for vin in $VINLIST; do + for vin in $VIN_LIST; do log_debug "poll_state_loop: Setting variables from MQTT for VIN: $vin" set +e @@ -29,19 +29,24 @@ function poll_state_loop() { eval export ${vin}_$assign done fi - - echo ${vin}_polling - echo ${vin}_polling_interval - + + # Get variables for this VIN. Note ash needs to use eval for dynamic variables + polling=$( eval "echo \"\$${vin}_polling\"" ) + polling_interval=$( eval "echo \"\$${vin}_polling_interval\"" ) + # Check if polling turned off for this car - if [ ${vin}_polling -ne "on" ]; then + if [ $polling -ne "on" ]; then log_debug "Polling is off for VIN: $vin, skipping" else log_debug "Polling is on for VIN: $vin, checking interval" - # Is i divisible by interval with no remainder? - mod=$(( i % ${vin}_polling_interval )) - echo Remander: $mod + # Is counter divisible by interval with no remainder? If so, it is time to attempt to poll + mod=$(( i % $polling_interval )) + if [ $mod -ne 0 ]; then + log_debug "Count not divisible by polling_interval for VIN: $vin, Count: $i, Interval: $polling_interval" + else + log_info "Attempting to poll VIN: $vin" + fi fi diff --git a/run.sh b/run.sh index 58feb37..98f0b21 100755 --- a/run.sh +++ b/run.sh @@ -14,6 +14,11 @@ VIN_LIST=$(echo $VIN_LIST | sed -e 's/[|,;]/ /g') vin_count=0 for vin in $VIN_LIST; do + + # Set defaults for MQTT derived variables + export ${vin}_polling=false + export ${vin}_polling_interval=680 + # Populate BLE Local Names list vin_count=$((vin_count + 1)) BLE_LN=$(vinToBLEln $vin) From 6b71e5d337da194dc9664b1c222ac629e406eaca Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Tue, 7 Jan 2025 08:44:58 +0000 Subject: [PATCH 25/75] Fix string comparison --- read-state.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/read-state.sh b/read-state.sh index f4983b8..5e2ac42 100644 --- a/read-state.sh +++ b/read-state.sh @@ -35,7 +35,7 @@ function poll_state_loop() { polling_interval=$( eval "echo \"\$${vin}_polling_interval\"" ) # Check if polling turned off for this car - if [ $polling -ne "on" ]; then + if [ "$polling != "on" ]; then log_debug "Polling is off for VIN: $vin, skipping" else log_debug "Polling is on for VIN: $vin, checking interval" From 3be29aae14cafb7eb6add2fefc771eb9d5061e7b Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Tue, 7 Jan 2025 08:50:40 +0000 Subject: [PATCH 26/75] Another typo --- read-state.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/read-state.sh b/read-state.sh index 5e2ac42..b324b26 100644 --- a/read-state.sh +++ b/read-state.sh @@ -35,7 +35,7 @@ function poll_state_loop() { polling_interval=$( eval "echo \"\$${vin}_polling_interval\"" ) # Check if polling turned off for this car - if [ "$polling != "on" ]; then + if [ "$polling" != "on" ]; then log_debug "Polling is off for VIN: $vin, skipping" else log_debug "Polling is on for VIN: $vin, checking interval" From de3ae9036ac456c6f5a8bd84a5d788b74cb6a9bc Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Tue, 7 Jan 2025 09:47:11 +0000 Subject: [PATCH 27/75] Is car awake --- read-state.sh | 112 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 71 insertions(+), 41 deletions(-) diff --git a/read-state.sh b/read-state.sh index b324b26..2d2346f 100644 --- a/read-state.sh +++ b/read-state.sh @@ -9,54 +9,84 @@ function poll_state_loop() { log_notice "Entering poll_state_loop..." # Loop indefinitely + while :; do + + # Loop for an hour (max polling interval) + i=0 + while [ $i -le 3600 ]; do + + # Repeat for each car + for vin in $VIN_LIST; do + + log_debug "poll_state_loop: Setting variables from MQTT for VIN: $vin" + set +e + mqttOp=$( eval $MOSQUITTO_SUB_BASE --nodelay -W 1 --topic tesla_ble/$vin/variables/+ -F \"%t=%p\" 2>/dev/null ) + EXIT_CODE=$? + set -e + if [ $EXIT_CODE -eq 27 ]; then + for item in $mqttOp; do + assign=${item##*/} + log_debug "Setting variable from MQTT: $assign" + eval export ${vin}_$assign + done + fi - # Loop for an hour (max polling interval) - i=0 - while [ $i -le 3600 ]; do - - # Repeat for each car - for vin in $VIN_LIST; do - - log_debug "poll_state_loop: Setting variables from MQTT for VIN: $vin" - set +e - mqttOp=$( eval $MOSQUITTO_SUB_BASE --nodelay -W 1 --topic tesla_ble/$vin/variables/+ -F \"%t=%p\" 2>/dev/null ) - EXIT_CODE=$? - set -e - if [ $EXIT_CODE -eq 27 ]; then - for item in $mqttOp; do - assign=${item##*/} - log_debug "Setting variable from MQTT: $assign" - eval export ${vin}_$assign - done - fi - - # Get variables for this VIN. Note ash needs to use eval for dynamic variables - polling=$( eval "echo \"\$${vin}_polling\"" ) - polling_interval=$( eval "echo \"\$${vin}_polling_interval\"" ) + # Get variables for this VIN. Note ash needs to use eval for dynamic variables + polling=$( eval "echo \"\$${vin}_polling\"" ) + polling_interval=$( eval "echo \"\$${vin}_polling_interval\"" ) - # Check if polling turned off for this car - if [ "$polling" != "on" ]; then - log_debug "Polling is off for VIN: $vin, skipping" - else - log_debug "Polling is on for VIN: $vin, checking interval" - - # Is counter divisible by interval with no remainder? If so, it is time to attempt to poll - mod=$(( i % $polling_interval )) - if [ $mod -ne 0 ]; then - log_debug "Count not divisible by polling_interval for VIN: $vin, Count: $i, Interval: $polling_interval" + # Check if polling turned off for this car + if [ "$polling" != "on" ]; then + log_debug "Polling is off for VIN: $vin, skipping" else - log_info "Attempting to poll VIN: $vin" - fi - - fi + log_debug "Polling is on for VIN: $vin, checking interval" + + # Is counter divisible by interval with no remainder? If so, it is time to attempt to poll + mod=$(( i % $polling_interval )) + if [ $mod -ne 0 ]; then + log_debug "Count not divisible by polling_interval for VIN: $vin, Count: $i, Interval: $polling_interval" + else + log_info "Attempting to poll VIN: $vin" + # Send a body-controller-state command. This checks if car is in bluetooth range and whether awake or asleep without acutally waking it + TESLA_VIN=$vin + TESLA_KEY_FILE=$KEYS_DIR/${vin}_private.pem + TESLA_KEY_NAME=$KEYS_DIR/${vin}_private.pem + retjson=$( TESLA_CONTROL_CMD="/usr/bin/tesla-control -ble -command-timeout 5s -connect-timeout 10s body-controller-state 2>&1" ) + EXIT_VALUE=$? + + # If non zero, car is not contactable by bluetooth + if [ $EXIT_VALUE -ne 0 ]; then + log_warning "Car is not responding to bluetooth, maybe it's away. Not attempting to poll. VIN: $vin" + else + # Car has responded. Check if awake or asleep from the body-controller-state response + rqdValue=$(echo $retjson | jq -e '.vehicleSleepStatus') + EXIT_VALUE=$? + if [ $EXIT_VALUE -eq 0] && [ "$rqdValue" == "VEHICLE_SLEEP_STATUS_AWAKE" ]; then + log_info "Car is awake, so polling VIN: $vin" + + + else + log_debug "Car is asleep, not polling VIN: $vin" + fi + + fi + + fi + + fi + + fi + + done + + # Loop repeat approx every 30 secs + sleep 29 + i=$(( i + 30 )) done - # Loop repeat approx every 30 secs - sleep 29 - i=$(( i + 30 )) - done + } function stateMQTTpub() { From d2ba73302fb67ebd98e67970cc9bd0b2a9131f82 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Tue, 7 Jan 2025 10:11:50 +0000 Subject: [PATCH 28/75] Update changelog --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1169e30..af84a42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,8 +5,14 @@ - RELEASE NEW Feature: Automatic Polling is now possible for state - NEW Feature: The following new states / entities are added: + - Sensors: Awake; Last Update - Switches: State Polling - - Numbers: Polling Interval + - Numbers: Polling Interval + - Buttons: Force Update buttons for individual state sections + +- NEW Feature: Environment variables provided to disable updating of various state sections during polling. This speeds up state updates, though less state entities are updated by the polling. The entities can still be manually updated by pressing the Force Update button for the relevent state section + +- Changes: 'Force Data Update' Button is renamed to 'Force Update All' - Fixes: From 7f11fb37b3c539173c5884027b76647e27a336b9 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Tue, 7 Jan 2025 10:22:03 +0000 Subject: [PATCH 29/75] Fix indentation --- read-state.sh | 66 +++++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 34 deletions(-) diff --git a/read-state.sh b/read-state.sh index 2d2346f..bb64353 100644 --- a/read-state.sh +++ b/read-state.sh @@ -22,60 +22,58 @@ function poll_state_loop() { set +e mqttOp=$( eval $MOSQUITTO_SUB_BASE --nodelay -W 1 --topic tesla_ble/$vin/variables/+ -F \"%t=%p\" 2>/dev/null ) EXIT_CODE=$? - set -e - if [ $EXIT_CODE -eq 27 ]; then - for item in $mqttOp; do - assign=${item##*/} - log_debug "Setting variable from MQTT: $assign" - eval export ${vin}_$assign + set -e + if [ $EXIT_CODE -eq 27 ]; then + for item in $mqttOp; do + assign=${item##*/} + log_debug "Setting variable from MQTT: $assign" + eval export ${vin}_$assign done fi # Get variables for this VIN. Note ash needs to use eval for dynamic variables - polling=$( eval "echo \"\$${vin}_polling\"" ) + polling=$( eval "echo \"\$${vin}_polling\"" ) polling_interval=$( eval "echo \"\$${vin}_polling_interval\"" ) # Check if polling turned off for this car - if [ "$polling" != "on" ]; then + if [ "$polling" != "on" ]; then log_debug "Polling is off for VIN: $vin, skipping" else log_debug "Polling is on for VIN: $vin, checking interval" - # Is counter divisible by interval with no remainder? If so, it is time to attempt to poll - mod=$(( i % $polling_interval )) - if [ $mod -ne 0 ]; then - log_debug "Count not divisible by polling_interval for VIN: $vin, Count: $i, Interval: $polling_interval" - else - log_info "Attempting to poll VIN: $vin" - # Send a body-controller-state command. This checks if car is in bluetooth range and whether awake or asleep without acutally waking it - TESLA_VIN=$vin - TESLA_KEY_FILE=$KEYS_DIR/${vin}_private.pem - TESLA_KEY_NAME=$KEYS_DIR/${vin}_private.pem - retjson=$( TESLA_CONTROL_CMD="/usr/bin/tesla-control -ble -command-timeout 5s -connect-timeout 10s body-controller-state 2>&1" ) + # Is counter divisible by interval with no remainder? If so, it is time to attempt to poll + mod=$(( i % $polling_interval )) + if [ $mod -ne 0 ]; then + log_debug "Count not divisible by polling_interval for VIN: $vin, Count: $i, Interval: $polling_interval" + else + log_info "Attempting to poll VIN: $vin" + # Send a body-controller-state command. This checks if car is in bluetooth range and whether awake or asleep without acutally waking it + TESLA_VIN=$vin + TESLA_KEY_FILE=$KEYS_DIR/${vin}_private.pem + TESLA_KEY_NAME=$KEYS_DIR/${vin}_private.pem + retjson=$( TESLA_CONTROL_CMD="/usr/bin/tesla-control -ble -command-timeout 5s -connect-timeout 10s body-controller-state 2>&1" ) + EXIT_VALUE=$? + + # If non zero, car is not contactable by bluetooth + if [ $EXIT_VALUE -ne 0 ]; then + log_warning "Car is not responding to bluetooth, maybe it's away. Not attempting to poll. VIN: $vin" + else + # Car has responded. Check if awake or asleep from the body-controller-state response + rqdValue=$(echo $retjson | jq -e '.vehicleSleepStatus') EXIT_VALUE=$? + if [ $EXIT_VALUE -eq 0] && [ "$rqdValue" == "VEHICLE_SLEEP_STATUS_AWAKE" ]; then + log_info "Car is awake, so polling VIN: $vin" - # If non zero, car is not contactable by bluetooth - if [ $EXIT_VALUE -ne 0 ]; then - log_warning "Car is not responding to bluetooth, maybe it's away. Not attempting to poll. VIN: $vin" - else - # Car has responded. Check if awake or asleep from the body-controller-state response - rqdValue=$(echo $retjson | jq -e '.vehicleSleepStatus') - EXIT_VALUE=$? - if [ $EXIT_VALUE -eq 0] && [ "$rqdValue" == "VEHICLE_SLEEP_STATUS_AWAKE" ]; then - log_info "Car is awake, so polling VIN: $vin" - - - else - log_debug "Car is asleep, not polling VIN: $vin" - fi + else + log_debug "Car is asleep, not polling VIN: $vin" fi fi fi - fi + fi done From 2b1f0d375f3ea27a8c35982353d7708fef0bef88 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Tue, 7 Jan 2025 10:35:08 +0000 Subject: [PATCH 30/75] Typo fixes --- read-state.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/read-state.sh b/read-state.sh index bb64353..30b2c86 100644 --- a/read-state.sh +++ b/read-state.sh @@ -51,7 +51,7 @@ function poll_state_loop() { TESLA_VIN=$vin TESLA_KEY_FILE=$KEYS_DIR/${vin}_private.pem TESLA_KEY_NAME=$KEYS_DIR/${vin}_private.pem - retjson=$( TESLA_CONTROL_CMD="/usr/bin/tesla-control -ble -command-timeout 5s -connect-timeout 10s body-controller-state 2>&1" ) + retjson=$( /usr/bin/tesla-control -ble -command-timeout 5s -connect-timeout 10s body-controller-state 2>&1" ) EXIT_VALUE=$? # If non zero, car is not contactable by bluetooth @@ -66,7 +66,7 @@ function poll_state_loop() { else - log_debug "Car is asleep, not polling VIN: $vin" + log_info "Car is asleep, not polling VIN: $vin" fi fi From 22261c92bfbfcb7d0a75ff6a127021289dc18962 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Tue, 7 Jan 2025 10:37:22 +0000 Subject: [PATCH 31/75] Remove quote --- read-state.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/read-state.sh b/read-state.sh index 30b2c86..2356c09 100644 --- a/read-state.sh +++ b/read-state.sh @@ -51,7 +51,7 @@ function poll_state_loop() { TESLA_VIN=$vin TESLA_KEY_FILE=$KEYS_DIR/${vin}_private.pem TESLA_KEY_NAME=$KEYS_DIR/${vin}_private.pem - retjson=$( /usr/bin/tesla-control -ble -command-timeout 5s -connect-timeout 10s body-controller-state 2>&1" ) + retjson=$( /usr/bin/tesla-control -ble -command-timeout 5s -connect-timeout 10s body-controller-state 2>&1 ) EXIT_VALUE=$? # If non zero, car is not contactable by bluetooth From 10c2c9eac5cfe04235afde3e4b8563bf91e6eb3d Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Tue, 7 Jan 2025 11:12:22 +0000 Subject: [PATCH 32/75] Extra quotes --- read-state.sh | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/read-state.sh b/read-state.sh index 2356c09..25fb467 100644 --- a/read-state.sh +++ b/read-state.sh @@ -48,11 +48,10 @@ function poll_state_loop() { else log_info "Attempting to poll VIN: $vin" # Send a body-controller-state command. This checks if car is in bluetooth range and whether awake or asleep without acutally waking it - TESLA_VIN=$vin - TESLA_KEY_FILE=$KEYS_DIR/${vin}_private.pem - TESLA_KEY_NAME=$KEYS_DIR/${vin}_private.pem - retjson=$( /usr/bin/tesla-control -ble -command-timeout 5s -connect-timeout 10s body-controller-state 2>&1 ) + set +e + retjson=$( /usr/bin/tesla-control -ble -vin $vin -command-timeout 5s -connect-timeout 10s body-controller-state 2>&1 ) EXIT_VALUE=$? + set -e # If non zero, car is not contactable by bluetooth if [ $EXIT_VALUE -ne 0 ]; then @@ -61,7 +60,7 @@ function poll_state_loop() { # Car has responded. Check if awake or asleep from the body-controller-state response rqdValue=$(echo $retjson | jq -e '.vehicleSleepStatus') EXIT_VALUE=$? - if [ $EXIT_VALUE -eq 0] && [ "$rqdValue" == "VEHICLE_SLEEP_STATUS_AWAKE" ]; then + if [ $EXIT_VALUE -eq 0 ] && [ "$rqdValue" == "\"VEHICLE_SLEEP_STATUS_AWAKE\"" ]; then log_info "Car is awake, so polling VIN: $vin" From 33014ca0fa4fa787830254fa0da6d8f66bb01000 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Tue, 7 Jan 2025 12:23:55 +0000 Subject: [PATCH 33/75] Publish to state topic --- mqtt-discovery-sensors.sh | 22 +++++++++++++++++++++- read-state.sh | 10 +++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/mqtt-discovery-sensors.sh b/mqtt-discovery-sensors.sh index 9f93ac4..e0316c6 100644 --- a/mqtt-discovery-sensors.sh +++ b/mqtt-discovery-sensors.sh @@ -142,7 +142,7 @@ function setupChargeStateSensors { "unit_of_measurement": "V", "suggested_display_precision": "0", "unique_id": "'${DEVICE_ID}'_charger_voltage" - "enabled_by_default": "false", + "enabled_by_default": "false" }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 36 10 -t homeassistant/sensor/${DEVICE_ID}/charger_voltage/config -l echo '{ @@ -711,6 +711,26 @@ function setupChargeStateSensors { "unique_id": "'${DEVICE_ID}'_mirror_heater" }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 36 10 -t homeassistant/binary_sensor/${DEVICE_ID}/mirror_heater/config -l + echo '{ + "state_topic": "'${TOPIC_ROOT}'/binary_sensor/awake", + "device": { + "identifiers": [ + "'${DEVICE_ID}'" + ], + "manufacturer": "tesla-local-control", + "model": "Tesla_BLE", + "name": "'${DEVICE_NAME}'", + "sw_version": "'${SW_VERSION}'" + }, + "platform": "binary_sensor", + "icon": "mdi:sleep-off", + "name": "Awake", + "payload_on": "true", + "payload_off": "false", + "qos": "'${QOS_LEVEL}'", + "unique_id": "'${DEVICE_ID}'_awake" + }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 36 10 -t homeassistant/binary_sensor/${DEVICE_ID}/awake/config -l + # Status is only Disengaged for short time, it gets reengaged soon after even with no charger plugged in. Not useful # echo '{ # "state_topic": "'${TOPIC_ROOT}'/binary_sensor/charge_port_latch", diff --git a/read-state.sh b/read-state.sh index 25fb467..3aeee4c 100644 --- a/read-state.sh +++ b/read-state.sh @@ -56,16 +56,22 @@ function poll_state_loop() { # If non zero, car is not contactable by bluetooth if [ $EXIT_VALUE -ne 0 ]; then log_warning "Car is not responding to bluetooth, maybe it's away. Not attempting to poll. VIN: $vin" + + # TODO: Update a future presence sensor. Set awake sensor to Unknown via MQTT availability + else # Car has responded. Check if awake or asleep from the body-controller-state response rqdValue=$(echo $retjson | jq -e '.vehicleSleepStatus') EXIT_VALUE=$? if [ $EXIT_VALUE -eq 0 ] && [ "$rqdValue" == "\"VEHICLE_SLEEP_STATUS_AWAKE\"" ]; then log_info "Car is awake, so polling VIN: $vin" - + + # Publish to MQTT awake topic + stateMQTTpub $vin 'true' 'binary_sensor/awake' else log_info "Car is asleep, not polling VIN: $vin" + stateMQTTpub $vin 'false' 'binary_sensor/awake' fi fi @@ -211,6 +217,8 @@ sendBLECommand() { if [ $EXIT_STATUS -eq 0 ]; then log_debug "sendBLECommand; $TESLACTRLOUT" log_info "Command $command was successfully delivered to vin:$vin" + # Publish to MQTT awake topic + stateMQTTpub $vin 'true' 'binary_sensor/awake' return 0 else if [[ "$TESLACTRLOUT" == *"car could not execute command"* ]]; then From 7bb71dcbf8dae3bcf57728758e295e5f43302689 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Tue, 7 Jan 2025 13:11:37 +0000 Subject: [PATCH 34/75] Press the button --- mqtt-discovery-sensors.sh | 2 +- read-state.sh | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/mqtt-discovery-sensors.sh b/mqtt-discovery-sensors.sh index e0316c6..fe04418 100644 --- a/mqtt-discovery-sensors.sh +++ b/mqtt-discovery-sensors.sh @@ -141,7 +141,7 @@ function setupChargeStateSensors { "device_class": "voltage", "unit_of_measurement": "V", "suggested_display_precision": "0", - "unique_id": "'${DEVICE_ID}'_charger_voltage" + "unique_id": "'${DEVICE_ID}'_charger_voltage", "enabled_by_default": "false" }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 36 10 -t homeassistant/sensor/${DEVICE_ID}/charger_voltage/config -l diff --git a/read-state.sh b/read-state.sh index 3aeee4c..4c451ab 100644 --- a/read-state.sh +++ b/read-state.sh @@ -66,8 +66,9 @@ function poll_state_loop() { if [ $EXIT_VALUE -eq 0 ] && [ "$rqdValue" == "\"VEHICLE_SLEEP_STATUS_AWAKE\"" ]; then log_info "Car is awake, so polling VIN: $vin" - # Publish to MQTT awake topic - stateMQTTpub $vin 'true' 'binary_sensor/awake' + # Publish to MQTT awake topic, 'press' the Data Update button + stateMQTTpub $vin 'true' 'binary_sensor/awake' + stateMQTTpub $vin 'read-state' 'config' else log_info "Car is asleep, not polling VIN: $vin" From d6aad5d9b9ab719d26868817ae1d998ec0f79ca6 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Tue, 7 Jan 2025 13:50:08 +0000 Subject: [PATCH 35/75] First pass individual buttons --- env.sh | 4 +- mqtt-discovery.sh | 126 ++++++++++++++++++++++++++++++++++++++- mqtt-listen.sh | 33 ++++++++++- read-state.sh | 147 ++++++++++++++++++++++++++++------------------ 4 files changed, 247 insertions(+), 63 deletions(-) diff --git a/env.sh b/env.sh index 70243cc..844dcb6 100755 --- a/env.sh +++ b/env.sh @@ -35,6 +35,7 @@ export PRESENCE_DETECTION_LOOP_DELAY=${PRESENCE_DETECTION_LOOP_DELAY:-120} export PRESENCE_DETECTION_TTL=${PRESENCE_DETECTION_TTL:-240} export TEMPERATURE_UNIT_FAHRENHEIT=${TEMPERATURE_UNIT_FAHRENHEIT:-false} export MAX_CURRENT=${MAX_CURRENT:-48} +export NO_POLL_SECTIONS=${NO_POLL_SECTIONS:-} export BLE_LN_REGEX='S[0-9A-Fa-f]{16}C' export BLTCTL_COMMAND_DEVICES=false @@ -54,7 +55,8 @@ log_info "Configuration Options are: PRESENCE_DETECTION_TTL=$PRESENCE_DETECTION_TTL TEMPERATURE_UNIT_FAHRENHEIT=$TEMPERATURE_UNIT_FAHRENHEIT VIN_LIST=$VIN_LIST - MAX_CURRENT=$MAX_CURRENT" + MAX_CURRENT=$MAX_CURRENT + NO_POLL_SECTIONS=$NO_POLL_SECTIONS" [ -n "$ENABLE_HA_FEATURES" ] && log_info " ENABLE_HA_FEATURES=$ENABLE_HA_FEATURES" [ -n "$BLECTL_FILE_INPUT" ] && log_info " BLECTL_FILE_INPUT=$BLECTL_FILE_INPUT" diff --git a/mqtt-discovery.sh b/mqtt-discovery.sh index 2e16ab3..0c7c81c 100644 --- a/mqtt-discovery.sh +++ b/mqtt-discovery.sh @@ -494,6 +494,7 @@ function setupExtendedControls() { "unique_id": "'${DEVICE_ID}'_climate-set-temp" }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 6 10 -t homeassistant/number/${DEVICE_ID}/climate-temp/config -l fi + echo '{ "command_topic": "'${TOPIC_ROOT}'/variables/polling_interval", "device": { @@ -756,6 +757,7 @@ function setupDiagnostic() { "entity_category": "diagnostic", "icon": "mdi:car-info", "name": "Car state information", + "enabled_by_default": "false", "payload_press": "body-controller-state", "qos": "'${QOS_LEVEL}'", "unique_id": "'${DEVICE_ID}'_body-controller-state" @@ -812,12 +814,132 @@ function setupDiagnostic() { "sw_version": "'${SW_VERSION}'" }, "icon": "mdi:database-sync", - "name": "Force Data Update", + "name": "Force Update All", "entity_category": "diagnostic", "payload_press": "read-state", "qos": "'${QOS_LEVEL}'", "unique_id": "'${DEVICE_ID}'_read-state" - }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 6 10 -t homeassistant/button/${DEVICE_ID}/read-state/config -l + }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 6 10 -t homeassistant/button/${DEVICE_ID}/read-state-all/config -l + + echo '{ + "command_topic": "'${TOPIC_ROOT}'/config", + "device": { + "identifiers": [ + "'${DEVICE_ID}'" + ], + "manufacturer": "tesla-local-control", + "model": "Tesla_BLE", + "name": "'${DEVICE_NAME}'", + "sw_version": "'${SW_VERSION}'" + }, + "icon": "mdi:database-sync", + "name": "Force Update Env", + "entity_category": "diagnostic", + "payload_press": "read-state-envcheck", + "qos": "'${QOS_LEVEL}'", + "enabled_by_default": "false", + "unique_id": "'${DEVICE_ID}'_read-state-envcheck" + }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 6 10 -t homeassistant/button/${DEVICE_ID}/read-state-envcheck/config -l + + echo '{ + "command_topic": "'${TOPIC_ROOT}'/config", + "device": { + "identifiers": [ + "'${DEVICE_ID}'" + ], + "manufacturer": "tesla-local-control", + "model": "Tesla_BLE", + "name": "'${DEVICE_NAME}'", + "sw_version": "'${SW_VERSION}'" + }, + "icon": "mdi:database-sync", + "name": "Force Update Charge", + "entity_category": "diagnostic", + "payload_press": "read-state-charge", + "qos": "'${QOS_LEVEL}'", + "enabled_by_default": "false", + "unique_id": "'${DEVICE_ID}'_read-state-charge" + }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 6 10 -t homeassistant/button/${DEVICE_ID}/read-state-charge/config -l + + echo '{ + "command_topic": "'${TOPIC_ROOT}'/config", + "device": { + "identifiers": [ + "'${DEVICE_ID}'" + ], + "manufacturer": "tesla-local-control", + "model": "Tesla_BLE", + "name": "'${DEVICE_NAME}'", + "sw_version": "'${SW_VERSION}'" + }, + "icon": "mdi:database-sync", + "name": "Force Update Climate", + "entity_category": "diagnostic", + "payload_press": "read-state-climate", + "qos": "'${QOS_LEVEL}'", + "enabled_by_default": "false", + "unique_id": "'${DEVICE_ID}'_read-state-climate" + }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 6 10 -t homeassistant/button/${DEVICE_ID}/read-state-climate/config -l + + echo '{ + "command_topic": "'${TOPIC_ROOT}'/config", + "device": { + "identifiers": [ + "'${DEVICE_ID}'" + ], + "manufacturer": "tesla-local-control", + "model": "Tesla_BLE", + "name": "'${DEVICE_NAME}'", + "sw_version": "'${SW_VERSION}'" + }, + "icon": "mdi:database-sync", + "name": "Force Update Tyre", + "entity_category": "diagnostic", + "payload_press": "read-state-tyre", + "qos": "'${QOS_LEVEL}'", + "enabled_by_default": "false", + "unique_id": "'${DEVICE_ID}'_read-state-tyre" + }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 6 10 -t homeassistant/button/${DEVICE_ID}/read-state-tyre/config -l + + echo '{ + "command_topic": "'${TOPIC_ROOT}'/config", + "device": { + "identifiers": [ + "'${DEVICE_ID}'" + ], + "manufacturer": "tesla-local-control", + "model": "Tesla_BLE", + "name": "'${DEVICE_NAME}'", + "sw_version": "'${SW_VERSION}'" + }, + "icon": "mdi:database-sync", + "name": "Force Update Closure", + "entity_category": "diagnostic", + "payload_press": "read-state-closure", + "qos": "'${QOS_LEVEL}'", + "enabled_by_default": "false", + "unique_id": "'${DEVICE_ID}'_read-state-closure" + }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 6 10 -t homeassistant/button/${DEVICE_ID}/read-state-closure/config -l + + echo '{ + "command_topic": "'${TOPIC_ROOT}'/config", + "device": { + "identifiers": [ + "'${DEVICE_ID}'" + ], + "manufacturer": "tesla-local-control", + "model": "Tesla_BLE", + "name": "'${DEVICE_NAME}'", + "sw_version": "'${SW_VERSION}'" + }, + "icon": "mdi:database-sync", + "name": "Force Update Drive", + "entity_category": "diagnostic", + "payload_press": "read-state-drive", + "qos": "'${QOS_LEVEL}'", + "enabled_by_default": "false", + "unique_id": "'${DEVICE_ID}'_read-state-drive" + }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 6 10 -t homeassistant/button/${DEVICE_ID}/read-state-drive/config -l log_debug "setupDiagnostic() leaving vin:$vin" diff --git a/mqtt-listen.sh b/mqtt-listen.sh index 1114711..30a1910 100755 --- a/mqtt-listen.sh +++ b/mqtt-listen.sh @@ -76,9 +76,38 @@ listen_to_mqtt() { infoBluetoothAdapter $vin ;; - read-state) + read-state-all) log_notice "read-state; calling readState()" - readState $vin + readState $vin all + ;; + + read-state-envcheck) + log_notice "read-state; calling readState()" + readState $vin env_check + ;; + + read-state-charge) + log_notice "read-state; calling readState()" + readState $vin charge + ;; + + read-state-climate) + log_notice "read-state; calling readState()" + readState $vin climate + ;; + + read-state-tyre) + log_notice "read-state; calling readState()" + readState $vin tyre + ;; + + read-state-closure) + log_notice "read-state; calling readState()" + readState $vin closure + ;; + read-state-drive) + log_notice "read-state; calling readState()" + readState $vin drive ;; *) diff --git a/read-state.sh b/read-state.sh index 4c451ab..b3cb43d 100644 --- a/read-state.sh +++ b/read-state.sh @@ -118,74 +118,105 @@ function stateMQTTpub() { function readState() { vin=$1 - - log_debug "readState; entering vin:$vin" - - # Read and parse charge state - readChargeState $vin - EXIT_STATUS=$? - if [ $EXIT_STATUS -ne 0 ]; then - log_debug "readState; failed to read charge state vin:$vin. Exit status: $EXIT_STATUS" - return 2 - else - log_notice "readState; read of charge state succeeded vin:$vin" - ret=0 + sections=$2 + + log_debug "readState; entering. Sections: $sections VIN:$vin" + charge=0; climate=0; tyre=0; closure=0; drive=0 + case $sections in + charge) + charge=1 + ;; + climate) + climate=1 + ;; + tyre) + tyre=1 + ;; + closure) + closure=1 + ;; + drive) + drive=1 + ;; + env_check) + echo No poll sections: $NO_POLL_SECTIONS + charge=1; climate=1; tyre=1; closure=1; drive=1 + ;; + *) + charge=1; climate=1; tyre=1; closure=1; drive=1 + ;; + esac + + if [ $charge -eq 1 ]; then + # Read and parse charge state + readChargeState $vin + EXIT_STATUS=$? + if [ $EXIT_STATUS -ne 0 ]; then + log_debug "readState; failed to read charge state vin:$vin. Exit status: $EXIT_STATUS" + return 2 + else + log_notice "readState; read of charge state succeeded vin:$vin" + ret=0 + fi + sleep $BLE_CMD_RETRY_DELAY fi - sleep $BLE_CMD_RETRY_DELAY - - # Read and parse climate state - readClimateState $vin - EXIT_STATUS=$? - if [ $EXIT_STATUS -ne 0 ]; then - log_debug "readState; failed to read climate state vin:$vin. Exit status: $EXIT_STATUS" - return 2 - else - log_notice "readState; read of climate state succeeded vin:$vin" - ret=0 + if [ $climate -eq 1 ]; then + # Read and parse climate state + readClimateState $vin + EXIT_STATUS=$? + if [ $EXIT_STATUS -ne 0 ]; then + log_debug "readState; failed to read climate state vin:$vin. Exit status: $EXIT_STATUS" + return 2 + else + log_notice "readState; read of climate state succeeded vin:$vin" + ret=0 + fi + sleep $BLE_CMD_RETRY_DELAY fi - sleep $BLE_CMD_RETRY_DELAY - - # Read and parse tire-pressure state - readTyreState $vin - EXIT_STATUS=$? - if [ $EXIT_STATUS -ne 0 ]; then - log_debug "readState; failed to read tire-pressure state vin:$vin. Exit status: $EXIT_STATUS" - return 2 - else - log_notice "readState; read of tire-pressure state succeeded vin:$vin" - ret=0 + if [ $tyre -eq 1 ]; then + # Read and parse tire-pressure state + readTyreState $vin + EXIT_STATUS=$? + if [ $EXIT_STATUS -ne 0 ]; then + log_debug "readState; failed to read tire-pressure state vin:$vin. Exit status: $EXIT_STATUS" + return 2 + else + log_notice "readState; read of tire-pressure state succeeded vin:$vin" + ret=0 + fi + sleep $BLE_CMD_RETRY_DELAY fi - sleep $BLE_CMD_RETRY_DELAY - - # Read and parse closures state - closuresState $vin - EXIT_STATUS=$? - if [ $EXIT_STATUS -ne 0 ]; then - log_debug "readState; failed to read closures state vin:$vin. Exit status: $EXIT_STATUS" - return 2 - else - log_notice "readState; read of closures state succeeded vin:$vin" - ret=0 + if [ $closure -eq 1 ]; then + # Read and parse closures state + closuresState $vin + EXIT_STATUS=$? + if [ $EXIT_STATUS -ne 0 ]; then + log_debug "readState; failed to read closures state vin:$vin. Exit status: $EXIT_STATUS" + return 2 + else + log_notice "readState; read of closures state succeeded vin:$vin" + ret=0 + fi + sleep $BLE_CMD_RETRY_DELAY fi - sleep $BLE_CMD_RETRY_DELAY - - # Read and parse drive state - driveState $vin - EXIT_STATUS=$? - if [ $EXIT_STATUS -ne 0 ]; then - log_debug "readState; failed to read drive state vin:$vin. Exit status: $EXIT_STATUS" - return 2 - else - log_notice "readState; read of drive state succeeded vin:$vin" - ret=0 + if [ $drive -eq 1 ]; then + # Read and parse drive state + driveState $vin + EXIT_STATUS=$? + if [ $EXIT_STATUS -ne 0 ]; then + log_debug "readState; failed to read drive state vin:$vin. Exit status: $EXIT_STATUS" + return 2 + else + log_notice "readState; read of drive state succeeded vin:$vin" + ret=0 + fi + sleep $BLE_CMD_RETRY_DELAY fi - sleep $BLE_CMD_RETRY_DELAY - log_debug "readState; leaving vin:$vin return:$ret" return $ret From af1c624ad8285d513d30e641f29e8d80b3d95e01 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Tue, 7 Jan 2025 14:16:50 +0000 Subject: [PATCH 36/75] List sections --- read-state.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/read-state.sh b/read-state.sh index b3cb43d..df43976 100644 --- a/read-state.sh +++ b/read-state.sh @@ -66,9 +66,9 @@ function poll_state_loop() { if [ $EXIT_VALUE -eq 0 ] && [ "$rqdValue" == "\"VEHICLE_SLEEP_STATUS_AWAKE\"" ]; then log_info "Car is awake, so polling VIN: $vin" - # Publish to MQTT awake topic, 'press' the Data Update button + # Publish to MQTT awake topic, 'press' the Data Update Env button (which checks NO_POLL_SECTIONS environment variable to exclude various sections if required) stateMQTTpub $vin 'true' 'binary_sensor/awake' - stateMQTTpub $vin 'read-state' 'config' + stateMQTTpub $vin 'read-state-envcheck' 'config' else log_info "Car is asleep, not polling VIN: $vin" @@ -141,6 +141,9 @@ function readState() { env_check) echo No poll sections: $NO_POLL_SECTIONS charge=1; climate=1; tyre=1; closure=1; drive=1 + for sect in $NO_POLL_SECTIONS; do + echo Section: $sect + done ;; *) charge=1; climate=1; tyre=1; closure=1; drive=1 From ae78cdcdff777b36998ec86575f3bbf5d7285157 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Tue, 7 Jan 2025 14:35:51 +0000 Subject: [PATCH 37/75] Test NO_POLL_SECTIONS functionality --- CHANGELOG.md | 8 ++++---- read-state.sh | 21 +++++++++++++++++++-- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index af84a42..64749b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,12 +5,12 @@ - RELEASE NEW Feature: Automatic Polling is now possible for state - NEW Feature: The following new states / entities are added: - - Sensors: Awake; Last Update - - Switches: State Polling + - Sensors: Awake + - Switches: Polling - Numbers: Polling Interval - - Buttons: Force Update buttons for individual state sections + - Buttons: Force Update buttons for individual state categories -- NEW Feature: Environment variables provided to disable updating of various state sections during polling. This speeds up state updates, though less state entities are updated by the polling. The entities can still be manually updated by pressing the Force Update button for the relevent state section +- NEW Feature: Environment variable NO_POLL_SECTIONS is provided to disable updating of various state categories during polling. This speeds up state updates, though less state entities are updated by the polling. The entities can still be manually updated by pressing the Force Update button for the relevent state category - Changes: 'Force Data Update' Button is renamed to 'Force Update All' diff --git a/read-state.sh b/read-state.sh index df43976..df21791 100644 --- a/read-state.sh +++ b/read-state.sh @@ -139,10 +139,27 @@ function readState() { drive=1 ;; env_check) - echo No poll sections: $NO_POLL_SECTIONS charge=1; climate=1; tyre=1; closure=1; drive=1 for sect in $NO_POLL_SECTIONS; do - echo Section: $sect + case $sect in + charge) + charge=0 + ;; + climate) + climate=0 + ;; + tire-pressure) + tyre=0 + ;; + closures) + closure=0 + ;; + drive) + drive=0 + ;; + *) + log_warning "readState: Invalid state category in NO_POLL_SECTIONS" + ;; done ;; *) From 3e06793db91f1e25267ce1394cf716ef2786494a Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Tue, 7 Jan 2025 14:37:58 +0000 Subject: [PATCH 38/75] Missing esac --- read-state.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/read-state.sh b/read-state.sh index df21791..aa889cd 100644 --- a/read-state.sh +++ b/read-state.sh @@ -160,6 +160,7 @@ function readState() { *) log_warning "readState: Invalid state category in NO_POLL_SECTIONS" ;; + esac done ;; *) From bb071f97ee3b856923cffa4d025b8d4f4f7fde35 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Tue, 7 Jan 2025 14:51:27 +0000 Subject: [PATCH 39/75] Update changelog --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64749b4..2e3f029 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,9 +12,13 @@ - NEW Feature: Environment variable NO_POLL_SECTIONS is provided to disable updating of various state categories during polling. This speeds up state updates, though less state entities are updated by the polling. The entities can still be manually updated by pressing the Force Update button for the relevent state category -- Changes: 'Force Data Update' Button is renamed to 'Force Update All' +- Changes: + - 'Force Data Update' Button is renamed to 'Force Update All' + - Errors which occur whilst reading state will not automatically prevent the next state or state category being read. This will fix an issue reported in #135 below where a user doesn't have a Heated Steering Wheel. This previously prevented any states after this one from being read - Fixes: + - All my sensor entities are "unknown" #131 (_core) + - Any potential to "read state" via bluetooth? #115 (_core) ## 0.3.1 From a52a5cd18b7255b410e9c8d097737090520c916f Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Tue, 7 Jan 2025 15:00:16 +0000 Subject: [PATCH 40/75] First pass dont abort --- read-state.sh | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/read-state.sh b/read-state.sh index aa889cd..0d11fe1 100644 --- a/read-state.sh +++ b/read-state.sh @@ -174,7 +174,7 @@ function readState() { EXIT_STATUS=$? if [ $EXIT_STATUS -ne 0 ]; then log_debug "readState; failed to read charge state vin:$vin. Exit status: $EXIT_STATUS" - return 2 + ret=2 else log_notice "readState; read of charge state succeeded vin:$vin" ret=0 @@ -188,7 +188,7 @@ function readState() { EXIT_STATUS=$? if [ $EXIT_STATUS -ne 0 ]; then log_debug "readState; failed to read climate state vin:$vin. Exit status: $EXIT_STATUS" - return 2 + ret=2 else log_notice "readState; read of climate state succeeded vin:$vin" ret=0 @@ -202,7 +202,7 @@ function readState() { EXIT_STATUS=$? if [ $EXIT_STATUS -ne 0 ]; then log_debug "readState; failed to read tire-pressure state vin:$vin. Exit status: $EXIT_STATUS" - return 2 + ret=2 else log_notice "readState; read of tire-pressure state succeeded vin:$vin" ret=0 @@ -216,7 +216,7 @@ function readState() { EXIT_STATUS=$? if [ $EXIT_STATUS -ne 0 ]; then log_debug "readState; failed to read closures state vin:$vin. Exit status: $EXIT_STATUS" - return 2 + ret=2 else log_notice "readState; read of closures state succeeded vin:$vin" ret=0 @@ -230,7 +230,7 @@ function readState() { EXIT_STATUS=$? if [ $EXIT_STATUS -ne 0 ]; then log_debug "readState; failed to read drive state vin:$vin. Exit status: $EXIT_STATUS" - return 2 + ret=2 else log_notice "readState; read of drive state succeeded vin:$vin" ret=0 @@ -388,21 +388,21 @@ function readChargeState() { fi # Get values from the JSON and publish corresponding MQTT state topic - getStateValueAndPublish $vin '.chargeState.batteryLevel' sensor/charge_state "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.chargeState.batteryRange' sensor/battery_range "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.chargeState.chargerPower' sensor/charger_power "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.chargeState.chargerActualCurrent' sensor/charger_actual_current "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.chargeState.chargerVoltage' sensor/charger_voltage "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.chargeState.chargeEnergyAdded' sensor/charge_energy_added "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.chargeState.chargeMilesAddedRated' sensor/charge_range_added "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.chargeState.chargeRateMph' sensor/charge_speed "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.chargeState.connChargeCable' sensor/charge_cable "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.chargeState.chargeEnableRequest' switch/charge_enable_request "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.chargeState.chargePortDoorOpen' cover/charge_port_door_open "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.chargeState.chargeCurrentRequest' number/charge_current_request "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.chargeState.chargeLimitSoc' number/charge_limit_soc "$TESLACTRLOUT" + EXIT_STATUS=0 + getStateValueAndPublish $vin '.chargeState.batteryLevel' sensor/charge_state "$TESLACTRLOUT" || EXIT_STATUS=1 + getStateValueAndPublish $vin '.chargeState.batteryRange' sensor/battery_range "$TESLACTRLOUT" || EXIT_STATUS=1 + getStateValueAndPublish $vin '.chargeState.chargerPower' sensor/charger_power "$TESLACTRLOUT" || EXIT_STATUS=1 + getStateValueAndPublish $vin '.chargeState.chargerActualCurrent' sensor/charger_actual_current "$TESLACTRLOUT" || EXIT_STATUS=1 + getStateValueAndPublish $vin '.chargeState.chargerVoltage' sensor/charger_voltage "$TESLACTRLOUT" || EXIT_STATUS=1 + getStateValueAndPublish $vin '.chargeState.chargeEnergyAdded' sensor/charge_energy_added "$TESLACTRLOUT" || EXIT_STATUS=1 + getStateValueAndPublish $vin '.chargeState.chargeMilesAddedRated' sensor/charge_range_added "$TESLACTRLOUT" || EXIT_STATUS=1 + getStateValueAndPublish $vin '.chargeState.chargeRateMph' sensor/charge_speed "$TESLACTRLOUT" || EXIT_STATUS=1 + getStateValueAndPublish $vin '.chargeState.connChargeCable' sensor/charge_cable "$TESLACTRLOUT" || EXIT_STATUS=1 + getStateValueAndPublish $vin '.chargeState.chargeEnableRequest' switch/charge_enable_request "$TESLACTRLOUT" || EXIT_STATUS=1 + getStateValueAndPublish $vin '.chargeState.chrgePortDoorOpen' cover/charge_port_door_open "$TESLACTRLOUT" || EXIT_STATUS=1 + getStateValueAndPublish $vin '.chargeState.chargeCurrentRequest' number/charge_current_request "$TESLACTRLOUT" || EXIT_STATUS=1 + getStateValueAndPublish $vin '.chargeState.chargeLimitSoc' number/charge_limit_soc "$TESLACTRLOUT" || EXIT_STATUS=1 - EXIT_STATUS=$? if [ $EXIT_STATUS -ne 0 ]; then ret=3 log_error "readChargeState; one of the getStateValueAndPublish calls failed for vin:$vin return:$ret" From b3844fee959eaf55cfdc1a493750ab4f01910f98 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Tue, 7 Jan 2025 15:18:27 +0000 Subject: [PATCH 41/75] Simplify errors --- read-state.sh | 38 ++++++++++++++------------------------ 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/read-state.sh b/read-state.sh index 0d11fe1..e502186 100644 --- a/read-state.sh +++ b/read-state.sh @@ -366,7 +366,7 @@ function getStateValueAndPublish() { else ret=2 - log_debug "getStateValueAndPublish; failed to parse $jsonParam for vin:$vin return:$ret" + log_warning "getStateValueAndPublish; failed to parse $jsonParam for vin:$vin return:$ret" fi return $ret @@ -388,30 +388,20 @@ function readChargeState() { fi # Get values from the JSON and publish corresponding MQTT state topic - EXIT_STATUS=0 - getStateValueAndPublish $vin '.chargeState.batteryLevel' sensor/charge_state "$TESLACTRLOUT" || EXIT_STATUS=1 - getStateValueAndPublish $vin '.chargeState.batteryRange' sensor/battery_range "$TESLACTRLOUT" || EXIT_STATUS=1 - getStateValueAndPublish $vin '.chargeState.chargerPower' sensor/charger_power "$TESLACTRLOUT" || EXIT_STATUS=1 - getStateValueAndPublish $vin '.chargeState.chargerActualCurrent' sensor/charger_actual_current "$TESLACTRLOUT" || EXIT_STATUS=1 - getStateValueAndPublish $vin '.chargeState.chargerVoltage' sensor/charger_voltage "$TESLACTRLOUT" || EXIT_STATUS=1 - getStateValueAndPublish $vin '.chargeState.chargeEnergyAdded' sensor/charge_energy_added "$TESLACTRLOUT" || EXIT_STATUS=1 - getStateValueAndPublish $vin '.chargeState.chargeMilesAddedRated' sensor/charge_range_added "$TESLACTRLOUT" || EXIT_STATUS=1 - getStateValueAndPublish $vin '.chargeState.chargeRateMph' sensor/charge_speed "$TESLACTRLOUT" || EXIT_STATUS=1 - getStateValueAndPublish $vin '.chargeState.connChargeCable' sensor/charge_cable "$TESLACTRLOUT" || EXIT_STATUS=1 - getStateValueAndPublish $vin '.chargeState.chargeEnableRequest' switch/charge_enable_request "$TESLACTRLOUT" || EXIT_STATUS=1 - getStateValueAndPublish $vin '.chargeState.chrgePortDoorOpen' cover/charge_port_door_open "$TESLACTRLOUT" || EXIT_STATUS=1 - getStateValueAndPublish $vin '.chargeState.chargeCurrentRequest' number/charge_current_request "$TESLACTRLOUT" || EXIT_STATUS=1 - getStateValueAndPublish $vin '.chargeState.chargeLimitSoc' number/charge_limit_soc "$TESLACTRLOUT" || EXIT_STATUS=1 + getStateValueAndPublish $vin '.chargeState.batteryLevel' sensor/charge_state "$TESLACTRLOUT" + getStateValueAndPublish $vin '.chargeState.batteryRange' sensor/battery_range "$TESLACTRLOUT" + getStateValueAndPublish $vin '.chargeState.chargerPower' sensor/charger_power "$TESLACTRLOUT" + getStateValueAndPublish $vin '.chargeState.chargerActualCurrent' sensor/charger_actual_current "$TESLACTRLOUT" + getStateValueAndPublish $vin '.chargeState.chargerVoltage' sensor/charger_voltage "$TESLACTRLOUT" + getStateValueAndPublish $vin '.chargeState.chargeEnergyAdded' sensor/charge_energy_added "$TESLACTRLOUT" + getStateValueAndPublish $vin '.chargeState.chargeMilesAddedRated' sensor/charge_range_added "$TESLACTRLOUT" + getStateValueAndPublish $vin '.chargeState.chargeRateMph' sensor/charge_speed "$TESLACTRLOUT" + getStateValueAndPublish $vin '.chargeState.connChargeCable' sensor/charge_cable "$TESLACTRLOUT" + getStateValueAndPublish $vin '.chargeState.chargeEnableRequest' switch/charge_enable_request "$TESLACTRLOUT" + getStateValueAndPublish $vin '.chargeState.chrgePortDoorOpen' cover/charge_port_door_open "$TESLACTRLOUT" + getStateValueAndPublish $vin '.chargeState.chargeCurrentRequest' number/charge_current_request "$TESLACTRLOUT" + getStateValueAndPublish $vin '.chargeState.chargeLimitSoc' number/charge_limit_soc "$TESLACTRLOUT" - if [ $EXIT_STATUS -ne 0 ]; then - ret=3 - log_error "readChargeState; one of the getStateValueAndPublish calls failed for vin:$vin return:$ret" - else - ret=0 - log_info "readChargeState; Completed successfully for vin:$vin" - fi - - return $ret } function readClimateState() { From 292b30686065d3a65ffd40f9c8d5264faaefe549 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Tue, 7 Jan 2025 15:28:55 +0000 Subject: [PATCH 42/75] More error simplification --- read-state.sh | 146 ++++++++++++-------------------------------------- 1 file changed, 33 insertions(+), 113 deletions(-) diff --git a/read-state.sh b/read-state.sh index e502186..72bd674 100644 --- a/read-state.sh +++ b/read-state.sh @@ -171,70 +171,30 @@ function readState() { if [ $charge -eq 1 ]; then # Read and parse charge state readChargeState $vin - EXIT_STATUS=$? - if [ $EXIT_STATUS -ne 0 ]; then - log_debug "readState; failed to read charge state vin:$vin. Exit status: $EXIT_STATUS" - ret=2 - else - log_notice "readState; read of charge state succeeded vin:$vin" - ret=0 - fi sleep $BLE_CMD_RETRY_DELAY fi if [ $climate -eq 1 ]; then # Read and parse climate state readClimateState $vin - EXIT_STATUS=$? - if [ $EXIT_STATUS -ne 0 ]; then - log_debug "readState; failed to read climate state vin:$vin. Exit status: $EXIT_STATUS" - ret=2 - else - log_notice "readState; read of climate state succeeded vin:$vin" - ret=0 - fi sleep $BLE_CMD_RETRY_DELAY fi if [ $tyre -eq 1 ]; then # Read and parse tire-pressure state readTyreState $vin - EXIT_STATUS=$? - if [ $EXIT_STATUS -ne 0 ]; then - log_debug "readState; failed to read tire-pressure state vin:$vin. Exit status: $EXIT_STATUS" - ret=2 - else - log_notice "readState; read of tire-pressure state succeeded vin:$vin" - ret=0 - fi sleep $BLE_CMD_RETRY_DELAY fi if [ $closure -eq 1 ]; then # Read and parse closures state closuresState $vin - EXIT_STATUS=$? - if [ $EXIT_STATUS -ne 0 ]; then - log_debug "readState; failed to read closures state vin:$vin. Exit status: $EXIT_STATUS" - ret=2 - else - log_notice "readState; read of closures state succeeded vin:$vin" - ret=0 - fi sleep $BLE_CMD_RETRY_DELAY fi if [ $drive -eq 1 ]; then # Read and parse drive state driveState $vin - EXIT_STATUS=$? - if [ $EXIT_STATUS -ne 0 ]; then - log_debug "readState; failed to read drive state vin:$vin. Exit status: $EXIT_STATUS" - ret=2 - else - log_notice "readState; read of drive state succeeded vin:$vin" - ret=0 - fi sleep $BLE_CMD_RETRY_DELAY fi @@ -366,7 +326,7 @@ function getStateValueAndPublish() { else ret=2 - log_warning "getStateValueAndPublish; failed to parse $jsonParam for vin:$vin return:$ret" + log_warning "getStateValueAndPublish; failed to parse $jsonParam for vin:$vin" fi return $ret @@ -420,32 +380,22 @@ function readClimateState() { fi # Get values from the JSON and publish corresponding MQTT state topic - getStateValueAndPublish $vin '.climateState.insideTempCelsius' sensor/inside_temp "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.climateState.outsideTempCelsius' sensor/outside_temp "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.climateState.passengerTempSetting' sensor/passenger_temp "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.climateState.driverTempSetting' number/driver_temp_setting "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.climateState.isClimateOn' switch/is_climate_on "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.climateState.steeringWheelHeater' switch/steering_wheel_heater "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.climateState.batteryHeater' binary_sensor/battery_heater_on "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.climateState.isFrontDefrosterOn' binary_sensor/front_defrost "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.climateState.isRearDefrosterOn' binary_sensor/rear_defrost "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.climateState.wiperBladeHeater' binary_sensor/wiper_heater "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.climateState.sideMirrorHeaters' binary_sensor/mirror_heater "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.climateState.seatHeaterLeft' select/seat_heater_left "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.climateState.seatHeaterRight' select/seat_heater_right "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.climateState.seatHeaterRearLeft' select/seat_heater_rear_left "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.climateState.seatHeaterRearRight' select/seat_heater_rear_right "$TESLACTRLOUT" + getStateValueAndPublish $vin '.climateState.insideTempCelsius' sensor/inside_temp "$TESLACTRLOUT" + getStateValueAndPublish $vin '.climateState.outsideTempCelsius' sensor/outside_temp "$TESLACTRLOUT" + getStateValueAndPublish $vin '.climateState.passengerTempSetting' sensor/passenger_temp "$TESLACTRLOUT" + getStateValueAndPublish $vin '.climateState.driverTempSetting' number/driver_temp_setting "$TESLACTRLOUT" + getStateValueAndPublish $vin '.climateState.isClimateOn' switch/is_climate_on "$TESLACTRLOUT" + getStateValueAndPublish $vin '.climateState.steeringWheelHeater' switch/steering_wheel_heater "$TESLACTRLOUT" + getStateValueAndPublish $vin '.climateState.batteryHeater' binary_sensor/battery_heater_on "$TESLACTRLOUT" + getStateValueAndPublish $vin '.climateState.isFrontDefrosterOn' binary_sensor/front_defrost "$TESLACTRLOUT" + getStateValueAndPublish $vin '.climateState.isRearDefrosterOn' binary_sensor/rear_defrost "$TESLACTRLOUT" + getStateValueAndPublish $vin '.climateState.wiperBladeHeater' binary_sensor/wiper_heater "$TESLACTRLOUT" + getStateValueAndPublish $vin '.climateState.sideMirrorHeaters' binary_sensor/mirror_heater "$TESLACTRLOUT" + getStateValueAndPublish $vin '.climateState.seatHeaterLeft' select/seat_heater_left "$TESLACTRLOUT" + getStateValueAndPublish $vin '.climateState.seatHeaterRight' select/seat_heater_right "$TESLACTRLOUT" + getStateValueAndPublish $vin '.climateState.seatHeaterRearLeft' select/seat_heater_rear_left "$TESLACTRLOUT" + getStateValueAndPublish $vin '.climateState.seatHeaterRearRight' select/seat_heater_rear_right "$TESLACTRLOUT" - EXIT_STATUS=$? - if [ $EXIT_STATUS -ne 0 ]; then - ret=3 - log_error "readClimateState; one of the getStateValueAndPublish calls failed for vin:$vin return:$ret" - else - ret=0 - log_info "readClimateState; Completed successfully for vin:$vin" - fi - - return $ret } function readTyreState() { @@ -464,21 +414,11 @@ function readTyreState() { fi # Get values from the JSON and publish corresponding MQTT state topic - getStateValueAndPublish $vin '.tirePressureState.tpmsPressureFl' sensor/tpms_pressure_fl "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.tirePressureState.tpmsPressureFr' sensor/tpms_pressure_fr "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.tirePressureState.tpmsPressureRl' sensor/tpms_pressure_rl "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.tirePressureState.tpmsPressureRr' sensor/tpms_pressure_rr "$TESLACTRLOUT" + getStateValueAndPublish $vin '.tirePressureState.tpmsPressureFl' sensor/tpms_pressure_fl "$TESLACTRLOUT" + getStateValueAndPublish $vin '.tirePressureState.tpmsPressureFr' sensor/tpms_pressure_fr "$TESLACTRLOUT" + getStateValueAndPublish $vin '.tirePressureState.tpmsPressureRl' sensor/tpms_pressure_rl "$TESLACTRLOUT" + getStateValueAndPublish $vin '.tirePressureState.tpmsPressureRr' sensor/tpms_pressure_rr "$TESLACTRLOUT" - EXIT_STATUS=$? - if [ $EXIT_STATUS -ne 0 ]; then - ret=3 - log_error "readTyreState; one of the getStateValueAndPublish calls failed for vin:$vin return:$ret" - else - ret=0 - log_info "readTyreState; Completed successfully for vin:$vin" - fi - - return $ret } function closuresState() { @@ -500,27 +440,18 @@ function closuresState() { export ANYWINDOWOPEN=0 # Get values from the JSON and publish corresponding MQTT state topic - getStateValueAndPublish $vin '.closuresState.sentryModeState' switch/sentry_mode "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.closuresState.doorOpenTrunkRear' cover/rear_trunk "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.closuresState.doorOpenTrunkFront' binary_sensor/frunk_open "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.closuresState.windowOpenDriverFront' binary_sensor/window_open_driver_front "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.closuresState.windowOpenPassengerFront' binary_sensor/window_open_pass_front "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.closuresState.windowOpenDriverRear' binary_sensor/window_open_driver_rear "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.closuresState.windowOpenPassengerRear' binary_sensor/window_open_pass_rear "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.closuresState.doorOpenDriverFront' binary_sensor/door_open_driver_front "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.closuresState.doorOpenPassengerFront' binary_sensor/door_open_pass_front "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.closuresState.doorOpenDriverRear' binary_sensor/door_open_driver_rear "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.closuresState.doorOpenPassengerRear' binary_sensor/door_open_pass_rear "$TESLACTRLOUT" && - getStateValueAndPublish $vin '.closuresState.locked' lock/locked "$TESLACTRLOUT" - - EXIT_STATUS=$? - if [ $EXIT_STATUS -ne 0 ]; then - ret=3 - log_error "closuresState; one of the getStateValueAndPublish calls failed for vin:$vin return:$ret" - else - ret=0 - log_info "closuresState; Completed successfully for vin:$vin" - fi + getStateValueAndPublish $vin '.closuresState.sentryModeState' switch/sentry_mode "$TESLACTRLOUT" + getStateValueAndPublish $vin '.closuresState.doorOpenTrunkRear' cover/rear_trunk "$TESLACTRLOUT" + getStateValueAndPublish $vin '.closuresState.doorOpenTrunkFront' binary_sensor/frunk_open "$TESLACTRLOUT" + getStateValueAndPublish $vin '.closuresState.windowOpenDriverFront' binary_sensor/window_open_driver_front "$TESLACTRLOUT" + getStateValueAndPublish $vin '.closuresState.windowOpenPassengerFront' binary_sensor/window_open_pass_front "$TESLACTRLOUT" + getStateValueAndPublish $vin '.closuresState.windowOpenDriverRear' binary_sensor/window_open_driver_rear "$TESLACTRLOUT" + getStateValueAndPublish $vin '.closuresState.windowOpenPassengerRear' binary_sensor/window_open_pass_rear "$TESLACTRLOUT" + getStateValueAndPublish $vin '.closuresState.doorOpenDriverFront' binary_sensor/door_open_driver_front "$TESLACTRLOUT" + getStateValueAndPublish $vin '.closuresState.doorOpenPassengerFront' binary_sensor/door_open_pass_front "$TESLACTRLOUT" + getStateValueAndPublish $vin '.closuresState.doorOpenDriverRear' binary_sensor/door_open_driver_rear "$TESLACTRLOUT" + getStateValueAndPublish $vin '.closuresState.doorOpenPassengerRear' binary_sensor/door_open_pass_rear "$TESLACTRLOUT" + getStateValueAndPublish $vin '.closuresState.locked' lock/locked "$TESLACTRLOUT" # Publish to windows cover state topic if [ $ANYWINDOWOPEN == "true" ]; then @@ -530,7 +461,6 @@ function closuresState() { stateMQTTpub $vin "false" "cover/windows" fi - return $ret } function driveState() { @@ -545,20 +475,10 @@ function driveState() { log_debug "driveState; sendBLECommand failed for vin:$vin return:$ret" return $ret else - log_debug "driveState; sendBLECommand succeeded for vin:$vin" + log_warning "driveState; sendBLECommand succeeded for vin:$vin" fi # Get values from the JSON and publish corresponding MQTT state topic getStateValueAndPublish $vin '.driveState.odometerInHundredthsOfAMile' sensor/odometer "$TESLACTRLOUT" - EXIT_STATUS=$? - if [ $EXIT_STATUS -ne 0 ]; then - ret=3 - log_error "driveState; one of the getStateValueAndPublish calls failed for vin:$vin return:$ret" - else - ret=0 - log_info "driveState; Completed successfully for vin:$vin" - fi - - return $ret } From c3ee9e74572ac90cc7e6653ca79ce712ed10613b Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Tue, 7 Jan 2025 15:36:50 +0000 Subject: [PATCH 43/75] Fix Force Update All --- mqtt-discovery.sh | 2 +- read-state.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mqtt-discovery.sh b/mqtt-discovery.sh index 0c7c81c..a1d01e6 100644 --- a/mqtt-discovery.sh +++ b/mqtt-discovery.sh @@ -816,7 +816,7 @@ function setupDiagnostic() { "icon": "mdi:database-sync", "name": "Force Update All", "entity_category": "diagnostic", - "payload_press": "read-state", + "payload_press": "read-state-all", "qos": "'${QOS_LEVEL}'", "unique_id": "'${DEVICE_ID}'_read-state" }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 6 10 -t homeassistant/button/${DEVICE_ID}/read-state-all/config -l diff --git a/read-state.sh b/read-state.sh index 72bd674..8e83a35 100644 --- a/read-state.sh +++ b/read-state.sh @@ -358,7 +358,7 @@ function readChargeState() { getStateValueAndPublish $vin '.chargeState.chargeRateMph' sensor/charge_speed "$TESLACTRLOUT" getStateValueAndPublish $vin '.chargeState.connChargeCable' sensor/charge_cable "$TESLACTRLOUT" getStateValueAndPublish $vin '.chargeState.chargeEnableRequest' switch/charge_enable_request "$TESLACTRLOUT" - getStateValueAndPublish $vin '.chargeState.chrgePortDoorOpen' cover/charge_port_door_open "$TESLACTRLOUT" + getStateValueAndPublish $vin '.chargeState.chargePortDoorOpen' cover/charge_port_door_open "$TESLACTRLOUT" getStateValueAndPublish $vin '.chargeState.chargeCurrentRequest' number/charge_current_request "$TESLACTRLOUT" getStateValueAndPublish $vin '.chargeState.chargeLimitSoc' number/charge_limit_soc "$TESLACTRLOUT" From 4cc752d0657047555fa48c363c43d1961797033f Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Tue, 7 Jan 2025 17:08:06 +0000 Subject: [PATCH 44/75] Delete config and command messages --- mqtt-discovery.sh | 13 +++++++++---- run.sh | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/mqtt-discovery.sh b/mqtt-discovery.sh index a1d01e6..1303249 100644 --- a/mqtt-discovery.sh +++ b/mqtt-discovery.sh @@ -962,12 +962,17 @@ setupHADiscoveryAllVINsMain() { else log_info "setupHADiscoveryAllVINsMain; HA backend is disable, skipping setup for HA Auto Discovery" fi + + # Discard /config and /command messages + log_notice "setupHADiscoveryAllVINsMain; Discarding unread MQTT messages for command and config topics" + eval $MOSQUITTO_PUB_BASE -t tesla_ble/$vin/config -n + eval $MOSQUITTO_PUB_BASE -t tesla_ble/$vin/command -n done - # Discard /config messages - topic=tesla_ble/$vin/config - log_notice "setupHADiscoveryAllVINsMain; Discarding any unread MQTT messages for topic:$topic" - eval $MOSQUITTO_SUB_BASE -E -i tesla_ble_mqtt -t $topic + #topic=tesla_ble/$vin/config + #log_notice "setupHADiscoveryAllVINsMain; Discarding any unread MQTT messages for topic:$topic" + #eval $MOSQUITTO_SUB_BASE -E -i tesla_ble_mqtt -t $topic + } ### diff --git a/run.sh b/run.sh index 98f0b21..5ddc9a5 100755 --- a/run.sh +++ b/run.sh @@ -64,7 +64,7 @@ for vin in $VIN_LIST; do else # Remove single entities (brute force command, no easy way to collect declared MQTT topics crossplatform) log_notice "Removing single buttons to be replaced by switches & covers:" - log_notice "windows, charger, cherge-port, climate, trunk" + log_notice "windows, charger, charge-port, climate, trunk" delete_legacies_singles $vin fi # END TEMPORARY From da37a49ba6f923bd4d1404f19ee146e83c9db9f8 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Tue, 7 Jan 2025 17:45:57 +0000 Subject: [PATCH 45/75] log_debug --- read-state.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/read-state.sh b/read-state.sh index 8e83a35..be55067 100644 --- a/read-state.sh +++ b/read-state.sh @@ -475,7 +475,7 @@ function driveState() { log_debug "driveState; sendBLECommand failed for vin:$vin return:$ret" return $ret else - log_warning "driveState; sendBLECommand succeeded for vin:$vin" + log_debug "driveState; sendBLECommand succeeded for vin:$vin" fi # Get values from the JSON and publish corresponding MQTT state topic From 793af8a75fe9bef4ddf816d00b58628254fcaf8d Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Tue, 7 Jan 2025 17:55:11 +0000 Subject: [PATCH 46/75] Remove obsolete code --- mqtt-discovery.sh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/mqtt-discovery.sh b/mqtt-discovery.sh index 1303249..819a74a 100644 --- a/mqtt-discovery.sh +++ b/mqtt-discovery.sh @@ -968,10 +968,6 @@ setupHADiscoveryAllVINsMain() { eval $MOSQUITTO_PUB_BASE -t tesla_ble/$vin/config -n eval $MOSQUITTO_PUB_BASE -t tesla_ble/$vin/command -n done - - #topic=tesla_ble/$vin/config - #log_notice "setupHADiscoveryAllVINsMain; Discarding any unread MQTT messages for topic:$topic" - #eval $MOSQUITTO_SUB_BASE -E -i tesla_ble_mqtt -t $topic } From f102ad26175117e36d0b8affba3147e8829e8d7a Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Wed, 8 Jan 2025 06:43:02 +0000 Subject: [PATCH 47/75] Make loop 1 day --- read-state.sh | 4 ++-- version.sh | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/read-state.sh b/read-state.sh index be55067..a9e7081 100644 --- a/read-state.sh +++ b/read-state.sh @@ -11,9 +11,9 @@ function poll_state_loop() { # Loop indefinitely while :; do - # Loop for an hour (max polling interval) + # Loop for a day (arbitary but need to be a long time as modulus may slip when it resets casuing an early poll) i=0 - while [ $i -le 3600 ]; do + while [ $i -le 86400 ]; do # Repeat for each car for vin in $VIN_LIST; do diff --git a/version.sh b/version.sh index cde4221..cd1fb31 100644 --- a/version.sh +++ b/version.sh @@ -2,4 +2,5 @@ # # shellcheck shell=dash # -export SW_VERSION=0.3.1 +export SW_VERSION=0.4.0 +log_info "Version is $SW_VERSION" From a4ead175dd2f417013902ac026317f21222f4356 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Wed, 8 Jan 2025 06:43:27 +0000 Subject: [PATCH 48/75] Core version message --- version.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sh b/version.sh index cd1fb31..b95c58a 100644 --- a/version.sh +++ b/version.sh @@ -3,4 +3,4 @@ # shellcheck shell=dash # export SW_VERSION=0.4.0 -log_info "Version is $SW_VERSION" +log_info "Core version is $SW_VERSION" From 2b7721c8ef2412e9df5d4586750890009483d985 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Wed, 8 Jan 2025 16:51:50 +0000 Subject: [PATCH 49/75] Add Presence_BC feature --- CHANGELOG.md | 3 ++- mqtt-discovery-sensors.sh | 22 +++++++++++++++++ read-state.sh | 52 +++++++++++++++++++-------------------- version.sh | 2 +- 4 files changed, 51 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e3f029..f120b26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,12 @@ # Changelog -## 0.4.0 +## 0.4.1 - RELEASE NEW Feature: Automatic Polling is now possible for state - NEW Feature: The following new states / entities are added: - Sensors: Awake + - Binary_Sensors: Presence_BC (experimental presence detection using tesla-control body_controller_state rather than listening for BLE mac) - Switches: Polling - Numbers: Polling Interval - Buttons: Force Update buttons for individual state categories diff --git a/mqtt-discovery-sensors.sh b/mqtt-discovery-sensors.sh index fe04418..de11afd 100644 --- a/mqtt-discovery-sensors.sh +++ b/mqtt-discovery-sensors.sh @@ -731,6 +731,28 @@ function setupChargeStateSensors { "unique_id": "'${DEVICE_ID}'_awake" }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 36 10 -t homeassistant/binary_sensor/${DEVICE_ID}/awake/config -l + echo '{ + "state_topic": "'${TOPIC_ROOT}'/binary_sensor/presence_bc", + "device": { + "identifiers": [ + "'${DEVICE_ID}'" + ], + "manufacturer": "tesla-local-control", + "model": "Tesla_BLE", + "name": "'${DEVICE_NAME}'", + "sw_version": "'${SW_VERSION}'" + }, + "platform": "binary_sensor", + "name": "Presence BC", + "payload_on": "true", + "payload_off": "false", + "qos": "'${QOS_LEVEL}'", + "device_class": "presence", + "icon": "mdi:car-connected", + "enabled_by_default": "false", + "unique_id": "'${DEVICE_ID}'_presence_bc" + }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 36 10 -t homeassistant/binary_sensor/${DEVICE_ID}/presence_bc/config -l + # Status is only Disengaged for short time, it gets reengaged soon after even with no charger plugged in. Not useful # echo '{ # "state_topic": "'${TOPIC_ROOT}'/binary_sensor/charge_port_latch", diff --git a/read-state.sh b/read-state.sh index a9e7081..661c70c 100644 --- a/read-state.sh +++ b/read-state.sh @@ -30,42 +30,42 @@ function poll_state_loop() { eval export ${vin}_$assign done fi - # Get variables for this VIN. Note ash needs to use eval for dynamic variables polling=$( eval "echo \"\$${vin}_polling\"" ) polling_interval=$( eval "echo \"\$${vin}_polling_interval\"" ) - - # Check if polling turned off for this car - if [ "$polling" != "on" ]; then - log_debug "Polling is off for VIN: $vin, skipping" - else - log_debug "Polling is on for VIN: $vin, checking interval" - - # Is counter divisible by interval with no remainder? If so, it is time to attempt to poll - mod=$(( i % $polling_interval )) - if [ $mod -ne 0 ]; then - log_debug "Count not divisible by polling_interval for VIN: $vin, Count: $i, Interval: $polling_interval" - else - log_info "Attempting to poll VIN: $vin" - # Send a body-controller-state command. This checks if car is in bluetooth range and whether awake or asleep without acutally waking it - set +e - retjson=$( /usr/bin/tesla-control -ble -vin $vin -command-timeout 5s -connect-timeout 10s body-controller-state 2>&1 ) - EXIT_VALUE=$? - set -e - # If non zero, car is not contactable by bluetooth - if [ $EXIT_VALUE -ne 0 ]; then - log_warning "Car is not responding to bluetooth, maybe it's away. Not attempting to poll. VIN: $vin" + # Send a body-controller-state command. This checks if car is in bluetooth range and whether awake or asleep without acutally waking it + set +e + bcs_json=$( /usr/bin/tesla-control -ble -vin $vin -command-timeout 5s -connect-timeout 10s body-controller-state 2>&1 ) + EXIT_VALUE=$? + set -e + # If non zero, car is not contactable by bluetooth + if [ $EXIT_VALUE -ne 0 ]; then + log_warning "Car is not responding to bluetooth, maybe it's away. Not attempting to poll. VIN: $vin" + # Publish to MQTT presence_bc sensor. TODO: Set awake sensor to Unknown via MQTT availability + stateMQTTpub $vin 'false' 'binary_sensor/presence_bc' - # TODO: Update a future presence sensor. Set awake sensor to Unknown via MQTT availability + else + # Publish to MQTT presence_bc sensor. + stateMQTTpub $vin 'true' 'binary_sensor/presence_bc' + # Check if polling turned off for this car + if [ "$polling" != "on" ]; then + log_debug "Polling is off for VIN: $vin, skipping" + else + log_debug "Polling is on for VIN: $vin, checking interval" + # Is counter divisible by interval with no remainder? If so, it is time to attempt to poll + mod=$(( i % $polling_interval )) + if [ $mod -ne 0 ]; then + log_debug "Count not divisible by polling_interval for VIN: $vin, Count: $i, Interval: $polling_interval" + else + log_info "Attempting to poll VIN: $vin" # Car has responded. Check if awake or asleep from the body-controller-state response - rqdValue=$(echo $retjson | jq -e '.vehicleSleepStatus') + rqdValue=$(echo $bcs_json | jq -e '.vehicleSleepStatus') EXIT_VALUE=$? if [ $EXIT_VALUE -eq 0 ] && [ "$rqdValue" == "\"VEHICLE_SLEEP_STATUS_AWAKE\"" ]; then - log_info "Car is awake, so polling VIN: $vin" - + log_info "Car is awake, so polling VIN: $vin" # Publish to MQTT awake topic, 'press' the Data Update Env button (which checks NO_POLL_SECTIONS environment variable to exclude various sections if required) stateMQTTpub $vin 'true' 'binary_sensor/awake' stateMQTTpub $vin 'read-state-envcheck' 'config' diff --git a/version.sh b/version.sh index b95c58a..4df9d98 100644 --- a/version.sh +++ b/version.sh @@ -2,5 +2,5 @@ # # shellcheck shell=dash # -export SW_VERSION=0.4.0 +export SW_VERSION=0.4.1 log_info "Core version is $SW_VERSION" From 69b88625a183e9b56c79e8e74346a9d6a5a21712 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Wed, 8 Jan 2025 17:40:02 +0000 Subject: [PATCH 50/75] Check if awake every 30 secs --- read-state.sh | 50 +++++++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/read-state.sh b/read-state.sh index 661c70c..db1cd56 100644 --- a/read-state.sh +++ b/read-state.sh @@ -18,7 +18,7 @@ function poll_state_loop() { # Repeat for each car for vin in $VIN_LIST; do - log_debug "poll_state_loop: Setting variables from MQTT for VIN: $vin" + log_debug "poll_state_loop: Setting variables from MQTT for VIN:$vin" set +e mqttOp=$( eval $MOSQUITTO_SUB_BASE --nodelay -W 1 --topic tesla_ble/$vin/variables/+ -F \"%t=%p\" 2>/dev/null ) EXIT_CODE=$? @@ -41,38 +41,42 @@ function poll_state_loop() { set -e # If non zero, car is not contactable by bluetooth if [ $EXIT_VALUE -ne 0 ]; then - log_warning "Car is not responding to bluetooth, maybe it's away. Not attempting to poll. VIN: $vin" + log_info "Car is not responding to bluetooth, assuming it's away. VIN:$vin" # Publish to MQTT presence_bc sensor. TODO: Set awake sensor to Unknown via MQTT availability stateMQTTpub $vin 'false' 'binary_sensor/presence_bc' else - # Publish to MQTT presence_bc sensor. + # Car has responded + log_debug "Car has responded to bluetooth, it is present. VIN:$vin" stateMQTTpub $vin 'true' 'binary_sensor/presence_bc' - # Check if polling turned off for this car - if [ "$polling" != "on" ]; then - log_debug "Polling is off for VIN: $vin, skipping" + + # Check if awake or asleep from the body-controller-state response + rqdValue=$(echo $bcs_json | jq -e '.vehicleSleepStatus') + EXIT_VALUE=$? + if [ $EXIT_VALUE -ne 0 ] || [ "$rqdValue" != "\"VEHICLE_SLEEP_STATUS_AWAKE\"" ]; then + log_info "Car is present but asleep VIN:$vin" + stateMQTTpub $vin 'false' 'binary_sensor/awake' else - log_debug "Polling is on for VIN: $vin, checking interval" - # Is counter divisible by interval with no remainder? If so, it is time to attempt to poll - mod=$(( i % $polling_interval )) - if [ $mod -ne 0 ]; then - log_debug "Count not divisible by polling_interval for VIN: $vin, Count: $i, Interval: $polling_interval" - + log_info "Car is present and awake VIN:$vin" + stateMQTTpub $vin 'true' 'binary_sensor/awake' + + # Check if polling turned off for this car + if [ "$polling" != "on" ]; then + log_debug "Polling is off for VIN: $vin, skipping" + else - log_info "Attempting to poll VIN: $vin" - # Car has responded. Check if awake or asleep from the body-controller-state response - rqdValue=$(echo $bcs_json | jq -e '.vehicleSleepStatus') - EXIT_VALUE=$? - if [ $EXIT_VALUE -eq 0 ] && [ "$rqdValue" == "\"VEHICLE_SLEEP_STATUS_AWAKE\"" ]; then - log_info "Car is awake, so polling VIN: $vin" - # Publish to MQTT awake topic, 'press' the Data Update Env button (which checks NO_POLL_SECTIONS environment variable to exclude various sections if required) - stateMQTTpub $vin 'true' 'binary_sensor/awake' + log_debug "Polling is on for VIN: $vin, checking interval" + # Is counter divisible by interval with no remainder? If so, it is time to attempt to poll + mod=$(( i % $polling_interval )) + if [ $mod -ne 0 ]; then + log_debug "Count not divisible by polling_interval for VIN: $vin, Count: $i, Interval: $polling_interval" + + else + log_info "Polling VIN: $vin" + # 'Press' the Data Update Env button (which checks NO_POLL_SECTIONS environment variable to exclude various sections if required) stateMQTTpub $vin 'read-state-envcheck' 'config' - else - log_info "Car is asleep, not polling VIN: $vin" - stateMQTTpub $vin 'false' 'binary_sensor/awake' fi fi From 62963ba3685bff47905a18ece5d11163e96446f1 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Wed, 8 Jan 2025 17:48:19 +0000 Subject: [PATCH 51/75] Reduce log spam --- CHANGELOG.md | 4 ++-- mqtt-listen.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f120b26..c8a1e1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,8 +5,8 @@ - RELEASE NEW Feature: Automatic Polling is now possible for state - NEW Feature: The following new states / entities are added: - - Sensors: Awake - - Binary_Sensors: Presence_BC (experimental presence detection using tesla-control body_controller_state rather than listening for BLE mac) + - Sensors: Awake (updated approx every 30 secs from body-controller-state) + - Binary_Sensors: Presence_BC (experimental presence detection updated approx every 30 secs from body_controller_state rather than listening for BLE mac) - Switches: Polling - Numbers: Polling Interval - Buttons: Force Update buttons for individual state categories diff --git a/mqtt-listen.sh b/mqtt-listen.sh index 30a1910..99dfb2f 100755 --- a/mqtt-listen.sh +++ b/mqtt-listen.sh @@ -33,7 +33,7 @@ listen_to_mqtt() { topic_stripped=${topic#*/} vin=${topic_stripped%/*} cmd=${topic_stripped#*/} - log_info "Received MQTT message; topic:$topic msg:$msg vin:$vin cmd:$cmd" + log_debug "Received MQTT message; topic:$topic msg:$msg vin:$vin cmd:$cmd" case $cmd in config) From 94a21d7a75f08132d284e9d9663ae8237c6ed182 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Wed, 8 Jan 2025 17:52:44 +0000 Subject: [PATCH 52/75] More log spam reduction --- mqtt-listen.sh | 2 +- read-state.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mqtt-listen.sh b/mqtt-listen.sh index 99dfb2f..30a1910 100755 --- a/mqtt-listen.sh +++ b/mqtt-listen.sh @@ -33,7 +33,7 @@ listen_to_mqtt() { topic_stripped=${topic#*/} vin=${topic_stripped%/*} cmd=${topic_stripped#*/} - log_debug "Received MQTT message; topic:$topic msg:$msg vin:$vin cmd:$cmd" + log_info "Received MQTT message; topic:$topic msg:$msg vin:$vin cmd:$cmd" case $cmd in config) diff --git a/read-state.sh b/read-state.sh index db1cd56..59ca87b 100644 --- a/read-state.sh +++ b/read-state.sh @@ -104,7 +104,7 @@ function stateMQTTpub() { MQTT_TOPIC="tesla_ble/$vin/$topic" - log_info "Setting MQTT topic $MQTT_TOPIC to $state" + log_debug "Setting MQTT topic $MQTT_TOPIC to $state" # Maybe we need a function in the future for mosquitto_pub w/ retry set +e From c3c1bd4b912d72c835e73d38771d7c83b803eaaf Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Thu, 9 Jan 2025 14:41:34 +0000 Subject: [PATCH 53/75] More MQTT logs but less spam --- read-state.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/read-state.sh b/read-state.sh index 59ca87b..05e0f2c 100644 --- a/read-state.sh +++ b/read-state.sh @@ -55,11 +55,11 @@ function poll_state_loop() { EXIT_VALUE=$? if [ $EXIT_VALUE -ne 0 ] || [ "$rqdValue" != "\"VEHICLE_SLEEP_STATUS_AWAKE\"" ]; then log_info "Car is present but asleep VIN:$vin" - stateMQTTpub $vin 'false' 'binary_sensor/awake' + stateMQTTpub $vin 'asleep' 'binary_sensor/awake' else log_info "Car is present and awake VIN:$vin" - stateMQTTpub $vin 'true' 'binary_sensor/awake' + stateMQTTpub $vin 'awake' 'binary_sensor/awake' # Check if polling turned off for this car if [ "$polling" != "on" ]; then @@ -114,7 +114,12 @@ function stateMQTTpub() { [ $EXIT_STATUS -ne 0 ] && log_error "${MQTT_OUT}" && return 1 - log_debug "MQTT topic $MQTT_TOPIC succesfully updated to $state" + if [ $topic == "binary_sensor/presence_bc" ] || [ $topic == "binary_sensor/asleep" ] + # Don't spam the logs for these topics + log_debug "MQTT topic $MQTT_TOPIC successfully updated to $state" + else + log_info "MQTT topic $MQTT_TOPIC successfully updated to $state" + fi return 0 From cf41e3980e93ea4ce3951dd04267aa32a60efb48 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Thu, 9 Jan 2025 15:05:29 +0000 Subject: [PATCH 54/75] Add force update to certain sensors --- mqtt-discovery-sensors.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mqtt-discovery-sensors.sh b/mqtt-discovery-sensors.sh index de11afd..f63d2cf 100644 --- a/mqtt-discovery-sensors.sh +++ b/mqtt-discovery-sensors.sh @@ -57,6 +57,7 @@ function setupChargeStateSensors { "device_class": "battery", "unit_of_measurement": "%", "suggested_display_precision": "0", + "force_update": "true", "unique_id": "'${DEVICE_ID}'_charge_state" }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 36 10 -t homeassistant/sensor/${DEVICE_ID}/charge_state/config -l @@ -310,7 +311,8 @@ function setupChargeStateSensors { "qos": "'${QOS_LEVEL}'", "device_class": "temperature", "unit_of_measurement": "°C", - "suggested_display_precision": "1", + "suggested_display_precision": "1", + "force_update": "true", "unique_id": "'${DEVICE_ID}'_inside_temp" }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 36 10 -t homeassistant/sensor/${DEVICE_ID}/inside_temp/config -l From e96c6e0414994939cfeafe83ef4ee425b1e673c0 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Thu, 9 Jan 2025 15:54:21 +0000 Subject: [PATCH 55/75] Fix typo --- read-state.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/read-state.sh b/read-state.sh index 05e0f2c..9e75c7d 100644 --- a/read-state.sh +++ b/read-state.sh @@ -114,7 +114,7 @@ function stateMQTTpub() { [ $EXIT_STATUS -ne 0 ] && log_error "${MQTT_OUT}" && return 1 - if [ $topic == "binary_sensor/presence_bc" ] || [ $topic == "binary_sensor/asleep" ] + if [ $topic == "binary_sensor/presence_bc" ] || [ $topic == "binary_sensor/asleep" ]; then # Don't spam the logs for these topics log_debug "MQTT topic $MQTT_TOPIC successfully updated to $state" else From b458be62807ffdd7182e8109ab473a360d81b289 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Thu, 9 Jan 2025 16:09:11 +0000 Subject: [PATCH 56/75] awake asleep true false --- read-state.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/read-state.sh b/read-state.sh index 9e75c7d..2dc988e 100644 --- a/read-state.sh +++ b/read-state.sh @@ -55,11 +55,11 @@ function poll_state_loop() { EXIT_VALUE=$? if [ $EXIT_VALUE -ne 0 ] || [ "$rqdValue" != "\"VEHICLE_SLEEP_STATUS_AWAKE\"" ]; then log_info "Car is present but asleep VIN:$vin" - stateMQTTpub $vin 'asleep' 'binary_sensor/awake' + stateMQTTpub $vin 'false' 'binary_sensor/awake' else log_info "Car is present and awake VIN:$vin" - stateMQTTpub $vin 'awake' 'binary_sensor/awake' + stateMQTTpub $vin 'true' 'binary_sensor/awake' # Check if polling turned off for this car if [ "$polling" != "on" ]; then @@ -114,7 +114,8 @@ function stateMQTTpub() { [ $EXIT_STATUS -ne 0 ] && log_error "${MQTT_OUT}" && return 1 - if [ $topic == "binary_sensor/presence_bc" ] || [ $topic == "binary_sensor/asleep" ]; then + + if [ $topic == "binary_sensor/presence_bc" ] || [ $topic == "binary_sensor/awake" ]; then # Don't spam the logs for these topics log_debug "MQTT topic $MQTT_TOPIC successfully updated to $state" else From c6ddcba5a51a267f71a42ce6493509be8e290a9e Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Thu, 9 Jan 2025 16:51:57 +0000 Subject: [PATCH 57/75] Remove force update not reqd --- mqtt-discovery-sensors.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/mqtt-discovery-sensors.sh b/mqtt-discovery-sensors.sh index f63d2cf..d42338d 100644 --- a/mqtt-discovery-sensors.sh +++ b/mqtt-discovery-sensors.sh @@ -57,7 +57,6 @@ function setupChargeStateSensors { "device_class": "battery", "unit_of_measurement": "%", "suggested_display_precision": "0", - "force_update": "true", "unique_id": "'${DEVICE_ID}'_charge_state" }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 36 10 -t homeassistant/sensor/${DEVICE_ID}/charge_state/config -l @@ -312,7 +311,6 @@ function setupChargeStateSensors { "device_class": "temperature", "unit_of_measurement": "°C", "suggested_display_precision": "1", - "force_update": "true", "unique_id": "'${DEVICE_ID}'_inside_temp" }' | sed ':a;N;$!ba;s/\n//g' | retryMQTTpub 36 10 -t homeassistant/sensor/${DEVICE_ID}/inside_temp/config -l From 3a582a9c87c76a5b84b496a2fb2ebc13521cc459 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Fri, 10 Jan 2025 11:02:14 +0000 Subject: [PATCH 58/75] Create poll_state function --- read-state.sh | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/read-state.sh b/read-state.sh index 2dc988e..827433b 100644 --- a/read-state.sh +++ b/read-state.sh @@ -7,16 +7,29 @@ ## function poll_state_loop. For future implementation function poll_state_loop() { log_notice "Entering poll_state_loop..." - # Loop indefinitely while :; do - - # Loop for a day (arbitary but need to be a long time as modulus may slip when it resets casuing an early poll) + # Loop for a day (arbitary but need to be a long time as modulus may slip when it resets causing an early poll) i=0 while [ $i -le 86400 ]; do - # Repeat for each car for vin in $VIN_LIST; do + # Call poll_state via MQTT command queue + done + # Loop repeat approx every 30 secs + sleep 29 + i=$(( i + 30 )) + done + done +} + +function poll_state() { +vin=$1 +loop_count=$2 + +echo VIN $vin +echo Count: $loop_count +return 0 log_debug "poll_state_loop: Setting variables from MQTT for VIN:$vin" set +e @@ -85,15 +98,6 @@ function poll_state_loop() { fi - done - - # Loop repeat approx every 30 secs - sleep 29 - i=$(( i + 30 )) - - done - - done } From eb11d6d7f0cd8325b4a01d378ea10caf7db8aa4f Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Fri, 10 Jan 2025 11:29:04 +0000 Subject: [PATCH 59/75] publish poll_state to MQTT --- mqtt-listen.sh | 5 +++++ read-state.sh | 1 + 2 files changed, 6 insertions(+) diff --git a/mqtt-listen.sh b/mqtt-listen.sh index 30a1910..7d00168 100755 --- a/mqtt-listen.sh +++ b/mqtt-listen.sh @@ -249,6 +249,11 @@ listen_to_mqtt() { # These get handled in the subshell where they are used ;; + poll_state) + # Attempt to poll state for selected vehicle ($vin=vin, $msg=loop count from poll_state_loop) + poll_state $vin $msg + ;; + *) log_error "Invalid request; topic:$topic vin:$vin msg:$msg" ;; diff --git a/read-state.sh b/read-state.sh index 827433b..408de1c 100644 --- a/read-state.sh +++ b/read-state.sh @@ -15,6 +15,7 @@ function poll_state_loop() { # Repeat for each car for vin in $VIN_LIST; do # Call poll_state via MQTT command queue + stateMQTTpub $vin $1 'poll_state' done # Loop repeat approx every 30 secs sleep 29 From 05d5dae454c2e9d53f70ac89e418cf5bf65da17f Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Fri, 10 Jan 2025 12:05:16 +0000 Subject: [PATCH 60/75] Poll now triggered by MQTT --- read-state.sh | 142 +++++++++++++++++++++++++------------------------- 1 file changed, 71 insertions(+), 71 deletions(-) diff --git a/read-state.sh b/read-state.sh index 408de1c..5acf281 100644 --- a/read-state.sh +++ b/read-state.sh @@ -15,7 +15,7 @@ function poll_state_loop() { # Repeat for each car for vin in $VIN_LIST; do # Call poll_state via MQTT command queue - stateMQTTpub $vin $1 'poll_state' + stateMQTTpub $vin $i 'poll_state' done # Loop repeat approx every 30 secs sleep 29 @@ -28,78 +28,78 @@ function poll_state() { vin=$1 loop_count=$2 -echo VIN $vin +#echo VIN $vin echo Count: $loop_count -return 0 - - log_debug "poll_state_loop: Setting variables from MQTT for VIN:$vin" - set +e - mqttOp=$( eval $MOSQUITTO_SUB_BASE --nodelay -W 1 --topic tesla_ble/$vin/variables/+ -F \"%t=%p\" 2>/dev/null ) - EXIT_CODE=$? - set -e - if [ $EXIT_CODE -eq 27 ]; then - for item in $mqttOp; do - assign=${item##*/} - log_debug "Setting variable from MQTT: $assign" - eval export ${vin}_$assign - done - fi - # Get variables for this VIN. Note ash needs to use eval for dynamic variables - polling=$( eval "echo \"\$${vin}_polling\"" ) - polling_interval=$( eval "echo \"\$${vin}_polling_interval\"" ) - - # Send a body-controller-state command. This checks if car is in bluetooth range and whether awake or asleep without acutally waking it - set +e - bcs_json=$( /usr/bin/tesla-control -ble -vin $vin -command-timeout 5s -connect-timeout 10s body-controller-state 2>&1 ) - EXIT_VALUE=$? - set -e - # If non zero, car is not contactable by bluetooth - if [ $EXIT_VALUE -ne 0 ]; then - log_info "Car is not responding to bluetooth, assuming it's away. VIN:$vin" - # Publish to MQTT presence_bc sensor. TODO: Set awake sensor to Unknown via MQTT availability - stateMQTTpub $vin 'false' 'binary_sensor/presence_bc' - - else - # Car has responded - log_debug "Car has responded to bluetooth, it is present. VIN:$vin" - stateMQTTpub $vin 'true' 'binary_sensor/presence_bc' - - # Check if awake or asleep from the body-controller-state response - rqdValue=$(echo $bcs_json | jq -e '.vehicleSleepStatus') - EXIT_VALUE=$? - if [ $EXIT_VALUE -ne 0 ] || [ "$rqdValue" != "\"VEHICLE_SLEEP_STATUS_AWAKE\"" ]; then - log_info "Car is present but asleep VIN:$vin" - stateMQTTpub $vin 'false' 'binary_sensor/awake' - - else - log_info "Car is present and awake VIN:$vin" - stateMQTTpub $vin 'true' 'binary_sensor/awake' - - # Check if polling turned off for this car - if [ "$polling" != "on" ]; then - log_debug "Polling is off for VIN: $vin, skipping" - - else - log_debug "Polling is on for VIN: $vin, checking interval" - # Is counter divisible by interval with no remainder? If so, it is time to attempt to poll - mod=$(( i % $polling_interval )) - if [ $mod -ne 0 ]; then - log_debug "Count not divisible by polling_interval for VIN: $vin, Count: $i, Interval: $polling_interval" - - else - log_info "Polling VIN: $vin" - # 'Press' the Data Update Env button (which checks NO_POLL_SECTIONS environment variable to exclude various sections if required) - stateMQTTpub $vin 'read-state-envcheck' 'config' - - fi - - fi - - fi - - fi +log_debug "poll_state_loop: Setting variables from MQTT for VIN:$vin" +set +e +mqttOp=$( eval $MOSQUITTO_SUB_BASE --nodelay -W 1 --topic tesla_ble/$vin/variables/+ -F \"%t=%p\" 2>/dev/null ) +EXIT_CODE=$? +set -e +if [ $EXIT_CODE -eq 27 ]; then + for item in $mqttOp; do + assign=${item##*/} + log_debug "Setting variable from MQTT: $assign" + eval export ${vin}_$assign + done +fi + +# Get variables for this VIN. Note ash needs to use eval for dynamic variables +polling=$( eval "echo \"\$${vin}_polling\"" ) +polling_interval=$( eval "echo \"\$${vin}_polling_interval\"" ) + +# Send a body-controller-state command. This checks if car is in bluetooth range and whether awake or asleep without acutally waking it +set +e +bcs_json=$( /usr/bin/tesla-control -ble -vin $vin -command-timeout 5s -connect-timeout 10s body-controller-state 2>&1 ) +EXIT_VALUE=$? +set -e + +# If non zero, car is not contactable by bluetooth +if [ $EXIT_VALUE -ne 0 ]; then + log_info "Car is not responding to bluetooth, assuming it's away. VIN:$vin" + # Publish to MQTT presence_bc sensor. TODO: Set awake sensor to Unknown via MQTT availability + stateMQTTpub $vin 'false' 'binary_sensor/presence_bc' + +else + # Car has responded + log_debug "Car has responded to bluetooth, it is present. VIN:$vin" + stateMQTTpub $vin 'true' 'binary_sensor/presence_bc' + + # Check if awake or asleep from the body-controller-state response + rqdValue=$(echo $bcs_json | jq -e '.vehicleSleepStatus') + EXIT_VALUE=$? + if [ $EXIT_VALUE -ne 0 ] || [ "$rqdValue" != "\"VEHICLE_SLEEP_STATUS_AWAKE\"" ]; then + log_info "Car is present but asleep VIN:$vin" + stateMQTTpub $vin 'false' 'binary_sensor/awake' + + else + log_info "Car is present and awake VIN:$vin" + stateMQTTpub $vin 'true' 'binary_sensor/awake' + + # Check if polling turned off for this car + if [ "$polling" != "on" ]; then + log_debug "Polling is off for VIN: $vin, skipping" + + else + log_debug "Polling is on for VIN: $vin, checking interval" + + # Is counter divisible by interval with no remainder? If so, it is time to attempt to poll + mod=$(( i % $polling_interval )) + if [ $mod -ne 0 ]; then + log_debug "Count not divisible by polling_interval for VIN: $vin, Count: $i, Interval: $polling_interval" + + else + log_info "Polling VIN: $vin" + # 'Press' the Data Update Env button (which checks NO_POLL_SECTIONS environment variable to exclude various sections if required) + stateMQTTpub $vin 'read-state-envcheck' 'config' + + fi + + fi + + fi +fi } function stateMQTTpub() { @@ -120,7 +120,7 @@ function stateMQTTpub() { log_error "${MQTT_OUT}" && return 1 - if [ $topic == "binary_sensor/presence_bc" ] || [ $topic == "binary_sensor/awake" ]; then + if [ $topic == "binary_sensor/presence_bc" ] || [ $topic == "binary_sensor/awake" ] || [ $topic == "poll_state" ]; then # Don't spam the logs for these topics log_debug "MQTT topic $MQTT_TOPIC successfully updated to $state" else From 9f6cc7b91781bd8a0a64e2738a4a6681996ba844 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Fri, 10 Jan 2025 12:15:10 +0000 Subject: [PATCH 61/75] Reduce log spam --- mqtt-listen.sh | 10 ++++++++-- read-state.sh | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/mqtt-listen.sh b/mqtt-listen.sh index 7d00168..cf3bd87 100755 --- a/mqtt-listen.sh +++ b/mqtt-listen.sh @@ -33,8 +33,14 @@ listen_to_mqtt() { topic_stripped=${topic#*/} vin=${topic_stripped%/*} cmd=${topic_stripped#*/} - log_info "Received MQTT message; topic:$topic msg:$msg vin:$vin cmd:$cmd" + # Don't spam the logs for these topics/ commands + if [ $cmd == "poll_state" ]; then + log_debug "Received MQTT message; topic:$topic msg:$msg vin:$vin cmd:$cmd" + else + log_info "Received MQTT message; topic:$topic msg:$msg vin:$vin cmd:$cmd" + fi + case $cmd in config) @@ -253,7 +259,7 @@ listen_to_mqtt() { # Attempt to poll state for selected vehicle ($vin=vin, $msg=loop count from poll_state_loop) poll_state $vin $msg ;; - + *) log_error "Invalid request; topic:$topic vin:$vin msg:$msg" ;; diff --git a/read-state.sh b/read-state.sh index 5acf281..2f62d58 100644 --- a/read-state.sh +++ b/read-state.sh @@ -120,8 +120,8 @@ function stateMQTTpub() { log_error "${MQTT_OUT}" && return 1 + # Don't spam the logs for these topics if [ $topic == "binary_sensor/presence_bc" ] || [ $topic == "binary_sensor/awake" ] || [ $topic == "poll_state" ]; then - # Don't spam the logs for these topics log_debug "MQTT topic $MQTT_TOPIC successfully updated to $state" else log_info "MQTT topic $MQTT_TOPIC successfully updated to $state" From c1560d975b83fd4c73416574d00209059f86974a Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Fri, 10 Jan 2025 12:37:10 +0000 Subject: [PATCH 62/75] Fix loop count --- read-state.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/read-state.sh b/read-state.sh index 2f62d58..b6d8c43 100644 --- a/read-state.sh +++ b/read-state.sh @@ -84,9 +84,9 @@ else log_debug "Polling is on for VIN: $vin, checking interval" # Is counter divisible by interval with no remainder? If so, it is time to attempt to poll - mod=$(( i % $polling_interval )) + mod=$(( loop_count % $polling_interval )) if [ $mod -ne 0 ]; then - log_debug "Count not divisible by polling_interval for VIN: $vin, Count: $i, Interval: $polling_interval" + log_debug "Count not divisible by polling_interval for VIN: $vin, Count: $loop_count, Interval: $polling_interval" else log_info "Polling VIN: $vin" From b1b14de0fad01a8aedb90b1bd21260df5779f831 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Fri, 10 Jan 2025 15:21:02 +0000 Subject: [PATCH 63/75] Check for unclean JSON --- read-state.sh | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/read-state.sh b/read-state.sh index b6d8c43..bc5c731 100644 --- a/read-state.sh +++ b/read-state.sh @@ -31,7 +31,7 @@ loop_count=$2 #echo VIN $vin echo Count: $loop_count -log_debug "poll_state_loop: Setting variables from MQTT for VIN:$vin" +log_debug "poll_state: Setting variables from MQTT for VIN:$vin" set +e mqttOp=$( eval $MOSQUITTO_SUB_BASE --nodelay -W 1 --topic tesla_ble/$vin/variables/+ -F \"%t=%p\" 2>/dev/null ) EXIT_CODE=$? @@ -54,6 +54,13 @@ bcs_json=$( /usr/bin/tesla-control -ble -vin $vin -command-timeout 5s -connect-t EXIT_VALUE=$? set -e +# Check for json having unwanted text at the end. This might be a sign of a bluetooth hardware issue or sending commands too quickly +# See https://github.com/tesla-local-control/tesla_ble_mqtt_docker/issues/74 +clean_bcs_json=$( echo "$bcs_json" | sed 's/\([0-9]\{4\}\/[0-9]\{2\}\/[0-9]\{2\}\).*$//' ) +if [ "$bcs_json" != "$clean_bcs_json" ]; then + log_warning "poll_state: tesla-control returned unclean JSON. See https://github.com/tesla-local-control/tesla_ble_mqtt_docker/issues/74" +fi + # If non zero, car is not contactable by bluetooth if [ $EXIT_VALUE -ne 0 ]; then log_info "Car is not responding to bluetooth, assuming it's away. VIN:$vin" @@ -66,7 +73,7 @@ else stateMQTTpub $vin 'true' 'binary_sensor/presence_bc' # Check if awake or asleep from the body-controller-state response - rqdValue=$(echo $bcs_json | jq -e '.vehicleSleepStatus') + rqdValue=$(echo $clean_bcs_json | jq -e '.vehicleSleepStatus') EXIT_VALUE=$? if [ $EXIT_VALUE -ne 0 ] || [ "$rqdValue" != "\"VEHICLE_SLEEP_STATUS_AWAKE\"" ]; then log_info "Car is present but asleep VIN:$vin" From 5f553ae8f6e903abc2134bf6748faf32b1fa164a Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Fri, 10 Jan 2025 15:27:14 +0000 Subject: [PATCH 64/75] Fix unclean Jason v2 --- read-state.sh | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/read-state.sh b/read-state.sh index bc5c731..505ce03 100644 --- a/read-state.sh +++ b/read-state.sh @@ -54,13 +54,6 @@ bcs_json=$( /usr/bin/tesla-control -ble -vin $vin -command-timeout 5s -connect-t EXIT_VALUE=$? set -e -# Check for json having unwanted text at the end. This might be a sign of a bluetooth hardware issue or sending commands too quickly -# See https://github.com/tesla-local-control/tesla_ble_mqtt_docker/issues/74 -clean_bcs_json=$( echo "$bcs_json" | sed 's/\([0-9]\{4\}\/[0-9]\{2\}\/[0-9]\{2\}\).*$//' ) -if [ "$bcs_json" != "$clean_bcs_json" ]; then - log_warning "poll_state: tesla-control returned unclean JSON. See https://github.com/tesla-local-control/tesla_ble_mqtt_docker/issues/74" -fi - # If non zero, car is not contactable by bluetooth if [ $EXIT_VALUE -ne 0 ]; then log_info "Car is not responding to bluetooth, assuming it's away. VIN:$vin" @@ -73,7 +66,7 @@ else stateMQTTpub $vin 'true' 'binary_sensor/presence_bc' # Check if awake or asleep from the body-controller-state response - rqdValue=$(echo $clean_bcs_json | jq -e '.vehicleSleepStatus') + rqdValue=$(echo $bcs_json | jq -e '.vehicleSleepStatus') EXIT_VALUE=$? if [ $EXIT_VALUE -ne 0 ] || [ "$rqdValue" != "\"VEHICLE_SLEEP_STATUS_AWAKE\"" ]; then log_info "Car is present but asleep VIN:$vin" @@ -282,10 +275,16 @@ sendBLECommand() { function getStateValueAndPublish() { vin=$1 - jsonParam=$2 mqttTopic=$3 stateJSON=$4 + # Check for json having unwanted text at the end. This might be a sign of a bluetooth hardware issue or sending commands too quickly + # See https://github.com/tesla-local-control/tesla_ble_mqtt_docker/issues/74 + jsonParam=$( echo "$2" | sed 's/\([0-9]\{4\}\/[0-9]\{2\}\/[0-9]\{2\}\).*$//' ) + if [ "$jsonParam" != "$2" ]; then + log_warning "poll_state: tesla-control returned unclean JSON. See https://github.com/tesla-local-control/tesla_ble_mqtt_docker/issues/74" + fi + # Get value from JSON, and publish to MQTT rqdValue=$(echo $stateJSON | jq -e $jsonParam) EXIT_STATUS=$? From 345a562504098dc9ef3f1062159bb59f7150477e Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Fri, 10 Jan 2025 15:39:12 +0000 Subject: [PATCH 65/75] Remove echo --- read-state.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/read-state.sh b/read-state.sh index 505ce03..92fa4dd 100644 --- a/read-state.sh +++ b/read-state.sh @@ -28,9 +28,6 @@ function poll_state() { vin=$1 loop_count=$2 -#echo VIN $vin -echo Count: $loop_count - log_debug "poll_state: Setting variables from MQTT for VIN:$vin" set +e mqttOp=$( eval $MOSQUITTO_SUB_BASE --nodelay -W 1 --topic tesla_ble/$vin/variables/+ -F \"%t=%p\" 2>/dev/null ) From 471a2ff0e04aa49d0ea94d29cd9af0c09522b1c5 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Fri, 10 Jan 2025 16:21:58 +0000 Subject: [PATCH 66/75] Fix for numeric first char in VIN --- read-state.sh | 6 +++--- run.sh | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/read-state.sh b/read-state.sh index 92fa4dd..2ba59ec 100644 --- a/read-state.sh +++ b/read-state.sh @@ -37,13 +37,13 @@ if [ $EXIT_CODE -eq 27 ]; then for item in $mqttOp; do assign=${item##*/} log_debug "Setting variable from MQTT: $assign" - eval export ${vin}_$assign + eval export $var_{vin}_$assign done fi # Get variables for this VIN. Note ash needs to use eval for dynamic variables -polling=$( eval "echo \"\$${vin}_polling\"" ) -polling_interval=$( eval "echo \"\$${vin}_polling_interval\"" ) +polling=$( eval "echo \"\$var_${vin}_polling\"" ) +polling_interval=$( eval "echo \"\$var_${vin}_polling_interval\"" ) # Send a body-controller-state command. This checks if car is in bluetooth range and whether awake or asleep without acutally waking it set +e diff --git a/run.sh b/run.sh index 5ddc9a5..a6a3b73 100755 --- a/run.sh +++ b/run.sh @@ -16,8 +16,8 @@ vin_count=0 for vin in $VIN_LIST; do # Set defaults for MQTT derived variables - export ${vin}_polling=false - export ${vin}_polling_interval=680 + export var_${vin}_polling=false + export var_${vin}_polling_interval=680 # Populate BLE Local Names list vin_count=$((vin_count + 1)) From bcda0d50060008e24ff5d34deca201e115b5e8cd Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Fri, 10 Jan 2025 16:45:20 +0000 Subject: [PATCH 67/75] Typo and Changelog --- CHANGELOG.md | 2 ++ read-state.sh | 2 +- version.sh | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8a1e1a..24055ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,8 @@ - Errors which occur whilst reading state will not automatically prevent the next state or state category being read. This will fix an issue reported in #135 below where a user doesn't have a Heated Steering Wheel. This previously prevented any states after this one from being read - Fixes: + - [ Dev ] Bad variable name #75 (_docker). Many thanks to aneisch and dettofatto who really helped to track down this bug + - parse error: Invalid numeric literal #74 (_docker). Many thanks to jipema who also helped a lot in identifying this issue - All my sensor entities are "unknown" #131 (_core) - Any potential to "read state" via bluetooth? #115 (_core) diff --git a/read-state.sh b/read-state.sh index 2ba59ec..4cd41fa 100644 --- a/read-state.sh +++ b/read-state.sh @@ -37,7 +37,7 @@ if [ $EXIT_CODE -eq 27 ]; then for item in $mqttOp; do assign=${item##*/} log_debug "Setting variable from MQTT: $assign" - eval export $var_{vin}_$assign + eval export var_${vin}_$assign done fi diff --git a/version.sh b/version.sh index 4df9d98..d7c486d 100644 --- a/version.sh +++ b/version.sh @@ -2,5 +2,5 @@ # # shellcheck shell=dash # -export SW_VERSION=0.4.1 +export SW_VERSION=0.4.1a-dev log_info "Core version is $SW_VERSION" From fb204b629b77513dfbd681505e1d95b316aaf23d Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Fri, 10 Jan 2025 16:50:46 +0000 Subject: [PATCH 68/75] Credit Issue #75 --- run.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/run.sh b/run.sh index a6a3b73..478ad40 100755 --- a/run.sh +++ b/run.sh @@ -16,6 +16,7 @@ vin_count=0 for vin in $VIN_LIST; do # Set defaults for MQTT derived variables + # https://github.com/tesla-local-control/tesla_ble_mqtt_docker/issues/75 export var_${vin}_polling=false export var_${vin}_polling_interval=680 From f9970bf690aa53682c093cf1c23b4b7a5dd5f58d Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Sat, 11 Jan 2025 07:18:00 +0000 Subject: [PATCH 69/75] Clean stateJSON not jsonParam --- read-state.sh | 7 ++++--- version.sh | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/read-state.sh b/read-state.sh index 4cd41fa..bb8f95a 100644 --- a/read-state.sh +++ b/read-state.sh @@ -272,13 +272,14 @@ sendBLECommand() { function getStateValueAndPublish() { vin=$1 + jsonParam=$2 mqttTopic=$3 - stateJSON=$4 + #stateJSON=$4 # Check for json having unwanted text at the end. This might be a sign of a bluetooth hardware issue or sending commands too quickly # See https://github.com/tesla-local-control/tesla_ble_mqtt_docker/issues/74 - jsonParam=$( echo "$2" | sed 's/\([0-9]\{4\}\/[0-9]\{2\}\/[0-9]\{2\}\).*$//' ) - if [ "$jsonParam" != "$2" ]; then + stateJSON=$( echo "$4" | sed 's/\([0-9]\{4\}\/[0-9]\{2\}\/[0-9]\{2\}\).*$//' ) + if [ "$stateJSON" != "$4" ]; then log_warning "poll_state: tesla-control returned unclean JSON. See https://github.com/tesla-local-control/tesla_ble_mqtt_docker/issues/74" fi diff --git a/version.sh b/version.sh index d7c486d..e1f12c9 100644 --- a/version.sh +++ b/version.sh @@ -2,5 +2,5 @@ # # shellcheck shell=dash # -export SW_VERSION=0.4.1a-dev +export SW_VERSION=0.4.1b-dev log_info "Core version is $SW_VERSION" From 1707b787f8dfabd2df3213b087c020b668da9466 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Sat, 11 Jan 2025 08:28:10 +0000 Subject: [PATCH 70/75] Fix shellcheck errors --- mqtt-discovery.sh | 2 +- mqtt-listen.sh | 4 +- read-state.sh | 174 +++++++++++++++++++++++++--------------------- run.sh | 2 +- 4 files changed, 98 insertions(+), 84 deletions(-) diff --git a/mqtt-discovery.sh b/mqtt-discovery.sh index 819a74a..f366679 100644 --- a/mqtt-discovery.sh +++ b/mqtt-discovery.sh @@ -968,7 +968,7 @@ setupHADiscoveryAllVINsMain() { eval $MOSQUITTO_PUB_BASE -t tesla_ble/$vin/config -n eval $MOSQUITTO_PUB_BASE -t tesla_ble/$vin/command -n done - + } ### diff --git a/mqtt-listen.sh b/mqtt-listen.sh index cf3bd87..6adf887 100755 --- a/mqtt-listen.sh +++ b/mqtt-listen.sh @@ -24,7 +24,7 @@ listen_to_mqtt_loop() { } -listen_to_mqtt() { +listen_to_mqtt() { log_info "Listening to MQTT" eval $MOSQUITTO_SUB_BASE --nodelay --disable-clean-session --qos 1 --topic tesla_ble/+/+ -F \"%t %p\" --id tesla_ble_mqtt | while read -r payload; do @@ -252,7 +252,7 @@ listen_to_mqtt() { ;; variables) - # These get handled in the subshell where they are used + # These get handled in the subshell where they are used ;; poll_state) diff --git a/read-state.sh b/read-state.sh index bb8f95a..f58e853 100644 --- a/read-state.sh +++ b/read-state.sh @@ -18,85 +18,85 @@ function poll_state_loop() { stateMQTTpub $vin $i 'poll_state' done # Loop repeat approx every 30 secs - sleep 29 - i=$(( i + 30 )) + sleep 29 + i=$(( i + 30 )) done done } function poll_state() { -vin=$1 -loop_count=$2 - -log_debug "poll_state: Setting variables from MQTT for VIN:$vin" -set +e -mqttOp=$( eval $MOSQUITTO_SUB_BASE --nodelay -W 1 --topic tesla_ble/$vin/variables/+ -F \"%t=%p\" 2>/dev/null ) -EXIT_CODE=$? -set -e -if [ $EXIT_CODE -eq 27 ]; then - for item in $mqttOp; do - assign=${item##*/} - log_debug "Setting variable from MQTT: $assign" - eval export var_${vin}_$assign - done -fi - -# Get variables for this VIN. Note ash needs to use eval for dynamic variables -polling=$( eval "echo \"\$var_${vin}_polling\"" ) -polling_interval=$( eval "echo \"\$var_${vin}_polling_interval\"" ) - -# Send a body-controller-state command. This checks if car is in bluetooth range and whether awake or asleep without acutally waking it -set +e -bcs_json=$( /usr/bin/tesla-control -ble -vin $vin -command-timeout 5s -connect-timeout 10s body-controller-state 2>&1 ) -EXIT_VALUE=$? -set -e - -# If non zero, car is not contactable by bluetooth -if [ $EXIT_VALUE -ne 0 ]; then - log_info "Car is not responding to bluetooth, assuming it's away. VIN:$vin" - # Publish to MQTT presence_bc sensor. TODO: Set awake sensor to Unknown via MQTT availability - stateMQTTpub $vin 'false' 'binary_sensor/presence_bc' - -else - # Car has responded - log_debug "Car has responded to bluetooth, it is present. VIN:$vin" - stateMQTTpub $vin 'true' 'binary_sensor/presence_bc' - - # Check if awake or asleep from the body-controller-state response - rqdValue=$(echo $bcs_json | jq -e '.vehicleSleepStatus') + vin=$1 + loop_count=$2 + + log_debug "poll_state: Setting variables from MQTT for VIN:$vin" + set +e + mqttOp=$( eval $MOSQUITTO_SUB_BASE --nodelay -W 1 --topic tesla_ble/$vin/variables/+ -F \"%t=%p\" 2>/dev/null ) + EXIT_CODE=$? + set -e + if [ $EXIT_CODE -eq 27 ]; then + for item in $mqttOp; do + assign=${item##*/} + log_debug "Setting variable from MQTT: $assign" + eval export var_${vin}_$assign + done + fi + + # Get variables for this VIN. Note ash needs to use eval for dynamic variables + polling=$( eval "echo \"\$var_${vin}_polling\"" ) + polling_interval=$( eval "echo \"\$var_${vin}_polling_interval\"" ) + + # Send a body-controller-state command. This checks if car is in bluetooth range and whether awake or asleep without acutally waking it + set +e + bcs_json=$( /usr/bin/tesla-control -ble -vin $vin -command-timeout 5s -connect-timeout 10s body-controller-state 2>&1 ) EXIT_VALUE=$? - if [ $EXIT_VALUE -ne 0 ] || [ "$rqdValue" != "\"VEHICLE_SLEEP_STATUS_AWAKE\"" ]; then - log_info "Car is present but asleep VIN:$vin" - stateMQTTpub $vin 'false' 'binary_sensor/awake' + set -e + + # If non zero, car is not contactable by bluetooth + if [ $EXIT_VALUE -ne 0 ]; then + log_info "Car is not responding to bluetooth, assuming it's away. VIN:$vin" + # Publish to MQTT presence_bc sensor. TODO: Set awake sensor to Unknown via MQTT availability + stateMQTTpub $vin 'false' 'binary_sensor/presence_bc' else - log_info "Car is present and awake VIN:$vin" - stateMQTTpub $vin 'true' 'binary_sensor/awake' + # Car has responded + log_debug "Car has responded to bluetooth, it is present. VIN:$vin" + stateMQTTpub $vin 'true' 'binary_sensor/presence_bc' - # Check if polling turned off for this car - if [ "$polling" != "on" ]; then - log_debug "Polling is off for VIN: $vin, skipping" + # Check if awake or asleep from the body-controller-state response + rqdValue=$(echo $bcs_json | jq -e '.vehicleSleepStatus') + EXIT_VALUE=$? + if [ $EXIT_VALUE -ne 0 ] || [ "$rqdValue" != "\"VEHICLE_SLEEP_STATUS_AWAKE\"" ]; then + log_info "Car is present but asleep VIN:$vin" + stateMQTTpub $vin 'false' 'binary_sensor/awake' else - log_debug "Polling is on for VIN: $vin, checking interval" + log_info "Car is present and awake VIN:$vin" + stateMQTTpub $vin 'true' 'binary_sensor/awake' + + # Check if polling turned off for this car + if [ "$polling" != "on" ]; then + log_debug "Polling is off for VIN: $vin, skipping" + + else + log_debug "Polling is on for VIN: $vin, checking interval" - # Is counter divisible by interval with no remainder? If so, it is time to attempt to poll - mod=$(( loop_count % $polling_interval )) - if [ $mod -ne 0 ]; then - log_debug "Count not divisible by polling_interval for VIN: $vin, Count: $loop_count, Interval: $polling_interval" + # Is counter divisible by interval with no remainder? If so, it is time to attempt to poll + mod=$(( loop_count % polling_interval )) + if [ $mod -ne 0 ]; then + log_debug "Count not divisible by polling_interval for VIN: $vin, Count: $loop_count, Interval: $polling_interval" - else - log_info "Polling VIN: $vin" - # 'Press' the Data Update Env button (which checks NO_POLL_SECTIONS environment variable to exclude various sections if required) - stateMQTTpub $vin 'read-state-envcheck' 'config' + else + log_info "Polling VIN: $vin" + # 'Press' the Data Update Env button (which checks NO_POLL_SECTIONS environment variable to exclude various sections if required) + stateMQTTpub $vin 'read-state-envcheck' 'config' + + fi fi fi fi - -fi } function stateMQTTpub() { @@ -118,7 +118,7 @@ function stateMQTTpub() { return 1 # Don't spam the logs for these topics - if [ $topic == "binary_sensor/presence_bc" ] || [ $topic == "binary_sensor/awake" ] || [ $topic == "poll_state" ]; then + if [ $topic == "binary_sensor/presence_bc" ] || [ $topic == "binary_sensor/awake" ] || [ $topic == "poll_state" ]; then log_debug "MQTT topic $MQTT_TOPIC successfully updated to $state" else log_info "MQTT topic $MQTT_TOPIC successfully updated to $state" @@ -133,51 +133,65 @@ function readState() { sections=$2 log_debug "readState; entering. Sections: $sections VIN:$vin" - charge=0; climate=0; tyre=0; closure=0; drive=0 + + charge=0 + climate=0 + tyre=0 + closure=0 + drive=0 + case $sections in charge) charge=1 - ;; + ;; climate) climate=1 - ;; + ;; tyre) tyre=1 - ;; + ;; closure) closure=1 - ;; + ;; drive) drive=1 - ;; + ;; env_check) - charge=1; climate=1; tyre=1; closure=1; drive=1 + charge=1 + climate=1 + tyre=1 + closure=1 + drive=1 for sect in $NO_POLL_SECTIONS; do case $sect in charge) charge=0 - ;; + ;; climate) climate=0 - ;; + ;; tire-pressure) tyre=0 - ;; + ;; closures) closure=0 - ;; + ;; drive) drive=0 - ;; + ;; *) log_warning "readState: Invalid state category in NO_POLL_SECTIONS" - ;; + ;; esac done - ;; + ;; *) - charge=1; climate=1; tyre=1; closure=1; drive=1 - ;; + charge=1 + climate=1 + tyre=1 + closure=1 + drive=1 + ;; esac if [ $charge -eq 1 ]; then @@ -243,7 +257,7 @@ sendBLECommand() { log_debug "sendBLECommand; $TESLACTRLOUT" log_info "Command $command was successfully delivered to vin:$vin" # Publish to MQTT awake topic - stateMQTTpub $vin 'true' 'binary_sensor/awake' + stateMQTTpub $vin 'true' 'binary_sensor/awake' return 0 else if [[ "$TESLACTRLOUT" == *"car could not execute command"* ]]; then @@ -278,11 +292,11 @@ function getStateValueAndPublish() { # Check for json having unwanted text at the end. This might be a sign of a bluetooth hardware issue or sending commands too quickly # See https://github.com/tesla-local-control/tesla_ble_mqtt_docker/issues/74 - stateJSON=$( echo "$4" | sed 's/\([0-9]\{4\}\/[0-9]\{2\}\/[0-9]\{2\}\).*$//' ) + stateJSON=$(echo "$4" | sed 's/\([0-9]\{4\}\/[0-9]\{2\}\/[0-9]\{2\}\).*$//') if [ "$stateJSON" != "$4" ]; then log_warning "poll_state: tesla-control returned unclean JSON. See https://github.com/tesla-local-control/tesla_ble_mqtt_docker/issues/74" fi - + # Get value from JSON, and publish to MQTT rqdValue=$(echo $stateJSON | jq -e $jsonParam) EXIT_STATUS=$? diff --git a/run.sh b/run.sh index 478ad40..80df54c 100755 --- a/run.sh +++ b/run.sh @@ -112,7 +112,7 @@ while :; do # Launch poll_state_loop in background log_notice "main loop; Launching background poll_state_loop..." poll_state_loop & - + # Don't run presence detection if TTL is 0 # If PRESENCE_DETECTION_TTL > 0 and BLE_MAC_LIST is not empty if [ $PRESENCE_DETECTION_TTL -gt 0 ]; then From 3210700e75bf92db2c77baf506fd0754da979510 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Sat, 11 Jan 2025 08:34:01 +0000 Subject: [PATCH 71/75] Fix shellcheck errors +1 --- mqtt-listen.sh | 4 ++-- read-state.sh | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/mqtt-listen.sh b/mqtt-listen.sh index 6adf887..08db34a 100755 --- a/mqtt-listen.sh +++ b/mqtt-listen.sh @@ -35,12 +35,12 @@ listen_to_mqtt() { cmd=${topic_stripped#*/} # Don't spam the logs for these topics/ commands - if [ $cmd == "poll_state" ]; then + if [ $cmd == "poll_state" ]; then log_debug "Received MQTT message; topic:$topic msg:$msg vin:$vin cmd:$cmd" else log_info "Received MQTT message; topic:$topic msg:$msg vin:$vin cmd:$cmd" fi - + case $cmd in config) diff --git a/read-state.sh b/read-state.sh index f58e853..865abf5 100644 --- a/read-state.sh +++ b/read-state.sh @@ -19,7 +19,7 @@ function poll_state_loop() { done # Loop repeat approx every 30 secs sleep 29 - i=$(( i + 30 )) + i=$((i + 30)) done done } @@ -30,7 +30,7 @@ function poll_state() { log_debug "poll_state: Setting variables from MQTT for VIN:$vin" set +e - mqttOp=$( eval $MOSQUITTO_SUB_BASE --nodelay -W 1 --topic tesla_ble/$vin/variables/+ -F \"%t=%p\" 2>/dev/null ) + mqttOp=$(eval $MOSQUITTO_SUB_BASE --nodelay -W 1 --topic tesla_ble/$vin/variables/+ -F \"%t=%p\" 2>/dev/null) EXIT_CODE=$? set -e if [ $EXIT_CODE -eq 27 ]; then @@ -42,12 +42,12 @@ function poll_state() { fi # Get variables for this VIN. Note ash needs to use eval for dynamic variables - polling=$( eval "echo \"\$var_${vin}_polling\"" ) - polling_interval=$( eval "echo \"\$var_${vin}_polling_interval\"" ) + polling=$(eval "echo \"\$var_${vin}_polling\"") + polling_interval=$(eval "echo \"\$var_${vin}_polling_interval\"") # Send a body-controller-state command. This checks if car is in bluetooth range and whether awake or asleep without acutally waking it set +e - bcs_json=$( /usr/bin/tesla-control -ble -vin $vin -command-timeout 5s -connect-timeout 10s body-controller-state 2>&1 ) + bcs_json=$(/usr/bin/tesla-control -ble -vin $vin -command-timeout 5s -connect-timeout 10s body-controller-state 2>&1) EXIT_VALUE=$? set -e @@ -67,7 +67,7 @@ function poll_state() { EXIT_VALUE=$? if [ $EXIT_VALUE -ne 0 ] || [ "$rqdValue" != "\"VEHICLE_SLEEP_STATUS_AWAKE\"" ]; then log_info "Car is present but asleep VIN:$vin" - stateMQTTpub $vin 'false' 'binary_sensor/awake' + stateMQTTpub $vin 'false' 'binary_sensor/awake' else log_info "Car is present and awake VIN:$vin" @@ -78,14 +78,14 @@ function poll_state() { log_debug "Polling is off for VIN: $vin, skipping" else - log_debug "Polling is on for VIN: $vin, checking interval" + log_debug "Polling is on for VIN: $vin, checking interval" # Is counter divisible by interval with no remainder? If so, it is time to attempt to poll - mod=$(( loop_count % polling_interval )) + mod=$((loop_count % polling_interval)) if [ $mod -ne 0 ]; then log_debug "Count not divisible by polling_interval for VIN: $vin, Count: $loop_count, Interval: $polling_interval" - else + else log_info "Polling VIN: $vin" # 'Press' the Data Update Env button (which checks NO_POLL_SECTIONS environment variable to exclude various sections if required) stateMQTTpub $vin 'read-state-envcheck' 'config' @@ -133,7 +133,7 @@ function readState() { sections=$2 log_debug "readState; entering. Sections: $sections VIN:$vin" - + charge=0 climate=0 tyre=0 @@ -180,7 +180,7 @@ function readState() { drive=0 ;; *) - log_warning "readState: Invalid state category in NO_POLL_SECTIONS" + log_warning "readState: Invalid state category in NO_POLL_SECTIONS" ;; esac done @@ -191,7 +191,7 @@ function readState() { tyre=1 closure=1 drive=1 - ;; + ;; esac if [ $charge -eq 1 ]; then From 2972f98a33667dd9e97296d7713109aa0dc4f363 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Sat, 11 Jan 2025 08:35:57 +0000 Subject: [PATCH 72/75] Fix shellcheck errors +2 --- read-state.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/read-state.sh b/read-state.sh index 865abf5..3e733b5 100644 --- a/read-state.sh +++ b/read-state.sh @@ -86,7 +86,7 @@ function poll_state() { log_debug "Count not divisible by polling_interval for VIN: $vin, Count: $loop_count, Interval: $polling_interval" else - log_info "Polling VIN: $vin" + log_info "Polling VIN: $vin" # 'Press' the Data Update Env button (which checks NO_POLL_SECTIONS environment variable to exclude various sections if required) stateMQTTpub $vin 'read-state-envcheck' 'config' @@ -184,7 +184,7 @@ function readState() { ;; esac done - ;; + ;; *) charge=1 climate=1 From 82703eb4ca74b2be59869fec7660b9ea2f36dffb Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Sat, 11 Jan 2025 08:37:30 +0000 Subject: [PATCH 73/75] Fix shellcheck errors +3 --- read-state.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/read-state.sh b/read-state.sh index 3e733b5..2e29b0b 100644 --- a/read-state.sh +++ b/read-state.sh @@ -79,12 +79,12 @@ function poll_state() { else log_debug "Polling is on for VIN: $vin, checking interval" - + # Is counter divisible by interval with no remainder? If so, it is time to attempt to poll mod=$((loop_count % polling_interval)) if [ $mod -ne 0 ]; then log_debug "Count not divisible by polling_interval for VIN: $vin, Count: $loop_count, Interval: $polling_interval" - + else log_info "Polling VIN: $vin" # 'Press' the Data Update Env button (which checks NO_POLL_SECTIONS environment variable to exclude various sections if required) From 438cd68bf1c375424957fd151bdce5e8e77dc717 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Mon, 13 Jan 2025 16:39:37 +0000 Subject: [PATCH 74/75] SW_VERSION=0.4.2 --- version.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.sh b/version.sh index e1f12c9..6edcaff 100644 --- a/version.sh +++ b/version.sh @@ -2,5 +2,5 @@ # # shellcheck shell=dash # -export SW_VERSION=0.4.1b-dev +export SW_VERSION=0.4.2 log_info "Core version is $SW_VERSION" From 875ac721abbce5c9bd146ff307acd15058de9c75 Mon Sep 17 00:00:00 2001 From: Iain Bullock <59146297+iainbullock@users.noreply.github.com> Date: Mon, 13 Jan 2025 17:18:32 +0000 Subject: [PATCH 75/75] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24055ca..9d3fe12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## 0.4.1 +## 0.4.2 - RELEASE NEW Feature: Automatic Polling is now possible for state