Jep now I saw the rmv-card and reinstalled it but it don’t change the view an the log-entries:
I need to take a look next week.
Edit:
Noob me, adding the card to the resources is done automatically.
Fresh HA (Docker) installation here, works fine for me.
- Installed rmv-card via HACS
- Edited in RAW Mode, throw this at top
resources:
- url: /config/www/community/rmv-card/rmv-card.js?v=0
type: js
and this under cars:
cards:
- type: 'custom:rmv-card'
entity:
- sensor.<<insertStationsensorName>>
Just to drop some idea, i think it would be nice to have the card more like a real Frankfurt Station Sign. If the train,bus, etc is more than 60 minutes away (i guess thats the default) it should show the real time, not the minutes.
But, works nice for me, so thanks!
I am very satisfied with that card. But only one more thing should be nice, if in addition to the “arriving minutes” also the planned departure time would be displayed.
Had the same idea!
So i added a little bit quick & dirty code and there we have it:
As far as i remembered, i just deleted the .js.gz file and added those 3 variables and enhanced the <td>
with the new variables. Some <small>
as dirty styling format.
const hours = (jtime.getUTCHours()<10?'0':'') + jtime.getUTCHours()
const minutes = (jtime.getUTCMinutes()<10?'0':'') + jtime.getUTCMinutes()
const depTime = `(${hours}:${minutes})`
tablehtml += `
<tr>
<td class="shrink" style="text-align:center;"><span class="line ${product} ${linename}">${linename}</span></td>
<td class="expand">${destination}</td>
<td class="shrink" style="text-align:right;">${time} <small>${depTime}</small></td>
</tr>
`
Note: No javascript developer here. Take care.
I also saw those strange behaviour around midnight. I guess this is based on the enforcement of the UTC timezone and pressing the dates from the RMV API into that.
As i totally understand working with dates in ‘plain’ javascript is a total pain, i am curios if you tried using something like moment.js
or similiar?
@MaxW thanks so much!!
That means i also need to delete the gzip file and edit the rmv-card.js?
What is this rmv-card.js.gz for? Only a zipped copy of the script. Is it necessary to have it in the folder?
The gzip file contains an compressed version of the rmv-card.js. The main purpose is to speedup loading times as modern browsers will prefere the compressed version over the non compressed. For compatibiliy reasons the uncompressed file is also available.
(This is a very complex thing, as there are many implementations based on the webserver, the client, caching proxy and others.)
You could compress it back, but i don’t really care about that 3.1 KiloBytes. I guess we talk about less than 10 millisecons.
I did not deceide yet how i will continue with this modification. Maybe i clean it up and provide it as PullRequest for @cgtobi to have it as additonal feature. Are you intrested?
Else i can simply fork it and do my own version of it.
This manually overwriting will work fine until he releases a new version of his card. Then HASC will overwrite it.
So, long story short: Yes, delete the gzip file and edit the rmv-card.js.
Here is mine for reference in total. You could copy paste it, or adjust it manually and lern a little bit
class RmvCard extends HTMLElement {
set hass (hass) {
const entityId = this.config.entity
const state = hass.states[entityId]
const name = state.attributes['friendly_name']
if (!this.content) {
const card = document.createElement('ha-card')
card.header = name
this.content = document.createElement('div')
const style = document.createElement('style')
style.textContent = `
table {
width: 100%;
padding: 6px 14px;
}
td {
padding: 3px 0px;
}
td.shrink {
white-space:nowrap;
}
td.expand {
width: 99%
}
span.line {
font-weight: bold;
font-size:0.9em;
padding:3px 8px 2px 8px;
color: #fff;
background-color: #888;
margin-right:0.7em;
}
span.S {
background-color: #009252;
}
span.U-Bahn {
background-color: #0067ad;
}
span.Tram {
background-color: #eb6810;
}
span.Bus {
background-color: #a3047a;
}
span.Bahn {
background-color: #000000;
}
`
card.appendChild(style)
card.appendChild(this.content)
this.appendChild(card)
}
var tablehtml = `
<table>
`
const now = new Date()
const utc = Date.UTC(now.getFullYear(), now.getMonth(), now.getDate(),
now.getHours(), now.getMinutes(), now.getSeconds(), now.getMilliseconds())
const next = {
'line': state.attributes['line'],
'product': state.attributes['product'],
'destination': state.attributes['destination'],
'departure_time': state.attributes['departure_time'],
'direction': state.attributes['direction']
}
const journeys = [next].concat(state.attributes['next_departures'])
for (const journey of journeys) {
var destination = journey['destination']
if (typeof journey['destination'] === 'undefined') {
destination = journey['direction']
}
const linename = journey['line']
const product = journey['product']
const jtime = new Date(journey['departure_time'] + 'Z')
const time = parseInt((jtime.getTime() - utc) / 60000)
const hours = (jtime.getUTCHours()<10?'0':'') + jtime.getUTCHours()
const minutes = (jtime.getUTCMinutes()<10?'0':'') + jtime.getUTCMinutes()
const depTime = `(${hours}:${minutes})`
tablehtml += `
<tr>
<td class="shrink" style="text-align:center;"><span class="line ${product} ${linename}">${linename}</span></td>
<td class="expand">${destination}</td>
<td class="shrink" style="text-align:right;">${time} <small>${depTime}</small></td>
</tr>
`
}
tablehtml += `
</table>
`
this.content.innerHTML = tablehtml
}
setConfig (config) {
if (!config.entity) {
throw new Error('You need to define an entity')
}
this.config = config
}
getCardSize () {
return 1
}
}
customElements.define('rmv-card', RmvCard)
of course … very interested. thanks for that clear explanation. i will implement it at weekend, when i have enough time seems to be quit easy. thanks so much!
managed to capture a screenshot of those strange minutes:
As 1441 equals roughly 24h and a little, which would lead to the correct time, but one day to late.
The more i look at this, i am confused why there is a calculation at all, as the sensor is already providing the minutes?
Indeed, this looks promising to me. I dropped the UTC calculation magic and simply used the minutes provided by the sensor attribute:
class RmvCard extends HTMLElement {
set hass (hass) {
const entityId = this.config.entity
const state = hass.states[entityId]
const name = state.attributes['friendly_name']
if (!this.content) {
const card = document.createElement('ha-card')
card.header = name
this.content = document.createElement('div')
const style = document.createElement('style')
style.textContent = `
table {
width: 100%;
padding: 6px 14px;
}
td {
padding: 3px 0px;
}
td.shrink {
white-space:nowrap;
}
td.expand {
width: 99%
}
span.line {
font-weight: bold;
font-size:0.9em;
padding:3px 8px 2px 8px;
color: #fff;
background-color: #888;
margin-right:0.7em;
}
span.S {
background-color: #009252;
}
span.U-Bahn {
background-color: #0067ad;
}
span.Tram {
background-color: #eb6810;
}
span.Bus {
background-color: #a3047a;
}
span.Bahn {
background-color: #000000;
}
`
card.appendChild(style)
card.appendChild(this.content)
this.appendChild(card)
}
var tablehtml = `
<table>
`
const next = {
'line': state.attributes['line'],
'product': state.attributes['product'],
'destination': state.attributes['destination'],
'departure_time': state.attributes['departure_time'],
'direction': state.attributes['direction'],
'minutes': state.attributes['minutes']
}
const journeys = [next].concat(state.attributes['next_departures'])
for (const journey of journeys) {
var destination = journey['destination']
if (typeof journey['destination'] === 'undefined') {
destination = journey['direction']
}
const linename = journey['line']
const product = journey['product']
const jtime = new Date(journey['departure_time'] + 'Z')
const hours = (jtime.getUTCHours() <10 ? '0' : '') + jtime.getUTCHours()
const minutes = (jtime.getUTCMinutes() < 10 ? '0': '') + jtime.getUTCMinutes()
const depTime = `(${hours}:${minutes})`
tablehtml += `
<tr>
<td class="shrink" style="text-align:center;"><span class="line ${product} ${linename}">${linename}</span></td>
<td class="expand">${destination}</td>
<td class="shrink" style="text-align:right;">${journey['minutes']} <small>${depTime}</small></td>
</tr>
`
}
tablehtml += `
</table>
`
this.content.innerHTML = tablehtml
}
setConfig (config) {
if (!config.entity) {
throw new Error('You need to define an entity')
}
this.config = config
}
getCardSize () {
return 1
}
}
customElements.define('rmv-card', RmvCard)
Please check out the latest version on GitHub - custom-cards/rmv-card: Custom card for the RMV component. or straight from HACS.
I’ve added a few options:
Title
friendly_name: My custom name
hide_title: true
Departure time and minutes
hide_minutes: true
show_time: true
Thx, works nice for me!
You might want to drop superflous code around here: https://github.com/cgtobi/rmv-card/blob/4d2868944703af8dcbdd5c3825f98e85b65f5eab/rmv-card.js#L59
Well spotted. The new features are now available via HACS.
Hi @cgtobi! thx! it works now!
With the destination “Frankfurt (Main) Dornbusch” seems to be a bug. however!
I decided to use “Frankfurt (Main) Südbahnhof” instead. know it works fine
sensor:
.
.
.
- platform: rmvtransport
scan_interval: 120
timeout: 10
next_departure:
- station: 3002398
time_offset: 5
max_journeys: 6
name: BadHomburg
destinations:
- 'Bad Homburg v.d.H.-Ober-Eschbach (U)'
products:
- 'U-Bahn'
- 'Bus'
- platform: rmvtransport
scan_interval: 120
timeout: 10
next_departure:
- station: 3002398
time_offset: 5
max_journeys: 6
name: Suedbahnhof
destinations:
- 'Frankfurt (Main) Südbahnhof'
products:
- 'U-Bahn'
- 'Bus'
thx a lot!
This is so nice! Thanks a lot. A question from my side: would it be possible to show “minutes” or something like “min” behind the number?
Hi,
My card is giving me an “Invalid Time Value” error.
The Card config is as simple as:
type: custom:rmv-card
entity:
- sensor.karben_burg_grafenrode_friedhof
The sensor is setup as the following (in sensor.yaml):
- platform: rmvtransport
next_departure:
- station: 3022913
time_offset: 5
destinations:
- "Karben-Groß-Karben Gesamtschule"
products:
- "Bus"
The entity has been created successful, however the state of the created sensor is unavailable
Any hints on how to get this solved?!
Best,
goeste
This is what I can see from the logs:
File "/usr/src/homeassistant/homeassistant/components/rmvtransport/sensor.py", line 190, in async_update
await self.data.async_update()
File "/usr/src/homeassistant/homeassistant/components/rmvtransport/sensor.py", line 237, in async_update
_data = await self.rmv.get_departures(
File "/usr/local/lib/python3.10/site-packages/RMVtransport/rmvtransport.py", line 78, in get_departures
raise RMVtransportError(err) from err
followed by
2022-09-01 09:39:11.251 ERROR (MainThread) [homeassistant.helpers.entity] Update for sensor.rmv_journey fails
Traceback (most recent call last):
File "/usr/local/lib/python3.10/site-packages/RMVtransport/rmvtransport.py", line 74, in get_departures
for journey in self.obj.SBRes.JourneyList.Journey:
File "src/lxml/objectify.pyx", line 234, in lxml.objectify.ObjectifiedElement.__getattr__
File "src/lxml/objectify.pyx", line 453, in lxml.objectify._lookupChildOrRaise
AttributeError: no such child: JourneyList
and
File "/usr/src/homeassistant/homeassistant/components/rmvtransport/sensor.py", line 190, in async_update
await self.data.async_update()
File "/usr/src/homeassistant/homeassistant/components/rmvtransport/sensor.py", line 237, in async_update
_data = await self.rmv.get_departures(
File "/usr/local/lib/python3.10/site-packages/RMVtransport/rmvtransport.py", line 78, in get_departures
raise RMVtransportError(err) from err
RMVtransport.errors.RMVtransportError: no such child: JourneyList
Probably, the connection to the API is broken?
Hello! I opened an issue on github, but I wanted to cover all bases
The card doesn’t show up for me. I installed it via HACS and it just doesn’t show up. Logs aren’t mentioning the card at all.
€: Ok, figured it out. Was my own fault. Sorry!