I threw the lock back into the mix, had to fix a couple little things I'd broken but it is working fine. The only thing currently is that the lock never reports being locked, despite accepting either lock or unlock commands and reacting to them. I'm guessing maybe I actually have to physically assemble it a bit more or something. I have the two parts just laying on the desk. If so that will be sort of suck since I have no play to actually install it, and I wouldn't want to anyway, it needs to be here for me to interact with it during testing.
Maybe you could find one of those miniature door lock demo doors or make one. My Yale locks have 3 parts, the inside and outside bits and the deadbolt mechanism. Perhaps you just need to assemble the bits (or maybe you have already done that) The inside and outside bits on the Yale plug into each other as the batteries and electronics are on the inside and the keypad is on the outside.
I tried just sort of putting it together, but it just would bind up and sit there and grind ominously for a long time. I gave up on that and pulled out the other one (Yale 210. ) It works when just stuck together. But it's old and uses the old ALARM V1 class to report status. That class had no predefined values, they were all proprietary, and the spec says they MUST be documented. Are they? No. I cannot find anywhere what its reported alarm codes mean.
Oh, nevermind, somehow I figured them out a long time ago and the VRC0P driver has some basic info as to how to interpret them. It seems to correspond to what I'm seeing. It'll require a custom handler though, or some more extra configuration info in the device info file. Or, I create a special V1 alarm class implementation. The gotcha is that you only know it's V1 if you can get the versions of the command classes supported, which you may not be able to. Sigh...
Oh well, it didn't survive as is. I should have been suspicious when it started making so much sense. As soon as I threw that other lock in I realized I'd made a mistake. I have these 'command class implementation' classes which implement a whole CC or a part of one, mostly parts of them. I was letting them create their own fields and keep them updated based on incoming messages.
But I failed to consider the inconsistency of Z-Wave implementations. My lock class assumed that the door lock was used to manage the lock. But on the Yale, it's not used to send notifications of state changes, though it's perfectly suited to be used for that and it's silly to do anything else. But they use the notification system, and the old V1 alarm one as well, which has no defined values.
But anyway, the problem is that there would then be two of these implementation objects, both wanting to create their own fields, but they really are dealing with the same field.
So, then I started accepting that I'd just let these things maintain an internal state, and that the unit objects would create all of the files and just use the internal states of these CC implementation objects to update the fields. But that was bringing back a lot of redundant code that I'd worked hard to not have. But, I'm a Fifth Level Yoyo Master, so I figured out, by adding yet another layer, how to do both. I can have a base class and derivative of each of these things, the base of which just maintains the internal value, and the derivative of which creates the field and keeps updated using the info from the base class.
So, for the most part I will still be able to use these very convenient field managing CC implementation objects. In those cases like the Yale lock, the unit object can create an alarm/notification object of the base class sort. Each time it reports a change in its state, the unit object can use that to update the state of the field in the door lock handler.
So more complexity but it keeps things much cleaner, and maintains the previous scheme of minimizing redundant code while maintaining flexibility.
So for something like the lock, I can have my generic lock handler have a flag in the device info that tells him to use the notification class in this way. So I still don't have to have custom handlers for any other locks that do that sort of thing. As before, it starts becoming an issue of how much parameterization (aka complexity) are you willing to deal with in order to support as many units as possible via generic handlers. In this case, it's probably worth since there will probably be other Yale, and other older locks that do this.
I expanded out my 'extra info' stuff in the device info files to include both unit level stuff, and per-command class stuff for this purpose. So the unit level handler doesn't have to understand how to pass on parameters to specific CC implementation objects.
Anyway, that probably sounded like Klingon or something, but the bottom line is another long and painful day of rearranging to make up for a failure to foresee something. I didn't quite get all the changes done, but almost there. I'll get it back up once again tomorrow and move forward again.
Wow, amazingly that all worked. At least for the lock which is the only real use of it so far. I created a 'notification lock' C++ handler, to generically handle locks of that sort, and it just creates a non-field oriented notification CC implementation object which parses his CC specific extra info out to get the event ids he needs to know about. The notification lock unit handler passes msgs to the notification CC impl, and if that guy indicates its state changed the unit handler forces that new state to the door lock CC's lock state field.
OK, that now makes a lot of things possible moving forward without having to get unit specific handlers. It might require some other generic handlers to deal with a particular sort of usage pattern, but that's still big win, and I still get to keep the field management down in the CC implementation objects which avoids a lot of redundant busy work over time.
OK, so far, so good. I'm moving on to making sure that battery powered devices are handled correctly. We have to queue up msgs and send them at the appropriate time. And we need to be able get information on them when we get the chance to do so. Then I guess I'll try my old multi-sensor since it's one that's most likely to be furthest off the beaten path of any I have. Though, with the tools I have now I think it will be fairly straightforward now. I'll need to do a CC impl class for multi-level sensor which I've not done yet, since a few of the things it reports use that.
And more good progress. I think I have the battery powered ones basically figured out. If you do the batteries out/in thing that most of them require (or some of them have a button pressing sequence) to make them start up and come online, they will send out their node info. The driver will see that and, if it sees it's a battery powered unit waiting for config info, it will kick off that process. If it can get manufacturer ids it will self configure if it can. Once it has the info you are good.
I also realized that the stuff I did above allows for much more generic handlers in some cases. There were going to be a lot of complicates with, say, a generic motion sensor, since I'd have to have a device info for each possible variation (does it send BASIC or BINARY SENSOR, or NOTIFICATION stuff.) But, with the field-less CC impl option, I can just have a generic motion handler that creates one of each (for each class supported by the device.) IT passes any CC msgs to any it creates. If they change stage, it stores that state to the field that it maintains itself.
So it becomes a pretty hassle free, generic motion sensor handler that will deal easily with all of the common scenarios, and handle them without any real need for user intervention. Of course we can have device info files for specific motion sensors as well, just to make it as easy as possible to insure that the driver fully understands a given one, or deals with special case concerns, or just so that we can show them by make/model in the list to make it easier on the user to make sure he's selecting the right one. For the most part, those can also just consist of a device info file that parameterizes one of the more generic unit handler classes.
Things are going suspiciously well. I've got the battery powered ones doing nicely. Queued up msgs are being sent to them when I get a wakeup or if you do the battery cycle thing. I found some goobers along the way and got them fixed which improved things more. I have a lock, a motion sensor, a door sensor, a tilt sensor, and a dual channel outlet all going and it's working quite well.
Of course I've got it all in one room, but I'm getting no failures at all in terms of msg I/O, with plenty of overlap, i.e. I can have an outstanding transaction with each unit at the same time, though the need to ask for receipt acks for outgoing commands slows that down a bit since we have to wait for that ack before the next msg can be sent. For queries that's not necessary since the response to the query is the ack. In that case we just have to wait long enough for the Z-Stick to say he sent it out.
So the throughput is quite good. I also have no crusty old units either. These are all reasonably modern. Not super-new all of them, but not cave units.
Dean, check under you bed, no seriously...
Well once you are ready to release for beta I have a very old Wayne Dalton light switch that uses vampire power for the zwave receiver, it's gen 1, maybe even gen .25 its so old. Have to keep a CFL or incandescent bulb in the light for the dang thing to work.