@Tms_Hervik_Fuglm @gaute91
Sorry guys for not getting back to you earlier. The setup to run the Ruter widget is kind of messy. Ideally, somone with a knowledge of json would set this up as a job in ruby. Anyways, here it goes!
Sourcing the data
I’ve added the two bus stops as HTTP-bindings in the configuration file of openhab. Check out the API documentation of Ruter on how to manipulate this into your requirements.
http:RuterSann37.url=http://reisapi.ruter.no/stopvisit/getdepartures/3010324?linenames=37&json=true
http:RuterSann37.updateInterval=30000
http:RuterSann5434.url=http://reisapi.ruter.no/stopvisit/getdepartures/3010516?linenames=54,34&json=true
http:RuterSann5434.updateInterval=30000
The json string from the http-binding is parsed and added as items. I parse the 3 next departures per direction (south/north):
DateTime Ruter_37s_1n "[%1$tR]" (ruter) {http="<[RuterSann37:60000:JSONPATH($..MonitoredVehicleJourney[?(@.DirectionRef==2)].MonitoredCall.ExpectedDepartureTime[0])]"}
DateTime Ruter_37s_2n "[%1$tR]" (ruter) {http="<[RuterSann37:60000:JSONPATH($..MonitoredVehicleJourney[?(@.DirectionRef==2)].MonitoredCall.ExpectedDepartureTime[1])]"}
DateTime Ruter_37s_3n "[%1$tR]" (ruter) {http="<[RuterSann37:60000:JSONPATH($..MonitoredVehicleJourney[?(@.DirectionRef==2)].MonitoredCall.ExpectedDepartureTime[2])]"}
DateTime Ruter_37s_1s "[%1$tR]" (ruter) {http="<[RuterSann37:60000:JSONPATH($..MonitoredVehicleJourney[?(@.DirectionRef==1)].MonitoredCall.ExpectedDepartureTime[0])]"}
DateTime Ruter_37s_2s "[%1$tR]" (ruter) {http="<[RuterSann37:60000:JSONPATH($..MonitoredVehicleJourney[?(@.DirectionRef==1)].MonitoredCall.ExpectedDepartureTime[1])]"}
DateTime Ruter_37s_3s "[%1$tR]" (ruter) {http="<[RuterSann37:60000:JSONPATH($..MonitoredVehicleJourney[?(@.DirectionRef==1)].MonitoredCall.ExpectedDepartureTime[2])]"}
A problem with this, is that when there are no buses that run at night your log will be full of errors and warnings. This is due to the fact that the json strin beeing parsed is empty…
Sending data to dashing
I send the parsed data to dashing by concatenating the string in a rule. In this rule, I also transform the timestamp into “minutes left”.
rule "Ruter"
when
Time cron "0 0/1 * * * ?"
then
lock.lock()
Thread::sleep(3000)
var DateTimeType dt_Ruter_37s_1n = Ruter_37s_1n.state as DateTimeType
var DateTimeType dt_Ruter_37s_2n = Ruter_37s_2n.state as DateTimeType
var DateTimeType dt_Ruter_37s_3n = Ruter_37s_3n.state as DateTimeType
var DateTimeType dt_Ruter_37s_1s = Ruter_37s_1s.state as DateTimeType
var DateTimeType dt_Ruter_37s_2s = Ruter_37s_2s.state as DateTimeType
var DateTimeType dt_Ruter_37s_3s = Ruter_37s_3s.state as DateTimeType
var DateTimeType dt_Ruter_54s_1n = Ruter_54s_1n.state as DateTimeType
var DateTimeType dt_Ruter_54s_2n = Ruter_54s_2n.state as DateTimeType
var DateTimeType dt_Ruter_54s_3n = Ruter_54s_3n.state as DateTimeType
var DateTimeType dt_Ruter_54s_1s = Ruter_54s_1s.state as DateTimeType
var DateTimeType dt_Ruter_54s_2s = Ruter_54s_2s.state as DateTimeType
var DateTimeType dt_Ruter_54s_3s = Ruter_54s_3s.state as DateTimeType
var DateTimeType dt_Ruter_34s_1n = Ruter_34s_1n.state as DateTimeType
var DateTimeType dt_Ruter_34s_2n = Ruter_34s_2n.state as DateTimeType
var DateTimeType dt_Ruter_34s_3n = Ruter_34s_3n.state as DateTimeType
var DateTimeType dt_Ruter_34s_1s = Ruter_34s_1s.state as DateTimeType
var DateTimeType dt_Ruter_34s_2s = Ruter_34s_2s.state as DateTimeType
var DateTimeType dt_Ruter_34s_3s = Ruter_34s_3s.state as DateTimeType
var int m_ruter_37s_1n = Minutes::minutesBetween(now, new DateTime(dt_Ruter_37s_1n.calendar.timeInMillis)).getMinutes()
var int m_ruter_37s_2n = Minutes::minutesBetween(now, new DateTime(dt_Ruter_37s_2n.calendar.timeInMillis)).getMinutes()
var int m_ruter_37s_3n = Minutes::minutesBetween(now, new DateTime(dt_Ruter_37s_3n.calendar.timeInMillis)).getMinutes()
var int m_ruter_37s_1s = Minutes::minutesBetween(now, new DateTime(dt_Ruter_37s_1s.calendar.timeInMillis)).getMinutes()
var int m_ruter_37s_2s = Minutes::minutesBetween(now, new DateTime(dt_Ruter_37s_2s.calendar.timeInMillis)).getMinutes()
var int m_ruter_37s_3s = Minutes::minutesBetween(now, new DateTime(dt_Ruter_37s_3s.calendar.timeInMillis)).getMinutes()
var int m_ruter_54s_1n = Minutes::minutesBetween(now, new DateTime(dt_Ruter_54s_1n.calendar.timeInMillis)).getMinutes()
var int m_ruter_54s_2n = Minutes::minutesBetween(now, new DateTime(dt_Ruter_54s_2n.calendar.timeInMillis)).getMinutes()
var int m_ruter_54s_3n = Minutes::minutesBetween(now, new DateTime(dt_Ruter_54s_3n.calendar.timeInMillis)).getMinutes()
var int m_ruter_54s_1s = Minutes::minutesBetween(now, new DateTime(dt_Ruter_54s_1s.calendar.timeInMillis)).getMinutes()
var int m_ruter_54s_2s = Minutes::minutesBetween(now, new DateTime(dt_Ruter_54s_2s.calendar.timeInMillis)).getMinutes()
var int m_ruter_54s_3s = Minutes::minutesBetween(now, new DateTime(dt_Ruter_54s_3s.calendar.timeInMillis)).getMinutes()
var int m_ruter_34s_1n = Minutes::minutesBetween(now, new DateTime(dt_Ruter_34s_1n.calendar.timeInMillis)).getMinutes()
var int m_ruter_34s_2n = Minutes::minutesBetween(now, new DateTime(dt_Ruter_34s_2n.calendar.timeInMillis)).getMinutes()
var int m_ruter_34s_3n = Minutes::minutesBetween(now, new DateTime(dt_Ruter_34s_3n.calendar.timeInMillis)).getMinutes()
var int m_ruter_34s_1s = Minutes::minutesBetween(now, new DateTime(dt_Ruter_34s_1s.calendar.timeInMillis)).getMinutes()
var int m_ruter_34s_2s = Minutes::minutesBetween(now, new DateTime(dt_Ruter_34s_2s.calendar.timeInMillis)).getMinutes()
var int m_ruter_34s_3s = Minutes::minutesBetween(now, new DateTime(dt_Ruter_34s_3s.calendar.timeInMillis)).getMinutes()
dashing_ruter.postUpdate(
//Ruter_37s_1n.state.toString +"|"+ Ruter_37s_2n.state.toString +"|"+ Ruter_37s_3n.state.toString +"|"+
//Ruter_37s_1s.state.toString +"|"+ Ruter_37s_2s.state.toString +"|"+ Ruter_37s_3s.state.toString +"|"+
//Ruter_54s_1n.state.toString +"|"+ Ruter_54s_2n.state.toString +"|"+ Ruter_54s_3n.state.toString +"|"+
//Ruter_54s_1s.state.toString +"|"+ Ruter_54s_2s.state.toString +"|"+ Ruter_54s_3s.state.toString
m_ruter_37s_1n +"|"+ m_ruter_37s_2n +"|"+ m_ruter_37s_3n +"|"+
m_ruter_37s_1s +"|"+ m_ruter_37s_2s +"|"+ m_ruter_37s_3s +"|"+
m_ruter_54s_1n +"|"+ m_ruter_54s_2n +"|"+ m_ruter_54s_3n +"|"+
m_ruter_54s_1s +"|"+ m_ruter_54s_2s +"|"+ m_ruter_54s_3s +"|"+
m_ruter_34s_1n +"|"+ m_ruter_34s_2n +"|"+ m_ruter_34s_3n +"|"+
m_ruter_34s_1s +"|"+ m_ruter_34s_2s +"|"+ m_ruter_34s_3s
)
lock.unlock()
end
Dashing
I have configured a widget called ohlist to make use of the concatenated string. First, I split the string into the original elements.
class Dashing.Ohlist extends Dashing.Widget
constructor: ->
super
@queryState()
@accessor 'ruter_37s_1n',
get: -> @_ruter_37s_1n ? @get('state').split("|")[0]
set: (key, value) ->
@_ruter_37s_1n = value
@accessor 'ruter_37s_2n',
get: -> @_ruter_37s_2n ? @get('state').split("|")[1]
set: (key, value) ->
@_ruter_37s_2n = value
@accessor 'ruter_37s_3n',
get: -> @_ruter_37s_3n ? @get('state').split("|")[2]
set: (key, value) ->
@_ruter_37s_3n = value
@accessor 'ruter_37s_1s',
get: -> @_ruter_37s_1s ? @get('state').split("|")[3]
set: (key, value) ->
@_ruter_37s_1s = value
@accessor 'ruter_37s_2s',
get: -> @_ruter_37s_2s ? @get('state').split("|")[4]
set: (key, value) ->
@_ruter_37s_2s = value
@accessor 'ruter_37s_3s',
get: -> @_ruter_37s_3s ? @get('state').split("|")[5]
set: (key, value) ->
@_ruter_37s_3s = value
@accessor 'ruter_54s_1n',
get: -> @_ruter_54s_1n ? @get('state').split("|")[6]
set: (key, value) ->
@_ruter_54s_1n = value
@accessor 'ruter_54s_2n',
get: -> @_ruter_54s_2n ? @get('state').split("|")[7]
set: (key, value) ->
@_ruter_54s_2n = value
@accessor 'ruter_54s_3n',
get: -> @_ruter_54s_3n ? @get('state').split("|")[8]
set: (key, value) ->
@_ruter_54s_3n = value
@accessor 'ruter_54s_1s',
get: -> @_ruter_54s_1s ? @get('state').split("|")[9]
set: (key, value) ->
@_ruter_54s_1s = value
@accessor 'ruter_54s_2s',
get: -> @_ruter_54s_2s ? @get('state').split("|")[10]
set: (key, value) ->
@_ruter_54s_2s = value
@accessor 'ruter_54s_3s',
get: -> @_ruter_54s_3s ? @get('state').split("|")[11]
set: (key, value) ->
@_ruter_54s_3s = value
@accessor 'ruter_34s_1n',
get: -> @_ruter_34s_1n ? @get('state').split("|")[12]
set: (key, value) ->
@_ruter_34s_1n = value
@accessor 'ruter_34s_2n',
get: -> @_ruter_34s_2n ? @get('state').split("|")[13]
set: (key, value) ->
@_ruter_34s_2n = value
@accessor 'ruter_34s_3n',
get: -> @_ruter_34s_3n ? @get('state').split("|")[14]
set: (key, value) ->
@_ruter_34s_3n = value
@accessor 'ruter_34s_1s',
get: -> @_ruter_34s_1s ? @get('state').split("|")[15]
set: (key, value) ->
@_ruter_34s_1s = value
@accessor 'ruter_34s_2s',
get: -> @_ruter_34s_2s ? @get('state').split("|")[16]
set: (key, value) ->
@_ruter_34s_2s = value
@accessor 'ruter_34s_3s',
get: -> @_ruter_34s_3s ? @get('state').split("|")[17]
set: (key, value) ->
@_ruter_34s_3s = value
queryState: ->
$.get '/openhab/dispatch',
widgetId: @get('id'),
deviceId: @get('device'),
deviceType: 'rutetider'
(data) =>
json = JSON.parse data
@set 'state', json.state
ready: ->
onData: (data) ->
Each element is referenced in the html-part of the widget:
<tr style="background-color: rgb(230, 0, 0); line-height: 24px; text-align: left;">
<td colspan="3" style="align: left;">
<img src="/assets/ruter.png" height="24px" style="padding-top: 10px;padding-left: 10px;padding-bottom: 10px;">
</td>
</tr>
<tr class="RuteDest">
<td></td>
<td>Kjelsås</td>
<td>Aker Brygge</td>
</tr>
<tr>
<td rowspan="3" class="RuteNummer"><span>54</span></td>
<td class="RuteTid"><span data-bind="ruter_54s_1n | append ' m'"></span></td>
<td class="RuteTid"><span data-bind="ruter_54s_1s | append ' m'"></span></td>
</tr>
<tr>
<td class="RuteTid"><span data-bind="ruter_54s_2n | append ' m'"></span></td>
<td class="RuteTid"><span data-bind="ruter_54s_2s | append ' m'"></span></td>
</tr>
<tr>
<td class="RuteTid"><span data-bind="ruter_54s_3n | append ' m'"></span></td>
<td class="RuteTid"><span data-bind="ruter_54s_3s | append ' m'"></span></td>
</tr>
<tr class="RuteDest">
<td></td>
<td>Tåsen</td>
<td>Ekeberg</td>
</tr>
<tr>
<td rowspan="3" class="RuteNummer"><span>34</span></td>
<td class="RuteTid"><span data-bind="ruter_34s_1n | append ' m'"></span></td>
<td class="RuteTid"><span data-bind="ruter_34s_1s | append ' m'"></span></td>
</tr>
<tr>
<td class="RuteTid"><span data-bind="ruter_34s_2n | append ' m'"></span></td>
<td class="RuteTid"><span data-bind="ruter_34s_2s | append ' m'"></span></td>
</tr>
<tr>
<td class="RuteTid"><span data-bind="ruter_34s_3n | append ' m'"></span></td>
<td class="RuteTid"><span data-bind="ruter_34s_3s | append ' m'"></span></td>
</tr>
<tr class="RuteDest">
<td></td>
<td>Nydalen</td>
<td>Helsfyr</td>
</tr>
<tr>
<td rowspan="3" class="RuteNummer"><span>37</span></td>
<td class="RuteTid"><span data-bind="ruter_37s_1n | append ' m'"></span></td>
<td class="RuteTid"><span data-bind="ruter_37s_1s | append ' m'"></span></td>
</tr>
<tr>
<td class="RuteTid"><span data-bind="ruter_37s_2n | append ' m'"></span></td>
<td class="RuteTid"><span data-bind="ruter_37s_2s | append ' m'"></span></td>
</tr>
<tr>
<td class="RuteTid"><span data-bind="ruter_37s_3n | append ' m'"></span></td>
<td class="RuteTid"><span data-bind="ruter_37s_3s | append ' m'"></span></td>
</tr>
</table>
<p class="updated-at" data-bind="updatedAtMessage"></p>
And finally some css to make it look nice.
// ----------------------------------------------------------------------------
// Sass declarations
// ----------------------------------------------------------------------------
$background-color: #12b0c5;
$value-color: #fff;
$title-color: rgba(255, 255, 255, 0.7);
$label-color: rgba(255, 255, 255, 0.7);
$moreinfo-color: rgba(255, 255, 255, 0.7);
// ----------------------------------------------------------------------------
// Widget-list styles
// ----------------------------------------------------------------------------
.widget-ohlist {
background-color: $background-color;
vertical-align: top;
.title {
color: $title-color;
}
.RuteNummer {
font-size: 300%;
width: 20px;
padding-left: 10px;
padding-top: 5px;
}
.RuteTid {
font-weight: 600;
}
.RuteDest {
line-height: 23px;
background-color: rgb(230, 0, 0);
}
ol, ul {
margin: 0 15px;
text-align: left;
color: $label-color;
}
ol {
list-style-position: inside;
}
li {
margin-bottom: 5px;
}
.list-nostyle {
list-style: none;
}
.label {
color: $label-color;
}
.value {
float: right;
margin-left: 12px;
font-weight: 600;
color: $value-color;
}
.updated-at {
color: rgba(0, 0, 0, 0.3);
}
.more-info {
color: $moreinfo-color;
}
}
Hopefully you will be able to make use of this! And again, this is a very hacky solution and should definitely be improved upon. First step would be to just simply parse the json in dashing itself.