Virtual lock to show combined status of all locks?


#1

1) Give a description of the problem
I’m new to webcore and essentially lost. I have 7 entry doors with Kwikset 914 locks on them. I was wanting to create a single virtual lock that could act as a single point of contact for all of the locks.

2) What is the expected behaviour?
Virtual lock would show “Locked” if ALL doors are locked, and “Unlocked” if ANY door is unlocked. If virtual lock is unlocked, locking it would lock any door that is currently unlocked. If all doors are locked, unlocking virtual lock would unlock all doors.

3) What is happening/not happening?
I’m not even sure where to start creating something that could handle this.

Any help would be greatly appreciated. Please excuse my lack of knowledge in regards to creating pistons.


#2

I am very new to this also but do a lot of tinkering with it, so I am sure someone will come along with a good way of doing it. I myself would try making a piston that stored the values of each lock as locked or unlocked in a string and then if any turned to unlocked it would unlock a virtual switch or lock in SmartThings and would only show as locked if all actual locks showed locked.


#3

Some basics to get you started:
You can set one device variable as a list of all the locks.
You can cycle through the locks if you want an actual count.
Set Show advance statements under options in the editing menu bar
Use for each ($device in {locks})
do …
You can also use If {[locks.locked]} and set the comparison to Any of the selected devices or All of the selected devices. There’s also an option to Store the list of matching devices (or non-matching devices) into a variable.
(If you check that they’re locked and store non-matching devices you can then do a for each… with $device; Lock; to lock all the still unlocked doors.)
If you issue an unlock to {locks} then everything gets unlocked.


#4

This is about as logical as playing follow the leader with two leaders.
For optimal execution, there should really be only one “in charge”.

My two cents is to either:
(A) Let the real locks control the virtual lock
-OR-
(B) Let the virtual lock control the real locks

Trying to do both with the same virtual lock is really asking for trouble.

I would highly consider using method (B) above, and using one of the many other ways to alert yourself to the status of the real locks. (such as the variables mentioned above, or setting a piston state (my preference), or creating a second Simulated device)


Keep in mind that, no matter what path you take, when one door is unlocked, you will not be able to unlock all the rest without toggling the virtual lock twice. (with a nice long wait in between)

If your original goal was a bit flexible, you could make your house more secure, and the coding more reliable, if you got rid of the UNLOCK ALL DOORS section. That one request makes the resulting code more complex, and runs a higher risk of your house being wide open to criminals. (I will never add “Unlock ALL” to my house)


#5

I am still very concerned with your entire house being unlocked while you are at work, but I believe the following does all that you originally requested…

I think the best results would be using two small pistons working together:

Piston 1 (runs when any lock changes)

IF **any** of Lock 1, Lock 2, etc are unlocked  <-- Condition acting as a Trigger
Then
    With Virtual Lock
    Unlock
END IF

IF **all** of Lock 1, Lock 2, etc are locked    <-- Condition acting as a Trigger
Then
    With Virtual Lock
    Lock
END IF

Piston 2 (runs when virtual lock changes)

IF Virtual Lock changes to Unlock                 <-- Trigger
Then
    IF **all** of Lock 1, Lock 2, etc are locked  <-- Condition
    Then
        With Lock 1, Lock 2, etc
        Unlock
    END IF
END IF

IF Virtual Lock changes to Lock                   <-- Trigger
Then
    With Lock 1, Lock 2, etc
    Lock
END IF

(Edit: Removed all ELSE blocks, to make this piston safer)

Notice each IF ends before the next one begins… (except the first two in Piston 2)


Also, since many (most) smart locks take a moment while the gears turn, in Piston 2, I would probably send 7 individual commands with a 1 second wait between each. (instead of all in one line like shown above) This should increase the reliability greatly.


PS. I would still like to encourage you to consider dropping the UNLOCK ALL part of this code. I program “Locks” all the time, all over the place, with no hesitation… but when it comes to “Unlocks” I am very cautious in my coding. Whenever my client insists on automating an unlock, I will place triple/quadruple checks to make sure their household is safe at all times. And all that for a single unlock code. The complexity for a quadruple check on seven locks is mind staggering, and could should never be discussed in a public forum.


#6

Full disclosure here:

The only reason I wanted to create this piston, was so I could mimic the functionality of the “Smart Locks” tile on the SmartThings (Classic) dashboard…but within ActionTiles, instead.

I agree, there’s no reason for me to click the Virtual Lock and have it Unlock ALL doors. I was in the middle of several things while typing that post last night, and didn’t really think that one through.

Essentially, I just want to create a tile that I can give a label like “All Doors Locked” or something, and have it report as “Unlocked” if any door of the 7 is unlocked. And “Locked” if all of the doors are locked. The more useful part was to allow me to click that tile (if it was showing “Unlocked”) on the ActionTiles panel, and have it lock any door that happened to be unlocked. Which is what the “Smart Locks” function does within SmartThings dashboard.

SO…thanks to your help, I’ve got that all working exactly like I was hoping it would. I left out the first “IF” in the 2nd piston, so the only action I can generate is to lock all doors…not unlock.

I’m thinking it would be better to have it check to see which doors are unlocked, and only send the lock command to those doors. Looks like qoheleth suggested that above. I’ll have to look into that. Maybe a bit more advanced than my current capabilities.


#7

Any chance you can elaborate a bit on this? I’m having a bit of trouble understanding variables and how to create or even use them…


#8

Just to let you know, webCoRE is smart enough to not send a lock command to a device that is already locked. This is why it is ok to send an lock command to all of the locks without a bunch of fancy coding.


#9

Something like this: (I don’t have locks so I’m just writing the code in text here)
To create a device variable click on the “+ add a new variable”, select Device from the first drop-down, name it, Set initial value to Physical devices, and select each of the locks from the drop-down next to that. It will look like this when you’re done:
define
device allMyLocks = FrontDoorLock, BackDoorLock, SideDoorLock;
end define;

execute
    /* this will lock all the locks if one lock is locked */
    if {allMyLocks}'s lock changes to locked
    then
        with
            allMyLocks
        do
            Lock;
        end with;
    end if;

To get to the "Store a list of matching/non-matching devices into a variable, when you set the condition (allMyLocks.lock changes to locked) tap the little gear at the bottom right next to [Save] and select a device variable you’ve defined (say allUnlockedLocks).

/* this will get a list of all the locks that are unlocked and lock them*/
If
    (Any of the selected devices)
    if {allMyLocks}'s lock changes to locked
    (Store the list of non-matching devices into variable... allUnlockedLocks)
then
    with
        allUnlockedLocks
    do
        Lock;
    end with;
end if;
/ * this will count all unlocked locks */
   set variable unlockedCount = 0;
for each ($device in {allMyLocks})
do
    if
        {[$device.lock] = unlocked
    then
        set variable unlockedCount = unlockedCount+1;
     end if;
 end for each;