Swift Command Caravan Monitor

I’ve been working on an integration to pull data from the Swift Command remote access webpage/app.
It allows you to show the location of your caravan on a map along with status information such as battery voltage and temperature (Although I haven’t worked out the format of the temp yet, I took a stab at it being in fahrenheit but I’m not too sure it is so will have to confirm next time I have the caravan at home.

I’ve used the map entity and attribute entity cards to display in a panel.

Details are here: https://github.com/markgdev/home-assistant_swiftcommand

If anyone is reading this in 2025 (or beyond), this integration no longer works as Swift have changed how the Swift Command portal works.

There is a way of doing it however - I have virtually no coding skills but managed to get something work with the help of AI.

Will try and explain it here in case anyone is interested to getting swift command data in home assistant. Using this method, you can get any of the information that is displayed on SwiftCommand such as battery voltage, location and alarm status.

The overall solution involves four steps:
Shell Script: Logs in and captures the temporary access token.
Token Holder Sensor: Stores the captured token in HA.
REST Sensor: Uses the stored token to fetch the live caravan data.
Template Sensors & Automation: Extracts specific data points (location, voltage, alarms)

Step 1: The Token Refresh Script
The SwiftCommand token expires quickly, so we use a script (/config/swiftcommand_login.sh) to log in and update a dedicated sensor attribute with the new token. Create a new file in config/ and copy for following code
File: /config/swiftcommand_login.sh

#!/bin/bash 

# !!! WARNING: Replace ALL placeholder values before use !!!
SWIFT_LOGIN_URL="[https://www.swiftcommand.co.uk/api/login](https://www.swiftcommand.co.uk/api/login)"  
SWIFT_LOGIN_DATA='{"email":"YOUR_EMAIL_HERE","password":"YOUR_PASSWORD_HERE"}'  

# Your HA IP and the long-lived token for the HA API
HA_URL="[http://192.168.XX.XX:8123/api/states/sensor.swiftcommand_token_holder](http://192.168.XX.XX:8123/api/states/sensor.swiftcommand_token_holder)" 
HA_TOKEN="YOUR_LONG_LIVED_HA_TOKEN" # Get this from your HA Profile

# --- 1. Get the SwiftCommand token via API --- 
LOGIN_RESPONSE=$(curl -s -w "%{http_code}" -X POST "$SWIFT_LOGIN_URL" \  
  -H "Content-Type: application/json" \  
  -d "$SWIFT_LOGIN_DATA")  

LOGIN_STATUS="${LOGIN_RESPONSE:(-3)}"  
LOGIN_BODY="${LOGIN_RESPONSE:0:$((${#LOGIN_RESPONSE}-3))}"  

if [ "$LOGIN_STATUS" -ne 200 ]; then  
  echo "Login Failed: $LOGIN_STATUS"  
  exit 1  
fi  

TOKEN=$(echo "$LOGIN_BODY" | jq -r '.token')  

if [ "$TOKEN" == "null" ] || [ -z "$TOKEN" ]; then  
  echo "Login Failed: Token not found."  
  exit 1  
fi  

# --- 2. Update the attribute using Home Assistant API ---  
HA_DATA='{"state": "ok", "attributes": {"full_token": "'"$TOKEN"'"}}'  

HA_RESPONSE=$(curl -s -w "%{http_code}" -X POST \  
  -H "Authorization: Bearer $HA_TOKEN" \  
  -H "Content-Type: application/json" \  
  -d "$HA_DATA" \  
  "$HA_URL")  

HA_STATUS="${HA_RESPONSE:(-3)}"  

if [ "$HA_STATUS" -ne 200 ] && [ "$HA_STATUS" -ne 201 ]; then  
  echo "HA API Update FAILED with Status: $HA_STATUS"  
  exit 1  
fi  

echo "Success! Token sensor updated."

Action: The above method uses a long lived Home Assistant token, if you are unfamiliar how to create, AI can advise on how to create on

Action: Make the script executable, copy the following code into terminal (chmod +x /config/swiftcommand_login.sh).

Step 2: Configuration (configuration.yaml)
This section sets up the core components: the shell command, the token holder, the REST sensor for data, and the voltage template sensor. You need to get you customer ID, this can be found by enabling your web inspector within the developer section of your web browser, if you click on the NETWORK tab, I found mine in the file ‘1’, under ID.
Add the following to your configuration.yaml:

shell_command:
  # This makes the script available as a service: shell_command.swiftcommand_refresh_token
  swiftcommand_refresh_token: "/config/swiftcommand_login.sh"

template:
  - sensor:
    # 1. The Sensor that holds the token from the script
    - name: "SwiftCommand Token Holder"
      unique_id: swiftcommand_token_holder
      state: "ok"  
      attributes:
        full_token: "Unknown"

    # 2. The Sensor that extracts the voltage (Crucial fix for data path)
    - name: "SwiftCommand Leisure Voltage"
      unique_id: swiftcommand_leisure_voltage
      state: >-
        {% set voltage = state_attr('sensor.swiftcommand_data', 'lastPosition').leisureVoltage %}
        {% if voltage is not none %}
          {{ voltage | float(0) }}
        {% else %}
          unavailable
        {% endif %}
      unit_of_measurement: "V"
      device_class: voltage


# The REST sensor fetches the data using the token from the sensor above
rest:
  - resource: "[https://www.swiftcommand.co.uk/api/customers/YOUR_CUSTOMER_ID_HERE/1](https://www.swiftcommand.co.uk/api/customers/YOUR_CUSTOMER_ID_HERE/1)"
    # IMPORTANT: Keep interval long, we update via automation/script
    scan_interval: 3153600000 
    headers:
      # Pulls the live token from the holder sensor attribute
      Authorization: "Bearer {{ state_attr('sensor.swiftcommand_token_holder', 'full_token') }}"
      
    sensor:
      - name: SwiftCommand Data
        # New value_template is simply the raw JSON dump
        value_template: "{{ value_json.vehicles[0].lastPosition.leisureVoltage }}"
        # We need to expose 'lastPosition' so we can extract attributes from it
        json_attributes:
          - vehicles

I then created a helper for the different sensors, using a template sensor and using the below code in the state (this one is for voltage):
{{ state_attr('sensor.swiftcommand_data', 'vehicles')[0].lastPosition.leisureVoltage }}
You can use similar sensors for the other aspect, this one is for longtitude
{{ (state_attr('sensor.swiftcommand_data', 'vehicles')[0].lastPosition.longitude) }}

I then created a template to trigger the shell command, you may think the timings are a bit odd, however looking at my data, this worked for pulling it down from the swift servers without doing too many requests:


alias: SwiftCommand - Token and Data Refresh
description: Refreshes token and forces data update within the 25-45 minute active window.
triggers:
  - minutes: 24
    trigger: time_pattern
conditions: []
actions:
  - alias: Ensure the token is fresh (runs at :24)
    data: {}
    action: shell_command.swiftcommand_refresh_token
  - delay:
      seconds: 5
  - alias: Force update of Caravan Data (runs at :24:05)
    target:
      entity_id: sensor.swiftcommand_caravan_voltage
    action: homeassistant.update_entity
  - repeat:
      count: 2
      sequence:
        - delay:
            minutes: 10
        - target:
            entity_id: sensor.swiftcommand_data
          action: homeassistant.update_entity
mode: single

I have another automation that uses my longitude and latitude sensors and publishes it as a device tracker so I can place the location on the map, can post this if there is anyone out there who is uses.

There maybe better ways of doing this however after a lot of trial and error and going round in circles, this method seemed to work. You can’t use a normal sensor to store the token as it is too long (HA only can store 255 characters and the token is 260).

I went a bit further and did a near complete custom component. Still got heating and hot water control to sort. Don’t flood the API as you will get rejections and not be able to connect for a while

I also have directly connected an ESP32 and a canbus adapter to the caravan canbus and have near complete local control and monitoring. Took a lot of trial and error to decode the canbus signals. I’ve also got home assistant installed in the caravan with some BLE tyre sensors and a BLE gas tank sensor