OpenZWave / python-openzwave

Python wrapper for openzwave
Other
200 stars 141 forks source link

1.6 Update - Central Scene Command Class (python-openzwave) #170

Open Fishwaldo opened 5 years ago

Fishwaldo commented 5 years ago

As per the OZW 1.6 Release Notes, The Central Scene CommandClass has undergone a complete rewrite

Need to confirm no changes are required.

kdschlosser commented 5 years ago

would someone be willing to give me a code example on using this. C code is fine.

Fishwaldo commented 5 years ago

the ozwcp works fine with the CentralScene. Its similar to the UserCode changes - CentralSceneIndex_SceneCount is the number of scenes a device supports and from index 1, each Scene is exposed as a ValueList with the following options:

        "Inactive",
        "Pressed 1 Time",
        "Key Released",
        "Key Held down",
        "Pressed 2 Times",
        "Pressed 3 Times",
        "Pressed 4 Times",
        "Pressed 5 Times"

and the values of each are 0 based - meaning inactive = 0

kdschlosser commented 5 years ago

OK so only devices that have COMMAND_CLASS_CENTRAL_SCENE will have the appropriate values.

I was a bit spun about because of the depreciated scene methods in the manager. I am still learning and have some old thoughts kicking about. Most ZWave controllers have the ability to create "scenes", these scenes do not require a device to have COMMAND_CLASS_CENTRAL_SCENE. because of the manager having those scene methods I had thought that the actual scenes get stored on the network.

Does the controller have COMMAND_CLASS_CENTRAL_SCENE?? that would make sense if it does. I never looked.

Fishwaldo commented 5 years ago

The old Scene methods was not anything specific to the Zwave spec. Just some convince methods to trigger a bunch of devices with one command. I think I only ever saw one user using it in 8 years!

This is referring to Central Scene command class. It’s separate

kdschlosser commented 5 years ago

ahhh OK.

so give me some detail into the Central Scene command class. I am thinking this is for things like remotes and wall button pads. where you can program a button to say turn on a light or several lights.

I looked at the code in openzwave for it. I am a little fuzzy on what exactly it does..

Fishwaldo commented 5 years ago

It’s essentially just a fancy remote. You press a button, it sends a button pressed message to the nodes in its association group. You press a button twice, it sends a button pressed twice message.

You hold a button down, it sends a button held down message and when you release, it sends a button released message.

We handle these as a valueList so you can distinguish between the different number of presses etc.

Each “scene” usually represents a different button.

The contents of the ValueList represent what the device supports (Eg, not all devices support 3, 4 or 5 presses of a single button). (But not all devices will advertise what they support, so in that case we just populate with all possible combinations).

kdschlosser commented 5 years ago

ok. and is there some kind of mechanism in there for knowing what button was pressed manually?? or it is only for programmatically pressing a button

kdschlosser commented 5 years ago

Now if i wanted to add or remove a node from an association group would I use the value id of the scene as the group id?

Fishwaldo commented 5 years ago

ok. and is there some kind of mechanism in there for knowing what button was pressed manually?? or it is only for programmatically pressing a button

eh? the user presses a button on the device. not software. the commandclass sends a message that the button was pressed

Fishwaldo commented 5 years ago

Now if i wanted to add or remove a node from an association group would I use the value id of the scene as the group id?

no. always the node in associations. (maybe the instamcs if the device is a multiinstance device).

the target node has to support processing Centralscene messages. I've never seen a device like a switch or outlet have that support. I am guessing it's more intended for communicating with gateway software and the gateway decides what to turn on/off and send subsequent messages to those devices.

Fishwaldo commented 5 years ago

eh. I think I missundstood your association question. there is no relation between CentralScene and associations. a device can have 5 buttons but one association group. (or one button and 5 association groups)

kdschlosser commented 5 years ago

you stated this a couple of posts back.

It’s essentially just a fancy remote. You press a button, it sends a button pressed message to the nodes in its association group. You press a button twice, it sends a button pressed twice message.

and from reading the code in python_openzwave for the get associations method it falls in line with an association group being attached to the index of one of the values that would be considered a "scene"

the code in the method for getting the association groups iterates all numbers from 1 to 255 and then calls the Manager::GetMaxAssociations method to verify that the index for the group does allow associations to it.

It would make sense if the value index for a scene would be the same number as the group index for the associations that are assigned to that scene. It could possibly be a coincidence that the group indexes have the exact same range as the central scene indexes.

Maybe? or am i reaching here? LOL

kdschlosser commented 5 years ago

I also incorrectly stated to use the value id as the group id. in the previous posts. it was value index that i meant to say.

kdschlosser commented 5 years ago

maybe my understanding of how association groups work is incorrect. IDK. I thought the association groups purpose was to be able to control multiple devices from a single node. an example would be if i wanted to turn on both of my outside lights from a single switch, I could do something like that from a single switch. The purpose would be to reduce network packets being transmitted. The "master" would send a command directly to the other switch without having to send a packet to the controller and then have the controller send another packet to that switch to turn it on.

If this is how it works then how would i assign a node to a specific "scene" or button on the central scene node? This gets done through the use of a group index yes? so how do I know what group index is for what scene.

the but i cannot figure out is on a device that supports association groups you have a group index for each of the button press types. 1, 2, 3.... and i have to assign the remote node that i want to control to that specific association group index.

I know I am using a theoretical scenario. if the protocol was written so that a node can support 255 scenes it would be possible for the node to also have 255 buttons. and that would require one association group for each of the button press types available to each scene, which is a total of 1785 association groups.

kdschlosser commented 5 years ago

i have been trying to figure out the relationship between the scenes and the association groups. There is one. This is how the scenes work. I just can't get a grasp on how the groups get assigned to specific button presses of a scene.

these command classes are pretty well intertwined

COMMAND_CLASS_ASSOCIATION COMMAND_CLASS_ASSOCIATION_GRP_INFO COMMAND_CLASS_ASSOCIATION_COMMAND_CONFIGURATION COMMAND_CLASS_MULTI_CHANNEL_ASSOCIATION COMMAND_CLASS_CENTRAL_SCENE COMMAND_CLASS_SCENE_ACTIVATION COMMAND_CLASS_SCENE_ACTUATOR_CONF COMMAND_CLASS_SCENE_CONTROLLER_CONF

if someone has a device that supports the central scene we would be able to see how the association groups get applied to the scenes simply by adding a node to the different available association groups and see what button press controls the remote node.

from my reading I believe I am correct in that there is an association group that gets assigned to each button type for in each of the scenes. and a scene can be a physical GUI based or even virtual. so an actual physical button does not have to be on the device in order to support additional buttons.

I think it may use the multi channel association command class to do this. it states in the specification that node id's can be used as endpoints. and this would allow each scene to become a channel and each channel would have the ability to to have a set of association groups.

I am not really sure tho. there is some kind of mechanics behind it that i simply do not understand

Fishwaldo commented 5 years ago

No. There is NO relation between a “Scene ID” and groups in Association classes. Associations only contain Nodes (and instances).

When something changes on a device it sends a REPORT or SET message to devices listed in the association groups. (And the setup of what triggers this message is partially defined by the spec for group 1 - lifeline) but for other groups is upto the manufacturer. The receiving nodes must support the command classes messages sent otherwise they do nothing. (They don’t understand it).

So a device with CentralScene and one association group (lifeline) will send a Scene_Set with the Scene ID equal to the button, any action equal to single/double press etc etc etc to the nodes listed in the lifeline association group.

There is no requirement for having number of groups equal to number of scenes (and in fact from memory, I believe the max number of groups is limited to 8).

Fishwaldo commented 5 years ago

I have multiple CentralScene devices. As mentioned there is no relation with the number of scenes and groups.

Check out this for a example. The CentralScene is only assigned to Association Group 1. Other functions are assigned to the other groups.

https://aeotec.freshdesk.com/support/solutions/articles/6000162392-wallmote-quad-user-guide-

kdschlosser commented 5 years ago

ok so with what I am seeing the theoretical maximum number of association groups is in fact 1785 + 1 for the lifeline so a total of 1786 association group id's

It seems there is a problem with the specification. because the Central Scene class has support for 255 scenes (buttons) and the association group command class only has 1 byte allocated for the group id this only allows for 256 possible ids. and since the ids also have to start at 1 that now makes it 255 available ids. and id 1 is reserved for the mandatory lifeline now the number drops to 254 available group ids.

even from the original design specification it was impossible to make use of all 255 available scenes there is not enough association group id's available. despite the fact that the central scene command class in version 1 supported 3 button press types (3 255) + 1 = 766 association groups (FAIL). it would never even work with one press type assigned to each scene (255 (buttons) 1 (press type) ) + 1 (lifeline) = 256 association groups (FAIL),

if supporting all 7 press types for every button the max number of scenes (buttons) would be 36.

Because the use of virtual buttons is allowed and there is also concessions for having a touch screen interface and GUI buttons the possibility of a device that can implement more then 36 buttons is very possible.

and the really crappy thing is there is no link between the button press types in a scene and the association groups that represent them.

in the example you provided (see below) there is a definite pattern to how the groups are mapped to the scenes button press types.

image

and we would hope that all the manufacturers would do the same. an outline of this is below as well. example:

scene 1 (button 1)
    single press: association group 1
    double press: association group 2
    triple press: association group 3

scene 2 (button 2)
    single press: association group 4
    double press: association group 5
    triple press: association group 6

because there is no specification on how the arrangement of buttons/press types/association groups the following can be done by the manufacturer if they wanted to.

scene 1 (button 6)
    single press: association group 22
    double press: association group 36
    triple press: association group 21

scene 2 (button 3)
    single press: association group 9
    double press: association group 54
    triple press: association group 11

with no way to programmatically map them together this makes it impossible to write any kind of a handler that would shield the user from having to know about association groups, and the central scene command class. I know that was one of the goals you wanted for this library was to keep the protocol exposure as small as possible.

I would imagine that a device manufacturer would use the logic in the first example. But there is no guarantee that they will. there is no guaranteed way of knowing. This portion of the specification was not thought thru very well.

I hope that I am explaining this in a better way.

I am no expert on this and you have a much larger scope of understanding of the protocol then I do. PLEASE tell me if I am wrong in seeing a problem with the specification. again I am a green horn programmer, and at 44 years old I am not the sharpest tack in the box (not even the second sharpest). LOL.

If this is in fact a problem with the specification and you have a contact over at Silicon Labs you may want to bring this to their attention. I did outline 2 possible solutions below. maybe one of them will work if my interpretation of the specification is correct.

solution 1: The COMMAND_CLASS_ASSOCIATION specification would need to be modified to allow for an additional byte to be added to the id portion. this would then allow for 65536 - 1 (starts at id 1) possible association group id's, as a nicety adding some mechanism to be able to identify what scene button press type maps to what association group id.

solution 2: This is still kind of fuzzy and would require more eyes to look at it and see if it is possible doing this or not. It would make it so that the association group command class would not have to be touched. Maybe...

If COMMAND_CLASS_MULTI_CHANNEL_ASSOCIATION was a requirement of COMMAND_CLASS_CENTRAL_SCENE there would be enough association group id's available. this is due to an additional byte added for the endpoint id. This would also make it possible to know what association groups belong to what scenes (buttons). the void of knowing what press type is associated to what group can then be filled easily by making it a requirement so that the association group id would need to be the same as the value used to "press the button" .

the enum for the press types are outlined in openzwave as:

enum CentralScene_KeyAttributes
{
    CentralScene_KeyAttributes_KeyPressed1time        = 0,
    CentralScene_KeyAttributes_KeyReleased            = 1,
    CentralScene_KeyAttributes_KeyHeldDown            = 2,
    CentralScene_KeyAttributes_KeyPressed2times       = 3,
    CentralScene_KeyAttributes_KeyPressed3times       = 4,
    CentralScene_KeyAttributes_KeyPressed4times       = 5,
    CentralScene_KeyAttributes_KeyPressed5times       = 6,
    CentralScene_KeyAttributes_reserved               = 7,
};

because association group ID's need to start at 1. so all that would need to be done is the following.

association group assigned to KeyPressed1time = CentralScene_KeyAttributes_KeyPressed1time + 1
association group assigned to KeyReleased = CentralScene_KeyAttributes_KeyReleased + 1
association group assigned to KeyHeldDown  = CentralScene_KeyAttributes_KeyHeldDown + 1
association group assigned to KeyPressed2times = CentralScene_KeyAttributes_KeyPressed2times + 1
association group assigned to KeyPressed3times = CentralScene_KeyAttributes_KeyPressed3times + 1       
association group assigned to KeyPressed4times  = CentralScene_KeyAttributes_KeyPressed4times + 1       
association group assigned to KeyPressed5times = CentralScene_KeyAttributes_KeyPressed5times + 1      

This design would now make it possible to know exactly what association group is responsible for carrying out the actions of a press type.

how the association groups get assigned to the actual scenes would be simply done by scene id. so scene scene id 1 (button 1) = endpoint id 1 scene id 2 (button 2) = endpoint id 2 etc...

because each endpoint now has the availability of having a max of 255 association groups this fixes the issue. because there are only 7 button press types it is well below the maximum. I do not know how many endpoints are supported. I would think it would be a single byte for the endpoint id making the maximum number of endpoints the same as the maximum number of scenes (255)

with just a quick look COMMAND_CLASS_ASSOCIATION_GRP_INFO could be used to identify the press type to an association group id. Not 100% sure on that.

Fishwaldo commented 5 years ago

I think you are thoroughly confused! Central Scene, as the name implies, IS NOT really intended for controlling devices directly. Its for triggering a "Scene" on a controller. in 99.999999% of cases, Central Scene doesn't talk to other devices - it can't! see below

Stop connecting Central Scene with Association Groups. There is no need! when you press a button, Central Scene sends a message saying Scene 1 - 1 Press (or 2 press or 3 press etc). It sends that message to the devices listed in the Association Group that handles Central Scene on that device (typically lifeline). The "devices" is usually the controller (hence why its in the lifeline group). and its usually not plural, but 1 device (as not many people would have multiple controllers). OZW receives a message from say Node 10, CentralScene CommandClass (0x5B) with a CentralSceneCommand_Get (0x03), and the params say Scene 5, and Key Attribute Set to KeyPressed1Time. OZW puts that all together, emits a ValueChanged Message for Node 10, CentralScene CC, Index 5 (=Scene5) and KeyPress1Time. Your application then goes off and does whatever it needs to alter to setup a scene that represents Scene5, KeyPress1Time "scene" in your home. No mapping of association groups, endpoints etc is needed at all to decode that.

Central Scene IS NOT intended to directly change the state of another device! As the name implies its to trigger a "Scene" on a "Central" Controller. The controller then takes care of sending out the messages to the individual devices.

In the table above, you will see Association Groups >= 2 that have NOTHING todo with Central Scene. They either send a basic set, or multilevel set to directly control devices. So in the case of the WallMote, you have some flexibility. You can use it to trigger a Scene on your controller (the part behind OZW), or directly control a device, or if your really fancy, do both.

And in real life, while there are plenty of devices that support Central Scene, they are a "controlling" Central Scene node, and NOT a "controlled" Central Scene Node (meaning they can't decode a Central Scene Set Message thats sent by a WallMote etc). And even if they could, how would they know exactly what to do? Do you want to turn something on/off/Dim/Brighten/Change Color, Volume Up/Down etc? The Central Scene CC doesn't specify that. it just says Scene 1, 1 Press on the Button.

If you want to directly control say a bunch of Lights (via multiple Switches), then you get another device that supports SwitchBinary CC, and add the Light Switches to the Association Groups (as per the manufacturers specifications) of if your using something like the wallmote, you ignore the Central Scene Support and add your light switches to groups >= 2.

I guess go and erase everything you assumed about Central Scene, Forget that associations even exist in the context of Central Scene, and understand this CC is for triggering Controllers/Gateways.

kdschlosser commented 5 years ago

OK I got ya. the application is supposed to be set up to listen for value changed events from the node that has the central scene command class. and when one of those notifications comes in then the application is responsible for modifying the sate of whatever nodes it needs to.

What would be the purpose of the application being able to send a command to the central scene device to press a button? since the application would be able to run a scene directly without the need to do that. it only creates additional network traffic there is also an increased chance of either the command never reaching the central scene device. or the notification from the central scene device never being received by the controller. this is the largest reason why I had thought the central scene device controls other nodes directly. simply because it doesn't make any sense to be able to mimic the pressing of the button if the application is ultimately responsible for running the scene.

So this is for my own knowledge. does openzwave create a value changed notification every 200 milliseconds when it receives the notification from the device for the button being held down? because technically speaking the value has not changed.

does openzwave send a value changed notification for the button being released if it has not received a button held down notification from the device after 400 milliseconds?

Fishwaldo commented 5 years ago

does openzwave create a value changed notification every 200 milliseconds when it receives the notification from the device for the button being held down? because technically speaking the value has not changed.

Yes - But its triggered by the device (ie, the device is sending a Report every so often).

OZW will go Button Held Down - Button Released as long as the device reports released. Otherwise it will reset to inactive after 1 second.

What would be the purpose of the application being able to send a command to the central scene device to press a button? at least in OZW we don't. The values are ReadOnly. I don't think the devices I've seen support a SET message

Fishwaldo commented 5 years ago

btw, when will you be able to open PR's for this? There are a bunch of users waiting to "test" :)

kdschlosser commented 5 years ago

There are a few more things I have to hammer out. I want to make sure everything is done so that it is not going to possibly cause an issue further on down the road. I am also trying to make changes in a way that is going to cause as little (if any) impact on them. The goal is to update python-openzwave to be compliant with OZW 1.6, but do it in such a way that the user does not have to change any of their code right away.

This is going to be the last question dealing with the scenes. Right now OZW has built into it the building of scenes. this includes what values are to be change when a scene gets activated. all of the methods for using this have been depreciated and I do not see anything added to the central scene command class that would take over any of these abilities.

here are the depreciated methods.

Manager::GetNumOfScenes
Manager::GetAllScenes
Manager::RemoveAllScenes
Manager::CreateScene
Manager::RemoveScene
Manager::AddSceneValue
Manager::AddSceneValueListSelection
Manager::RemoveSceneValue
Manager::SceneGetValues
Manager::SceneGetValueAsBool
Manager::SceneGetValueAsByte
Manager::SceneGetValueAsFloat
Manager::SceneGetValueAsInt
Manager::SceneGetValueAsShort
Manager::SceneGetValueAsString
Manager::SceneGetValueListSelection
Manager::SetSceneValue
Manager::SetSceneValueListSelection
Manager::GetSceneLabel
Manager::SetSceneLabel
Manager::SceneExists
Manager::ActivateScene

So I am gathering is that the current game plan is. All handling of the grouping of nodes values to be changed has to be done by the user. the changing of the values in a grouping for a specific notification received from a central scene device for a button press is going to have to be handled by the user as well.

Has anyone thought about re-purposing the existing scene handling. All of the relevant bits are already coded in OZW to handle this. I do not imagine it would be that difficult to modify the code so that the incoming notifications from a central scene device would then "active" the scene that OZW has stored. add a method to assign the node ID and the index of the button as well as the data that is used to "activate" a specific scene.

I am wondering if the lack of use of the scenes was because no one knew what to use it for. It served no real purpose. if it has an attachment to a command class it now has a purpose.

I am working my fastest to get this working. I have finally managed to get the build system on the windows side of things properly functioning. those last changes you made to the Utils.cpp file have taken care of that. I did have to modify the windows build system because of the "test" folder that has now been introduced into the "src" folder in OZW 1.6. the Windows build does not use the solution file to build OZW it enumerates the files to be compiled from the files located in the "src" folder. I also need to verify compiler flags used when building using the solution file against the ones I am using in python-openzwave. I have to be very careful with any changes being made in regards to the build system. because python-openzwave supports building of older versions of openzwave. don't want to break anything.

Currently only building python-openzwave will function by building it in development mode. This is because the new code is not in a release. and the development mode downloads OZW from github. when the new code gets released then python-openzwave will be able to support the other build types.

There is a project that I am the administrator for and we had a nasty thing happen to use with our server. and corrupted backups... it's very ugly actually. My focus has been redirected somewhat to rebuilding the website/forum/docs and every things else in the middle. I have not been able to put in as much work on this in the past few days as I would have liked to. I am working on it. There were a slew of changed made in OZW 1.6 and from there a bunch of changes to python-openzwave need to be made as well.

I had to write a mechanism that would handle the assortment of depreciated items properly. we want to let the users know that there will be API breaking changes coming soon. I do not want to "throw anyone under the bus" when these changes happen. needed to have a mechanism to properly inform them of the changes.

Right now I am simply going to put a depreciation warning on the scene methods to be depreciated and leave the central scene command class how it is. simply being able to set the button press type. it seems as tho there is no other thing that it does other then that currently.

I believe there are only a few changes left to be made. and none of them appear to difficult to do. I am going to work on this some today. if everything goes smoothly and I do not have more questions or get stuck some where expect a PR as soon as today.

kdschlosser commented 5 years ago

OK I believe I am now finished. I am going to run some quick tests. make sure the thing actually imports. It does compile properly and without any errors. YAY!

It is probably going to fail appveyor and travis because of the unittests. I am going to have to update that as well. I will deal with that when the PR takes place.

so barring any major complications I whould be able to do a PR pretty soon