Broadlink binding for RMx, A1, SPx and MP. Any interest?

I agree, I placed the jar in the folder, I configured everything but I’m stuck since I have no idea of how to set the signal codes, and use a button to send the signal :frowning:

All the information is there, did you do step 7?

Step 7 : For RMx devices only. Create an item in your items file and add it to your sitemap.

item file:
String TV_LIVINGROOM “TV” { channel=“broadlink:rm2:b4-43-0d-38-fa-9d:command” }

sitemap file:
Switch item=TV_LIVINGROOM label=“Power” mappings=[TV_POWER_ON=“On”, TV_POWER_OFF=“Off”]

Thank you for this summary @X-Ray181 , I was spending lot of time going through all posts and was not clear how to make it work.
Now it works like a charm (I have 2 RM3 mini and add AC’s, TV’s , set top boxes and fans).

Dear @Cato_Sognen,
Is it possible to update 1st post with info from X-ray181 post 813 to allow new users go directly for installation/configuration?

1 Like

Hello Karel,
You’re welcome, Cato is not with us anymore, so he won’t answer, but whats keeping you from making a new and improved version of the installation/configuration? you now know how to make it work and where you struggled…

1 Like

edit : I’m sorry for Off Topic

sounds as good idea to create additional how to (i’ll try to summary it during weekend) even i would say your post is enough to guide anybody and I really appreciate your help. But my point was more that it is not easy to find correct info in several hundreds of posts.
There is no function to make some of the posts “sticky” on top of thread?

No Problem! I understand the problem :crazy_face: All the information is here, but its not easy to find, I agree totaly.
I think this info should be on the document site off OH, with all the other binding “How To’s’” documentation, I think it should be here: https://www.openhab.org/addons/ ?
I have no idea how to get it there, but somebody will tell us soon!:laughing:, I will help and I hope John will to @themillhousegroup
I think it’s time to make it official, the binding is stable and working reliable for many off us, so now its time to document it for the next generation! :vulcan_salute:
Ray

2 Likes

hi @themillhousegroup,

thanks for fixing this binding, Broadlink SP2 going online and offline, check below

from events.log:
21:13:03.074 [INFO ] [ome.event.ThingStatusInfoChangedEvent] - ‘broadlink:sp2:34-ea-34-b6-9e-8c’ changed from ONLINE to OFFLINE (COMMUNICATION_ERROR): Could not find device at IP address 192.168.1.14

21:13:33.184 [INFO ] [ome.event.ThingStatusInfoChangedEvent] - ‘broadlink:sp2:34-ea-34-b6-9e-8c’ changed from OFFLINE (COMMUNICATION_ERROR): Could not find device at IP address 192.168.1.14 to ONLINE

from openhab.log:
2019-07-22 21:13:03.036 [ERROR] [handler.BroadlinkSocketModel2Handler] - sp2:34-ea-34-b6-9e-8c[^]: Exception while getting status from device
java.net.ProtocolException: Incoming packet from device is null.
at org.openhab.binding.broadlink.internal.BroadlinkProtocol.decodePacket(BroadlinkProtocol.java:193) ~[199:org.openhab.binding.broadlink:2.4.0.201906030227]
at org.openhab.binding.broadlink.handler.BroadlinkSocketModel2Handler.getStatusFromDevice(BroadlinkSocketModel2Handler.java:47) [199:org.openhab.binding.broadlink:2.4.0.201906030227]
at org.openhab.binding.broadlink.handler.BroadlinkBaseThingHandler.updateItemStatus(BroadlinkBaseThingHandler.java:204) [199:org.openhab.binding.broadlink:2.4.0.201906030227]
at org.openhab.binding.broadlink.handler.BroadlinkBaseThingHandler$1.run(BroadlinkBaseThingHandler.java:77) [199:org.openhab.binding.broadlink:2.4.0.201906030227]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:?]
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) [?:?]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) [?:?]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) [?:?]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:?]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:?]
at java.lang.Thread.run(Thread.java:745) [?:?]
2019-07-22 21:13:03.048 [ERROR] [handler.BroadlinkSocketModel2Handler] - sp2:34-ea-34-b6-9e-8c[^]: Problem getting status. Marking as offline …
2019-07-22 21:13:03.049 [ERROR] [handler.BroadlinkSocketModel2Handler] - sp2:34-ea-34-b6-9e-8c[^]: updateItemStatus: Online -> Offline

thanks

@Mohammad_Chaaban Try with the parameters below

StaticIp
IgnoreFailedUpdateds
Retries 1

Thing broadlink:sp2:34-ea-34-f5-ae-aa "txtBroadlink SP2 [192.168.1.105] SP2_3" [ ipAddress="192.168.1.105", port=80, staticIp=true, mac="34:ea:34:f5:ae:aa", authorizationKey="097628343fe99e23765c1513accf8b02", iv="562e17996d093d28ddb3ba695a2e6f58", pollingInterval=400, retries=1, ignoreFailedUpdates=true]

Hi,
I would like to control my TV using a Broadlink IR mini and Google Home Assistant.
To achieve this I configured IFTTT to react to a Change Channel command and to Update an Openhab Item with channel number, in example 401.

I created a map file for ir with all 10 digit, called IR_SKY_0 to IR_SKY_9
In a rule i scompose channel number 401 to 4 single digits 4, 0 and 1

The stem I miss is how to send this 3 command to broadling from a rule, instead using button from a sitemap, using the same map file. Someone can help me?

Thanks

i quite enjoy the question because it’s on the very to the limit of my knowlede and i enjoy challenges.

disclaimer:
in principle i know it works.
in practice, i’ve seen a lambda working this way in the OH scheduler widget for habpanel, but have never written one myself YET, and the inner workings of reentrant lock are still vague to me

I’d try this way:

  1. create a Digits_Group containing the items with single digits (first_digit, second_digit, third_digit, fourth_digit)

  2. write a rule that fires when any of your regex-ed single digits is updated with a non null value (maybe it’s enough reacting on the first one as it’s always going to be there)
    This rule would need a “Digits_Group.members.forEach” lambda expression, and within the lambda, if the digit item is not null, you compose the name of the command to send as a String command="IR_SKY_"+digit , where var digit = triggeringItem.state or similar.
    Send the command.
    You will need a brief Thread::sleep to give the Broadlink device the necessary time to send the IR command AND you might need to use concurrency guard via reentrand lock.

  3. use expire binding or something similar to reset the digit items to null after use

There! i might try in the next few weeks to write something alike for the sheer fun of the challenge XD

PS.: it just dawned on me that with reentrant lock+ expire binding would be possible to write a buffer for the commands sent to the broadlink device. another challenge XD

PS2: @marcolino7 , if you make it, please post it, i’m really interested

HI,
this is how I would like to procede. Issue is that the channel is into a string, like 401 or 5001
My issue at this time is to iterate the string and extract single digit.

Hi Dario,
for sure.

Marco

thanks… ill try it and report back…

Hi @lagging
there is 1st version of my rule. I did not tested yet with real IR codes but looking at the logs it works:

rule "Imposta Canale Sky"
when
	Item SALOTTO_IR_IFTTT received command
then
    val sState = SALOTTO_IR_IFTTT.state.toString
	logInfo("IR.SKY.Channel","Ricevuto Canale Sky "+sState)
    
    var len = sState.length
    logInfo("IR.SKY.Channel","Lunghezza Canale Sky "+len.toString)

    var String digit = ""
    var int charIndex = 0
    while(charIndex < sState.length){
        digit = sState.toString.substring(charIndex,charIndex+1)
        logInfo("IR.SKY.Channel","index Ciclo / Digit da Inviare :"+charIndex.toString+" / "+digit)
        SALOTTO_IR.sendCommand("IR_SKY_"+digit)
        Thread::sleep(500)
        charIndex = charIndex+1
    }

end

Basically IFTTT update item SALOTTO_IR_IFTTT with the string containing the channel (IE 401 or 5001), then rule iterate throught digit of received string and Update the Broadlink Item (SALOTTO_IR) with the map name IR_SKY_ and the digit. A sleep should give time to broadlink to receive command and sent to my TV set top Box.

This Night I will test.

Marco

1 Like

The Broadlink RM2 was working for months… then I had to reset it and re-add it to openhab.
Now I’m getting

OFFLINE - CONFIGURATION_ERROR

I added the IV and Authentication key…
anything changed recently?

Thanks

:slightly_smiling_face: this just proves how many different ways there are to achieve a goal. I had not thought about using lenght + substring that way. I’d have gone with regex digit by digit until null :slightly_smiling_face:
Yours is way leaner.

Inspired by @marcolino7’s question (and solution), I I have fashioned together a BUFFER for the outgoing commands, to be sent via a a RM device to the other RF433 controlled devices, either coming from different sources in short bursts or at the same time from a single source.

My situation is that I have different devices in separate rooms controlled via a single rf433 Broadlink RM3(still in range), so the chance of more than one command arriving as input to OH and needing to be sent almost simultaneously by the RM3 is quite real.

@marcolino7 ’s situation is that he receives 1,2,3 or 4 digits as a string from IFTTT (from a hook from a Google voice command), and those need to be chained into 1,2,3 or 4 IRcommands.

In short, I thought- both situations could be solved creating a “buffering into a pipeline of commands” mechanism, like a queue at the butcher’s of sorts.

Starting from imports, you will need
import java.util.HashMap
import java.lang.String
and the following global variables:
var Timer rf433Timer = null
var String rfqueue=''
var String rfqueueB=''

At this point you also need to have created (as per the guides for this binding) a broadlink.map file with your rf commands in hex code format, matching them to command names(command_name = hex code).

Take note of the ms needed for each command to work properly, as that is the length of the timeout for that command, then place them in a HashMap within your rules file as global val(L not R). Mine spread between 800ms(-ish) for ON/OFFs and 4800ms for a 50% dimmer increase/decrease, so this is my hashmap:

val HashMap<String,Integer>timeoutMap = newHashMap(
'Dario_Luce_Toggle' -> 750, 'Dario_Led_On' ->850, 'Dario_Led_Off'->850, 'Dario_Dimmer'->4800, 'Dario_MemDim'->850, 'Dario_Vent_Off'->800, 'Dario_Vent_1'->850, 'Dario_Vent_2'->850, 'Dario_Vent_3'->850,
'Camera_Luce_Toggle' -> 750, 'Camera_Led_On' ->850, 'Camera_Led_Off'->850, 'Camera_Dimmer'->4800, 'Camera_MemDim'->850, 'Camera_Vent_Off'->800, 'Camera_Vent_1'->850, 'Camera_Vent_2'->850, 'Camera_Vent_3'->850,
'Sogg_Luce_Toggle' -> 750, 'Sogg_Led_On' ->850, 'Sogg_Led_Off'->850, 'Sogg_Dimmer'->4800, 'Sogg_MemDim'->850, 'Sogg_Vent_Off'->800, 'Sogg_Vent_1'->850, 'Sogg_Vent_2'->850, 'Sogg_Vent_3'->850)

Create your own dummies representing statuses of your own RF433 or IR commanded items. You may want to expose those dummies vie openhabcloud and tag them to receive voice commands.

Add the followinng to your items:

String RM3_in <text>
String RM3_Queue <text>
String RM3_out <text> {channel="broadlink:rm3:_____xyz______:command"}
Switch RM3_Busy_lock <switch>

Then write a set of rules, that aside from representing the correct logic statuses of your devices on your sitemap, all send their commands to a first collector dummy item, that I called RM_in.
The commands sent are the names of the commands you have defined in the broadlink.map.

An example from my rules:

 rule"fan ON while powered on"
     when 
      Item Vent_Dario received command ON or Item Vent_Dario received command OFF
      then
      if (receivedCommand==ON){
        PotVent_Dario.postUpdate(1)
        sendCommand(RM3_in,"Dario_Vent_1")}
      if (receivedCommand==OFF){
        PotVent_Dario.postUpdate(0)
        RM3_in.sendCommand("Dario_Vent_Off")
      }
 end

RM3_in feeds into the FIRST “digestion” RULE for the buffer/queue.
The buffer is represented in this rule by the 2 global variables (rfqueue for the first command it receives, and it stores the following ones in the global variable rfqueueB), and at the first entry in the queue, feeds also into the item RM3_Queue, which triggers the follow-up second rule.

rule "Feeding the RF433 queue"
when Item RM3_in received command
then
if(rfqueue==''){
    rfqueue=receivedCommand.toString
    RM3_Queue.postUpdate(rfqueue)
    logInfo("FEEDING RFQUEUE","addedto it: "+rfqueue)
 }
 else {
  if (rfqueueB==''){
    rfqueueB=receivedCommand.toString
  }
  if (rfqueueB!=''){
     rfqueueB=rfqueueB+"-"+receivedCommand.toString  
  }
  logInfo("FEEDING RFQUEUE-BUSY!","rfqueueB waiting to be added"+rfqueueB)
 }
RM3_in.postUpdate('-')
end

IN THE SECOND “output” RULE
-The rule checks if the rfqueue and rfqueueB are empty and if rfqueueB isn’t, it chains it after the old rfqueue (and empties it)
-takes the oldest command received and sends it to RM3_Out (the item linked to the channel of the binding in your items file- finally!)
-matches it to the duration of the command in the hashmap and creates a timer forcing the queue to wait for their turn.
-saves the remaining part of the que into the variable rfqueue and into the item RM3_Queue, effectively triggering (the rule) itself to restart, until the queue is empty.

rule "Emptying the RF433 queue- transmitting commands"
when Item RM3_Queue changed
then
 logInfo("RFQUEUE","LOCK?")
  if(RM3_Busy_lock==OFF){
  return;      
  }
  else{
    if(rfqueueB!=''){
      postUpdate(RM3_Busy_lock,OFF)
      logInfo("RFQUEUE","PASSED, locked")
      logInfo("RFQUEUE","rfqueueB to be added! "+rfqueueB)
       if (rfqueue!=''){
         logInfo("RFQUEUE","rfqueueB:the rfqueue was NOT empty")
         rfqueue=rfqueue+"-"+rfqueueB
         rfqueueB=''
       }
       if (rfqueue==''){
         logInfo("RFQUEUE","rfqueueB:the rfqueue was empty")
         rfqueue=rfqueueB
         rfqueueB=''
       }
    } 
    if(rfqueue!=''){
      postUpdate(RM3_Busy_lock,OFF)
      logInfo("RFQUEUE","que not empty, PASSED, locked")
      var String remainingQueue=''
      var String currentCommand=''
        if(!rfqueue.contains("-")){
            currentCommand=rfqueue
            logInfo("RFQUEUE","Que with single command: "+rfqueue)
            remainingQueue=''
         }
        if(rfqueue.contains("-")){
            currentCommand=rfqueue.split('-').get(0)
            logInfo("RFQUEUE","que with minuses,current command: "+currentCommand)
             var int stripIndex = (currentCommand.length()+1)
            remainingQueue=rfqueue.substring(stripIndex)
            logInfo("RFQUEUE","que with minuses,remainingQue: "+remainingQueue)
         }
     if(rf433Timer===null){
         var timeout=timeoutMap.get(currentCommand)
         var notifyme="received "+currentCommand+" so will wait for "+timeout+"ms "
         logInfo("EXTRACTION FROM HASHMAP","REPORT:"+notifyme)
         RM3_out.sendCommand(currentCommand)
         logInfo("RFQUEUE","The remaining Queue that arrives "+remainingQueue)
         rf433Timer= createTimer(now.plusMillis(timeout),[|
             rfqueue=remainingQueue
             RM3_out.postUpdate('')
             logInfo("RFQUEUE","UNLOCKED")
             postUpdate(RM3_Busy_lock,ON)
             rf433Timer=null
             RM3_Queue.postUpdate(rfqueue)
          ])
        }
    } 
  }
end

NOTE1:
In testing the flow of rules within simple UI (and using way longer command durations to be able to follow what happens), I’ve noticed some double commands as a response to a single click… If you experience anything similar, that behaviour of course is unavoidable and mirrored in the Queue….

NOTE2:
Somehow, logically, in the second rule, last block, I’d have liked for the line rfqueue=remainingQueue to be positioned right before the Timer lambda (VSC complains about it as well), but then, while testing it, someweird behaviours appeared when feeding new commands to rfqueueB while rfqueue wasn’t empty. I haven’t found any better solution than having the mentioned line inside the lambda (…empirically it works…)

NOTE3:
As I haven’t been able to make reentrant lock and timers play nice with each other (timers slip into another thread and the re-entrant lock in the original thread unlocks too soon), I chose to prioritize the use of Timer vs Thread::sleep over the use of re-entrant lock.

On the way I tried to simulate a comparable behaviour was with a dummy item called RM3_Busy_lock, however in the end it is almost useless, as feeding RM3_Queue EXCLUSIVELY the first time from the input rule, and the remaining times at the end of the output rule to cycle back, while passing the meaningful data through global variables, is effectively already achieving the desired effect…

However RM3_Busy_lock comes with a perk:
it can be used to colour any rf433 Item in your sitemap, so you get a graphical representation of the actual “busy - sending” situation , with labelcolor=[RM3_Busy_lock==OFF="red", RM3_Busy_lock==ON="green"] valuecolor=[RM3_Busy_lock==OFF="red", RM3_Busy_lock==ON="green"] .

NOTE4:
I’ve noticed that using global variables instead of items to pass stringed Queue values from a rule to another has resulted in more reliable execution, yet, because the last rule in the pipeline needs to be triggered by something, the item RM3_Queue comes into play (following the variable rfqueue really)

CONCLUSION:
I’m hoping this way we’ll all get a nice stream of commands no matter how many you throw at the RM_, and all will be transmitted correctly in due time and orderly fashion.

Using this mechanism there is no need to put a Thread::sleep in each and every rule involving an rf433/IR command, and the risk of having 2 rules firing almost simultaneously blocking 2 threads and loosing at least one of the commands in the process is avoided all together.

My first tests seem positive, if you’re happy with it, you can obviously remove all the logInfo s as I’ve placed them for my own troubleshooting purposes.

PLEASE UNDERSTAND. that I have been learning to program following rulesDSL and @rlkoshak’s design patterns for about 6 months,I’m no expert, my solution can be improved and built upon, shortened and solidified, by knowledgeable peeps on this forum, it’s possibly the first decently complex thing I’ve written.

I thought for instance of feeding the queue into a list type variable and than a for.each type lambda with a timer… or maybe a re-entrant queue …but I got lost in the caveats of the stuff I don’t know nor understand and decided to work with what I kinda grasped so far.
Feel free to improve on this, share and explain why&how, I, for one, am eager to learn…

PS
If you wanna play with it, for testing purposes,I used a sitemap like this:

Frame label="input"{
   Switch item=RfTest label="Comandi" mappings=['Dario_Luce_Toggle'=Luce, 'Dario_Led_On'=Led_On, 'Dario_Led_Off'=Led_Off, 'Dario_Dimmer'=Dimmer, 'Dario_MemDim'=MemDim, 'Dario_Vent_Off'=Vent_Off, 'Dario_Vent_1'=Vent_1, 'Dario_Vent_2'=Vent_2, 'Dario_Vent_3'=Vent_3]
}
Frame label="gestione Broadlink RM3"{
    Text item=RM3_in label="Rm3 IN [%s]" icon="text"
    Text label="" icon=""
    Text item=RM3_Queue label="Rm3 Queue[%s]" labelcolor=[RM3_Busy_lock==OFF="red", RM3_Busy_lock==ON="green"] icon="text"
    Text item=RM3_Busy_lock label="RM3_Busy? [MAP(available.map):%s]" labelcolor=[RM3_Busy_lock==OFF="red", RM3_Busy_lock==ON="green"] valuecolor=[RM3_Busy_lock==OFF="red", RM3_Busy_lock==ON="green"]icon="switch"
    Text item=RM3_out label="Rm3 OUT [%s]" icon="text"
}

ofc adding to your items also
String RfTest <switch>

and available.map in the transform folder

ON=Available
OFF=BUSY
-=-
undefined=-
uninitialized=-
NULL=-

Hope you’ll Njoy it!

Have you seen the Design Pattern: Gate Keeper post? In particular the version using Thread safe queues?

I think it is a way simpler approach and more importantly a safer approach. Depending on timing, trying to maintain the queue in a String is going to get double entries or miss entries entirely. And using reentrant locks can be really dangerous.

I posted my previous post on friday , at the time i had already read through the gatekeeper DP but did not understand it properly until saturday (most likely because of the pains i went through to write this solution of mine, as i said i’m learning).

Regarding safety of data through strings: with the double global vars rfqueue and rfqueueB my buffer is doing pretty well, even if the que gets fed new values while the timer lambda is running. At this time i’m not sure what will happen with the reentrant.queue in that condition, but that is besides the point:
simplicity makes for better code - I’ll do some reading, give it a try and see!

Any further concearn or issue i might face, i’ll post in that thread before reposting an improved version here.

Following @rlkoshak’s advice (Thank you!) i reworked the Buffer :slight_smile:

Now it’s way more compact

  • instead of using 2 global variables (rfqueue+rfqueueB) it uses only one
  • instead of being split in 2 rules it’s all in a single one
  • there is no use anymore for the item Rm3_Queue, all remaining items and (also in the sitemap) stay as they were
  • I have kept the hashMap use i for varying the lenght of the looping timer.
  • i have kept RM3_Busy_lock purely to paint in red the items while sending a command and in green when available (in the sitemaps), you can remove it if you wish.
  • there are a few postUpdate(Item_Name,'') -those in my mind are pure “tidying up”, but aren’t strictly necessary and can be removed
  • again all logInfo -'s are there for debugging purposes and follow my own need for clarity. they can all be removed or changed according to your own wishes.

For simplicity’s sake, i’m pasting here my whole rules relevant section, including imports:

import java.util.HashMap
import java.util.concurrent.ConcurrentLinkedQueue

var ConcurrentLinkedQueue<String> rfqueue = new ConcurrentLinkedQueue()
var Timer rf433Timer = null

val HashMap<String,Integer>timeoutMap = newHashMap(
'Dario_Luce_Toggle' -> 750, 'Dario_Led_On' ->850, 'Dario_Led_Off'->850, 'Dario_Dimmer'->4800, 'Dario_MemDim'->850, 'Dario_Vent_Off'->800, 'Dario_Vent_1'->850, 'Dario_Vent_2'->850, 'Dario_Vent_3'->850,
'Camera_Luce_Toggle' -> 750, 'Camera_Led_On' ->850, 'Camera_Led_Off'->850, 'Camera_Dimmer'->4800, 'Camera_MemDim'->850, 'Camera_Vent_Off'->800, 'Camera_Vent_1'->850, 'Camera_Vent_2'->850, 'Camera_Vent_3'->850,
'Sogg_Luce_Toggle' -> 750, 'Sogg_Led_On' ->850, 'Sogg_Led_Off'->850, 'Sogg_Dimmer'->4800, 'Sogg_MemDim'->850, 'Sogg_Vent_Off'->800, 'Sogg_Vent_1'->850, 'Sogg_Vent_2'->850, 'Sogg_Vent_3'->850)

rule "RF433 buffering in a single rule"
when Item RM3_in received command
then
    var String lastCommand=receivedCommand.toString
    rfqueue.add(lastCommand)
    postUpdate(RM3_in,'')
    var String currentQue=rfqueue.toString
    var String notifyMe1=lastCommand+" so the queue now is "+currentQue
    logInfo("RF433 Buffer","outside the loop: added "+notifyMe1)
    if(rf433Timer !== null){
      logInfo("RF433 Buffer","outside the loop: not interferring with the running Timer")
      }
    else{
        rf433Timer = createTimer(now, [ |
        logInfo("RF433 Buffer","iterating the output loop")
        postUpdate(RM3_Busy_lock,ON)
        postUpdate(RM3_out,'')
        var currentCommand = rfqueue.peek
        if(currentCommand === null) {
           rf433Timer = null
           logInfo("RF433 Buffer","inside the loop- LAST RUN")
          }
        else {
           postUpdate(RM3_Busy_lock,OFF)
           RM3_out.sendCommand(rfqueue.poll) 
           var timeout=timeoutMap.get(currentCommand)
           var notifyMe2="sent "+currentCommand+" so will wait for "+timeout+"ms "
           logInfo("RF433 Buffer","inside the loop: "+notifyMe2)
           var exitingQue=rfqueue.toString
           logInfo("RF433 Buffer","inside the loop: the remaining Queue is "+exitingQue)
           rf433Timer.reschedule(now.plusMillis(timeout))
          }
        ])
     }
end

The following portion is relevant if you want to test it with the RfTest item i mentioned at the end of my previous post, to quickly throw at the buffer as many commands as possible.

rule "extraction from hashmap"
when Item RfTest changed
then
if(RfTest.state instanceof StringType) {
var myKey=RfTest.state.toString
sendCommand(RM3_in,myKey)
}
end

Hope it works for everyone, any constructive feedback is welcome :slight_smile:

1 Like