Compare three Numbers and display the lowest in Sitemap

Dear Community,
I have 3 gaz stations in my proximity and I want my basicUI (eventually my HabPanel when I figured out how to work it) to only show the cheapest station
so I am thinking of a rule with something like:

rule "figure out the cheapest station"
then 
Item Station1 received update or
Item Station2 received update or
Item Station3 received update

then
var station1 = ??
//what do I need to put here, so that var station1 equals the prize of Station 1
var Station2= 
var Station3=
var min
if
(Station1 <= Station2 && Station1 <= Station3)
{var min==Station1}
else if
(Station2 <= Station1 && Station2 <= Station3)
{var min==Station2}
else
var min==Station3
end

something like that.
A couple of problems I run into when thinking about it:
how do i now which station actually has the lowest value? And how do I put that rule in proper syntax.
I feel quite stupid…
Thanks guys

Have a look at this example:

1 Like

It’s not so diffuclt with three. Compare A and B to find the lowest. Now compare that with C and choose the lowest of that pair. That’ll be the lowest of three.

What about using a group for that purpose?

Group:Number:MIN gGasStations "Cheapest one [%d]"  //assuming the value comes as decimal. Otherwise use [%.1f].

And your item definitions then should be part of the group

Number Station1 "some Label" <some_icon> (gGasStations) {channel="some_binding:some_channel"}
Number Station2 "some Label" <some_icon> (gGasStations) {channel="some_binding:some_channel"}
Number Station3 "some Label" <some_icon> (gGasStations) {channel="some_binding:some_channel"}

So in the end the group does the comparison for you and report the cheapest gas station. No rule needed.

See also
https://docs.openhab.org/configuration/items.html#group-type

Thanks Sascha,
that does work actually - an approach I would have never come up with.
Unfortunately it leads to 2 new problems:
1st: one of the 3 stations is only open at certain times.

It does have a switch:

Contact Station1_open {channel="tankerkoenig_open"}

But when closed the price equals 0, hence the MIN Group returns 0 - behavior which is not intended.

2nd:
I do not only want to display the value of the Min station, but also which Station the value is from. In fact the sitemap should only show the price in € of the cheapest Station together with its name…

My head is spinning :slight_smile:

To be honest, I initially thought that you want also the name of the gas station displayed. :slight_smile:

So therefore we might need a proxy item:

String CheapestGasStation

and then a rule that writes the name of the station and the current value to this item:

rule "My cheapest gas station"

when 
   Item gGasStations changed
then
  gGasStations.allMembers.forEach [ item | 
    if(item.state == gGasStations.state){
      CheapestGasStation.sendCommand(item.toString() + item.state.toString())
 ]
end

i didn’t test this code so it might have some typos but the idea would be:
Iterating through all items within the group and if you find an item has got the same value as the group, this item name and it’s value should then be sent to the proxy Item.
You still can format the string that you are passing through sendCommand to your needs.

So there’s only one drawback - you still have the problem that the group value is 0 when a station is closed and therefore you would display the 0 value together with its item name.
So maybe instead of looking for the item that has the same value as the group, you might iterate through all items and still look for the lowest that it not 0.

Don’t have a good example for that so i think you’re a bit on your own for now :wink:

Hi,
it’s getting better on my side.
Using

rule "My cheapest gas station"
when 
   Item gGasStations changed
then
  gGasStations.allMembers.forEach [ item | 
    if(item.state == gGasStations.state){
      CheapestGasStation.sendCommand(item.toString(Label) + item.to.string(State))
    }]
end

Returns this in the logfile:

CheapestGasStation changed from NULL to tanken_stuhr_hem_diesel (Type=NumberItem, State=1.149, Label=HEM Moordeich Diesel, Category=null, Groups=[Tanken, gGasStations])1.149

So all the Information is right there in the log file. Now I just need to extract it into some kind of format to show on my Sitemap (Desired would be “LABEL” followed by State + € - so in my example it would return: “HEM Moordeich Diesel 1,149 €”)

However putting

Text item=CheapestGasStation 

does not return anything.

Text item=gGasStations

At least gives me the value of the Station (so 1,149€ in my case)

What to do?

Well I think you should create the item like:

String CheapestGasStation "Cheapest Gas Station is [%s]"

So it now will display the whole string that you can see in the logfile which means you should write in your rule:

CheapestGasStation.sendCommand(item.label + item.state.toString())

That should result in

HEM Moordeich Diesel1.149

So you still should to some nice formatting, e.g.:

CheapestGasStation.sendCommand(item.label + " " + "€" + item.state.toString() )
HEM Moordeich Diesel €1.149

I’ve read that it can cause problems to change an item label from a rule, but reading shouldn’t cause any issues

CheapestGasStation.sendCommand(item.label + " " + "€" + item.state.toString() )

works pretty well. It only does not acknowledge the spaces but that is fine with me (meaning " " does not make a difference to " ").
The only weird thing is that normally the price is shown with comma (,) but stated formatting returns a (.) But that is a fact I can also live with for now.

a other way for cheapest gas price and station(s).