I think I read every thread and the docs related to this and I am stuck. There are a lot.
@tgauchat talked about the subtleties… Oh, the subtleties… and, the documentation.
The docs are much better these days, but not complete.
It took me over six different threads to get to this point – all Hail the Weary ST hackers whose shoulders I stand on
The Pattern provides a Virtual Device Handler exposed as a Device in the App & addressable by other Apps as ONE.
Two particular Use Cases are a Garage Door and a Regular Door.
Both have at least two related Devices: A Relay & Contact. A Lock & Contact.
So, the pattern necessarily includes those two devices, a Controller App that mediates to the Virtual Device.
Ignore the light - it gets its own async SmartLighting instance.
Pressing the Device opens the door via the Relay: The App gets that Event & calls the Relay
The Device button changes Image/State based on the Contact: The App gets that Event and invokes a Command
I got this far, but invoking that Command through a method that createsEvent causes ping-ponging…
I.e. Since the Open/Close Actions are really just button presses this happens:
Press Open:Door starts opening, Contact opens:Sends Event, App sends to Virtual device.
Device receives Opened Event: Attribute State Changed: Action taken… Relay re-engaged. Oops.
Code may be accessible here: https://github.com/gtc100gh/SmartThingsPublic