Trying to make 17track integration useful again

I used and loved the 17track integration for years. It’s been refactored and I’ve never been more frustrated with Home Assistant than trying to get this data displaying on my dashboard again.

The official documentation is straight up incorrect and out-dated. It does not create a sensor per status. When it did I could use it. Instead, you need to call the get_packages action to get data out.

There is no example of that on the site. I found this commit on a pull request with an example. I tried to use that and I can do everything except do anything useful with the response variable. If I try to define the sensor in the YAML of the automation as per the example in the PR, it tells me it is invalid and won’t save. If I try to create a template sensor in configuration.yaml it has no value for packages_var and does nothing.

I have no idea how to do anything sensible with the results of the get_packages call. All I want to do is get the info about the packages into a form I can display. I can call it from debug and verify it works but I am failing to persist the results from that call in the automation into anything I can use. Can anyone help please?

Full YAML of the automation:

alias: Update 17Track Packages
description: ""
triggers:
  - trigger: state
    entity_id:
      - sensor.17track_delivered
  - trigger: state
    entity_id:
      - sensor.17track_in_transit
  - trigger: state
    entity_id:
      - sensor.17track_ready_to_be_picked_up
  - trigger: state
    entity_id:
      - sensor.17track_returned
  - trigger: state
    entity_id:
      - sensor.17track_undelivered
conditions: []
actions:
  - action: seventeentrack.get_packages
    metadata: {}
    data:
      config_entry_id: REDACTED
    response_variable: packages_var
sensor:
  - name: packages_data
    unique_id: packages_data
    state: "{{ packages_var['packages']|length }}"
    attributes:
      packages: "{{ packages_var['packages']  }}"
mode: single

The error I get from this is Message malformed: extra keys not allowed @ data['sensor']. I’ve also been trying to find the full specification of what is allowed here and failing. HA does not want sensor where it is but I don’t know what can be. This page has some information but it does not seem to be exhaustive.

To close on this, I found a workable solution on Discord. I had to modify from there because inexplicably writing to an input variable too small to hold the text doesn’t generate an error. It just silently does nothing.

I ended up using the variable function of Saver to store the formatted results. This data is back on my dashboard again!

Is your fix still working for you? Is so, could you show how to make it work again? I’m fairly new to home assistant, so I’m having trouble getting it working.

2 Likes

Any chance you could post the code either from Discord or your solution?

This is what I am using. I found the input variable even at max size was too small to hold the markdown if I had more than one package so I am using the Saver integration. If you have anything that can hold this, then put it in there. Turns out getting arbitrary text on the screen was the hardest part for me.

alias: Parcel Check
description: SeventeenTrack (17track) info
triggers:
  - trigger: time_pattern
    minutes: /15
conditions: []
actions:
  - action: seventeentrack.get_packages
    metadata: {}
    data:
      package_state:
        - in_transit
      config_entry_id: 01JXXXXXXXXXX0VT
    response_variable: transit
  - action: seventeentrack.get_packages
    metadata: {}
    data:
      package_state:
        - not_found
      config_entry_id: 01JXXXXXXXXXX0VT
    response_variable: notfound
  - action: seventeentrack.get_packages
    metadata: {}
    data:
      package_state:
        - ready_to_be_picked_up
      config_entry_id: 01JXXXXXXXXXX0VT
    response_variable: outfordelivery
  - action: seventeentrack.get_packages
    metadata: {}
    data:
      package_state:
        - delivered
      config_entry_id: 01JXXXXXXXXXX0VT
    response_variable: delivered
  - action: saver.set_variable
    metadata: {}
    data:
      name: parcel_17track_status
      value: >-
        {% if notfound.packages|length > 0 %}# <ha-icon
        icon="mdi:alert"></ha-icon> Not Found 

        {% for package in notfound.packages %} - **{{ package.friendly_name }}
        ({{ package.tracking_number }}):** {{ package.info_text }} 

        {% endfor %} {% endif %}


        {% if transit.packages|length > 0 %}# <ha-icon
        icon="mdi:transit-connection-variant"></ha-icon> In Transit

        {% for package in transit.packages %} - **{{ package.friendly_name }}
        ({{ package.tracking_number }}):** {{ package.info_text }}

        {% endfor %}{% endif %} 


        {% if outfordelivery.packages|length > 0 %}# <ha-icon
        icon="mdi:truck-delivery"></ha-icon> Out for Delivery 

        {% for package in outfordelivery.packages %} - **{{
        package.friendly_name }} ({{ package.tracking_number }}):** {{
        package.info_text }} 

        {% endfor %}{% endif %}


        {% if delivered.packages|length > 0 %}# <ha-icon
        icon="mdi:package-variant-closed-check"></ha-icon> Delivered 

        {% for package in delivered.packages %} - **{{ package.friendly_name }}
        ({{ package.tracking_number }}):** {{ package.info_text }} 
        
        {% endfor %} {% endif %}

        {% if transit.packages|length == 0 and outfordelivery.packages|length ==
        0 and notfound.packages |length ==  0
        and delivered.packages|length == 0 %} No packages currently tracked 
        {%  endif %}
mode: single

1 Like

For those coming across this post, to further close the loop.

The above example stores a text string with markdown formatting included. The easiest way to display this on a dashboard is to add a markdown card with the following content.

{{ saver_variable("parcel_17track_status") }}

where "parcel_17track_status" is the variable name set in

- action: saver.set_variable
  data:
    name: parcel_17track_status

The only thing I might suggest is to only make one call to the 17track API and instead pull all of the different statuses at one time, then use conditions in your jinja templating to sort and separate the different statuses as desired.

You can either exclude package_state from the API call, which will return all packages or you can list the desired package states as (for me I don’t really want to see a package after it’s delivered):

package_state:
  - in_transit
  - ready_to_be_picked_up
  - not_found

Go to Developer Tools > Actions > Select seventeentrack.get_packages check Package States and you can see all available package states in the dropdown box.

I’m not sure if there is a speed trade off, but the 17track API is limited to 3 requests per second, which depending on how quickly the above example executes, would result in a 429 error for the last two statuses. From some previous comments, I suspect the 17track integration would just drop those actions and it would appear as though there were no packages with those statuses, but you wouldn’t know because the integration doesn’t generate an error.

To follow up on my previous comment about not seeing delivered packages, I would probably create a separate automation that monitors the sensor.17track_delivered for a value increase and then make an API call specifically for the delivered package state and send a notification to a desired notification endpoint.

My biggest complaint right now is that the 17track API exposes much more data than is made available by this integration and I wish it would pass the full dataset and allow us to drill down to the data we want rather than being limited by the data they’ve decided we should have.