WebThingsIO / gateway-addon-python

Python bindings for developing add-ons for WebThings Gateway
Mozilla Public License 2.0
16 stars 10 forks source link

Creating actions #73

Closed flatsiedatsie closed 4 years ago

flatsiedatsie commented 4 years ago

I'm trying to implement the lock capability in the MySensors add-on. I'm a bit stuck on how to add actions. Are there any existing python add-ons that showcase how this works?

I've tried to just copy the actions code from the virtual things example, but that didn't seem to work.

I'm also not sure how I would 'catch' when these button would be pressed in the interface. My guess is that it will somehow end up in the action_notify method, and I can work from there?

flatsiedatsie commented 4 years ago

I'm trying "add_action" now.

I just realised: my smart lock device supports two actual electronic locks. It can manage the front door and apartment door at the same time. So to have a 'lock' and 'unlock' action for each individual electronic lock, I'll probably have to add something like "lock 1", "unlock 1", "lock 2" and "unlock 2".

flatsiedatsie commented 4 years ago

name 'title' is not defined

When I try:

                        self.add_action('unlock', {
                            '@type': 'UnlockAction',
                            title: 'Unlock',
                            description: 'Unlock the locking mechanism',
                        })

(with the above copied from the virtual things code)

Ah, it thinks title is a variable. Of course.

lock_working Progress!

Lock are going to get a lot of properties with this 'action' route.

flatsiedatsie commented 4 years ago

I wonder if this means the voice control now also has to support actions, and access new parts of the API. This is getting a bit much.

If the lock's state display is already separated from the actuator as a new property, why then also split up the actuator into two actions? I know the answer is "because sometimes lock are in an intermediary state", but if the state display and the actuator are already separated, this is no longer an issue anyway. The add-on can then handle this. For example, the actuator may be in the 'locked' state, while the state display property reads "locking.." during that period, until it finally says "locked" (for example).

In a way even the separate state display and actuator button may not be required. Currently there already is the ... display on a property if it's in the middle of changing a state. By exposing that functionality to add-ons, they could handle this intermediary phase in a more basic but also simpler way?

flatsiedatsie commented 4 years ago

Something else: it seems actions cannot be put at the 'center' of the octopus (which would allow for quicker use on the thing overview screen, e.g. a quick tap on a wall mounted tablet). Even if it were possible, the 'lock' and 'unlock' actions are two separate 'properties', so it wouldn't be possible to have a single 'lock/unlock' central bubble.

It's a shame so many activities require three clicks. Which is exacerbated by the fact that the 'octopus' arms are always in new random position, so it becomes:

benfrancis commented 4 years ago

I can't answer your Python-specific questions but you can read the rationale behind the schema and UI design on GitHub.

As far as I know there are currently no voice controls to lock/unlock a door. There might be security issues with unlocking a door with your voice...

The "..." UI indicates that LockedProperty has a value of "uknown". You can access this state through the Web Thing API.

Not being able to lock/unlock a door with a single tap is an intentional design decision. I know it's not ideal, but neither is accidentally butt-dialling your front door open ;)

mrstegeman commented 4 years ago

@flatsiedatsie do you still have open questions about creating actions, or is this now just a general discussion about the Lock capability?

In general, you will use add_action() in your Device class to add a new action to your thing description. Then, you will use perform_action() to act upon a new action requested by the user.

flatsiedatsie commented 4 years ago

Not being able to lock/unlock a door with a single tap is an intentional design decision. I know it's not ideal, but neither is accidentally butt-dialling your front door open ;)

Perhaps users could choose what they want? E.g. by setting lock+unlock button as a 'center stage' option somehow? For example, it would be possible to create a special user for the wall tablet, and in that users' settings expose such direct options in the central bubble for quicker interactions? While a normal user could leave them hidden? A 'one size must fit all' situation could be avoided?

but you can read the rationale behind the schema and UI design on GitHub.

I have indeed read those, and enjoyed seeing the design process. I very much recognise the issues. I'm just giving some feedback as an add-on developer that the new situation may have unforeseen consequences and complexity. Especially the large amount of bubbles that a device may gain if the lock also has some other features (including having two locks in one device)

The "..." UI indicates that LockedProperty has a value of "uknown". You can access this state through the Web Thing API.

Sure. But my point was that allowing add-ons to purposefully set this state bring you halfway to solving the issue that led to the separation of actuators and state display into separate bubbles. Displaying the 'unknown' state was already possible in the UI, it just couldn't be explicitly set by add-ons.

There are two types of locks: A. Dumb smart locks. You can lock them from the UI, but if a user manually unlocks them, this is not communicated back to the system. Having a separate lock and unlock button is indeed very useful here to avoid state mismatch (but the button can still show which option was pressed last). smart_smart_lock_unlocked

B. Smart smart locks, which send news about their actual state back to the system. With these locks, there could be a simpler way of displaying their state in one property bubble. smart_smart_lock_unlocked smart_smart_lock_locking smart_smart_lock_jammed

Now this is all very much at the opposite end of the spectrum from "a lock now has a property and two action bubbles", and may go to far in lots of ways (including being too late in the process to comment).

As far as I know there are currently no voice controls to lock/unlock a door. There might be security issues with unlocking a door with your voice...

Voco does support this. But you're right, that is a security issue, and I haven't addressed that properly. Do you have a recommendation on how to let users selectively erect barriers? Otherwise I could just block all locks from being voice controlled. Or only allow voice control if presence detection indicates that users are home already. Or only allow is during the day. Users could decide all this using rules. Which would give the smart lock yet another property to toggle :-). And I was already going to add more for some privacy features. It pushing the current bubble UI to breaking point :-)

In general, you will use add_action() in your Device class to add a new action to your thing description. Then, you will use perform_action() to act upon a new action requested by the user.

Ah, so when the user initiated an action, my code can 'capture' it by creating a perform_action method? I can grab the name of the action there? That part of the route was still unclear to me.

mrstegeman commented 4 years ago

Ah, so when the user initiated an action, my code can 'capture' it by creating a perform_action method? I can grab the name of the action there? That part of the route was still unclear to me.

Yes. For an example, which is actually an example of how to use the lock/unlock actions when the underlying data model is a property, see here: https://github.com/mozilla-iot/homekit-adapter/blob/master/lib/homekit-device.js#L3382-L3409