Polish version: https://github.com/DominikWrobel/mpk_lodz/blob/main/PL.md
This is an integration to get live bus and tram departures using an unofficial MPK Łódź API. The code is based on the work of @PiotrMachowski
- Install it with HACS by adding (https://github.com/DominikWrobel/mpk_lodz) as a custom repository
Find MPK Łódź in integrations page:
You can use stop_id, stop_number or group of stops, to get the stop info go to the page (http://rozklady.lodz.pl/) and find your stop, click on it and in the popup page you will see the number:
If it says busStopNum= use the number field, if it says busStopId= use the id field. To get the group stop number on the rozklady.lodz.pl page you have to check the Węzły przystankowe option and find your stop group:
After the integration is set up you will get 10 entities, one for each departure from your stop, in the first entitie you will also get info on alert and the current time sent by the system
This data format is optimised for use by the custom:flex-table-card and you can get this card:
Card yaml
type: custom:flex-table-card
entities:
include:
- sensor.mpk_lodz_group_1_piotrkowska_centrum_0
- sensor.mpk_lodz_group_1_piotrkowska_centrum_1
- sensor.mpk_lodz_group_1_piotrkowska_centrum_2
- sensor.mpk_lodz_group_1_piotrkowska_centrum_3
- sensor.mpk_lodz_group_1_piotrkowska_centrum_4
- sensor.mpk_lodz_group_1_piotrkowska_centrum_5
- sensor.mpk_lodz_group_1_piotrkowska_centrum_6
- sensor.mpk_lodz_group_1_piotrkowska_centrum_7
- sensor.mpk_lodz_group_1_piotrkowska_centrum_8
- sensor.mpk_lodz_group_1_piotrkowska_centrum_9
columns:
- name: " "
icon: mdi:unicorn-variant
data: line
align: c
modify: |-
if (x.length == 0) {
" ";
} else {
const lineNumber = parseInt(x);
let icon = '';
let style = '';
switch(true) {
case x.includes('N'):
icon = 'mdi:bus';
style = 'background-color: darkblue; color: lightgray;';
break;
case x.includes('6.'):
icon = 'mdi:bus';
style = 'color: green;';
break;
case !isNaN(lineNumber) && lineNumber >= 1 && lineNumber <= 49:
icon = 'mdi:tram';
style = 'color: orange;';
break;
case !isNaN(lineNumber) && lineNumber >= 50 && lineNumber <= 99:
icon = 'mdi:bus';
style = 'color: green;';
break;
case x.includes('Z'):
icon = 'mdi:bus';
style = 'color: green;';
break;
case x.includes('O'):
icon = 'mdi:tram';
style = 'color: orange;';
break;
case x.includes('100'):
icon = 'mdi:bus';
style = 'color: green;';
break;
case x.includes('151'):
icon = 'mdi:bus';
style = 'background-color: darkblue; color: lightgray;';
break;
case x.includes('102'):
icon = 'mdi:bus';
style = 'background-color: magenta; color: white;';
break;
case x.includes('C'):
icon = 'mdi:tram';
style = 'color: orange;';
break;
default:
icon = 'mdi:bus';
}
'<div style="' + style + '"><ha-icon icon="' + icon + '"></ha-icon> ' + x + '</div>';
}
- name: Piotrkowska Centrum
data: direction
align: center
modify: if(x.length == 0){" "}else{x}
- name: " "
icon: mdi:information-slab-circle-outline
data: features
align: c
- name: " "
data: time
align: center
modify: |-
if (x.length == 0) {
" ";
} else {
let style = '';
let cssClass = '';
if (x === '<1min') {
style = 'color: red;';
cssClass = 'blink';
} else if (x.includes(':')) {
style = 'color: lightgray;';
} else {
const minutes = parseInt(x);
if (minutes === 1) {
style = 'color: red;';
} else if (minutes >= 2 && minutes <= 5) {
style = 'color: yellow;';
} else if (minutes >= 6) {
style = 'color: green;';
} else {
style = 'color: gray;';
}
}
'<div class="' + cssClass + '" style="' + style + '">' + x + '</div>';
}
css:
thead th:nth-child(1): "color: #4682B4;"
thead th:nth-child(2): "color: #4682B4;"
thead th:nth-child(3): "color: #4682B4;"
thead th:nth-child(4): "color: #4682B4;"
tbody tr td:nth-child(1)+: "min-width: 55px;width: 55px;"
tbody tr td:nth-child(4)+: "min-width: 50px;width: 50px;"
tbody tr td:nth-child(2)+: "min-width: 150px;width: 210px;"
tbody tr td:nth-child(3)+: "min-width: 49px;width: 49px;"
table+: "padding-bottom: 4px;"
tbody tr:nth-child(even): "background-color: #a2542f6;"
tbody tr:nth-child(odd): "background-color: #a2542f6;"
card_mod:
style: |
@keyframes blink {
0% { opacity: 1; }
50% { opacity: 0; }
100% { opacity: 1; }
}
.blink {
animation: blink 1s linear infinite;
}
ha-card {
overflow: visible !important;
}
thead th:nth-child(4)::after {
content: "{{ (state_attr("sensor.mpk_lodz_group_1_piotrkowska_centrum_0", "current_time")) }}";
}
And for the allert you can use the markdown card:
Card yaml
type: markdown
content: >
<center> {{ (state_attr("sensor.mpk_lodz_group_1_piotrkowska_centrum_0",
"alert")) }} </center>
You can set up as many stops as you want the data will be fatched every 1 min. Be aware that bus and tram stops without a LED display will not show the allert status, you can set up another stop (like Piotrkowska Centrum) to get the allert info.
If you like my work you can support me via: