Member of Group Min -> TTS of the cheapest value doesn't work

Hi.
I have 5 values in a group.

Group:Number:MIN gGasStations                         "Cheapest one [%s]"
Number Aral_G1                 "Aral_G1"                              (gGasStations, gGasStations1,g2) {channel="tankerkoenig:station:WebserviceName:Aral:e5"}
Number Shell_G1                "Shell_G1 [%2.f]"                      (gGasStations, gGasStations1,g2) {channel="tankerkoenig:station:WebserviceName:Shell:e5"}
Number Aral_G2                 "Aral_G2 [%3.f]"                       (gGasStations, gGasStations1,g2) {channel="tankerkoenig:station:WebserviceName:AralGK:e5"}
Number Star                    "Star [%3.f]"                          (gGasStations, gGasStations1,g2) {channel="tankerkoenig:station:WebserviceName:Star:e5"}
Number PM_G1                   "PM_G1 [%.3f]"                         (gGasStations, gGasStations1,g2) {channel="tankerkoenig:station:WebserviceName:PM:e5"}
String CheapestGasStation            "Cheapest Gas Station is [%s]"

By member of group, it should be sort by the cheapest:

rule "My cheapest gas station"

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

That works.
But when i want to send this value to a TTS command, i hear the beginning of the first four values after each other for a second and at least the fifth value will be spoken complete. It reads the complete list and not the cheapest only i think.

rule "Tanken PM"

when 
 Item CheapestGasStation received update
then
    if(now.getHourOfDay() >8 && now.getHourOfDay() <21){
                  Wohnzimmer_TTS.sendCommand('Hey!' + ',' + 'Die Spritpreise haben sich gerade geändert' + ',' + 'Die günstigste Tankstelle ist' + ','  + CheapestGasStation.state.toString() + 'Euro')      
    }
end

Another problem is that CheapestGasStation.state.toString() gives me the right label, but becaue of the string the price will be 1.509 (thousend) and not 1,509 Euro.
Any ideas?
Thanks and Greetings,
Markus

If you only want the cheapest price, leave the forEach-loop after the first cycle, but you ever get the cheapest price, even than a higer is changed.

I think it’s the decimal point.
If OH is runnung on Linux set locale to de_DE.UTF-8.

Hi Harry.
Oh, after updating to OH2.3 i haven’t check the locale. Right, i have set the wrong locale. Now changed.
But how can i change the rule, so that the cheapest price will be checked with the cheapest price before. If this is not equal, send it to TTS?
Thank you very much for helping,
Markus

I need the label of the item too. And the five items changes every hour at the same time. Can i use a thread::sleep in the TTS rule to get only the last change to the min value?
Greetings,
Markus

String CheapestGasStation "Cheapest Gas Station[%s]"
Number CheapestGasPrice "Cheapest Gas Price[%.3f]"
CheapestGasStation.postUpdate(item.label)
CheapestGasPrice.postUpdate(item.state)
Group:Number:MIN gGasStations   "Cheapest Gas Price[%.3f €]"
Number Aral_G1                  "Aral_G1[%.3f]"                 (gGasStations) {channel="tankerkoenig:station:WebserviceName:Aral:e5"}
Number Shell_G1                 "Shell_G1[%.3f]"                (gGasStations) {channel="tankerkoenig:station:WebserviceName:Shell:e5"}
Number Aral_G2                  "Aral_G2[%.3f]"                 (gGasStations) {channel="tankerkoenig:station:WebserviceName:AralGK:e5"}
Number Star                     "Star[%.3f]"                    (gGasStations) {channel="tankerkoenig:station:WebserviceName:Star:e5"}
Number PM_G1                    "PM_G1[%.3f]"                   (gGasStations) {channel="tankerkoenig:station:WebserviceName:PM:e5"}
String CheapestGasStation       "Cheapest Gas Station(s)[%s]"
String cgsDummy
rule "My cheapest gas station"
when 
   Item gGasStations received update
then
    cgsDummy.postUpdate("")
    gGasStations.allMembers.forEach [ item | if (item.state == gGasStations.state) {
        Thread::sleep(30)
        if (cgsDummy.state == "") {cgsDummy.postUpdate(item.label)} else {cgsDummy.postUpdate(cgsDummy.state + "; " + item.label)}}]
    CheapestGasStation.postUpdate(cgsDummy.state)
//  logInfo("___", gGasStations.state.toString +" "+ CheapestGasStation.state)
end

Shows cheapest gas price and station(s).

you have to change additional

rule "Tanken PM"
when 
    Item gGasStations changed or
    Item CheapestGasStation changed
then
    if(now.getHourOfDay() >8 && now.getHourOfDay() <21){
        Wohnzimmer_TTS.sendCommand(... + CheapestGasStation.state +" "+ gGasStations.state.toString + " Euro")      
    }
end

Hi Harry.
So much thanks for your help. :slight_smile:
But if i use the rule it logs two item.labels (“1.439 PM_G1;Star”)

2018-06-29 17:56:14.948 [vent.ItemStateChangedEvent] - cgsDummy changed from PM_G1 to PM_G1; Star

Could it be a problem if two or more Stations have the same price?
Greetings,
Markus

Okay PM-G1 and Star have the same price. Is it possible to give both labels to the TTS command.
And after changing the local it still gives 1 thousand 4 houndred and 39. ?

I think (not knowing!) that is caused by the TTS service. You could prove that by changing the item to show only two decimal places, I would expect the TTS to say either 1 hundred and 39 or 1 thousend and 39 for 1.39.

Group:Number:MIN gGasStations   "Cheapest Gas Price[%.3f €]"
Number Aral_G1                  "Aral_G1[%.3f €]"                 (gGasStations) {channel="tankerkoenig:station:WebserviceName:Aral:e5"}
Number Shell_G1                 "Shell_G1[%.3f €]"                (gGasStations) {channel="tankerkoenig:station:WebserviceName:Shell:e5"}
Number Aral_G2                  "Aral_G2[%.3f €]"                 (gGasStations) {channel="tankerkoenig:station:WebserviceName:AralGK:e5"}
Number Star                     "Star[%.3f €]"                    (gGasStations) {channel="tankerkoenig:station:WebserviceName:Star:e5"}
Number PM_G1                    "PM_G1[%.3f €]"                   (gGasStations) {channel="tankerkoenig:station:WebserviceName:PM:e5"}
String CheapestGasStation       "Cheapest Gas Station/s[%s]"
rule "My cheapest gas station"
when 
    Item gGasStations received update
then
    val StringBuilder sb = new StringBuilder
    gGasStations.members.filter[ i | i.state == gGasStations.state].forEach[i | sb.append(", " + i.name) ]
    CheapestGasStation.postUpdate(sb.substring(2))
//  logInfo("***", String::format("%s %.3f Euro", CheapestGasStation.state, (gGasStations.state as DecimalType).floatValue))
//  if(now.getHourOfDay() >8 && now.getHourOfDay() <21){Wohnzimmer_TTS.sendCommand(String::format("%s %.3f Euro", CheapestGasStation.state, (gGasStations.state as DecimalType).floatValue))}    
end
sitemap tmp label="TMP" {
    Text     item=gGasStations
    Setpoint item=Aral_G1  minValue=1.309 maxValue=1.709 step=0.01
    Setpoint item=Shell_G1 minValue=1.309 maxValue=1.709 step=0.01
    Setpoint item=Aral_G2  minValue=1.309 maxValue=1.709 step=0.01
    Setpoint item=Star     minValue=1.309 maxValue=1.709 step=0.01
    Setpoint item=PM_G1    minValue=1.309 maxValue=1.709 step=0.01
    Default  item=CheapestGasStation
}

Hi Harry.
It’s running beautiful. Thank you very much for your help and time.
I have changed %.3f to %.2f to get a correct value in Euro.
The only thing that happens is that the TTS command repeats for every change. And Alexa says by 5 changes to the same time: Hey,Hey,Hey,Hey,Hey, die Spritpreise haben sich geändert…
I will test it with a ‘,’ before the text, so in background it will fire the rule five times but you cannot hear it. :slight_smile:
Thanks so much.
Greetings,
Markus

If you use

Item gGasStations changed

the rule runs only, if the cheapest price changed ,but not if one station added or remove from the list of cheapest.

untested

var lastgGasStations = 0.0
var lastCheapestGasStation = ""

rule "My cheapest gas station"
when 
    Item gGasStations received update
then
    ...
    if((lastCheapestGasStation != CheapestGasStation.state || lastgGasStations != gGasStations.state) && now.getHourOfDay() >8 && now.getHourOfDay() <21) {
        lastgGasStations = gGasStations.state
        lastCheapestGasStation = CheapestGasStation.state
        Wohnzimmer_TTS.sendCommand(String::format("%s %.3f Euro", CheapestGasStation.state, (gGasStations.state as DecimalType).floatValue))}*/
end

Hi Harry.
I have tested it an the log shows:


2018-07-04 10:36:44.483 [vent.ItemStateChangedEvent] - Star changed from 1.499 to 1.459

2018-07-04 10:36:44.483 [GroupItemStateChangedEvent] - gGasStations changed from 1.499 to 1.459 through Star

2018-07-04 10:36:44.692 [vent.ItemStateChangedEvent] - Hausserver_LastUpdated changed from 2018-07-04T10:36:34.691+0200 to 2018-07-04T10:36:44.691+0200

2018-07-04 10:36:44.693 [vent.ItemStateChangedEvent] - FlowerCare_LastUpdated changed from 2018-07-04T10:36:34.691+0200 to 2018-07-04T10:36:44.691+0200

2018-07-04 10:36:44.913 [vent.ItemStateChangedEvent] - Aral_G1_Update changed from 2018-07-04T09:36:53.733+0200 to 2018-07-04T10:36:44.911+0200

2018-07-04 10:36:44.913 [vent.ItemStateChangedEvent] - PM_G1_Update changed from 2018-07-04T09:36:53.633+0200 to 2018-07-04T10:36:44.911+0200

==> /var/log/openhab2/openhab.log <==

2018-07-04 10:36:44.915 [INFO ] [g.eclipse.smarthome.model.script.***] - Star 1,459 Euro

2018-07-04 10:36:44.916 [INFO ] [g.eclipse.smarthome.model.script.***] - Star 1,459 Euro

==> /var/log/openhab2/events.log <==

2018-07-04 10:36:44.916 [vent.ItemStateChangedEvent] - Shell_G1_Update changed from 2018-07-04T09:36:53.672+0200 to 2018-07-04T10:36:44.911+0200

2018-07-04 10:36:44.916 [vent.ItemStateChangedEvent] - Aral_G1_Update changed from 2018-07-04T09:36:53.685+0200 to 2018-07-04T10:36:44.911+0200

2018-07-04 10:36:44.918 [vent.ItemStateChangedEvent] - CheapestGasStation changed from Star, PM_G1 to Star

==> /var/log/openhab2/openhab.log <==

2018-07-04 10:36:44.918 [INFO ] [g.eclipse.smarthome.model.script.***] - Star 1,459 Euro

==> /var/log/openhab2/events.log <==

2018-07-04 10:36:44.925 [ome.event.ItemCommandEvent] - Item 'Wohnzimmer_TTS' received command Star 1,459 Euro

2018-07-04 10:36:44.925 [ome.event.ItemCommandEvent] - Item 'Wohnzimmer_TTS' received command Star 1,459 Euro

2018-07-04 10:36:44.925 [vent.ItemStateChangedEvent] - Star_Update changed from 2018-07-04T09:36:53.656+0200 to 2018-07-04T10:36:44.917+0200

2018-07-04 10:36:44.926 [vent.ItemStateChangedEvent] - Wohnzimmer_TTS changed from  to Star 1,459 Euro

==> /var/log/openhab2/openhab.log <==

2018-07-04 10:36:45.045 [INFO ] [g.eclipse.smarthome.model.script.***] - Star 1,459 Euro

2018-07-04 10:36:45.046 [INFO ] [g.eclipse.smarthome.model.script.***] - Star 1,459 Euro

There are again two commands to the TTS and Alexa will stutter.

Greetings,
Markus

Please post your actuel rule.

var lastgGasStations = 0.0
var lastCheapestGasStation = ""

rule "My cheapest gas station"

when 
    Item gGasStations received update
then
    val StringBuilder sb = new StringBuilder
    gGasStations.members.filter[ i | i.state == gGasStations.state].forEach[i | sb.append(", " + i.name) ]
    CheapestGasStation.postUpdate(sb.substring(2))
    logInfo("***", String::format("%s %.3f Euro", CheapestGasStation.state, (gGasStations.state as DecimalType).floatValue))
    if((lastCheapestGasStation != CheapestGasStation.state || lastgGasStations != gGasStations.state) && now.getHourOfDay() >7 && now.getHourOfDay() <21) {
        lastgGasStations = *gGasStations.state* error 1
        lastCheapestGasStation = *CheapestGasStation.state* error 2
        Wohnzimmer_TTS.sendCommand(',' + String::format("%s %.3f Euro", CheapestGasStation.state, (gGasStations.state as DecimalType).floatValue))}
end

error 1 Type mismatch: cannot convert from State to double
error 2 Type mismatch: cannot convert from State to String

Visual Studio code doesn’t show me the error before.
So after restart Vsc,copying and sending you the code i have seen it. :slight_smile:

This could ba a solution

include java.util.concurrent.locks.ReentrantLock
val ReentrantLock stompingLock = new ReentrantLock

rule ...
when
...
then
    try {
        stompingLock.lock()
...
    } catch(Throwable t) { }
    finally {
        stompingLock.unlock()
    }
end

Thanks for your rule, but i doen’t understand where i have to copy it.
And i don’t understand the code too. :slight_smile: