I have a rule set up to play a 90’s era rap hook when someone rings the doorbell. Straight forward enough, that in and of itself is working just fine at this point. I was wondering if there is a way to have it cycle through a list of audio files, playing a different one each time the door bell is pressed. The first time it would play file db01.mp3, the next time it was pressed it would play db02.mp3, the next time db03.mp3, and so on. After it has cycled through all the files (at this point up to db08.mp3) it would start back over with the db01.mp3
Here is the rule as it stands now
rule "Door Bell"
when
Item DoorbellNotification changed from 0 to 1
then
playSound("db01.mp3")
end
I have a hunch I’m going to have to incorporate something to do with persistence but I’m not sure. At this point I have MySQL up and running, as far as I know it only logs the status history of items. So I can see when the doorbell has been pressed, but not necessarily the last audio file that was played when it was pressed.
Not quite the same, but maybe it helps:
Below a rule that plays a random voice message out of a pool of messages every time it is triggered:
import java.util.concurrent.locks.ReentrantLock
import java.util.concurrent.TimeUnit
rule "VoiceMSG"
when
Item gBedroom changed from ON to OFF
then
// logInfo("Notifications","Notifications rule got triggered")
var gotLock = lock.tryLock(1000, TimeUnit.MILLISECONDS)
try {
if (gotLock) {
var Quotes = newArrayList(
"string",
"string",
"string",
"string",
"string"
)
var i = rand.nextInt(Quotes.size);
logInfo("VoiceCMD","number of quotes available: "+Quotes.size+"; reading out quote: " + i)
var msg = Quotes.get(i)
say(msg,"voicerss:enUS", "squeezebox:squeezeboxplayer:BridgeID:PlayerMAC")
}
else logInfo("VoiceMSG", "re-entry lock activated")
}
finally {
if(gotLock){
lock.unlock()
}
}
end
Some notes:
I shortened it for readability, my original rule has more conditions (and the text is not only “string”) so apologies if I missed to delete some closing parenths
my rule is triggered by a group and such can get triggered multiple times (one time for each member), the re-entrant lock ensures that it is execute only once
for whatever reason, my system had trouble with getting a lock using the default setting of lock.tryLock; explicitly adding a time limit here, resolved that for me, this may not be necessary
arrays are indexed starting with zero, so the quote count displayed in the logs is off by one
Here’s my round-robin version. Essentially it’s the same as @lipp_markus’, key is to use an ArrayList.
It’s got nothing to do with persistence … except maybe that you need an item to store the current sound number and that you should persist that item so on reloads it’s not reset or even NULL which would lead to a (permanent) error in rule execution (that’s why I’m checking for NULL && eventually correcting this in my rule).
var String Silence = "silence-10sec.mp3"
if (es_klingelt)
exit
es_klingelt = true
val int Anzahl_Klingeltoene = 7
val Klingeltoene = newArrayList('doorbell.mp3', 'Klingelton-GranVals-Variation.mp3', 'Pferd-aufm-Flur.mp3', 'SMS_Alarm.mp3','Hells_Bells.mp3', 'laughter.mp3', 'Was_wolln_Sie_denn_hier.mp3')
if (Klingelton.state == NULL)
Klingelton.postUpdate(1)
var String s = Klingeltoene.get((Klingelton.state as Number).intValue)
var Number neuer_Klingelton = Klingelton.state
neuer_Klingelton = neuer_Klingelton + 1
if (neuer_Klingelton == Anzahl_Klingeltoene)
neuer_Klingelton = 0
Klingelton.postUpdate(neuer_Klingelton)
playSound (s)
playSound (Silence)
es_klingelt = false
My ‘lock’ is the es_klingelt variable . In another cron-triggered rule, I’m resetting es_klingelt to false every minute to ensure just a single sound is being played per minute.
If you don’t lock, with longish sound files and every postman pressing two or three times per default you could have overlapping sounds or sounds queueing up.
And just to provide another approach which takes advantage of the fact that you have a consistent naming scheme for the mp3 files (note, the rule assumes you are starting from 0, not 1):
var currDBNum = -1
val numSounds = 8
rule "Door Bell"
when
Item DoorbellNotification changed from 0 to 1
then
currDBNum = (currDBNum + 1) % numSounds
val sound = String.format("db%02d.mp3", currDBNum)
playSound(sound)
end