Voice control rules

NOTE: If you are on OH 2, as written, you need none of those imports.

I’ve not done this myself but I would try to break the problem into parts. For example, first I’d try to figure out the command:

import java.util.regex.Pattern
import java.util.regex.Matcher
import org.eclipse.smarthome.model.script.ScriptServiceUtil

val Pattern digits = Pattern.compile(".*([\d]+).*")

rule “Voice control”
when
    Item VoiceCommand received command
then

    val command = VoiceCommand.state.toString.toLowerCase
    val Matcher digitsM = digits.matcher(command)

    // get the new state from the command
    var newState= ""
    switch command {
        case command.contains("on"): newState = "ON"
        case command.contains("off"): newState = "OFF"
        case command.matches(".* to [\d]+.*") : newState = digitsM.find.get(0)
        case command.contains("open"): newState = "OPEN"
        // and so on
    }

    // get the room
    var room = ""
    switch command {
        case command.contains("kitchen"): room = "Kitchen"
        case command.contains("master bedroom"),
        case command.contains("our room"): room = "MBR"
        // and so on
    }

    // get the device
    var device = ""
    switch command {
        case command.contains("light"): device = "Light"
        case command.contains("lights"): device = "Lights"
        case command.contains("lamp"): device = "Lamp"
        case command.contains("tv"): device = "TV"
        // and so on
    }

    // With clever naming we should have everything we need to command the device
    var itemName = room+"_"+device

    // Special cases
    if(newState == "" || room == "" || device == "") {
        // List each special case that cannot be handled by the keyword searching above
        switch command {
            case command.contains("it's party time"): { itemName = "PartyTime" newState = "ON" }
            // and so on
        }
    }

    // error checking
    val itemRef = val override = ScriptServiceUtil.getItemRegistry.getItem(itemName)
    if(itemRef == null) {
        logError("Voice", "Cannot find Item " + itemName + ": " + command)
    }
    else itemRef(newState)
end

Rather than trying to match full phrases or sentences, look for keywords and name your Items so that you can build the Item name from the words in the voice command. Notice how there are two cases that result in “MBR”. This is how you can handle synonyms.

If you need to do things like control color you will probably need to create some more regular expression Patterns to search for common color names.

Like I said, I don’t do voice control so this is notional, but I think it should work and it is a bit more flexible than listing phrases separately and it is a little easier to update and follow with nested if else statements.

One case it doesn’t handle well is statements like “turn off the lamp on the coffee table” since it contains both “on” and “off” but I bet this case could be managed if it were a problem.

2 Likes