Design Pattern: Gate Keeper

Edit: @5iver solved my problem and I have corrected the code so that one can copy&paste items and code if one have a similar use case. @rlkoshak thank you for this great design pattern!

Hi @rlkoshak , this is the case with my sonos speakers, when there are multiple notifications to be played.
That’s why I try to use the complex example of your design pattern to manage playing notifications.
But there are errors in my openhab.log that I cannot solve and I couldn’t find a solution in the forum.

My items in file GateKeeperExamples.items

Group GrpMessages
Switch CreateMessage    "CreateMessage [%s]"    (GrpMessages)
String TextQueued       "TextQueued [%s]"       (GrpMessages)
String TextOutput       "TextOutput [%s]"       (GrpMessages)

My code in file GateKeeperExamples.rules

// IMPORTS **************************************************************************  
    import java.util.concurrent.ConcurrentLinkedQueue

// GLOBAL VARIABLES ************************************************************
    val MyQueue = new ConcurrentLinkedQueue()    // Edited this line. The code causing the errror was: val Queue<String> MyQueue = new ConcurrentLinkedQueue()
    var Timer timer = null
    var lastCommand = now.minusSeconds(1).millis

    var MyMessageCounter = 0

// RULES ****************************************************************************

rule "rGateKeeperExample_CreateMessage"
 when
    Item CreateMessage received command
 then
    MyMessageCounter = MyMessageCounter + 1     // MyMessageCounter see global variables section
    val MyMessage = "Message no. " + MyMessageCounter.toString + " , date = " + now.toString
    TextQueued.sendCommand( MyMessage )
    logInfo("openhab", "New Message = " + MyMessage )
end // EndOfRule rGateKeeperExample_CreateMessage

rule "rGateKeeperExample_MessageOutput"
 when
    Item TextQueued received command
 then
    val String          MyLogFile = "MySeparateLogFile"   // if 'MySeparateLogFile' does not exist, logging goes into openhab.log (to create a separate logfile see https://www.openhab.org/docs/administration/logging.html#logging-into-separate-file)
    val DateTime        MyLogDate = now  
    val StringBuilder   MyLogMessage = new StringBuilder
    MyLogMessage.append( "\n" + "\n" + " ----------   rGateKeeperExample_MessageOutput v001   ----------" + "\n" + "\n" )
    MyLogMessage.append( "    MyLogDate = " + MyLogDate.toString + "\n" + "\n" ) // ("yyyy-MM-dd'T'HH:mm:ss.SSSZ")

    MyQueue.add(receivedCommand.toString)  // https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentLinkedQueue.html#add(E)
    MyLogMessage.append( "    TextQueued = " + receivedCommand.toString + "\n" ) 

    if(timer === null) {
        timer = createTimer(now, [ |
            if(MyQueue.peek !== null) {    // https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentLinkedQueue.html#peek()
                val TmpText = MyQueue.poll     // https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentLinkedQueue.html#poll()
                TextOutput.sendCommand( TmpText.toString )
                // say(TextOutput, "voicerss:deDE", "sonos:PLAY1:SonosLiving", new PercentType(25))
                MyLogMessage.append( "       TextOutput = " + TmpText.toString + "\n" ) 
                lastCommand = now.millis
            }
            timer.reschedule(now.plusMillis(60000))  // output of next message after 60s
        ] )
    } 
    logInfo( MyLogFile, MyLogMessage.toString )
end // EndOfRule rGateKeeperExample_MessageOutput

My openhab.log

2019-03-28 20:58:18.129 [INFO ] [el.core.internal.ModelRepositoryImpl] - Refreshing model 'GateKeeperExample.rules'
2019-03-28 21:25:55.014 [INFO ] [el.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model 'GateKeeperExample.rules', using it anyway:
The field Tmp_GateKeeperExampleRules.MyQueue refers to the missing type Object
The field Tmp_GateKeeperExampleRules.MyQueue refers to the missing type Object
The field Tmp_GateKeeperExampleRules.MyQueue refers to the missing type Object
2019-03-28 21:25:55.209 [INFO ] [el.core.internal.ModelRepositoryImpl] - Refreshing model 'GateKeeperExample.rules'
2019-03-28 21:26:26.329 [INFO ] [lipse.smarthome.model.script.openhab] - New Message = Message no. 1 , date = 2019-03-28T21:26:26.320+01:00
2019-03-28 21:26:26.359 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'rGateKeeperExample_MessageOutput': 'add' is not a member of 'Object'; line 38, column 5, length 37
2019-03-28 21:26:28.888 [INFO ] [lipse.smarthome.model.script.openhab] - New Message = Message no. 2 , date = 2019-03-28T21:26:28.875+01:00
2019-03-28 21:26:28.915 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'rGateKeeperExample_MessageOutput': 'add' is not a member of 'Object'; line 38, column 5, length 37
2019-03-28 21:26:29.725 [INFO ] [lipse.smarthome.model.script.openhab] - New Message = Message no. 3 , date = 2019-03-28T21:26:29.719+01:00
2019-03-28 21:26:29.757 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'rGateKeeperExample_MessageOutput': 'add' is not a member of 'Object'; line 38, column 5, length 37

Problem
I think the info in openhab.log
The field Tmp_GateKeeperExampleRules.MyQueue refers to the missing type Object
indicates, that there is something wrong with the declaration of MyQueue in this line of my code
val Queue<String> MyQueue = new ConcurrentLinkedQueue()

Every time the rule is triggered I get this error
Rule 'rGateKeeperExample_MessageOutput': 'add' is not a member of 'Object'; line 38, column 5, length 37
which points to line 38 with this code MyQueue.add(receivedCommand.toString)

I couldn’t find a solution yet, so every help is appreciated.

My system is openhabian installed on raspberry pi:

  • Release = Raspbian GNU/Linux 9 (stretch)*
  • Kernel = Linux 4.14.79-v7+*
  • Platform = Raspberry Pi 3 Model B Rev 1.2*
  • openHAB 2.4.0-1 (Release Build)*
1 Like