Door lock reporting with mios binding (in groovy)

This is my first draft of the script. Still rudimentary, but it tell you witch user have LOCK/UNLOCK the door.

First, you need to have install the mios binding, and configure it.

You also need an item like this one:
(8 is the device id for mios, not zwave. it is very confusing to find the right number in mios)

Switch   MainDoorLock "Main door lock [MAP(lock.map):%s]" <door> (GLock) {mios="unit:house,device:8/service/DoorLock1/Status,in:MAP(miosSwitchIn.map)"}

lock.map

ON=LOCK
OFF=UNLOCK

Now, for the groovy script:
you need to change: miosIP, miosPort ,miosDeviceId for your mios and device information.
you need to add the variable sl_UserCode to the lock in mios lock setting-advanced

lock.groovy

import org.openhab.core.jsr223.internal.shared.*
import org.openhab.core.items.ItemRegistry
import org.joda.time.DateTime
import org.openhab.core.library.types.*
import java.util.timer.*

//implementing a script to check a lock status via mios (vera)
class LockStatus implements Rule {
    static int checkDelay = 15 //15 seconds delay to remove multiple LOCK/UNLOCK
    static miosIP = '192.168.1.22'
    static miosPort = '3480'
    static miosDeviceId = '8'
    
    static ItemRegistry itemRegistry
    static Class pe
    def logger = Openhab.getLogger('LockStatus')
    def http = Openhab.getAction('HTTP')
    def userRegEx = ~/(UserID=")(\d+)(.*)/
    static lastChangeWithPin = new DateTime().minusMinutes(30)
    static lastStateWithPin
    static timer = null
    static lastUserId
    
    LockStatus() {
        //init
        logger.info('LockStatus init') 
    } 

    java.util.List<EventTrigger> getEventTrigger() {
        return [
            new ChangedEventTrigger("MainDoorLock")
        ]
    }

    void execute(Event event) {
        //ON = Lock
        //OFF = Unlock
        def doorStatus = convertOnOff(event.getNewState())
        //eliminate double trigger from pin entry ( ON - OFF - ON or OFF - ON - OFF)
        if(lastChangeWithPin.plusSeconds(checkDelay).beforeNow) {
            checkLock(doorStatus)
        }else{
            //need to check with a timer if the door was change for real. (inside x seconds delay)
            checkLockWithDelay(doorStatus)
        }
    }
    
    boolean convertOnOff(OnOffType status) {
        return status == OnOffType.ON
    }
    
    def getLastUser() {
        def lastUser = http.sendHttpGetRequest('http://' + miosIP + ':' + miosPort + '/data_request?id=variableget&DeviceNum='+miosDeviceId+'&serviceId=urn:micasaverde-com:serviceId:DoorLock1&Variable=sl_UserCode')
        //erase last user entry 
        http.sendHttpGetRequest('http://' + miosIP + ':' + miosPort + '/data_request?id=variableset&DeviceNum=' + miosDeviceId + '&serviceId=urn:micasaverde-com:serviceId:DoorLock1&Variable=sl_UserCode&Value=Erase')
        def m = (lastUser =~ /$userRegEx/)
        
        return m.matches() ? m.getAt(0)[2].toInteger() : null
    }
    
    void checkLock(boolean doorStatus) {
        def statusName = (doorStatus) ? 'LOCK' : 'UNLOCK'
        lastUserId = getLastUser()
        
        if(lastUserId){
            lastChangeWithPin = new DateTime()
            lastStateWithPin = doorStatus
            logger.info("The door as been $statusName by user #" + lastUserId)
        }else{
            //the door was open/close without pin
            logger.info("The door as been $statusName manually")
        }
    }
    
    void checkLockWithDelay(boolean doorStatus) {
        timer?.cancel()
        timer = Openhab.createTimer(new DateTime().plusSeconds(checkDelay),{
                if(lastStateWithPin!=doorStatus) {
                    logger.info('door status changed')
                    checkLock(doorStatus)
                }else{
                    logger.info('no door status changed, dropping')
                }
            } as TimerTask )
    }
}

RuleSet getRules() { 
    return new RuleSet(new LockStatus())
}
 
LockStatus.itemRegistry = this.ItemRegistry
LockStatus.pe = this.PersistenceExtensions 

it will tell you something like that in your log:

The door as been UNLOCK by user #5
door status changed
The door as been LOCK manually

In theory the MiOS Binding/Action combo should help you avoid building the URL to MiOS directly.

In practice, from your sample above, it looks like I’m missing the variableSet call, which I’ve not used before (assuming the MiOS Action binding can be invoked from Groovy.

If you open an issue for the missing variableSet call then I’ll add it and, hopefully, that addition will help simplify your Rule somewhat.

PS: The newer version of the MiOS Item Generator code (in github) generates the relevant REGEX to extract the elements of the sl_usercode, that may also save you a step.

Thanks,

can i run the Mios item Generator in windows?

If i use the binding to get the user, would i be able to erase it after? Wont it just refresh automatically?
I need to take the user, and erase it after that, because mios keep this variable intact, and if i unlock manually it will tell that a user unlock it!

Joel

The MiOS Item generator is a UNIX shell script that uses an XML/XSLT converter pre shipped on UNIX systems. It’ll run on any Linux box, as well as a Mac, but I’ve not found an equivalent for Windows. There are a few online XML/XSLT converters, but I’ve not used those recently.

Thanks for filing the issue! I plan to implement/expose that functionality this weekend.

Typically MiOS data that “repeats” is also augmented by a Datetime value that changes at the same time. This can then be used to dedup the openHAB startup events (since you have use UPDATED instead of CHANGED)…

It looks like MCV left that out of locks for some reason.

Sam,
Were you able to get it working the way “guessed” was saying. I have a Yale Z-Wave lock that in Vera I would disarm my alarm system when the correct code was entered in the Z-wave lock. I would like to get it working directly in OpenHAB.

Hello MikeH,

you can check here: https://github.com/openhab/openhab/issues/4009
There is a way to use it with the actual binding.

Joel