[SOLVED] Kodi, RPI3-B+, TASMOTA S26 Switch and Rules

  • GOAL:

    • When I click on ‘T4E’ button in openHAB2 Sitemap the rule should check if ‘Kodi001_Status’ is ON and when ON change ‘Kodi001_Favorieten’ to ‘TECHNO4EVER.FM’ directly. When Kodi001_Status’ is OFF it should then turn ‘Stopcontact001_Knop’ ON and when ‘Kodi001_Status’ is ON it then should set ‘Kodi001_Favorieten’ to ‘TECHNO4EVER.FM’.
  • In human language:

  • When I click on a radiostation button, I want kodi to turn on and put on that radio station. If Kodi is already on it should also turn to that radio station. Kodi runs on an RaspberryPi3B+, with a Sonoff tasmota S26 switch to turn the PI off when unused.

I have multiple buttons (T4E/QMUSIC/…)all mapped to a casenumber in the rules.

My current rule/setup does work sort of, but it runs both options in the rules. So it start the favorite and then runs the timeout rule and starts the favorite(again). But thats not what I want. If you change before the timer runs out it will change it again.

What It needs to do is only run the timer if Kodi is offline. And put on favorite if Kodi is onlline.

Here are my files:

THINGS:

Thing kodi:kodi:kodi001                             "Kodi001"           @ "Woonkamer" [ipAddress="192.168.1.250", httpPort="2003", Username="mediaspeler", Password="1983gizmo"]
Thing network:pingdevice:status_rpi001              "Status RPI001"     @ "Woonkamer" [hostname="192.168.1.250",            retry=5, timeout=3000, refreshInterval=1000]
Thing network:servicedevice:status_kodi001          "Status Kodi001"    @ "Woonkamer" [hostname="192.168.1.250", port=2003, retry=5, timeout=3000, refreshInterval=1000]

ITEMS:

Number  Kodi001_Opties               "Kodi Opties"

String  Kodi001_Titel                "Titel [%s]"                    {channel="kodi:kodi:kodi001:title"}
Switch  Kodi001_Dempen               "Dempen"                        {channel="kodi:kodi:kodi001:mute"}
Dimmer  Kodi001_Volume               "Volume [%d]"                   {channel="kodi:kodi:kodi001:volume"}
Player  Kodi001_Besturing            "Besturing"                     {channel="kodi:kodi:kodi001:control"}
Switch  Kodi001_Stop                 "Stoppen"                       {channel="kodi:kodi:kodi001:stop"}
String  Kodi001_Favorieten           "Start Favoriet [%s]"           {channel="kodi:kodi:kodi001:playfavorite"}
String  Kodi001_Systeem_Commando     "Systeem Commando"              {channel="kodi:kodi:kodi001:systemcommand"}

Switch  Kodi001_Schakel              "Kodi aan/uit zetten"
Switch  Kodi001_Status               "Kodi001 Status"                {channel="network:servicedevice:status_kodi001:online"}
Switch  RPI001_Status                "RPI001 Status"                 {channel="network:pingdevice:status_rpi001:online"}

SITEMAP:

    Text    item=Kodi001_Titel		        label="Titel"			        icon="keyring"
    Switch  item=Kodi001_Opties                 label="Kodi:"                           icon="receiver"         mappings=[0='Uit', 1='AAN', 2='T4E', 3='FunX', 4='Joy', 5='Qmusic']
    Switch  item=Kodi001_Besturing              label="Besturing"                       icon="control"          mappings=[PREVIOUS='Vorige', PLAY='Afspelen', PAUSE='Pause', NEXT='Volgende']
    Slider  item=Kodi001_Volume 	        label="Volume"	                        icon="soundvolume"

RULES:

// kodies.rules

var Timer delayTimer = null
val int timeoutMinutes = 1



rule "Kodi 001 Uit timer"
when
    Item RPI001_Status changed 
then
    if(RPI001_Status.state == OFF)
    Stopcontact001_Knop.sendCommand(OFF)
end

rule "Kodi 001 Keuzes"
when
    Item Kodi001_Opties changed
then
    switch (Kodi001_Opties.state) {
        case 0 :{
            // UIT
            Kodi001_Systeem_Commando.sendCommand('Shutdown')
        }// CASE EINDE
        case 1 :{
            // AAN
            Stopcontact001_Knop.sendCommand(ON)           
        }//CASE EINDE
        case 2 :{
            // T4E
            if(RPI001_Status.state == ON)
            Kodi001_Favorieten.sendCommand('TECHNO4EVER.FM')
            if(RPI001_Status.state == OFF) 
            Stopcontact001_Knop.sendCommand(ON) {
            delayTimer = createTimer(now.plusSeconds(60), [|
            Kodi001_Favorieten.sendCommand('TECHNO4EVER.FM')
            delayTimer = null 
            ])
            } // REGEL EINDE
        } // CASE EINDE                       
 
 
        case 3 :{
            // FunX
            if(RPI001_Status.state == ON)
            Kodi001_Favorieten.sendCommand('FunX') 
            if(RPI001_Status.state == OFF) 
            Stopcontact001_Knop.sendCommand(ON) {
            delayTimer = createTimer(now.plusSeconds(60), [|
            Kodi001_Favorieten.sendCommand('FunX')
            delayTimer = null 
            ])
            }// REGEL EINDE
        }// CASE EINDE                       
        case 4 :{
            // Joy Radio
            if(RPI001_Status.state == ON)
            Kodi001_Favorieten.sendCommand('Joy Radio NL') 
            if(RPI001_Status.state == OFF)
            Stopcontact001_Knop.sendCommand(ON) {
            delayTimer = createTimer(now.plusSeconds(60), [|
            Kodi001_Favorieten.sendCommand('Joy Radio NL')
            delayTimer = null 
            ])
            }// REGEL EINDE
        }// CASE EINDE                       
        case 5 :{
            // QMusic Foute Uur
            if(RPI001_Status.state == ON)
            Kodi001_Favorieten.sendCommand('QMusic Foute Uur') 
            if(RPI001_Status.state == OFF)
            Stopcontact001_Knop.sendCommand(ON) {
            delayTimer = createTimer(now.plusSeconds(60), [|
            Kodi001_Favorieten.sendCommand('QMusic Foute Uur')
            delayTimer = null 
            ])
            }// REGEL EINDE
        }// CASE EINDE
    }// SWITCH EINDE
end

I’m from Holland, so a lot of stuff in there is in the Dutch language. If for clarity sake you want it translated into English, then let me know.

Any help would be great. Thank you.

I have even tried the following in rules:

        case 2 :{
            // T4E
            if(RPI001_Status.state == ON)
            Kodi001_Favorieten.sendCommand('TECHNO4EVER.FM') else Stopcontact001_Knop.sendCommand(ON) {
            delayTimer = createTimer(now.plusSeconds(60), [|
            Kodi001_Favorieten.sendCommand('TECHNO4EVER.FM')
            delayTimer = null 
            ])
            } // REGEL EINDE
        } // CASE EINDE 

But it basically gives the same outcome (it executes the first command and the second with the timer in it)

Wrong place of brackets?

// kodies.rules

var Timer delayTimer = null
val int timeoutMinutes = 1



rule "Kodi 001 Uit timer"
when
    Item RPI001_Status changed 
then
    if(RPI001_Status.state == OFF)
    Stopcontact001_Knop.sendCommand(OFF)
end

rule "Kodi 001 Keuzes"
when
    Item Kodi001_Opties changed
then
    switch (Kodi001_Opties.state) {
        case 0 :{
            // UIT
            Kodi001_Systeem_Commando.sendCommand('Shutdown')
        }// CASE EINDE
        case 1 :{
            // AAN
            Stopcontact001_Knop.sendCommand(ON)           
        }//CASE EINDE
        case 2 :{
            // T4E
            if(RPI001_Status.state == ON)
                Kodi001_Favorieten.sendCommand('TECHNO4EVER.FM')
            if(RPI001_Status.state == OFF) {  // <- curly bracket here 
                Stopcontact001_Knop.sendCommand(ON)  // { not here
                delayTimer = createTimer(now.plusSeconds(60), [|
                    Kodi001_Favorieten.sendCommand('TECHNO4EVER.FM')
                    delayTimer = null
                ])
            } // REGEL EINDE
        } // CASE EINDE                       
        case 3 :{
            // FunX
            if(RPI001_Status.state == ON)
                Kodi001_Favorieten.sendCommand('FunX') 
            if(RPI001_Status.state == OFF)  {  // <- curly bracket here 
                Stopcontact001_Knop.sendCommand(ON) // { not here
                delayTimer = createTimer(now.plusSeconds(60), [|
                    Kodi001_Favorieten.sendCommand('FunX')
                    delayTimer = null
                ])
            }// REGEL EINDE
        }// CASE EINDE                       
        case 4 :{
            // Joy Radio
            if(RPI001_Status.state == ON)
                Kodi001_Favorieten.sendCommand('Joy Radio NL') 
            if(RPI001_Status.state == OFF) {  // <- curly bracket here 
                Stopcontact001_Knop.sendCommand(ON) // { not here
                delayTimer = createTimer(now.plusSeconds(60), [|
                    Kodi001_Favorieten.sendCommand('Joy Radio NL')
                    delayTimer = null
                ])
            }// REGEL EINDE
        }// CASE EINDE                       
        case 5 :{
            // QMusic Foute Uur
            if(RPI001_Status.state == ON)
                Kodi001_Favorieten.sendCommand('QMusic Foute Uur') 
            if(RPI001_Status.state == OFF) {  // <- curly bracket here 
                Stopcontact001_Knop.sendCommand(ON) // { not here
                delayTimer = createTimer(now.plusSeconds(60), [|
                    Kodi001_Favorieten.sendCommand('QMusic Foute Uur')
                    delayTimer = null
                ])
            }// REGEL EINDE
        }// CASE EINDE
    }// SWITCH EINDE
end

And there is a less complex way for the second rule :slight_smile:

// define global vars at the beginning of the rules file!
var String sChannel
var Timer delayTimer = null

rule "Kodi 001 Keuzes"
when
    Item Kodi001_Opties changed
then
    switch (Kodi001_Opties.state) {
        case 0 : {                                           // UIT
            Kodi001_Systeem_Commando.sendCommand('Shutdown')
            return;
        }
        case 1 : {                                           // AAN
            Stopcontact001_Knop.sendCommand(ON)           
            return;
        }
        case 2 : sChannel = "TECHNO4EVER.FM"                 // T4E
        case 3 : sChannel = "FunX"                           // FunX
        case 4 : sChannel = "Joy Radio NL"                   // Joy Radio
        case 5 : sChannel = "QMusic Foute Uur"               // QMusic Foute Uur
        default : return;
    }
    var Number nWait = 50
    if(RPI001_Status.state != ON) {
        Stopcontact001_Knop.sendCommand(ON)
        nWait = 60000
    }
    if (delayTimer === null) 
        delayTimer = createTimer(now.plusMillis(nWait), [ |
            Kodi001_Favorieten.sendCommand(sChannel)
            delayTimer = null
        ])
end

So instead of doing all things twice :wink:
In question of the Timer: Using plusMillis() allows to do the sendCommand() “almost” at once if Kodi is already switched ON.
Another thing is, if Kodi was OFF, then by sending channel selection more than once, there will be chaos :wink: but this is catched by if (delayTimer === null)
So, when selecting another channel while Kodi is starting because of a first channel selection, openHAB will simply chose the other channel when the timer expires.

Why, thank you very much! This cleans up a lot! WoW!:open_mouth:

And the brackets :man_facepalming: My mistake. Thank you for clearing it up. I´ll put in the code and see if all is working correctly. Again: Thank you! Also for the extra work and cleanup of the code! :clap: :smile: :wink:

When I put in your code, openHAB spit out that it contained errors. But I was able to solve them. Case 2 trough 5 and default:return; needed brackets. The code was then accepted and is working. I’m now going to try and wrap my head around it. There are a few things that I do not yet get. But I will get there… Again: THANK YOU VERY MUCH!

Below the code that works for me:

        case 2 : { sChannel = "TECHNO4EVER.FM" }                // T4E
        case 3 : { sChannel = "FunX" }                           // FunX
        case 4 : { sChannel = "Joy Radio NL" }                  // Joy Radio
        case 5 : { sChannel = "QMusic Foute Uur" }               // QMusic Foute Uur
        default : { return; }