Looking at the DHL app, this should be easy. They use a simple POST call to my.dhlparcel.nl/api/user/login with the username and password. The response headers include two cookies (access_token and refresh_token) which are JWT tokens.
https://my.dhlparcel.nl/receiver-parcel-api/parcels returns all parcels.
https://my.dhlparcel.nl/receiver-parcel-api/track-trace?key={TT_CODE}%2B{ZIPCODE}&role=receiver will return the details.
I try to avoid DHL as much as possible, so I am not really able to properly build and test a new version of the integration.
I created a beta release (11.2.0 beta 1). In this release I try to solve an issue which I encountered a couple of times. Sometimes the PostNL API doesnât return any data (5xx error) or is unreachable. This will break the sensor and therefor the lovelace. I try to solve this by adding a retry strategy. I also changed the behaviour in retrieving data (using async now). This will improve the start time of the integration.
Please test the beta release and let me know if there are (no) issues .
If there is an expected delivery date and time, then this data is added to the delivery data. However, the original lovelace does not show this data. I forked the lovelace and changed the code. In my HA env I can see the data.
You need to do some template magic if you want to create an automation.
Can you describe it more detailed please how you did this? Because I got the postnl integration from arjenbos working but the letters entity is not in there. So how did you solve this with the python api wrapper? Please a short step-by-step procedure would be awesome!
This is not PostNL related, but since we discussed DHL earlier I thought I should share some findings here.
Long story short, I got my DHL packages which are on the way available within Home Assistant through the multiscrape component.
So far it has been running for almost 24 hours and I havenât seen any issues yet. As my package meanwhile got delivered, I canât garantuee that it works flawlessly though.
The only issue that is present is whenever you (re)start home assistant, the sensor might be unavailable, but becomes available after reloading the multiscrape configuration.
This is my multiscrape setup. Replace YOUR EMAIL and YOUR PASSWORD with your credentials.
It might also work with the default rest integration. Havenât tried that.
Of course risking to deviate too much from the PostNL integration (thanks!), I am struggling in getting the DHL code you posted to work.
I get the following errors:
Scraper_noname_1 # Updating failed with exception: Client error '403 Forbidden' for url 'https://my.dhlparcel.nl/receiver-parcel-api/parcels' For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/403
Scraper_noname_0 # Updating failed with exception: Client error '401 Unauthorized' for url 'https://my.dhlparcel.nl/api/user/login' For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/401
Did DHL change something on their end? Or should I have a business account?
You donât need a business account. At my place it still works.
Do note that it doesnât work on restart of home assistant. After an hour it will work or after manually reloading the multiscrape component within the developer tools.
Check the DHL package sensor. It should say zero or more (except on restart, then it says unavailable).
Since this weekend, I had an error in HA in showing the joint PostNL & DHL card:
TypeError: 'NoneType' object is not iterable
Via ChatGTP I was able to adjust the code to get it working again, it might help you as well
type: conditional
conditions:
- condition: or
conditions:
- condition: numeric_state
entity: sensor.postnl_delivery
above: 0
- condition: numeric_state
entity: sensor.dhl_packages
above: 0
card:
type: markdown
card_mod:
style:
ha-markdown$: |
table {
width: 100%;
}
thead {
font-weight: bold;
}
ha-icon {
--icon-primary-color: #44739e;
}
content: |
<header style="display: flex; align-items: flex-end;">
<ha-icon icon="mdi:package-variant" style="vertical-align: bottom;"></ha-icon>
<font size="5">Pakketjes</font>
</header>
<table>
<thead>
<tr>
<td>Bezorger</td>
<td>Pakket</td>
<td>Datum</td>
<td>Tijd</td>
</tr>
</thead>
<tbody>
{% for package in state_attr('sensor.postnl_delivery', 'enroute') %}
{% if package.planned_date is not none and package.planned_from is defined and package.planned_to is defined %}
<tr>
<td>PostNL</td>
<td>{{ package.name }}</td>
<td>{{ as_timestamp(package.planned_date) | timestamp_custom('%-d %b') }}</td>
<td>{{ as_timestamp(package.planned_from) | timestamp_custom('%H:%M') }} - {{ as_timestamp(package.planned_to) | timestamp_custom('%H:%M') }}</td>
</tr>
{% endif %}
{% endfor %}
{% for package in state_attr('sensor.dhl_packages', 'parcels') %}
{% if package.receivingTimeIndication is not none and package.receivingTimeIndication.start is defined and package.receivingTimeIndication.end is defined %}
<tr>
<td>DHL</td>
<td>{{ package.sender.name if package.sender is defined else 'Unknown' }}</td>
<td>{{ as_timestamp(package.receivingTimeIndication.start) | timestamp_custom('%-d %b') }}</td>
<td>{{ as_timestamp(package.receivingTimeIndication.start) | timestamp_custom('%H:%M') }} - {{ as_timestamp(package.receivingTimeIndication.end) | timestamp_custom('%H:%M') }}</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
The following steps were suggested to resolve this (by ChatGTP):
Check if Attributes are None:
Ensure that the attributes you are trying to iterate over (âenrouteâ for sensor.postnl_delivery and âparcelsâ for sensor.dhl_packages) are not None.
Add Checks for None:
You can add a check to ensure these attributes are not None before attempting to iterate over them.