diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000000..0a41225d86 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,8 @@ +# These are supported funding model platforms + +#github: [Fishwaldo, nechry] +patreon: # Replace with a single Patreon username +open_collective: ozw +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +custom: # Replace with a single custom sponsorship URL diff --git a/.github/workflows/PRTest.yml b/.github/workflows/PRTest.yml new file mode 100644 index 0000000000..faa46984ea --- /dev/null +++ b/.github/workflows/PRTest.yml @@ -0,0 +1,21 @@ +name: PR Test + +on: + pull_request: + types: [opened, edited, reopened, synchronize] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - name: Trigger Build + uses: Fishwaldo/Bamboo-PR-Trigger@master + env: + BBSERVER: bamboo.my-ho.st + BBUSER: ${{ secrets.bamboouser }} + BBPASS: ${{ secrets.bamboopass }} + BBPRJ: OZW-PRTST + BBPR: ${{ github.event.number }} + diff --git a/.gitignore b/.gitignore index 3fb3af7cf2..3fcdfddb49 100644 --- a/.gitignore +++ b/.gitignore @@ -53,5 +53,5 @@ ozw_config .idea/ .idea/* ozw_config - +gtest-main cpp/src/command_classes/\.DS_Store diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..0a041280bd --- /dev/null +++ b/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/Makefile b/Makefile index 6265f6f542..2b997b7555 100644 --- a/Makefile +++ b/Makefile @@ -20,23 +20,26 @@ UNAME := $(shell uname) export UNAME all: - LDFLAGS="$(LDFLAGS)" CPPFLAGS="$(CPPFLAGS)" $(MAKE) -C $(top_srcdir)/cpp/build/ -$(MAKEFLAGS) - LDFLAGS="$(LDFLAGS)" CPPFLAGS="$(CPPFLAGS)" $(MAKE) -C $(top_srcdir)/cpp/examples/MinOZW/ -$(MAKEFLAGS) + @LDFLAGS="$(LDFLAGS)" CPPFLAGS="$(CPPFLAGS)" $(MAKE) -C $(top_srcdir)/cpp/build/ -$(MAKEFLAGS) + @LDFLAGS="$(LDFLAGS)" CPPFLAGS="$(CPPFLAGS)" $(MAKE) -C $(top_srcdir)/cpp/examples/MinOZW/ -$(MAKEFLAGS) install: - $(MAKE) -C $(top_srcdir)/cpp/build/ -$(MAKEFLAGS) $(MAKECMDGOALS) - $(MAKE) -C $(top_srcdir)/cpp/examples/MinOZW/ -$(MAKEFLAGS) $(MAKECMDGOALS) + @$(MAKE) -C $(top_srcdir)/cpp/build/ -$(MAKEFLAGS) $(MAKECMDGOALS) + @$(MAKE) -C $(top_srcdir)/cpp/examples/MinOZW/ -$(MAKEFLAGS) $(MAKECMDGOALS) clean: - $(MAKE) -C $(top_srcdir)/cpp/build/ -$(MAKEFLAGS) $(MAKECMDGOALS) - $(MAKE) -C $(top_srcdir)/cpp/examples/MinOZW/ -$(MAKEFLAGS) $(MAKECMDGOALS) - $(MAKE) -C $(top_srcdir)/cpp/test/ -$(MAKEFLAGS) $(MAKECMDGOALS) + @$(MAKE) -C $(top_srcdir)/cpp/build/ -$(MAKEFLAGS) $(MAKECMDGOALS) + @$(MAKE) -C $(top_srcdir)/cpp/examples/MinOZW/ -$(MAKEFLAGS) $(MAKECMDGOALS) + @$(MAKE) -C $(top_srcdir)/cpp/test/ -$(MAKEFLAGS) $(MAKECMDGOALS) + +updateIndexDefines: + @$(MAKE) -C $(top_srcdir)/cpp/build -$(MAKEFLAGS) $(MAKECMDGOALS) test: - $(MAKE) -C $(top_srcdir)/cpp/test/ -$(MAKEFLAGS) $(MAKECMDGOALS) + @$(MAKE) -C $(top_srcdir)/cpp/test/ -$(MAKEFLAGS) $(MAKECMDGOALS) cpp/src/vers.cpp: - LDFLAGS="$(LDFLAGS)" CPPFLAGS="$(CPPFLAGS)" $(MAKE) -C $(top_srcdir)/cpp/build/ -$(MAKEFLAGS) $(top_srcdir)/cpp/src/vers.cpp + @LDFLAGS="$(LDFLAGS)" CPPFLAGS="$(CPPFLAGS)" $(MAKE) -C $(top_srcdir)/cpp/build/ -$(MAKEFLAGS) $(top_srcdir)/cpp/src/vers.cpp check: xmltest @@ -52,6 +55,7 @@ xmltest: $(XMLLINT) @$(XMLLINT) --noout --schema $(top_srcdir)/config/manufacturer_specific.xsd $(top_srcdir)/config/manufacturer_specific.xml @$(XMLLINT) --noout --schema $(top_srcdir)/config/Localization.xsd $(top_srcdir)/config/Localization.xml @$(XMLLINT) --noout --schema $(top_srcdir)/config/NotificationCCTypes.xsd $(top_srcdir)/config/NotificationCCTypes.xml + @$(XMLLINT) --noout --schema $(top_srcdir)/config/SensorMultiLevelCCTypes.xsd $(top_srcdir)/config/SensorMultiLevelCCTypes.xml @$(XMLLINT) --noout --schema $(top_srcdir)/config/device_configuration.xsd $(top_srcdir)/config/*/*.xml -@cpp/build/testconfig.pl endif diff --git a/README.md b/README.md index 2ce75a5cdc..7134a7e9eb 100644 --- a/README.md +++ b/README.md @@ -1,58 +1,118 @@ ![Open-ZWave Library](https://github.com/OpenZWave/open-zwave-web/raw/master/gfx/OZW_SF.png) ================== -Our goal is to create free software library that interfaces with selected Z-Wave PC controllers, allowing anyone to create applications that manipulate and respond to devices on a Z-Wave network, without requiring in-depth knowledge of the Z-Wave protocol. +*Last Updated: 4 October 2019* + +Our goal is to create free software library that interfaces with Z-Wave controllers, allowing anyone to create applications to control devices on a Z-Wave network, without requiring in-depth knowledge of the Z-Wave protocol. OpenZWave is not about creating Z-Wave devices (nodes). The project consists of the main library, written in C++ and wrappers and supporting projects, to interface different languages and protocol(s). This software is currently aimed at Application Developers who wish to incorporate Z-Wave functionality into their applications. -Our Homepage is at http://www.openzwave.net/ and our Github Page is located at https://github.com/OpenZWave/. If you wish to participate on our Mailing List, please visit https://groups.google.com/forum/#!forum/openzwave +Our Homepage is at [http://www.openzwave.net](http://www.openzwave.net/) and our Github Organization is located at [https://github.com/OpenZWave/](https://github.com/OpenZWave/). There are several repositories at that location. This is the README of the main project (often called "the library" or "OpenZWave" or "open-zwave"), located at [https://github.com/OpenZWave/open-zwave](https://github.com/OpenZWave/open-zwave). + +The current version of the main library is called OpenZWave 1.6, it is the *master* branch of the open-zwave repository and tagged "1.6". The previous version was 1.4 (same branch name and tag), and 1.5 was a development branch. The older versions are no longer maintained. The Dev branch is experimental and is not recommend unless someone specifically asks you to try it. + +OpenZWave 1.6 was released on March the 5th, 2019, when the Dev branch was merged into master and the 1.6 tag was created. The [OpenZWave Wiki 1.6 Release Notes](https://github.com/OpenZWave/open-zwave/wiki/OpenZWave-1.6-Release-Notes) summarizes changes. ## Getting Started -There is a example application on how to interface with the library called MinOZW. This currently offers a minimal example on how to monitor for changes and enable Polling of values. There are also plenty of other examples on the Internet that you can research. + +There is an example application based on the library, it is called MinOZW and it is part of the [open-zwave repository](https://github.com/OpenZWave/open-zwave). This currently offers a minimal example. There are also plenty of other examples on the Internet that you can research. + +On Linux, macOS, BSD run "make" to build the library and MinOZW. Optionally, run "make install" to install the library, header and config files system-wide. Run "BUILD=DEBUG make" to make a debug build. + +Online [Developers documentation](http://www.openzwave.com/dev/) is generated from source comments by Doxygen. If you do "make install" and have Doxygen on your system, a description of the api will be in open-zwave/docs/api/html/index.html + +On Windows, install "Visual Studio" then open "open-zwave/cpp/build/windows/vs2010/OpenZWave.sln" to build the library or "open-zwave/cpp/examples/windows/MinOZW/vs2010/MinOZW.sln" to build both library and sample application. ## Getting Help -If you are using a Application that uses OZW, you should first check with the Application Developers for support. As OZW is a library used by dozens of large opensource home automation applications, we can not support application related issues here. If your application developer indicates the problem may be with OZW, please follow the guidelines below. -First thing you should do if you are running into troubles is search our [mailing list](https://groups.google.com/forum/#!forum/openzwave). There is a high chance that your problem may have already been discussed on the list. -If you're still having problems, you should Generate a Log file and upload your Log to the [Log Analyzer on our homepage](http://www.openzwave.com/log-analyzer), which will check for common issues, and provide some basic recommendations. Please follow the instructions on that page to ensure your log file contains the relevant information. +If you are using a Application based on OpenZWave, and you have an issue, you should check: -If you think you have found a bug, please see the next section. +1. If you are an end user, check the Forum and Issue Tracker of your product based on OpenZWave. As this is a library used by dozens of large open source home automation applications, we can not support application related issues here. +2. The [OpenZWave Mailing List](https://groups.google.com/forum/#!forum/openzwave) for general discussion of issues and contacting peers and developers. +3. The [OpenZWave Wiki](https://github.com/OpenZWave/open-zwave/wiki) for main library information. +4. The Issue Tracker of the sub-project, for example the [Zwave2Mqtt Issue Tracker](https://github.com/OpenZWave/Zwave2Mqtt/issues) +5. The [OpenZWave Issue Tracker](https://github.com/OpenZWave/open-zwave/issues) for main library issues and "things being worked on". See "Opening or Contributing to an Issue on Github" if you think the problem is related to the OpenZWave main library. -For General Questions/How Do I etc, please post a message to our [mailing list](https://groups.google.com/forum/#!forum/openzwave) +## Opening or Contributing to an Issue on Github + +Please check *both closed and open Issues* before reporting. If you're still having problems, you should generate a (debug) log file and upload that to the [OpenZWave Log Analyzer on our homepage](http://www.openzwave.com/log-analyzer), which will check for common issues, and provide some basic recommendations. Please follow the instructions on that page to ensure your log file contains the relevant information. + +If you think you have found a bug, ZIP the OZW_log.txt and your ozwcache*xml file and "drag and drop" the resulting archive on the github issue or comment you create on GitHub. Please do not paste as text. + +Please always provide an OZW_Log.txt file. Z-Wave is a reasonably complex protocol, and thus, it is almost always necessary for us to review that log file to understand what is going on. ## Language Wrappers -A number of members of the community have developed wrappers for OpenZWave for other languages. Those actively maintained wrappers can be found at the OpenZWave Organisation page at https://github.com/OpenZWave -If you have developed a wrapper for another language, and would like to publish it under the OpenZWave organisation (and gain access to things like CI, Distribution Build Servers etc) please contact Fishwaldo on our mailing list. +A number of members of the community have developed wrappers for OpenZWave for other languages. Those actively maintained wrappers can be found at the [OpenZWave Github Organization](https://github.com/OpenZWave) + +If you have developed a wrapper for another language, and would like to publish it under the OpenZWave Organization (and gain access to things like CI, Distribution Build Servers etc) please contact Fishwaldo on our mailing list. + +## Device Database and Supporting New Devices + +If your device is not recognized by OpenZWave, it should still work as long as its compliant with the Z-Wave specifications. Our Device database is mainly based on community contributions, so please consult the [wiki page on Adding Devices](https://github.com/OpenZWave/open-zwave/wiki/Adding-Devices) on how to add the Device to the manufacturer_specific.xml file and generate a Configuration xml file for it. + +When OpenZWave 1.6 starts, it checks the version of several related files configuration files and downloads the latest revision. This behavior can be changed by changing the AutoUpdateConfigFile configuration in options.xml. Config options are explained on the [wiki page on Config-Options](https://github.com/OpenZWave/open-zwave/wiki/Config-Options) -## Opening or Contributing to a Issue on Github -Z-Wave is a reasonably complex protocol, and thus, it almost always necessary for us to review a OZW Log file to determine what’s going on. As GitHub does not support attachments on Issues, please upload a [LogFile](http://www.openzwave.com/log-analyzer) and then create a issue on [GitHub](https://github.com/OpenZWave/open-zwave/issues). Please include a link to the LogFile Scan results (check the "Public Results" button on the results page and copy the URL it links to). -Not uploading a Log file will often mean that we are unable to provide any further help without seeing what’s going on, so please ensure you do this. +You can have a look at the current device database for OpenZWave 1.6 by browsing to the [Online Device Database](http://openzwave.com/device-database) -## Supporting New Devices -If your device is not recognized by OZW, it should still work as long as its compliant with the Z-Wave specifications. Our Device database is mainly community contributions, so please consult [this page](https://github.com/OpenZWave/open-zwave/wiki/Adding-Devices) on how to add the Device to the manufacturer_specific.xml file and generate a Configuration file for it. +Please note device configuration files for 1.6 and 1.4 are different. If your application is based on OpenZWave version 1.4, the older database is still available but unmaintained at: [OpenZWave 1.4 branch, config folder](https://github.com/OpenZWave/open-zwave/tree/1.4/config) -## Contributing to OZW -We are happy to accept Pull Requests via GitHub. A few things to follow when preparing a Pull Request. +## Contributing to OpenZWave -1. If you have added or changed any of the configuration files (eg, adding a new device) please run "make xmltest" from the root directory to ensure your XML is well formed. -2. Please add a entry to the ChangeLog describing the change you made. -3. If you are changing some internal code paths in OZW, please discuss on the mailing list prior to starting your work. Z-Wave is complex and there are lots of corner cases as far as proper support of the various (non-standard) devices out there. While it might sometimes seem overcomplicated, it most likely is there for a reason. -4. Finally, if you have signed a NDA with Sigma Designs, we are unable to accept your changes. OZW is developed by reverse engineering and consulting publically available information. We have not signed a NDA with Sigma, and do not want users to infringe upon their agreement with Sigma either. +We are happy to accept Pull Requests via GitHub. A few things to follow when preparing a Pull Request. -## Final Words -As of Sept, 2016, Sigma has released a large portion (not all) of the Z-Wave Protocol Specifications into the public domain. Prior to Sept, 2016, OpenZWave was developed by mainly reverse engineering the protocol as well as consulting various public information on the Internet. +1. If you have added or changed any of the configuration files (eg, adding a new device) please run "make xmltest" from the root directory to ensure your XML is well formed. Also run "make dist-update" if you have added files. +2. Please add a entry to the ChangeLog describing the change you made. +3. If you want to change OpenZWave code, please discuss your plan through the Mailing List or on Github *prior to starting your work*. Z-Wave is complex and there are lots of corner cases as far as proper support of the various (non-standard) devices out there. While it might sometimes seem (overly) complicated, it most likely is there for a reason. +4. Finally, if you have signed a NDA with Sigma Designs, and your proposed changes are covered by that NDA, we are unable to accept your changes. OZW is developed by reverse engineering and consulting publicly available information. We do not want users to infringe upon their agreements. The OpenZWave organization has not signed a NDA with Sigma. +5. Parts of the spec have been released as the [Public Z-Wave Specification](https://www.silabs.com/products/wireless/mesh-networking/z-wave/specification), and the radio protocol is know as [G.9959](https://www.itu.int/rec/T-REC-G.9959-201501-I/en). There may be more public resources, but please do check the terms and conditions of every part before posting for compatibility with "Open Source Software" -The Z-Wave Specifications can now be found at http://zwavepublic.com/ and we welcome contributions or -reviews of the specifications against our code base. +## Trivia -OpenZWave is a opensource program that is LGPL licensed. This does allow commercial applications to utilize the openzwave libary, but we ask that you support us by either contributing any changes back to the community, or consider a donation of Z-Wave hardware to the developers so we can continue to ensure openzwave works well with the z-wave ecosystem. (You should also be aware that of the Z-Wave restrictions about selling software that implements this public standard. Please consult Sigma, or the Z-Wave Alliance for further info) +Prior to Sept, 2016, OpenZWave was developed by mainly reverse engineering the protocol as well as consulting various public information on the Internet. -Of course, for Open Source applications, as long as you abide by our License (LGPL) we would love to welcome you the OZW community! +In September 2016, Sigma Designs released a large portion (not all) of the Z-Wave Protocol Specifications into the public domain. -And for those that are wondering, you cannot use OZW to create Z-Wave Nodes. This is not the goal of the library. We allow applications to talk to Z-Wave nodes on the network via a Z-Wave Controller. +On April 18, 2018, [Silabs acquired Sigma Design's Z-Wave business](https://news.silabs.com/2018-04-18-Silicon-Labs-Completes-Acquisition-of-Sigma-Designs-Z-Wave-Business), they now host the official [Z-Wave Support Resources](https://www.silabs.com/support/z-wave) + +In 2005 the [Z-Wave Alliance](https://z-wavealliance.org) was established. OpenZWave is an Affiliate Member of the Z-Wave Alliance.

-
-OpenZWave is a Affiliate Member of the Z-Wave Alliance +

+ +## License + +OpenZWave is an open source program that is LGPL licensed. This does allow commercial applications to utilize the OpenZWave library, but we ask that you support us by either contributing any changes back to the community, or consider a donation of Z-Wave hardware to the developers so we can continue to ensure openzwave works well with the z-wave ecosystem. (You should also be aware that of the Z-Wave restrictions about selling software that implements this public standard. Please consult the [Z-Wave Alliance](https://z-wavealliance.org) and [Z-Wave Support Resources](https://www.silabs.com/support/z-wave) for further info. + +Of course, for Open Source applications, as long as you abide by our License (LGPL) we would love to welcome you the OpenZWave community! + +## Contributors + +### Code Contributors + +This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)]. + + +### Financial Contributors + +Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/ozw/contribute)] + +#### Individuals + + + +#### Organizations + +Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/ozw/contribute)] + + + + + + + + + + + diff --git a/config/2gig/ct100.xml b/config/2gig/ct100.xml index ae4c3240fb..24973f45db 100644 --- a/config/2gig/ct100.xml +++ b/config/2gig/ct100.xml @@ -1,26 +1,26 @@ - + http://www.openzwave.com/device-database/0098:0106:6401 images/2gig/ct100.png https://products.z-wavealliance.org/products/795/ Australia / New Zealand / U.S. / Canada / Mexico - CT100-US Thermostat - ENERGY MANAGEMENT MADE EASY. - -The CT100 brings together everything you need to create an energy-intelligent home: remote control, seven-day programming, and seamless integration with the Go!Control panel. - -• Ultra Slim Form Factor -• Two Year Battery Life -• 4 Stage Heat, 2 Cool -• Bright Display with Touch Screen -• Improved Z-Wave Range -• Auto Mode -• Improved User Experience + CT100 Plus + The CT100 Plus is a sleek, modern thermostat design for home automation systems. It’s clean user interface compliments app-enabled systems. It features adjustable real-time alerts to enable cloud triggers, a robust data stream of HVAC information for cloud monitoring, and configurable comfort response settings to customize home control scenes. The CT100 Plus is compatible with all popular HVAC systems and is battery-operated without the need for a C-wire. CT100-US Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/782/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/795/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1798/xml + https://products.z-wavealliance.org/products/1798/ + Switch the thermostat to Off Mode. Press and hold the lower left corner of touch screen for five (5) seconds. The thermostat then resets itself, displays its current firmware version, and restarts in Off Mode. Use this procedure only in the event that the network primary controller is missing or otherwise inoperable. + CT100 + Same process as inclusion. Similarly, when you are trying to exclude from a network, the LINK icon disappears when the node has successfully excluded the network. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1798/CT100_Plus_UserGuide_20160504.pdf + U.S. / Canada / Mexico + When included into a Z-Wave network on battery power, this device is a FLiRS device. The Thermostat will wake up for communication when it receives a valid Z-Wave beam. + From the CT100’s Menu screen, touch MATE under the radio icon. The Network Include screen displays a large r1. Touch MATE again. This initiates the network inclusion process. The MATE icon and the status indicator LEDs will blink. When the CT100 has successfully included into a Z-Wave network, the +MATE icon is replaced by the LINK icon under the radio tower. diff --git a/config/BeNext/AlarmSound.xml b/config/BeNext/AlarmSound.xml index a2770dc4b4..c18786f0eb 100644 --- a/config/BeNext/AlarmSound.xml +++ b/config/BeNext/AlarmSound.xml @@ -74,10 +74,6 @@ Use the Alarm Sound in combination with the Door Sensor or MoLite Sensor to aler - - - - Default value : 99 @@ -144,10 +140,6 @@ Use the Alarm Sound in combination with the Door Sensor or MoLite Sensor to aler Default value : 0 - - - - Default value : 99 @@ -215,10 +207,6 @@ Use the Alarm Sound in combination with the Door Sensor or MoLite Sensor to aler - - - - Default value : 99 @@ -286,10 +274,6 @@ Use the Alarm Sound in combination with the Door Sensor or MoLite Sensor to aler - - - - Default value : 99 @@ -357,10 +341,6 @@ Use the Alarm Sound in combination with the Door Sensor or MoLite Sensor to aler - - - - Default value : 99 @@ -428,10 +408,6 @@ Use the Alarm Sound in combination with the Door Sensor or MoLite Sensor to aler - - - - Default value : 99 diff --git a/config/BeNext/TagReader500.xml b/config/BeNext/TagReader500.xml index c8d121112a..36914619e2 100644 --- a/config/BeNext/TagReader500.xml +++ b/config/BeNext/TagReader500.xml @@ -1,4 +1,28 @@ - + + + http://www.openzwave.com/device-database/008A:0200:0007 + images/BeNext/TagReader500.png + https://products.z-wavealliance.org/products/2478/ + Tag Reader 500 US + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2478/Quickstart_Technical Manual_Tag_Reader500_US_v_0_12.pdf + The Tag Reader 500 US has an option to reset it self to factory settings. Please use this procedure only when the network primary controller is missing or otherwise inoperable. + +To reset to factory settings please follow these steps: +1. Press the enter button for 2 seconds, release the enter button to start the remove routine (indication LED will blink 3 times every second). +2. During the remove routine press enter button 4 times within 1,5 seconds to reset the product. +3. If ‘back to factory settings’ was successful the indication LED will go in for 1 full second on the end of the remove routine. +4. A DEVICE_RESET_LOCALLY_NOTIFICATION is sent to the nodes associated in the lifeline group. + To include the Tag Reader 500 US press and hold the enter button for two seconds (indication LED blinks shortly). Release the enter button now to start the inclusion (during the inclusion routine the indication LED willblink twice per second). + To exclude the Tag Reader 500 US press and hold the enter button for two seconds (indication LED blinks shortly). Release the enter button now to start the exclusion (during the exclusion routine the indication LED willblink twice three times per 1,5 second). + Press and hold the button fpr 7 seconds, the indication LED will go on for 1 full second. + A Z-Wave security enabled entry control device. You can arm/disarm your house to home or away with the Tag Reader 500. With the use of a RFID tag or a numerical code the device can send an entry control message which can be handled by a supported gateway. In addition the Tag Reader supports the activation of scenes. + 80820702 + CEPT (Europe) / U.S. / Canada / Mexico + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1979/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2478/xml + + diff --git a/config/Localization.xml b/config/Localization.xml index a52df9dad4..e579507636 100644 --- a/config/Localization.xml +++ b/config/Localization.xml @@ -1,7 +1,9 @@ - + - + + + A Smoke Alarm Alert @@ -18,11 +20,11 @@ Unknown Event - Carbon Monoxied Alerts - + Carbon Monoxide Alerts + Clear - Carbon Monoxied Detected at Location - Carbon Monoxied Detected at Unknown Location + Carbon Monoxide Detected at Location + Carbon Monoxide Detected at Unknown Location Test Replacement Required (Unspecified) Replacement Required (End Of Life) @@ -31,11 +33,11 @@ Unknown Event - Carbon Dixoide Alerts - + Carbon Dioxide Alerts + Clear - Carbon Dixoide Detected at Location - Carbon Dixoide Detected at Unknown Location + Carbon Dioxide Detected at Location + Carbon Dioxide Detected at Unknown Location Test Replacement Required (Unspecified) Replacement Required (End Of Life) @@ -66,8 +68,8 @@ Clear Water Leak at Location Water Leak at Unknown Location - Water Level Droped at Location - Water Level Droped at Unnknown Location + Water Level Dropped at Location + Water Level Dropped at Unknown Location Replace Filter Water Flow Water Pressure @@ -87,7 +89,7 @@ Wireless Not Fully Locked Auto Lock Auto Lock Not Fully Locked - Lock Jamed + Lock Jammed All User Codes Deleted Single User Code Deleted New User Code Added @@ -107,10 +109,10 @@ Barrier Failed Operation Barrier Unattended Operation Disabled Barrier Malfunction - Barrier Vacaction Mode - Barrier Saftey Beam Obstruction + Barrier Vacation Mode + Barrier Safety Beam Obstruction Barrier Sensor Not Detected - Barrier Battery Low + Barrier Sensor Battery Low Barrier Short in Wall Station Wires Barrier Associated with Non ZWave Device Unknown Event @@ -122,7 +124,7 @@ Intrusion at Location Intrusion at Unknown Location Tampering - Cover Removed - Tamperting - Invalid Code + Tampering - Invalid Code Glass Breakage at Location Glass Breakage at UnknownLocation Motion Detected at Location @@ -140,7 +142,7 @@ Surge Detected Brownout Detected Over Current Detected - Over Voltage Voltage + Over Voltage Detected Over Load Detected Load Error Replace Battery Soon @@ -218,7 +220,7 @@ Lying On Bed Posture Changed Sitting On Edge Of Bed - Volatile Organic Level + Volatile Organic Compound Level Unknown Event @@ -267,8 +269,8 @@ Combustable Gas Detected at Unknown Location Toxic Gas Detected at Location Toxic Gas Detected Unknown Location - Test - Replacement Required (Unspecified) + Alarm Test + Replacement Required Unknown Event @@ -302,10 +304,9 @@ - User Codethat was used + User Code that was used - Progress of Operation @@ -358,7 +359,6 @@ The ID of the Valve Table that triggered this alert - Alarm Type Received Type d'alarme reçu @@ -534,7 +534,7 @@ - + @@ -584,7 +584,7 @@ - State of the Exterior Handle Control + State of the Interior Handle Control @@ -678,7 +678,78 @@ - + + Electric Kilowatt Hour Reading + + + + Electric Kilo Volt Amperes Hours Reading + + + + Electric Watts Reading + + + + Electric Pulses Reading + + + + Electric Volts Reading + + + + Electric Amps Reading + + + + Electric Power Factor Reading + + + + Electric Kilovolt-amperes Reactive Reading + + + + Electric Kilo Volt Amps Reactive Hours Reading + + + + Gas Cubic Meters Reading + + + + Gas Cubic Feet Reading + + + + Gas Pulses Reading + + + + Water Cubic Meters Reading + + + + Water Cubic Feet Reading + + + + Water US Gallons Reading + + + + Water Pulses Reading + + + + Heating kWh Reading + + + + Cooling kWh Reading + + @@ -812,17 +883,13 @@ - - Undefined Sensor State - - - Temperature Sensor Value - + Air Temperature Sensor Value + - General Sensor Value - + General Purpose Sensor Value + Luminance Sensor Value @@ -833,8 +900,8 @@ - Relative Humidity Sensor Value - + Humidity Sensor Value + Velocity Sensor Value @@ -881,8 +948,8 @@ - CO2 Level Sensor Value - + Carbon Dioxide Sensor Value + Air Flow Sensor Value @@ -913,39 +980,599 @@ - Binary Sensor Value - - - Seismic Intensity Sensor Value - + Seismic Magnitude Sensor Value - + - + Ultraviolet Sensor Value - + Electrical Resistivity Sensor Value - + Electrical Conductivity Sensor Value - + Loudness Sensor Value - + Moisture Sensor Value + + Frequency Sensor Value + + + + Time Sensor Value + + + + Target Temperature Sensor Value + + + + Particulate Mater 2.5 Sensor Value + + + + Formaldehyde CH20 Level Sensor Value + + + + Radon Concentration Sensor Value + + + + Methane Density Sensor Value + + + + Volatile Organic Compound Sensor Value + + + + Carbon Monoxide Sensor Value + + + + Soil Humidity Sensor Value + + + + Soil Reactivity Sensor Value + + + + Soil Salinity Sensor Value + + + + Heart Rate Sensor Value + + + + Blood Pressure Sensor Value + + + + Muscle Mass Sensor Value + + + + Fat Mass Sensor Value + + + + Bone Mass Sensor Value + + + + Total Body Water Sensor Value + + + + Basic Metabolic Rate Sensor Value + + + + Body Mass Index Sensor Value + + + + X-Axis Acceleration Sensor Value + + + + Y-Axis Acceleration Sensor Value + + + + Z-Axis Acceleration Sensor Value + + + + Smoke Density Sensor Value + + + + Water Flow Sensor Value + + + + Water Pressure Sensor Value + + + + RF Signal Strength Sensor Value + + + + Particulate Matter Sensor Value + + + + Respiratory Rate Sensor Value + + + + Relative Modulation Sensor Value + + + + Boiler Water Temperature Sensor Value + + + + Domestic Hot Water Temperature Sensor Value + + + + Outside Temperature Sensor Value + + + + Exhaust Temperature Sensor Value + + + + Water Chlorine Sensor Value + + + + Water Acidity Sensor Value + + + + Water Oxidation Reduction Potential Sensor Value + + + + Heart Rate LF/HF Ratio Sensor Value + + + + Motion Direction Sensor Value + + + + Applied Force Sensor Value + + + + Return Air Temperature Sensor Value + + + + Supply Air Temperature Sensor Value + + + + Condenser Coil Temperature Sensor Value + + + + Evaporator Coil Temperature Sensor Value + + + + Liquid Line Temperature Sensor Value + + + + Discharge Line Temperature Sensor Value + + + + Suction Sensor Value + + + + Discharge Sensor Value + + + + Defrost Temperature Sensor Value + + + + Ozone Sensor Value + + + + Sulfur Dioxide Sensor Value + + + + Nitrogen Dioxide Sensor Value + + + + Ammonia Sensor Value + + + + Lead Sensor Value + + + + Particulate Matter Sensor Value + + + + Air Temperature Sensor Available Units + + + + General Purpose Sensor Available Units + + + + Luminance Sensor Available Units + + + + Power Sensor Available Units + + + + Humidity Sensor Available Units + + + + Velocity Sensor Available Units + + + + Direction Sensor Available Units + + + + Atmospheric Pressure Sensor Available Units + + + + Barometric Pressure Sensor Available Units + + + + Solar Radiation Sensor Available Units + + + + Dew Point Sensor Available Units + + + + Rain Rate Sensor Available Units + + + + Tide Level Sensor Available Units + + + + Weight Sensor Available Units + + + + Voltage Sensor Available Units + + + + Current Sensor Available Units + + + + Carbon Dioxide Sensor Available Units + + + + Air Flow Sensor Available Units + + + + Tank Capacity Sensor Available Units + + + + Distance Sensor Available Units + + + + Angle Position Sensor Available Units + + + + Rotation Sensor Available Units + + + + Water Temperature Sensor Available Units + + + + Soil Temperature Sensor Available Units + + + + Seismic Intensity Sensor Available Units + + + + Seismic Magnitude Sensor Available Units + + + + Ultraviolet Sensor Available Units + + + + Electrical Resistivity Sensor Available Units + + + + Electrical Conductivity Sensor Available Units + + + + Loudness Sensor Available Units + + + + Moisture Sensor Available Units + + + + Frequency Sensor Available Units + + + + Time Sensor Available Units + + + + Target Temperature Sensor Available Units + + + + Particulate Mater 2.5 Sensor Available Units + + + + Formaldehyde CH20 Level Sensor Available Units + + + + Radon Concentration Sensor Available Units + + + + Methane Density Sensor Available Units + + + + Volatile Organic Compound Sensor Available Units + + + + Carbon Monoxide Sensor Available Units + + + + Soil Humidity Sensor Available Units + + + + Soil Reactivity Sensor Available Units + + + + Soil Salinity Sensor Available Units + + + + Heart Rate Sensor Available Units + + + + Blood Pressure Sensor Available Units + + + + Muscle Mass Sensor Available Units + + + + Fat Mass Sensor Available Units + + + + Bone Mass Sensor Available Units + + + + Total Body Water Sensor Available Units + + + + Basic Metabolic Rate Sensor Available Units + + + + Body Mass Index Sensor Available Units + + + + X-Axis Acceleration Sensor Available Units + + + + Y-Axis Acceleration Sensor Available Units + + + + Z-Axis Acceleration Sensor Available Units + + + + Smoke Density Sensor Available Units + + + + Water Flow Sensor Available Units + + + + Water Pressure Sensor Available Units + + + + RF Signal Strength Sensor Available Units + + + + Particulate Matter Sensor Available Units + + + + Respiratory Rate Sensor Available Units + + + + Relative Modulation Sensor Available Units + + + + Boiler Water Temperature Sensor Available Units + + + + Domestic Hot Water Temperature Sensor Available Units + + + + Outside Temperature Sensor Available Units + + + + Exhaust Temperature Sensor Available Units + + + + Water Chlorine Sensor Available Units + + + + Water Acidity Sensor Available Units + + + + Water Oxidation Reduction Potential Sensor Available Units + + + + Heart Rate LF/HF Ratio Sensor Available Units + + + + Motion Direction Sensor Available Units + + + + Applied Force Sensor Available Units + + + + Return Air Temperature Sensor Available Units + + + + Supply Air Temperature Sensor Available Units + + + + Condenser Coil Temperature Sensor Available Units + + + + Evaporator Coil Temperature Sensor Available Units + + + + Liquid Line Temperature Sensor Available Units + + + + Discharge Line Temperature Sensor Available Units + + + + Suction Sensor Available Units + + + + Discharge Sensor Available Units + + + + Defrost Temperature Sensor Available Units + + + + Ozone Sensor Available Units + + + + Sulfur Dioxide Sensor Available Units + + + + Nitrogen Dioxide Sensor Available Units + + + + Ammonia Sensor Available Units + + + + Lead Sensor Available Units + + + + Particulate Matter Sensor Available Units + + - + The Number of Available Tones on the Node @@ -963,7 +1590,6 @@ The default tone to play when none is specified in a Play Command - @@ -1002,7 +1628,7 @@ - Ignore the Start Level of the Device when increasing/descreasing brightness + Ignore the Start Level of the Device when increasing/decreasing brightness @@ -2194,7 +2820,7 @@ - The Raw UserCode as specified at the Postition in Raw UserCode Index + The Raw UserCode as specified at the Position in Raw UserCode Index diff --git a/config/NotificationCCTypes.xml b/config/NotificationCCTypes.xml index de8e4edbbc..61546ad257 100644 --- a/config/NotificationCCTypes.xml +++ b/config/NotificationCCTypes.xml @@ -1,6 +1,8 @@ - - + + + + @@ -26,14 +28,14 @@ - + - + - + @@ -47,20 +49,20 @@ - + - + - + - + @@ -74,7 +76,7 @@ - + @@ -122,10 +124,10 @@ - + - + @@ -175,7 +177,7 @@ - + @@ -220,13 +222,13 @@ - + - + @@ -257,7 +259,7 @@ - + @@ -291,7 +293,7 @@ - + @@ -430,7 +432,7 @@ - + @@ -468,7 +470,7 @@ - + @@ -527,7 +529,7 @@ - + @@ -540,9 +542,9 @@ - + - + diff --git a/config/SensorMultiLevelCCTypes.xml b/config/SensorMultiLevelCCTypes.xml new file mode 100644 index 0000000000..63d365b63c --- /dev/null +++ b/config/SensorMultiLevelCCTypes.xml @@ -0,0 +1,318 @@ + + + + C + F + + + % + + + + + % + Lux + + + Watt + Btu/h + + + % + g/m3 + + + m/s + Mph + + + ° + + + kPa + inHg + + + kPa + inHg + + + W/m2 + + + C + F + + + mm/h + in/h + + + m + ft + + + Kg + lb + + + V + mV + + + A + mA + + + Ppm + + + M3/h + cfm + + + l + M3 + gal + + + m + cm + ft + + + % + + + + + rpm + Hz + + + C + F + + + C + F + + + MM + EMS + Liedu + Shindo + + + Ml + Mw + Ms + Mb + + + UV + + + Ωm + + + S⋅m-1 + + + dB + dBA + + + % + M3/m3 + + aw + + + Hz + kHz + + + s + + + C + F + + + mol/m3 + μg/m3 + + + mol/m3 + + + bq/m3 + pCi/L + + + mol/m3 + + + mol/m3 + Ppm + + + mol/m3 + Ppm + + + % + + + pH + + + mol/m3 + + + Bpm + + + mmHg + mmHg + + + Kg + + + Kg + + + Kg + + + Kg + + + J + + + BMI + + + m/s2 + + + m/s2 + + + m/s2 + + + % + + + l/h + + + kPa + + + RSSI + dBm + + + mol/m3 + μg/m3 + + + Bpm + + + % + + + C + F + + + C + F + + + C + F + + + C + F + + + mg/l + + + pH + + + mV + + + + + + degrees + + + N + + + C + F + + + C + F + + + C + F + + + C + F + + + C + F + + + C + F + + + kPa + psi + + + kPa + psi + + + C + F + + + μg/m3 + + + μg/m3 + + + μg/m3 + + + μg/m3 + + + μg/m3 + + + μg/m3 + + diff --git a/config/SensorMultiLevelCCTypes.xsd b/config/SensorMultiLevelCCTypes.xsd new file mode 100644 index 0000000000..cc284f9445 --- /dev/null +++ b/config/SensorMultiLevelCCTypes.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/config/aeotec/dsa03202.xml b/config/aeotec/dsa03202.xml index 452bcf5e10..05524833c5 100644 --- a/config/aeotec/dsa03202.xml +++ b/config/aeotec/dsa03202.xml @@ -1,4 +1,5 @@ - + http://www.openzwave.com/device-database/0086:0003:0001 images/aeotec/dsa03202.png @@ -14,6 +15,7 @@ Although simplicity and user experience is the primary focus, the full range of Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/142/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/143/xml + Added GetSupported false and add 3rd option to parameter 250 to work around this limitation + - + + false + + Default Mode 0 The button on the Minimote uses the factory default functions for operation instead of any special functionality related to the below modes. Scene Mode 1 The button on the Minimote executes a scene from data received for Parameters Numbers 0-239 related to the button being pressed. Add Mode 2 The button on the Minimote is able to include/add devices into the Z-Wave network. Remove Mode 3 The button on the Minimote is able to remove devices from the Z-Wave network. Association Mode 4 The button on the Minimote is able to associate one device to another. Learn Mode 5 The button on the Minimote is able to allow the Minimote to be included into other Z-Wave networks and to learn Z-Wave network information. @@ -33,7 +39,7 @@ https://aeotec.freshdesk.com/helpdesk/attachments/6009584532 - + @@ -41,7 +47,7 @@ https://aeotec.freshdesk.com/helpdesk/attachments/6009584532 - + @@ -49,7 +55,7 @@ https://aeotec.freshdesk.com/helpdesk/attachments/6009584532 - + @@ -57,12 +63,16 @@ https://aeotec.freshdesk.com/helpdesk/attachments/6009584532 - + - Enable selective Group Mode or Scene Mode when Button is in Use. + Enable selective Group Mode or Scene Mode. Long press learn button to wake up device. + Option As-Last-Set is not a real option, it exists because the Minimote does not report back its actual setting. + When long-pressing a button, if RED + BLUE LED turn on/off at the same time, device is in scene mode. + If the BLUE LED starts blinking, it is in group mode. NOTE: Minimote firmware 1.17 or higher is required, firmware 1.19 is highly recommended. + @@ -76,6 +86,9 @@ https://aeotec.freshdesk.com/helpdesk/attachments/6009584532 + + false + diff --git a/config/aeotec/dsc14104.xml b/config/aeotec/dsc14104.xml index 30e7560a62..4389eb1d54 100644 --- a/config/aeotec/dsc14104.xml +++ b/config/aeotec/dsc14104.xml @@ -1,64 +1,73 @@ - - - - + Motor start delay time (ms) - + Total time from endpoint of close go to endpoint of opening (ms). This value set 0x00000000, will use the time of last calibration. Default 5 seconds - + Total time from endpoint of opening go to endpoint of close (ms). This value set 0x00000000, will use the time of last calibration. Default 5 seconds - - + + Motor status after power on - - + + Set count of External Button/Switch Note: Single External Button must connect to ST and COM port. - - + + Enable automatic notifications to associated group Reports devices whenever there is a state change - - - - - + + + + + Set External Switch/Button Control mode - - - - + + + + Device tag. - + Reset to the default configuration. - - + - + - diff --git a/config/aeotec/dsc35103.xml b/config/aeotec/dsc35103.xml index fb785555c1..8ef1ae81ad 100644 --- a/config/aeotec/dsc35103.xml +++ b/config/aeotec/dsc35103.xml @@ -1,47 +1,55 @@ - - +--> + + http://www.openzwave.com/device-database/0086:0011:0003 + images/aeotec/dsc35103.png + https://products.z-wavealliance.org/products/1622/ + Micro Double Smart Switch + Aeon Labs Micro Double Smart Switch DSC17103 ZWUS + U.S. / Canada / Mexico + DSC17103 ZWUS + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1622/xml + + - + This is actually a double byte value. The LSB defines the total time the device needs to blink in seconds. The MSB defines the on/off interval of the blink in tenths of seconds. - + Enables automatic notifications to associated devices whenever there is a state change. - - - + + + - + Set External Switch/Button Control mode - - - + + + - + Device tag. - + Reset to the default configuration. - - + - diff --git a/config/aeotec/zw056.xml b/config/aeotec/zw056.xml index 6e76b333e7..063d71474c 100644 --- a/config/aeotec/zw056.xml +++ b/config/aeotec/zw056.xml @@ -1,7 +1,7 @@ +--> http://www.openzwave.com/device-database/0086:0038:0104 images/aeotec/zw056.png @@ -18,10 +18,18 @@ By taking advantage of the Z-Wave mesh network, commands can be routed to their Also a tool that can be programmed, scheduled, controlled and communicated with from anywhere in the world. ZW056-A U.S. / Canada / Mexico - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1307/Doorbell manual(20150604).pdf + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1583/Aeon Labs Doorbell Gen5 manual.pdf Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1307/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1581/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1583/xml + https://products.z-wavealliance.org/products/1581/ + ZW056-B + Australia / New Zealand + https://products.z-wavealliance.org/products/1583/ + ZW056-C + CEPT (Europe) diff --git a/config/aeotec/zw095.xml b/config/aeotec/zw095.xml index 9235d3afd6..6934b2bfcf 100644 --- a/config/aeotec/zw095.xml +++ b/config/aeotec/zw095.xml @@ -1,7 +1,7 @@ +--> http://www.openzwave.com/device-database/0086:005F:0102 images/aeotec/zw095.png @@ -15,11 +15,16 @@ Products that are Z-Wave certified can be used and communicate with other Z-Wave ZW095-A N/A Turn the primary controller of Z-Wave network into exclusion mode, short press the product’s Action button that you can find on the product's housing. - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1289/Instructions manual for Aeon Labs Home Energy Meter Gen5.pdf + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2046/Home Energy Meter Gen5 manual.pdf Home Energy Meter Gen5 Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1289/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1596/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2046/xml + https://products.z-wavealliance.org/products/2046/ + CEPT (Europe) + ZW095-C diff --git a/config/aeotec/zw096.xml b/config/aeotec/zw096.xml index d1eaee70cd..5320115db3 100644 --- a/config/aeotec/zw096.xml +++ b/config/aeotec/zw096.xml @@ -1,16 +1,16 @@ - + http://www.openzwave.com/device-database/0086:0060:0103 images/aeotec/zw096.png - https://products.z-wavealliance.org/products/1312/ + https://products.z-wavealliance.org/products/3093/ Smart Switch 6 N/A - Press and hold the Action button that you can find on the product's housing for 20 seconds and then release. This procedure should only be used when the primary controller is missing or inoperable. + Press and hold the Action button that you can find on the product's housing for 20 seconds and then release. This procedure should only be used when the primary controller is inoperable. Aeotec Smart Switch 6 is a low-cost Z-Wave Switch plug-in module specifically used to enable Z-Wave command and control (on/off) of any plug-in tool. It can report immediate wattage consumption or kWh energy usage over a period of time. In the event of power failure, non-volatile memory retains all programmed information relating to the unit’s operating status. Its surface has a Smart RGB LED, which can be used for indicating the output load status or strength of the wireless signal. You can configure its indication colour according to your favour. -The Smart Switch 6 is also a security Z-wave device and supports Over The Air (OTA) feature for the products firmware upgrade. +The Plug is also a security Z-wave device and supports Over The Air (OTA) feature for the products firmware upgrade. - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1425/Aeon Labs Smart Switch 6 manual (2) .pdf + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3119/Instructions - Aeon Labs Smart Switch 6 (2).pdf Turn the primary controller of Z-Wave network into inclusion mode, short press the product’s Action button that you can find on the product's housing. U.S. / Canada / Mexico Turn the primary controller of Z-Wave network into exclusion mode, short press the product’s Action button that you can find on the product's housing. @@ -19,11 +19,14 @@ The Smart Switch 6 is also a security Z-wave device and supports Over The Air (O Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1312/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1331/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1425/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3093/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3104/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3119/xml - https://products.z-wavealliance.org/products/1331/ + https://products.z-wavealliance.org/products/3119/ Australia / New Zealand ZW096-B09 - https://products.z-wavealliance.org/products/1425/ + https://products.z-wavealliance.org/products/3104/ CEPT (Europe) ZW096-C16 diff --git a/config/aeotec/zw098.xml b/config/aeotec/zw098.xml index 1076b1f066..5a59f3a91b 100644 --- a/config/aeotec/zw098.xml +++ b/config/aeotec/zw098.xml @@ -1,12 +1,12 @@ - + http://www.openzwave.com/device-database/0086:0062:0103 images/aeotec/zw098.png - https://products.z-wavealliance.org/products/1368/ + https://products.z-wavealliance.org/products/1829/ Aeotec LED Bulb is a low-cost Z-Wave LED module which allows control (on/off/dim) with the use of Z-Wave. It’s a bulb has a Smart RGB LED, which can be used to add colour to your home. The bulb has 5 main colour channels available for you to adjust: Red, Green, Blue, Warm White and Cold White. You can configure its colour according to your favour. -The LED Bulb is also a security Z-wave device and supports the Over The Air (OTA) feature for the product’s firmware upgrade. - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1380/Aeon Labs LED Bulb manual 2.pdf +The LED Bulb is also a security Z-Wave device and supports the Over The Air (OTA) feature for the product’s firmware upgrade. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1851/LED Bulb manual.pdf Turn the primary controller of Z-Wave network into exclusion mode, press the external switch of LED Bulb to turn off and then press the external switch again to turn on it, repeat the operation 3 times. ZW098-A52 U.S. / Canada / Mexico @@ -21,11 +21,15 @@ Use this procedure only in the event that your primary network controller is mis Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1368/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1379/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1380/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1594/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1829/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1844/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1851/xml - https://products.z-wavealliance.org/products/1379/ + https://products.z-wavealliance.org/products/1844/ Australia / New Zealand ZW098-B55 - https://products.z-wavealliance.org/products/1380/ + https://products.z-wavealliance.org/products/1851/ CEPT (Europe) ZW098-C55 diff --git a/config/aeotec/zw099.xml b/config/aeotec/zw099.xml index cdcec275d1..3b2f58d102 100644 --- a/config/aeotec/zw099.xml +++ b/config/aeotec/zw099.xml @@ -1,4 +1,28 @@ - + + + http://www.openzwave.com/device-database/0086:0063:0103 + images/aeotec/zw099.png + https://products.z-wavealliance.org/products/2246/ + Turn the primary controller of Z-Wave network into exclusion mode, short press the product’s Action button that you can find on the product's housing. + Turn the primary controller of Z-Wave network into inclusion mode, short press the product’s Action button that you can find on the product's housing. + ZW099-A02 + Smart Dimmer 6 + U.S. / Canada / Mexico + Press and hold the Action button that you can find on the product's housing for 20 seconds and then release. This procedure should only be used when the primary controller is inoperable. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2246/Aeon Labs Smart Dimmer 6 manual.pdf + Aeotec Smart Dimmer 6 is a low-cost Z-Wave Dimmer plug-in module specifically used to enable Z-Wave command and control (on/off/dim) of any plug-in tool. It can report immediate wattage consumption or kWh energy usage over a period of time. In the event of power failure, non-volatile memory retains all programmed information relating to the unit’s operating status. +Its surface has a Smart RGB LED, which can be used for indicating the output load status or strength of the wireless signal. You can configure its indication colour according to your favour. +The Smart Dimmer 6 is also a security Z-Wave device and supports Over The Air (OTA) feature for the products firmware upgrade. + + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1515/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1519/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2246/xml + + https://products.z-wavealliance.org/products/1519/ + ZW099-C16 + CEPT (Europe) + diff --git a/config/aeotec/zw100.xml b/config/aeotec/zw100.xml index 47a6025f40..03381caa11 100644 --- a/config/aeotec/zw100.xml +++ b/config/aeotec/zw100.xml @@ -2,29 +2,34 @@ Aeotec ZW100 MultiSensor 6 https://aeotec.freshdesk.com/helpdesk/attachments/6028954764 V1.10 + V1.11 (12/14/2017) ---> +--> http://www.openzwave.com/device-database/0086:0064:0102 images/aeotec/zw100.png - https://products.z-wavealliance.org/products/1390/ + https://products.z-wavealliance.org/products/2684/ U.S. / Canada / Mexico Pressing the Z-Wave button once will trigger sending the Wake up notification command. If press and hold the Z-Wave button for 3 seconds, the MultiSensor will wake up for 10 minutes. Turn the primary controller of Z-Wave network into inclusion mode, short press the product’s Z-Wave button that you can find in the back of the product. ZW100-A MultiSensor 6 Turn the primary controller of Z-Wave network into exclusion mode, short press the product’s Z-Wave button that you can find in back of the product. - Aeotec by Aeon Labs’ MultiSensor looks like a motion sensor and it acts like one too. But it’s also so much more. Installing this 1 piece of Z-Wave® technology is the same as installing 6 pieces of Z-Wave technology. Your home control network will immediately understand motion, temperature, humidity, light, Ultraviolet and Vibration readings wherever MultiSensor installed. Those intelligent readings will equate to intelligence automation. And intelligent automation will give you the perfect, smart home. + Aeotec MultiSensor 6 looks like a motion sensor and it acts like one too. But it’s also so much more. Installing this 1 piece of Z-Wave® technology is the same as installing 6 pieces of Z-Wave technology. Your home control network will immediately understand motion, temperature, humidity, light, Ultraviolet and Vibration readings wherever MultiSensor installed. Those intelligent readings will equate to intelligence automation. And intelligent automation will give you the perfect, smart home. Press and hold the Z-Wave button that you can find in back of the product for 20 seconds and then release. This procedure should only be used when the primary controller is inoperable. - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1404/Aeon Labs MultiSensor 6 manual.pdf + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2714/Aeon Labs MultiSensor 6 manual.pdf Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1390/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1403/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1404/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1810/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1812/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2684/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2695/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2714/xml - https://products.z-wavealliance.org/products/1403/ + https://products.z-wavealliance.org/products/2714/ ZW100-C CEPT (Europe) - https://products.z-wavealliance.org/products/1404/ + https://products.z-wavealliance.org/products/2695/ ZW100-B Australia / New Zealand diff --git a/config/aeotec/zw111.xml b/config/aeotec/zw111.xml index b0b583c43b..ee9bddcf47 100644 --- a/config/aeotec/zw111.xml +++ b/config/aeotec/zw111.xml @@ -1,30 +1,54 @@ - - - - - - Output Load will be turned off automatically after 30 seconds and if the current overrun 1.5A. - - - - - Output load will be closed after 30 seconds if the temperature inside the product exceeds 100C. - - - - - Configure the output load status after re-power on - - - - - - +--> + + http://www.openzwave.com/device-database/0086:006F:0103 + images/aeotec/zw111.png + https://products.z-wavealliance.org/products/2095/ + Press and hold the Action button that you can find on the product's housing for 20 seconds and then release. This procedure should only be used when the primary controller is inoperable. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2149/Aeon Labs Nano Dimmer manual.pdf + Aeotec Nano Dimmer is a Z-Wave Smart Dimmer specifically used to enable Z-Wave command and control (on/off/dim) of any wall switches. It can report immediate wattage consumption or kWh energy usage over a period of time. In the event of power failure, non-volatile memory retains all programmed information relating to the unit’s operating status. +It can connect to 2 external manual switches to control the load ON/OFF independently. Its surface has a pin socket, which can be used for connecting to the touch panel, so you can also use the touch panel to control the Nano Dimmer. +The Nano Dimmer is also a security Z-Wave plus device and supports Over The Air (OTA) feature for the products firmware upgrade. + Turn the primary controller of Z-Wave network into inclusion mode, short press the product’s Action button that you can find on the product's housing. + Turn the primary controller of Z-Wave network into exclusion mode, short press the product’s Action button that you can find on the product's housing. + Nano Dimmer + ZW111-A + U.S. / Canada / Mexico + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2095/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2135/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2149/xml + + https://products.z-wavealliance.org/products/2135/ + ZW111-C + CEPT (Europe) + https://products.z-wavealliance.org/products/2149/ + Australia / New Zealand + ZW111-B + + + + + Output Load will be turned off automatically after 30 seconds and if the current overrun 1.5A. + + + + + Output load will be closed after 30 seconds if the temperature inside the product exceeds 100C. + + + + + Configure the output load status after re-power on + + + + + + Enable/disable the IR sensor of WallSwipe. (LSB) Value 1. Value 1 = 0, disable the IR Sensor. @@ -36,135 +60,135 @@ https://aeotec.freshdesk.com/helpdesk/attachments/6048080397 Value 4 = 0, disable the scene control functionality for all wave actions. Value 4 = 1, enable the scene control functionality for all wave actions. - - - + + + Set the button color of WallSwipe. Value 1= Level. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the LED indication color of WallSwipe when the gesture action is UP. Value 1= Reserved. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the LED indication color of WallSwipe when the gesture action is Down. Value 1= Level. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the LED indication color of WallSwipe when the gesture action is Left. Value 1= Level. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the LED indication color of WallSwipe when the gesture action is Right. Value 1= Level. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the LED indication color of WallSwipe when it is in Night light state. Value 1= Level. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the sensitivity of WallSwipe. - - - To set which notification would be sent to the associated nodes in association group 1 when the state of output load is changed - - - - - - - - To set which notification would be sent to the associated nodes in association group 3 when using the external switch 1 to switch the loads - - - - - - To set which notification would be sent to the associated nodes in association group 4 when using the external switch 2 to switch the loads - - - - - - Configure the state of LED when it is in 3 modes below - - - - - - + + + To set which notification would be sent to the associated nodes in association group 1 when the state of output load is changed + + + + + + + + To set which notification would be sent to the associated nodes in association group 3 when using the external switch 1 to switch the loads + + + + + + To set which notification would be sent to the associated nodes in association group 4 when using the external switch 2 to switch the loads + + + + + + Configure the state of LED when it is in 3 modes below + + + + + + Value1: Hour of ON. Value2: Minute of ON. Value3: Hour of OFF. Value4: Minute of OFF. E.g. The default setting is the Night light mode is enabled at 12: 00 and disabled at 8:00 0x12000800. - - - State appointment + + + State appointment Set the ON time of output load. Value1 = 0, disable or = non zero, enable (day, bit0 - bit6 represent Mon to Sun). Value2 = ON (hour) Value3 = ON (minute) Value4 = ON (brightness level) - - - State appointment + + + State appointment Set the ON time of output load. Value1 = 0, disable or = non zero, enable (day, bit0 - bit6 represent Mon to Sun). Value2 = ON (hour) Value3 = ON (minute) Value4 = ON (brightness level) - - - Enables/disables parameter 91 and 92 - - - - - The value represents the minimum change in wattage for a Report to be sent (default 25 W) - - - The value represents the minimum percentage change in wattage for a Report to be sent (Default 5) - - - Set report types for groups 1, 2 and 3 to default. - - - + + + Enables/disables parameter 91 and 92 + + + + + The value represents the minimum change in wattage for a Report to be sent (default 25 W) + + + The value represents the minimum percentage change in wattage for a Report to be sent (Default 5) + + + Set report types for groups 1, 2 and 3 to default. + + + Defines the type of report sent for reporting group 1. 1 is meter report for voltage. 2 is meter report for current. @@ -179,9 +203,9 @@ https://aeotec.freshdesk.com/helpdesk/attachments/6048080397 bit 1 current bit 0 voltage - - - + + + Defines the type of report sent for reporting group 2. 1 is meter report for voltage. 2 is meter report for current. @@ -196,9 +220,9 @@ https://aeotec.freshdesk.com/helpdesk/attachments/6048080397 bit 1 current bit 0 voltage - - - + + + Defines the type of report sent for reporting group 3. 1 is meter report for voltage. 2 is meter report for current. @@ -213,81 +237,81 @@ https://aeotec.freshdesk.com/helpdesk/attachments/6048080397 bit 1 current bit 0 voltage - - - Set time interval for sending reports for groups 1, 2 and 3 to default. - - - Defines the time interval when the defined report for group 1 is sent. - - - Defines the time interval when the defined report for group 2 is sent. - - - Defines the time interval when the defined report for group 3 is sent. - - - When the mode is determined, this mode value will not be reset after exclusion - - - - - - - - When the mode is determined, this mode value will not be reset after exclusion - - - - - - - - Get the state of touch panel port - - - - - Set the control destination for external switch S1 - - - - - - Set the control destination for external switch S2 - - - - - - Set the default dimming rate - - - Get the current working mode - - - - - - Set the dimming principle - - - - - To get what type of load the Dimmer is connected to - - - - - - - Set the min brightness level that the load can reach to - - - Set the max brightness level that the load can reach to - - - + + + Set time interval for sending reports for groups 1, 2 and 3 to default. + + + Defines the time interval when the defined report for group 1 is sent. + + + Defines the time interval when the defined report for group 2 is sent. + + + Defines the time interval when the defined report for group 3 is sent. + + + When the mode is determined, this mode value will not be reset after exclusion + + + + + + + + When the mode is determined, this mode value will not be reset after exclusion + + + + + + + + Get the state of touch panel port + + + + + Set the control destination for external switch S1 + + + + + + Set the control destination for external switch S2 + + + + + + Set the default dimming rate + + + Get the current working mode + + + + + + Set the dimming principle + + + + + To get what type of load the Dimmer is connected to + + + + + + + Set the min brightness level that the load can reach to + + + Set the max brightness level that the load can reach to + + + Set the working way for S1/S2 when the Switch mode is 2 state switch mode. Bit 0 =0, S1 is a toggle switch. Bit 0 =1, S1 is an On/Off switch, the out load state and S1 switch state would be in sync when using S1 to control the output load. @@ -295,9 +319,9 @@ https://aeotec.freshdesk.com/helpdesk/attachments/6048080397 Bit 1 =1, S2 is an On/Off switch, the out load state and S2 switch state would be in sync when using S2 to control the output load. Bit 2- Bit 7, reserved. - - - + + + Set the function of S1/S2. Bit 0 = 0, the function of sending NIF is disabled. Bit 0 = 1, the function of sending NIF is enabled. @@ -309,32 +333,32 @@ https://aeotec.freshdesk.com/helpdesk/attachments/6048080397 Bit 7 = 0, the setting for Bit 0 -Bit 2 are ineffective. Bit 7 = 1, the setting for Bit 0 -Bit 2 are effective. - - - Set the recognition way of load - - - - - - Enable/disable Configuration Locked - - - - - Reset to factory defaults - - - - - - - - - - - - - - + + + Set the recognition way of load + + + + + + Enable/disable Configuration Locked + + + + + Reset to factory defaults + + + + + + + + + + + + + + diff --git a/config/aeotec/zw112.xml b/config/aeotec/zw112.xml index 43327b4699..a65bb5f886 100644 --- a/config/aeotec/zw112.xml +++ b/config/aeotec/zw112.xml @@ -1,5 +1,31 @@ - - + + + http://www.openzwave.com/device-database/0086:0070:0102 + images/aeotec/zw112.png + https://products.z-wavealliance.org/products/1611/ + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1616/Door Window Sensor 6 manual.pdf + Turn the primary controller into exclusion mode, short press the product’s Action Button that you can find in back of the product. + Press the Action Button once, which will trigger sending out the Wake up notification command, press and hold the Action Button for 3 seconds, which will toggle on/off the Sensor be waked up for 10 minutes. + U.S. / Canada / Mexico + Turn the primary controller into inclusion mode, short press the product’s Action Button that you can find in the back of the product. + Aeon Labs Door/ Window Sensor 6 is a smart Z-Wave sensor that can detect the status of door/window's open/close in real time. +It’s a security Z-Wave device that supports security encryption. Also it supports the “Over the Air Firmware Updating” that allows you wirelessly update its firmware if needs. +It can be included and operated in any Z-Wave network with other Z-Wave certified devices from manufacturers and/or other applications. + Door/ Window Sensor 6 + Press the Action Button once that you can find in the back of the product for 20 seconds and then release. This procedure should only be used when the primary controller is inoperable. + ZW112-A + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1611/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1615/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1616/xml + + https://products.z-wavealliance.org/products/1615/ + CEPT (Europe) + ZW112-C + https://products.z-wavealliance.org/products/1616/ + ZW112-B + Australia / New Zealand + diff --git a/config/aeotec/zw116.xml b/config/aeotec/zw116.xml index a20450aec0..6728ec4bae 100644 --- a/config/aeotec/zw116.xml +++ b/config/aeotec/zw116.xml @@ -1,29 +1,53 @@ - - - - - - Output load will be closed after 30 seconds if the current exceeds (US: 15.5A, AU or EU: 10.5A). - - - - - Output load will be closed after 30 seconds if the temperature inside the product exceeds 100C. - - - - - Configure the output load status after re-power on - - - - - - +--> + + http://www.openzwave.com/device-database/0086:0074:0103 + images/aeotec/zw116.png + https://products.z-wavealliance.org/products/2208/ + Turn the primary controller of Z-Wave network into inclusion mode, short press the product’s Action button that you can find on the product's housing. + Press and hold the Action button that you can find on the product's housing for 20 seconds and then release. This procedure should only be used when the primary controller is inoperable. + Nano Switch + ZW116-A + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2289/Nano Switch manual.pdf + Turn the primary controller of Z-Wave network into exclusion mode, short press the product’s Action button that you can find on the product's housing. + U.S. / Canada / Mexico + Aeotec Nano Switch is a Z-Wave Smart Switch specifically used to enable Z-Wave command and control (on/off) of any wall switches. It can report immediate wattage consumption or kWh energy usage over a period of time. In the event of power failure, non-volatile memory retains all programmed information relating to the unit’s operating status. +It can connect to 2 external manual switches to control the load ON/OFF independently. Its surface has a pin socket, which can be used for connecting to the touch panel, so you can also use the touch panel to control the Dual Nano Switch. +The Nano Switch is also a security Z-Wave device and supports Over The Air (OTA) feature for the products firmware upgrade. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2208/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2288/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2289/xml + + https://products.z-wavealliance.org/products/2288/ + ZW116-B + Australia / New Zealand + https://products.z-wavealliance.org/products/2289/ + ZW116-C + CEPT (Europe) + + + + + Output load will be closed after 30 seconds if the current exceeds (US: 15.5A, AU or EU: 10.5A). + + + + + Output load will be closed after 30 seconds if the temperature inside the product exceeds 100C. + + + + + Configure the output load status after re-power on + + + + + + Enable/disable the IR sensor of WallSwipe. (LSB) Value 1. Value 1 = 0, disable the IR Sensor. @@ -35,132 +59,132 @@ Product Type ID: EU=0x00, US=0x01, AU=0x02 CN=0x1D Value 4 = 0, disable the scene control functionality for all wave actions. Value 4 = 1, enable the scene control functionality for all wave actions. - - - + + + Set the button color of WallSwipe. Value 1= Level 1. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the LED indication color of WallSwipe when the gesture action is UP. Value 1= Reserved. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the LED indication color of WallSwipe when the gesture action is Down. Value 1= Reserved. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the LED indication color of WallSwipe when the gesture action is Left. Value 1= Reserved. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the LED indication color of WallSwipe when the gesture action is Right. Value 1= Reserved. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the LED indication color of WallSwipe when it is in Night light state. Value 1= Reserved. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the sensitivity of WallSwipe. - - - To set which notification would be sent to the associated nodes in association group 1 when the state of output load is changed - - - - - - - To set which notification would be sent to the associated nodes in association group 3 when using the external switch 1 to switch the loads - - - - - To set which notification would be sent to the associated nodes in association group 4 when using the external switch 2 to switch the loads - - - - - Configure the state of LED when it is in 3 modes below - - - - - - + + + To set which notification would be sent to the associated nodes in association group 1 when the state of output load is changed + + + + + + + To set which notification would be sent to the associated nodes in association group 3 when using the external switch 1 to switch the loads + + + + + To set which notification would be sent to the associated nodes in association group 4 when using the external switch 2 to switch the loads + + + + + Configure the state of LED when it is in 3 modes below + + + + + + Value1: Hour of ON. Value2: Minute of ON. Value3: Hour of OFF. Value4: Minute of OFF. E.g. The default setting is the Night light mode is enabled at 12: 00 and disabled at 8:00 0x12000800. - - - + + + Value1: 0= Disable / 1= Enable. Value2: Weekday (Bit 0-6 means Monday to Sunday). Value3: Hour of turning OFF. Value4: Minute of turning OFF E.g. The default setting 0x007F1200 - - - + + + Value1: 0= Disable / 1= Enable. Value2: Weekday (Bit 0-6 means Monday to Sunday). Value3: Hour of turning OFF. Value4: Minute of turning OFF E.g. The default setting 0x001707F00 - - - If this parameter is set to 1 (Enable), the parameter 101 - 103 should be set to 0. - - - - - The value represents the minimum change in wattage for a Report to be sent (default 25 W) - - - The value represents the minimum percentage change in wattage for a Report to be sent (Default 5) - - - Set report types for groups 1, 2 and 3 to default. - - - + + + If this parameter is set to 1 (Enable), the parameter 101 - 103 should be set to 0. + + + + + The value represents the minimum change in wattage for a Report to be sent (default 25 W) + + + The value represents the minimum percentage change in wattage for a Report to be sent (Default 5) + + + Set report types for groups 1, 2 and 3 to default. + + + Defines the type of report sent for reporting group 1. 1 is meter report for voltage. 2 is meter report for current. @@ -175,9 +199,9 @@ Product Type ID: EU=0x00, US=0x01, AU=0x02 CN=0x1D bit 1 watt bit 0 kWh - - - + + + Defines the type of report sent for reporting group 2. 1 is meter report for voltage. 2 is meter report for current. @@ -192,9 +216,9 @@ Product Type ID: EU=0x00, US=0x01, AU=0x02 CN=0x1D bit 1 watt bit 0 kWh - - - + + + Defines the type of report sent for reporting group 3. 1 is meter report for voltage. 2 is meter report for current. @@ -209,61 +233,61 @@ Product Type ID: EU=0x00, US=0x01, AU=0x02 CN=0x1D bit 1 watt bit 0 kWh - - - Set time interval for sending reports for groups 1, 2 and 3 to default. - - - Defines the time interval when the defined report for group 1 is sent. - - - Defines the time interval when the defined report for group 2 is sent. - - - Defines the time interval when the defined report for group 3 is sent. - - - When the switch mode of S1 is determined or identified or configured, this mode value will not be reset after exclusion - - - - - - - - When the switch mode of S2 is determined or identified or configured, this mode value will not be reset after exclusion - - - - - - - - Set the control destination for external switch S1 - - - - - - Set the control destination for external switch S2 - - - - - - Get the state of touch panel port - - - - - Set the working way for S1/S2 when the Switch mode is 3-way switch mode. - - - - - - - + + + Set time interval for sending reports for groups 1, 2 and 3 to default. + + + Defines the time interval when the defined report for group 1 is sent. + + + Defines the time interval when the defined report for group 2 is sent. + + + Defines the time interval when the defined report for group 3 is sent. + + + When the switch mode of S1 is determined or identified or configured, this mode value will not be reset after exclusion + + + + + + + + When the switch mode of S2 is determined or identified or configured, this mode value will not be reset after exclusion + + + + + + + + Set the control destination for external switch S1 + + + + + + Set the control destination for external switch S2 + + + + + + Get the state of touch panel port + + + + + Set the working way for S1/S2 when the Switch mode is 3-way switch mode. + + + + + + + Set the function of S1/S2. Bit 0 = 0, the function of sending NIF is disabled. Bit 0 = 1, the function of sending NIF is enabled. @@ -274,31 +298,31 @@ Product Type ID: EU=0x00, US=0x01, AU=0x02 CN=0x1D Bit 3 to Bit 6 are reserved. Bit 7 = 0, the setting for Bit 0 to Bit 2 are ineffective. Bit 7 = 1, the setting for Bit 0 to Bit 2 are effective. - - - Enable/disable the factory reset function of Action Button, external switches or WallSwipe. - - - - - Enable/disable Configuration Locked - - - - - Reset to factory defaults - - - - - - - - - - - - - - + + + Enable/disable the factory reset function of Action Button, external switches or WallSwipe. + + + + + Enable/disable Configuration Locked + + + + + Reset to factory defaults + + + + + + + + + + + + + + diff --git a/config/aeotec/zw117.xml b/config/aeotec/zw117.xml index 7cf33adb0e..260c4f789d 100644 --- a/config/aeotec/zw117.xml +++ b/config/aeotec/zw117.xml @@ -1,7 +1,33 @@ - +--> + + http://www.openzwave.com/device-database/0086:0075:0104 + images/aeotec/zw117.png + https://products.z-wavealliance.org/products/1966/ + U.S. / Canada / Mexico + Turn the primary controller of Z-Wave network into exclusion mode, press the Z-Wave Button on Range Extender 6. + Aeotec Range Extender is a Z-Wave mesh network repeater which can extend the range of communication between Z-Wave products and assist other devices to reach each other in your Z-Wave network. +The Range Extender can also communicate securely via AES 128 wireless Z-Wave commands and supports Over-The-Air (OTA) firmware upgrades. + + Range Extender 6 + Press and hold the Z-Wave Button for 20 seconds and then release it. +Use this procedure only in the event that your primary network controller is missing or inoperable. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1998/Range Extender 6 manual.pdf + ZW117-A01 + Turn the primary controller of Z-Wave network into inclusion mode, press the Z-Wave Button on Range Extender 6. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1966/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1994/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1998/xml + + https://products.z-wavealliance.org/products/1994/ + ZW117-B21 + Australia / New Zealand + https://products.z-wavealliance.org/products/1998/ + CEPT (Europe) + ZW117-C15 + diff --git a/config/aeotec/zw120.xml b/config/aeotec/zw120.xml index 8c0ea9f74c..2bdb5adeb6 100644 --- a/config/aeotec/zw120.xml +++ b/config/aeotec/zw120.xml @@ -1,5 +1,32 @@ - - + + + http://www.openzwave.com/device-database/0086:0078:0102 + images/aeotec/zw120.png + https://products.z-wavealliance.org/products/1574/ + Aeon Labs Door/ Window Sensor Gen5 is a smart Z-Wave sensor that can detect the status of door/window's open/close in real time. +It’s a security Z-Wave device that supports security encryption. Also it supports the “Over the Air Firmware Updating” that allows you wirelessly update its firmware if needs. +It can be included and operated in any Z-Wave network with other Z-Wave certified devices from manufacturers and/or other applications. + + Press the Action Button once, which will trigger sending out the Wake up notification command, press and hold the Action Button for 3 seconds, which will toggle on/off the Sensor be waked up for 10 minutes. + Turn the primary controller of Z-Wave network into inclusion mode, short press the product’s Action Button that you can find in the back of the product. + Press the Action Button once that you can find in back of the product for 20 seconds and then release. This procedure should only be used when the primary controller is inoperable. + ZW120-A + U.S. / Canada / Mexico + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1579/Door Window Sensor Gen5 manual.pdf + Door/ Window Sensor Gen5 + Turn the primary controller of Z-Wave network into exclusion mode, short press the product’s Action Button that you can find in back of the product. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1574/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1578/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1579/xml + + https://products.z-wavealliance.org/products/1578/ + Australia / New Zealand + ZW120-B + https://products.z-wavealliance.org/products/1579/ + U.S. / Canada / Mexico + ZW120-C + diff --git a/config/aeotec/zw121.xml b/config/aeotec/zw121.xml index ecd2884708..78a1cc3d3e 100644 --- a/config/aeotec/zw121.xml +++ b/config/aeotec/zw121.xml @@ -1,106 +1,130 @@ - - - - - - The LED Strip state after re-power on it. - - - - - - Enable/disable to send out a report when the color is changed - - - - - +--> + + http://www.openzwave.com/device-database/0086:0079:0103 + images/aeotec/zw121.png + https://products.z-wavealliance.org/products/1963/ + Turn the primary controller of Z-Wave network into inclusion mode, press the Action Button on the LED Strip Controller. + LED Strip + Press and hold the Action Button on the LED Strip Controller for 20 seconds and then release it. +Use this procedure only in the event that your primary network controller is missing or inoperable. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2000/LED Strip manual.pdf + Aeotec LED Strip is a multi-coloured LED Strip which allows control (on/off/dim/colour change) via wireless Z-Wave commands. +The LED Strip can also communicate securely via AES 128 wireless Z-Wave commands and supports Over-The-Air (OTA) firmware upgrades. + + U.S. / Canada / Mexico + Turn the primary controller of Z-Wave network into exclusion mode, press the Action Button on the LED Strip Controller. + ZW121-A + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1963/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1999/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2000/xml + + https://products.z-wavealliance.org/products/1999/ + Australia / New Zealand + ZW121-B + https://products.z-wavealliance.org/products/2000/ + ZW121-C + CEPT (Europe) + + + + + The LED Strip state after re-power on it. + + + + + + Enable/disable to send out a report when the color is changed + + + + + Get the LED Strip color value Value 1: (msb) Reserved Value 2: Red color value Value 3: Green color value Value 4: Blue color value - - - Enable/disable to turn on the last brightness level of the LED Strip when using the Color Switch Set CC to change its color - - - - - Configure the display mode of Cold/Warm white - - - - - - Reboot/save/exit Colorful mode - - - - - - - + + + Enable/disable to turn on the last brightness level of the LED Strip when using the Color Switch Set CC to change its color + + + + + Configure the display mode of Cold/Warm white + + + + + Reboot/save/exit Colorful mode + + + + + + + Will set the LED Strip into different modes. See the table in documentation - - - + + + Value 1: (msb) The speed from OFF to ON. Value 2: The speed from ON to OFF. Value 3: Pause time of ON. Value 4: Pause time of OFF. - - - + + + Can be used to set the 8 color index when the Bulb is in Multi color mode. See the table in documentation - - - Reboot/save/exit Colorful mode - - - - - - - - Enable to send notifications to associated devices (Group 1) when the state of LED Strip is changedd - - - - - - - - - - - - - Enable/disable Configuration Locked - - - - - Reset to factory defaults - - - - - - - - - - - - + + + Reboot/save/exit Colorful mode + + + + + + + + Enable to send notifications to associated devices (Group 1) when the state of LED Strip is changedd + + + + + + + + + + + + + Enable/disable Configuration Locked + + + + + Reset to factory defaults + + + + + + + + + + + + diff --git a/config/aeotec/zw122.xml b/config/aeotec/zw122.xml index 06894f4665..fdd38a6d60 100644 --- a/config/aeotec/zw122.xml +++ b/config/aeotec/zw122.xml @@ -1,8 +1,35 @@ - +--> + + http://www.openzwave.com/device-database/0086:007A:0102 + images/aeotec/zw122.png + https://products.z-wavealliance.org/products/2407/ + Press and hold the Action Button that you can find on the product for 20 seconds and then release. This procedure should only be used when the primary controller is inoperable. + Turn the primary controller of Z-Wave network into inclusion mode, short press the product’s Action Button that you can find on the product. + Turn the primary controller of Z-Wave network into exclusion mode, short press the product’s Action Button that you can find on the product. + Pressing the Action Button once will trigger sending the Wake up notification command. If press and hold the Z-Wave button for 3 seconds, the Water Sensor will wake up for 10 minutes. + Water Sensor 6 + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2437/Aeon Labs Water Sensor 6 manual.pdf + ZW122-A + Aeotec by Aeon Labs Water Sensor 6 brings intelligence to a new level, one that is suited to both safety and convenience. It contains 4 sensing points, which would be more accurately to detect the presence and absence of water or detect whether there is water leak in some places of your home. The Water Sensor 6 has an inbuilt buzzer that can play alarm sounds to let you know when the water is detected. + +The Water Sensor 6 is also a security Z-Wave device that supports Over The Air (OTA) for firmware updates. + + U.S. / Canada / Mexico + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2407/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2411/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2437/xml + + https://products.z-wavealliance.org/products/2411/ + Australia / New Zealand + ZW122-B + https://products.z-wavealliance.org/products/2437/ + ZW122-C + CEPT (Europe) + diff --git a/config/aeotec/zw129.xml b/config/aeotec/zw129.xml index 59c0536222..bb3fd1ae72 100644 --- a/config/aeotec/zw129.xml +++ b/config/aeotec/zw129.xml @@ -1,7 +1,35 @@ - + + + http://www.openzwave.com/device-database/0086:0081:0102 + images/aeotec/zw129.png + https://products.z-wavealliance.org/products/2232/ + Press and hold the Action button that you can find on the product's housing for 20 seconds and then release. This procedure should only be used when the primary controller is inoperable. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2234/Aeon Labs WallMote manual.pdf + WallMote + Turn the primary controller of Z-Wave network into exclusion mode, short press the product’s Action button that you can find on the product's housing. + Aeotec WallMote is an intelligent Z-Wave remote controller that mounted on a wall. It has 2 touch buttons that you can easily control the Z-Wave devices in your home network via touching, long pressing or sliding the button areas. +Its surface has a RGB LED to indicate the button actions also accompanied by touch beep and vibration. +The WallMote Quad is also a security Z-Wave device and supports Over The Air (OTA) feature for the products firmware upgrade. + + ZW129-A + U.S. / Canada / Mexico + Turn the primary controller of Z-Wave network into inclusion mode, short press the product’s Action button that you can find on the product's housing. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2232/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2233/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2234/xml + Remove CentralScene from Endpoints - RemoveCC + + https://products.z-wavealliance.org/products/2233/ + Australia / New Zealand + ZW129-B + https://products.z-wavealliance.org/products/2234/ + ZW129-C + CEPT (Europe) + @@ -83,6 +111,13 @@ Aeotec ZW129 WallMote Duo, base on Engineering Spec 9/27/2016 + + + true + + + + diff --git a/config/aeotec/zw130.xml b/config/aeotec/zw130.xml index 92c96a229d..0f45810793 100644 --- a/config/aeotec/zw130.xml +++ b/config/aeotec/zw130.xml @@ -1,7 +1,33 @@ - +--> + + http://www.openzwave.com/device-database/0086:0082:0102 + images/aeotec/zw130.png + https://products.z-wavealliance.org/products/2130/ + Turn the primary controller of Z-Wave network into inclusion mode, short press the product’s Action button that you can find on the product's housing. + Turn the primary controller of Z-Wave network into exclusion mode, short press the product’s Action button that you can find on the product's housing. + WallMote Quad + Press and hold the Action button that you can find on the product's housing for 20 seconds and then release. This procedure should only be used when the primary controller is missing or inoperable. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2153/Aeon Labs WallMote Quad manual.pdf + U.S. / Canada / Mexico + Aeotec WallMote Quad is an intelligent Z-Wave remote controller that mounted on a wall. It has 4 touch buttons that you can easily control the Z-Wave devices in your home network via touching, long pressing or sliding the button areas. +Its surface has a RGB LED to indicate the button actions also accompanied by touch beep and vibration. +The WallMote Quad is also a security Z-Wave device and supports Over The Air (OTA) feature for the products firmware upgrade. + + ZW130-A + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2130/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2152/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2153/xml + + https://products.z-wavealliance.org/products/2152/ + ZW130-B + Australia / New Zealand + https://products.z-wavealliance.org/products/2153/ + ZW130-C + CEPT (Europe) + @@ -88,5 +114,8 @@ Aeotec ZW130 WallMote Quad, base on Engineering Spec 9/27/2016 + + + diff --git a/config/aeotec/zw132.xml b/config/aeotec/zw132.xml index d59b2cac33..35008e25ed 100644 --- a/config/aeotec/zw132.xml +++ b/config/aeotec/zw132.xml @@ -1,29 +1,53 @@ - - - - - - Output load will be closed after 30 seconds if the current exceeds (US: 15.5A, AU or EU: 10.5A). - - - - - Output load will be closed after 30 seconds if the temperature inside the product exceeds 100C. - - - - - Configure the output load status after re-power on - - - - - - +--> + + http://www.openzwave.com/device-database/0086:0084:0103 + images/aeotec/zw132.png + https://products.z-wavealliance.org/products/2136/ + Aeotec Dual Nano Switch is a Z-Wave Smart Switch specifically used to enable Z-Wave command and control (on/off) of any wall switches. It can report immediate wattage consumption or kWh energy usage over a period of time. In the event of power failure, non-volatile memory retains all programmed information relating to the unit’s operating status. +It can connect to 2 external manual switches to control the load ON/OFF independently. Its surface has a pin socket, which can be used for connecting to the touch panel, so you can also use the touch panel to control the Dual Nano Switch. +The Dual Nano Switch is also a security Z-Wave device and supports Over The Air (OTA) feature for the products firmware upgrade. + Dual Nano Switch + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2151/Dual Nano Switch manual.pdf + Turn the primary controller of Z-Wave network into inclusion mode, short press the product’s Action button that you can find on the product's housing. + Press and hold the Action button that you can find on the product's housing for 20 seconds and then release. This procedure should only be used when the primary controller is missing or inoperable. + ZW132-A + U.S. / Canada / Mexico + Turn the primary controller of Z-Wave network into exclusion mode, short press the product’s Action button that you can find on the product's housing. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2136/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2150/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2151/xml + + https://products.z-wavealliance.org/products/2150/ + ZW132-B + Australia / New Zealand + https://products.z-wavealliance.org/products/2151/ + ZW132-C + CEPT (Europe) + + + + + Output load will be closed after 30 seconds if the current exceeds (US: 15.5A, AU or EU: 10.5A). + + + + + Output load will be closed after 30 seconds if the temperature inside the product exceeds 100C. + + + + + Configure the output load status after re-power on + + + + + + Enable/disable the IR sensor of WallSwipe. (LSB) Value 1. Value 1 = 0, disable the IR Sensor. @@ -35,132 +59,132 @@ Product Type ID: EU=0x00, US=0x01, AU=0x02 CN=0x1D Value 4 = 0, disable the scene control functionality for all wave actions. Value 4 = 1, enable the scene control functionality for all wave actions. - - - + + + Set the button color of WallSwipe. Value 1= Level 1. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the LED indication color of WallSwipe when the gesture action is UP. Value 1= Reserved. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the LED indication color of WallSwipe when the gesture action is Down. Value 1= Reserved. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the LED indication color of WallSwipe when the gesture action is Left. Value 1= Reserved. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the LED indication color of WallSwipe when the gesture action is Right. Value 1= Reserved. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the LED indication color of WallSwipe when it is in Night light state. Value 1= Reserved. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the sensitivity of WallSwipe. - - - To set which notification would be sent to the associated nodes in association group 1 when the state of output load is changed - - - - - - - To set which notification would be sent to the associated nodes in association group 3 when using the external switch 1 to switch the loads - - - - - To set which notification would be sent to the associated nodes in association group 4 when using the external switch 2 to switch the loads - - - - - Configure the state of LED when it is in 3 modes below - - - - - - + + + To set which notification would be sent to the associated nodes in association group 1 when the state of output load is changed + + + + + + + To set which notification would be sent to the associated nodes in association group 3 when using the external switch 1 to switch the loads + + + + + To set which notification would be sent to the associated nodes in association group 4 when using the external switch 2 to switch the loads + + + + + Configure the state of LED when it is in 3 modes below + + + + + + Value1: Hour of ON. Value2: Minute of ON. Value3: Hour of OFF. Value4: Minute of OFF. E.g. The default setting is the Night light mode is enabled at 12: 00 and disabled at 8:00 0x12000800. - - - + + + Value1: 0= Disable / 1= Enable. Value2: Weekday (Bit 0-6 means Monday to Sunday). Value3: Hour of turning OFF. Value4: Minute of turning OFF E.g. The default setting 0x007F1200 - - - + + + Value1: 0= Disable / 1= Enable. Value2: Weekday (Bit 0-6 means Monday to Sunday). Value3: Hour of turning OFF. Value4: Minute of turning OFF E.g. The default setting 0x001707F00 - - - If this parameter is set to 1 (Enable), the parameter 101 - 103 should be set to 0. - - - - - The value represents the minimum change in wattage for a Report to be sent (default 25 W) - - - The value represents the minimum percentage change in wattage for a Report to be sent (Default 5) - - - Set report types for groups 1, 2 and 3 to default. - - - + + + If this parameter is set to 1 (Enable), the parameter 101 - 103 should be set to 0. + + + + + The value represents the minimum change in wattage for a Report to be sent (default 25 W) + + + The value represents the minimum percentage change in wattage for a Report to be sent (Default 5) + + + Set report types for groups 1, 2 and 3 to default. + + + Defines the type of report sent for reporting group 1. 1 is meter report for voltage average. 2 is meter report for current total. @@ -185,9 +209,9 @@ Product Type ID: EU=0x00, US=0x01, AU=0x02 CN=0x1D bit 1 watt total bit 0 kWh total - - - + + + Defines the type of report sent for reporting group 2. 1 is meter report for voltage average. 2 is meter report for current total. @@ -212,9 +236,9 @@ Product Type ID: EU=0x00, US=0x01, AU=0x02 CN=0x1D bit 1 watt total bit 0 kWh total - - - + + + Defines the type of report sent for reporting group 3. 1 is meter report for voltage average. 2 is meter report for current total. @@ -239,61 +263,61 @@ Product Type ID: EU=0x00, US=0x01, AU=0x02 CN=0x1D bit 1 watt total bit 0 kWh total - - - Set time interval for sending reports for groups 1, 2 and 3 to default. - - - Defines the time interval when the defined report for group 1 is sent. - - - Defines the time interval when the defined report for group 2 is sent. - - - Defines the time interval when the defined report for group 3 is sent. - - - When the switch mode of S1 is determined or identified or configured, this mode value will not be reset after exclusion - - - - - - - - When the switch mode of S2 is determined or identified or configured, this mode value will not be reset after exclusion - - - - - - - - Set the control destination for external switch S1 - - - - - - Set the control destination for external switch S2 - - - - - - Get the state of touch panel port - - - - - Set the working way for S1/S2 when the Switch mode is 3-way switch mode. - - - - - - - + + + Set time interval for sending reports for groups 1, 2 and 3 to default. + + + Defines the time interval when the defined report for group 1 is sent. + + + Defines the time interval when the defined report for group 2 is sent. + + + Defines the time interval when the defined report for group 3 is sent. + + + When the switch mode of S1 is determined or identified or configured, this mode value will not be reset after exclusion + + + + + + + + When the switch mode of S2 is determined or identified or configured, this mode value will not be reset after exclusion + + + + + + + + Set the control destination for external switch S1 + + + + + + Set the control destination for external switch S2 + + + + + + Get the state of touch panel port + + + + + Set the working way for S1/S2 when the Switch mode is 3-way switch mode. + + + + + + + Set the function of S1/S2. Bit 0 = 0, the function of sending NIF is disabled. Bit 0 = 1, the function of sending NIF is enabled. @@ -304,31 +328,31 @@ Product Type ID: EU=0x00, US=0x01, AU=0x02 CN=0x1D Bit 3 to Bit 6 are reserved. Bit 7 = 0, the setting for Bit 0 to Bit 2 are ineffective. Bit 7 = 1, the setting for Bit 0 to Bit 2 are effective. - - - Enable/disable the factory reset function of Action Button, external switches or WallSwipe. - - - - - Enable/disable Configuration Locked - - - - - Reset to factory defaults - - - - - - - - - - - - - - + + + Enable/disable the factory reset function of Action Button, external switches or WallSwipe. + + + + + Enable/disable Configuration Locked + + + + + Reset to factory defaults + + + + + + + + + + + + + + diff --git a/config/aeotec/zw139.xml b/config/aeotec/zw139.xml index 874511a9f7..5432a51b76 100644 --- a/config/aeotec/zw139.xml +++ b/config/aeotec/zw139.xml @@ -1,24 +1,48 @@ - - - - - - Output load will be closed after 30 seconds if the temperature inside the product exceeds 100C. - - - - - Configure the output load status after re-power on - - - - - - +--> + + http://www.openzwave.com/device-database/0086:008B:0103 + images/aeotec/zw139.png + https://products.z-wavealliance.org/products/2306/ + Nano Switch + Aeotec Nano Switch is a Z-Wave Smart Switch specifically used to enable Z-Wave command and control (on/off) of any wall switches. In the event of power failure, non-volatile memory retains all programmed information relating to the unit’s operating status. +It can connect to 2 external manual switches to control the load ON/OFF independently. Its surface has a pin socket, which can be used for connecting to the touch panel, so you can also use the touch panel to control the Dual Nano Switch. +The Nano Switch is also a security Z-Wave device and supports Over The Air (OTA) feature for the products firmware upgrade. + Press and hold the Action button that you can find on the product's housing for 20 seconds and then release. This procedure should only be used when the primary controller is inoperable. + Turn the primary controller of Z-Wave network into exclusion mode, short press the product’s Action button that you can find on the product's housing. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2320/Nano Switch manual.pdf + ZW139-A + U.S. / Canada / Mexico + Turn the primary controller of Z-Wave network into inclusion mode, short press the product’s Action button that you can find on the product's housing. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2306/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2319/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2320/xml + + https://products.z-wavealliance.org/products/2319/ + ZW139-B + Australia / New Zealand + https://products.z-wavealliance.org/products/2320/ + ZW139-C + CEPT (Europe) + + + + + Output load will be closed after 30 seconds if the temperature inside the product exceeds 100C. + + + + + Configure the output load status after re-power on + + + + + + Enable/disable the IR sensor of WallSwipe. (LSB) Value 1. Value 1 = 0, disable the IR Sensor. @@ -30,152 +54,152 @@ Product Type ID: EU=0x00, US=0x01, AU=0x02 CN=0x1D Value 4 = 0, disable the scene control functionality for all wave actions. Value 4 = 1, enable the scene control functionality for all wave actions. - - - + + + Set the button color of WallSwipe. Value 1= Level 1. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the LED indication color of WallSwipe when the gesture action is UP. Value 1= Reserved. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the LED indication color of WallSwipe when the gesture action is Down. Value 1= Reserved. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the LED indication color of WallSwipe when the gesture action is Left. Value 1= Reserved. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the LED indication color of WallSwipe when the gesture action is Right. Value 1= Reserved. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the LED indication color of WallSwipe when it is in Night light state. Value 1= Reserved. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the sensitivity of WallSwipe. - - - To set which notification would be sent to the associated nodes in association group 1 when the state of output load is changed - - - - - - - To set which notification would be sent to the associated nodes in association group 3 when using the external switch 1 to switch the loads - - - - - To set which notification would be sent to the associated nodes in association group 4 when using the external switch 2 to switch the loads - - - - - Configure the state of LED when it is in 3 modes below - - - - - - + + + To set which notification would be sent to the associated nodes in association group 1 when the state of output load is changed + + + + + + + To set which notification would be sent to the associated nodes in association group 3 when using the external switch 1 to switch the loads + + + + + To set which notification would be sent to the associated nodes in association group 4 when using the external switch 2 to switch the loads + + + + + Configure the state of LED when it is in 3 modes below + + + + + + Value1: Hour of ON. Value2: Minute of ON. Value3: Hour of OFF. Value4: Minute of OFF. E.g. The default setting is the Night light mode is enabled at 12: 00 and disabled at 8:00 0x12000800. - - - + + + Value1: 0= Disable / 1= Enable. Value2: Weekday (Bit 0-6 means Monday to Sunday). Value3: Hour of turning OFF. Value4: Minute of turning OFF E.g. The default setting 0x007F1200 - - - + + + Value1: 0= Disable / 1= Enable. Value2: Weekday (Bit 0-6 means Monday to Sunday). Value3: Hour of turning OFF. Value4: Minute of turning OFF E.g. The default setting 0x001707F00 - - - When the switch mode of S1 is determined or identified or configured, this mode value will not be reset after exclusion - - - - - - - - When the switch mode of S2 is determined or identified or configured, this mode value will not be reset after exclusion - - - - - - - - - - - - - - Get the state of touch panel port - - - - - Set the working way for S1/S2 when the Switch mode is 3-way switch mode. - - - - - - - + + + When the switch mode of S1 is determined or identified or configured, this mode value will not be reset after exclusion + + + + + + + + When the switch mode of S2 is determined or identified or configured, this mode value will not be reset after exclusion + + + + + + + + + + + + + + Get the state of touch panel port + + + + + Set the working way for S1/S2 when the Switch mode is 3-way switch mode. + + + + + + + Set the function of S1/S2. Bit 0 = 0, the function of sending NIF is disabled. Bit 0 = 1, the function of sending NIF is enabled. @@ -186,26 +210,26 @@ Product Type ID: EU=0x00, US=0x01, AU=0x02 CN=0x1D Bit 3 to Bit 6 are reserved. Bit 7 = 0, the setting for Bit 0 to Bit 2 are ineffective. Bit 7 = 1, the setting for Bit 0 to Bit 2 are effective. - - - Enable/disable the factory reset function of Action Button, external switches or WallSwipe. - - - - - Reset to factory defaults - - - - - - - - - - - - - - + + + Enable/disable the factory reset function of Action Button, external switches or WallSwipe. + + + + + Reset to factory defaults + + + + + + + + + + + + + + diff --git a/config/aeotec/zw140.xml b/config/aeotec/zw140.xml index 3c6819f8e4..ec03c4c095 100644 --- a/config/aeotec/zw140.xml +++ b/config/aeotec/zw140.xml @@ -1,24 +1,49 @@ - - - - - - Output load will be closed after 30 seconds if the temperature inside the product exceeds 100C. - - - - - Configure the output load status after re-power on - - - - - - +--> + + http://www.openzwave.com/device-database/0086:008C:0103 + images/aeotec/zw140.png + https://products.z-wavealliance.org/products/2247/ + Dual Nano Switch + Aeotec Dual Nano Switch is a Z-Wave Smart Switch specifically used to enable Z-Wave command and control (on/off) of any wall switches. +In the event of power failure, non-volatile memory retains all programmed information relating to the unit’s operating status. +It can connect to 2 external manual switches to control the load ON/OFF independently. Its surface has a pin socket, which can be used for connecting to the touch panel, so you can also use the touch panel to control the Dual Nano Switch. +The Dual Nano Switch is also a security Z-Wave device and supports Over The Air (OTA) feature for the products firmware upgrade. + Turn the primary controller of Z-Wave network into exclusion mode, short press the product’s Action button that you can find on the product's housing. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2313/Dual Nano Switch manual.pdf + Turn the primary controller of Z-Wave network into inclusion mode, short press the product’s Action button that you can find on the product's housing. + U.S. / Canada / Mexico + ZW140-A + Press and hold the Action button that you can find on the product's housing for 20 seconds and then release. This procedure should only be used when the primary controller is inoperable. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2247/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2312/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2313/xml + + https://products.z-wavealliance.org/products/2312/ + Australia / New Zealand + ZW140-B + https://products.z-wavealliance.org/products/2313/ + CEPT (Europe) + ZW140-C + + + + + Output load will be closed after 30 seconds if the temperature inside the product exceeds 100C. + + + + + Configure the output load status after re-power on + + + + + + Enable/disable the IR sensor of WallSwipe. (LSB) Value 1. Value 1 = 0, disable the IR Sensor. @@ -30,161 +55,161 @@ Product Type ID: EU=0x00, US=0x01, AU=0x02 CN=0x1D Value 4 = 0, disable the scene control functionality for all wave actions. Value 4 = 1, enable the scene control functionality for all wave actions. - - - + + + Set the button color of WallSwipe. Value 1= Level 1. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the LED indication color of WallSwipe when the gesture action is UP. Value 1= Reserved. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the LED indication color of WallSwipe when the gesture action is Down. Value 1= Reserved. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the LED indication color of WallSwipe when the gesture action is Left. Value 1= Reserved. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the LED indication color of WallSwipe when the gesture action is Right. Value 1= Reserved. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the LED indication color of WallSwipe when it is in Night light state. Value 1= Reserved. Value 2= the color value of Red. Value 3= the color value of Green. Value 4= the color value of Blue. - - - + + + Set the sensitivity of WallSwipe. - - - + + + To set which notification would be sent to the associated nodes in association group 1 when the state of output load is changed. Note: When just only one channel load state is changed, the report message Hail CC or Basic Report CC would be Multi Channel encapsulated. - - - - - - - To set which notification would be sent to the associated nodes in association group 3 when using the external switch 1 to switch the loads - - - - - To set which notification would be sent to the associated nodes in association group 4 when using the external switch 2 to switch the loads - - - - - Configure the state of LED when it is in 3 modes below - - - - - - + + + + + + + To set which notification would be sent to the associated nodes in association group 3 when using the external switch 1 to switch the loads + + + + + To set which notification would be sent to the associated nodes in association group 4 when using the external switch 2 to switch the loads + + + + + Configure the state of LED when it is in 3 modes below + + + + + + Value1: Hour of ON. Value2: Minute of ON. Value3: Hour of OFF. Value4: Minute of OFF. E.g. The default setting is the Night light mode is enabled at 12: 00 and disabled at 8:00 0x12000800. - - - + + + Value1: 0= Disable / 1= Enable. Value2: Weekday (Bit 0-6 means Monday to Sunday). Value3: Hour of turning OFF. Value4: Minute of turning OFF E.g. The default setting 0x007F1200 - - - + + + Value1: 0= Disable / 1= Enable. Value2: Weekday (Bit 0-6 means Monday to Sunday). Value3: Hour of turning OFF. Value4: Minute of turning OFF E.g. The default setting 0x001707F00 - - - When the switch mode of S1 is determined or identified or configured, this mode value will not be reset after exclusion - - - - - - - - When the switch mode of S2 is determined or identified or configured, this mode value will not be reset after exclusion - - - - - - - - Set the control destination for external switch S1 - - - - - - Set the control destination for external switch S2 - - - - - - Get the state of touch panel port - - - - - Set the working way for S1/S2 when the Switch mode is 3-way switch mode. - - - - - - - + + + When the switch mode of S1 is determined or identified or configured, this mode value will not be reset after exclusion + + + + + + + + When the switch mode of S2 is determined or identified or configured, this mode value will not be reset after exclusion + + + + + + + + Set the control destination for external switch S1 + + + + + + Set the control destination for external switch S2 + + + + + + Get the state of touch panel port + + + + + Set the working way for S1/S2 when the Switch mode is 3-way switch mode. + + + + + + + Set the function of S1/S2. Bit 0 = 0, the function of sending NIF is disabled. Bit 0 = 1, the function of sending NIF is enabled. @@ -195,31 +220,31 @@ Product Type ID: EU=0x00, US=0x01, AU=0x02 CN=0x1D Bit 3 to Bit 6 are reserved. Bit 7 = 0, the setting for Bit 0 to Bit 2 are ineffective. Bit 7 = 1, the setting for Bit 0 to Bit 2 are effective. - - - Enable/disable the factory reset function of Action Button, external switches or WallSwipe. - - - - - Enable/disable Configuration Locked - - - - - Reset to factory defaults - - - - - - - - - - - - - - + + + Enable/disable the factory reset function of Action Button, external switches or WallSwipe. + + + + + Enable/disable Configuration Locked + + + + + Reset to factory defaults + + + + + + + + + + + + + + diff --git a/config/aeotec/zw141.xml b/config/aeotec/zw141.xml index b3ef39fc64..4825bdfce6 100644 --- a/config/aeotec/zw141.xml +++ b/config/aeotec/zw141.xml @@ -1,66 +1,99 @@ - - - - - - +--> + + http://www.openzwave.com/device-database/0086:008D:0103 + images/aeotec/zw141.png + https://products.z-wavealliance.org/products/3075/ + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3075/Aeon Labs Nano Shutter -manual - 2.pdf + Press and hold the Action button that you can find on the product's housing for 20 seconds and then release. This procedure should only be used when the primary controller is inoperable. + Turn the primary controller of Z-Wave network into exclusion mode, quick press the product’s Action button 6 times that you can find on the product's housing or toggle the external manual switch 2 times in fast succession. + +If the Nano Dimmer has been successfully removed from your Z-Wave network, its RGB LED will remain colorful gradient. If the removal was unsuccessful, the RGB LED will still be solid (following the state of the output load), repeat the instructions above from step 1. + Nano Shutter + Aeotec Nano Shutter is a Z-Wave motor controller specifically used to enable Z-Wave command and control (up/down/stop) for existing window covering motors. +It can connect to 2 external manual switches/buttons to control the motor up/down/stop independently. Its surface has a pin socket, which can be used for connecting to the touch panel, so you can also use the touch panel to control the Nano Shutter. +The wireless module is powered from the mains supply. In the event of power failure, non-volatile memory retains all programmed information relating to the units operating status. +Nano Shutter is also a security Z-Wave plus device and supports Over The Air (OTA) feature for the products firmware upgrade. +It can be a repeater in the Z-Wave network. Acting as a bridge for communication, it will forward Z-Wave command messages to their destinations if the originating controller is out of range from the destination node. +By taking advantage of the Z-Wave mesh network, commands can be routed to their destination via intermediary “listening” Z-Wave products. Products that are Z-Wave certified can be used and communicate with other Z-Wave certified devices. + U.S. / Canada / Mexico + ZW141-A + Turn the primary controller of Z-Wave network into inclusion mode, short press the product’s Action button that you can find on the product's housing. + +If the Nano Dimmer has been successfully added to your Z-Wave network, its RGB LED will be solid. If unsuccessful, the red LED will be on for 2 seconds and then remain a colorful gradient, repeat the instructions above from step 1. + + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2903/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2907/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2953/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3075/xml + + https://products.z-wavealliance.org/products/2907/ + ZW141-B + Australia / New Zealand + https://products.z-wavealliance.org/products/2953/ + ZW141-C + CEPT (Europe) + + + + + Set the moving time from up (left) to down (right) for curtain. - - - + + + To set which report would be sent to the associated nodes in association group 1 when the state of output load is changed. Note: When just only one channel load state is changed, the report message Basic Report CC would be Multi Channel encapsulated. - - - - - + + + + + Set the operation mode of external switch. For detailed instructions for Operation Mode 1 and 2, see end of this table. - - - - - When the mode is determined, this mode value will not be reset after exclusion - - - - - - - - When the mode is determined, this mode value will not be reset after exclusion - - - - - - - - Enable/disable Configuration Locked - - - - - Reset to factory defaults - - - - - - - - - - - - + + + + + When the mode is determined, this mode value will not be reset after exclusion + + + + + + + + When the mode is determined, this mode value will not be reset after exclusion + + + + + + + + Enable/disable Configuration Locked + + + + + Reset to factory defaults + + + + + + + + + + + + diff --git a/config/aeotec/zw162.xml b/config/aeotec/zw162.xml index 4bea2ddfbd..e4ac7c66fb 100644 --- a/config/aeotec/zw162.xml +++ b/config/aeotec/zw162.xml @@ -1,75 +1,186 @@ - - +--> + + http://www.openzwave.com/device-database/0371:00A2:0103 + images/aeotec/zw162.png + https://products.z-wavealliance.org/products/3218/ + This product supports Security 2 Command Class. While a Security S2 enabled Controller is needed in order to fully use the security feature. This product can be included and operated in any Z-Wave network with other Z-Wave certified devices from other manufacturers and/or other applications. All non-battery operated nodes within the network will +act as repeaters regardless of vendor to increase reliability of the network. + +1. Set your Z-Wave Controller into its 'Add Device' mode in order to add Chime into your Z-Wave system. Refer to the Controller's manual if you are unsure of how to perform this step. + +2. Power on Chime via the provided power adapter; its LED will be breathing white light all the time. + +3. Click Chime Action Button once, it will quickly flash white light for 30 seconds until Chime is added into the network. It will become constantly bright white light after being assigned a NodeID. + +4. If your Z-Wave Controller supports S2 encryption, enter the first 5 digits of DSK into your Controller's interface if/when requested. The DSK is printed on Chime's housing. + +5. If Adding fails, it will slowly flash white light 3 times and then become breathing white light; repeat steps 1 to 4. Contact us for further support if needed. + +6. If Adding succeeds, it will quickly flash white light 3 times and then become off. Now, Chime is a part of your Z-Wave home control system. You can configure it and its automations via your Z-Wave system; please refer to your software's user guide for precise instructions. + +Note: +If Action Button is clicked again during the Learn Mode, the Learn Mode will exit. At the same time, Indicator Light will extinguish immediately, and then become breathing white light. + U.S. / Canada / Mexico + Doorbell 6 + - S2 Security. +- Not only a doorbell, but also can be used as a siren via setting. +- Can be wireless controlled by more Button, up to 3. +- Longer Button control distance, up to 120m. +- Built-in multiple tones, up to 30. +- Built-in multiple adjustable Light Effect. + + 1. Set your Z-Wave Controller into its ' Remove Device' mode in order to remove Chime from your Z-Wave system. Refer to the Controller's manual if you are unsure of how to perform this step. + +2. Power on Chime via the provided power adapter; its LED will be off. + +3. Click Chime Action Button 6 times quickly; it will bright white light, up to 2s. + +4. If Removing fails, it will keep off; repeat steps 1 to 3. Contact us for further support if needed. + +5. If Removing succeeds, it will quickly flash white light 3 times and then become breathing white light. Now, Chime is removed from Z-Wave network successfully. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3292/Doorbell 6 product manual.pdf + If the primary controller is missing or inoperable, you may need to reset the device to factory settings. + +Make sure the Chime is powered. To complete the reset process manually, press and hold the Action Button for at least 20s. The LED indicator will quickly flash white light 3 times and then become breathing white light, which indicates the reset operation is successful. Otherwise, please try again. Contact us for further support if needed. + +Note: +1. This procedure should only be used when the primary controller is missing or inoperable. +2. Factory Reset Chime will: +(a) Remove Chime from Z-Wave network; +(b) Delete the Association setting; +(c) Restore the configuration settings to the default.(Except configuration parameter 51/52/53/54) + ZW162-A + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3218/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3291/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3292/xml + + https://products.z-wavealliance.org/products/3291/ + Australia / New Zealand + ZW162-B + https://products.z-wavealliance.org/products/3292/ + ZW162-C + CEPT (Europe) + - - Please Refer to Engineering Specification - Aeotec Doorbell 6 + + Light Effect and PlayTone configuration for Browse Endping + + + Use the Last Valid Configuration Value for the Light Effect + + + + Use Light Effect #7, Defined in Parameter 22 + + + + Use Light Effect #6, Defined in Parameter 21 + + + + Use Light Effect #5, Defined in Parameter 20 + + + + Use Light Effect #4, Defined in Parameter 19 + + + + Use Light Effect #3, Defined in Parameter 18 + + + + Use Light Effect #2, Defined in Parameter 17 + + + + Use Light Effect #1, Defined in Parameter 16 + + + + Use the Last Valid Configuration Value for the Tone + + + + If you’re not sure which tone to use, you can configure the value of Tone Play Mode to be 3. Then send Basic Set 0xFF to Endpoint 1 or Root Device to trigger auto-selecting tone function. Chime will play built-in tones randomly and the Default Tone Identifier will be changed each time a new tone is played. When send Basic Set 0x00 to Endpoint 1 or Root Device to stop playing tone, the Default Tone Identifier will store, which means the tone has been selected. +Please note that the Tone Play Mode needs to be configured to be 0 or 1 after the tone is selected, otherwise the automatic selection tone function will be retriggered when the Endpoint 1 or Root Device is triggered to play tone and light again. + + + + If you’re not sure which tone to use, you can configure the value of Tone Play Mode to be 2. Then send Basic Set 0xFF to Endpoint 1 or Root Device to trigger auto-selecting tone function. Chime will play built-in tones in order and the Default Tone Identifier will be changed each time a new tone is played. When send Basic Set 0x00 to Endpoint 1 or Root Device to stop playing tone, the Default Tone Identifier will store, which means the tone has been selected. +Please note that the Tone Play Mode needs to be configured to be 0 or 1 after the tone is selected, otherwise the automatic selection tone function will be retriggered when the Endpoint 1 or Root Device is triggered to play tone and light again. + + + + Use a single loop playback for the Tone + - + Please Refer to Engineering Specification - Aeotec Doorbell 6 - + Please Refer to Engineering Specification - Aeotec Doorbell 6 - + Please Refer to Engineering Specification - Aeotec Doorbell 6 - + Please Refer to Engineering Specification - Aeotec Doorbell 6 - + Please Refer to Engineering Specification - Aeotec Doorbell 6 - + Please Refer to Engineering Specification - Aeotec Doorbell 6 - + Please Refer to Engineering Specification - Aeotec Doorbell 6 - + Please Refer to Engineering Specification - Aeotec Doorbell 6 - + Please Refer to Engineering Specification - Aeotec Doorbell 6 - + Please Refer to Engineering Specification - Aeotec Doorbell 6 - + Please Refer to Engineering Specification - Aeotec Doorbell 6 - + Please Refer to Engineering Specification - Aeotec Doorbell 6 - + Please Refer to Engineering Specification - Aeotec Doorbell 6 - + Please Refer to Engineering Specification - Aeotec Doorbell 6 - + Configure how to send Basic Set to nodes in Group 2 @@ -77,7 +188,7 @@ ZW162 Doorbell 6 - + Configure how to send Basic Set to nodes in Group 3 @@ -85,7 +196,7 @@ ZW162 Doorbell 6 - + Configure how to send Basic Set to nodes in Group 4 @@ -93,7 +204,7 @@ ZW162 Doorbell 6 - + Configure how to send Basic Set to nodes in Group 5 @@ -101,7 +212,7 @@ ZW162 Doorbell 6 - + Configure how to send Basic Set to nodes in Group 6 @@ -109,7 +220,7 @@ ZW162 Doorbell 6 - + Configure how to send Basic Set to nodes in Group 8 @@ -117,7 +228,7 @@ ZW162 Doorbell 6 - + Configure how to send Basic Set to nodes in Group 9 @@ -125,7 +236,7 @@ ZW162 Doorbell 6 - + @@ -135,21 +246,21 @@ ZW162 Doorbell 6 - + - + - + @@ -160,50 +271,48 @@ ZW162 Doorbell 6 - + Please Refer to Engineering Specification - Aeotec Doorbell 6 - + Please Refer to Engineering Specification - Aeotec Doorbell 6 - + Please Refer to Engineering Specification - Aeotec Doorbell 6 - + Reset to factory defaults - - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - + + + + + + + + + diff --git a/config/aeotec/zw164.xml b/config/aeotec/zw164.xml new file mode 100644 index 0000000000..6ecf8f73fd --- /dev/null +++ b/config/aeotec/zw164.xml @@ -0,0 +1,311 @@ + + + + + http://www.openzwave.com/device-database/0086:00a4:0003 + images/aeotec/zw164.png + ZW164-C + https://products.z-wavealliance.org/products/3301/ + CEPT (Europe) + + This product supports Security 2 Command Class. While a Security S2 enabled Controller is needed in order to fully use the security feature. This product can be included and operated in any Z-Wave network with other Z-Wave certified devices from other manufacturers and/or other applications. All non-battery operated nodes within the network will act as repeaters regardless of vendor to increase reliability of the network. 1. Set your Z-Wave Controller into its 'Add Device' mode in order to add Chime into your Z-Wave system. Refer to the Controller's manual if you are unsure of how to perform this step. 2. Power on Chime via the provided power adapter; its LED will be breathing white light all the time. 3. Click Chime Action Button once, it will quickly flash white light for 30 seconds until Chime is added into the network. It will become constantly bright white light after being assigned a NodeID. 4. If your Z-Wave Controller supports S2 encryption, enter the first 5 digits of DSK into your Controller's interface if/when requested. The DSK is printed on Chime's housing. 5. If Adding fails, it will slowly flash white light 3 times and then become breathing white light; repeat steps 1 to 4. Contact us for further support if needed. 6. If Adding succeeds, it will quickly flash white light 3 times and then become off. Now, Chime is a part of your Z-Wave home control system. You can configure it and its automations via your Z-Wave system; please refer to your software's user guide for precise instructions. Note: If Action Button is clicked again during the Learn Mode, the Learn Mode will exit. At the same time, Indicator Light will extinguish immediately, and then become breathing white light. + Indoor Siren 6 + 1. Set your Z-Wave Controller into its ' Remove Device' mode in order to remove Chime from your Z-Wave system. Refer to the Controller's manual if you are unsure of how to perform this step. 2. Power on Chime via the provided power adapter; its LED will be off. 3. Click Chime Action Button 6 times quickly; it will bright white light, up to 2s. 4. If Removing fails, it will keep off; repeat steps 1 to 3. Contact us for further support if needed. 5. If Removing succeeds, it will quickly flash white light 3 times and then become breathing white light. Now, Chime is removed from Z-Wave network successfully. + - S2 Security. - Not only a siren, but also can be used as a doorbell via setting. - Can be wireless controlled by more Button, up to 3. - Longer Button control distance, up to 120m. - Built-in multiple tones, up to 30. - Built-in multiple adjustable Light Effect. + If the primary controller is missing or inoperable, you may need to reset the device to factory settings. Make sure the Chime is powered. To complete the reset process manually, press and hold the Action Button for at least 20s. The LED indicator will quickly flash white light 3 times and then become breathing white light, which indicates the reset operation is successful. Otherwise, please try again. Contact us for further support if needed. Note: 1. This procedure should only be used when the primary controller is missing or inoperable. 2. Factory Reset Chime will: (a) Remove Chime from Z-Wave network; (b) Delete the Association setting; (c) Restore the configuration settings to the default.(Except configuration parameter 51/52/53/54) + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3301/Indoor%20Siren%206%20product%20manual.pdf + + Add metadata for aeotec indoor siren 6 #1894 + + + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Please Refer to Engineering Specification - Aeotec Indoor Siren 6 + + + + + Please Refer to Engineering Specification - Aeotec Indoor Siren 6 + + + + + Please Refer to Engineering Specification - Aeotec Indoor Siren 6 + + + + + + + + + + Reset to factory defaults + + + + + + + + + + false + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/config/aeotec/zw175.xml b/config/aeotec/zw175.xml new file mode 100644 index 0000000000..aa3f469f3c --- /dev/null +++ b/config/aeotec/zw175.xml @@ -0,0 +1,182 @@ + + + ZW175 Smart Switch 7 + + Elegant appearance, small size, easy to use, friendly operation. + Support power metering function, with high measurement accuracy, and more accurate knowledge of the power consumption of the load. + Support over-current, over-load and over-heat protection, which is more secure and reliable. + Support scene personalization and is more intelligent. + Support Night Light Mode to reduce light pollution. + Support S2 Security, which is safer and more reliable. + Support SmartStart, making inclusion more convenient. + + http://www.openzwave.com/device-database/0371:00af:0003 + https://products.z-wavealliance.org/products/3437 + https://products.z-wavealliance.org/products/3437 + images/aeotec/zw195.png + https://products.z-wavealliance.org/products/3437 + N/A + + 1. Set your Z-Wave Controller into its 'Add Device' mode in order to add the product into your Z-Wave system. Refer to the Controller's manual if you are unsure of how to perform this step. + 2. Make sure the product is powered. If not, plug it into a wall socket and power on; its LED will be breathing blue light all the time. + 3. Click Action Button once, it will quickly flash blue light for 30 seconds until it is added into the network. It will become constantly bright yellow light after being assigned a NodeID. + 4. If your Z-Wave Controller supports S2 encryption, enter the first 5 digits of DSK into your Controller's interface if /when requested. The DSK is printed on its housing. + 5. If Adding fails, it will bright red light for 2s and then become breathing blue light; repeat steps 1 to 4. Contact us for further support if needed. + 6. If Adding succeeds, it will bright blue light for 2s and then turn to Load Indicator Mode. Now, this product is a part of your Z-Wave home control system. You can configure it and its automations via your Z-Wave system; please refer to your software's user guide for precise instructions. + + 1. Set your Z-Wave Controller into its 'Remove Device' mode in order to remove the product from your Z-Wave system. Refer to the Controller's manual if you are unsure of how to perform this step. + 2. Make sure the product is powered. If not, plug it into a wall socket and power on. 3. Click Action Button 2 times quickly; it will bright violet light, up to 2s. + 4. If Removing fails, it will bright red light for 2s and then turn back to Load Indicator Mode; repeat steps 1 to 3. Contact us for further support if needed. + 5. If Removing succeeds, it will become breathing blue light. Now, it is removed from Z-Wave network successfully. + + Make sure the product is powered. If not, plug it into a wall socket and power on. To complete the reset process manually, press and hold the Action Button for at least 15s and then release. The LED indicator will become breathing blue light, which indicates the reset operation is successful. Otherwise, please try again. + https://products.z-wavealliance.org/products/3437 + CEPT (Europe) + ZW175-C16 + + Add ZW175 Smart Switch 7 + Change refresh on node info frame + + + + + + + + + Define a threshold power and automatically turn off switch when the load connected bypasses the maximum allowed power regardless of always on setting. + Note: + Over-load protection will be active if the load power exceeds the setting and lasts for more than 30s. + If be active, Indicator Light will become red light blinking and the product will send out Notification Report (Over-load detected), and disable the function that manually or RF control the switch state until users set Protection State to be unprotected through the Gateway or Controller. + Even power off will still keep Protection State. + + + + + Enabled by (Alarm Settings), and determines what the switch does in the case an alarm is triggered. + Note: + When receives any alarm enabled by Alarm Settings, Indicator Light will keep blinking based on Parameter 18. + It will prohibit user from manually or RF control the switch state until the alarm is disable. + + + + + + + + + Determine if alarms are enabled in Switch, and what Switch will react to which alarm. + The format of the parameter is Bit field (Checkboxes). + The parameter MUST be treated as a bit field where each individual bit can be set or reset. + A graphical configuration tool SHOULD present this parameter as a series of checkboxes. + + + + + Determines the method of disabling the alarm of the device. + Note: Power off will also disable the alarm response without any limitation. + + 0=> Can be disabled by 3x tapping Action Button within 1 second. + 1=> Can be disabled when receives a State Idle corresponding to the alarm. + Note: If Access Control is enable, it also can be disabled when receives the reversal state of window/door. + 10..255=> Sets the duration of the alarm in seconds(i.e. Customer sets this setting to 50, the alarm state of the Switch will disable after 50 seconds) + + + + + Set amount of blinks per seconds. + Note: When receiving the enable Alarm, it will flash according to the blink frequency configured by this parameter until the Alarm is disable. + Brightness level and color is based on current indicator. + If the value of brightness level and color is 0, it will flash based on last visible color. + + + + + Note: The parameter can be used to test the effect of LED blinking. + 0=> Stop blinking. + 1..255=> Set the duration and start the blinking process. + * This sets the timeframe of blinking in seconds. + * Once the duration ends, the blinking will stop. + + + + Configure the output load status after re-power on. + + + + + + Defines the automated status notification of an associated device when status changes + + + + + + Configuring brightness and color of Indicator Light in different time/status of different modes will be saved in the current setting mode. + + + + + + + Value1: Enable Hour. Valid value are 0-23 and 127. Value 127 means use last valid setting. + Value2: Enable Minute. Valid value are 0-59 and 255. Value 255 means use last valid setting. + Value3: Disable Hour. Valid value are 0-23 and 255. Value 255 means use last valid setting. + Value4: Disable Minute. Valid value are 0-59 and 255. Value 255 means use last valid setting. + + + + + 0 => Disable. + 1-2300 => 1-2300W. + + + + + 0 => Disable. + 1-10000 => 1-10000kWh. + + + + + 0 => Disable. + 1-100 => 0.1-10A. + + + + + Defines the type of report sent for reporting group 1. + 1 is meter report for voltage. + 2 is meter report for current. + 4 is meter report for watts. + 8 is meter report for kilowatts. + Value 1 (msb) Reserved + Value 2 Reserved + Value 3 Reserved + Value 4 (lsb) bits 7-4 reserved + bit 3 Current + bit 2 Voltage + bit 1 Power + bit 0 Power Consumption + + + + + 0 => Disable. + 600..2592000 => 600-2592000s. (10minute-30day) + + + + Reset to factory defaults + + + + + + + + + + + + diff --git a/config/aeotec/zw187.xml b/config/aeotec/zw187.xml new file mode 100644 index 0000000000..6fae235f4c --- /dev/null +++ b/config/aeotec/zw187.xml @@ -0,0 +1,98 @@ + + + + http://www.openzwave.com/device-database/0371:00bb:0002 + images/aeotec/zw187.png + https://products.z-wavealliance.org/products/3694/ + CEPT (Europe) + ZW089-C + https://products.z-wavealliance.org/products/3694/ + U.S. / Canada / Mexico + ZW089-A + https://products.z-wavealliance.org/products/3694/ + Australia / New Zealand + ZW089-B + Recessed Door Sensor 7 + Press and hold the Z-Wave button for 5 seconds will trigger sending the Wake up notification command and then keep waking up for 10 seconds after release the Z-Wave button. + https://products.z-wavealliance.org/ProductManual/File?folder=&filename=product_documents/3694/Recessed%20Door%20Sensor%207%20-%20Product%20Manual.pdf + Turn the primary controller of Z-Wave network into inclusion mode, short press the product’s Z-Wave button that you can find in the back of the product. + Press and hold the Z-Wave button that you can find in back of the product for 20 seconds and then release. This procedure should only be used when the primary controller is inoperable. + Turn the primary controller of Z-Wave network into exclusion mode, short press the product’s Z-Wave button that you can find in back of the product. + The Aeotec Recessed Door Sensor 7 is a door sensor that can detect the state of the door's open/close. It will report the door state to your controller/ gateway/associated nodes in real time when the state of your door has a change. +It’s a security Z-Wave device that supports security encryption. Also it supports the “Over the Air Firmware Updating” that allows you wirelessly update its firmware if needs. +It can be included and operated in any Z-Wave network with other Z-Wave certified devices from manufacturers and/or other applications. + + + Initial version + + + + + + + + Enable/Disable Binary Sensor Report. Allow for backward compatibility to report Binary if Notification Report cannot be used for status changes. + + + + + Reverse Sensor Reports (both Sensor Binary Report and Notification Report.) + + + + + Configure the Basic Set value. Determine the Basic Set value to control other Z-Wave devices directly when Magnet is away or near. + + + + + + + + + + + Configure retry number and wait time. + The device supports an application retry mechanism when the application of the device has detected a transmission error when Basic Set, Sensor Binary Report or Notification Report (Access Control) message is sent out but fails to result in an ACK or a Supervision Report. + The Byte 1 is used to configure the number of retries. The valid value is 0-5. 0 means disable retry. + The Byte 2 is used to configure the wait time between retries. The valid value is 0-255. Unit is 100ms. + + + + + Configure Supervision Report Wait Time. + Unit is 100ms. + Note: Issuing Basic Set, Sensor Binary Report or Notification Report(Access Control) via association groups uses Supervision encapsulation only if sending commands with S2(or higher security) encapsulation. + In other word, this parameter can be configured in any network, but works only in S2 (or higher security) network. + + + + + Control LED Indicator. Determine whether the LED flash or not when sending Basic Set, Sensor Binary Report, Notification Report (Access Control) or Wake Up Notification. + + + + + + + + Configure the low battery threshold. Induce battery report when battery level is less than or equal to threshold. Forward low battery report. + + + Set how often battery is reported in minutes. + + + + + + true + + + + + + + + + + diff --git a/config/aeotec/zw189.xml b/config/aeotec/zw189.xml new file mode 100644 index 0000000000..3a8bd1a00e --- /dev/null +++ b/config/aeotec/zw189.xml @@ -0,0 +1,39 @@ + + + + http://www.openzwave.com/device-database/0371:00bd:0004 + images/aeotec/zw189.png + https://products.z-wavealliance.org/products/3616 + CEPT (Europe) + ZW189-C + https://products.z-wavealliance.org/products/3616 + U.S. / Canada / Mexico + ZW189-A + Turn the primary controller of Z-Wave network into exclusion mode, press the Z-Wave Button on Range Extender 7. + Aeotec Range Extender 7 is a Z-Wave mesh network repeater which can extend the range of communication between Z-Wave products and assist other devices to reach each other in your Z-Wave network. + The Range Extender can also communicate securely via AES 128 wireless Z-Wave commands and supports Over-The-Air (OTA) firmware upgrades. + + Range Extender 7 + Press and hold the Z-Wave Button for 20 seconds and then release it. + Use this procedure only in the event that your primary network controller is missing or inoperable. + + Turn the primary controller of Z-Wave network into inclusion mode, press the Z-Wave Button on Range Extender 7. + + Initial version + + + + + + false + + + + + + + + + diff --git a/config/aeotec/zwa001.xml b/config/aeotec/zwa001.xml index 3665725ed1..8547f84c9d 100644 --- a/config/aeotec/zwa001.xml +++ b/config/aeotec/zwa001.xml @@ -1,31 +1,66 @@ - - - - - - Enable to send notifications to associated devices (Group 1) when the state of LED Bulb is changed. - - - - - +--> + + http://www.openzwave.com/device-database/0371:0001:0003 + images/aeotec/zwa001.png + https://products.z-wavealliance.org/products/2840/ + LED Bulb 6: Multi-White + Reset the device : +a) Please use this procedure only when the network primary controller is missing or otherwise inoperable. +b) Led bulb re-power 6 times (between 0.5-2 seconds each time); If the 6th power on, the led bulb flashes twice, which means that the resetting is successful. + + + Standard form factor and appearance of the light bulb with 800 lm output +Tunable white: dimmable from 5% to 100%, tunable from 2700K to 6500K. +Possible to be included in groups, scenes, or schedules +Suitable for indoor lighting: Corridors, Bedroom, Living Room, etc. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2843/LED Bulb Manul.pdf + + ZWA001-C + Remove for exclusion: +a) Set the Z-Wave network main controller into removing mode. +b) Led bulb re-power 3 times (between 0.5-2 seconds each time). +c) Wait a moment, the led bulb should be removed from the controller.Then the led bulb will flash once, dim to 5% first, and then increased to 100% after 5 seconds. + + Add for inclusion: +a) Set the Z-Wave network main controller into adding mode. +b) Power cycle once for led bulb(OFF->ON).The led bulb will flash twice and send node info frame. +c) Wait a moment, the led bulb should be added to the controller.Then the led bulb will flash once when it has been included into the network. + + + CEPT (Europe) + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2840/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2843/xml + + https://products.z-wavealliance.org/products/2843/ + U.S. / Canada / Mexico + ZWA001-A + + + + + Enable to send notifications to associated devices (Group 1) when the state of LED Bulb is changed. + + + + + Adjusting the color temperature in warm white color component. available value: 2700k to 4999k - - - + + + Adjusting the color temperature in cold white color component. available value:5000k to 6500k - - - - - - - + + + + + + + diff --git a/config/aeotec/zwa002.xml b/config/aeotec/zwa002.xml index 55f7f45f60..cf3cc67c70 100644 --- a/config/aeotec/zwa002.xml +++ b/config/aeotec/zwa002.xml @@ -1,58 +1,103 @@ - - - - - - User custom mode for LED animations - - - - - - Enable/Disable Strobe over Custom Color. - - - - - +--> + + http://www.openzwave.com/device-database/0371:0002:0103 + images/aeotec/zwa002.png + https://products.z-wavealliance.org/products/2880/ + U.S. / Canada / Mexico + Reset the Device. +1. Assuming led bulb was added to controller and was power on. +2. RGBW bulb re-power 6 times (between 0.5-2 seconds each time). +Note: ON -> OFF -> ON -> OFF -> ON -> OFF -> ON -> OFF -> ON -> OFF -> ON -> OFF -> ON +3. If the 6th power on, the led bulb change to Yellow color(into pairing process ), which means that the reset factory settings are successf. + +Using this action in case of the primary controller is missing or inoperable. + + ✓ Standard form factor and appearance of the light bulb with 800 lm output +✓ RGBW: dimmable from 5% to 100%, tunable from 1800K to 6500K, and 16 million colors +✓ Possible to be included in groups, scenes, or schedules +✓ Suitable for indoor lighting: Corridors, Bedroom, Living Room, etc. + Add for inclusion +1. Ensure the led bulb has been excluded outside the network. +2. Triggered by OFF ->ON (between 0.5-2 seconds each time) +3. LED solid yellow Color (0xFFFF00) during the pairing(Timeout is 10 seconds). + + Failure: +Blinks between 100% White and Red 0x0000FF color for 3 seconds (at a rate of 200ms per flash), Once 3 seconds have passed, the LED should return to a Warm White LED at 100% + Success: +Blinks between 100% White and Green 0x00FF00 color for 3 seconds (at a rate of 200ms per flash). Once 3 seconds have passed, the LED should return to a Warm White LED at 100%. + + LED Bulb 6:Multi-Colour + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2881/AA LED Bulb 6 说明书(RGBW-AL001)_转曲-2dd.pdf + Remove for exclusion +1. Assuming led bulb was added to controller. +2. Triggered by OFF -> ON -> OFF -> ON -> OFF -> ON (between 0.5-2 seconds each time). +3. LED Solid Purple/Violet Color (0xEE82EE) during the unpairing process. (Timeout is 10 seconds). + Failure: +Blinks between 100% White and Red 0x0000FF color for 3 seconds (at a rate of 200ms per flash), Once 3 seconds have passed, the LED should return to the last color ( memory status(color cc set)) of LED Bulb. + Success: +Blinks between 100% White and Blue 0x0000FF color for 3 seconds (at a rate of 200ms per flash). Once 3 seconds have passed, the LED should return to a Warm White LED at 100%. + + ZWA002-A + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2880/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2881/xml + + https://products.z-wavealliance.org/products/2881/ + CEPT (Europe) + ZWA002-C + + + + + User custom mode for LED animations + + + + + + Enable/Disable Strobe over Custom Color. + + + + + Set the rate of change to next color in Custom Mode. - - - + + + Set color that LED Bulb blinks in Blink Mode. - - - + + + Specifying the ramp rate when dimming using Multilevel Switch V1 CC in 100ms. - - - Enable to send notifications to associated devices (Group 1) when the state of LED Bulb is changed. - - - - - + + + Enable to send notifications to associated devices (Group 1) when the state of LED Bulb is changed. + + + + + Adjusting the color temperature in warm white color component. available value: 2700k to 4999k - - - + + + Adjusting the color temperature in cold white color component. available value:5000k to 6500k - - - - - - - + + + + + + + diff --git a/config/aeotec/zwa003.xml b/config/aeotec/zwa003.xml index 2eb2fc1f15..52a5dc7563 100644 --- a/config/aeotec/zwa003.xml +++ b/config/aeotec/zwa003.xml @@ -1,40 +1,75 @@ - - - - - - +--> + + http://www.openzwave.com/device-database/0371:0003:0102 + images/aeotec/zwa003.png + https://products.z-wavealliance.org/products/2817/ + TheNanoMote Quad is a wireless, portable and rechargeable scene switch. It can control a Z-Wave device, such as smart plug, smart dimmer with a Z-Wave gateway. You can also activate a scene like sleep scene, movie scene and entertainment scene with it. + To remove the NanoMote Quad from the Z-Wave network: +(1) Insert the LIR2450 battery. +(2) Set the Z-Wave network main controller into remove mode +(see Z-Wave controller operating manual). +(3) Triple click the a button, if the exclusion is successful, LED +will blink long. + + + + Included device: +1. Insert the LIR2450 battery. +2. Set the Z-Wave network main controller into learning mode (see Z-Wave network controller operating manual). +3. Pressing and holding a button for 3 seconds. +4. If the inclusion is successful, the LED will blink in green less than for 5 seconds and then keep on for 15 seconds. + + + NanoMote Quad + Pressing and holding a button for 20 seconds. Release the button after 20 seconds, LED will keep in yellow for 3 seconds. Scene Controller will be reset to factory defaults if you short press the button within this 3 seconds. +Please use this procedure only when the network primary controller is missing or otherwise inoperable. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2820/NanoMote Quad USER MANUAL .pdf + Pressing and holding a button for 3 seconds. Led will turn to green, +which means Scene Controller has been woken up. + U.S. / Canada / Mexico + ZWA003-A + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2817/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2820/xml + + https://products.z-wavealliance.org/products/2820/ + ZWA003-C + CEPT (Europe) + + + + + Set the low battery value. Range: 10% - 50%. - - - + + + Setting the duration value of the command switch multilevel. Available settings: 0-255. - - - Enable/disable the buzzer alarm when battery is running low - - - - - - - - - - - - - - - - - - + + + Enable/disable the buzzer alarm when battery is running low + + + + + + + + + + + + + + + + + + diff --git a/config/aeotec/zwa004.xml b/config/aeotec/zwa004.xml index a24f92a78b..9cae55b002 100644 --- a/config/aeotec/zwa004.xml +++ b/config/aeotec/zwa004.xml @@ -1,39 +1,75 @@ - - - - - - +--> + + http://www.openzwave.com/device-database/0371:0004:0102 + images/aeotec/zwa004.png + https://products.z-wavealliance.org/products/2811/ + Included device: +1. Insert the LIR2450 battery. +2. Set the Z-Wave network main controller into learning mode( see Z-Wave network controller operating manual). +3. Pressing and holding the button for 3 seconds. +4. If the inclusion is successful, the LED will blink in green less than for 5 seconds and then keep on for 15 seconds. + + + U.S. / Canada / Mexico + To remove the NanoMote One from the Z-Wave network: +(1) Insert the LIR2450 battery. +(2) Set the Z-Wave network main controller into remove mode +(see Z-Wave controller operating manual). +(3) Triple click the button, if the exclusion is successful, LED +will blink in orange for less than 5 seconds and then keep on +for 3 seconds. + + + + Pressing and holding the button for 20 seconds. Release the button after 20 seconds, LED will keep in yellow for 3 seconds. Scene Controller will be reset to factory defaults if you short press the button within this 3 seconds. +Using this procedure only in the event that the network primary controller is missing or otherwise inoperable. + NanoMote One + Pressing and holding Button for 3 seconds. Led will turn to green, +which means Scene Controller has been woken up. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2816/NanoMote One USER MANUAL .pdf + ZWA004-A + The NanoMote One is a wireless, portable and rechargeable scene switch. It can control a Z-Wave device, such as smart plug, smart dimmer with a Z-Wave gateway. You can also activate a scene like sleep scene, movie scene and entertainment scene with it. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2811/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2816/xml + + https://products.z-wavealliance.org/products/2816/ + ZWA004-C + CEPT (Europe) + + + + + Set the low battery value. Range: 10% - 50%. - - - Enable send central scene notification - - - - - + + + Enable send central scene notification + + + + + Setting the duration value of the command switch multilevel. Available settings: 0-255. - - - Enable/disable the buzzer alarm when battery is running low - - - - - - - - - - - - + + + Enable/disable the buzzer alarm when battery is running low + + + + + + + + + + + + diff --git a/config/aeotec/zwa005.xml b/config/aeotec/zwa005.xml index f4ea4dadff..564e051795 100644 --- a/config/aeotec/zwa005.xml +++ b/config/aeotec/zwa005.xml @@ -1,7 +1,38 @@ - +--> + + http://www.openzwave.com/device-database/0371:0005:0002 + images/aeotec/zwa005.png + https://products.z-wavealliance.org/products/2898/ + CEPT (Europe) + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2919/TriSensor user manual 20180416.pdf + Aeotec TriSensor is a universal Z-Wave Plus compatible product, consists of temperature, lighting and motion sensors, powered by a CR123A battery. It can be included and operated in any Z-Wave network with other Z-Wave certified devices from other manufacturers and/or other applications. By the built-in motion sensor, an alam will be sent to the gateway when the motion sensor is triggered. + + Press once TriSensor’s Action Button, the Purple LED will keep solid until whole network processing is complete. If the exclusion is successful, the LED will flash white -> green - +>white -> green and then LED will pulse a blue. If failed, the yellow LED lasts for 30 seconds, then the green LED flashes once. + + Press and hold the button at least 2s until Red Led is on and then release the button,device will send wakeup notification to controller if device is in a Z-Wave network. + ZWA005-C + TriSensor + Press once TriSensor’s Action Button. If it is the first installation, the yellow LED will keep solid until whole network processing is complete. If successful, the LED will flash white -> green -> white -> green, after 2 seconds finished. If failed, the yellow LED lasts for 30 seconds, then the green LED flashes once. +If it is the S2 encryption network, please enter the first 5 digits of DSK. + + 1. Power up the device. +2. Press and hold the button for 15s until Red Led is blinking,then release the button. Note: Please use this procedure only when the network primary controller is missing or otherwise inoperable. + + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2898/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2919/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2920/xml + + https://products.z-wavealliance.org/products/2919/ + ZWA005-A + U.S. / Canada / Mexico + https://products.z-wavealliance.org/products/2920/ + ZWA005-B + Australia / New Zealand + diff --git a/config/aeotec/zwa006.xml b/config/aeotec/zwa006.xml index 49c1cf9154..4b7a4636f6 100644 --- a/config/aeotec/zwa006.xml +++ b/config/aeotec/zwa006.xml @@ -1,111 +1,138 @@ - - - - - - +--> + + http://www.openzwave.com/device-database/0371:00B4:0003 + images/aeotec/zwa006.png + https://products.z-wavealliance.org/products/3067/ + CEPT (Europe) + Please use this procedure only when the primary controller is missing or inoperable. + +1. Make sure the device has been powered. +2. Press and hold the action button for 15 seconds. When the red LED turns on, release the button. Then, the device will enter factory reset mode. If the reset is successful, the LED will blink blue slowly. + + + + 1. Power on the device, and the power led will blink blue slowly. +2. Put the Z-Wave Primary Controller into inclusion mode (If you don’t know how to do this, refer to its manual) +3. Press and hold the action button, and when the yellow LED is on, release the button. It indicates the device has enter learn mode. +4. If added successfully, the power LED will remain green for 2 seconds, then turn off. + The Aeotec Smart Boost Timer Switch is a Z-Wave Plus enabled device and can be included/operated in any Z-Wave™ network with other Z-Wave™ certified devices from other manufacturers and/or other applications. All non-battery operated nodes within the network will act as repeaters regardless of vendor to increase reliability of the network. +The Aeotec Smart Boost Time Switch supports consumption meter function. When the device has been included in the network, it will report the consumption power periodically. It is also a high output countdown timer that can be used to control immersion heater elements or other electrical appliances rated up to 16A. On the product, four simple white LEDs are used to show the user how much time is left to run. Pressing the switch whilst the unit is operating allows the user to cancel the timing program,and the memory function of the timer will remember the last period selected. + + Smart Boost Timer Switch + ZWA006-C + 1. Power on the device. +2. Put the Primary Controller into exclusion mode (If you don’t know how to do this refer to its manual) +3. Press and hold the action button, and when the purple LED turns on, release the button. This indicates that the device has entered learn mode. If removal is successful, the blue LED will blink slowly. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3067/Smart Boost Timer Switch User Manual-V1.9.pdf + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3067/xml + + + + + + Action in case of power out. This parameter is used to configure the device state after power on. - - - - - - - + + + + + + + Configure LED (except boost) to be off irrespective of switch status. - - - - - - + + + + + + Timer acts as auto off after specified minutes, setting is set in seconds. 0 - no auto off with timer. 1 ~ 86400 auto off after this specified time, unit second. - - - + + + Current and overload protection - - - - - + + + + + Configure boost time interval, unit minute. When user press the boost button one time, the boost time will increase 30 (the value can be changed) minutes. - - - + + + This parameter is used to configure the power led threshold, unit W. When the load <= 100W, the power led will indicate yellow. When the load > 100W, the power led will indicate orange. When no load, the power led will indicate white. - - - + + + Threshold settings for energy kWh. When the energy above the threshold, it will send a meter report command to gateway. 0 - disable report. 1 ~ 10000 - enable report. - - - + + + Threshold settings for Watt automatic report, unit W. When Watt above the threshold, it will send a meter report command to gateway. 0 - disable report. 1 ~ 2500 - enable report. - - - + + + Threshold settings for Current automatic report, unit 0.1A. When current above the threshold, it will send a meter report command to gateway. 0 - disable report. 1 ~ 150 - enable report. - - - + + + Watt automatic report interval, unit second. 0 - disable. 65535 - enable. - - - + + + kWh automatic report interval, unit second. 0 - disable. 65535 - enable. - - - + + + Voltage automatic report interval, unit second. 0 - disable. 65535 - enable. - - - + + + Current automatic report interval, unit second. 0 - disable. 65535 - enable. - - - - - - - - - + + + + + + + + + diff --git a/config/alfred/DB2.xml b/config/alfred/DB2.xml new file mode 100644 index 0000000000..08e550e21e --- /dev/null +++ b/config/alfred/DB2.xml @@ -0,0 +1,41 @@ + + + DB2 Z-Wave Accessory + Connect a DB2 or DB2-B to your smart hub using this easy to install Z-Wave module + http://www.openzwave.com/device-database/021D:0001:0003 + images/alfred/DB2.png + https://alfredinc.com/collections/products/products/zwave-module + https://alfredinc.com/pages/support + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3324/Alfred Z-Wave Plus System Integrators Guide V5.1.pdf + + Follow the user guide of hub to enter inclusion mode. +-Operate on lock following guide below: +1.Enter master mode(refer to programming instruction) +2.Input “8” to enter “function extension settings” +3.Input “1” to join a network. + Follow the user guide of hub to enter exclusion mode. +-Operate on lock following guide below: +1.Enter master mode(refer to programming instruction) +2.Input “8” to enter “function extension settings” +3.Input “2” to log off a network. + Please use this procedure only when the network primary controller is missing or inoperable. +-Operations on lock +1.Open the door and keep the lock in "unlock" status +2.Open battery box and find the reset button. +3.Use a sharp thing to press and hold the reset button. +4.Keep holding the reset button and remove a battery from battery box then replace it. +5.Keep holding the reset button until hearing voice guide. + https://products.z-wavealliance.org/products/3324 + + Initial file based on z-wavealliance.org + + + + + + + + + + diff --git a/config/assa_abloy/ConexisL1.xml b/config/assa_abloy/ConexisL1.xml index 812dce4a4b..de2a7111d4 100644 --- a/config/assa_abloy/ConexisL1.xml +++ b/config/assa_abloy/ConexisL1.xml @@ -1,68 +1,121 @@ - - - - - - - Volume of the keypad tones and any voice prompts (default = 3, high) - - - - - - Enable or disable the Auto relock feature (default = 255, enable) - - - - - After successful local unlock, automatically relock after the specified time (default = 7 seconds) - - - - Number of incorrect tags before lock will accept before sending TAMPER Alarm. - When number of wrong code entries is exceeded, lock will disable for the time specified by Wrong tag timeout parameter. (5 = default) - - - - - - - - - - - - - - - - - - - - - - - - Number of seconds unit will be inoperable after number of Wrong tag attempts is exceeded (30 = default) - - - - - - - - - - - - - - - + + + http://www.openzwave.com/device-database/0129:0002:6600 + images/assa_abloy/ConexisL1.png + https://products.z-wavealliance.org/products/2535/ + Features: + +Control Via Smartphone - Configure, Control and unlock your Smart Door Lock from your smartphone via our secure Bluetooth App. + +Keyless - Say goodbye to keys, Open your Smart Door lock via your smartphone, Key Card or Key Tag. + +Simple to Fit - Engineered for easy installation. + +Connectivity - Compatible with the Yale Smart Home system. (Yale module sold separately) + +Security as standard - Built in tamper alarm, PAS24 accredited. + +Battery Operated - Powered by 4 AA batteries and a warning when they're running low. + +Battery Backup - A 9v battery connection port can be used to power the Smart door lock in the event of flat batteries. + +Secure Push & Turn Thumbturn - Engineered to give additional convenience and security to your door + CEPT (Europe) + SD-L1000-CH + Put the Z-Wave controller into add or learn mode + +Press the R button on the lock 3 times quickly (within 1.5 seconds) + +Refer to the operation manual of the Z-Wave controller to complete the learn in process + +For more information on this please visit: +www.yale.co.uk/smart-living + + Only use this when the existing Z-Wave controller is missing or inoperable + + Lift up the lever handle + +While holding the handle up, press the R button 3 times within 1.5 seconds + + Put the existing Z-Wave controller into Remove Mode + +Press the R button on the lock 3 times quickly (within 1.5 secs) + +The lock is now ready to be added to a new Z-Wave controller + +For more information on this please visit: +www.yale.co.uk/smart-living + + + Conexis L1 + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2535/Instruction Manual V2a.pdf + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2535/xml + + + + + + + Volume of the keypad tones and any voice prompts (default = 3, high) + + + + + + Enable or disable the Auto relock feature (default = 255, enable) + + + + + After successful local unlock, automatically relock after the specified time (default = 7 seconds) + + + + Number of incorrect tags before lock will accept before sending TAMPER Alarm. + When number of wrong code entries is exceeded, lock will disable for the time specified by Wrong tag timeout parameter. (5 = default) + + + + + + + + + + + + + + + + + + + + + + + + Number of seconds unit will be inoperable after number of Wrong tag attempts is exceeded (30 = default) + + + + + + + + + + + + + + + diff --git a/config/assa_abloy/KeyfreeConnected-plus.xml b/config/assa_abloy/KeyfreeConnected-plus.xml index 7a198ffe4a..e0d4b347fb 100644 --- a/config/assa_abloy/KeyfreeConnected-plus.xml +++ b/config/assa_abloy/KeyfreeConnected-plus.xml @@ -1,45 +1,105 @@ - - - - - - - - Volume of the keypad tones and any voice prompts (default = 3, high) - - - - - - Enable or disable the Auto relock feature (default = 255, enable) - - - - - After successful local unlock, automatically relock after the specified time (default = 7 seconds) - - - After successful remote unlock, automatically relock after the specified time (default = 10 seconds) - - - - - - - - - - - - - - - + + + http://www.openzwave.com/device-database/0129:0001:0007 + images/assa_abloy/KeyfreeConnected-plus.png + https://products.z-wavealliance.org/products/2576/ + Put the Z-Wave controller into add mode + +Enter the Master code on the lock, followed by # + +Press the 4 button, followed by # + +Press the 1 button followed by # + +Refer to the operation manual of the Z-Wave controller to complete the add/inclusion process + +For more information on this please visit: +www.yale.co.uk/smart-living + + Put the Z-Wave controller into remove mode + +Enter the Master code on the lock, followed by # + +Press the 4 button, followed by # + +Press the 2 button followed by # + +Refer to the operation manual of the Z-Wave controller to complete the remove/exclusion process + +For more information on this please visit: +www.yale.co.uk/smart-living + + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2743/Instruction Manual V2b.pdf + Keyfree Connected Ready smart lock + +Features + + Battery operated + Low battery indicator with emergency battery connection + User codes and settings remain if batteries are replaced + 3 minute lock out if code is entered incorrectly 5 times + Tamper alarm + For use on UPVC & Composite Doors + 2 year guarantee + + Keyfree Connected + Enter the Master code on the lock, followed by # + +Press the 4 button, followed by # + +Press the 0 button followed by # + +Please use this procedure only when the network controller is missing or inoperable + CEPT (Europe) + YD-01-CON + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2576/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2743/xml + + https://products.z-wavealliance.org/products/2743/ + CEPT (Europe) + YKFCON + + + + + + + Volume of the keypad tones and any voice prompts (default = 3, high) + + + + + + Enable or disable the Auto relock feature (default = 255, enable) + + + + + After successful local unlock, automatically relock after the specified time (default = 7 seconds) + + + After successful remote unlock, automatically relock after the specified time (default = 10 seconds) + + + + + + + + + + + + + + + diff --git a/config/assa_abloy/PushButtonDeadbolt.xml b/config/assa_abloy/PushButtonDeadbolt.xml index 42cc805212..0c8fbcd6b5 100644 --- a/config/assa_abloy/PushButtonDeadbolt.xml +++ b/config/assa_abloy/PushButtonDeadbolt.xml @@ -1,20 +1,38 @@ - + http://www.openzwave.com/device-database/0129:0000:0004 images/assa_abloy/PushButtonDeadbolt.png https://products.z-wavealliance.org/products/687/ - Key Free Pushbutton Deadbolt, Integrated Z-Wave + Yale Real Living® Assure Lock™ Interconnect combines electronic deadbolts with the convenience of a passage lever for panic proof egress. From the inside, both the latchbolt and the deadbolt are retracted simultaneously in a single motion for a quick and easy exit. Ships with Z-Wave Plus Smart Module. U.S. / Canada / Mexico Yale/YRD/ 210 http://www.yalerealliving.com - Yale YRD110-ZW-US + Yale Real Living® Assure Lock™ Interconnected Z-Wave Enabled Push Button Deadbolt Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/687/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1039/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1971/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3239/xml https://products.z-wavealliance.org/products/1039/ YRD110-ZW-US U.S. / Canada / Mexico + https://products.z-wavealliance.org/products/3239/ + Enter the 4-8 master Pin code followed by the gear key. +Press the 7 key followed by the gear key +Press the 1 key followed by the gear key + Remove the battery cover and batteries. +Remove the interior escutcheon to access the reset button. +The reset button is located above the PCB cable connector. +While pressing the reset button for a minimum of 3 seconds, reinstall batteries. Release reset button. +Replace battery cover. +Please use this procedure only when the network primary controller is missing or otherwise inoperable + YRC216-ZW2 + U.S. / Canada / Mexico + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3239/YRC216_YaleRealLivingAssureDeadbolt_Z-WavePlus_SystemIntegratorsGuide.pdf + Enter the 4-8 digit master pin code followed by the gear key +Press the 7 key followed by the gear key +Press the 3 key followed by the gear key - - - Disable the door sensor alarm function. - - - - - - - - - - - seconds; after successful code entry and unit unlocks, it will automatically re-lock after specified time (30 = default value) - - - + + + Disable the door sensor alarm function. + + + + + + + + + + + seconds; after successful code entry and unit unlocks, it will automatically re-lock after specified time (30 = default value) + + + The number of invalid code entries lock will accept before sending TAMPER Alarm. When number of wrong code entries is exceeded, lock will disable keypad for the time specified by Shutdown Time parameter. (5 = default) - - - - - - - - - - - + + + + + + + + + + + The number of invalid code entries lock will accept before sending TAMPER Alarm. When number of wrong code entries is exceeded, lock will disable keypad for the time specified by Shutdown Time parameter. (5 = default) - - - - - - number of seconds unit will be inoperable after number of wrong code entries is exceeded (30 = default) - - - + + + + + + number of seconds unit will be inoperable after number of wrong code entries is exceeded (30 = default) + + + The number of invalid code entries lock will accept before sending TAMPER Alarm. When number of wrong code entries is exceeded, lock will disable keypad for the time specified by Shutdown Time parameter. (5 = default) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + diff --git a/config/august/asl-03.xml b/config/august/asl-03.xml index 1eec43c793..fe8ec05ce6 100644 --- a/config/august/asl-03.xml +++ b/config/august/asl-03.xml @@ -1,10 +1,45 @@ - - - - - - - - - + + + http://www.openzwave.com/device-database/033F:0001:0001 + images/august/asl-03.png + https://products.z-wavealliance.org/products/2624/ + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2624/August Z-Wave Required Documentation.pdf + Any operation (manual, RF, etc.) will wake up the lock. + August Smart Lock Rev 3 + In order to include the August Smart Lock on to a Z-Wave network the user will have to do the following: +1. Open the August app +2. Go to the Lock Settings screen +3. Select Z-Wave Settings +4. Select Add To A Z-Wave Network +5. Put the controller into inclusion mode and select My Hub is in Inclusion Mode on the August app + In order to exclude the August Smart Lock from a Z-Wave network the user will have to do the following: +1. Open the August app +2. Go to the Lock Settings screen +3. Select Z-Wave Settings +4. Select Remove Z-Wave Device +5. Put the controller into exclusion mode and select My Hub is in Exlusion Mode on the August app + Give your customer total control over their front door, from anywhere. The August Smart Lock Pro is the leading Z-Wave Plus retrofit smart lock. You can lock and unlock your door, create virtual keys for guests, and keep track of who comes and goes with a 24/7 activity log, all from your iOS or Android smartphone. The August Smart Lock Pro features Z-Wave Plus and BLE and it is the only lock to support the three leading voice-assistants, Siri, Google Assistant, and Amazon Alexa. The lock quickly installs on the inside of your door with just a screwdriver. Keep your exterior door hardware exactly as it is and use your traditional key any +time. + ASL-03 + In order to reset the August Smart Lock the user will have to do the following: +1. Open the August app +2. Go to the Lock Settings screen +3. Select Z-Wave Settings +4. Select Remove Z-Wave device +5. Select My Hub Is No Longer Working +6. Caution: Resetting a Z-Wave device without telling the hub can cause performance issues. Use this procedure only when the Z-Wave hub is missing or otherwise inoperable. +7. Select Reset Z-Wave Device +8. On the Reset Z-Wave Device? prompt select Reset + U.S. / Canada / Mexico + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2624/xml + + + + + + + + + diff --git a/config/config-template.xml b/config/config-template.xml new file mode 100644 index 0000000000..191900a5c8 --- /dev/null +++ b/config/config-template.xml @@ -0,0 +1,76 @@ + + + + + + http://www.openzwave.com/device-database/XXXX:XXXX:XXXX + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Small Description of what this config param does. + + + + + Short Help Description + + + + + + + Short Help Description + + + + + Help text that describes what this Param does over all + + + + What Bit 1 Does + + + + What Bit 5 Does + + + + + + + false + + + + + + + + + diff --git a/config/danfoss/z.xml b/config/danfoss/z.xml index f534690185..c605adcb6b 100644 --- a/config/danfoss/z.xml +++ b/config/danfoss/z.xml @@ -1,4 +1,4 @@ - + http://www.openzwave.com/device-database/0002:0003:0005 images/danfoss/z.png @@ -6,18 +6,20 @@ http://heating.consumers.danfoss.com/xxTypex/585379.html 014G0013 CEPT (Europe) - Devolo Connect + Danfoss Living Connect Z v1.06 014G0013 Electronic radiator thermostat Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/932/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/967/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1035/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1258/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1506/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1507/xml - https://products.z-wavealliance.org/products/1035/ + https://products.z-wavealliance.org/products/1507/ 014G0013 CEPT (Europe) - https://products.z-wavealliance.org/products/1258/ + https://products.z-wavealliance.org/products/1506/ CEPT (Europe) 014G0801 diff --git a/config/device_classes.xml b/config/device_classes.xml index e5514a2058..e6985d1b0a 100644 --- a/config/device_classes.xml +++ b/config/device_classes.xml @@ -1,72 +1,88 @@ - - - - - + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - + + + + + - + - + - - - + + + - + - - - - - - + + + + + + - + - + + + - + + + + - - - + + + + + + - - - - - - + + + + + + + + + + + @@ -74,70 +90,73 @@ - - - + + + - - + + - + - + - + - - - + + + - - - - - - - + + + + + + + + + + + - + - - - - - - - - - - + + + + + + + + + + - - + @@ -147,14 +166,16 @@ - - - - - - - - + + + + + + + + + + - + @@ -239,4 +260,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/config/device_configuration.xsd b/config/device_configuration.xsd index 09bfdcb4be..21c28b8063 100644 --- a/config/device_configuration.xsd +++ b/config/device_configuration.xsd @@ -94,6 +94,16 @@ + + + + + + + + + + diff --git a/config/devolo/mt02755.xml b/config/devolo/mt02755.xml index 36bbaafe62..4fd2679cb1 100644 --- a/config/devolo/mt02755.xml +++ b/config/devolo/mt02755.xml @@ -1,4 +1,49 @@ - + + + http://www.openzwave.com/device-database/0175:0020:0002 + images/devolo/mt02755.png + https://products.z-wavealliance.org/products/2226/ + 1. Have Z-Wave™ Controller entered inclusion mode. +2. Pressing the tamper key three times within 1.5 +seconds to enter the inclusion mode. +3. After add successful, the device will wake to +receive the setting command from Z-Wave™ +Controller about 20 seconds. + + MT02755 + Notice: Use this procedure only in the event +that the primary controller is lost or +otherwise inoperable. +1. Pressing tamper key four times within 1.5 seconds +and do not release the tamper key in the 4 th +pressed, and the LED will light ON. +2. After 3 seconds the LED will turn OFF, after that +within 2 seconds, release the tamper key. If +successful, the LED will light ON one second. +Otherwise, the LED will flash once. +3. IDs are excluded and all settings will reset to +factory default. + MT02755 has temperature and humidity,based on Z-Wave™ technology. +It is the Z-Wave™ plus product, it support the security, OTA... Those newest features of the Z-Wave™ technology. Z-Wave™ is a wireless communication protocol designed for home automation, specifically to remotely control applications in residential and light commercial environments. The technology uses a low-power RF radio embedded or retrofitted into home electronics devices and systems, such as lighting, home access control, entertainment systems and household appliances. +This product can be included and operated in any Z-Wave™ network with other Z-Wave™ certified devices from other manufacturers and/or other applications. All non-battery operated nodes within the network will act as repeaters regardless of vendor to increase reliability of the +network. + + When the device power on, the device will wake about 20 seconds. In +this duration, the controller can communicate with the device. Normally +the device is always sleeping to save the battery energy. + + 1. Have Z-Wave™ Controller entered exclusion mode. +2. Pressing tamper key three times within 1.5 seconds +to enter the exclusion mode. +Node ID has been excluded. + + CEPT (Europe) + Humidity Sensor + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2226/MT02756_MT02755_Manual.pdf + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2226/xml + + - +--> + + http://www.openzwave.com/device-database/0175:000A:0004 + images/devolo/mt02758.png + https://products.z-wavealliance.org/products/2308/ + 1. Have Z-Wave™ Controller entered exclusion mode. +2. Pressing tamper key three times within 1.5 seconds to enter the exclusion mode. +Node ID has been excluded. + Siren MT02758 is a wireless siren, based on Z-Wave™ technology. It is the Z-Wave™ plus product, it support the security, OTA... Those newest features of the Z-Wave™ technology. + Siren + CEPT (Europe) + MT02758 + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2308/MT02758_manual.pdf + Notice: Use this procedure only in the event that the primary controller is lost or otherwise inoperable. +1. Pressing tamper key four times within 1.5 seconds and do not release the tamper key in the 4 pressed, and the LED will light ON. +2. After 3 seconds the LED will turn OFF, after that within 2 seconds, release the tamper key. If successful, the LED will light ON one second. Otherwise, the LED will flash once. +3. IDs are excluded and all settings will reset to factory default. + 1. Have Z-Wave™ Controller entered inclusion mode. +2. Pressing tamper key three times within 1.5 seconds +to enter the inclusion mode. +3. After add successful, the LED will light ON 1 second + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2308/xml + + diff --git a/config/devolo/mt2756.xml b/config/devolo/mt2756.xml index 28952bb52a..095ef9bac1 100644 --- a/config/devolo/mt2756.xml +++ b/config/devolo/mt2756.xml @@ -1,4 +1,49 @@ - + + + http://www.openzwave.com/device-database/0175:0021:0002 + images/devolo/mt2756.png + https://products.z-wavealliance.org/products/2227/ + 1. Have Z-Wave™ Controller entered inclusion mode. +2. Pressing the tamper key three times within 1.5 +seconds to enter the inclusion mode. +3. After add successful, the device will wake to +receive the setting command from Z-Wave™ +Controller about 20 seconds. + + MT02756 has temperature and humidity,based on Z-Wave™ technology. +It is the Z-Wave™ plus product, it support the security, OTA... Those newest features of the Z-Wave™ technology. Z-Wave™ is a wireless communication protocol designed for home automation, specifically to remotely control applications in residential and light commercial environments. The technology uses a low-power RF radio embedded or retrofitted into home electronics devices and systems, such as lighting, home access control, entertainment systems and household appliances. +This product can be included and operated in any Z-Wave™ network with other Z-Wave™ certified devices from other manufacturers and/or other applications. All non-battery operated nodes within the network will act as repeaters regardless of vendor to increase reliability of the +network. + + When the device power on, the device will wake about 20 seconds. In +this duration, the controller can communicate with the device. Normally +the device is always sleeping to save the battery energy. + + Flood Sensor + MT02756 + CEPT (Europe) + 1. Have Z-Wave™ Controller entered exclusion mode. +2. Pressing tamper key three times within 1.5 seconds +to enter the exclusion mode. +Node ID has been excluded. + + Notice: Use this procedure only in the event +that the primary controller is lost or +otherwise inoperable. +1. Pressing tamper key four times within 1.5 seconds +and do not release the tamper key in the 4 th +pressed, and the LED will light ON. +2. After 3 seconds the LED will turn OFF, after that +within 2 seconds, release the tamper key. If +successful, the LED will light ON one second. +Otherwise, the LED will flash once. +3. IDs are excluded and all settings will reset to +factory default. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2227/MT02756_MT02755_Manual.pdf + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2227/xml + + - - - - - - - - - - + + + http://www.openzwave.com/device-database/021F:0002:0003 + images/dome/0002.png + https://products.z-wavealliance.org/products/2158/ + Press and hold the open/close button for at least 10 seconds then release. The Shut-Off’s memory will be erased to factory settings. A flashing light indicates a successful factory reset. Beware that resetting your device will disconnect it from your system. Only do this if the controller is missing or otherwise unreachable! + The Dome™ Home Automation DMWV1 Water Main Shut-off is designed to fit over existing ¼ turn ball-valves for pipes sized up to 1½ inch. No professional plumbing contractor is required- it can be installed by a homeowner with just a screwdriver. This device requires a Z-Wave Certified hub for operation. When configured with a Water Leak Sensor, the Water Main Shut-off can automatically cut off the supply to limit the damage. You can also remotely control the valve position using your smarthome system mobile app. Extra-long Z-Wave wireless range (up to 150 ft) allows you to place it where it’s needed without worrying if the signal is reaching your Z-Wave Hub. Also functions as Z-Wave signal extender. Dome™ DMWV1 Water Main Shut-off comes with a 1-year limited warranty. Measurements in inches: 2.5 x 3.5 x 6. Dome™ Home Automation Z-Wave devices give your family peace of mind and security you can count on. With Dome™, you’re always connected and always covered. + +• Installs over existing valve without need of a plumber using just a screw driver. Works with ¼ turn ball-valves on pipes sized up to 1½ inch +• Open/Close valve control allowing for automatic water shut-off when leaks are detected as well as on demand control using your smarthome mobile app. +• Up to 150-foot range. Functions as Z-Wave signal extender +• Z-Wave Plus Certified. Requires a Z-Wave Certified Hub to operate + + DMWV1 + 1. Follow the instructions for your Z-Wave certified Controller to enter exclusion mode. +2. When prompted, press the “open/close” button on the Shut-Off quickly 3 times in a row. + U.S. / Canada / Mexico + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2158/Dome Water Main Shut-Off Advanced Manual.pdf + 1 For proper inclusion, bring the Water Main Shut-Off to the final location where it will be used. * +2 Follow the instructions for your Z-Wave controller to enter inclusion mode. +3 Make sure the Water Main Shut-Off is powered on, and when prompted by your controller, press the “open/close” button quickly 3 times in a row. The LED will stop blinking and stay on continuously upon successful inclusion. + +*For non Z-Wave Plus networks, please consult the owner’s manual for your primary controller to determine the best method and location for adding the Water Main Shut-Off to your Z-Wave network. + Water Main Shut-Off + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2158/xml + + + + + + + + + + + + + diff --git a/config/dome/0085.xml b/config/dome/0085.xml index 5c92670979..374aa4999b 100644 --- a/config/dome/0085.xml +++ b/config/dome/0085.xml @@ -1,40 +1,74 @@ - - - + This parameter sets the total amount of time the Leak Sensor will beep and light its LED in the event of a leak. 0 Leak Sensor beeps until water is removed. 1 to 255 in Minutes. - + This parameter defines the amount of time the Leak Sensor remains quiet between each Reminder Alarm. - + This parameter sets the amount of time the Leak Sensor beeps before it is muted. - + This parameter sets the length of each beep after the Initial Alarm. - + This parameter enables or disables the audible alarm (beeping) functionality of the Leak Sensor. - + This parameter enables or disables the Leak Sensor. If disabled, the device will not respond in any way to detected leaks. @@ -42,7 +76,7 @@ - + This parameter defines the value sent by the BASIC_SET command to Association Group 2. 0 Turn Off Device. @@ -54,10 +88,10 @@ - - - - + + + + diff --git a/config/dome/0086.xml b/config/dome/0086.xml index af824b1f7c..775bcfb52f 100644 --- a/config/dome/0086.xml +++ b/config/dome/0086.xml @@ -1,12 +1,52 @@ - - + + + http://www.openzwave.com/device-database/021F:0086:0003 + images/dome/0086.png + https://products.z-wavealliance.org/products/1847/ + The Dome™ Home Automation DMMZ1 Mouser is a powerful rodent electric trap with Z-Wave technology built-in. It kills mice, rats and other rodents quickly, cleanly and humanely with a powerful jolt of electricity. Simply set bait, turn on and place in desired location. When connected to Z-Wave Certified Hub, once the trap is full, it sends out a notification to your smarthome system. You can easily dispose of Mouser’s contents without ever having to touch them. Use the top handle and tip to dispose of caught rodents. Specially designed removable and washable bait tray will allow you to easily replace the bait and set it back up. It operates on 4 AA batteries (not included) and is optimised to last over 50 uses. Mouser features extra-long Z-Wave wireless range (up to 150 ft) and Dome™ DMMZ1 Mouser comes with a 1-year limited warranty. Measurements in inches: 8.75 x 4.5 x 5. Dome™ Home Automation Z-Wave devices give your family peace of mind and security you can count on. With Dome™, you’re always connected and always covered. +• Humanely kills mice, rats and other rodents with a powerful electric shock and sends an alert to your smarthome system when the trap needs to be emptied +• Easy to use: set bait, turn on and place in desired location +Touch free: hold handle and tip to dispose of contents, then set it again +• Up to 150-foot Z-Wave range. Operating Temperature: 32°F - 112°F. Powered by 4 AA batteries (not included) enabling it to be triggered over 50 times +• Z-Wave Plus Certified. Works as a stand alone electronic mouse trap but requires a Z-Wave Certified Hub for notification functionality +• Tested to work with SmartThings, Vera, Staples Connect, HomeSeer, Nexia, Piper, URC, Harmony. Not supported by Wink, DSC, ADT Pulse, 2Gig, Napco, Interlogix, Honeywell (Dome is not associated with listed brands) + + Follow the instructions for your Z-Wave Certified controller to enter inclusion mode. When prompted by the controller: +1. Bring the Mouser to within 10’ of your Z-Wave controller for the inclusion process. After successful pairing, the device can be brought to the desired location. +2. Remove top cover by sliding it back and lifting up. +3. Insert batteries. +4. Press the CONNECT BUTTON quickly 3 times in a row. +5. The LED INDICATOR will flash five times indicating inclusion + + If needed, the Mouser can be reset locally by following these steps. Only do this when your Z-Wave controller is disconnected or otherwise unreachable. Beware that resetting your device will disconnect it from the system: +1. Remove the TOP COVER and confirm that your Mouser is powered up. +2. Press and hold the CONNECT BUTTON for at least 10 seconds then release. A flashing LED INDICATOR indicates a successful factory reset. +3. The Mouser’s memory will be erased to factory settings. + + DMMZ1 + If needed, the Mouser can be reset locally by following these steps. Only do this when your Z-Wave controller is disconnected or otherwise unreachable. Beware that resetting your device will disconnect it from the system: +1. Remove the TOP COVER and confirm that your Mouser is powered up. +2. Press and hold the CONNECT BUTTON for at least 10 seconds then release. A flashing LED INDICATOR indicates a successful factory reset. +3. The Mouser’s memory will be erased to factory settings. + U.S. / Canada / Mexico + Follow the instructions for your Z-Wave Certified controller to enter exclusion mode. +When prompted by the controller: +1. Remove top cover by sliding it back and lifting up. +2. Press the CONNECT BUTTON quickly 3 times in a row. +The LED INDICATOR will flash five times indicating exclusion/disconnection. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1847/Mouser API Manual.pdf + Dome Mouser + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1847/xml + + - + This parameter defines the value sent by the BASIC_SET command to Association Group 2. 0 Turn Off Device. @@ -14,7 +54,7 @@ 255 Turn On Device. - + This parameter sets firing mode of the Mouser. Two firing modes are available: in the first (Continuous Fire,) electricity is passed continuously for the entire duration, @@ -23,34 +63,33 @@ - + This parameter defines how long the Mouser will fire continuously before it starts to burst-fire - + This parameter enables or disables the indicator LED alarm when the trap is tripped. - + This parameter sets the amount of time the LED Indicator blinks after the trap is tripped. 0 LED Blinks Until Trap is Reset. 1 to 255 in Hours. - - - - - + + + + diff --git a/config/dome/0088.xml b/config/dome/0088.xml index 5b79ec5bc6..b72ca59531 100644 --- a/config/dome/0088.xml +++ b/config/dome/0088.xml @@ -1,35 +1,63 @@ - - + + + http://www.openzwave.com/device-database/021F:0088:0003 + images/dome/0088.png + https://products.z-wavealliance.org/products/2059/ + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2059/Dome Siren Manual.pdf + The Dome™ Home Automation DMS01 Siren offers ten user selectable sounds with three volume levels (at up to 105dB) and adjustable siren timeout (30/60/300 seconds or infinite). It includes a functionality of an alarm siren, doorbell and an audible chime notification when door/window opens (advanced settings subject to Z-Wave Hub compatibility). Additional visual notification is provided by built-in flashing LED’s when triggered. One of a kind device on the market with 100% battery operation allowing for easy installation anywhere in your home. There is a 3-year battery life, so you can always be confident that your siren has power. Extra-long Z-Wave wireless range (up to 150 ft) allows you to place it where it’s needed without worrying if the signal is reaching your Z-Wave Hub. Dome™ DMS01 Siren comes with a 1-year limited warranty. Measurements in inches: 2.625 x 2.625 x 1.125. Dome™ Home Automation Z-Wave devices give your family peace of mind and security you can count on. With Dome™, you’re always connected and always covered. + Follow the instructions for your Z-Wave certified Controller to enter exclusion mode. +When prompted by the Controller: +1. Remove the Back Plate of the Siren. +2. Press the Connect Button quickly 3 times in a row. +The LED Ring will flash five times indicating exclusion/disconnection. + U.S. / Canada / Mexico + Follow the instructions for your Z-Wave certified Controller to enter inclusion mode. +When prompted by the Controller: +1. For proper inclusion, bring the Siren to the final location where it will be used. * +2. Remove the Back Plate of the Siren. +3. Remove the Battery Tabs. +4. Press the Connect Button quickly 3 times in a row. +The LED Ring will flash five times indicating inclusion. +*For non Z-Wave Plus networks, please consult the owner’s manual for your primary controller to determine the best method and location for adding the Siren to your Z-Wave network. + Dome Z-Wave Plus Siren + To disconnect from the Z-Wave Network and restore factory default settings: +1. Open the Back Plate and make sure the Siren is powered. +1. Hold the Connect Button for 10 seconds until the LED Ring blinks once, then release the button. +Only do this if the controller is missing or otherwise unreachable! + DMS01 + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2059/xml + + - + This parameter sets the volume of the Siren (primary) sound. There are three possible volume levels available. - - + This parameter defines the length of the Alarm/primary notification. - + This parameter defines the number of times the Chime/Secondary Notification will play. - + This parameter sets the volume of the Chime (secondary) sound. There are three possible volume levels available. - + The Siren offers ten different sounds to use as the Siren (primary) notification. This parameter sets the Siren (primary) notification sound. @@ -45,7 +73,7 @@ - + If Parameter 7 is set to 02, the Siren will play a secondary chime sound instead of the main alarm. The Siren offers ten different sounds to use as the Chime (secondary) notification. @@ -62,28 +90,28 @@ - + This Parameter toggles between the Primary and Secondary notification sound to be played when the Siren receives a BINARY_SWITCH_SET(FF) command. - - + + - + This Parameter enables or disables the Flashing LED Ring (strobe) accompanying the Primary Notification. - - + + - + This Parameter enables or disables the Flashing LED Ring (strobe) accompanying the Secondary Notification. - - + + - - - + + + diff --git a/config/dome/0201.xml b/config/dome/0201.xml index d91d783211..e618f06586 100644 --- a/config/dome/0201.xml +++ b/config/dome/0201.xml @@ -1,94 +1,149 @@ - - - - - - - - This parameter enables or disables the LED Indicator flashing to indicate opening and closing events. - The Door/Window Sensor will always flash the LED Indicator for inclusion, exclusion, tamper, and other system events. - - - - - - - This parameter switches the Notification or Binary Sensor report sent when the door opens or closes. - If this parameter is set to 01, the Door/Window Sensor will report closed instead of open when the Magnet and Sensor are pulled apart. - - - - - - - By default, the Door/Window Sensor uses the Notification command class to communicate open/close and tamper events. - If this Parameter is set to 1, the device will instead use the Binary Sensor command class. - - - - - - - - The Door/Window Sensor can also monitor and report ambient temperature conditions. - However, temperature sensing functionality is disabled by default to save battery life, and this configuration parameter is used to enable or disable this feature. - - - - - - - This Configuration Parameter can offset the temperature value reported by +/- 125 degrees to compensate for temperature variances in a room - for example, the temperature near the ceiling in a room is significantly higher than the average temperature of the same room. - This Parameter accepts a signed 8-bit value with an absolute value of up to 125, and its units are Dependant on Configuration Parameter 07. - Temperature Offset. - 0 to 125 : 0 to 125 degrees. - 255 to 130 : -1 to -125 degrees. - - - - The Door/Window Sensor can report temperature values in either Celsius or Fahrenheit, and this parameter allows the user to decide which unit is used. - - - - - - This parameter sets the value sent by the Basic Set command to Association Group 2 (for more information, see Association Group Info.). - 0 Turn Off Device. - 1 to 99 Set Device to Value. - 255 Turn On Device. - - - - - This parameter sets the value sent by the Basic Set command to Association Group 4. - The Door/Window Sensor sends a Basic Set command to Association Group 4 when the door or window opens (for more information, see Association Group Info.). - 0 Turn Off Device. - 1 to 99 Set Device to Value. - 255 Turn On Device. - - - - - This parameter sets the value sent by the Basic Set command to Association Group 4. - The Door/Window Sensor sends a Basic Set command to Association Group 4 when the door or window opens (for more information, see Association Group Info.). - 0 Turn Off Device. - 1 to 99 Set Device to Value. - 255 Turn On Device. - - - - - - - - - - - - - - + + + http://www.openzwave.com/device-database/021F:0201:0003 + images/dome/0201.png + https://products.z-wavealliance.org/products/2830/ + The Dome Door/Window Sensor Pro is a battery powered security-enabled* Z-Wave Plus magnetic reed switch that can monitor the status of doors, windows, and anything else that opens and closes. It can also report ambient temperature levels. The Door/Window Sensor consists of two parts - the “sensor,” and the “magnet.” The sensor has a “reed switch” inside, which is sensitive to the magnet’s presence when aligned properly and within the defined distance. When the sensor and magnet are brought together or pulled apart, the sensor will report its open/close status to its Z-Wave controller, and the encrypted wireless communication* ensures that user data remains secure. Because many manufacturers use Z-Wave to communicate, the Door/Window Sensor can interact with different products of different categories. + +• Z-Wave Plus Certified +• S0 Security-Enabled* +• Built-In Temperature Sensor +• Up to 250’ range +• Ten-Year Battery Life +• LED Signal Strength Indication +• 1.25” Max distance between sensor & magnet +• Ultra-Narrow (1/4”) Magnet for Placement Between Door and Casing +• Monitor doors, windows, medicine cabinets, drawers, garage doors, and many other openings + Because the Door/Window Sensor Pro is a battery powered device, it wakes up on regular intervals to give battery and other status updates to the controller, as well as to accept configuration settings from the controller. This helps to extend the battery life. The Sensor Cover holds down the Button when installed, and the device can be forced to wake up to submit reports or accept new settings immediately by simply removing the Sensor Cover and then replacing it after. If the device is already included in a system, the LED Indicator will flash Red until the cover is closed. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2830/Gen2DWAPIManualv1.2_1.pdf + Dome Door/Window Sensor Pro + If needed, the Door/Window Sensor Pro can be reset locally by following these steps. Only do this if your Z-Wave controller is missing or otherwise unreachable. Beware that resetting your device will disconnect it from the system: +1. Remove the Sensor Cover and confirm that your Door/Window Sensor Pro is powered up. +2. Wait for 5 seconds. +3. Move the Magnet and Sensor Base in and out of the closed position 6 times. +4. The LED Indicator will light up red for five seconds when reset successfully. + +The Door/Window Sensor Pro memory will be erased to factory settings. + + U.S. / Canada / Mexico / CEPT (Europe) / Australia / New Zealand + DMDP1 + Follow the instructions for your Z-Wave Certified Controller to enter exclusion mode. When prompted by the controller: +Remove the SENSOR COVER and the LED Indicator will start blinking red. +Press the Button quickly 3 times in a row. +The LED Indicator will flash green three times indicating exclusion/disconnection and will then continue flashing red (indicating tamper) until the cover is replaced. + New Installation +1. For proper inclusion, bring the Door/Window Sensor Pro to the final location where it will be used*. +2. Follow the instructions for your Z-Wave controller to enter inclusion mode. +3. Remove the Battery Tab protruding from the Battery Tab Slit. +4. The device will automatically enter inclusion mode for two minutes and the LED Indicator will alternate between green and red. + +Upon successful inclusion the LED Indicator will flash green three times then stop blinking. + +Re-Installation +1. For proper inclusion, bring the Door/Window Sensor Proto the final location where it will be used*. +2. Follow the instructions for your Z-Wave controller to enter inclusion mode. +3. Remove the Sensor Cover and the LED Indicator will start blinking yellow. +4. Press the Button quickly 3 times in a row. +5. The device will enter inclusion mode for two minutes and the LED Indicator will alternate between green and red. + +After successful inclusion, the LED Indicator will flash green three times then blink red until the cover is replaced. + +*For non Z-Wave Plus networks, please consult the owner’s manual for your primary controller to determine the best method and location for adding the Door/Window Sensor Pro to your Z-Wave network. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2399/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2829/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2830/xml + + + + + + + + This parameter enables or disables the LED Indicator flashing to indicate opening and closing events. + The Door/Window Sensor will always flash the LED Indicator for inclusion, exclusion, tamper, and other system events. + + + + + + + This parameter switches the Notification or Binary Sensor report sent when the door opens or closes. + If this parameter is set to 01, the Door/Window Sensor will report closed instead of open when the Magnet and Sensor are pulled apart. + + + + + + + By default, the Door/Window Sensor uses the Notification command class to communicate open/close and tamper events. + If this Parameter is set to 1, the device will instead use the Binary Sensor command class. + + + + + + + + The Door/Window Sensor can also monitor and report ambient temperature conditions. + However, temperature sensing functionality is disabled by default to save battery life, and this configuration parameter is used to enable or disable this feature. + + + + + + + This Configuration Parameter can offset the temperature value reported by +/- 125 degrees to compensate for temperature variances in a room - for example, the temperature near the ceiling in a room is significantly higher than the average temperature of the same room. + This Parameter accepts a signed 8-bit value with an absolute value of up to 125, and its units are Dependant on Configuration Parameter 07. + Temperature Offset. + 0 to 125 : 0 to 125 degrees. + 255 to 130 : -1 to -125 degrees. + + + + The Door/Window Sensor can report temperature values in either Celsius or Fahrenheit, and this parameter allows the user to decide which unit is used. + + + + + + This parameter sets the value sent by the Basic Set command to Association Group 2 (for more information, see Association Group Info.). + 0 Turn Off Device. + 1 to 99 Set Device to Value. + 255 Turn On Device. + + + + + This parameter sets the value sent by the Basic Set command to Association Group 4. + The Door/Window Sensor sends a Basic Set command to Association Group 4 when the door or window opens (for more information, see Association Group Info.). + 0 Turn Off Device. + 1 to 99 Set Device to Value. + 255 Turn On Device. + + + + + This parameter sets the value sent by the Basic Set command to Association Group 4. + The Door/Window Sensor sends a Basic Set command to Association Group 4 when the door or window opens (for more information, see Association Group Info.). + 0 Turn Off Device. + 1 to 99 Set Device to Value. + 255 Turn On Device. + + + + + + + + + + + + + + diff --git a/config/domitech/zb22uk.xml b/config/domitech/zb22uk.xml index 5c5fbf9367..f1082ecd5a 100644 --- a/config/domitech/zb22uk.xml +++ b/config/domitech/zb22uk.xml @@ -1,24 +1,63 @@ - - +--> + + http://www.openzwave.com/device-database/020E:3135:4C42 + images/domitech/zb22uk.png + https://products.z-wavealliance.org/products/1543/ + ZB22UK + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1543/Instructions_ZB22UK_10222015 small.pdf + Smart LED light bulb with Z-Wave radio. +- Control lights remotely and save energy +- Compatible with smart home systems supporting Z-Wave +- 60 Watt equivalent light (806 lumens) +- Consumes only 9 watts of power +- 2700K Day light with frosted glass +- Instant ON and fully dimmable +- Functions as a Z-Wave signal repeater +- Very simple to include in your network +- Z-Wave Plus certified + + 1. Turn Off power to the light bulb socket +2. Screw in the light bulb +3. Place your network controller into inclusion mode by following the controller manufacturer's instructions +4. Turn On power to the light bulb. If successful, the LED light bulb will flash twice to indicate successful inclusion. +5. If the controller/gateway shows it was a fail, repeat the procedure. + +Note: If Inclusion still fails after the 2nd attempt, you need to first RESET the dt Smart Bulb before repeating the above steps. + + CEPT (Europe) + You may manually reset the light bulb as follows: +1. Flick the wall switch “OFF-ON” 4 times within 4 seconds. +2. The dt Smart Bulb will flash twice after Reset is successful. + +Use this procedure only in the event that the network primary controller is lost or otherwise inoperable. + 1. Turn off power to the light bulb socket +2. Follow the network controller instruction to place your network controller into exclusion mode to remove the dt light bulb from the network. +3. After being prompted by the network controller, turn On power to the light bulb. If successful, the LED light bulb will flash twice to indicate successful inclusion. + + + Smart LED Light Bulb + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1543/xml + + - + You may select the dim level whenever the light is turned back ON to be either full brightness (100% dim level) or be the same as the last dim setting when the light is ON by flicking the wall switch - + You may change the dimming step level when you adjust the brightness by your controller/gateway. When the value is low, dimming/brightening is gradual. When the value is high, dimming/brightening is rapid. - + You may change the dimming speed quicker or slower. When the value is low, the step timing is quick. @@ -29,8 +68,7 @@ http://products.z-wavealliance.org/MarketCertification/File?folder=&filename=Mar - + - diff --git a/config/domitech/ze27eu.xml b/config/domitech/ze27eu.xml index 38eb76d1e0..2d33033c3e 100644 --- a/config/domitech/ze27eu.xml +++ b/config/domitech/ze27eu.xml @@ -1,37 +1,72 @@ - - - + + + http://www.openzwave.com/device-database/020E:3134:4C42 + images/domitech/ze27eu.png + https://products.z-wavealliance.org/products/1914/ + 1. Turn off power to the light bulb socket +2. Follow the network controller instruction to place your network controller into exclusion mode to remove the dt light bulb from the network. +3. After being prompted by the network controller, turn On power to the light bulb. If successful, the LED light bulb will flash twice to indicate successful exclusion. + + CEPT (Europe) / U.S. / Canada / Mexico + You may manually reset the light bulb as follows: +1. Flick the wall switch “OFF-ON” 4 times within 4 seconds. +2. The dt Smart Bulb will flash twice after Reset is successful. + +Use this procedure only in the event that the network primary controller is lost or otherwise inoperable. + ZE26i + Smart LED light bulb with Z-Wave radio. +- Control lights remotely and save energy +- Compatible with smart home systems supporting Z-Wave +- 60 Watt equivalent light (750 lumens) +- Consumes only 9 watts of power +- 2700K soft light with frosted glass +- Instant ON and fully dimmable +- Functions as a Z-Wave signal repeater +- Very simple to include in your network +- Z-Wave Plus certified + + Smart LED Light Bulb + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1914/ZE26I Manual.pdf + 1. Turn Off power to the light bulb socket +2. Screw in the light bulb +3. Place your network controller into inclusion mode by following the controller manufacturer's instructions +4. Turn On power to the light bulb. If successful, the LED light bulb will flash twice to indicate successful inclusion. +5. If the controller/gateway shows it was a fail, repeat the procedure. + +Note: If Inclusion still fails after the 2nd attempt, you need to first RESET the dt Smart Bulb before repeating the above steps. + + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1530/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1914/xml + + - + You may select the dim level whenever the light is turned back ON to be either full brightness (100% dim level) or be the same as the last dim setting when the light is ON by flicking the wall switch - + You may change the dimming step level when you adjust the brightness by your controller/gateway. When the value is low, dimming/brightening is gradual. When the value is high, dimming/brightening is rapid. - - + You may change the dimming speed quicker or slower. When the value is low, the step timing is quick. When the value is high, the step timing is slow. - - - + - diff --git a/config/dragontech/wd-100.xml b/config/dragontech/wd-100.xml index 7acee3ec57..8cf39c0a9c 100644 --- a/config/dragontech/wd-100.xml +++ b/config/dragontech/wd-100.xml @@ -1,8 +1,8 @@ - + http://www.openzwave.com/device-database/0184:3034:4447 images/dragontech/wd-100.png - https://products.z-wavealliance.org/products/1127/ + https://products.z-wavealliance.org/products/2031/ 1. Turn the connected appliance ON/OFF by tapping the switch. Tapping and releasing the upper part of the rocker turns the appliance ON. Tapping and releasing the lower part of the rocker turns the appliance OFF. 2. Delete(Exclude) the module to/from your Z-Wave network with your primary controller. Please refer to the instructions manual of your gateway or remote controller for details and procedures on how these actions can be done. 3. Normally, the sequence is as follows: when the exclusion process is prompted by your primary controller, single click and release the rocker switch. The controller should show that the action was successful. If the controller shows it was a fail, repeat the procedure. @@ -11,24 +11,27 @@ 1. Turn the connected lights ON/OFF by tapping the switch. Tapping and releasing the upper part of the rocker turns the appliance ON. Tapping and releasing the lower part of the rocker turns the appliance OFF. 2. Add(Include) the module to/from your Z-Wave network with your primary controller. Please refer to the instructions manual of your gateway or remote controller for details and procedures on how these actions can be done. 3. Normally, the sequence is as follows: when the inclusion process is prompted by your primary controller, single click and release the rocker switch to ON or OFF position. The controller should show that the action was successful. If the controller shows it was a fail, repeat the procedure. - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1127/WD100 UG 8.29.14.doc + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2031/WD-100_UG_updated 07212016.pdf Please use this procedure only in the event that the network primary controller is lost or otherwise inoperable. All Configuration Parameters can all be restored to their factory default settings by using your primary controller to delete/reset the device. To manually reset, tap the ON button twice quickly and then tap the OFF button twice quickly. Repeat the procedure to restore the settings to the factory default. - - Works with incandescent and dimmable florescent (CFL) or LED lighting + - Works with incandescent and dimmable florescent (CFL) or most LED lighting - ON/OFF status and location LED indicator - Fits into standard single or multiple gang junction box - Keypad can be replaced manually to match color with other wall switches - Over-The-Air firmware upgrade available with compatible gateway, Z-Wave static controller, or PC and software - Internal resettable fuse to protect from surge current - Manual reset capability +- Support Central Scene U.S. / Canada / Mexico Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1127/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1676/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2031/xml diff --git a/config/ecolink/doorwindow.xml b/config/ecolink/doorwindow.xml index cf3b743345..3b3bc44a5c 100644 --- a/config/ecolink/doorwindow.xml +++ b/config/ecolink/doorwindow.xml @@ -1,32 +1,46 @@ +--> http://www.openzwave.com/device-database/014A:0002:0001 images/ecolink/doorwindow.png https://products.z-wavealliance.org/products/1498/ U.S. / Canada / Mexico - Ecolink Door Window Sensor - Ecolink Z-Wave Door/Window Sensor - --Z-Wave Plus certified --Frequency 908.42MHz --Range up to 100 feet --Battery life up to 3 years with 50 openings/closing per day --CR123A Lithium battery --Input on the sensor for non-powered external contact --BOTH brown and white cases included in each box + EU Z-WAVE DOOR WINDOW SENSOR + Includes Brown & White covers +Sleek design virtually disappears +Easy-to-open case requires no special tools +Case tamper protection +Ideal for double-hung window +Up to 3 year battery life on 1 CR123A lithium battery +Uses rare earth magnet for up to 5/8th inch gap detection +Includes white and brown cases DWZWAVE2.5-ECO Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/790/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1498/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2927/xml - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1498/D.W. Zwave Manual R1.04.docx - If sensor is sleeping, remove the cover to wake up. - Once the controller is in inclusion mode, either remove the battery isolation tab, OR insert the battery to power up the sensor. - Once the controller is in exclusion mode, either remove the battery isolation tab, OR insert the battery to power up the sensor. - To restore this sensor to factory default settings, follow the instructions in the manual to exclude this sensor from the Z-Wave network. Upon completion of removal from the network the sensor will restore itself to factory default settings automatically. Use this procedure only in the event that the network primary controller is missing or otherwise inoperable. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2927/EU Z-wave Door Window Sensor H114101 ZWAVE_Ver03.pdf + The sensor will wake up every so often and when the case is closed to send a Wake-Up Notification to allow the life line master node controller that the sensor is now available for any queued messages that the controller may have for the sensor. The time between Wake-Up Notifications can be configured with the Wake-Up Notification command class to be between 1 hour and 1 week with interval steps of 200 seconds. + The sensor must be added to a Z-Wave network prior to use. To include the sensor in a network both the sensor and the network controller must be in inclusion mode at the same time. Refer to the instructions provided by the manufacturer of your specific controller for details on initiating the controller’s inclusion mode. + +STEP ONE Start by placing the controller into inclusion mode. + +STEP TWO Activate inclusion mode for the sensor by removing the plastic pull-tab from the back of the sensor. When the + inclusion process is complete, the LED on the sensor will be solid blue, then go out. + +STEP THREE Test the sensor. Place the magnet next to the sensor to represent a closed position (see Installation section + to see where to position the magnet). If the LED flashes ONE TIME, it is successfully communicating on your + Zwave network. If the LED on the sensor flashes slow and steady for 5 seconds, you need to repeat the + inclusion process. + + Exclusion mode on the senor is initiated following the same exact procedure as inclusion. + To restore this sensor to factory default settings, follow the instructions in this manual to exclude this sensor from the Z-Wave network. Upon completion of removal from the network the sensor will restore itself to factory default settings automatically. Use this procedure only in the event that the network primary controller is missing or otherwise inoperable. + https://products.z-wavealliance.org/products/2927/ + CEPT (Europe) + H114101 diff --git a/config/ecolink/firefighter.xml b/config/ecolink/firefighter.xml index 50f426aa53..3e562ebc0e 100644 --- a/config/ecolink/firefighter.xml +++ b/config/ecolink/firefighter.xml @@ -1,8 +1,39 @@ - +--> + + http://www.openzwave.com/device-database/014A:000F:0005 + images/ecolink/firefighter.png + https://products.z-wavealliance.org/products/1827/ + The Ecolink Z-Wave Plus FireFighter is an audio detector that listens for your smoke, fire, or Carbon Monoxide alarm and transmits as alert back to your hub to notify you of an event. It is easy to include/exclude with your hub, detector both temporal 3 and 4 patterns of your sensing device, has a 5 year battery life on (1) CR123A Lithium battery included. Dimensions are 3 1/8" x 1" tall. Certified to work with most Z-Wave enabled hubs on the market. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1827/1 - Ecolink FireFighter Z-wave plus Manual (standard).pdf + FF-ZWAVE5-ECO + Ecolink Z-Wave Plus FireFighter + Removing Sensor +A) Any sensor can be removed from any Z-Wave Plus network with any Z-Wave Plus controller. Follow the directions to put your Z-Wave Plus Controller into Z-Wave Plus exclusion mode. +B) Press the learn button located near the LED and Tamper switch. If successfully removed from the Z-Wave Plus network, the sensor’s LED should blink continuously if successful. + + Factory Default + The FireFighter™ can be restored back to factory default settings which will remove its Z-Wave Plus node ID from the sensor (but not the controller) with the following steps. +A) Put the battery into the sensor. +B) Do not press the tamper switch. +C) Hold the learn button down for 10 seconds until the LED turns RED. +D) Release the learn button and wait for the sensor’s green LED to “breath” on and off continuously. The sensor is now ready to be added to a Z-Wave Plus network, and all settings have been restored. + +Please use this procedure only when the network primary +controller is missing or otherwise inoperable. + U.S. / Canada / Mexico + Adding Sensor +A) Be sure that the Z-Wave Plus Controller you are using is compatible with the FireFighter™. +B) Either mount or move the sensor as close as possible to the place in the building where the sensor is to be mounted in order that the new Z-Wave Plus node is added to the correct place in the mesh network routing tables. +C) To add the sensor to an existing Z-Wave Plus network, follow the directions to put your Z-Wave Plus Controller into add (inclusion) mode. The FireFighter™ enters add and remove (inclusion/exclusion) mode on pressing the learn button for 1 second which is located on the PCB between the LED and the tamper switch. If the LED starts blinking continuously, the sensor has no node ID and was not successfully added, so start step C over again. +D) If after 5 seconds the LED is not blinking, look on the Z-Wave Plus controller’s interface for feedback on whether the sensor was added successfully. If you do not see any feedback that the sensor was added, follow directions for removing the sensor from a Z-Wave Plus network, and then try adding the sensor again. If you are still having problems, you may need to add additional Z-Wave Plus listening devices in-between the controller and the sensor. + + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1827/xml + + diff --git a/config/ecolink/floodfreeze.xml b/config/ecolink/floodfreeze.xml new file mode 100644 index 0000000000..b61cdefed8 --- /dev/null +++ b/config/ecolink/floodfreeze.xml @@ -0,0 +1,40 @@ + + + + http://www.openzwave.com/device-database/014A:0010:0005 + images/ecolink/floodfreeze.png + -Z-Wave Plus enabled device which detects flood and freeze. +-Reports tamper condition when cover is open. +Product Specifications +-For indoor use only +-Operating frequency: 908.42 MHz +-Operating temperature: 0° – 49°C, 32° – 120°F (ambient temperature) +-Operating humidity 5-95% non-condensing +-Battery type required: 3V Lithium CR123A +-Battery life approximately 5 years + + http://www.openzwave.com/device-database/XXXX:XXXX:XXXX + https://products.z-wavealliance.org/ProductManual/File?folder=&filename=MarketCertificationFiles/2551/Z-Wave%20Plus%20Wireless%20Flood%20Sensor%20with%20a%20Probe%20FLF-ZWAVE5_V5.pdf + Put Z-Wave Controller into inclusion mode. Insert battery into sensor to enter inclusion mode. + Put Z-Wave Controller into exclusion mode. Remove battery for 1 second and reinsert to enter exclusion mode. + + https://products.z-wavealliance.org/products/2551/ + U.S. / Canada / Mexico + FLF-ZWAVE5 + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2551/xml + + + + + + + + + + + + diff --git a/config/ecolink/motion.xml b/config/ecolink/motion.xml index b76e43b4f3..a2b9b5210d 100644 --- a/config/ecolink/motion.xml +++ b/config/ecolink/motion.xml @@ -1,31 +1,42 @@ +--> http://www.openzwave.com/device-database/014A:0001:0004 images/ecolink/motion.png - https://products.z-wavealliance.org/products/1500/ - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1500/Ecolink PIR Zwave Plus Manual R1.04 021116kgs.docx - Once the controller is in inclusion mode, simply remove the battery isolation tab, OR insert the battery, OR press the small button on the back of the Motion Detector. - PIRZWAVE2.5-ECO - To restore this sensor to factory default settings, follow the instructions for product exclusion which will reset the sensor upon completion of the process. Use this procedure only in the event that the network primary controller is missing or otherwise inoperable. - • For indoor use only -• Operating frequency: 908.42 MHz -• Operating range: Up to 100 feet (30.5 meters) line-of-sight -• Operating temperature: 0˚C to 49˚C, 32˚F to 120˚F (ambient temperature) -• Detection radius: 39 feet (see detection region diagram) -• Detection angle: 45 degrees in either direction from the sensor’s center -• Battery type: 3V Lithium CR123A -• Battery life: approximately 3 years -• Passive Infrared (PIR) based technology + https://products.z-wavealliance.org/products/2928/ + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2928/EU Z-wave PIR H214101 ZWAVE_Ver02.pdf + The sensor must be added to a Z-Wave network prior to use. To include the sensor in a network, both the sensor and the network controller must be in inclusion mode at the same time. + +Activate inclusion mode for the sensor by removing the battery isolation pull tab, or by inserting the battery (see next section for battery installation tips). When the inclusion process is complete the red LED will turn on for approximately 10 seconds and then it will go out. If the LED continues to flash repeat the inclusion process. + +Refer to the instructions provided by the manufacturer of your specific controller for details on initiating the controller’s inclusion mode. + + +STEP ONE Start by placing the controller into inclusion mode. + +STEP TWO Activate inclusion mode for the sensor by removing the battery isolation pull tab, or by inserting the battery (see next section for battery installation tips). When the inclusion process is complete the red LED will turn on for approximately 10 seconds and then it will go out. If the LED continues to flash repeat the inclusion process. +STEP THREE Test the motion sensor before mounting it. Place the sensor in an unoccupied room. Leave the room for at least 4 minutes. Return to the room and pass in front of the sensor lens. The LED will flash once to indicate that motion was detected. - Ecolink Motion Detector - If the sensor is asleep, simply remove the cover to wake up the sensor for configuration. - U.S. / Canada / Mexico - Once the controller is in exclusion mode, simply remove the battery isolation tab, OR insert the battery, OR press the small button on the back of the Motion Detector. + H214101 + To restore this sensor to factory default settings, follow the instructions in this manual to exclude this sensor from the Z-Wave network. Upon completion of removal from the network the sensor will restore itself to factory default settings automatically. Use this procedure only in the event that the network primary controller is missing or otherwise inoperable. + • For indoor use only +• Operating frequency: 908.42 MHz +• Operating range: Up to 100 feet (30.5 meters) line-of-sight +• Operating temperature: 0˚C to 49˚C, 32˚F to 120˚F (ambient temperature) +• Detection radius: 39 feet (see detection region diagram) +• Detection angle: 45 degrees in either direction from the sensor’s center +• Battery type: 3V Lithium CR123A +• Battery life: approximately 3 years +• Passive Infrared (PIR) based technology + EU Z-WAVE PIR MOTION SENSOR + To save power, this sensor sleeps most of the time and is therefore not awake to receive messages from a gateway for testing. Removing the top case from the sensor will put in device into a tampered mode in which the sensor will stay awake and able to receive messages. Most of the time an end user would not do this, but if the sensor needs to be configured after inclusion, an end user can follow the instructions below for sending Wake-Up notifications. + U.S. / Canada / Mexico / CEPT (Europe) + Exclusion mode on the sensor is initiated following the same exact procedure as inclusion. Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1500/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2928/xml diff --git a/config/ecolink/tiltsensor.xml b/config/ecolink/tiltsensor.xml index 2d13adb2a7..d206751f34 100644 --- a/config/ecolink/tiltsensor.xml +++ b/config/ecolink/tiltsensor.xml @@ -1,17 +1,32 @@ +--> http://www.openzwave.com/device-database/014A:0003:0001 images/ecolink/tiltsensor.png https://products.z-wavealliance.org/products/816/ TILTZWAVE1 - Ecolink Tilt Sensor + Ecolink Garage Door Tilt Sensor U.S. / Canada / Mexico - This sensor determines the state (open or closed) of a door (typically a garage door) using a roller ball switch. The open/closed status is communicated to a Z-Wave Gateway/Controller + • For indoor use only +• Operating frequency: 908.42 MHz +• Operating range: Up to 100 feet (30.5 meters) line-of-sight +• Operating temperature: 0˚C to 49˚C, 32˚F to 120˚F (ambient temperature) +• Battery type: 3V Lithium CR123A +• Battery life: 5 to 8 years depending upon operating conditions + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/816/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1501/xml + https://products.z-wavealliance.org/products/1501/ + Once the controller is in exclusion mode, remove the battery pull tab OR insert the battery into the sensor to initiate power up. + Simply remove the sensor cover to wake up for configuration. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1501/Tilt_ZWave_Plus_Manual_R1.04_021816kgs.pdf + Once the controller is in inclusion mode, remove the battery pull tab OR insert the battery to power up the sensor. + U.S. / Canada / Mexico + TILTZWAVE2.5-ECO + To reset the sensor to factory default, place the controller in exclusion mode and then insert the battery into the sensor to initiate power up. Use this procedure only in the event that the network primary controller is missing or otherwise inoperable. diff --git a/config/enerwave/zw15rmplus.xml b/config/enerwave/zw15rmplus.xml index 5ee90cda6c..89a59dafde 100644 --- a/config/enerwave/zw15rmplus.xml +++ b/config/enerwave/zw15rmplus.xml @@ -1,38 +1,57 @@ - - - - - - - Synchronization of load power and LED indicator - - - - - How often to send the energy report for the moment-in-time usage (METER_REPORT version) automatically in minutes. 0 = disabled. - - - How often to send the energy report for the moment-in-time usage (SENSOR_MULTILEVEL_REPORT version) automatically in minutes. 0 = disabled. - - - How often to send the energy report for the accumulated energy usage usage (METER_REPORT) automatically in minutes. 0 = disabled. - - - Enable automatic notifications when there is a change in wattage. - - - - - - - How much the wattage needs to change by to trigger the wattage change notifications. Units are 1-10th of a watt; 0-255: 0.0-25.5W - - - - - - - - - + + + http://www.openzwave.com/device-database/011A:0105:0111 + images/enerwave/zw15rmplus.png + https://products.z-wavealliance.org/products/1776/ + The ZW15RM TR Duplex Receptacle is a perfect wireless manual and remote on/off control replacement of regular receptacles, controlling table and floor lamps, small appliances, etc. It provides two different type outlets. One outlet with Z-Wave mark has programmable functions such as scenes, association, schedule event, etc. It is fully interoperable with other Z-Wave certified device from other manufacturers and/or other applications. It can report wattage energy usage or kWh energy usage to a Z-Wave gateway.It has a Blue LED on the face cover indicates the status of the controlled outlet and/or act as a night light. The other outlet with Tamper-Resistant feature provides constant power, helps you and your families prevent electrical injuries. + When the controller is in add mode and the blue LED is blinking on the +ZW15RM, press and hold the program button of ZW15RM for 3 second, and +then the controller will verify the add. + IN-Wall Smart Meter TR Duplex Receptacle + U.S. / Canada / Mexico + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1776/ZW15RM(20160509 ).pdf + When the controller is in remove mode, press and hold the program button of +ZW15RM for 3 second, and then the controller will remove it from the current +Z-Wave network, and the LED will blink on the receptacle,when power on. + Once program button is pressed and hold for 10 second, the device will send a device reset locally notification to controller. Then clear all of information for +the network, and restore factory defaults, and reset the module. Use this procedure only in the event that the network primary controller is missing or otherwise inoperable. + ZW15RM + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1776/xml + + + + + + Synchronization of load power and LED indicator + + + + + How often to send the energy report for the moment-in-time usage (METER_REPORT version) automatically in minutes. 0 = disabled. + + + How often to send the energy report for the moment-in-time usage (SENSOR_MULTILEVEL_REPORT version) automatically in minutes. 0 = disabled. + + + How often to send the energy report for the accumulated energy usage usage (METER_REPORT) automatically in minutes. 0 = disabled. + + + Enable automatic notifications when there is a change in wattage. + + + + + + + How much the wattage needs to change by to trigger the wattage change notifications. Units are 1-10th of a watt; 0-255: 0.0-25.5W + + + + + + + + + diff --git a/config/enerwave/zw20rm.xml b/config/enerwave/zw20rm.xml index 00abf7b843..4c853c0eaa 100644 --- a/config/enerwave/zw20rm.xml +++ b/config/enerwave/zw20rm.xml @@ -1,36 +1,55 @@ - - - - - - - Synchronization of outlet power and LED indicator - - - - - How often to send the energy report for the moment-in-time usage (METER_REPORT version) automatically in minutes. 0 = disabled. - - - How often to send the energy report for the moment-in-time usage (SENSOR_MULTILEVEL_REPORT version) automatically in minutes. 0 = disabled. - - - How often to send the energy report for the accumulated energy usage usage (METER_REPORT) automatically in minutes. 0 = disabled. - - - Enable automatic notifications when there is a change in wattage. - - - - - - - How much the wattage needs to change by to trigger the wattage change notifications. Units are 1-10th of a watt; 0-255: 0.0-25.5W - - - - - - - + + + http://www.openzwave.com/device-database/011A:0101:0111 + images/enerwave/zw20rm.png + https://products.z-wavealliance.org/products/1766/ + PLUG-IN SMART METER APPLIANCE MODULE + ZWN-333M + This ZWN-333M Smart Meter Appliance Module is a Z-Wave enabled device and fully interoperable with other Z-Wave certified device from other manufacturers and/or other applications, which can report wattage energy usage or kWh energy usage to a Z-Wave gateway. In a Z-Wave network, ZWN-333M can be controlled to turn on/off to save energy, also act as a wireless repeater regardless of vendor to increase reliability of the network. With a horizontal design, the Smart Meter Appliance Module will not block other nearby AC outlets. + Once program button is pressed and hold for 3 second, the device will enter into +learn mode to accomplish adding or removing by controller. Refer to the instruction +for your primary controller to access the setup function and add or remove devices. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1766/ZWN-333M_20160506.pdf + Once program button is pressed and hold for 3 second, the device will enter into +learn mode to accomplish adding or removing by controller. Refer to the instruction +for your primary controller to access the setup function and add or remove devices. + Once program button is pressed and hold for 10 second, the device will send a device reset locally notification to controller. Then clear all of information for the network, and restore factory defaults, and reset the module. Use this procedure only in the event that the network primary controller is missing or otherwise inoperable. + + U.S. / Canada / Mexico + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1766/xml + + + + + + Synchronization of outlet power and LED indicator + + + + + How often to send the energy report for the moment-in-time usage (METER_REPORT version) automatically in minutes. 0 = disabled. + + + How often to send the energy report for the moment-in-time usage (SENSOR_MULTILEVEL_REPORT version) automatically in minutes. 0 = disabled. + + + How often to send the energy report for the accumulated energy usage usage (METER_REPORT) automatically in minutes. 0 = disabled. + + + Enable automatic notifications when there is a change in wattage. + + + + + + + How much the wattage needs to change by to trigger the wattage change notifications. Units are 1-10th of a watt; 0-255: 0.0-25.5W + + + + + + + diff --git a/config/enerwave/zwn-bpc.xml b/config/enerwave/zwn-bpc.xml index 0567282910..a37316f011 100644 --- a/config/enerwave/zwn-bpc.xml +++ b/config/enerwave/zwn-bpc.xml @@ -1,4 +1,21 @@ - + + + http://www.openzwave.com/device-database/011A:0901:0601 + images/enerwave/zwn-bpc.png + https://products.z-wavealliance.org/products/2165/ + 3. Once program button is pressed and hold for 10 second, the device will send a device reset locally notification to controller. Then clear all the module. Use this procedure only in the event that the network primary controller is missing or otherwise inoperable. + 1. When the controller is in add mode, press and hold the program button of ZWN-BPC for 2 second, and then the controller will verify the add. + Once short press the program button it will send singlecast wake up notification to controller devices. + U.S. / Canada / Mexico + The PIR Motion Sensor ZWN-BPC is a Z-Wave enabled device and is fully compatible with other Z-Wave certified device from other manufacturers. With the ZWN-BDS to monitor the environment and provide hand-free lighting control, it can also trigger a Z-Wave enabled alarm when motion is detected and when there is movement within or across the detection of coverage, one triggering signal will be transmitted to all associated Z-Wave devices. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2165/20170111 ZWN-BPC.pdf + 2. When the controller is in remove mode, press and hold the program button of ZWN-BPC for 2 second, and then the controller will remove it from the current Z-Wave network. + ZWN-BPC + Ceiling Mounted PIR Motion Sensor + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2165/xml + + Sets the time after triggering the sensor to send the Basic OFF command. 0: Don't send Basic OFF. 1-240: N minutes. 241-255: 15 seconds. diff --git a/config/enerwave/zwnrsm1plus.xml b/config/enerwave/zwnrsm1plus.xml index e7f52c498e..55e6a67204 100644 --- a/config/enerwave/zwnrsm1plus.xml +++ b/config/enerwave/zwnrsm1plus.xml @@ -1,12 +1,27 @@ - - - - - - - - - + http://enerwaveautomation.com/wp-content/uploads/products/zwnrsm1s/ZWN-RSM1-Plus-0208160043-02.pdf--> + + http://www.openzwave.com/device-database/011A:0605:0111 + images/enerwave/zwnrsm1plus.png + https://products.z-wavealliance.org/products/2242/ + ZWN-RSM2 + Smart Dual Relay Switch Module + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2242/ZWN-RSM2 2017-2-28.pdf + The ZWN-RSM2 Switch Module have two channels switch ,that is a component of lighting control system, it can not be used separately but should turn an existing switch into a Z-Wave switch. This ZWN-RSM2 module is a Z-Wave enabled device and is fully compatible with other Z-Wave certified device from other manufacturers. In a Z-Wave network, each device is designed to act as a wireless repeater. Once the ZWN-RSM2 module is installed and setup with in your wall, it will retransmit the RF signal from one device to another until the intended device to intended device is reached. This ensures that the signal is received by its intended destination + U.S. / Canada / Mexico + Once program button is pressed and hold for 10 second, the device will send a device reset locally notification to controller. Then clear all of information for the network, and restore factory defaults, and reset the module. Use this procedure only in the event that the network primary controller is missing or otherwise inoperable. + When the controller is in remove mode,Press and release the program button of ZWN-RSM2 module, or Flick 3 times of the connected switch with Aux1 line (or Aux2 line) in 1.5 second. Then the controller will remove the module from current Z-Wave network. + When the controller is in add mode,Press and release the program button of ZWN-RSM2 module,or Flick 3 times of the connected switch with Aux1 line(or Aux 2 line) in 1.5 second. Then the controller will add the module into current Z-Wave network. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1777/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2242/xml + + + + + + + + + diff --git a/config/eurotronic/eur_cometz.xml b/config/eurotronic/eur_cometz.xml index 29b6210a62..fb3982c54e 100644 --- a/config/eurotronic/eur_cometz.xml +++ b/config/eurotronic/eur_cometz.xml @@ -1,4 +1,19 @@ - + + + http://www.openzwave.com/device-database/0148:0001:0002 + images/eurotronic/eur_cometz.png + https://products.z-wavealliance.org/products/2202/ + CEPT (Europe) + LIZY001 + Comap LIZY001 + LIZY001 + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1601/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2200/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2201/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2202/xml + + diff --git a/config/eurotronic/eur_spiritz.xml b/config/eurotronic/eur_spiritz.xml index 7cb56279c2..8c0d664015 100644 --- a/config/eurotronic/eur_spiritz.xml +++ b/config/eurotronic/eur_spiritz.xml @@ -2,8 +2,48 @@ Eurotronic Spirit Z-Wave Plus Thermostat Product website: https://www.eurotronic.org/produkte/spirit-z-wave-plus.html Tech manual: https://www.eurotronic.org/fileadmin/user_upload/eurotronic.org/Produktbilder/spirit_z_wave_plus/Spirit_Z-Wave_BAL_web_EN_view_04.pdf ---> - +--> + + http://www.openzwave.com/device-database/0148:0001:0003 + images/eurotronic/eur_spiritz.png + https://products.z-wavealliance.org/products/2543/ + Start Inclusion mode of your primary Z-Wave Controller. +Press the Boost-Button. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2650/Spirit_Z-Wave_BAL_web_EN_view_05.pdf + Start Exclusion mode of your primary Z-Wave Controller. +Now press and hold the boost button of the Spirit Z-Wave Plus for at least 5 seconds. + KOMFORTHAUS Spirit Z-Wave Plus + 4260012711110 + UAE + Please use this procedure only when the network primary controller is missing or otherwise inoperable. + +Remove batteries. +Press and hold boost button. +While still holding boost button insert batteries. +The LCD shows RES. Release boost button. +To perform the factory reset press boost button. + + • Easy control for water radiators from any Z-Wave Controller +• Fits most European water radiators (wide range of additional adaptors for different manufacturers available) +• FLiRS for quick response time +• LED Backlit LCD +• Metal nut for reliable connection to the radiator +• 2 buttons for easy temperature regulation +• Battery level indicator +• Child Lock +• Over the Air update +• UK-Mode for upside down installation +• Open Window detection +• Automatic frost protection + + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2543/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2650/xml + + https://products.z-wavealliance.org/products/2650/ + 4250848804063 + UAE + diff --git a/config/everspring/ad147.xml b/config/everspring/ad147.xml index 3db251863f..8bd2565bd3 100644 --- a/config/everspring/ad147.xml +++ b/config/everspring/ad147.xml @@ -1,29 +1,25 @@ - + http://www.openzwave.com/device-database/0060:0003:0003 images/everspring/ad147.png - https://products.z-wavealliance.org/products/1065/ + https://products.z-wavealliance.org/products/1527/ 1. Put the Z-Wave Controller into exclusion mode. -2. Press the link key three times within 1.5 seconds to put the unit into exclusion mode. (Please refer to the documentation for the location of the link key.) - +2. Press the link key three times within 1.5 seconds to put the unit into exclusion mode. 1. Put the Z-Wave Controller into inclusion mode. -2. Press the link key three times within 1.5 seconds to put the unit into inclusion mode. (Please refer to the documentation for the location of the link key.) - - Dimmer Plug +2. Press the link key three times within 1.5 seconds to put the unit into inclusion mode. + wireless dimmer plug CEPT (Europe) - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1065/Manual_AD147_20140728.pdf - AD147-6 - (This procedure should only be used when the network primary controller is inoperable.) -1. Press the link key three times within 1.5 seconds to put the unit into exclusion mode. -2. Within 1 second of step 1, press link key again and hold it until LED is off (about 5 seconds). (Please refer to the documentation for the location of the link key.) -3. Node ID is excluded. The device reverts to factory default state and will be in auto-inclusion mode for 4 minutes. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1527/Manual - AD147_20151007-A501112259R01.pdf + AD147-2 + 1. Press the link key three times within 1.5 seconds to put the unit into exclusion mode. +2. Within 1 second of step 1, press link key again and hold it until LED is off (about 5 seconds). +3. Node ID is excluded. The device reverts to factory default state and will be in auto-inclusion mode for 4 minutes. +4. Use this procedure only in the event that the network primary controller is missing, or otherwise inoperable NR - The mini Dimmer Plug is a Z-Wave enabled device which is fully compatible with any Z-Wave enabled network. Z-Wave enabled devices displaying the Z-Wave logo can also be used with it regardless of the manufacturer, and ours can also be used in other manufacturer’s Z-Wave enabled networks. Inclusion of this unit on other manufacturer’s Wireless Controller menu allows remote operation of the unit and the connected load. - -The mini Dimmer Plug is designed to control the on/off status of lighting and appliances load in your house. The unit also provides dimmer function which is only applicable to light bulbs. At 220-240V voltage, this Dimmer Plug can support connected load of 6 - 250W. - + The mini Dimmer Plug is designed to control the on/off status of lighting and appliance load in your house. The unit also provides dimmer function which is only applicable to light bulbs. At 220-240V voltage, this Dimmer Plug can support connected load of 6W - 250W. Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1065/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1527/xml diff --git a/config/everspring/sp815.xml b/config/everspring/sp815.xml index 2b2898fc93..63920efac9 100644 --- a/config/everspring/sp815.xml +++ b/config/everspring/sp815.xml @@ -1,4 +1,46 @@ - + + + http://www.openzwave.com/device-database/0060:0004:0001 + images/everspring/sp815.png + https://products.z-wavealliance.org/products/3366/ + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3366/SP815 user manual_05102019-A501112752R01.pdf + CEPT (Europe) + 1. Put the Z-Wave Controller into inclusion mode. +2. Press the learn key 3 times within 1.5 seconds to put the unit into inclusion mode. + + After it has been included into a Z-Wave network, the detector will go to sleep but will send a Wakeup Notification Command periodically at preset period to the controller. The Motion detector will stay awake for 10 seconds at least and then go back to sleep to conserve battery life. + +The time interval between Wakeup Notification Commands can be set in the Wakeup Command Class based on the range values below: + +Minimum Wake Up Interval 600s (10 minutes) +Maximum Wake Up Interval 86400s (1 day) +Default Wake Up Interval 14400s (4 hours) +Wake Up Interval Step Seconds 600s (10 minutes) + + 1. Press the learn key 3 times within 1.5 seconds to put the unit into exclusion mode. +2. Within 1 second of step 1, press the learn key again and hold for 5 seconds. +3. Node ID is excluded. The device reverts to factory default state. +(This procedure should only be used when the controller is inoperable.) + 1. Put the Z-Wave Controller into exclusion mode. +2. Press the learn key 3 times within 1.5 seconds to put the unit into exclusion mode. + + The SP815 is a multifunction device with motion detector and temperature/humidity sensor. It uses Passive Infra-Red (PIR) technology to detect movement in a protected area by sensing the changes of thermal radiation caused by the moving body within or across the field of detection. Featuring dual PIR sensor designed with dual lens technology, this detector is immune to presence of pets in the home allowing your pet to move freely without causing false alarms. + +This product is a Z-Wave Plus enabled device and is fully compatible with any Z-Wave enabled network. The device can be set up in a Z-Wave network to communicate directly with other end devices such as smartplugs, or to report directly to a Z-Wave controller (usually a gateway). + +When the motion detector is triggered, an alarm signal will be emitted to the controller and the controller, after receiving the signal, will perform certain action according to its settings. + +The product has a built in digital temperature sensor and humidity sensor to report environmental condition of the protected area to the controller. + +This product supports the S2 security protocol that uses encrypted Z-Wave Plus messages to communicate to other security-enabled Z-Wave Plus products. A security-enabled Z-Wave Plus Controller must be used in order to fully utilize the security features of this product. + + + SP815-1 + PET IMMUNE PIR MOTION DETECTOR + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3366/xml + + diff --git a/config/everspring/sp816.xml b/config/everspring/sp816.xml index 2a53312a07..ecaae23915 100644 --- a/config/everspring/sp816.xml +++ b/config/everspring/sp816.xml @@ -1,8 +1,40 @@ - +--> + + http://www.openzwave.com/device-database/0060:0005:0001 + images/everspring/sp816.png + https://products.z-wavealliance.org/products/3077/ + After it has been included into a Z-wave network, the detector will go to sleep but will send a Wakeup Notification Command periodically at preset period to the controller. The Motion detector will stay awake for 10 seconds at least and then go back to sleep to conserve battery life. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3077/SP816 A501112630R01_20180913.pdf + Outdoor Motion Detector + CEPT (Europe) / U.S. / Canada / Mexico + The SP816 Outdoor Motion Detector is a Z-Wave PlusTM enabled device and is fully compatible with any Z-WaveTM enabled network. The device can be set up in a Z-Wave network to communicate directly with other end devices such as lighting controllers, or to report directly to a Z-Eave controller (usually a gateway). + +This motion detector is primarily designed for outdoor lighting control application. It features a PIR motion detector to detect movement in a protected area and a lux sensor for determining brightness of its surroundings. It comes with a built in timer to set the duration for light turn on. The lux level and the timer can be set through knobs on the device itself. + +If the PIR detects motion when lux level falls below a preset setting, the device will transmit a signal to turn on the outdoor lighting (or indirectly through gateway) and then later turns it off when its timer has elapsed. + +This device can also be used as a basic motion sensor for indoor security application. + + SP816-2 + 1. Put the Z-Wave Controller into exclusion mode. +2. Press the tamper switch 3 times within 1.5 seconds to put the unit into exclusion mode. + + + 1. Press the tamper switch 3 times within 1.5 seconds to put the unit into exclusion mode. +2. Within 1 second of step 1, press the tamper switch again and hold until LED is off (about 5 seconds). +3. Node ID is excluded. The device reverts to factory default state and will be in auto-inclusion mode for 4 minutes. +(This procedure should only be used when the controller is inoperable.) + 1.Put the Z-Wave Controller into inclusion mode. +2.Press the tamper switch 3 times within 1.5 seconds to put the unit into inclusion mode. + + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2656/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3077/xml + + diff --git a/config/fibaro/fgbs222.xml b/config/fibaro/fgbs222.xml index 7735e8961a..54af58d90e 100644 --- a/config/fibaro/fgbs222.xml +++ b/config/fibaro/fgbs222.xml @@ -1,4 +1,68 @@ - + + + http://www.openzwave.com/device-database/010F:1000:0502 + images/fibaro/fgbs222.png + https://products.z-wavealliance.org/products/3285/ + FGBS-222 + FIBARO Smart Implant allows to enhance the functionality of wired sensors and other devices by adding Z-Wave network communication. +You can connect binary sensors, analog sensors, DS18B20 temperature sensors or DHT22 humidity and temperature sensor to report their readings to the Z-Wave controller. +It can also control devices by opening/closing output contacts independently of the inputs. + +Main features of FIBARO Smart Implant: +- Compatible with any Z-Wave or Z-Wave+ Controller, +- Supports Z-Wave network Security Modes: S0 with AES-128 encryption and S2 with PRNG-based encryption, +- Allows for connecting sensors: + o 6 DS18B20 sensors, + o 1 DHT sensor, + o 2 2-wire analog sensor, + o 2 3-wire analog sensor, + o 2 binary sensors. +- Works as a Z-Wave signal repeater, +- Built-in temperature sensor. + + To remove the device from the Z-Wave network: +1. Power the device. +2. Set the main controller into remove mode (see the controller’s manual). +3. Quickly, triple click button on the device housing or switch connected to IN1 or IN2. +4. LED will start blinking yellow, wait for the removing process to end. +5. Successful removing will be confirmed by the Z-Wave controller’s message. + + FIBARO Smart Implant is powered using DC power supply unit so it is always awake. + Smart Implant + To add the device to the Z-Wave network manually: +1. Power the device. +2. Set the main controller in (Security/non-Security Mode) add mode (see the controller’s manual). +3. Quickly, triple click button on the device housing or switch connected to IN1 or IN2. +4. If you are adding in Security S2 Authenticated, scan the DSK QR code or input the 5-digit PIN code (label on the bottom of the box). +5. LED will start blinking yellow, wait for the adding process to end. +6. Successful adding will be confirmed by the Z-Wave controller’s message. + +To add the device to the Z-Wave network using Smart Start: +1. Set the main controller in Security S2 Authenticated add mode (see the controller’s manual). +2. Scan the DSK QR code or input the 5-digit PIN code (label on the bottom of the box). +3. Power the device. +4. LED will start blinking yellow, wait for the adding process to end. +5. Successful adding will be confirmed by the Z-Wave controller’s message. + + CEPT (Europe) + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3285/FGBS-222-EN-T-v1.2c.pdf + Reset procedure allows to restore the device back to its factory settings, which means all information about the Z-Wave controller and user configuration will be deleted. + +Resetting the device is not the recommended way of +removing the device from the Z-Wave network. Use this procedure only when the network primary controller is missing or inoperable. Certain device removal can be achieved by the procedure of removing described. + +1. Press and hold the button to enter the menu. +2. Release button when the device glows yellow. +3. Quickly click the button to confirm. +4. After few seconds the device will be restarted, which is signalled with the red colour. + + + + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3195/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3285/xml + + - + + + http://www.openzwave.com/device-database/010F:1000:0702 + images/fibaro/fgdw2.png + https://products.z-wavealliance.org/products/2181/ + FIBARO Door/Window Sensor 2 + FIBARO Door/Window Sensor 2 is a wireless, battery powered, Z-Wave Plus compatible magnetic contact sensor. Changing the device’s status will automatically send signal to the Z-Wave controller and associated devices. In addition the FIBARO Door/Window Sensor 2 is equipped with a built-in temperature sensor. +Sensor can be used to trigger scenes and wherever there is a need for information about opening or closing of doors, windows, garage doors, etc. Opening is detected by separating the sensor’s body and the magnet. + + FGDW-002 + 1) Place the Door/Window Sensor 2 within the direct range of your Z-Wave controller. +2) Set the main controller in (security/non-security) add mode (see the controller’s manual). +3) Click the Button at least six times. +4) Quickly, three times press one of the TMP buttons (while the other button is pressed). +5) Wait for the adding process to end. +6) Successful adding will be confirmed by the Z-Wave controller’s message. + + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2181/FGDW-002-EN-T-v0.3.2.pdf + 1) Place the Door/Window Sensor 2 within the direct range of your Z-Wave controller. +2) Set the main controller into remove mode (see the controller’s manual). +3) Quickly, three times press one of the TMP buttons (while the other button is pressed). +4) Wait for the removing process to end. +5) Successful removing will be confirmed by the Z-Wave controller’s message. - - - - This parameter allows to set in what state is door/window when the magnet is close to the sensor. - - - - - This parameter defines events indicated by the visual LED indicator. + + The Door/Window Sensor 2 needs to be woken up to receive informa¬tion about the new configuration from the controller, like parameters and associations. +1) To wake up the sensor manually, click one of the TMP buttons (while the other button is pressed). + + Reset procedure allows to restore the device back to its factory settings, which means all information about the Z-Wave controller and user configuration will be deleted. In order to reset the device: +1) Open the cover. +2) Remove the battery. +3) Install the battery while holding both TMP buttons. +4) Release the TMP button within 5 seconds. +5) Visual indicator will blink 3 times to confirm launching of reset procedure. +6) Wait around 30s for the resetting process to end, do not remove the battery. +7) Visual LED indicator will blink 6 times to confirm the reset. + +*Resetting the device is not the recommended way of removing the device from the Z-Wave network. Use reset procedure only if the primary controller is missing or inoperable. + CEPT (Europe) + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2181/xml + + + + + + This parameter allows to set in what state is door/window when the magnet is close to the sensor. + + + + + This parameter defines events indicated by the visual LED indicator. Disabling events might extend battery life. 0 - no indications 1 - indication of opening/closing status change (input IN) 2 - indication of wake up (1 x click or periodical) 4 - indication of device tampering - - - This parameter defines how commands are sent in specified association groups: as secure or non-secure. + + + This parameter defines how commands are sent in specified association groups: as secure or non-secure. Parameter is active only in Z-Wave network security mode. It does not apply to 1st group Lifeline - - - - - - - Parameter defines events which result in sending on/off commands to devices added to the 2nd association group. + + + + + + + Parameter defines events which result in sending on/off commands to devices added to the 2nd association group. These commands are sent alternately to switch the devices on and off. - - - - - - Value sent to devices in 2nd association group when opening is detected. + + + + + + Value sent to devices in 2nd association group when opening is detected. The value of 0 turns OFF the device, 255 turns it On. In case of associating devices allowing smooth control, values 1-99 allow to set an associated device to a specified level. - - - Value sent to devices in 2nd association group when closing is detected. + + + Value sent to devices in 2nd association group when closing is detected. The value of 0 turns OFF the device, 255 turns it On. In case of associating devices allowing smooth control, values 1-99 allow to set an associated device to a specified level. - - - Time that must elapse from opening to send the command frame to to devices in 2nd association group. - - - Time that must elapse from closing to send the command frame to devices in 2nd association group. - - - Time period after which a tamper alarm will be cancelled. - - - Reporting cancellation of tamper alarm to the controller and 3rd association group. - - - - - This parameter defines how often the temperature will be measured. + + + Time that must elapse from opening to send the command frame to to devices in 2nd association group. + + + Time that must elapse from closing to send the command frame to devices in 2nd association group. + + + Time period after which a tamper alarm will be cancelled. + + + Reporting cancellation of tamper alarm to the controller and 3rd association group. + + + + + This parameter defines how often the temperature will be measured. The shorter the time, the more frequently the temperature will be measured, but the battery life will shorten. 0 - temperature measurements disabled 5-32400 - time in seconds - - - This parameter defines the change of temperature in comparison with last reported, resulting in temperature report being sent to the main controller. + + + This parameter defines the change of temperature in comparison with last reported, resulting in temperature report being sent to the main controller. 0 - temperature reports based on threshold disabled 1-300 - temperature threshold (0.1-30C, 0.1C step) - - - This parameter determines how often the temperature reports will be sent to the main controller. + + + This parameter determines how often the temperature reports will be sent to the main controller. 0 - periodic temperature reports disabled 5-32400 - time in seconds - - - The value to be added to the actual temperature, measured by the sensor (temperature compensation). (0.1C steps) + + + The value to be added to the actual temperature, measured by the sensor (temperature compensation). (0.1C steps) - - - Temperature alarms reported to the Z-Wave controller. + + + Temperature alarms reported to the Z-Wave controller. Thresholds are set in parameters 55 and 56. - - - - - - - If temperature is higher than set value, overheat notification will be sent and high temperature scene will be triggered (if activated). + + + + + + + If temperature is higher than set value, overheat notification will be sent and high temperature scene will be triggered (if activated). 0-600 (0-60C, 0.1C step). - - - If temperature is lower than the set value, underheat notification will be sent and low temperature scene will be triggered (if activated). + + + If temperature is lower than the set value, underheat notification will be sent and low temperature scene will be triggered (if activated). 0-599 (0-59.9C, 0.1C step) - - - - - - - - - - - + + + + + + + + + + diff --git a/config/fibaro/fgfs101zw5.xml b/config/fibaro/fgfs101zw5.xml index d1a6b10a98..dd8dee9005 100644 --- a/config/fibaro/fgfs101zw5.xml +++ b/config/fibaro/fgfs101zw5.xml @@ -1,40 +1,52 @@ - + http://www.openzwave.com/device-database/010F:1002:0B01 images/fibaro/fgfs101zw5.png - https://products.z-wavealliance.org/products/1354/ + https://products.z-wavealliance.org/products/2791/ 1) Open the cover by turning it counter-clockwise. -2) Make sure the sensor is connected to a battery or a DC power supply. -3) Press and hold the TMP button for 15-20 seconds until LED glows yellow to confirm entering into 4th menu option. -4) Release and click the TMP button to start reset procedure. -5) The LED glowing red and then turning off will confirm successful reset. Reset completion will be also confirmed by an acoustic signal. -Note! Resetting the device is not the recommended way of removing the device from the Z-Wave network. Use reset procedure only if the primary controller is missing or -inoperable. +2) Make sure the device is powered (either by a battery or a DC power supply). +3) Press and hold the TMP button for 15-20 seconds until LED glows yellow (4th menu position). +4) Release and click the TMP button to start the reset procedure. +5) Successful reset will be confirmed with the LED indicator changing colour to red and an acoustic signal. +Use reset procedure only if the primary controller is missing or inoperable. + FGFS-101 - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1354/FGFS-101-EN-T-v1.0-5.pdf - FIBARO Flood Sensor will wake up at a defined time interval and will ALWAYS try to communicate with the main controller. There is a possibility to wake up the device manually by clicking the TMP button. - 1) Open the cover by turning it counter-clockwise. -2) Make sure the sensor is connected to a battery or a DC power supply. -3) Locate the sensor nearby the main Z-Wave controller. -4) Set the main Z-Wave controller into learning mode (see main controller’s operating manual). + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3327/FGFS-101-EN-T-v2.11.pdf + FIBARO Flood Sensor will wake up at a defined time interval and will always try to communicate with the main controller. There is a possibility to wake up the device manually by clicking the TMP button + 1) Open the cover by turning it counter-clockwise. +2) Make sure the device is powered (either by a battery or a DC power supply). +3) Place the device within the direct range of your Z-Wave controller. +4) Set the main controller in remove mode (see the controller’s manual). 5) Quickly, triple click the TMP button located inside the casing. -6) Wait for the device to be excluded from the system. Successful exclusion will be confirmed by the controller. +6) Wait for the removing process to end. +7) Successful removing will be confirmed by the Z-Wave controller’s message. + 1) Open the cover by turning it counter-clockwise. 2) Remove battery blocker. -3) Locate the sensor nearby the main Z-Wave controller. -4) Set the main Z-Wave controller into learning mode (see main controller’s operating manual). +3) Place the device within the direct range of your Z-Wave controller. +4) Set the main controller in (security/non-security) add mode (see the controller’s manual). 5) Quickly, triple click the TMP button located inside the casing. -6) Wait for the device to be included into the system. Successful inclusion will be confirmed by the controller. -7) Close the cover by turning it clockwise. -8) Place the sensor onto a surface prone to flooding. Three electrodes underneath the device should evenly touch the surface. +6) Wait for the adding process to end. +7) Successful adding will be confirmed by the Z-Wave controller’s message. +8) Close the cover by turning it clockwise. +9) Place the sensor onto a surface prone to flooding. Three electrodes underneath the device should evenly touch the surface. - FIBARO Flood Sensor is a universal, Z-Wave compatible, flood and temperature sensor. Device can be battery (ca. 2 years battery life) or VDC powered (12 or 24 VDC). FIBARO Flood Sensor is designed to be placed on the floor or on a wall with a flood sensor probes extended by connected wire. Flood alarm is sent to Z-Wave network devices or additionally to any alarm system controller, through opening a NC contact. The device has built-in temperature sensor, monitoring temperature of e.g. floor, LED indicator, acoustic alarm, and is equipped with a tilt sensor, reporting tilt or movement e.g. when someone has taken the Sensor from its original location. LED diode signals flood, operating mode or the Z-Wave network communication range. FIBARO Flood Sensor is sink-proof, which means it drifts on the water surface and keeps on sending alarm signal in case of substantial inundation of water. Flood Sensor is compatible with any Z-Wave or Z-Wave+ Controller. -https://www.youtube.com/watch?v=8JRxUoHbEN8 + FIBARO Flood Sensor is a universal, Z-Wave Plus compatible, flood and temperature sensor. The device can be powered using battery, 12/24V DC power supply or both. Flood alarm is sent to the Z-Wave network devices or additionally to any alarm system controller through opening a NC contact using the external power supply. The device has a built-in temperature sensor that allows to monitor ambient temperature. FIBARO Flood Sensor is designed to be placed on the floor or mounted on a wall (in this case Flood Sensor probes should be extended using addition wire). The device has a built-in visual LED indicator and an acoustic alarm. The LED indicator signals flood, operating mode or the Z-Wave network communication range. In addition, the device is equipped with a sensor reporting tilt or movement to the main controller e.g. when someone has taken the Sensor from its original location. FIBARO Flood Sensor is sink-proof, which means it drifts on the water surface and keeps on sending alarm signal in case of substantial inundation of water (if not wired). Flood Sensor is compatible with any Z-Wave or Z-Wave+ Controller. CEPT (Europe) FIBARO Flood Sensor Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1354/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1642/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2742/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2791/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3327/xml + https://products.z-wavealliance.org/products/2742/ + FGFS-101 + U.S. / Canada / Mexico + https://products.z-wavealliance.org/products/3327/ + FGFS-101 + CEPT (Europe) diff --git a/config/fibaro/fggc001.xml b/config/fibaro/fggc001.xml index fc2294be36..655f81ceda 100644 --- a/config/fibaro/fggc001.xml +++ b/config/fibaro/fggc001.xml @@ -1,63 +1,119 @@ - - - - - - - + + + http://www.openzwave.com/device-database/010F:1000:0D01 + images/fibaro/fggc001.png + https://products.z-wavealliance.org/products/1655/ + CEPT (Europe) + 1) Place the Swipe within the direct range of your Z-Wave controller. +2) Set the main controller in (security/non-security) add mode (see the controller’s manual). +3) Move and hold your hand close to the centre of the pad. +4) If the device is battery powered, high pitched beep will signal exiting the Standby Mode. +5) Loud sound sequence will confirm entering the menu, keep holding your hand. +6) After hearing two short beeps, withdraw the hand and perform swiping up gesture to confirm selection (two beeps will confirm validity). +7) Wait for the adding process to end. +8) Successful adding will be confirmed by the Z-Wave controller’s message and 3 short beeps. + + The Swipe needs to be woken up to receive information about the new configuration from the Z-Wave controller, like parameters and associations. Use 1st menu position to wake up the device or click the button on the back of the device once. + +1) Move and hold your hand close to the center of the pad. +2) Loud sound sequence will confirm entering the menu, keep holding your hand. +3) Wait for the buzzer to indicate the 1st menu position (1 short beep) +4) Withdraw the hand and perform swiping up gesture to confirm selection (two beeps will confirm validity). + + + Reset procedure allows to restore the device back to its factory settings, which means all information about the Z-Wave controller and user configuration will be deleted. In order to reset the device: +1) Make sure the device is powered. +2) Move and hold your hand close to the center of the pad. +3) Loud sound sequence will confirm entering the menu, keep holding your hand. +4) Wait for the buzzer to indicate the 3rd menu position (3 short beeps) +5) Withdraw the hand and perform swiping up gesture to confirm selection (two beeps will confirm validity). +Resetting the device is not the recommended way of removing the device from the +Z-Wave network. Use the reset procedure only if the primary controller is missing +or inoperable. Certain device removal can be achieved by the procedure of removing +described in "Adding the device" on page 8. + + + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1745/FGGC-001-US-T-v1.0.pdf + 1) Place the Swipe within the direct range of your Z-Wave controller. +2) Set the main controller in remove mode (see the controller’s manual). +3) Move and hold your hand close to the centre of the pad. +4) If the device is battery powered, high pitched beep will signal exiting the Standby Mode. +5) Loud sound sequence will confirm entering the menu, keep holding your hand. +6) After hearing two short beeps (green indicator colour), withdraw the hand and perform swiping up gesture to confirm selection (two beeps will confirm validity). +7) Wait for the removing process to end. +8) Successful removing will be confirmed by the Z-Wave controller’s message and sequence of 2 short beeps, pause, 1 short beep. + + FIBARO Swipe is a revolutionary, battery-powered gesture control pad that allows you to control devices through the Z-Wave network. Swipe your hand up, down, left or right in front of the pad, make circular gestures and use sequences of gestures to get full and intuitive control of your smart home. +Installed device perfectly matches your interior design, as it resembles a picture frame. You can even personalize it with your favourite picture. Gesture controlled menu allow to add/remove or reset the device without dismounting it. +The device is equipped with a buzzer that confirms performed gestures and other actions. + + FGGC-001 + FIBARO Swipe + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1655/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1745/xml + + https://products.z-wavealliance.org/products/1745/ + FGGC-001 + U.S. / Canada / Mexico + + + + + Parameter determines orientation of the Swipe in relation to its default position. Required for proper gestures recognition. - - - - - - - Acoustic signalling of gestures detection. - - - - - Visual indication of gestures detection - - - - - + + + + + + + Acoustic signalling of gestures detection. + + + + + Visual indication of gestures detection + + + + + Acoustic signalling of gesture recognition result (using the built-in buzzer). Note: Parameter 4 is relevant only if parameter 2 is set to Enabled. - - - - - - + + + + + + This parameter determines how often the device checks if the USB power supply is connected and updates powering mode if needed. 0 - powering mode is not updated 1-1080 (in minutes) - time interval Default : (4 minutes) - - - + + + This parameter determines operation of gesture detection when battery powered. When Standby Mode is selected, hold gesture must be performed to exit power saving mode and reactivate normal gesture recognition. The device in Standby Mode consumes the least battery life. When Simple Mode mode is selected, gesture recognition is always active, but only slowly performed gestures will be recognized properly (high battery consumption). - - - - - - This parameter allows to choose if the menu can be entered using the Hold gesture - - - - - + + + + + + This parameter allows to choose if the menu can be entered using the Hold gesture + + + + + Defines which actions result in sending scenes to 1st Lifeline group 1 - scenes for Flick UP gesture enabled 2 - scenes for Flick DOWN gesture enabled @@ -67,9 +123,9 @@ 32 - scenes for counter-clockwise circular gesture enabled Default setting: 15 - - - + + + Parameter defines how commands are sent in specified association groups: as secure or non-secure. Parameter is active only in Z-Wave network security mode. It does not apply to 1st Lifeline association group. @@ -80,9 +136,9 @@ 16 - 6th group Circular AirWheel sent as secure Default setting: 31 - - - + + + Parameter allows to choose control mode for 2nd-5th groups and scenes. By default, Toggle Mode is active, meaning that a single flick turns ON the group and the same flick turns it OFF, doubled flicks are inactive. @@ -93,114 +149,112 @@ 8 - Toggle Mode enabled for 5th association group Default setting: 15 - - - + + + Parameter allows to choose how long the hand has to be held near the center of the pad after AirWheel gesture for the associated devices to reach their maximum/minimum level. 0-10 - duration in seconds 255 - default settings of controlled devices - - - - + + + + This parameter allows to set value sent in switch ON command frame to the association group. 0-99 or 255 - - - + + + This parameter allows to set value sent in switch OFF command frame to the association group. 0-99 or 255 - - - + + + This parameter allows to set value sent in switch ON command frame to the association group. 0-99 or 255 - - - + + + This parameter allows to set value sent in switch OFF command frame to the association group. 0-99 or 255 - - - + + + This parameter allows to set value sent in switch ON command frame to the association group. 0-99 or 255 - - - + + + This parameter allows to set value sent in switch OFF command frame to the association group. 0-99 or 255 - - - + + + This parameter allows to set value sent in switch ON command frame to the association group. 0-99 or 255 - - - + + + This parameter allows to set value sent in switch OFF command frame to the association group. 0-99 or 255 - - - - + + + + Parameter activated by the main Z-Wave controller. Change its value to launch sequence learning procedure for the desired slot. 0 - learning mode disabled 1-6 - launch sequence learning for selected slot - - - + + + Value containing sequence of gestures. See Sequences of gestures on page 12 for more information. - - - + + + Value containing sequence of gestures. See Sequences of gestures on page 12 for more information. - - - + + + Value containing sequence of gestures. See Sequences of gestures on page 12 for more information. - - - + + + Value containing sequence of gestures. See Sequences of gestures on page 12 for more information. - - - + + + Value containing sequence of gestures. See Sequences of gestures on page 12 for more information. - - - + + + Value containing sequence of gestures. See Sequences of gestures on page 12 for more information. - - - - - - - - - - - - - - - + + + + + + + + + + + + + diff --git a/config/fibaro/fgk10x.xml b/config/fibaro/fgk10x.xml index 59a4f3f8cb..83c70327a4 100644 --- a/config/fibaro/fgk10x.xml +++ b/config/fibaro/fgk10x.xml @@ -1,136 +1,175 @@ - - - + + + http://www.openzwave.com/device-database/010F:2001:0701 + images/fibaro/fgk10x.png + https://products.z-wavealliance.org/products/1620/ + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1620/FGK-10x-US-T-v1.0.pdf + U.S. / Canada / Mexico + Resetting the device is not the recommended way of removing the device from the Z-Wave network. Use reset procedure only if the primary controller is missing or inoperable. - - - - Parameter defines device operation mode. - - - +1) Take off the Sensor's cover and remove battery. +2) Install the battery while holding both TMP buttons (after mounting the device, one button is constantly pressed by the cover). +3) Release the TMP button within 5 seconds. +4) LED will blink 3 times to confirm launching of reset procedure. +5) Reset procedure may last up to 30 seconds. Do not remove the battery until reset is complete. +6) Reset will be confirmed by the six blinks of the LED. + 1) Open the cover. +2) Remove the battery blocker. +3) Close the cover. +4) Locate the sensor nearby the main Z-Wave controller. +5) Set the main Z-Wave controller into adding mode (see main controller’s operating manual). +6) Quickly, triple click the TMP button located on the bottom of the casing. +7) Wait for the device to be added to the system. +8) Successful adding will be confirmed by the controller. +9) Install the device using the attached self-adhesive pads. + + FIBARO Door/Window Sensor is a wireless, battery powered reed sensor compatible with the Z-Wave Plus standard. Changing the device’s status will automatically send signal to the Z-Wave controller and associated devices. +Sensor can be used to trigger scenes and everywhere there is a need for information about opening or closing of doors, windows, garage doors, etc. Opening is detected by separating the sensor’s body and the magnet. +In addition the FIBARO Door/Window Sensor supports one DS18B20 temperature sensor and has one potential free input. - - Parameter defines state of the sensor when the magnet is close. +The FIBARO Door / Window Sensor is available in seven colors: white, silver, black, pearl powder, cappuccino, truffle surprise and dark chocolate. + + +https://www.youtube.com/watch?v=K35uFXoa5c0 + FGK-10X + 1) Place the device within direct reange of the Z-Wave controller. +2) Make sure that Sensor's cover is closed. +3) Set the main Z-Wave controller into learning mode (see main controller’s operating manual). +4) Quickly, triple click the TMP button. +5) Wait for the device to be excluded from the system. Successful exclusion will be confirmed by the controller. + + FIBARO Door/Window Sensor + FIBARO Door/Window Sensor will wake up at a defined time interval and will ALWAYS try to communicate with the main controller. Setting wake up interval to 0 disables sending Wake Up Notification frame automatically. There is a possibility to wake up the device manually by a single TMP button click. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1620/xml + + + + + + Parameter defines device operation mode. + + + + + Parameter defines state of the sensor when the magnet is close. If you connect the alarm sensor, it determines the output type. Parameter inactive in Switch Mode (parameter 1 set to 1). - - - - - - This parameter defines events indicated by the visual LED indicator. + + + + + This parameter defines events indicated by the visual LED indicator. Disabling events might extend battery life. 0 - no indications 1 - indication of opening/closing status change (input IN) 2 - indication of wake up (1 x click or periodical) 4 - indication of device tampering - - - Parameter defines state of the sensor when the magnet is close. + + + Parameter defines state of the sensor when the magnet is close. If you connect the alarm sensor, it determines the output type. Parameter inactive in Switch Mode (parameter 1 set to 1). - - - - - Parameter defines events which result in sending on/off commands to devices added to the 2nd association group. + + + + + Parameter defines events which result in sending on/off commands to devices added to the 2nd association group. These commands are sent alternately to switch the devices on and off. Commands represent the values of BASIC SET command frames. Parameter is inactive in external button mode (parameter 1 set to 1). - - - - - - Command frames sent to devices added to the 2nd association group. - - - - - - The value of 0 turns OFF the device, 255 turns it ON. + + + + + + Command frames sent to devices added to the 2nd association group. + + + + + + The value of 0 turns OFF the device, 255 turns it ON. In case of associating the Dimmer or Roller Shutter module, values 1-99 allow to set an associated device to a specified level. - - - The value of 0 turns OFF the device, 255 turns it ON. + + + The value of 0 turns OFF the device, 255 turns it ON. In case of associating the Dimmer or Roller Shutter module, values 1-99 allow to set an associated device to a specified level. - - - Time period after which ON command frame will be sent. + + + Time period after which ON command frame will be sent. - - - Time period after which OFF command frame will be sent. + + + Time period after which OFF command frame will be sent. - - - Type of control frames transmitted to the main controller and 3rd association group Alarm. + + + Type of control frames transmitted to the main controller and 3rd association group Alarm. If an external sensor is connected to IN input, it is possible to choose its functionality. Otherwise it is recommended to set this parameter to default value. - - - - - - - - - - Time period after which a tamper alarm will be cancelled. + + + + + + + + + Time period after which a tamper alarm will be cancelled. - - - Reporting cancellation of tamper alarm to the controller and 5th association group. - - - - - This parameter defines how often the temperature will be measured. + + + Reporting cancellation of tamper alarm to the controller and 5th association group. + + + + + This parameter defines how often the temperature will be measured. The shorter the time, the more frequently the temperature will be measured, but the battery life will shorten. 0 - temperature measurements disabled 5-32400 - time in seconds - - - This parameter defines the change of temperature in comparison with last reported, resulting in temperature report being sent to the main controller. + + + This parameter defines the change of temperature in comparison with last reported, resulting in temperature report being sent to the main controller. 0 - temperature reports based on threshold disabled 1-300 - temperature threshold (0.1-30C, 0.1C step) - - - This parameter determines how often the temperature reports will be sent to the main controller. + + + This parameter determines how often the temperature reports will be sent to the main controller. 0 - periodic temperature reports disabled 5-32400 - time in seconds - - - The value to be added to the actual temperature, measured by the sensor (temperature compensation). (0,1C steps) + + + The value to be added to the actual temperature, measured by the sensor (temperature compensation). (0,1C steps) - - - Temperature alarms reported to the Z-Wave controller. + + + Temperature alarms reported to the Z-Wave controller. Thresholds are set in parameters 55 and 56. - - - - - - - If temperature is higher than set value, overheat notification will be sent and high temperature scene will be triggered (if activated). + + + + + + + If temperature is higher than set value, overheat notification will be sent and high temperature scene will be triggered (if activated). 0-1000 (0-100C, 0.1C step). - - - If temperature is lower than the set value, underheat notification will be sent and low temperature scene will be triggered (if activated). + + + If temperature is lower than the set value, underheat notification will be sent and low temperature scene will be triggered (if activated). 300-700 (-30-70C, 0.1C step) - - - The device can trigger scenes using scene IDs assigned to different events. + + + The device can trigger scenes using scene IDs assigned to different events. To deactivate all scenes set the value to 0. To activate all scenes set the value to 3903. 1 - [ID 10] opening door/window (single click). @@ -144,9 +183,9 @@ 1024 - [ID 51] low temperature - door/window opened. 2048 - [ID 51] low temperature - door/window closed. - - - Settings for broadcasting ON/OFF commands, sensor alarm and tamper alarm. + + + Settings for broadcasting ON/OFF commands, sensor alarm and tamper alarm. Value other than 0 means alarms are sent in Broadcast Mode, to all devices only within the range of the device. They are not repeated by the mesh network. 0 - broadcasts inactive. @@ -154,9 +193,9 @@ 2 - sensor alarm broadcast active. 4 - tamper alarm broadcast active. - - - This parameter defines how commands are sent in specified association groups: as secure or non-secure. + + + This parameter defines how commands are sent in specified association groups: as secure or non-secure. Parameter is active only in Z-Wave network security mode. It does not apply to 1st group Lifeline 0 - none of the groups sent as secure. 1 - 2nd group Control sent as secure. @@ -164,17 +203,16 @@ 4 - 4th group Sensor ZW3 sent as secure. 8 - 5th group Tamper ZW3 sent as secure. - - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/config/fibaro/fgkf601.xml b/config/fibaro/fgkf601.xml index 745ad9e3ac..dffa1f9b35 100644 --- a/config/fibaro/fgkf601.xml +++ b/config/fibaro/fgkf601.xml @@ -1,21 +1,68 @@ - + + + http://www.openzwave.com/device-database/010F:1000:1001 + images/fibaro/fgkf601.png + https://products.z-wavealliance.org/products/2064/ + 1) Place the KeyFob within the direct range of your Z-Wave controller. +2) Set the main Z-Wave controller in (security/non-security) add mode (see the controller’s manual). +3) Press any button three times. +4) Wait for the adding process to end. +5) Successful adding will be confirmed by the Z-Wave controller’s message and green LED colour. + + CEPT (Europe) + FIBARO KeyFob is a Z-Wave Plus compatible, battery-powered, compact remote control. +Six buttons allow you to control other devices through the Z-Wave network and run various scenes defined in FIBARO System. +Configure actions for one, two, three clicks and holding the button to suit all your needs. +Built-in locking system will ensure that unauthorized person will not take control of your home. + + Reset procedure allows to restore the device back to its factory settings, which means all information about the Z-Wave controller and user configuration will be deleted. There are two ways of resetting the device: +• Resetting using the menu +1) Press O and – simultaneously. +2) Press Δ or X until LED glows yellow. +3) Press + to confirm. +• Resetting on start-up +1) Remove the battery. +2) Hold O and + while inserting the battery. +Successful resetting will be confirmed by smoothly brightening and dimming of the yellow LED colour. - - - - - - - +Please use this procedure only when the network primary controller is missing or otherwise inoperable + The Keyfob needs to be woken up to receive information about the new configuration from the Z-Wave controller, like parameters and associations. To wake up the device press O and + simultaneously or use 1st menu position: +1) Press O and – simultaneously. +2) Press Δ or X until LED glows white. +3) Press + to confirm. + + 1) Place the KeyFob within the direct range of your Z-Wave controller. +2) Set the main Z-Wave controller in remove mode (see the controller’s manual). +3) Press O and – simultaneously. +4) Press Δ or X until LED glows green. +5) Press + to confirm. +6) Wait for the removing process to end. +7) Successful removing will be confirmed by the Z-Wave controller’s message. + + FGKF-601 + FIBARO KeyFob + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2120/FGKF-601-EN-T-v1.0_30.11.2016.pdf + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2064/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2120/xml + + https://products.z-wavealliance.org/products/2120/ + U.S. / Canada / Mexico + FGKF-601 + + + + + This parameter allows to activate Lock Mode and set up unlocking sequence. Device will lock after time set in parameter 2 or after pressing and holding selected button. 0 - Lock Mode disabled. 9-28086 - unlocking sequence. See "Lock Mode" on page 9 for more information. - - - + + + This parameter allows to set time that must elapse from the last press of the button to lock the device and locking button. Setting locking button will deactivate associations and scenes for pressing and holding the selected button. This parameter is irrelevant if parameter 1 is set to 0 (Lock Mode disable). @@ -23,141 +70,141 @@ 5-1791- calculated value. See "Lock Mode" on page 9 for more information - - - + + + This parameter allows to set up sequence that activates scene with ID 7. 0 - 1st sequence disabled. 9-28086 - value of sequence. See "Sequences" on page 10 for more information. - - - + + + This parameter allows to set up sequence that activates scene with ID 8. 0 - 1st sequence disabled. 9-28086 - value of sequence. See "Sequences" on page 10 for more information. - - - + + + This parameter allows to set up sequence that activates scene with ID 9. 0 - 1st sequence disabled. 9-28086 - value of sequence. See "Sequences" on page 10 for more information. - - - + + + This parameter allows to set up sequence that activates scene with ID 10. 0 - 1st sequence disabled. 9-28086 - value of sequence. See "Sequences" on page 10 for more information. - - - + + + This parameter allows to set up sequence that activates scene with ID 11. 0 - 1st sequence disabled. 9-28086 - value of sequence. See "Sequences" on page 10 for more information. - - - + + + This parameter allows to set up sequence that activates scene with ID 12. 0 - 1st sequence disabled. 9-28086 - value of sequence. See "Sequences" on page 10 for more information. - - - + + + This parameter allows to set time that must elapse from the last press of the button to check if the sequence is valid. Available settings: 5-30 (0.5-3s, 0.1s step) - time to lock - - - This parameter allows to choose operating mode for single button associations. - - - - - - + + + This parameter allows to choose operating mode for single button associations. + + + + + + This parameter allows to set value sent to devices in association group. It will result in turning multilevel devices on with set or last level. Value is irrelevant for simple on/off devices. Available settings: 1-99 or 255. - - - + + + This parameter allows to set value sent to devices in association group. It will result in turning multilevel devices on with set or last level. Value is irrelevant for simple on/off devices. Available settings: 1-99 or 255. - - - + + + This parameter allows to set value sent to devices in association group. It will result in turning multilevel devices on with set or last level. Value is irrelevant for simple on/off devices. Available settings: 1-99 or 255. - - - + + + This parameter allows to set value sent to devices in association group. It will result in turning multilevel devices on with set or last level. Value is irrelevant for simple on/off devices. Available settings: 1-99 or 255. - - - + + + This parameter allows to set value sent to devices in association group. It will result in turning multilevel devices on with set or last level. Value is irrelevant for simple on/off devices. Available settings: 1-99 or 255. - - - + + + This parameter allows to set value sent to devices in association group. It will result in turning multilevel devices on with set or last level. Value is irrelevant for simple on/off devices. Available settings: 1-99 or 255. - - - + + + This parameter allows to activate paired buttons association mode for Square and Circle buttons. Paired buttons are dependent and association are sent only to Square groups. Circle turns devices on and increases value, Square turns them off and decreases value. - - - - - + + + + + This parameter allows to activate paired buttons association mode for Cross and Triangle buttons. Paired buttons are dependent and association are sent only to Cross groups. Triangle turns devices on and increases value, Cross turns them off and decreases value. - - - - - + + + + + This parameter allows to activate paired buttons association mode for Minus and Plus buttons. Paired buttons are dependent and association are sent only to Minus groups. Plus turns devices on and increases value, Minus turns them off and decreases value. - - - - - + + + + + This parameter determines which actions result in sending assigned scene IDs and attributes to the controller. 1 - Key Pressed 1 time. 2 - Key Pressed 2 times. @@ -165,9 +212,9 @@ 8 - Key Held Down and Released. Default setting: 9, 1x and hold. - - - + + + This parameter determines which actions result in sending assigned scene IDs and attributes to the controller. 1 - Key Pressed 1 time. 2 - Key Pressed 2 times. @@ -175,9 +222,9 @@ 8 - Key Held Down and Released. Default setting: 9, 1x and hold. - - - + + + This parameter determines which actions result in sending assigned scene IDs and attributes to the controller. 1 - Key Pressed 1 time. 2 - Key Pressed 2 times. @@ -185,9 +232,9 @@ 8 - Key Held Down and Released. Default setting: 9, 1x and hold. - - - + + + This parameter determines which actions result in sending assigned scene IDs and attributes to the controller. 1 - Key Pressed 1 time. 2 - Key Pressed 2 times. @@ -195,9 +242,9 @@ 8 - Key Held Down and Released. Default setting: 9, 1x and hold. - - - + + + This parameter determines which actions result in sending assigned scene IDs and attributes to the controller. 1 - Key Pressed 1 time. 2 - Key Pressed 2 times. @@ -205,9 +252,9 @@ 8 - Key Held Down and Released. Default setting: 9, 1x and hold. - - - + + + This parameter determines which actions result in sending assigned scene IDs and attributes to the controller. 1 - Key Pressed 1 time. 2 - Key Pressed 2 times. @@ -215,9 +262,9 @@ 8 - Key Held Down and Released. Default setting: 9, 1x and hold. - - - + + + Parameter defines how commands are sent in specified association groups: using Security Mode or not. Parameter is active only in Z-Wave network Security Mode. It does not apply to 1st Lifeline association group. 1 : 2nd group sent using Security Mode. @@ -233,24 +280,24 @@ 1024 : 12th group sent using Security Mode. 2048 : 13th group sent using Security Mode. - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + diff --git a/config/fibaro/fgmszw5.xml b/config/fibaro/fgmszw5.xml index 75cd33756f..6453714b01 100644 --- a/config/fibaro/fgmszw5.xml +++ b/config/fibaro/fgmszw5.xml @@ -1,58 +1,65 @@ - + http://www.openzwave.com/device-database/010F:1001:0801 images/fibaro/fgmszw5.png - https://products.z-wavealliance.org/products/1146/ + https://products.z-wavealliance.org/products/2762/ FGMS-001 - 1) Make sure tampering the device will not result in undesirable effects. Dismounting the sensor can trigger an alarm. -2) Open the sensor’s casing by turning the cover counter-clockwise. Enclosure lock is marked with a dot. -3) Make sure the sensor's battery is unlocked. -4) Set the main controller into learning mode (see main controller’s operating manual). -5) Quickly, triple click the B-button, located inside Fibaro Motion Sensor’s casing. LED diode will glow blue confirming that the device has sent the Node Info Z-Wave command frame. - + 1. Open the cover by turning it counter-clockwise. +2. Place the device within the direct range of your Z-Wave controller. +3. Set the main controller in remove mode (see the controller’s manual). +4. Quickly, three times press the B-button. +5. Wait for the removing process to end. +6. Successful removing will be confirmed by the Z-Wave controller’s message. FIBARO Motion Sensor - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1146/FGMS-001-EN-A-v1.02.pdf - FIBARO Motion Sensor is a highly advanced ultra-small, battery powered multi-sensor. This device detects movement, measures the current ambient temperature, intensity of the light and thanks to built-in accelerometer detects vibrations. FIBARO Motion Sensor is a completely wireless and mobile device. Depending on user-defined situation in the settings panel it’s eye will shine in different colours, alerting you whenever the temperature and light intensity changes, or when it detects the movement in the room. The battery can last up to 2 years while its level is automatically reported to the central unit. The notification is being sent to the central hub when the battery level approaches to critical. - -Product video: -https://www.youtube.com/watch?v=R_I2p1Tq2QU - The Fibaro Motion Sensor can be included into the Z-Wave network by using the B-button. -1) Open the sensor’s casing by turning the cover counter-clockwise. Enclosure lock is marked with a dot. -2) Unlock battery by removing “I'm ready” stripe. -3) Make sure the device is located within the direct range of the main controller. -4) Set the main controller into learning mode (see main controller’s operating manual). -5) Quickly, triple click the B-button - LED diode will glow blue to confirm setting into learning mode. -6) Fibaro Motion Sensor will be detected and included into the Z-Wave network. Wait for the main controller to configure the sensor. -7) If necessary, wake up the Motion Sensor by clicking the B-button. -8) Close the sensor’s casing and install the device in desired place. - Please use this procedure in the event that the system’s primary controller is missing or is inoperable. - -To reset the device: -1) Make sure the battery works and it’s correctly placed. -2) Press and hold the B-button for 4-6 seconds until the LED glows yellow signaling the 2nd option of the menu mode. -3) Release the B-button. -4) Again, press the B-button briefly. Successful reset will be confirmed with the LED changing colour to red and fading. - -For more information please check the user's manual. - + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3379/FGMS-001-EN-T-v2.1.pdf + FIBARO Motion Sensor is a universal, Z-Wave Plus compatible multi-sensor. This device has a built-in motion sensor, temperature sensor and light sensor. Additionally, through vibrations detection, it may detect tampering attempt or an earthquake. FIBARO Motion Sensor is battery powered, completely wireless, and its casing allows for quick and non-invasive installation on any surface. The eye of the sensor visually indicates motion, temperature level, operating mode or may inform about Z-Wave network range. The device can be used for lighting scenes and presence monitoring systems. + 1. Open the cover by turning it counter-clockwise. +2. Place the device within the direct range of your Z-Wave controller. +3. Set the main controller in (security/non-security) add mode (see the controller’s manual). +4. Quickly, three times press the B-button. +5. Wait for the adding process to end. +6. Successful adding will be confirmed by the Z-Wave controller’s message. + 1. Open the cover by turning it counter-clockwise. +2. Press and hold the B-button. +3. Wait for visual indicator to glow yellow (2nd menu position). +4. Release the B-button. +5. Click the B-button to confirm selection. +6. After few seconds the device will be reset, which is signalled with the red, fading visual indicator colour. +Use reset procedure only if the primary controller is missing or inoperable. CEPT (Europe) - The Motion Sensor will wake up at a defined time interval and will ALWAYS try to communicate with the main controller. There is a possibility to wake up the device manually by clicking the B-button. + The Motion Sensor will wake up at a defined time interval and will always try to communicate with the main controller. There is a possibility to wake up the device manually by clicking the B-button. Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1146/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1514/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2762/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2763/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3336/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3379/xml + Force Association Single Channel on Lifeline - https://github.com/OpenZWave/open-zwave/issues/1830 + https://products.z-wavealliance.org/products/2763/ + U.S. / Canada / Mexico + FGMS-001 + https://products.z-wavealliance.org/products/3336/ + FGMS-001 + CEPT (Europe) + https://products.z-wavealliance.org/products/3379/ + U.S. / Canada / Mexico + FGMS-001 - + The lower the value, the more sensitive the PIR sensor is. Available settings: 8 - 255 Default setting: 15 - + @@ -61,14 +68,14 @@ For more information please check the user's manual. Available settings: 0 - 15 (0.5-8 seconds). Formula to calculate the time: time [s] = 0.5 x (value+1)) Default setting: 3 - + This parameter determines the number of moves required for the PIR sensor to report motion. The higher the value, the less sensitive the PIR sensor is. It is not recommended to modify this parameter settings! Default setting: 1 (2 pulses) - + @@ -80,7 +87,7 @@ For more information please check the user's manual. The higher the value, the more sensitive the PIR sensor is. It is not recommended to modify this parameter setting! Default setting: 2 (12 seconds) - + @@ -92,7 +99,7 @@ For more information please check the user's manual. Any motion detected during this period resets the timer. Available settings: 1 - 65535 Default setting: 30 (30 seconds) - + @@ -100,7 +107,7 @@ For more information please check the user's manual. This parameter influences only the motion reports and associations. Tamper, light intensity and temperature measurements will be still active, regardless of this parameter settings. Default setting: 0 (always active) - + @@ -110,13 +117,13 @@ For more information please check the user's manual. This parameter defines the difference between night and day in terms of light intensity, used in parameter 8. Available settings: 1 - 65535 Default setting: 200 (200 lux) - + This parameter determines the command frames sent to 2nd association group (assigned to PIR sensor). Default setting: 0 (ON and OFF) - + @@ -127,14 +134,14 @@ For more information please check the user's manual. Further motion detections, during the cancellation time, will not result in sending the association. Available settings: 0 - 255 Default setting: 255 - + The command frame sent at the moment of motion alarm cancellation, after cancellation delay time specified in parameter 6. Available settings: 0 - 255 Default setting: 0 - + @@ -145,14 +152,14 @@ For more information please check the user's manual. 2 - 3rd group sent as secure. 4 - 4th group sent as secure. 8 - 5th group sent as secure. - + This parameter determines the change in force acting on the device, that will result in reporting tamper alarm - g-force acceleration. Available settings: 0 - 121 (0.08 - 2g; multiply by 0.016g; 0 = tamper inactive) Default setting: 20 (0.4g) - + @@ -160,14 +167,14 @@ For more information please check the user's manual. Any tampering detected during this period will not extend the delay. Available settings: 1 - 65535 Default setting: 30 (seconds) - + This parameter determines function of the tamper and sent reports. It is an advanced feature serving much more functions than just detection of tampering. Default setting: 0 (Tamper) - + @@ -176,7 +183,7 @@ For more information please check the user's manual. This parameter allows to disable cancellation of the tamper alarm. Default setting: 0 (Tamper). - + @@ -185,7 +192,7 @@ For more information please check the user's manual. The parameter determines whether the tamper alarm frame will or will not be sent in broadcast mode. Alarm frames sent in broadcast mode can be received by all of the devices within range (if they accept such frames), but not repeated by them. Default setting: 0 - + @@ -195,7 +202,7 @@ For more information please check the user's manual. Alarm frames sent in broadcast mode can be received by all of the devices within range (if they accept such frames), but not repeated by them. This parameter provides backward compatibility with controllers not supporting Z-Wave+. Default setting: 0 - + @@ -206,7 +213,7 @@ For more information please check the user's manual. 0 - reports are not sent. 1-32767 (luminance in lux). Default setting: 200 (200 lux). - + @@ -215,14 +222,14 @@ For more information please check the user's manual. Available settings: 0 - 32767. 0 - periodical reports are not sent. 1-32767 (in seconds). - + This parameter determines the change in measured temperature that will result in new temperature report being sent to the main controller. Available settings: 0 - 255 (0.1 - 25.5C; 0 = reports are not sent) Default setting: 10 (1C) - + @@ -230,27 +237,27 @@ For more information please check the user's manual. The shorter the time, the more frequently the temperature will be measured, but the battery life will shorten. Available settings: 0 - 32767 (1 - 32767 seconds; 0 = temperature is not measured) Default setting: 900 (900 seconds). - + Time interval between consecutive temperature reports. The reports are sent even if there is no change in the temperature. Available settings: 0 - 32767 (1 - 32767 seconds; 0 = periodical reports are not sent) Default setting: 0 - + The value to be added to the actual temperature, measured by the sensor (temperature compensation). Available settings: 0 - 100 (0 to 100C) or 64536 - 65535 (-100 to -0.10C) Default setting: 0 - + This parameter determines the way in which visual indicator behaves after motion has been detected. Default setting: 10 (Flashlight mode) - + @@ -285,14 +292,14 @@ For more information please check the user's manual. Available settings: 0 - brightness determined by the luminance (parameters 82 and 83). 1-100 (1-100%) Default setting: 50 (50 %) - + Light intensity level below which brightness of visual indicator is set to 1%. Available settings: 0 to value of parameter 83 (in lux). Default setting: 100. - + @@ -301,7 +308,7 @@ For more information please check the user's manual. Default setting: 1000 (1000 lux) NOTE The value of the parameter 83 must be higher than the value of the parameter 82. - + @@ -309,7 +316,7 @@ For more information please check the user's manual. Relevant only when parameter 80 has been properly configured. Available settings: 0 to value of parameter 87 (in Celsius degree) Default setting: 18 (18C) - + @@ -317,13 +324,13 @@ For more information please check the user's manual. Relevant only when parameter 80 has been properly configured. Available settings: value of parameter 86 to 255 (in Celsius degree) Default setting: 28 (28C) - + Indicating mode resembles a police car (white, red and blue). Default setting: 1 (on) - + @@ -334,14 +341,17 @@ For more information please check the user's manual. true - - + + + + false + - - + + diff --git a/config/fibaro/fgpb101.xml b/config/fibaro/fgpb101.xml index fef10e4182..55a10aceff 100644 --- a/config/fibaro/fgpb101.xml +++ b/config/fibaro/fgpb101.xml @@ -1,10 +1,51 @@ - - - - - - - + + + http://www.openzwave.com/device-database/010F:1000:0F01 + images/fibaro/fgpb101.png + https://products.z-wavealliance.org/products/1944/ + Reset procedure allows to restore the device back to its factory settings, which means all information about the Z-Wave controller and user configuration will be deleted. In order to reset the device: +1) Click the Button exactly five times. +2) Press and hold the Button for at least 5 seconds. +Please use this procedure only when the network primary controller is missing or otherwise inoperable + FIBARO Button + 1) Place the Button within the direct range of your Z-Wave controller. +2) Set the main controller in remove mode (see the controller’s manual). +3) Click the Button at least six times. +4) Wait for the removing process to end. +5) Successful removing will be confirmed by the Z-Wave controller’s message. + + 1) Place the Button within the direct range of your Z-Wave controller. +2) Set the main controller in (security/non-security) add mode (see the controller’s manual). +3) Click the Button at least six times. +4) Wait for the adding process to end. +5) Successful adding will be confirmed by the Z-Wave controller’s message. + + FIBARO Button is a compact, battery-powered, Z-Wave Plus compatible device. It allows you to control devices through the Z-Wave network and run various scenes defined in FIBARO System. +Different actions may be triggered with one to five clicks or by holding the button down. In Panic Button mode, each press of the button results in triggering the Fibaro Alarm. +With its small design and wireless communication, the FIBARO Button can be conveniently mounted on any surface and in any position or location at home, e.g. beside the bed or under the desk. + + FGPB-101 + The Button needs to be woken up to receive information about the new configuration from the controller, like parameters and associations. +1) Click the Button 4 times to wake it up + + CEPT (Europe) + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2018/FGPB-101-EN-T-v1.1.pdf + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1944/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2017/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2018/xml + + https://products.z-wavealliance.org/products/2017/ + FGPB-101 + U.S. / Canada / Mexico + https://products.z-wavealliance.org/products/2018/ + Australia / New Zealand + FGPB-101 + + + + + This parameter determines which actions result in sending scene IDs and attributes assigned to them. 1 - Key Pressed 1 time. 2 - Key Pressed 2 times. @@ -16,9 +57,9 @@ Note: Values of parameter 1 may be combined, e.g. 1+2=3 means that scenes will be sent after pressing the button once or twice. Default: 127 All. - - - + + + This parameter defines how commands are sent in specified association groups: as secure or non-secure. Parameter is active only in Z-Wave network security mode. It does not apply to 1st Lifeline group. 1 - 2nd group sent as secure. @@ -26,76 +67,76 @@ 4 - 4th group sent as secure. Default: 3 All. - - - This parameter defines commands sent to devices associated in 2nd association group after a single click - - - - - - - This parameter defines value of SWITCH ON command sent to devices in 2nd association group after a single click. - - - This parameter defines commands sent to devices associated in 2nd association group after a double click - - - - - - - This parameter defines value of SWITCH ON command sent to devices in 2nd association group after a double click. - - - This parameter defines commands sent to devices associated in 2nd association group after a triple click - - - - - - - This parameter defines value of SWITCH ON command sent to devices in 2nd association group after a triple click. - - - This parameter defines commands sent to devices associated in 2nd association group after a single click - - - - - - - This parameter defines value of SWITCH ON command sent to devices in 3rd association group after a single click. - - - This parameter defines commands sent to devices associated in 3rd association group after a double click - - - - - - - This parameter defines value of SWITCH ON command sent to devices in 3rd association group after a double click. - - - This parameter defines commands sent to devices associated in 3rd association group after a triple click - - - - - - - This parameter defines value of SWITCH ON command sent to devices in 3rd association group after a triple click. - - - This parameter defines commands sent to devices associated in 3rd association group after holding the button down. - - - - - - - + + + This parameter defines commands sent to devices associated in 2nd association group after a single click + + + + + + + This parameter defines value of SWITCH ON command sent to devices in 2nd association group after a single click. + + + This parameter defines commands sent to devices associated in 2nd association group after a double click + + + + + + + This parameter defines value of SWITCH ON command sent to devices in 2nd association group after a double click. + + + This parameter defines commands sent to devices associated in 2nd association group after a triple click + + + + + + + This parameter defines value of SWITCH ON command sent to devices in 2nd association group after a triple click. + + + This parameter defines commands sent to devices associated in 2nd association group after a single click + + + + + + + This parameter defines value of SWITCH ON command sent to devices in 3rd association group after a single click. + + + This parameter defines commands sent to devices associated in 3rd association group after a double click + + + + + + + This parameter defines value of SWITCH ON command sent to devices in 3rd association group after a double click. + + + This parameter defines commands sent to devices associated in 3rd association group after a triple click + + + + + + + This parameter defines value of SWITCH ON command sent to devices in 3rd association group after a triple click. + + + This parameter defines commands sent to devices associated in 3rd association group after holding the button down. + + + + + + + Parameter determines which actions result in sending alarm frames to 4th association group. 1 - Key Pressed 1 time. 2 - Key Pressed 2 times. @@ -106,15 +147,15 @@ 64 - Key Released. Default: 127 All. - - - - - - - - - - - + + + + + + + + + + + diff --git a/config/fibaro/fgr223.xml b/config/fibaro/fgr223.xml index fdfaf2ec85..8249e96592 100644 --- a/config/fibaro/fgr223.xml +++ b/config/fibaro/fgr223.xml @@ -1,40 +1,98 @@ - - - - - - + + + http://www.openzwave.com/device-database/010F:1000:0303 + images/fibaro/fgr223.png + https://products.z-wavealliance.org/products/3278/ + FIBARO Roller Shutter 3 is powered with mains voltage so it is always awake. + Reset procedure allows to restore the device back to its factory settings, which means all information about the Z-Wave controller and user configuration will be deleted. +1. Switch off the mains voltage (disable the fuse). +2. Remove the device from the wall switch box. +3. Switch on the mains voltage. +4. Press and hold the B-button to enter the menu. +5. Wait for the LED indicator to glow yellow. +6. Quickly release and click the B-button again. +7. After few seconds the device will be restarted, which is signalled with the red LED indicator colour. +Please use this procedure only when the network primary controller is missing or otherwise inoperable." + + FGR-223 + Roller Shutter 3 + To add the device to the Z-Wave network manually: +1. Power the device. +2. Identify the S1 switch. +3. Set the main controller in (Security/non-Security Mode) add mode (see the controller’s manual). +4. Quickly, triple click the S1 switch. +5. If you are adding in Security S2, scan the DSK QR code or input the underlined part of the DSK (label on the bottom of the box). +6. Wait for the adding process to end. +7. Successful adding will be confirmed by the Z-Wave controller’s message. + +To add the device to the Z-Wave network using Smart Start: +1. Set the main controller in Security S2 Authenticated add mode (see the controller’s manual) +2. Scan the DSK QR code or input the underlined part of the DSK +3. (label on the bottom of the box). +4. Power the device (turn on the mains voltage). +5. LED will start blinking yellow, wait for the adding process to end. +6. Successful adding will be confirmed by the Z-Wave controller’s message. + + + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3278/FGR-223-EN-T-v1.3.pdf + CEPT (Europe) + To remove the device from the Z-Wave network: +1. Make sure the device is powered. +2. Identify the S1 switch. +3. Set the main controller in remove mode (see the controller’s manual). +4. Quickly, triple click the S1 switch. +5. Wait for the removing process to end. +6. Successful removing will be confirmed by the Z-Wave controller’s message. + + FIBARO Roller Shutter 3 is a device designed to control roller blinds, awnings, venetian blinds, gates and other single phase, AC powered devices. +Roller Shutter 3 allows precise positioning of roller blinds or venetian blind lamellas. The device is equipped with power and energy monitoring. It allows to control connected devices either via the Z-Wave network or via a switch connected directly to it. +Main features of FIBARO Roller Shutter 3: +- Compatible with any Z-Wave or Z-Wave Plus Controller, +- Supports Z-Wave network Security Modes: S0 with AES-128 encryption and S2 with PRNG-based encryption, +- To be installed with roller blind motors with electronic or mechanical limit switches, +- Advanced microprocessor control, +- Active power and energy metering functionality, +- Works with various types of switches – momentary, toggle and dedicated roller blind switches, +- To be installed in wall switch boxes, +- Works as a Z-Wave signal repeater. + + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3183/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3278/xml + + + + + + This parameter defines as what type the device should treat the switch connected to the S1 and S2 terminals. This parameter is not relevant in gate operating modes (parameter 151 set to 3 or 4). In this case switch always works as a momentary and has to be connected to S1 terminal. - - - - - - - + + + + + + This parameter allows reversing the operation of switches connected to S1 and S2 without changing the wiring. Default: S1 -> 1st channel, S2 -> 2nd channel. Reversed: S1 -> 2nd channel, S2 -> 1st channel. - - - - - - + + + + + This parameter allows reversing the operation of Q1 and Q2 without changing the wiring (in case of invalid motor connection) to ensure proper operation. - Default: Q1 -> 1st channel, Q2 -> 2nd channel. - Reversed: Q1 -> 2nd channel, Q2 -> 1st channel. - - - - - - + + + + + This parameter determines to which alarm frames and how the device should react. The parameters consist of 4 bytes, three most significant bytes are set according to the official Z-Wave protocol specification. 1B [MSB] - notification Type. @@ -46,10 +104,9 @@ 2 - close blinds. Default setting: [0x00, 0x00, 0x00, 0x00] - - - - + + + This parameter determines to which alarm frames and how the device should react. The parameters consist of 4 bytes, three most significant bytes are set according to the official Z-Wave protocol specification. 1B [MSB] - notification Type. @@ -61,10 +118,9 @@ 2 - close blinds. Default setting: [0x05, 0xFF, 0x00, 0x00] (Water Alarm, any notification, no action) - - - - + + + This parameter determines to which alarm frames and how the device should react. The parameters consist of 4 bytes, three most significant bytes are set according to the official Z-Wave protocol specification. 1B [MSB] - notification Type. @@ -76,10 +132,9 @@ 2 - close blinds. Default setting: [0x01, 0xFF, 0x00, 0x00] (Smoke Alarm, any notification, no action) - - - - + + + This parameter determines to which alarm frames and how the device should react. The parameters consist of 4 bytes, three most significant bytes are set according to the official Z-Wave protocol specification. 1B [MSB] - notification Type. @@ -91,10 +146,9 @@ 2 - close blinds. Default setting: [0x02, 0xFF, 0x00, 0x00] (CO Alarm, any notification, no action) - - - - + + + This parameter determines to which alarm frames and how the device should react. The parameters consist of 4 bytes, three most significant bytes are set according to the official Z-Wave protocol specification. 1B [MSB] - notification Type. @@ -106,10 +160,9 @@ 2 - close blinds. Default setting: [0x04, 0xFF, 0x00, 0x00] (Heat Alarm, any notification, no action) - - - - + + + This parameter determines which actions result in sending scene IDs assigned to them. Sum of: 1 - Key pressed 1 time. @@ -118,10 +171,9 @@ 8 - Key hold down and key released. Default setting: 0. - - - - + + + This parameter determines which actions result in sending scene IDs assigned to them. Sum of: 1 - Key pressed 1 time. @@ -130,16 +182,14 @@ 8 - Key hold down and key released. Default setting: 0. - - - - This parameter determines whether the power metering should include the amount of active power consumed by the device itself. - - - - - - + + + This parameter determines whether the power metering should include the amount of active power consumed by the device itself. + + + + + This parameter determines the minimum change in consumed power that will result in sending new power report to the main controller. For loads under 50W, the parameter is not relevant and reports are sent every 5W change. Power reports are sent no often than every 30 seconds. @@ -147,125 +197,113 @@ 1-500 (1-500%): change in power. Default setting: 15. - - - - + + + This parameter determines in what time intervals the periodic power reports are sent to the main controller. Periodic reports do not depend on power change (parameter 61). 0: periodic reports are disabled 30-32400 (30-32400s): report interval. Default setting: 3600 (1h). - - - - + + + This parameter determines the minimum change in consumed energy that will result in sending new energy report to the main controller. 0: reports are disabled. 1-500 (0.01 - 5 kWh): change in energy. Default setting: 10 (0.1 kWh). - - - - + + + This parameter determines in what time intervals the periodic energy reports are sent to the main controller. Periodic reports do not depend on energy change (parameter 65). 0: periodic reports are disabled. 30-32400 (30-32400s): report interval. Default setting: 3600 (1h) - - - - + + + By setting this parameter to 2 the device enters the calibration mode. The parameter relevant only if the device is set to work in positioning mode (parameter 151 set to 1, 2 or 4). - - - - - - - This parameter allows adjusting operation according to the connected device. - - - - - - - - - - + + + + + + This parameter allows adjusting operation according to the connected device. + + + + + + + + + For Venetian blinds (parameter 151 set to 2) the parameter determines time of full turn cycle of the slats. For gates (parameter 151 set to 3 or 4) the parameter determines time after which open gate will start closing automatically (if set to 0, gate will not close). The parameter is irrelevant for other modes. 0-90000 (0 - 900s, every 0.01s) time of turn. Default setting: 150 (1.5s). - - - - + + + For Venetian blinds (parameter 151 set to 2) the parameter determines slats positioning in various situations. The parameter is irrelevant for other modes. - - - - - - - + + + + + + For blinds (parameter 151 set to 1, 2, 5 or 6) the parameter determines the time after which the motor will be stopped after end switch contacts are closed. For gates (parameter 151 set to 3 or 4) the parameter determines the time after which the gate will start closing automatically if S2 contacts are opened (if set to 0, gate will not close). 0-600 (0 - 60s). Default setting: 10 (1s). - - - - + + + Power threshold to be interpreted as reaching a limit switch. 0: reaching a limit switch will not be detected 1-255 (1-255W): report interval. Default setting: 10. - - - - + + + This parameter determines the time needed for roller blinds to reach the top. For modes with positioning value is set automatically during calibration, otherwise, it must be set manually. 1-90000 (0.01 - 900.00s). Default setting: 6000 (60s). - - - - + + + This parameter determines time needed for roller blinds to reach the bottom. For modes with positioning value is set automatically during calibration, otherwise, it must be set manually. 1-90000 (0.01 - 900.00s). Default setting: 6000 (60s). - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/config/fibaro/fgs213.xml b/config/fibaro/fgs213.xml index 706945e024..5fa0ef96de 100644 --- a/config/fibaro/fgs213.xml +++ b/config/fibaro/fgs213.xml @@ -1,4 +1,53 @@ - + + + http://www.openzwave.com/device-database/010F:1000:0403 + images/fibaro/fgs213.png + https://products.z-wavealliance.org/products/2730/ + Reset procedure allows to restore the device back to its factory settings, which means all information about the Z-Wave controller and user configuration will be deleted. In order to reset the device: + +1) Switch off the mains voltage (disable the fuse). +2) Remove the Switch 2 from the wall switch box. +3) Switch on the mains voltage. +4) Press and hold the B-button to enter the menu. +5) Wait for the visual LED indicator to glow yellow. +6) Quickly release and click the B-button again. +7) After few seconds the device will be restarted, which is signalled with the red LED indicator colour. + +Use reset procedure only if the primary controller is missing or inoperable. + + FGS-213 + 1) Switch off the mains voltage (disable the fuse). +2) Make sure the Switch 2 is within the direct range of your Z-Wave controller. +3) Connect the device in accordance with one of the diagrams included in the manual. +4) After verifying correctness of the connection switch on the mains voltage. +5) Identify the S1 switch or the B-button (located on the device’s housing). +6) Set the main controller in (security/non-security) add mode (see the controller’s manual). +7) Quickly, three times press the S1 switch or the B-button. +8) Wait for the adding process to end. +9) Successful adding will be confirmed by the Z-Wave controller’s message. + + The FIBARO Single Switch 2 is powered with the mains voltage so it is always awake. + The remotely operated FIBARO Single Switch 2 is designed to turn electrical devices on and off and to measure their power and energy consumption. The compact size of the device makes it the world's smallest of its type and allows for the product to be installed in wall switch boxes or housings. FIBARO Single Switch 2 can be controlled either via Z-Wave network or with a wall switch through a direct connection. + CEPT (Europe) + 1) Make sure the Switch 2 is within the direct range of your Z-Wave controller. +2) Identify the S1 switch or the B-button (located on the device’s housing). +3) Set the main controller in remove mode (see the controller’s manual). +4) Quickly, three times press the S1 switch or the B-button. +5) Wait for the removing process to end. +6) Successful removing will be confirmed by the Z-Wave controller’s message + + FIBARO Single Switch 2 + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2750/FGS-2x3-EN-T-v1.2.pdf + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1734/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1871/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2730/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2750/xml + + https://products.z-wavealliance.org/products/2750/ + U.S. / Canada / Mexico + FGS-213 + diff --git a/config/fibaro/fgs223.xml b/config/fibaro/fgs223.xml index 7c481020f2..f7e1370712 100644 --- a/config/fibaro/fgs223.xml +++ b/config/fibaro/fgs223.xml @@ -1,4 +1,58 @@ - + + + http://www.openzwave.com/device-database/010F:1000:0203 + images/fibaro/fgs223.png + https://products.z-wavealliance.org/products/2731/ + 1) Make sure the Switch 2 is within the direct range of your Z-Wave controller. +2) Identify the S1 switch or the B-button (located on the device’s housing). +3) Set the main controller in remove mode (see the controller’s manual). +4) Quickly, three times press the S1 switch or the B-button. +5) Wait for the removing process to end. +6) Successful removing will be confirmed by the Z-Wave controller’s message. + + The remotely operated FIBARO Double Switch 2 is designed to turn two electrical devices on and off and to measure their power and energy consumption. The compact size of the device makes it the world's smallest of its type and allows for the product to be installed in wall switch boxes or housings. FIBARO Double Switch 2 can be controlled either via Z-Wave network or with a wall switch through a direct connection. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2753/FGS-2x3-EN-T-v1.2.pdf + 1) Switch off the mains voltage (disable the fuse). +2) Make sure the Switch 2 is within the direct range of your Z-Wave controller. +3) Connect the device in accordance with one of the diagrams included in the manual. +4) After verifying correctness of the connection switch on the mains voltage. +5) Identify the S1 switch or the B-button (located on the device’s housing). +6) Set the main controller in (security/non-security) add mode (see the controller’s manual). +7) Quickly, three times press the S1 switch or the B-button. +8) Wait for the adding process to end. +9) Successful adding will be confirmed by the Z-Wave controller’s message. + + Reset procedure allows to restore the device back to its factory settings, which means all information about the Z-Wave controller and user configuration will be deleted. In order to reset the device: + +1) Switch off the mains voltage (disable the fuse). +2) Remove the Switch 2 from the wall switch box. +3) Switch on the mains voltage. +4) Press and hold the B-button to enter the menu. +5) Wait for the visual LED indicator to glow yellow. +6) Quickly release and click the B-button again. +7) After few seconds the device will be restarted, which is signalled with the red LED indicator colour. + +Use reset procedure only if the primary controller is missing or inoperable. + + FGS-223 + FIBARO Double Switch 2 + CEPT (Europe) + The FIBARO Double Switch 2 is powered with the mains voltage so it is always awake. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1742/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1874/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1875/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2731/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2751/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2753/xml + + https://products.z-wavealliance.org/products/2751/ + FGS-223 + U.S. / Canada / Mexico + https://products.z-wavealliance.org/products/2753/ + FGS-223 + Australia / New Zealand + diff --git a/config/fibaro/fgsd002.xml b/config/fibaro/fgsd002.xml index 8bb1744f73..ca89d2d100 100644 --- a/config/fibaro/fgsd002.xml +++ b/config/fibaro/fgsd002.xml @@ -1,45 +1,42 @@ - + http://www.openzwave.com/device-database/010F:1002:0C02 images/fibaro/fgsd002.png https://products.z-wavealliance.org/products/1273/ - Fibaro Smoke Sensor inclusion: -1) Install the battery. Visual indicator will signal the Z-Wave network inclusion status -(green - device included, red - device not included) + 1) Install the battery. Visual indicator will signal the Z-Wave network adding status (green - device added, red - device not added). 2) Make sure the device is located within direct range of the Z-Wave controller. -3) Set the main controller into the learning mode -(see main controllers operating manual). -4) Quickly, triple click the B-button, located on Fibaro Smoke Sensors enclosure. -5) Fibaro Smoke Sensor will be detected and included in the Z-Wave network. +3) Set the main controller in add mode (see main controller’s operating manual). +4) Quickly, triple click the B-button, located on FIBARO Smoke Sensor enclosure. +5) FIBARO Smoke Sensor will be detected and added to the Z-Wave network. + Please use this procedure only in the event that the system primary controller is missing or otherwise inoperable. -Fibaro Smoke Sensor reset procedure: -1) Make sure the device has the battery installed. +FIBARO Smoke Sensor reset procedure: +1) Make sure the device is powered. 2) Press and hold the B-button for 3 seconds. Visual indicator will glow white. 3) You will hear a short signal. 4) Release the B-button. -5) Wait until the visual indicator glows yellow, signaling entering the 4th menu level. -6) Press the B-button briefly to confirm menu level choice. At the same time you will hear a short beep, the same sound as during the power connection. -Successful reset will be confirmed with the visual indicator changing colour to red and -fading. At the same time, short beep will sound, same as at the power connection. + FGSD-002 - The FIBARO Smoke Sensor is a universal, ultra-light, perfectly designed, optical Z-Wave smoke detector. Fire alarm is signaled by sound, visual indicator blinking and alarm reports sent to the other devices within Z-wave network. The optical sensor detects smoke at an early stage of fire, often before flames appear and temperature starts to rise significantly. Moreover, the device has a built-in temperature sensor, which is adjustable to allow detection of fire by exceeding given temperature threshold. The FIBARO Smoke Sensor is a battery powered device designed to be placed on the wall or ceiling. Visual indicator signals fire, operating mode and it is used to check if the device is within the Z-wave network using a built-in Z-Wave range tester. The Smoke Sensor is designed to operate in confined spaces, under normal conditions (lacking of smoke, dust or condensed water vapor). - + The FIBARO Smoke Sensor is a universal, ultra-light, perfectly designed, optical Z-Wave smoke detector. Fire alarm is signalled by sound, visual indicator blinking and alarm reports sent to the other devices within Z-wave network. The optical sensor detects smoke at an early stage of fire, often before flames appear and temperature starts to rise significantly. Moreover, the device has a built-in temperature sensor, which is adjustable to allow detection of fire by exceeding given temperature threshold. The FIBARO Smoke Sensor is a battery powered device designed to be placed on the wall or ceiling. Visual indicator signals fire, operating mode and it is used to check if the device is within the Z-wave network using a built-in Z-Wave range tester. The Smoke Sensor is designed to operate in confined spaces, under normal conditions (lacking of smoke, dust or condensed water vapor). Product video: -https://www.youtube.com/watch?v=50QGfkdUtns - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1273/FGSD-002-EN-A-v1.01 LQ-1.pdf - The Smoke Sensor will wake up at defined time interval and -will ALWAYS try to communicate with the main controller. There is a possibility to wake the device up manually by triple-click the B-button. +https://www.youtube.com/watch?v=50QGfkdUtns + + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2837/FGSD-002-EN-A-v1.1.pdf + The Smoke Sensor will wake up at defined time interval and will ALWAYS try to communicate with the main controller. There is a possibility to wake the device up manually by triple-clicking the B-button. FIBARO Smoke Sensor CEPT (Europe) - 1) Make sure there is a battery installed -2) Set the main controller into the learning mode (see main controllers operating -manual) -3) Quickly, triple click the B-button, located on Fibaro Smoke Sensors enclosure. + 1) Make sure there is a battery installed. +2) Set the main controller in remove mode (see main controller’s operating manual). +3) Quickly, triple click the B-button, located on FIBARO Smoke Sensor enclosure. Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1273/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2837/xml + https://products.z-wavealliance.org/products/2837/ + FGSD-002 + CEPT (Europe) diff --git a/config/fibaro/fgt001.xml b/config/fibaro/fgt001.xml index a906368d30..63f901016b 100644 --- a/config/fibaro/fgt001.xml +++ b/config/fibaro/fgt001.xml @@ -1,4 +1,58 @@ - + + + http://www.openzwave.com/device-database/010F:1000:1301 + images/fibaro/fgt001.png + https://products.z-wavealliance.org/products/3194/ + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3194/FGT-001-EN-T-v1.0.pdf + The Heat Controller + Please use this procedure only when the network primary controller is missing or otherwise inoperable. +Reset procedure allows to restore the device back to its factory settings, which means all information about the network and user configuration will be deleted. +To perform factory reset: +1. Use the included key to press and hold the button. +2. Release the button when you see yellow LED colour. +3. Click the button to confirm the selection. +4. After finishing resetting the device will be put in Standby Mode. Click the button to activate it again. + + FIBARO Heat Controller is a remotely controlled thermostatic head to control temperature in the room. It measures the temperature and automatically adjust the heat level. It can be mounted without tools on three types of thermostatic radiator valves. It is also possible to create schedules via app to easily manage temperature throughout the week. +Main features: +• to be installed on three types of valves: M30 x 1.5, Danfoss RTD-N and Danfoss RA-N, +• compatible with any Z-Wave or Z-Wave Plus Controller, +• supports Z-Wave network Security Modes: S0 with AES-128 encryption and S2 with PRNG-based encryption, +• built-in battery recharged through standard micro-USB port, +• easy installation - no tools required, +• can use dedicated temperature sensor, +• supports heating schedules, +• automatic calibration, +• anti-freeze function, +• decalc function, +• unconstrained rotation spherical knob to set desired temperature. + + To add the device to the Z-Wave network: +1. Make sure the device is within the direct range of your Z-Wave controller. +2. Set the main controller in (security/non-security) add mode. +3. Use the included key to quickly triple click the button on the thermostatic head. +4. The LED ring will start blinking white. +5. If you are adding in S2 authenticated mode, type in the device pin code (underlined part of the public key on the label). +6. Wait for the adding process to end. +7. Successful adding will be confirmed by the Z-Wave controller. + + FIBARO Heat Controller is a FLiRS device. The FLiRS device alternates between sleep mode and a partially awake mode in which it is listening beam signal. When device receives this beam, it immediately fully wakes up and then communicates with the controller or other Z-Wave device. + CEPT (Europe) + FGT-001 + To remove the device from the Z-Wave network: +1. Make sure the device is within the direct range of your Z-Wave controller. +2. Set the main controller into remove mode. +3. Use the included key to quickly triple click the button on the thermostatic head. +4. The LED ring will start blinking white. +5. Wait for the removing process to end. +6. Successful removing will be confirmed by the Z-Wave controller. + + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2586/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2971/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3194/xml + + + + FGWDEU-111 Walli Dimmer + FIBARO Walli Dimmer is a smart wall dimmer designed to control light source via Z-Wave network. It measures active power and energy consumed by the controlled load. + http://www.openzwave.com/device-database/010f:1000:1C01 + https://www.fibaro.com/en/products/smart-switches-and-outlets-walli-dimmer/ + https://manuals.fibaro.com/walli-dimmer/ + images/fibaro/fgwd111.png + https://manuals.fibaro.com + FIBARO Walli Dimmer is powered using DC power supply unit so it is always awake. + To add the device to the Z-Wave network manually: +1. Power the device. +2. Set the main controller in add mode(see the controller’s manual). +3. Quickly, three times click one of the buttons. +4. LED will start blinking yellow, wait for the adding process to end. +5. Adding result will be confirmed by the Z-Wave controller’s message and the LED frame: +• Green – successful (non-secure, S0, S2 non-authenticated), +• Magenta – successful (Security S2 Authenticated), +• Red – not successful. + To remove the device from the Z-Wave network: +1. Power the device. +2. Set the main controller into remove mode (see the controller’s manual). +3. Quickly, three times click one of the buttons. +4. LED will start blinking yellow, wait for the removing process to end. +5. Successful removing will be confirmed by the Z-Wave controller’s message and red LED colour. + Reset procedure allows to restore the device back to its factory settings, which means all information about the Z-Wave controller and user configuration will be deleted. Resetting to factory defaults does not reset energy consumption memory. +1. Quickly, three times click, then press and hold one of the buttons to enter the menu. +2. Release button when the device glows yellow. +3. Quickly click the button to confirm. +4. After few seconds the device will be restarted, which is signalled with red LED colour. + https://products.z-wavealliance.org/products/3392 + FGWDEU-111 + CEPT (Europe) + + Initial Creation of config file - https://products.z-wavealliance.org/Products/3392/XML + Change definition of params 30-34 to fix https://github.com/domoticz/domoticz/issues/3557 + + + + + + + + This parameter determines how the device will react in the event of power supply failure (e.g. power outage). The parameter is not relevant for outputs set to pulse mode (parameter 150/151 set to 2). + 0 - remains switched off after restoring power + 1 - restores remembered state after restoring power + + + + + This function allows to turn off the controlled device in case of exceeding the defined power. Controlled device can be turned back on via the button or sending a control frame. + 0 - function disabled + 10-5000 - (1.0-500.0W, step 0.1W) – power threshold + + + + + This parameter determines maximum active power. Exceeding it results in the LED frame flashing violet. Function is active only when parameter 11 is set to 8 or 9. + 100-5000 - (10.0-500.0W, step 0.1W) – power threshold + + + + + This parameter defines the LED colour when thedevice is ON. When set to 8 or 9, LED frame colour will change depending on he measured power and parameter 10. Other colours are set permanently and do not depend on power consumption. + + + + + + + + + + + + + + + This parameter defines the LED colour when the device is OFF. + + + + + + + + + + + + + This parameter allows to adjust the LED frame brightness. + 0 - LED disabled + 1-100 - (1-100% brightness) + 101 - brightness directly proportional to measured power + 102 - brightness inversely proportional asured powerto me + + + + + This parameter allows reversing the operation of the buttons. + + + + + + + This parameter determines to which alarm frames and how the device should react. The parameters consist of 4 bytes, three most significant bytes are set according to the official Z-Wave protocol specification. +1B: [MSB] Notification Type, 2B: Notification Status, 3B: Event/State Parameters, 4B: [LSB] action +0xX0: no action on output, 0xX1: turn ON, 0xX2: turn OFF, 0xX3: turn ON/OFF continuously, 0x0X: no action on LED frame, 0x1X: LED frame blinks red, 0x2X: LED frame blinks green, 0x4X: LED frame blinks blue, 0x8X: disable LED frame, 0xFX: LED frame LAPD signal (red-white-blue) + + + + This parameter determines to which alarm frames and how the device should react. The parameters consist of 4 bytes, three most significant bytes are set according to the official Z-Wave protocol specification. +1B: [MSB] Notification Type, 2B: Notification Status, 3B: Event/State Parameters, 4B: [LSB] action +0xX0: no action on output, 0xX1: turn ON, 0xX2: turn OFF, 0xX3: turn ON/OFF continuously, 0x0X: no action on LED frame, 0x1X: LED frame blinks red, 0x2X: LED frame blinks green, 0x4X: LED frame blinks blue, 0x8X: disable LED frame, 0xFX: LED frame LAPD signal (red-white-blue) + + + + This parameter determines to which alarm frames and how the device should react. The parameters consist of 4 bytes, three most significant bytes are set according to the official Z-Wave protocol specification. +1B: [MSB] Notification Type, 2B: Notification Status, 3B: Event/State Parameters, 4B: [LSB] action +0xX0: no action on output, 0xX1: turn ON, 0xX2: turn OFF, 0xX3: turn ON/OFF continuously, 0x0X: no action on LED frame, 0x1X: LED frame blinks red, 0x2X: LED frame blinks green, 0x4X: LED frame blinks blue, 0x8X: disable LED frame, 0xFX: LED frame LAPD signal (red-white-blue) + + + + This parameter determines to which alarm frames and how the device should react. The parameters consist of 4 bytes, three most significant bytes are set according to the official Z-Wave protocol specification. +1B: [MSB] Notification Type, 2B: Notification Status, 3B: Event/State Parameters, 4B: [LSB] action +0xX0: no action on output, 0xX1: turn ON, 0xX2: turn OFF, 0xX3: turn ON/OFF continuously, 0x0X: no action on LED frame, 0x1X: LED frame blinks red, 0x2X: LED frame blinks green, 0x4X: LED frame blinks blue, 0x8X: disable LED frame, 0xFX: LED frame LAPD signal (red-white-blue) + + + + This parameter determines to which alarm frames and how the device should react. The parameters consist of 4 bytes, three most significant bytes are set according to the official Z-Wave protocol specification. +1B: [MSB] Notification Type, 2B: Notification Status, 3B: Event/State Parameters, 4B: [LSB] action +0xX0: no action on output, 0xX1: turn ON, 0xX2: turn OFF, 0xX3: turn ON/OFF continuously, 0x0X: no action on LED frame, 0x1X: LED frame blinks red, 0x2X: LED frame blinks green, 0x4X: LED frame blinks blue, 0x8X: disable LED frame, 0xFX: LED frame LAPD signal (red-white-blue) + + + + + This parameter defines duration of alarm sequence. When time set in this parameter elapses, alarm is cancelled, LED frame and relay restore normal operation, but do not recover state from before the alarm. + 0 - Infinite + 1-32400 - (1s-9h, 1s step) – Duration + + + + + This parameter determines which actions result in sending scene IDs assigned to them. Values can be combined (e.g. 1+2=3 means that scenes for single and double click are sent). Enabling scenes for triple click disables entering the device in learn mode by triple clicking. + 1 - Key pressed 1 time + 2 - Key pressed 2 time + 4 - Key pressed 3 time + 8 - Key hold down and key released + + + + + This parameter determines which actions result in sending scene IDs assigned to them. Values can be combined (e.g. 1+2=3 means that scenes for single and double click are sent). Enabling scenes for triple click disables entering the device in learn mode by triple clicking. + 1 - Key pressed 1 time + 2 - Key pressed 2 time + 4 - Key pressed 3 time + 8 - Key hold down and key released + + + + + This parameter determines whether the power measurements should include power consumed by the device itself. + + + + + + + This parameter defines minimal change (from the last reported) in measured power that results in sending new report. For loads under 50W the parameter is irrelevant, report are sent every 5W change. + 0 - Reporting on change disabled + 1-500 - (1-500%, 1% step) – Minimal change + + + + + This parameter defines reporting interval for measured power. Periodic reports are independent from changes in value (parameter 61). + 0 - periodic reports disabled + 30-32400 - (30s-9h, 1s step) – time interval + + + + + This parameter defines minimal change (from the last reported) in measured energy that results in sending new report. + 0 - reporting on change disabled + 1-500 - (0.01-5kWh, 0.01kWh step) – minimal change + + + + + This parameter defines reporting interval for measured energy. Periodic reports are independent from changes in value (parameter 65). + 0 - periodic reports disabled + 30-32400 - (30s-9h, 1s step) – time interval + + + + + This parameter is set automatically during the calibration process, but can be changed manually after the calibration. + 1-98 - (1-98%, 1% step) – level of brightness + + + + + This parameter is set automatically during the calibration process, but can be changed manually after the calibration. + 2-99 - (2-99%, 1% step) – level of brightness + + + + + The virtual value set as a percentage level between parameters MIN (1%) and MAX. (99%). The device will set to this value after the first switch on. It is required for warming up and switching dimmable compact fluorescent lamps and certain types of light sources. + 1-99 - (1-98%, 1% step) – level of brightness + + + + + This parameter determines the time required for switching compact fluorescent lamps and certain types of light sources. Setting this parameter to 0 will disable the incandescence functionality. + 0-255 - (0-25.5s, 0.1s step) – incandescence time + + + + + This parameter defines the percentage value of dimming step during the automatic control. + 0-99 - (1-99%, 1% step) – dimming step + + + + + This parameter defines the time of performing a single dimming step set in parameter 154 during the automatic control. + 0-255 - This parameter defines the time of performing a single dimming step set in parameter 154 during the automatic control. + + + + + This parameter defines the percentage value of the dimming step during the manual control. + 1-99 - (1-99%, 1% step) – dimming step + + + + + This parameter defines the time of performing a single dimming step set in parameter 156 during the manual control. + 0-255 - (0-2.55s, 10ms step) + + + + + This parameter allows to automatically switch off the device after a specified time from switching the light source on. It may be useful when the device is installed in the stairway. + 0 - auto-off disabled + 1-32767 - (1s-9.1h, 1s step) – auto-off time + + + + + Changing value of this parameter will force the calibration process. During the calibration parameter is set to 1 or 2 and switched to 0 upon completion. + + + + + + + + This parameter determines operating mode of the device (automatic/manual settings). + + + + + + + This parameter defines percentage power variation (compared to power consumption measured during the calibration) to be interpreted as load error/burnt out bulb. + 0 - function disabled + 1-99 - (1-99%, 1% step) – power variation + + + + + This parameter defines detection delay for the burnt out bulb (parameter 161) and overload (parameter 2). + 0 - detection of a burnt out bulb disabled + 1-255 - (1-255s, 1s step) – time delay + + + + + This parameter defines value sent with Switch OFF command to devices associated in 2nd and 3rd association group. + 0-99 - value sent + 254 - send value equal to the current level + 255 - value sent + + + + + This parameter defines value sent with Switch ON command to devices associated in 2nd and 3rd association group. + 0-99 - value sent + 254 - send value equal to the current level + 255 - value sent + + + + + This parameter defines brightness level set after double-clicking any of the buttons. The same value is also sent to devices associated with 2nd and 3rd association group. + 0-99 - (0-99%, 1% step) – set level + + + + + This parameter allows to set the desired load control mode. Auto-calibration sets value of this parameter to 2 (control mode recognized during auto-calibration), but the installer may force control mode using this parameter. After changing parameter value, turn the load OFF and ON to change control mode. + + + + + + + + This parameter allows to read load control mode that was set during auto-calibration. + + + + + + + This mode is necessary while connecting non-dimmable light sources. Setting this parameter to 1 automatically ignores brightening/dimming time settings. Forced auto-calibration will set this parameter’s value to 2. + + + + + + + + This parameter allows to read if the load detected during calibration procedure is dimmable. + + + + + + + This parameter allows to set time required to warm up the filament of halogen bulb. + + + + + + + + This parameter determines the trigger of auto-calibration procedure, e.g. power on, load error, etc. + + + + + + + + + Error occurrences related to surge or overcurrent results in turning off the output to prevent possible malfunction. By default the device performs three attempts to turn on the load (useful in case of temporary, short failures of the power supply). + + + + + + + Correction reduces spontaneous flickering of some capacitive loads (e.g. dimmable LEDs) at certain brightness levels in 2-wire installation. + In countries using ripple-control, correction may cause changes in brightness. In this case it is necessary to disable correction or adjust the time of correction for flickering loads. + 0 - automatic correction disabled + 1-254 - (1-254s, 1s step) – duration of correction + 255 - automatic correction always enabled + + + + + This parameter defines how to calculate active power. It is useful in a case of 2-wire connection with light sources other than resistive. + + + + + + + + This parameter determines the approximate value of the power that will be reported by the device at its maximum brightness level. + 0-500 - (0-500W, 1W step) – power consumed by the load at the maximum brightness level. + + + + + + + + + + + + + diff --git a/config/fibaro/fgwds221.xml b/config/fibaro/fgwds221.xml new file mode 100644 index 0000000000..0d3e876a31 --- /dev/null +++ b/config/fibaro/fgwds221.xml @@ -0,0 +1,346 @@ + + + + FGWDSEU-221 Walli Double Switch + FIBARO Walli Double Switch is a smart wall switch designed to control one or two light sources via Z-Wave network. It measures active power and energy consumed by the controlled load. + http://www.openzwave.com/device-database/010f:1000:1B01 + https://www.fibaro.com/en/products/smart-switches-and-outlets-walli-switch/ + https://manuals.fibaro.com/walli-switch/ + + https://products.z-wavealliance.org/ProductManual/File?folder=&filename=Manuals/3395/FGWDSEU-221-T-EN-0.19.pdf + FIBARO Walli Double Switch is powered using DC power supply unit so it is always awake. + To add the device to the Z-Wave network manually: +1. Power the device. +2. Set the main controller in add mode(see the controller’s manual). +3. Quickly, three times click one of the buttons. +4. LED will start blinking yellow, wait for the adding process to end. +5. Adding result will be confirmed by the Z-Wave controller’s message and the LED frame: +• Green – successful (non-secure, S0, S2 non-authenticated), +• Magenta – successful (Security S2 Authenticated), +• Red – not successful. + To remove the device from the Z-Wave network: +1. Power the device. +2. Set the main controller into remove mode (see the controller’s manual). +3. Quickly, three times click one of the buttons. +4. LED will start blinking yellow, wait for the removing process to end. +5. Successful removing will be confirmed by the Z-Wave controller’s message and red LED colour. + Reset procedure allows to restore the device back to its factory settings, which means all information about the Z-Wave controller and user configuration will be deleted. Resetting to factory defaults does not reset energy consumption memory. +1. Quickly, three times click, then press and hold one of the buttons to enter the menu. +2. Release button when the device glows yellow. +3. Quickly click the button to confirm. +4. After few seconds the device will be restarted, which is signalled with red LED colour. + https://products.z-wavealliance.org/products/3395 + FGWDSEU-221 + CEPT (Europe) + + Initial Creation of config file - https://products.z-wavealliance.org/Products/3395/XML + Change definition of params 30-34 to fix https://github.com/domoticz/domoticz/issues/3557 + + + + + + + + This parameter determines how the device will react in the event of power supply failure (e.g. power outage). The parameter is not relevant for outputs set to pulse mode (parameter 150/151 set to 2). + 0 - remains switched off after restoring power + 1 - restores remembered state after restoring power + + + + + This function allows to turn off the controlled device in case of exceeding the defined power. Controlled device can be turned back on via button or sending a control frame. + 0 - Function disabled + 10-36200 - (1.0-3620.0W, step 0.1W) – Power threshold + + + + + This function allows to turn off the controlled device in case of exceeding the defined power. Controlled device can be turned back on via button or sending a control frame. + 0 - Function disabled + 10-36200 - (1.0-3620.0W, step 0.1W) – Power threshold + + + + + This parameter determines maximum active power. Exceeding it results in the LED frame flashing violet. Function is active only when parameter 11 is set to 8 or 9. + (50.0-3000.0W, step 0.1W) – power threshold + + + + + This parameter defines the LED colour when thedevice is ON. When set to 8 or 9, LED frame colour will change depending on he measured power and parameter 10. Other colours are set permanently and do not depend on power consumption. + + + + + + + + + + + + + + + This parameter defines the LED colour when thedevice is ON. When set to 8 or 9, LED frame colour will change depending on he measured power and parameter 10. Other colours are set permanently and do not depend on power consumption. + + + + + + + + + + + + + This parameter allows to adjust the LED frame brightness. + 0 - LED disabled + 1-100 - (1-100% brightness) + 101 - brightness directly proportional to measured power + 102 - brightness inversely proportional asured powerto me + + + + + This parameter defines how device buttons should control the channels. + + + + + + + + This parameter allows reversing the operation of the buttons. + + + + + + This parameter allows reversing the operation of Q1 and Q2 without changing the wiring (e.g. in case of invalid connection). Changing orientation turns both outputs off. + + + + + + This parameter determines to which alarm frames and how the device should react. The parameters consist of 4 bytes, three most significant bytes are set according to the official Z-Wave protocol specification. +1B: [MSB] Notification Type, 2B: Notification Status, 3B: Event/State Parameters, 4B: [LSB] action +0xX0: no action on output, 0xX1: turn ON, 0xX2: turn OFF, 0xX3: turn ON/OFF continuously, 0x0X: no action on LED frame, 0x1X: LED frame blinks red, 0x2X: LED frame blinks green, 0x4X: LED frame blinks blue, 0x8X: disable LED frame, 0xFX: LED frame LAPD signal (red-white-blue) + + + + This parameter determines to which alarm frames and how the device should react. The parameters consist of 4 bytes, three most significant bytes are set according to the official Z-Wave protocol specification. +1B: [MSB] Notification Type, 2B: Notification Status, 3B: Event/State Parameters, 4B: [LSB] action +0xX0: no action on output, 0xX1: turn ON, 0xX2: turn OFF, 0xX3: turn ON/OFF continuously, 0x0X: no action on LED frame, 0x1X: LED frame blinks red, 0x2X: LED frame blinks green, 0x4X: LED frame blinks blue, 0x8X: disable LED frame, 0xFX: LED frame LAPD signal (red-white-blue) + + + + This parameter determines to which alarm frames and how the device should react. The parameters consist of 4 bytes, three most significant bytes are set according to the official Z-Wave protocol specification. +1B: [MSB] Notification Type, 2B: Notification Status, 3B: Event/State Parameters, 4B: [LSB] action +0xX0: no action on output, 0xX1: turn ON, 0xX2: turn OFF, 0xX3: turn ON/OFF continuously, 0x0X: no action on LED frame, 0x1X: LED frame blinks red, 0x2X: LED frame blinks green, 0x4X: LED frame blinks blue, 0x8X: disable LED frame, 0xFX: LED frame LAPD signal (red-white-blue) + + + + This parameter determines to which alarm frames and how the device should react. The parameters consist of 4 bytes, three most significant bytes are set according to the official Z-Wave protocol specification. +1B: [MSB] Notification Type, 2B: Notification Status, 3B: Event/State Parameters, 4B: [LSB] action +0xX0: no action on output, 0xX1: turn ON, 0xX2: turn OFF, 0xX3: turn ON/OFF continuously, 0x0X: no action on LED frame, 0x1X: LED frame blinks red, 0x2X: LED frame blinks green, 0x4X: LED frame blinks blue, 0x8X: disable LED frame, 0xFX: LED frame LAPD signal (red-white-blue) + + + + This parameter determines to which alarm frames and how the device should react. The parameters consist of 4 bytes, three most significant bytes are set according to the official Z-Wave protocol specification. +1B: [MSB] Notification Type, 2B: Notification Status, 3B: Event/State Parameters, 4B: [LSB] action +0xX0: no action on output, 0xX1: turn ON, 0xX2: turn OFF, 0xX3: turn ON/OFF continuously, 0x0X: no action on LED frame, 0x1X: LED frame blinks red, 0x2X: LED frame blinks green, 0x4X: LED frame blinks blue, 0x8X: disable LED frame, 0xFX: LED frame LAPD signal (red-white-blue) + + + + + This parameter defines duration of alarm sequence. When time set in this parameter elapses, alarm is cancelled, LED frame and relay restore normal operation, but do not recover state from before the alarm. + 0 - Infinite + 1-32400 - (1s-9h, 1s step) – Duration + + + + + This parameter determines which actions result in sending scene IDs assigned to them. Values can be combined (e.g. 1+2=3 means that scenes for single and double click are sent). Enabling scenes for triple click disables entering the device in learn mode by triple clicking. + 1 - Key pressed 1 time + 2 - Key pressed 2 time + 4 - Key pressed 3 time + 8 - Key hold down and key released + + + + + This parameter determines which actions result in sending scene IDs assigned to them. Values can be combined (e.g. 1+2=3 means that scenes for single and double click are sent). Enabling scenes for triple click disables entering the device in learn mode by triple clicking. + 1 - Key pressed 1 time + 2 - Key pressed 2 time + 4 - Key pressed 3 time + 8 - Key hold down and key released + + + + + This parameter determines whether the power measurements should include power consumed by the device itself. + + + + + + + This parameter defines minimal change (from the last reported) in measured power that results in sending new report. For loads under 50W the parameter is irrelevant, report are sent every 5W change. + 0 - Reporting on change disabled + 1-500 - (1-500%, 1% step) – Minimal change + + + + + This parameter defines reporting interval for measured power. Periodic reports are independent from changes in value (parameter 61). + 0 - periodic reports disabled + 30-32400 - (30s-9h, 1s step) – time interval + + + + + This parameter defines minimal change (from the last reported) in measured power that results in sending new report. For loads under 50W the parameter is irrelevant, report are sent every 5W change. + 0 - Reporting on change disabled + 1-500 - (1-500%, 1% step) – Minimal change + + + + + This parameter defines reporting interval for measured power. Periodic reports are independent from changes in value (parameter 63). + 0 - periodic reports disabled + 30-32400 - (30s-9h, 1s step) – time interval + + + + + This parameter defines minimal change (from the last reported) in measured energy that results in sending new report. + 0 - reporting on change disabled + 1-500 - (0.01-5kWh, 0.01kWh step) – minimal change + + + + + This parameter defines reporting interval for measured energy. Periodic reports are independent from changes in value (parameter 66). + 0 - periodic reports disabled + 30-32400 - (30s-9h, 1s step) – time interval + + + + + This parameter defines minimal change (from the last reported) in measured energy that results in sending new report. + 0 - reporting on change disabled + 1-500 - (0.01-5kWh, 0.01kWh step) – minimal change + + + + + This parameter defines reporting interval for measured energy. Periodic reports are independent from changes in value (parameter 67). + 0 - periodic reports disabled + 30-32400 - (30s-9h, 1s step) – time interval + + + + + This parameter allows to choose operating for the 1st channel. + + + + + + + + This parameter allows to choose operating for the 2nd channel. + + + + + + + + This parameter determines how the device in timed mode reacts to pushing the button for 1st channel. The parameter is relevant only for button toggles modes (parameter 20 set to 1 or 3). + + + + + + + + This parameter determines how the device in timed mode reacts to pushing the button for 2nd channel. The parameter is relevant only for button toggles modes (parameter 20 set to 1 or 3). + + + + + + + + This parameter allows to set time parameter used in timed modes for 1st channel (parameter 150). Delay time for switching off or duration of the pulse. + 0 - 0.1 second + 1-32000 - 1-32000s, 1s step – time parameter + + + + + This parameter allows to set time parameter used in timed modes for 2nd channel (parameter 151). Delay time for switching off or duration of the pulse. + 0 - 0.1 second + 1-32000 - 1-32000s, 1s step – time parameter + + + + + This parameter defines value sent with Switch ON command to devices associated in 2nd and 3rd association group for manual changes of Endpoint 1 state. + 0-99 - 2nd association group + 255 - 3rd association group + + + + + This parameter defines value sent with Switch OFF command to devices associated in 2nd and 3rd association group for manual changes of Endpoint 1 state. + 0-99 - 2nd association group + 255 - 3rd association group + + + + + This parameter defines value sent with Double Click command to devices associated in 2nd and 3rd association group for manual changes of Endpoint 1 state. + 0-99 - 2nd association group + 255 - 3rd association group + + + + + This parameter defines value sent with Switch ON command to devices associated in 4th and 5th association group for manual changes of Endpoint 2 state. + 0-99 - 4th association group + 255 - 5th association group + + + + + This parameter defines value sent with Switch OFF command to devices associated in 4th and 5th association group for manual changes of Endpoint 2 state. + 0-99 - 4th association group + 255 - 5th association group + + + + + This parameter defines value sent with Double Click command to devices associated in 4th and 5th association group for manual changes of Endpoint 2 state. + 0-99 - 4th association group + 255 - 5th association group + + + + + + + + + + + + + + + diff --git a/config/fibaro/fgwoe.xml b/config/fibaro/fgwoe.xml new file mode 100644 index 0000000000..cd0764abf8 --- /dev/null +++ b/config/fibaro/fgwoe.xml @@ -0,0 +1,491 @@ + + + + FIBARO Walli Outlet + http://www.openzwave.com/device-database/010F:1000:1f01 + images/fibaro/fgwoe.png + https://manuals.fibaro.com/content/manuals/en/FGWOEF-011/FGWOEF-011-T-EN-v1.0.pdf + https://products.z-wavealliance.org/products/3220 + CEPT (Europe) + FGWOE/F-11 + FIBARO Walli Outlet is a smart electrical outlet designed to control electrical devices via Z-Wave network. +It measures active power and energy consumed by the controlled load. +You can install it with provided cover plate and socket cover or other compatible. + +Main features of FIBARO Walli Outlet: +- Can turn ON/OFF plugged device remotely. +- Available in two versions for plug types: + o Type E, + o Type F. +- Can be used with provided cover plate or one of the following: + o GIRA - System 55 (Standard 55, E2, Event, Event Clear), + o Legrand - Celiane + o Schneider - Odace. +- Active power and energy consumption metering. +- Displays current load using multicolour LED frame (with FIBARO cover plate). +- Supports Z-Wave network Security Modes: S0 with AES-128 encryption and S2 Authenticated with PRNG-based encryption. +- Works as Z-Wave signal repeater (all non-battery operated devices within the network will act as repeaters to increase reliability of the network). +- May be used with all devices certified with the Z-Wave Plus certificate and should be compatible with such devices produced by other manufacturers. + + FIBARO Walli Outlet is powered using DC power supply unit so it is always awake. + To add the device to the Z-Wave network manually: +1. Power the device. +2. Set the main controller in (Security/non-Security Mode) add mode (see the controller's manual). +3. Quickly, three times click one of the buttons. +4. If you are adding in Security S2 Authenticated, scan the DSK QR code or input the underlined part of the DSK (on the device label). +5. LED will start blinking yellow, wait for the adding process to end. +6. Adding result will be confirmed by the Z-Wave controller's message and the LED frame: + - Green - successful (non-secure, S0, S2 non-authenticated), + - Magenta - successful (Security S2 Authenticated), + - Red - not successful. + + To remove the device from the Z-Wave network: +1. Power the device. +2. Set the main controller into remove mode (see the controller's manual). +3. Quickly, three times click the button. +4. LED will start blinking yellow, wait for the removing process to end. +5. Successful removing will be confirmed by the Z-Wave controller's message and red LED colour. + + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3220/xml + + + + + + This parameter determines how the device will react in the event of power supply failure (e.g. power outage). + + + + + This function allows to turn off the controlled device in case of exceeding the defined power. Controlled device can be turned back on via button or sending a control frame. +0: function disabled, 10-36800: (1.0-3680.0W, step 0.1W) power threshold + + + + This parameter determines maximum active power. Exceeding it results in the LED frame flashing violet. Function is active only when parameter 11 is set to 8 or 9. +500-36800 (50.0-3680.0W, step 0.1W) - power threshold + + + This parameter defines the LED colour when the device is ON. + +When set to 8 or 9, LED frame colour will change depending on the measured power and parameter 10. Other colours are set permanently and do not depend on power consumption. + + + + + + + + + + + + + This parameter defines the LED colour when the device is OFF. + + + + + + + + + + + This parameter allows to adjust the LED frame brightness. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This parameter determines to which alarm frames and how the device should react. The parameters consist of 4 bytes, three most significant bytes are set according to the official Z-Wave protocol specification. +1B: [MSB] Notification Type, 2B: Notification Status, 3B: Event/State Parameters, 4B: [LSB] action +0xX0: no action on output, 0xX1: turn ON, 0xX2: turn OFF, 0xX3: turn ON/OFF continuously, 0x0X: no action on LED frame, 0x1X: LED frame blinks red, 0x2X: LED frame blinks green, 0x4X: LED frame blinks blue, 0x8X: disable LED frame, 0xFX: LED frame LAPD signal (red-white-blue) + + + + This parameter determines to which alarm frames and how the device should react. The parameters consist of 4 bytes, three most significant bytes are set according to the official Z-Wave protocol specification. +1B: [MSB] Notification Type, 2B: Notification Status, 3B: Event/State Parameters, 4B: [LSB] action +0xX0: no action on output, 0xX1: turn ON, 0xX2: turn OFF, 0xX3: turn ON/OFF continuously, 0x0X: no action on LED frame, 0x1X: LED frame blinks red, 0x2X: LED frame blinks green, 0x4X: LED frame blinks blue, 0x8X: disable LED frame, 0xFX: LED frame LAPD signal (red-white-blue) + + + + This parameter determines to which alarm frames and how the device should react. The parameters consist of 4 bytes, three most significant bytes are set according to the official Z-Wave protocol specification. +1B: [MSB] Notification Type, 2B: Notification Status, 3B: Event/State Parameters, 4B: [LSB] action +0xX0: no action on output, 0xX1: turn ON, 0xX2: turn OFF, 0xX3: turn ON/OFF continuously, 0x0X: no action on LED frame, 0x1X: LED frame blinks red, 0x2X: LED frame blinks green, 0x4X: LED frame blinks blue, 0x8X: disable LED frame, 0xFX: LED frame LAPD signal (red-white-blue) + + + + This parameter determines to which alarm frames and how the device should react. The parameters consist of 4 bytes, three most significant bytes are set according to the official Z-Wave protocol specification. +1B: [MSB] Notification Type, 2B: Notification Status, 3B: Event/State Parameters, 4B: [LSB] action +0xX0: no action on output, 0xX1: turn ON, 0xX2: turn OFF, 0xX3: turn ON/OFF continuously, 0x0X: no action on LED frame, 0x1X: LED frame blinks red, 0x2X: LED frame blinks green, 0x4X: LED frame blinks blue, 0x8X: disable LED frame, 0xFX: LED frame LAPD signal (red-white-blue) + + + + This parameter determines to which alarm frames and how the device should react. The parameters consist of 4 bytes, three most significant bytes are set according to the official Z-Wave protocol specification. +1B: [MSB] Notification Type, 2B: Notification Status, 3B: Event/State Parameters, 4B: [LSB] action +0xX0: no action on output, 0xX1: turn ON, 0xX2: turn OFF, 0xX3: turn ON/OFF continuously, 0x0X: no action on LED frame, 0x1X: LED frame blinks red, 0x2X: LED frame blinks green, 0x4X: LED frame blinks blue, 0x8X: disable LED frame, 0xFX: LED frame LAPD signal (red-white-blue) + + + + This parameter defines duration of alarm sequence. When time set in this parameter elapses, alarm is cancelled, LED frame and relay restore normal operation, but do not recover state from before the alarm. + 0: Infinite, 1-32400: (1s-9h, 1s step) - Duration + + + + This parameter determines which actions will result in sending control frames to devices associated in 2nd group. + + + + + + This parameter determines upper power threshold for 2nd association group (paramter 45). Exceeding it will result in sending value set in parameter 47. Cannot be lower than DOWN threshold (parameter 48). +100-36800: (10-3680W, 0.1W step) - power threshold + + + + This parameter defines value sent to devices in 2nd association group when power exceeds UP threshold set in parameter 46 (using Basic Command Class). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This parameter determines lower power threshold for 2nd association group (parameter 45). Exceeding it will result in sending value set in parameter 49. +0-36700: (0-3670W, 0.1W step) - power threshold + + + + This parameter defines value sent to devices in 2nd association group when power exceeds UP threshold set in parameter 46 (using Basic Command Class). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This parameter determines whether the power measurements should include power consumed by the device itself. + + + + + This parameter defines minimal change (from the last reported) in measured power that results in sending new report. For loads under 50W the parameter is irrelevant, reports are sent every 5W change. +0: reporting on change disabled, 1-500: (1-500%, 1% step) minimal change + + + This parameter defines reporting interval for measured power. Periodic reports are independent from changes in value (parameter 61). +0: periodic reports disabled, 30-32400: (30s-9h, 1s step) time interval + + + This parameter defines minimal change (from the last reported) in measured energy that results in sending new report. +0: reporting on change disabled, 1-500: (0.01-5kWh, 0.01kWh step) minimal change + + + This parameter defines reporting interval for measured energy. Periodic reports are independent from changes in value (parameter 65). +0: periodic reports disabled, 30-32400: (30s-9h, 1s step) time interval + + + + + + + + + + diff --git a/config/fibaro/fgwpfzw5.xml b/config/fibaro/fgwpfzw5.xml index bbf8acb7e5..699d0de90d 100644 --- a/config/fibaro/fgwpfzw5.xml +++ b/config/fibaro/fgwpfzw5.xml @@ -1,4 +1,61 @@ - + + + http://www.openzwave.com/device-database/010F:1001:0602 + images/fibaro/fgwpfzw5.png + https://products.z-wavealliance.org/products/1653/ + FGWPE/F-102 + Resetting the device is not the recommended way of removing the device from the +Z-Wave network. Use reset procedure only if the primary controller is missing or +inoperable. Certain device removal can be achieved by the procedure of removing +described in “Adding/ removing the device”on page 6. + +1) Make sure the device is powered. +2) Press and hold the B-button. +3) Wait for the LED ring to glow yellow (4th menu position). +4) Release the B-button. +5) Click the B-button once to confirm selection. +6) After few seconds the device will restart with factory settings, which is signalled with the red ring colour. + + + + + 1) Plug the device into a socket nearby the main Z-Wave controller. +2) The LED ring will glow green signalling being added (removing is not necessary otherwise). +3) Set the main Z-Wave controller into remove mode (see the controller’s manual). +4) Quickly, triple click the B-button located on the casing. +5) Wait for the removing process to end. +6) Successful removing will be confirmed by the Z-Wave controller. + + FIBARO Wall Plug E/F + Wakeup Description +FIBARO Wall Plug is powered with mains voltage so it is always awake. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2818/FGWPEF-102-EN-A-v2.1.pdf + FIBARO Wall Plug is a universal, Z-Wave Plus compatible, remotely controlled outlet adapter. This device may be applied wherever you want to control electrical devices with up to 2500W load. The Wall Plug is equipped with a power and energy metering function. It uses a LED ring to visualize the current load with colour changing illumination and operating mode. This is the smallest and most attractive device of this type available in the world. The Wall Plug may be operated using the B-button located on its casing or via any Z-Wave compatible controller. + +Main features: +• Compatible with any Z-Wave or Z-Wave Plus Controller. +• Supports protected mode (Z-Wave network security mode) with AES-128 encryption. +• Extremely easy installation - simply plug the device into the mains socket. +• Works as a Z-Wave signal repeater. +• Active power and energy consumption metering. +• Current value of the load and operating mode are indicated by the multi-colour LED ring. + + CEPT (Europe) + 1) Plug the device into a socket nearby the main Z-Wave controller. +2) The LED ring will glow red signalling not being added (remove the device otherwise). +3) Set the main Z-Wave controller into adding mode (see the controller’s manual). +4) Quickly, triple click the B-button located on the casing. +5) Wait for the adding process to end. +6) Successful adding will be confirmed by the Z-Wave controller. + + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1653/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2818/xml + + https://products.z-wavealliance.org/products/2818/ + FGWPE/F-102 + CEPT (Europe) + diff --git a/config/fibaro/fgwpg111.xml b/config/fibaro/fgwpg111.xml index 0ce4163aed..82ce297dec 100644 --- a/config/fibaro/fgwpg111.xml +++ b/config/fibaro/fgwpg111.xml @@ -1,4 +1,56 @@ - + + + http://www.openzwave.com/device-database/010F:2000:1701 + images/fibaro/fgwpg111.png + https://products.z-wavealliance.org/products/2854/ + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2899/FGWPG-111-EN-T-v.0.2.pdf + To remove the device from the Z-Wave network: +1. Plug the device into a socket nearby the main Z-Wave controller. +2. The LED frame will glow green signaling being added (removing is not necessary otherwise). +3. Set the main controller into remove mode. +4. Quickly, triple click the button located on the casing. +5. Wait for the removing process to end. +6. Successful removing will be confirmed by the Z-Wave controller’s message. + + FIBARO Wall Plug is powered with mains voltage so it is always awake. + Reset procedure allows to restore the device back to its factory settings, which means all information about the Z-Wave controller and user configuration will be deleted. +1. Make sure the device is powered. +2. Press and hold the button. +3. Wait for the LED frame to glow yellow (3rd menu position). +4. Release the button. +5. Click the button once to confirm selection. +6. After few seconds the device will restart with factory settings, which is signaled with the red frame color. + +Resetting the device is not the recommended way of removing the device from the Z-Wave network. Use the reset procedure only if the primary controller is missing or inoperable. + Wall Plug UK + FIBARO Wall Plug is a remotely controlled plug-in switch with the ability to measure power and energy consumption. It uses a LED frame to visualize the current load and operating mode with color changing illumination. FIBARO Wall Plug makes it possible to control electrical devices in a convenient and maintenance-free way. +Main features of FIBARO Wall Plug: +- Compatible with any Z-Wave or Z-Wave+ Controller. +- Supports Z-Wave network Security Modes: S0 with AES-128 encryption and S2 with PRNG-based encryption. +- Extremely easy installation - simply plug the device into the mains socket. +- Works as a Z-Wave signal repeater. +- Active power and energy consumption metering for plugged device. +- Current value of the load and operating mode are indicated by the multi-color LED frame. + + FGWPB-111 + To add the device to the Z-Wave network: +1. Plug the device into a socket nearby the main Z-Wave controller. +2. The LED frame will glow red signaling not being added (reset or remove the device otherwise). +3. Set the main controller in (security/non-security) add mode. +4. Quickly, triple click the button located on the casing. +5. If you are adding in S2 authenticated mode, type in the device pin code (underlined part of the public key available on the device or in the manual). +6. Wait for the adding process to end. +7. Successful adding will be confirmed by the Z-Wave controller’s message. + + U.S. / Canada / Mexico + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2854/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2899/xml + + https://products.z-wavealliance.org/products/2899/ + FGWPG-111 + CEPT (Europe) + + + + This parameter defines the LED colour when the motor is running. + + + + + + + + + + + + This parameter defines the LED colour when the device motor is not running. + + + + + + + + + + + + + This parameter allows to adjust the LED frame brightness. + 0 - LED disabled + 1-100 - (1-100% brightness) + + + + + + This parameter allows reversing the operation of the buttons. + + 0 - default (1st button UP, 2nd button DOWN) + 1 - reversed (1st button DOWN, 2nd button UP) + + + + + + + + This parameter allows reversing the operation of Q1 and Q2 without changing the wiring (e.g. in case of invalid motor connection). + + 0 - default (Q1 - UP, Q2 - DOWN) + 1 - reversed (Q1 - DOWN, Q2 - UP) + + + + + + + + This parameter determines to which alarm frames and how the device should react. + The parameters consist of 4 bytes, three most significant bytes are set according to the official Z-Wave protocol specification. + + 1B [MSB] - Notification Type + 2B - Notification Status + 3B - Event/State Parameters + 4B [LSB] - action: + 0x00 - no action, + 0xX1 - open, + 0xX2 - close, + 0x0X - no action on LED frame, + 0x1X - LED frame blinks red, + 0x2X - LED frame blinks green, + 0x4X - LED frame blinks blue, + 0x8X - dis- able LED frame, + 0xFX - LED frame LAPD signal (red-white-blue) + + Default value: [0x00, 0x00, 0x00, 0x00] (disabled) + + + + + + This parameter determines to which alarm frames and how the device should react. + The parameters consist of 4 bytes, three most significant bytes are set according to the official Z-Wave protocol specification. + + 1B [MSB] - Notification Type + 2B – Notification Status + 3B – Event/State Parameters + 4B [LSB] – action: + 0x00 - no action, + 0xX1 - open, + 0xX2 - close, + 0x0X - no action on LED frame, + 0x1X - LED frame blinks red, + 0x2X - LED frame blinks green, + 0x4X - LED frame blinks blue, + 0x8X - dis- able LED frame, + 0xFX - LED frame LAPD signal (red-white-blue) + + Default value: [0x05, 0xFF, 0x00, 0x00] (Water Alarm, any notification, no action) + + + + + + This parameter determines to which alarm frames and how the device should react. + The parameters consist of 4 bytes, three most significant bytes are set according to the official Z-Wave protocol specification. + + 1B [MSB] - Notification Type + 2B - Notification Status + 3B - Event/State Parameters + 4B [LSB] - action: + 0x00 - no action, + 0xX1 - open, + 0xX2 - close, + 0x0X - no action on LED frame, + 0x1X - LED frame blinks red, + 0x2X - LED frame blinks green, + 0x4X - LED frame blinks blue, + 0x8X - dis- able LED frame, + 0xFX - LED frame LAPD signal (red-white-blue) + + Default value: [0x01, 0xFF, 0x00, 0x00] (Smoke Alarm, any notification, no action) + + + + + + This parameter determines to which alarm frames and how the device should react. + The parameters consist of 4 bytes, three most significant bytes are set according to the official Z-Wave protocol specification. + + 1B [MSB] - Notification Type + 2B - Notification Status + 3B - Event/State Parameters + 4B [LSB] - action: + 0x00 - no action, + 0xX1 - open, + 0xX2 - close, + 0x0X - no action on LED frame, + 0x1X - LED frame blinks red, + 0x2X - LED frame blinks green, + 0x4X - LED frame blinks blue, + 0x8X - dis- able LED frame, + 0xFX - LED frame LAPD signal (red-white-blue) + + Default value: [0x02, 0xFF, 0x00, 0x00] (CO Alarm, any notification, no action) + + + + + + This parameter determines to which alarm frames and how the device should react. + The parameters consist of 4 bytes, three most significant bytes are set according to the official Z-Wave protocol specification. + + 1B [MSB] - Notification Type + 2B - Notification Status + 3B - Event/State Parameters + 4B [LSB] - action: + 0x00 - no action, + 0xX1 - open, + 0xX2 - close, + 0x0X - no action on LED frame, + 0x1X - LED frame blinks red, + 0x2X - LED frame blinks green, + 0x4X - LED frame blinks blue, + 0x8X - dis- able LED frame, + 0xFX - LED frame LAPD signal (red-white-blue) + + Default value: [0x02, 0xFF, 0x00, 0x00] (CO Alarm, any notification, no action) + + + + + + This parameter defines duration of alarm sequence. + When time set in this parameter elapses, alarm is cancelled, LED frame and relay restore normal operation, but do not recover state from before the alarm. + + 0 – infinite + 1-32400 (1s-9h, 1s step) – duration + + Default value: 600 (10min) + + + + + + This parameter determines which actions result in sending scene IDs assigned to them. + Values can be combined (e.g. 1+2=3 means that scenes for single and double click are sent). + Enabling scenes for triple click disables entering the device in learn mode by triple clicking. + + 1 - Key pressed 1 time + 2 - Key pressed 2 times + 4 - Key pressed 3 times + 8 - Key hold down and key released + + Default value: 0 (no scenes) + + + + + + This parameter determines which actions result in sending scene IDs assigned to them. + Values can be combined (e.g. 1+2=3 means that scenes for single and double click are sent). + Enabling scenes for triple click disables entering the device in learn mode by triple clicking. + + 1 - Key pressed 1 time + 2 - Key pressed 2 times + 4 - Key pressed 3 times + 8 - Key hold down and key released + + Default value: 0 (no scenes) + + + + + This parameter determines whether the power measurements should include power consumed by the device itself. + + + + + + + This parameter defines minimal change (from the last reported) in measured power that results in sending new report. + For loads under 50W the parameter is irrelevant, report are sent every 5W change. + + 0 - reporting on change disabled + 1-500 (1-500%, 1% step) – minimal change + + Default value: 15 (15%) + + + + + + This parameter defines reporting interval for measured power. + Periodic reports are independent from changes in value (parameter 61). + + 0 – periodic reports disabled + 30-32400 (30s-9h, 1s step) – time interval + + Default value: 3600 (1h) + + + + + + This parameter defines minimal change (from the last reported) in measured energy that results in sending new report. + + 0 - reporting on change disabled + 1-500 (0.01-5kWh, 0.01kWh step) – minimal change + + Default value: 10 (0.1kWh) + + + + + + This parameter defines reporting interval for measured energy. + Periodic reports are independent from changes in value (parameter 65). + + 0 – periodic reports disabled + 30-32400 (30s-9h, 1s step) – time interval + + Default value: 3600 (1h) + + + + + + By setting this parameter to 2 the device enters the calibration mode. + The parameter relevant only if the device is set to work in positioning mode (parameter 151 set to 1 or 2). + + + + + + + + This parameter allows adjusting operation according to the connected device. + + + + + + + + + For Venetian blinds (parameter 151 set to 2) the parameter determines time of full turn cycle of the slats. + The parameter is irrelevant for other modes. + + 0-65535 (0 - 655.35s, every 0.01s) - time of turn + + Default value: 150 (1.5 seconds) + + + + + + For Venetian blinds (parameter 151 set to 2) the parameter determines slats positioning in various situations. + The parameter is irrelevant for other modes. + + + + + + + + + The parameter determines the time after which the motor will be stopped after end switch contacts are closed. + + 1-255 (0.1s - 25.5 seconds) + + + + + + Power threshold interpreted as reaching a limit switch. + + 1-255 (1-255W) - report interval + 0 - no detection + + Default value: 10 (10W) + + + + + + This parameter determines the time needed for roller blinds to reach the top. + For modes with positioning value is set automatically during calibration, otherwise, it must be set manually. + + 1-65535 (0.01 - 655.35 seconds) + + Default value: 6000 (60 seconds) + + + + + This parameter determines the time needed for roller blinds to reach the bottom. + For modes with positioning value is set automatically during calibration, otherwise, it must be set manually. + + 1-65535 (0.01 - 655.35 seconds) + + Default value: 6000 (60 seconds) + + + + + + + + + + + + + diff --git a/config/forest/fs2z5232000002.xml b/config/forest/fs2z5232000002.xml index a92ffe297b..5582192c8f 100644 --- a/config/forest/fs2z5232000002.xml +++ b/config/forest/fs2z5232000002.xml @@ -1,32 +1,35 @@ - + http://www.openzwave.com/device-database/0207:0100:0027 images/forest/fs2z5232000002.png - https://products.z-wavealliance.org/products/1294/ + https://products.z-wavealliance.org/products/3185/ Press configuration button 3 times. LED3 is ON. Press and hold once more for 4 seconds. Press configuration button 25x times. LED 1 is ON. Press and hold once more for 4 seconds to confirm. Please use this procedure only when your network primary controller is missing or otherwise inoperable. - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1294/Installing the FOREST SHUTTLE S - L Z-wave V1_0EN.pdf - FS2Z - CEPT (Europe) - Forest Shuttle L Z-Wave and the Forest motorized curtain track systems (FMS) make an unbeatable combination when it comes to noiseless operated motorized curtains. The smooth and silent running curtain track system can, in addition to remote operation, also be operated by hand. Thanks to Forest’s special Touch Impulse Technology, a gentle pull on the curtain is enough to activate the motor. The Forest Shuttle L Z-Wave also makes sure that your curtains will always hang beautifully smooth and supple. Opened as well as closed! + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3185/Installing_the_FOREST_SHUTTLE_S-M-L _Z-wave_V1_6EN.pdf + FS2Z5232000007 + CEPT (Europe) / U.S. / Canada / Mexico / India / Australia / New Zealand + Forest Shuttle L Z-wave, Shuttle S Z-wave (US) and Forest motorized curtain track systems (FMS) make an unbeatable combination when it comes to noiseless operated motorized curtains. The smooth and silent running curtain track system can, in addition to remote operation, also be operated by hand. Thanks to Forest’s special Touch Impulse Technology, a gentle pull on the curtain is enough to activate the motor. The Forest Shuttle L Z-wave, Shuttle S Z-Wave (US) makes sure that your curtains will always hang beautifully smooth and supple. Opened as well as closed! • Touch Impulse Technology, gently pulling the curtain will activate the motor. • Integrated Emergency Control ensures manual operation of the curtain in case of power failure. • Modular motor, different modules can be attached for various control options: Radio Frequency, Switch, Infrared, Domotics, Building/Hotel Automation, Serial Communication, Z-Wave, etc. -• Forest Shuttle L Z-Wave will have an internal Z-Wave receiver and BUS connection. +• Forest Shuttle L Z-Wave and Shuttle S Z-wave (US) will have an internal Z-Wave receiver and BUS connection. • Silent motor, speeds: 14 and 17 cm/sec., with slow start and slow stop. • Full automatic setting of the limits. • Stack-back position programmable to every desired setting. -• Forest Shuttle L Z-Wave has an integrated power supply. +• Forest Shuttle L Z-Wave and Shuttle S Z-wave (US) have an integrated power supply. • Motor pulley connects motor and FMS track. Also available in upside down version to conceal the motor into the ceiling. -• Available track lenghts: 5.80 meters and 7.00 meters. FMS track and components available in white and black. +• Available track lenghts: 5.80 meters and 7.00 meters. FMS track and components available in white, grey and black. - Forest Shuttle L Z-Wave + Forest Shuttle LZ ANZ Press configuration button 3 times. LED3 is ON. Press and hold once more for 4 seconds. Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1294/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2548/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3184/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3185/xml diff --git a/config/fortrezz/fmi.xml b/config/fortrezz/fmi.xml index a6d76546b7..bc05e1857d 100644 --- a/config/fortrezz/fmi.xml +++ b/config/fortrezz/fmi.xml @@ -1,42 +1,62 @@ - - - - - - - 246 to 69 -10 to 69C - - - 247 to 70 -9 to 70C - - - - 0 TO 2147483647 count rolls over at 99,999,999 - - - - - 0 to 2,550 seconds - - - - - Low vs High flow 0 to 65535 - - - - MultiLevel Sensor Report vs Notification Toggle - - - - - - - - - - - - - - + + + http://www.openzwave.com/device-database/0084:0110:0473 + images/fortrezz/fmi.png + https://products.z-wavealliance.org/products/1690/ + The FMI will send the Node information frame when the switch is briefly pressed. This is primarily used for inclusion; however, status information is also sent after a button press. + + FMI + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1690/User Manual FMI - 29Feb2016.pdf + 1) Set up the inclusion mode at the controller; 2) Briefly press the switch once and the controller will indicate the unit has been included in the network. Also, the LED will blink when the inclusion completes. + U.S. / Canada / Mexico + Device Reset to Factory Defaults – Press and hold the button for 15 or more seconds and then release. This can be done while the device is either in or out of a network, but not while in NWI mode. CAUTION – When a reset is done in-network, the device will no longer be in the network. All configurations and associations will be set to default. + + Information is power! With flow meter, you have the power to automate and manage water consumption and leak detection in your home or building. This is an integral part to a complete water management solution! Flow meter tracks water usage and reports in gallons. Track your households water usage! Drill into reports and find out where your peak consumption is and make changes to reduce your water bills. Flow meter also tells you if water is flowing or not. It knows if the flow is small (like a toilet running) or large (a garden hose left on). This can be used to detect leaks, faulty appliances, or fixtures left on. To add to it's capabilities, flow meter checks the temperature of the nearby surroundings to make sure the pipes don't freeze by sending you temperature reports. There's also a backup battery just in case power is interrupted. You wont have to worry about lost data or a lack of leak monitoring. Plumbed on the water main, flow meter is sure to be a valuable part of your home automation & leak prevention system. + + 1) Set up the exclusion mode at the controller; 2) Briefly press the switch once and then release. The controller will indicate the unit has been removed from the network. The LED will blink when the exclusion completes. + + Flow Meter + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1690/xml + + + + + + + 246 to 69 -10 to 69C + + + 247 to 70 -9 to 70C + + + + 0 TO 2147483647 count rolls over at 99,999,999 + + + + + 0 to 2,550 seconds + + + + + Low vs High flow 0 to 65535 + + + + MultiLevel Sensor Report vs Notification Toggle + + + + + + + + + + + + + + diff --git a/config/fortrezz/mimo2plus.xml b/config/fortrezz/mimo2plus.xml index 1aacf6778e..4c0e66bb15 100644 --- a/config/fortrezz/mimo2plus.xml +++ b/config/fortrezz/mimo2plus.xml @@ -1,60 +1,86 @@ - - - - - - - - 0 The relay will remain latched in the position it is commanded to (open/off or closed/on). - -128 to 127 Set this value to the amount of time in 100ms increments for the relay to remain closed/on before automatically returning to the open/off state. For example, a value of 2 = 0.2 Seconds. - - - - - 0 The relay will remain latched in the position it is commanded to (open/off or closed/on). - -128 to 127 Set this value to the amount of time in 100ms increments for the relay to remain closed/on before automatically returning to the open/off state. For example, a value of 2 = 0.2 Seconds. - - - - Set this value to trigger between thresholds. - - - Set this value to set the lower threshold high number - - - Set this to set the lower threshold low number. - - - Set this to set the upper threshold, high number - - - Set this to set the upper threshold low number - - - Set this value to trigger between thresholds. - - - Set this value to set the lower threshold high number - - - Set this to set the lower threshold low number. - - - Set this to set the upper threshold, high number - - - Set this to set the upper threshold low number - - - - - - - - - - - + + + http://www.openzwave.com/device-database/0084:0204:0463 + images/fortrezz/mimo2plus.png + https://products.z-wavealliance.org/products/1893/ + Device Reset to Factory Defaults – Press and hold the program button for 15 seconds and then release. This can be done while the device is either in or out of a network. CAUTION – When this is done in-network, the device will no longer be in the network and all configurations and associations will be set to default. +Please use this procedure only when your network primary controller is missing or otherwise inoperable. + The MIMO2+ module provides two voltage inputs and two relay outputs (either can be wired normally open or normally closed). +Z-Wave™ messages can be used to read the inputs and control the outputs. The inputs are very configurable for different trigger conditions and can even be mapped to control the outputs. The module includes a button for Z-Wave™ inclusion/exclusion and an LED for various status indications. The functionality of the SIG1 and SIG2 inputs is: +- Analog Triggering: Various trigger conditions can be set for high-to-low and low-to-high transitions. This provides great flexibility for capturing digital or analog events in a wide variety of applications. The trigger status can be automatically sent to the controller. +- Associations: Each input can be associated with up to two other Z-Wave™ devices, so that, for example, an associated device will automatically turn on (or off) based on the occurrence of a trigger event. +Voltage Reporting: The analog input voltage levels can also be sent to the controller. +The physical outputs are relays that are typically activated by Z-Wave™ commands. However, the user can override Z-Wave™ control by configuring the input trigger conditions to be mapped to the output relays via logical AND/OR functions. + + MIMO2+ + U.S. / Canada / Mexico + 1) Activate exclusion mode on your Z-wave controller. +2) Press the program button once. +3) LED will blink 4 times quickly to indicate "in network" status. + 1) Activate inclusion mode on your Z-wave controller. +2) Press the program button once. +3) LED will blink 2 times quickly to indicate "in network" status. + MIMO2+ + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1893/MIMO2 Plus Manual and Tech Appendix 2016-07-29.pdf + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1893/xml + + + + + + + + 0 The relay will remain latched in the position it is commanded to (open/off or closed/on). + -128 to 127 Set this value to the amount of time in 100ms increments for the relay to remain closed/on before automatically returning to the open/off state. For example, a value of 2 = 0.2 Seconds. + + + + + 0 The relay will remain latched in the position it is commanded to (open/off or closed/on). + -128 to 127 Set this value to the amount of time in 100ms increments for the relay to remain closed/on before automatically returning to the open/off state. For example, a value of 2 = 0.2 Seconds. + + + + Set this value to trigger between thresholds. + + + Set this value to set the lower threshold high number + + + Set this to set the lower threshold low number. + + + Set this to set the upper threshold, high number + + + Set this to set the upper threshold low number + + + Set this value to trigger between thresholds. + + + Set this value to set the lower threshold high number + + + Set this to set the lower threshold low number. + + + Set this to set the upper threshold, high number + + + Set this to set the upper threshold low number + + + + + + + + + + + diff --git a/config/fortrezz/mimolite.xml b/config/fortrezz/mimolite.xml index 99c4b39e8e..79c319cd79 100644 --- a/config/fortrezz/mimolite.xml +++ b/config/fortrezz/mimolite.xml @@ -1,85 +1,105 @@ - - - - - - - - Clear Pulse Meter Counts (actual value is dont care; count gets reset whenever - this command is received regardless of value). This parameter is for SIG1 only. - - - - - SIG1 triggered/untriggered sets or clears Relay1. - Refer to description in User Manual under section, Input to Relay Mapping. Note - that neither a Basic Report nor a Binary Switch Report is sent when relay is - automatically set or cleared by Trigger Mapping. Only applies to the Relay1 output. - - - - - SIG1 high lower threshold. - Must be less than Upper Threshold Low and greater than Lower Threshold Low. - - - - - SIG1 low lower threshold. - - - - - SIG1 high upper threshold. - - - - - SIG1 low upper threshold. - Must be greater than Lower Threshold High and less than Upper Threshold High. - - - - - Bits 7 - 2 are ignored and should be set to 0 - - Bit1 : Digital-Configuration flag - 1=Set Trigger levels for this channel to digital thresholds (approx. 1V); Default - 0=Set Trigger levels to analog thresholds (see parameters 4 through 7) - - Bit0 : Trigger-Between-Thresholds flag (see below) - 1 = Set to triggered when input falls between thresholds; Default - 0 = Set to triggered when input falls outside of thresholds - - - - - - - - - Periodic send interval of Multilevel Sensor Reports (Association Group 2) and/or - Pulse Count Reports (Association Group 5) for SIG1. This parameter has a resolution - of 10 seconds; for example, 1 = 10 seconds, 2 = 20 seconds, 3 = 30 seconds (Default), - ... 255 = 2550 seconds = 42.5 minutes. A value of 0 disables automatic reporting. - - - - - Momentary Relay1 output enable/disable. - 1..255 = enable / value sets the approximate momentary on time in increments - of 100msec. - - - - - - - - - - - - - - + + + http://www.openzwave.com/device-database/0084:0111:0453 + images/fortrezz/mimolite.png + https://products.z-wavealliance.org/products/1756/ + U.S. / Canada / Mexico + MIMOlite + MIMOlite + Make virtually anything speak Z-wave™! The MiMOlite Module is an interface / bridge module, capable of converting a wire or wireless input to a wire or wireless output. It provides one relay to wirelessly control low voltage applications & one signal input to connect a digital, analog, or pulse signal into your Z-waveTM network. + +Common Applications + + Garage Doors & Motorized Gates + Wired Door Bells / Chimes + Control Solenoids + Connect to existing wired buttons + Security Panel Zone-in + Motorized Shades + Connect to various wired sensors including Temperature probes, Soil Moisture probes, Float switches, Level Sensors, Reed Switches, Door / Window sensors, etc. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1756/xml + + + + + + + Clear Pulse Meter Counts (actual value is dont care; count gets reset whenever + this command is received regardless of value). This parameter is for SIG1 only. + + + + + SIG1 triggered/untriggered sets or clears Relay1. + Refer to description in User Manual under section, Input to Relay Mapping. Note + that neither a Basic Report nor a Binary Switch Report is sent when relay is + automatically set or cleared by Trigger Mapping. Only applies to the Relay1 output. + + + + + SIG1 high lower threshold. + Must be less than Upper Threshold Low and greater than Lower Threshold Low. + + + + + SIG1 low lower threshold. + + + + + SIG1 high upper threshold. + + + + + SIG1 low upper threshold. + Must be greater than Lower Threshold High and less than Upper Threshold High. + + + + + Bits 7 - 2 are ignored and should be set to 0 + + Bit1 : Digital-Configuration flag + 1=Set Trigger levels for this channel to digital thresholds (approx. 1V); Default + 0=Set Trigger levels to analog thresholds (see parameters 4 through 7) + + Bit0 : Trigger-Between-Thresholds flag (see below) + 1 = Set to triggered when input falls between thresholds; Default + 0 = Set to triggered when input falls outside of thresholds + + + + + + + + + Periodic send interval of Multilevel Sensor Reports (Association Group 2) and/or + Pulse Count Reports (Association Group 5) for SIG1. This parameter has a resolution + of 10 seconds; for example, 1 = 10 seconds, 2 = 20 seconds, 3 = 30 seconds (Default), + ... 255 = 2550 seconds = 42.5 minutes. A value of 0 disables automatic reporting. + + + + + Momentary Relay1 output enable/disable. + 1..255 = enable / value sets the approximate momentary on time in increments + of 100msec. + + + + + + + + + + + + + + diff --git a/config/ge/12724-dimmer.xml b/config/ge/12724-dimmer.xml index a82d0a9689..a40b21a875 100644 --- a/config/ge/12724-dimmer.xml +++ b/config/ge/12724-dimmer.xml @@ -1,18 +1,24 @@ - + http://www.openzwave.com/device-database/0063:3031:4944 images/ge/12724-dimmer.png https://products.z-wavealliance.org/products/1197/ - Z-Wave Fan Control + Transform any home into a smart home with the GE Z-Wave Smart Fan Control. The in-wall fan control easily replaces any standard in-wall switch remotely controls a ceiling fan in your home and features a three-speed control system. Your home will be equipped with ultimate flexibility with the GE Z-Wave Smart Fan Control, capable of being used by itself or with up to four GE add-on switches. Screw terminal installation provides improved space efficiency when replacing existing switches and the integrated LED indicator light allows you to easily locate the switch in a dark room. The GE Z-Wave Smart Fan Control is compatible with any Z-Wave certified gateway, providing access to many popular home automation systems. Take control of your home lighting with GE Z-Wave Smart Lighting Controls! U.S. / Canada / Mexico - Jasco Fan Speed Control (45743) + In-Wall Smart Fan Control http://www.ezzwave.com 12724 / ZW3005 + https://products.z-wavealliance.org/products/1198/ + U.S. / Canada / Mexico + 12725 / ZW3006 + Update for 3032 Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1197/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1201/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1202/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1221/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2103/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2506/xml https://products.z-wavealliance.org/products/1201/ U.S. / Canada / Mexico @@ -20,6 +26,17 @@ https://products.z-wavealliance.org/products/1221/ U.S. / Canada / Mexico 45743 + https://products.z-wavealliance.org/products/2506/ + U.S. / Canada / Mexico + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2506/Binder2.pdf + 14287/ZW4002 + 1. Follow the instructions for your Z-Wave certified controller to include a device to the Z-Wave network. +2. Once the controller is ready to include your device, press and release the top or bottom of the smart fan control switch (rocker) to include it in the network. +3. Once your controller has confirmed the device has been included, refresh the Z-Wave network to optimize performance. + 1. Follow the instructions for your Z-Wave certified controller to exclude a device from the Z-Wave network. +2. Once the controller is ready to Exclude your device, press and release the top or bottom of the wireless smart switch (rocker) to exclude it from the network. + 1. Quickly press ON (Top) button three (3) times then immediately press the OFF (Bottom) button three (3) times. The LED will flash ON/OFF 5 times when completed successfully. +Note: This should only be used in the event your network’s primary controller is missing or otherwise inoperable. diff --git a/config/ge/14282-plugin-switch.xml b/config/ge/14282-plugin-switch.xml index 8ad50ff162..0306623d58 100644 --- a/config/ge/14282-plugin-switch.xml +++ b/config/ge/14282-plugin-switch.xml @@ -1,26 +1,43 @@ + --> http://www.openzwave.com/device-database/0063:3033:5052 images/ge/14282-plugin-switch.png - https://products.z-wavealliance.org/products/1437/ - 1. Follow the instructions for your Z-wave certified controller to include the device to the Z-wave network. -2. Once the controller is ready to include your smart switch, single press and release the manual/program button on the smart dimmer to include it in the network. -3. Once your controller has confirmed that the smart switch has been included, refresh the Z-wave network to optimize performance. - 1. Follow the instructions for your Z-wave certified controller to exclude a device from the Z-wave network. -2. Once the controller is ready to Exclude your device, press and release the manual/program button on the smart switch to exclude it from the network. - Transform any home into a smart home with the GE Z-Wave Smart Lighting Control Plug-in Smart Switch. The lighting control enables wireless control of on/off functions for standard table and floor lamps, and is compatible with incandescent, LED, Xenon, Halogen, fluorescent and compact fluorescent bulbs. Easily controlled by your mobile device or computer using any Z-Wave certified gateway, the space-saving horizontal module plugs into a standard wall receptacle without blocking the second outlet or obstructing placement of furniture. It provides two Z-Wave enabled outlets controlled together for 2 lamps or appliances that you would like to. Perfect for 2 lamps or devices on other side of a couch or bed! Take control of your home lighting with GE Z-Wave Smart Lighting Controls! - 1. If plugged in, unplug the Switch from the receptacle. -2. Press and hold the top button for at least 3 seconds while you plug the switch into a receptacle. -Note: This should only be used in the event your network’s primary controller is missing or otherwise inoperable. - 14282 (ZW4106) - Plug-in Smart Switch, Dual Outlet with Simultaneous Control + https://products.z-wavealliance.org/products/2525/ + Adding your device to a Z-Wave network: +1. Follow the instructions for your Z-Wave certified controller to +include the device to the Z-Wave network. +2. Once the controller is ready to include your smart switch, +single press and release the manual/program button on the +smart switch to include it in the network. +Now you have complete control to turn your lamp ON/OFF +according to groups, scenes, schedules and interactive +automations programmed by your controller. +If your Z-Wave certified controller features Remote Access, +you can now control your lighting from your mobile devices + To exclude and reset the device: +1. Follow the instructions for your Z-Wave certified controller to +exclude a device from the Z-Wave network. +2. Once the controller is ready to Exclude your device, press +and release the manual/program button on the smart switch +to exclude it from the network. + Transform any home into a smart home with the GE Z-Wave Smart Lighting Control and Appliance Module. The lighting control enables wireless control of on/off functions for standard table and floor lamps, and is compatible with incandescent, LED, Xenon, Halogen, fluorescent and compact fluorescent bulbs. Easily controlled by your mobile device or computer using any Z-Wave certified gateway, the space-saving horizontal module plugs into a standard wall receptacle without blocking the second outlet or obstructing placement of furniture. It provides dual simultaneous Z-Wave enabled outlets for the lamp or appliance that you would like to control and a regular pass-through AC outlet for other electrical appliances. Perfect for plug-in fans, heaters, lamps and more! Take control of your home lighting with GE Z-Wave Smart Lighting Controls! + To return your switch to factory defaults: +1. If plugged in, unplug the Switch from the receptacle. +2. Press and hold the top button for at least 3 seconds while +you plug the switch into a receptacle. +Note: This should only be used in the event your networks’ +primary controller is missing or otherwise inoperable. + 14282/ZW4106 + Plug-in Smart Switch, Dual Plug U.S. / Canada / Mexico - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1437/14282-1 EnFrSp QSG.pdf + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2525/Binder1.pdf Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1437/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2104/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2525/xml diff --git a/config/ge/14284.xml b/config/ge/14284.xml new file mode 100644 index 0000000000..f16fd4548b --- /dev/null +++ b/config/ge/14284.xml @@ -0,0 +1,23 @@ + + + http://www.openzwave.com/device-database/0063:3032:4F50 + images/ge/14284.png + https://products.z-wavealliance.org/products/2526/ + 1. If plugged in, unplug the Switch from the receptacle. +2. Press and hold the top button for at least 3 seconds while you plug the switch into a receptacle. + 14284/ZW4201 + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2526/14284 EnFrSp QSG v1.pdf + Transform any home into a smart home with the GE Z-Wave Outdoor Smart Switch. The lighting control enables wireless control of on/off functions for outdoor applications, and is compatible with incandescent, LED, Xenon, Halogen, fluorescent and compact fluorescent bulbs. The weather-resistant housing with a protective outlet cover safeguards the outlet from dirt and debris when not in use. The discreet black color blends in with any outdoor environment. Perfect for decorative or seasonal lighting, fountains and other outdoor plug-in appliances. Take control of your home lighting with GE Z-Wave Smart Lighting Controls! + 1. Follow the instructions for your Z-Wave certified controller to exclude a device from the Z-Wave network. +2. Once the controller is ready to Exclude your device, press and release the manual/program button on the smart switch to exclude it from the network. + Plug-in Outdoor Smart Switch + U.S. / Canada / Mexico + 1. Follow the instructions for you Z-Wave certified controller to include the smart switch to the Z-Wave network. +2. Once the controller is ready to include your outdoor smart switch, press and release the manual/program button on the smart switch to include it in the network. +3. Once your controller has confirmed that the smart switch has been included, refresh the Z-Wave network to optimize performance. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1853/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2526/xml + + + diff --git a/config/ge/14288-outlet.xml b/config/ge/14288-outlet.xml index e611246785..f87f5b6979 100644 --- a/config/ge/14288-outlet.xml +++ b/config/ge/14288-outlet.xml @@ -1,26 +1,50 @@ - - - - - - - Sets when the LED on the outlet is lit. - - - - - - - - - - - - - +--> + + http://www.openzwave.com/device-database/0063:3134:4952 + images/ge/14288-outlet.png + https://products.z-wavealliance.org/products/2372/ + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2372/14315 QSG v0.pdf + In-Wall Tamper Resistant Smart Outlet + U.S. / Canada / Mexico + 14315/ZW1002 + 1. Follow the instructions for your Z-Wave certified controller to +remove a device from the Z-Wave network. +2. Once the controller is ready to remove your device, press and +release the manual/program button to remove it from the +network. + Follow the instructions for your Z-Wave certified +controller to add a device to the Z-Wave network. +2. Once the controller is ready to add your device, press and +release the Program Button to add it in the network. + Press the button 3 times, then press and hold the button for at least 3 +seconds. The LED will blink 5 times to confirm. +NOTE: This should only be used in the event your network’s primary +controller is missing or otherwise inoperable + Transform any home into a smart home with the Jasco Z-Wave Tamper Resistant Smart Outlet. The Jasco Z-Wave Tamper Resistant Smart Outlet enables wireless control of on/off functions from the Z-Wave controlled outlet, and is compatible with incandescent, LED, Xenon, Halogen, fluorescent and compact fluorescent bulbs. The tamper resistant duplex receptacle includes a blue LED indicator light to easily locate the receptacle in a dark room. The receptacle replaces your current electrical outlet, uses your existing wiring and provides a Z-Wave enabled outlet for the lamp or appliance that you would like to control and a standard pass-through AC outlet for other electrical appliances. Take control of your home lighting with Jasco Z-Wave Smart Lighting Controls! + + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2236/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2372/xml + + + + + + Sets when the LED on the outlet is lit. + + + + + + + + + + + + + - diff --git a/config/ge/14291-switch.xml b/config/ge/14291-switch.xml index 881bf11db8..21e7304240 100644 --- a/config/ge/14291-switch.xml +++ b/config/ge/14291-switch.xml @@ -1,21 +1,24 @@ - + http://www.openzwave.com/device-database/0063:3036:4952 images/ge/14291-switch.png - https://products.z-wavealliance.org/products/1438/ - 1. Follow the instructions for your Z-wave certified controller to exclude a device from the Z-wave network. -2. Once the controller is ready to Exclude your device, press and release the top or bottom of the wireless smart switch(rocker) to exclude it from the network. - 14291 (ZW4005) - Transform any home into a smart home with the GE Z-Wave Smart Lighting Control In-Wall Smart Switch. The on/off switch replaces your current light switch, uses your existing wiring, and provides Z-Wave wireless and in-wall control of overhead lighting. The switch enables wireless control of on/off functions of direct wire incandescent, LED, xenon, halogen and fluorescent lighting. Providing ultimate flexibility, the GE Z-Wave Smart Lighting Control On/Off Switch allows you to operate the switch by itself or easily integrate the switch with two-way, three-way or four-way wiring configurations by adding the GE Add-On switch. Single pole wiring configuration turns the light or appliance on/off from one location. Three-way wiring configuration turns the light on/off from two separate locations. Four-way wiring configuration turns the light on/off from three separate locations. The GE Add-On Switch is required for Three-way or Four-way installations. The lighting control includes a blue LED indicator light to easily locate the switch in a dark room. Take control of your home lighting with GE Z-Wave Smart Lighting Controls! - 1. Quickly press ON (Top) button three (3) times then immediately press the OFF (Bottom) button three (3) times. The LED will flash ON/OFF 5 times when completed successfully. -Note: This should only be used in the event your networks primary controller is missing or otherwise inoperable. + https://products.z-wavealliance.org/products/2501/ + 1. Follow the instructions for your Z-Wave certified controller to exclude a device from the Z-Wave network. +2. Once the controller is ready to exclude your device, press and release the top button of the wireless smart switch (rocker) to exclude it from the network. + 14291/ZW4005 + Transform any home into a smart home with the GE Z-Wave In-Wall Smart Switch. The on/off switch replaces your current light switch, uses your existing wiring, and provides Z-Wave wireless and in-wall control of overhead lighting. The switch enables wireless control of on/off functions of direct wire incandescent, LED, xenon, halogen and fluorescent lighting. Providing ultimate flexibility, the GE Z-Wave Smart Lighting Control On/Off Switch allows you to operate the switch by itself or easily integrate the switch with two-way, three-way or four-way wiring configurations by adding the GE Add-On switch. Single pole wiring configuration turns the light or appliance on/off from one location. Three-way wiring configuration turns the light on/off from two separate locations. Four-way wiring configuration turns the light on/off from three separate locations. The GE Add-On Switch is required for Three-way or Four-way installations. The lighting control includes a blue LED indicator light to easily locate the switch in a dark room. Take control of your home lighting with GE Z-Wave Smart Lighting Controls! + 1. Quickly press ON (Top) button 3 times then immediately press the OFF (Bottom) button 3 times. The LED will flash ON/OFF 5 times when completed successfully. +2. Please use this reset procedure only when the primary controller is missing or inoperable. U.S. / Canada / Mexico - In-Wall Smart Switch - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1438/14291-1 EnFrSp QSG.pdf - 1. Follow the instructions for your Z-wave certified controller to include a device to the Z-wave network. -2. Once the controller is ready to include your device, press and release the top or bottom of the wireless smart switch(rocker) to include it in the network. + In-Wall Smart Switch + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2501/Binder1.pdf + 1. Follow the instructions for your Z-Wave certified controller to include a device to the Z-Wave network. +2. Once the controller is ready to include your device, press and release the top or bottom of the wireless smart switch(rocker) to include it in the network. +3. Once your controller has confirmed that the device has been included, refresh the Z-Wave network to optimize performance. Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1438/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1879/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2501/xml diff --git a/config/ge/14292-toggle-switch.xml b/config/ge/14292-toggle-switch.xml index 4098d3ce35..ee86bde3f4 100644 --- a/config/ge/14292-toggle-switch.xml +++ b/config/ge/14292-toggle-switch.xml @@ -1,19 +1,42 @@ - - - - - - Change the top of the switch to OFF and the bottom of the switch to ON, if the switch was installed upside down. - - - - - - - - - - - - + + + http://www.openzwave.com/device-database/0063:3037:4952 + images/ge/14292-toggle-switch.png + https://products.z-wavealliance.org/products/2502/ + 1. Follow the instructions for your Z-Wave certified controller to include a device to the Z-Wave network. +2. Once the controller is ready to include your device, press up and release on the toggle to include it in the network. +3. Once your controller has confirmed that the device has been included, refresh the Z-Wave network to optimize performance. + 14292/ZW4003 + 1. Follow the instructions for your Z-Wave certified controller to exclude a device from the Z-Wave network. +2. Once the controller is ready to exclude your device, press up and release on the toggle to exclude it from the network. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2502/Binder2.pdf + Transform any home into a smart home with the GE Z-Wave Smart Toggle Switch. The In-Wall Smart Toggle Switch can easily replaces any standard in-wall switch and remotely controls a light in your home. Your home will be equipped with ultimate flexibility with the GE Z-Wave Smart Toggle Switch, capable of being used by itself or with up to four add-on switches. Screw terminal installation provides improved space efficiency when replacing existing switches and the integrated LED indicator light allows you to easily locate the switch in a dark room. The GE Z-Wave In-Wall Smart Toggle Switch is compatible with any Z-Wave certified gateway, providing access to many popular home automation systems. Take control of your home lighting with GE Z-Wave Smart Lighting Controls! + In-Wall Smart Toggle Switch (White) + U.S. / Canada / Mexico + 1. Quickly press ON (up) 3 times then immediately press the OFF (Down) button 3 times. Note: This should only be used in the event your networks primary controller is missing or otherwise inoperable. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1856/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2055/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2502/xml + + https://products.z-wavealliance.org/products/2055/ + U.S. / Canada / Mexico + 14293/ZW4003 + + + + + Change the top of the switch to OFF and the bottom of the switch to ON, if the switch was installed upside down. + + + + + + + + + + + + diff --git a/config/ge/14294-dimmer.xml b/config/ge/14294-dimmer.xml index 4553e21c9c..24a2ee8dae 100644 --- a/config/ge/14294-dimmer.xml +++ b/config/ge/14294-dimmer.xml @@ -1,23 +1,40 @@ + http://products.z-wavealliance.org/products/1442 --> http://www.openzwave.com/device-database/0063:3038:4944 images/ge/14294-dimmer.png - https://products.z-wavealliance.org/products/1442/ - In-Wall Smart Dimmer - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1442/14294-1 EnSpFr QSG.pdf + https://products.z-wavealliance.org/products/2105/ + In-Wall Smart 1000W Dimmer + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2168/Binder1.pdf U.S. / Canada / Mexico - 1. Quickly press ON (Top) button three (3) times then immediately press the OFF (Bottom) button three (3) times. The LED will flash ON/OFF 5 times when completed successfully. -Note: This should only be used in the event your networks primary controller is missing or otherwise inoperable. - 1. Follow the instructions for your Z-wave certified controller to include a device to the Z-wave network. -2. Once the controller is ready to include your device, press and release the top or bottom of the wireless smart switch(rocker) to include it in the network. - Transform any home into a smart home with the GE Z-Wave Wireless Lighting Control In-Wall Smart Dimmer. The dimmer enables wireless control of on/off and dim functions of hard-wired dimmable LED/CFL and incandescent lighting. The dimmer replaces your current light switch, uses your existing wiring, and provides Z-Wave wireless and in-wall control of overhead lighting. Use the dimmer feature to customize the lighting output and create the perfect ambiance for any room. Providing ultimate flexibility, the In-Wall Smart Dimmer allows you to operate the switch by itself or easily integrate the switch three-way or four-way wiring configurations by adding the GE Add-On Switch. Single Pole wiring configuration controls the light from one location. Three-way wiring configuration controls the light from two separate locations. Four-way wiring configuration controls the light from three separate locations. The GE Add-On Switch is required for three-way or four-way installations. The dimmer includes an LED indicator light to easily locate the switch in a dark room. Take control of your home lighting with GE Z-Wave Wireless Lighting Controls! - 14294 (ZW3005) - 1. Follow the instructions for your Z-wave certified controller to exclude a device from the Z-wave network. -2. Once the controller is ready to Exclude your device, press and release the top or bottom of the wireless smart switch(rocker) to exclude it from the network. + Quickly press ON (Top) button three (3) times then immediately +press the OFF (Bottom) button three (3) times. The LED will flash +ON/OFF 5 times when completed successfully. +NOTE: This should only be used in the event your network’s +primary controller is missing or otherwise inoperable. + 1. Follow the instructions for your Z-Wave certified controller to +include a device to the Z-Wave network. +2. Once the controller is ready to add your device, +press and release the top or bottom of the wireless smart +switch (rocker) to add it in the network. +Please reference the controller’s manual for instructions. + Transform any home into a smart home with the GE Z-Wave Smart 1000W Dimmer. The In-Wall Smart 1000W Dimmer can easily replace any standard in-wall switch and remotely controls a light in your home. Your home will be equipped with ultimate flexibility with the GE Z-Wave Smart 1000W Dimmer, capable of being used by itself or with up to four add-on switches. Screw terminal installation provides improved space efficiency when replacing existing switches and the integrated LED indicator light allows you to easily locate the switch in a dark room. The GE Z-Wave In-Wall Smart 1000W Dimmer is compatible with any Z-Wave certified gateway, providing access to many popular home automation systems. Take control of your home lighting with GE Z-Wave Smart Lighting Controls! + +Z-Wave is the world’s largest ecosystem of inter operable smart home products. Z-Wave lighting controls provide an easy-to-install and affordable system to control lighting and small appliances in your home. Add GE Z-Wave lighting controls to a Z-Wave certified gateway to access and control your home from anywhere in the world using your smartphone, tablet or computer as a home automation command center. Never worry if you accidentally left the lights on because you can turn them off remotely or program your lights to go on/off at specific times. Create customized lighting scenes for any occasion such as a “go to sleep” scene or a “movie night” scene. Give the illusion that someone is home by programming the lights to turn on/off while you are away—perfect for deterring crime and adding additional security!" + 14294/ZW3005 + 1. Follow the instructions for your Z-Wave certified controller to +remove a device from the Z-Wave network. +2. Once the controller is ready to Exclude your device, press +and release the top or bottom of the wireless smart dimmer +(rocker) to remove it from the network. Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1442/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2105/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2168/xml + https://products.z-wavealliance.org/products/2168/ + 14299/ZW3006 + U.S. / Canada / Mexico diff --git a/config/ge/14295-dimmer-toggle.xml b/config/ge/14295-dimmer-toggle.xml index 190d968f2c..fd6a070e7b 100644 --- a/config/ge/14295-dimmer-toggle.xml +++ b/config/ge/14295-dimmer-toggle.xml @@ -1,39 +1,62 @@ - - - - - - - Change the top of the switch to OFF and the bottom of the switch to ON, if the switch was installed upside down. - - - - - - Indicates how many levels the dimmer will change for each dimming step. - - - This value indicates in 10 millisecond resolution, how often the dim level will change. For example, if you set this parameter to 1, then every 10ms the dim level will change. If you set it to 255, then every 2.55 seconds the dim level will change. - - - Indicates how many levels the dimmer will change for each dimming step. - - - This value indicates in 10 millisecond resolution, how often the dim level will change. For example, if you set this parameter to 1, then every 10ms the dim level will change. If you set it to 255, then every 2.55 seconds the dim level will change. - - - Indicates how many levels the dimmer will change for each dimming step. - - - This value indicates in 10 millisecond resolution, how often the dim level will change. For example, if you set this parameter to 1, then every 10ms the dim level will change. If you set it to 255, then every 2.55 seconds the dim level will change. - - - - - - - - - - + + + http://www.openzwave.com/device-database/0063:3130:4944 + images/ge/14295-dimmer-toggle.png + https://products.z-wavealliance.org/products/2048/ + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2048/14295 QSG v0.pdf + In-Wall Smart Toggle Dimmer + 1. Follow the instructions for your Z-Wave certified controller to +include a device to the Z-Wave network. +2. Once the controller is ready to include your device, press +and release the top or bottom of the wireless smart dimmer +(rocker) to include it in the network. + U.S. / Canada / Mexico + 14295/ZW3004 + 1. Quickly press ON (up) button (3) times then immediately press the OFF (down) button (3) times. +Note: This should only be used in the even your network's primary controller is missing or otherwise inoperable. + 1. Follow the instructions for your Z-Wave certified controller to +exclude a device from the Z-Wave network. +2. Once the controller is ready to Exclude your device, press +and release the top or bottom of the wireless smart dimmer +(rocker) to exclude it from the network. + Transform any home into a smart home with the GE Z-Wave In-Wall Smart Toggle Dimmer. The dimmer enables wireless control of on/off and dim functions of hard-wired dimmable LED/CFL and incandescent lighting. The dimmer replaces your current light switch, uses your existing wiring, and provides Z-Wave wireless and in-wall control of overhead lighting. Use the dimmer feature to customize the lighting output and create the perfect ambiance for any room. Providing ultimate flexibility, the In-Wall Smart Dimmer allows you to operate the switch by itself or easily integrate the switch three-way or four-way wiring configurations by adding the GE Add-On Switch. Single Pole wiring configuration controls the light from one location. Three-way wiring configuration controls the light from two separate locations. Four-way wiring configuration controls the light from three separate locations. The GE Add-On Switch is required for three-way or four-way installations. Take control of your home lighting with GE Z-Wave Wireless Lighting Controls! + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2048/xml + + + + + + Change the top of the switch to OFF and the bottom of the switch to ON, if the switch was installed upside down. + + + + + + Indicates how many levels the dimmer will change for each dimming step. + + + This value indicates in 10 millisecond resolution, how often the dim level will change. For example, if you set this parameter to 1, then every 10ms the dim level will change. If you set it to 255, then every 2.55 seconds the dim level will change. + + + Indicates how many levels the dimmer will change for each dimming step. + + + This value indicates in 10 millisecond resolution, how often the dim level will change. For example, if you set this parameter to 1, then every 10ms the dim level will change. If you set it to 255, then every 2.55 seconds the dim level will change. + + + Indicates how many levels the dimmer will change for each dimming step. + + + This value indicates in 10 millisecond resolution, how often the dim level will change. For example, if you set this parameter to 1, then every 10ms the dim level will change. If you set it to 255, then every 2.55 seconds the dim level will change. + + + + + + + + + + diff --git a/config/ge/26931-motion-switch.xml b/config/ge/26931-motion-switch.xml index a34d5ff3d9..5fd6e0cdd2 100644 --- a/config/ge/26931-motion-switch.xml +++ b/config/ge/26931-motion-switch.xml @@ -1,46 +1,73 @@ - - - - - - - Amount of time the light stays on after motion stops - - - - - - - - - Valid values are 0-99 or 255 for last dimming level - - - Motion-sensing mode of operation. - - - - - - In a three-way configuration, change the top of the add-on switch to OFF and the bottom of the switch to ON, if the switch was installed upside down. - - - - - - - - - - - - - - - - - - 0 = disable + + + http://www.openzwave.com/device-database/0063:3032:494D + images/ge/26931-motion-switch.png + https://products.z-wavealliance.org/products/2035/ + In-Wall Smart Motion Switch + Press and release the top button ten times. +Note: This should only be used in the event your +network’s primary controller is missing or otherwise +inoperable. + 26931/ZW4006 + U.S. / Canada / Mexico + 1. Follow the instructions for your Z-Wave certified +controller to exclude a device from the Z-Wave +network. +2. Once the controller is ready to exclude your device, +press and release the top or bottom button on the +smart switch to exclude it from the network. + Transform any home into a smart home with the GE In-Wall Smart Motion Switch. This Z-Wave device replaces you current light switch using your existing wiring and provides Z-Wave wireless control of overhead lighting. The switch enables wireless control of On/OFF functions of incandescent, LED, xenon, halogen and fluorescent lighting. Not only does it act as a switch but the GE In-Wall Smart Motion Switch has a built in PIR sensor which can control the local and be set in occupancy or vacancy mode. + 1. Follow the instructions for your Z-Wave certified +controller to include the smart switch to the +Z-Wave network. +2. Once the controller is ready to include your smart +switch, press and release the top or bottom button +on the smart switch to include it in the network. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2035/26931 EnFrSp QSG v1.3 and Parameters.pdf + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2035/xml + + + + + + Amount of time the light stays on after motion stops + + + + + + + + + Valid values are 0-99 or 255 for last dimming level + + + Motion-sensing mode of operation. + + + + + + In a three-way configuration, change the top of the add-on switch to OFF and the bottom of the switch to ON, if the switch was installed upside down. + + + + + + + + + + + + + + + + + + 0 = disable 1 = 10 seconds 2 = 20 seconds 3 = 30 seconds @@ -48,18 +75,18 @@ ... 110 = 27 minutes 15 seconds - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/config/ge/26933-motion-dimmer.xml b/config/ge/26933-motion-dimmer.xml index 2d7d41e469..7c1041b2d6 100644 --- a/config/ge/26933-motion-dimmer.xml +++ b/config/ge/26933-motion-dimmer.xml @@ -1,65 +1,98 @@ - - - - - - - Amount of time the light stays on after motion stops - - - - - - - - - Valid values are 0-99 or 255 for last dimming level - - - Motion-sensing mode of operation. - - - - - - In a three-way configuration, change the top of the add-on switch to OFF and the bottom of the switch to ON, if the switch was installed upside down. - - - - - - - - - - Indicates how many levels the dimmer will change for each dimming step. - - - This value indicates in 10 millisecond resolution, how often the dim level will change. For example, if you set this parameter to 1, then every 10ms the dim level will change. If you set it to 255, then every 2.55 seconds the dim level will change. - - - Indicates how many levels the dimmer will change for each dimming step. - - - This value indicates in 10 millisecond resolution, how often the dim level will change. For example, if you set this parameter to 1, then every 10ms the dim level will change. If you set it to 255, then every 2.55 seconds the dim level will change. - - - Indicates how many levels the dimmer will change for each dimming step. - - - This value indicates in 10 millisecond resolution, how often the dim level will change. For example, if you set this parameter to 1, then every 10ms the dim level will change. If you set it to 255, then every 2.55 seconds the dim level will change. - - - - - - - - - - - - 0 = disable + + + http://www.openzwave.com/device-database/0063:3034:494D + images/ge/26933-motion-dimmer.png + https://products.z-wavealliance.org/products/2108/ + 26933 + 1. Follow the instructions for your Z-Wave certified +controller to remove a device from the Z-Wave +network. +2. Once the controller is ready to remove your device, +press and release the top button on the smart +dimmer to remove it from the network. + U.S. / Canada / Mexico + Press and release the top button ten times within 5 +seconds. The LED will flash 3 times quickly confirming +change. +Note: This should only be used in the event your +network’s primary controller is missing or otherwise +inoperable + 1. Follow the instructions for your Z-Wave certified +controller to add the smart dimmer to the Z-Wave +network. +2. Once the controller is ready to add your smart +dimmer, press and release the top or bottom +button on the smart dimmer to include it in the +network. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2108/26933 EnFrSp QSG v1.3 and Parameters.pdf + Transform any home into a smart home with the GE In-Wall Smart Motion Dimmer. This Z-Wave device replaces you current light switch using your existing wiring and provides Z-Wave wireless control of overhead lighting. The dimmer enables wireless control of On/Off functions of incandescent, LED, xenon, halogen and fluorescent lighting. Not only does it act as a dimmer but the GE In-Wall Smart Motion Dimmer has a built in PIR sensor which can control the local load and be set in occupancy or vacancy mode. + + + In-Wall Smart Motion Dimmer + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2108/xml + Fix paraleter size as per https://github.com/OpenZWave/open-zwave/pull/1968 + + + + + + Amount of time the light stays on after motion stops + + + + + + + + + Valid values are 0-99 or 255 for last dimming level + + + Motion-sensing mode of operation. + + + + + + In a three-way configuration, change the top of the add-on switch to OFF and the bottom of the switch to ON, if the switch was installed upside down. + + + + + + + + + + Indicates how many levels the dimmer will change for each dimming step. + + + This value indicates in 10 millisecond resolution, how often the dim level will change. For example, if you set this parameter to 1, then every 10ms the dim level will change. If you set it to 255, then every 2.55 seconds the dim level will change. + + + Indicates how many levels the dimmer will change for each dimming step. + + + This value indicates in 10 millisecond resolution, how often the dim level will change. For example, if you set this parameter to 1, then every 10ms the dim level will change. If you set it to 255, then every 2.55 seconds the dim level will change. + + + Indicates how many levels the dimmer will change for each dimming step. + + + This value indicates in 10 millisecond resolution, how often the dim level will change. For example, if you set this parameter to 1, then every 10ms the dim level will change. If you set it to 255, then every 2.55 seconds the dim level will change. + + + + + + + + + + + + 0 = disable 1 = 10 seconds 2 = 20 seconds 3 = 30 seconds @@ -67,28 +100,27 @@ ... 110 = 27 minutes 15 seconds - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/config/ge/28167-plugin-dimmer.xml b/config/ge/28167-plugin-dimmer.xml index 25ba4b24b1..5af8ac1a9a 100644 --- a/config/ge/28167-plugin-dimmer.xml +++ b/config/ge/28167-plugin-dimmer.xml @@ -1,22 +1,33 @@ - + http://www.openzwave.com/device-database/0063:3038:5044 images/ge/28167-plugin-dimmer.png - https://products.z-wavealliance.org/products/1433/ + https://products.z-wavealliance.org/products/2100/ U.S. / Canada / Mexico - Plug-in Smart Dimmer (Single Plug) - 1. Follow the instructions for your Z-wave certified controller to include the device to the Z-wave network. -2. Once the controller is ready to include your smart switch, single press and release the manual/program button on the smart dimmer to include it in the network. - 28167 (ZW3104) - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1433/28167-1 EnFrSp QSG.pdf - 1. If plugged in, unplug the Switch from the receptacle. -2. Press and hold the top button for at least 3 seconds while you plug the switch into a receptacle. -Note: This should only be used in the event your network’s primary controller is missing or otherwise inoperable. - Transform any home into a smart home with the GE Z-Wave Smart Lighting Control Plug-in Smart Dimmer. The lamp module enables wireless control of on/off and dim functions for standard incandescent table and floor lamps, as well as dimmable fluorescent, LED and CFL fixtures and more! Use the dimmer control to customize the lighting output and create the perfect ambiance for any room. The space-saving horizontal module plugs into a standard wall receptacle without blocking the second outlet or obstructing placement of furniture. The Dimmer provides one Z-Wave enabled outlet for the lamp you would like to control. Take control of your home lighting with GE Z-Wave Smart Lighting Controls! - 1. Follow the instructions for your Z-wave certified controller to exclude a device from the Z-wave network. -2. Once the controller is ready to Exclude your device, press and release the manual/program button on the smart switch to exclude it from the network. + Plug-in Smart Dimmer, Single Plug + 1. Follow the instructions for your Z-Wave certified controller to add +the smart dimmer to the Z-Wave network. +2. Once the controller is ready to add your smart dimmer, single +press and release the manual/program button on the smart +dimmer to add it in the network. +Please reference the controller/gateway’s manual for instructions. + 28167/ZW3104 + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2100/Binder1.pdf + To return your dimmer to factory defaults: +1. If plugged in, unplug the dimmer from the receptacle. +2. Press and hold the top button for at least 3 seconds while you +plug the dimmer into a receptacle. +Note: This should only be used in the event your networks’ primary +controller is missing or otherwise inoperable. + Transform any home into a smart home with the GE Z-Wave Plug-In Smart Dimmer. The Smart Dimmer enables wireless control of on/off and dim functions for standard incandescent table and floor lamps, as well as dimmable fluorescent, LED and CFL fixtures and more! Use the dimmer control to customize the lighting output and create the perfect ambiance for any room. The space-saving horizontal module plugs into a standard wall receptacle without blocking the second outlet or obstructing placement of furniture. The Dimmer provides one Z-Wave enabled outlet for the lamp you would like to control. Take control of your home lighting with GE Z-Wave Smart Lighting Controls! + 1. Follow the instructions for your Z-Wave certified controller to +remove a device from the Z-Wave network. +2. Once the controller is ready to remove your device, press and +release the manual/program button on the smart dimmer to +remove it from the network. Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1433/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2100/xml + --> http://www.openzwave.com/device-database/0063:3038:5052 images/ge/28169-plugin-switch.png - https://products.z-wavealliance.org/products/1435/ - Transform any home into a smart home with the Jasco Z-Wave Smart Lighting Plug-in Smart Switch. The lighting control enables wireless control of on/off functions for standard table and floor lamps, and is compatible with incandescent, LED, Xenon, Halogen, fluorescent and compact fluorescent bulbs. Easily controlled by your mobile device or computer using any Z-Wave certified gateway, the space-saving horizontal module plugs into a standard wall receptacle without blocking the second outlet or obstructing placement of furniture. It provides a Z-Wave enabled outlet for the lamp or appliance that you would like to control. Perfect for plug-in fans, heaters, lamps and more! Take control of your home lighting with Jasco Z-Wave Smart Lighting Controls! - 1. Follow the instructions for your Z-wave certified controller to include the device to the Z-wave network. -2. Once the controller is ready to include your smart switch, single press and release the manual/program button on the smart dimmer to include it in the network. -3. Once your controller has confirmed that the smart switch has been included, refresh the Z-wave network to optimize performance. - 1. Follow the instructions for your Z-wave certified controller to exclude a device from the Z-wave network. -2. Once the controller is ready to Exclude your device, press and release the manual/program button on the smart switch to exclude it from the network. - 28169 (ZW4103) - 1. If plugged in, unplug the Switch from the receptacle. -2. Press and hold the top button for at least 3 seconds while you plug the switch into a receptacle. -Note: This should only be used in the event your network’s primary controller is missing or otherwise inoperable. - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1435/28169-1 EnFrSp QSG.pdf + https://products.z-wavealliance.org/products/2533/ + Transform any home into a smart home with the GE Z-Wave Smart Lighting Plug-in Smart Switch. The lighting control enables wireless control of on/off functions for standard table and floor lamps, and is compatible with incandescent, LED, Xenon, Halogen, fluorescent and compact fluorescent bulbs. Easily controlled by your mobile device or computer using any Z-Wave certified gateway, the space-saving horizontal module plugs into a standard wall receptacle without blocking the second outlet or obstructing placement of furniture. It provides a Z-Wave enabled outlet for the lamp or appliance that you would like to control. Perfect for plug-in fans, heaters, lamps and more! Take control of your home lighting with GE Z-Wave Smart Lighting Controls! + 1. Follow the instructions for your Z-Wave certified controller to include the device to the Z-Wave network. +2. Once the controller is ready to include your smart switch, single press and release the manual/program button on the smart dimmer to include it in the network. +3. Once your controller has confirmed that the smart switch has been included, refresh the Z-Wave network to optimize performance. + + 1. Follow the instructions for you Z-Wave certified controller to exclude a device from the Z-Wave network. +2. Once the controller is ready to exclude your device, press and release the manual/program button on the smart switch to exclude it from the network. + + 28169/ZW4103 + 1. If plugged in, unplug the switch from the receptacle. +2. Press and hold the top button for at least 3 seconds while you plug the switch into a receptacle. Note: this should only be used in the event your network’s primary controller is missing or otherwise inoperable. + + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2533/Binder1.pdf U.S. / Canada / Mexico Plug-in Smart Switch (Single Plug) Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1435/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1805/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2533/xml diff --git a/config/ge/46201-switch.xml b/config/ge/46201-switch.xml new file mode 100644 index 0000000000..3d6ebc182e --- /dev/null +++ b/config/ge/46201-switch.xml @@ -0,0 +1,44 @@ + + + http://www.openzwave.com/device-database/0063:3135:4952 + images/ge/46201-switch.png + https://products.z-wavealliance.org/products/3317/ + 1. Follow the instructions for your Z-Wave certified controller to exclude a device from the Z-Wave network. +2. Once the controller is ready to exclude your device, press and release the top button of the wireless smart switch (rocker) to exclude it from the network. + 14291/46201/ZW4008 + In-Wall Smart Switch with QuickFit and SimpleWire enhancements. Revolutionary QuickFit design features a housing depth that is up to 20 percent smaller than the previous Z-Wave models. This reduced size coupled with the elimination of heat taps provides a better fit in older style boxes and multi-gang configurations. SimpleWire technology allows line and load to automatically be configured with auto-sensing line-load terminals. All of this is coupled with Z-Wave S2 and Smart Start allows for effortless installation while being safer than ever! + 1. Quickly press ON (Top) button 3 times then immediately press the OFF (Bottom) button 3 times. The LED will flash ON/OFF 5 times when completed successfully. +2. Please use this reset procedure only when the primary controller is missing or inoperable. + U.S. / Canada / Mexico + In-Wall Smart Switch + https://products.z-wavealliance.org/ProductManual/File?folder=&filename=MarketCertificationFiles/3317/46201%20Binder.pdf + 1. Follow the instructions for your Z-Wave certified controller to include a device to the Z-Wave network. +2. Once the controller is ready to include your device, press and release the top or bottom of the wireless smart switch(rocker) to include it in the network. +3. Once your controller has confirmed that the device has been included, refresh the Z-Wave network to optimize performance. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3317/xml + + + + + Sets when the LED on the switch is lit. + + + + + + + Default - normal exclusion + Active - perform a series of button presses to help eliminate accidental exclusion + + + + + + + + + + + + diff --git a/config/ge/hinge-pin.xml b/config/ge/hinge-pin.xml index 6005c0cad8..e9eb770005 100644 --- a/config/ge/hinge-pin.xml +++ b/config/ge/hinge-pin.xml @@ -1,12 +1,33 @@ - - - - - - - - - - - + + + http://www.openzwave.com/device-database/0063:3032:4953 + images/ge/hinge-pin.png + https://products.z-wavealliance.org/products/1800/ + 32563 / ZW4001 + U.S. / Canada / Mexico + You may wish to reset all of your Hinge Pin Smart Door Sensor's settings to their factory defaults. To do this, press the program button 10 times within 6 seconds. If your Door Sensor has been successfully reset, its LED light will blink for 3 seconds. +This should only be used in the event your network’s primary controller is missing or otherwise inoperable. + 1. Follow the instructions for your Z-Wave certified controller to exclude a device from the Z-Wave network. +2. Once the controller is ready to exclude your device, press and release the manual/program button on the Hinge Pin Smart Door Sensor to exclude it from the network. + Hinge Pin Smart Door Sensor + Transform any home into a smart home with the GE Hinge Pin Smart Door Sensor. This Smart Door Sensor is universal to fit any hinge size and is also reversible to allow it to work on a right or left opening door. With the adjustable zero pin position this will allow you to easily adjust for molding and when the sensor triggers. With the quick and easy installation, this sensor will notify you of when people enter or exit your home, you can also set the sensor to turn on a light or groups of lights. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1800/32563-1 EnFrSp QSG - Combined.pdf + 1. Press and hold the Z-Wave Button for 6 seconds. It will be wake up and send “Wake Up Notification CC “ to HUB. +2 .It will sleep after timeout for 10 seconds, or sleep right away when received the “Wake Up No More Information CC”. + + 1. Follow the instructions for your Z-Wave certified controller to include the device to the Z-Wave network. +2. Once the controller is ready to include your Hinge Pin Smart Door Sensor press and release the manual/program button on the smart switch to include it in the network. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1800/xml + + + + + + + + + + + diff --git a/config/ge/receptacle.xml b/config/ge/receptacle.xml index d3b7dbc71a..4117c3d3b7 100644 --- a/config/ge/receptacle.xml +++ b/config/ge/receptacle.xml @@ -1,23 +1,42 @@ - + http://www.openzwave.com/device-database/0063:3530:5252 images/ge/receptacle.png https://products.z-wavealliance.org/products/724/ http://www.jascoproducts.com/support/ - Duplex Receptacle + Transform any home into a smart home with the GE Z-Wave Tamper Resistant Smart Outlet. The GE Z-Wave Tamper Resistant Smart Outlet enables wireless control of on/off functions from the Z-Wave controlled outlet, and is compatible with incandescent, LED, Xenon, Halogen, fluorescent and compact fluorescent bulbs. The tamper resistant duplex receptacle includes a blue LED indicator light to easily locate the receptacle in a dark room. The receptacle replaces your current electrical outlet, uses your existing wiring and provides a Z-Wave enabled outlet for the lamp or appliance that you would like to control and a standard pass-through AC outlet for other electrical appliances. Take control of your home lighting with Jasco Z-Wave Smart Lighting Controls! + U.S. / Canada / Mexico http://www.ezzwave.com - Jasco Z-Wave Duplex Receptacle/Outlet + In-Wall Tamper Resistant Smart Outlet 45636/ZW1001 Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/657/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/724/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1195/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1212/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2732/xml https://products.z-wavealliance.org/products/1212/ U.S. / Canada / Mexico 45705 + https://products.z-wavealliance.org/products/2732/ + 1. Follow the instructions for your Z-Wave certified controller to +remove a device from the Z-Wave network. +2. Once the controller is ready to remove your device, press and +release the manual/program button to remove it from the +network. + 1. Follow the instructions for your Z-Wave certified +controller to add a device to the Z-Wave network. +2. Once the controller is ready to add your device, press and +release the Program Button to add it in the network. + U.S. / Canada / Mexico + Press the button 3 times, then press and hold the button for at least 3 +seconds. The LED will blink 5 times to confirm. +NOTE: This should only be used in the event your network’s primary +controller is missing or otherwise inoperable + 14288/ZW1002 + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2732/14288 QSG v1.pdf diff --git a/config/ge/ze26i.xml b/config/ge/ze26i.xml index 52f1c417d4..29cf64d59e 100644 --- a/config/ge/ze26i.xml +++ b/config/ge/ze26i.xml @@ -1,21 +1,62 @@ - - - + + + http://www.openzwave.com/device-database/0063:3031:4C42 + images/ge/ze26i.png + https://products.z-wavealliance.org/products/2528/ + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2528/39723 EnFrSp QSG v2..pdf + Smart LED light bulb with Z-Wave radio. +- Control lights remotely and save energy +- Compatible with smart home systems supporting Z-Wave +- 60 Watt equivalent light (750 lumens) +- Consumes only 9 watts of power +- 2700K soft light with frosted glass +- Instant ON and fully dimmable +- Functions as a Z-Wave signal repeater +- Very simple to include in your network +- Z-Wave Plus certified + + 1. Turn off power to the light bulb socket +2. Follow the network controller instruction to place your network controller into exclusion mode to remove the dt light bulb from the network. +3. After being prompted by the network controller, turn On power to the light bulb. If successful, the LED light bulb will flash twice to indicate successful exclusion. + + + U.S. / Canada / Mexico + 1. Turn Off power to the light bulb socket +2. Screw in the light bulb +3. Place your network controller into inclusion mode by following the controller manufacturer's instructions +4. Turn On power to the light bulb. If successful, the LED light bulb will flash twice to indicate successful inclusion. +5. If the controller/gateway shows it was a fail, repeat the procedure. + +Note: If Inclusion still fails after the 2nd attempt, you need to first RESET the dt Smart Bulb before repeating the above steps. + + 39723 + Z-Wave LED Light Bulb + You may manually reset the light bulb as follows: +1. Flick the wall switch “OFF-ON” 4 times within 4 seconds. +2. The dt Smart Bulb will flash twice after Reset is successful. + +Use this procedure only in the event that the network primary controller is lost or otherwise inoperable. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1942/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2528/xml + + + - + You may select the dim level whenever the light is turned back ON to be either full brightness (100% dim level) or be the same as the last dim setting when the light is ON by flicking the wall switch - + You may change the dimming step level when you adjust the brightness by your controller/gateway. When the value is low, dimming/brightening is gradual. When the value is high, dimming/brightening is rapid. - + You may change the dimming speed quicker or slower. When the value is low, the step timing is quick. @@ -26,7 +67,7 @@ - + diff --git a/config/ge/zw6302.xml b/config/ge/zw6302.xml index cf039130f2..37ac5626d7 100644 --- a/config/ge/zw6302.xml +++ b/config/ge/zw6302.xml @@ -1,39 +1,68 @@ - - - - - - PIR Sensitivity Setting - - - - - - + + + PIR Sensitivity Setting + + + + + + 1 to 60 => 1 min to 60 min. 255 => 5 seconds. - - - Motion Sensor will send out - - - - - - Enable or Disable the LED indication when PIR is triggered - - - - - - - - - - + + + Motion Sensor will send out + + + + + + Enable or Disable the LED indication when PIR is triggered + + + + + + + + + + diff --git a/config/gr/gr-302n.xml b/config/gr/gr-302n.xml new file mode 100644 index 0000000000..f1257664fd --- /dev/null +++ b/config/gr/gr-302n.xml @@ -0,0 +1,22 @@ + + + http://www.openzwave.com/device-database/0152:0003:0500 + images/gr/gr-302n.png + https://products.z-wavealliance.org/products/1722/ + PIR Sensor + Press the button unlock and lock-unlock 1 time it will be wake up 10 seconds. + GR-302N + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1722/PIR Sensor_UM.pdf + U.S. / Canada / Mexico + Press the button unlock and lock-unlock 6 times the device will send the reset notification to the list node in the group 1 and erases the device memory. +Use this procedure only in the event that the network primary controller is missing or otherwise inoperable. + + Please press the Z-Wave button in the pir sensor when the Z-Wave controller sends the instructions for inclusion, Press the Button: unlock and lock-unlock 1 time will send the NIF + This PIR motion sensor can association lighting switch , until leave the detect area. This PIR have support power supply and you don't replace the battery anymore. + Please press the Z-Wave button in the pir sensor when the Z-Wave controller sends the instructions for exclusion, Times to Press the Button: unlock and lock-unlock 1 time will send the NIF + + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1722/xml + + + diff --git a/config/gr/gr105n.xml b/config/gr/gr105n.xml index a17f16ebc3..105903fc97 100644 --- a/config/gr/gr105n.xml +++ b/config/gr/gr105n.xml @@ -1,11 +1,37 @@ - - - - - - - - - - + + + http://www.openzwave.com/device-database/0152:0512:0003 + images/gr/gr105n.png + https://products.z-wavealliance.org/products/2648/ + 1. Follow the instructions for your Z-Wave certified Controller to enter exclusion mode. +2. When prompted, press the “open/close” button on the Shut-Off quickly 3 times in a row. + The Dome™ Home Automation DMWV1 Water Main Shut-off is designed to fit over existing ¼ turn ball-valves for pipes sized up to 1½ inch. No professional plumbing contractor is required- it can be installed by a homeowner with just a screwdriver. This device requires a Z-Wave Certified hub for operation. When configured with a Water Leak Sensor, the Water Main Shut-off can automatically cut off the supply to limit the damage. You can also remotely control the valve position using your smarthome system mobile app. Extra-long Z-Wave wireless range (up to 150 ft) allows you to place it where it’s needed without worrying if the signal is reaching your Z-Wave Hub. Also functions as Z-Wave signal extender. Dome™ DMWV1 Water Main Shut-off comes with a 1-year limited warranty. Measurements in inches: 2.5 x 3.5 x 6. Dome™ Home Automation Z-Wave devices give your family peace of mind and security you can count on. With Dome™, you’re always connected and always covered. + +• Installs over existing valve without need of a plumber using just a screw driver. Works with ¼ turn ball-valves on pipes sized up to 1½ inch +• Open/Close valve control allowing for automatic water shut-off when leaks are detected as well as on demand control using your smarthome mobile app. +• Up to 150-foot range. Functions as Z-Wave signal extender +• Z-Wave Plus Certified. Requires a Z-Wave Certified Hub to operate + Water Main Shut-Off + Press and hold the open/close button for at least 10 seconds then release. The Shut-Off’s memory will be erased to factory settings. A flashing light indicates a successful factory reset. Beware that resetting your device will disconnect it from your system. Only do this if the controller is missing or otherwise unreachable! + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2648/Dome Water Main Shut-Off Advanced Manual.pdf + 1. For proper inclusion, bring the Water Main Shut-Off to the final location where it will be used. * +2. Follow the instructions for your Z-Wave controller to enter inclusion mode. +3 Make sure the Water Main Shut-Off is powered on, and when prompted by your controller, press the “open/close” button quickly 3 times in a row. The LED will stop blinking and stay on continuously upon successful inclusion. +*For non Z-Wave Plus networks, please consult the owner’s manual for your primary controller to determine the best method and location for adding the Water Main Shut-Off to your Z-Wave network. + U.S. / Canada / Mexico / South Africa / Australia / New Zealand + DMWV1 + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1537/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2647/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2648/xml + + + + + + + + + + diff --git a/config/graber/brz1.xml b/config/graber/brz1.xml index 7ce1663839..e74dcff218 100644 --- a/config/graber/brz1.xml +++ b/config/graber/brz1.xml @@ -1,15 +1,36 @@ - - + + + http://www.openzwave.com/device-database/026E:5A31:4252 + images/graber/brz1.png + https://products.z-wavealliance.org/products/1787/ + U.S. / Canada / Mexico + The Wakeup command class should be configured by a hub when the remote is joined to a Z-Wave network. A WAKE_UP_INTERVAL_SET command should configure the NodeID at a minimum. The Wakeup interval can be configured to any value from 6 minutes to 25 hours. Recommendation is to leave the interval at the default of 12 hours to maximize battery life. The remote will wake up every WakeUpInterval and send a WakeUp Notification command as well as a battery report to the NodeID assigned with the Interval Set command. The WakeUp Notification will be sent within a few minutes of power being applied to the remote and then once every Wake Up Interval. A Wakeup Interval Capabilities command will inform the hub of the default, minimum, maximum and step size of the Wake Up interval. + Enjoy the comfort, convenience and energy efficiency of beautiful custom motorized window treatments featuring Z-Wave protocol for easy integration. Lighting control has never been more simple. Window treatments can be automated using your favorite Z-Wave certified gateway or security system, or controlled by a remote control. Raise or lower the shades to control just the right amount of light, privacy and solar heat. Shades can be fully open, fully closed or anywhere in between, it’s up to you. In addition, some systems will also report back the state of the battery charge on battery operated versions. + Press and hold the button on the control for approximately 15 seconds (the LED will stop flashing when complete. + +"Please use this procedure only when the network primary controller is missing or otherwise inoperable." + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1787/Graber Virtual Cord Owner's Manual.pdf + BRZ1 + Basic Remote Control Z-Wave + 1. Press and release Twice on Control Programming button. (Tap 2x on prog button) + +2.Slave sends NIF + + 1. Press and release Three times on Control Programming button. (Tap 3x on prog button) + +2. Slave sends NIF + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1787/xml + + - - - + + - diff --git a/config/graber/csz1.xml b/config/graber/csz1.xml new file mode 100644 index 0000000000..c37869290b --- /dev/null +++ b/config/graber/csz1.xml @@ -0,0 +1,29 @@ + + + http://www.openzwave.com/device-database/026E:5A31:4353 + images/graber/csz1.png + https://products.z-wavealliance.org/products/1749/ + 1. Put Primary Controller into +Inclusion Mode + +2. Press and Hold Shade Programming Button for >2seconds + + U.S. / Canada / Mexico + The Wakeup command class should be configured by a hub when the remote is joined to a Z-Wave network. A WAKE_UP_INTERVAL_SET command should configure the NodeID at a minimum. The Wakeup interval can be configured to any value from 6 minutes to 25 hours. Recommendation is to leave the interval at the default of 12 hours to maximize battery life. The remote will wake up every WakeUpInterval and send a WakeUp Notification command as well as a battery report to the NodeID assigned with the Interval Set command. The WakeUp Notification will be sent within a few minutes of power being applied to the remote and then once every Wake Up Interval. A Wakeup Interval Capabilities command will inform the hub of the default, minimum, maximum and step size of the Wake Up interval. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1749/Graber Virtual Cord Owner's Manual 0002.pdf + Please use this procedure only when the network primary controller is missing or otherwise inoperable + +Press and hold the button on the shade for approximately 15 seconds (the LED will stop flashing when complete) + Enjoy the comfort, convenience and energy efficiency of beautiful custom motorized window treatments featuring Z-Wave protocol for easy integration. Lighting control has never been more simple. Window treatments can be automated using your favorite Z-Wave certified gateway or security system, or controlled by a remote control. Raise or lower the shades to control just the right amount of light, privacy and solar heat. Shades can be fully open, fully closed or anywhere in between, it’s up to you. In addition, some systems will also report back the state of the battery charge on battery operated versions. + Cellular Shade Radio Z-Wave + 1. Put Primary Controller into +Exclusion Mode + +2. Press and Hold Shade Programming Button for >2seconds + + CSZ1 + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1749/xml + + + diff --git a/config/graber/rsz1.xml b/config/graber/rsz1.xml new file mode 100644 index 0000000000..f0b9b381a9 --- /dev/null +++ b/config/graber/rsz1.xml @@ -0,0 +1,29 @@ + + + http://www.openzwave.com/device-database/026E:5A31:5253 + images/graber/rsz1.png + https://products.z-wavealliance.org/products/1785/ + 1. Put Primary Controller into +Exclusion Mode + +2. Press and Hold Shade Programming Button for >2seconds + + Enjoy the comfort, convenience and energy efficiency of beautiful custom motorized window treatments featuring Z-Wave protocol for easy integration. Lighting control has never been more simple. Window treatments can be automated using your favorite Z-Wave certified gateway or security system, or controlled by a remote control. Raise or lower the shades to control just the right amount of light, privacy and solar heat. Shades can be fully open, fully closed or anywhere in between, it’s up to you. In addition, some systems will also report back the state of the battery charge on battery operated versions. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1785/Graber Virtual Cord Owner's Manual.pdf + Press and hold the button on the shade for approximately 15 seconds (the LED will stop flashing when complete). + +"Please use this procedure only when the network primary controller is missing or otherwise inoperable." + 1. Put Primary Controller into +Inclusion Mode + +2. Press and Hold Shade Programming Button for >2seconds + + Roller Shade Radio Z-Wave + RSZ1 + The Wakeup command class should be configured by a hub when the remote is joined to a Z-Wave network. A WAKE_UP_INTERVAL_SET command should configure the NodeID at a minimum. The Wakeup interval can be configured to any value from 6 minutes to 25 hours. Recommendation is to leave the interval at the default of 12 hours to maximize battery life. The remote will wake up every WakeUpInterval and send a WakeUp Notification command as well as a battery report to the NodeID assigned with the Interval Set command. The WakeUp Notification will be sent within a few minutes of power being applied to the remote and then once every Wake Up Interval. A Wakeup Interval Capabilities command will inform the hub of the default, minimum, maximum and step size of the Wake Up interval. + U.S. / Canada / Mexico + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1785/xml + + + diff --git a/config/graber/vcz1.xml b/config/graber/vcz1.xml index 16747c9710..b0ac72df3f 100644 --- a/config/graber/vcz1.xml +++ b/config/graber/vcz1.xml @@ -1,15 +1,38 @@ - - + + + http://www.openzwave.com/device-database/026E:5A31:5643 + images/graber/vcz1.png + https://products.z-wavealliance.org/products/1786/ + Virtual Cord Remote Control Z-Wave + VCZ1 + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1786/Graber Virtual Cord Owner's Manual.pdf + Enjoy the comfort, convenience and energy efficiency of beautiful custom motorized window treatments featuring Z-Wave protocol for easy integration. Lighting control has never been more simple. Window treatments can be automated using your favorite Z-Wave certified gateway or security system, or controlled by a remote control. Raise or lower the shades to control just the right amount of light, privacy and solar heat. Shades can be fully open, fully closed or anywhere in between, it’s up to you. In addition, some systems will also report back the state of the battery charge on battery operated versions. + 1. Press and release Three times on Control Programming button. (Tap 3x on prog button) +2. Slave sends NIF + + + U.S. / Canada / Mexico + Press and hold the button on the control for approximately 15 seconds (the LED will stop flashing when complete. + +"Please use this procedure only when the network primary controller is missing or otherwise inoperable." + The Wakeup command class should be configured by a hub when the remote is joined to a Z-Wave network. A WAKE_UP_INTERVAL_SET command should configure the NodeID at a minimum. The Wakeup interval can be configured to any value from 6 minutes to 25 hours. Recommendation is to leave the interval at the default of 12 hours to maximize battery life. The remote will wake up every WakeUpInterval and send a WakeUp Notification command as well as a battery report to the NodeID assigned with the Interval Set command. The WakeUp Notification will be sent within a few minutes of power being applied to the remote and then once every Wake Up Interval. A Wakeup Interval Capabilities command will inform the hub of the default, minimum, maximum and step size of the Wake Up interval. + 1. Press and release Twice on Control Programming button. (Tap 2x on prog button) + +2.Slave sends NIF + + + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1786/xml + + - - - + + - diff --git a/config/guardtec/gkw2000d.xml b/config/guardtec/gkw2000d.xml new file mode 100644 index 0000000000..bddc203812 --- /dev/null +++ b/config/guardtec/gkw2000d.xml @@ -0,0 +1,52 @@ + + + GKW-2000D + The GKW-2000D is a secure electronic door lock + http://www.openzwave.com/device-database/037B:0001:0002 + http://gkw2000d.thekeywe.com + https://mykeywe.thekeywe.com/Home/Login + images/guardtec/gkw2000d.png + https://products.z-wavealliance.org/ProductManual/File?folder=&filename=MarketCertificationFiles/2905/GKW-2000DZ-WaveManual.pdf + press the [REG] button, enter the Master Pin (Default:1234) on the keypad followed by #88* + press the [REG] button, enter the Master Pin (Default:1234) on the keypad followed by #99* + press the [REG] button, enter the Master Pin (Default:1234) on the keypad followed by #5*2*[Master Pin]# + https://products.z-wavealliance.org/products/3060/ + https://products.z-wavealliance.org/products/3062/ + https://products.z-wavealliance.org/products/3030/ + https://products.z-wavealliance.org/products/3064/ + https://products.z-wavealliance.org/products/2905/ + https://products.z-wavealliance.org/products/3061/ + https://products.z-wavealliance.org/products/3063/ + https://products.z-wavealliance.org/products/3029/ + https://products.z-wavealliance.org/products/2993/ + Malaysia + Singapore + South Korea + Thailand + U.S. / Canada / Mexico + Brazil + Taiwan + Australia / New Zealand + CEPT (Europe) + + Refresh lock status when alarm message received + Initial Metadata import + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/config/hank/hkzw-dws01.xml b/config/hank/hkzw-dws01.xml index a03bc5c9e6..22ac7cd834 100644 --- a/config/hank/hkzw-dws01.xml +++ b/config/hank/hkzw-dws01.xml @@ -1,35 +1,68 @@ - - - - - - Enable/Disable BASIC SET command - - - - - + + + Enable/Disable BASIC SET command + + + + + Send BASIC SET VALUE = 255 to nodes associated with group 2 when door/window is opened. Send BASIC SET VALUE = 0 to nodes associated with group 2 when door/window is closed. - - - - - The value here defines the low battery - - - - - - - - - - - + + + + + The value here defines the low battery + + + + + + + + + diff --git a/config/hank/hkzw-fld01.xml b/config/hank/hkzw-fld01.xml index f0a2442989..3f63ef1d78 100644 --- a/config/hank/hkzw-fld01.xml +++ b/config/hank/hkzw-fld01.xml @@ -1,66 +1,111 @@ - - - - - - The Flood sensor can send BASIC SET command to nodes associated with group 2. - - - - - The Flood sensor can reverse its value of BASIC SET when flooding is triggered. - - - - - - - - - - - - - - - - - - - - US: -670 - 2570 (-67 - 257 F) + + + The Flood sensor can send BASIC SET command to nodes associated with group 2. + + + + + The Flood sensor can reverse its value of BASIC SET when flooding is triggered. + + + + + + + + + + + + + + + + + + + + US: -670 - 2570 (-67 - 257 F) Other: -550 - 1250 (-55 - 125 C) - - - - - - - - US: -670 - 2570 (-67 - 257 F) + + + + + + + + US: -670 - 2570 (-67 - 257 F) Other: -550 - 1250 (-55 - 125 C) - - - - - - - - This parameter defines a battery level as the "low battery". - - - - - - - - - - - + + + + + + + + This parameter defines a battery level as the "low battery". + + + + + + + + + diff --git a/config/hank/hkzw-ms01.xml b/config/hank/hkzw-ms01.xml index d3c4bba588..3217bd9d73 100644 --- a/config/hank/hkzw-ms01.xml +++ b/config/hank/hkzw-ms01.xml @@ -1,83 +1,111 @@ - - - - - - + + + Level 0 to 8. 0 Disabled. - - - Insensitivity - - - Enable/Disable BASIC SET command - - - - - + + + Insensitivity + + + Enable/Disable BASIC SET command + + + + + Send BASIC SET VALUE = 255 to nodes associated with group 2 when door/window is opened. Send BASIC SET VALUE = 0 to nodes associated with group 2 when door/window is closed. - - - - - The low level from 10% to 50% - - - - - - - - The interval of sending battery report - - - The interval of sending temperature report - - - The interval of sending Humidity report - - - The interval of sending luminance report - - - The change in battery level resulting in battery report being sent to the main controller. - - - + + + + + The low level from 10% to 50% + + + + + + + + The interval of sending battery report + + + The interval of sending temperature report + + + The interval of sending Humidity report + + + The interval of sending luminance report + + + The change in battery level resulting in battery report being sent to the main controller. + + + 0 reports are not sent. 1 to 255 the change in temperature level resulting in temperature report being sent to the main controller. - - - + + + 0 reports are not sent. 1 to 100 the change in humidity level resulting in humidity report being sent to the main controller. - - - + + + 0 Reports are not sent. 1 to 65535 the change in luminance level resulting in luminance report being sent to the main controller. - - - - - - - - - - - - + + + + + + + + + diff --git a/config/hank/hkzw-ms02-200.xml b/config/hank/hkzw-ms02-200.xml index 932364d891..dcd98042ab 100644 --- a/config/hank/hkzw-ms02-200.xml +++ b/config/hank/hkzw-ms02-200.xml @@ -1,54 +1,96 @@ - - - - - - + + + Level 1 to 8. The higher the value, the more sensitive the PIR sensor. 0 Disabled. - - - Enable/disable basic set command - - - - - + + + Enable/disable basic set command + + + + + Send basic set value = 255 to nodes associated with group 2 when motion alarm is triggered. Send basic set value = 0 to nodes associated with group 2 when motion alarm is canceled. Send basic set value = 0 to nodes associated with group 2 when motion alarm is triggered. Send basic set value = 255 to nodes associated with group 2 when motion alarm is canceled. - - - - - when the value is 0, the product will not sends a vibration alarm after moving or shaking; when the value is 1, the product will sends a vibration alarm after moving or shaking - - - - - + + + + + when the value is 0, the product will not sends a vibration alarm after moving or shaking; when the value is 1, the product will sends a vibration alarm after moving or shaking + + + + + 0 Reports are not sent. 1 to 65535 the change in luminance level resulting in luminance report being sent to the main controller. - - - The low level from 10% to 50% - - - - - - - - - - - - + + + The low level from 10% to 50% + + + + + + + + + diff --git a/config/hank/hkzw-ms02-300.xml b/config/hank/hkzw-ms02-300.xml index 932364d891..71647ee3f8 100644 --- a/config/hank/hkzw-ms02-300.xml +++ b/config/hank/hkzw-ms02-300.xml @@ -1,54 +1,97 @@ - - - - - + + + Level 1 to 8. The higher the value, the more sensitive the PIR sensor. 0 Disabled. - - - Enable/disable basic set command - - - - - + + + Enable/disable basic set command + + + + + Send basic set value = 255 to nodes associated with group 2 when motion alarm is triggered. Send basic set value = 0 to nodes associated with group 2 when motion alarm is canceled. Send basic set value = 0 to nodes associated with group 2 when motion alarm is triggered. Send basic set value = 255 to nodes associated with group 2 when motion alarm is canceled. - - - - - when the value is 0, the product will not sends a vibration alarm after moving or shaking; when the value is 1, the product will sends a vibration alarm after moving or shaking - - - - - + + + + + when the value is 0, the product will not sends a vibration alarm after moving or shaking; when the value is 1, the product will sends a vibration alarm after moving or shaking + + + + + 0 Reports are not sent. 1 to 65535 the change in luminance level resulting in luminance report being sent to the main controller. - - - The low level from 10% to 50% - - - - - - - - - - - - + + + The low level from 10% to 50% + + + + + + + + + diff --git a/config/hank/hkzw-rgb01.xml b/config/hank/hkzw-rgb01.xml index f3cf479709..c0422adbe9 100644 --- a/config/hank/hkzw-rgb01.xml +++ b/config/hank/hkzw-rgb01.xml @@ -1,47 +1,96 @@ - - + + + http://www.openzwave.com/device-database/0208:0004:0100 + images/hank/hkzw-rgb01.png + https://products.z-wavealliance.org/products/1897/ + There are two ways to reset the RGB BULB. One is that removing +RGB BULB from the Z-Wave network, the other is that using the +configuration command class. + RGB Bulb is a smart bulb enables Z-Wave remote command and control (on/off/dim). It has over 16,000,000 colors, you can choose its color according to your favour. + To remove the RGB BULB from the Z-Wave network: +(1) Screw in the RGB BULB. +(2) Set the Z-Wave network main controller into excluding mode +(see Z-Wave controller operating manual). +(3) Toggle the wall switch off and on 3 times quickly(within 3 +and the final ending position of the wall switch must be on), +if the exclusion is successful, the RGB BULB will blink fast in +orange for less than 5 seconds and then keep on for 3 seconds. +RGB BULB will keep on warm white after the exclusion procedure +is finished. + RGB Bulb + To include RGB BULB into a Z-Wave network as a non-security device: +(1) Make sure the power supply is disconnected and the RGB BULB is +located within a direct Z-Wave network's main controller +communication range. +(2) Set the Z-Wave network main controller into learning mode +(see Z-Wave network controller operating manual). +(3) Insert the RGB BULB into a lamp-socket and then power on. +(4) Auto-inclusion will be activated. If the inclusion is successful, the +RGB BULB will blink fast in blue for less than 5 seconds and then +keep on for 3 seconds. RGB BULB will keep on in the color before it +is included into the Z-Wave network after the inclusion procedure +is finished. +To include RGB BULB into a Z-Wave network as a security device: +(1) Screw in the RGB BULB. +(2) Set the Z-Wave network main controller into learning mode +(see Z-Wave network controller operating manual). +(3) Toggle the wall switch off and on 3 times quickly (within 3 seconds +and the final ending position of the wall switch must be on). +(4) If the inclusion is successful, the RGB BULB will blink fast in green +for less than 5 seconds and then keep on 3 seconds. RGB BULB will +keep on in the color before it is included into the Z-Wave network +after the inclusion procedure is finished. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1976/HKZW-RGB01 Manual.pdf + HKZW-RGB01 + CEPT (Europe) + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1897/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1976/xml + + https://products.z-wavealliance.org/products/1976/ + HKZW-RGB01 + U.S. / Canada / Mexico + - + Define how the RGB BULB will react after the power supply is back on. - - - + + + - + RGB BULB can send notifications to associated device - - - + + + - + Enable/disable the function of using wall switch to turn on/off RGB BULB - - + + - + RGB BULB can blink or cyclic/random change color automatically at set intervals. - - - - - - - - + + + + + + + + - + RGB BULB will exclude from the Z-Wave network with this particular command - + - - diff --git a/config/hank/hkzw-so01-smartplug.xml b/config/hank/hkzw-so01-smartplug.xml index 144842439c..4d85bb135e 100644 --- a/config/hank/hkzw-so01-smartplug.xml +++ b/config/hank/hkzw-so01-smartplug.xml @@ -1,86 +1,99 @@ - - - - - - Smart Plug keep detecting the load power, once the current exceeds 16.5a for more than 5s, smart plug's relay will turn off - - - - - Define how the plug reacts after the power supply is back on. + + + Smart Plug keep detecting the load power, once the current exceeds 16.5a for more than 5s, smart plug's relay will turn off + + + + + Define how the plug reacts after the power supply is back on. 0 - Smart Plug memorizes its state after a power failure. 1 - Smart Plug does not memorize its state after a power failure. Connected device will be on after the power supply is reconnected. 2 - Smart Plug does not memorize its state after a power failure. Connected device will be off after the power supply is reconnected. - - - - - - + + + + + + Smart Plug can send notifications to association device(Group Lifeline) when state of smart plug's load change 0 - The function is disabled 1 - Send Basic report. 2 - Send Basic report only when Load condition is not changed by Z-WAVE Command - - - - - - After smart plug being included into a Z-Wave network, the LED in the device will indicator the state of load. + + + + + + After smart plug being included into a Z-Wave network, the LED in the device will indicator the state of load. 0 - The LED will follow the status(on/off) of its load 1 - When the state of Switch's load changed, THe LED will follow the status(on/off) of its load, but the red LED will turn off after 5 seconds if there is no any switch action. - - - - - + + + + + Power threshold to be interpereted, when the change value of load power exceeds the setting threshold, the smart plug will send meter report to association device(Group Lifeline) - - - + + + Power percentage threshold to be interpreted, when change value of the load power exceeds the setting threshold, the smart plug will send meter report to association device(Group Lifeline). - - - + + + The interval of sending power report to association device(Group Lifeline). 0 - The function is disabled. - - - + + + The interval of sending power report to association device(Group Lifeline). 0 - The function is disabled. - - - + + + The interval of sending voltage report to association device(Group Lifeline). 0 - The function is disabled. - - - + + + The interval of sending electricity report to association device(Group Lifeline). 0 - The function is disabled. - - - - - - - - - - + + + + + + + + diff --git a/config/hank/hkzw-so03.xml b/config/hank/hkzw-so03.xml index 0fee9a7b3e..657e766e7c 100644 --- a/config/hank/hkzw-so03.xml +++ b/config/hank/hkzw-so03.xml @@ -1,56 +1,83 @@ - - + + + http://www.openzwave.com/device-database/0208:000A:0101 + images/hank/hkzw-so03.png + https://products.z-wavealliance.org/products/1854/ + 1) Insert the Plug into a socket. +2) Set the Z-Wave network controller into the exclusion mode (see Z-Wave controller operating manual). +3) Triple click the Z button. +4) RGB LED indicator will blink orange till the removing process is completed, than the indicator will keep orange for 3 seconds. + + U.S. / Canada / Mexico + Smart Plug + 1) Insert the Plug into a socket, +2) Press and hold the Z button for more than 20 seconds, +3) If holding time more than 20seconds, the RGB LED indicator will keep yellow for 2 seconds, which means resetting is complete. + Use this procedure only in the event that the network primary controller is missing or otherwise inoperable. + + Smart plug is a Z-Wave Switch plugin module specifically used to enable Z-Wave command and control (on/off) of any plug-in tool. It can report wattage consumption or kWh energy usage. +Smart Plug is also a security Z-Wave device and supports the Over The Air (OTA) feature for the product’s firmware upgrade . + + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1854/HKZW-SO03_manual.pdf + HKZW-SO03 + 1) Connect the power supply. +2) Set the Z-Wave network main controller into inclusion mode (see Z-Wave network controller operating manual). +3) Triple click the Z-button or power up the device , RGB LED indicator should blink fast in blue. +4) Smart Plug should be recognized and included into the Z-Wave network. + + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1854/xml + + - + turns relay off once voltage exceeds 16.5A for over 5 secs if enabled - - + + - + Recovery state for power failure - - - + + + - + Send notifications to associated devices - - - + + + - + LED Indicator Control - - + + - + Minimum change in watts to report - + Minimum percentage change to report - + How often to report power consumption (W) in secs - + How often to report energy usage (KWH) in secs - + How often to report voltage (V) in secs - + How often to report electrical current (A) in secs - - + - diff --git a/config/hank/hkzw-so05-smartplug.xml b/config/hank/hkzw-so05-smartplug.xml index 95ef382a32..b773f43bd5 100644 --- a/config/hank/hkzw-so05-smartplug.xml +++ b/config/hank/hkzw-so05-smartplug.xml @@ -1,87 +1,114 @@ - - - - - - - Smart Plug keep detecting the load power, once the current exceeds 10.5a for more than 5s, smart plug's relay will turn off - - - - - Define how the plug reacts after the power supply is back on. - 0 - Smart Plug memorizes its state after a power failure. - 1 - Smart Plug does not memorize its state after a power failure. Connected device will be on after the power supply is reconnected. - 2 - Smart Plug does not memorize its state after a power failure. Connected device will be off after the power supply is reconnected. - - - - - - - - Smart Plug can send notifications to association device(Group Lifeline) when state of smart plug's load change - 0 - The function is disabled - 1 - Send Basic report. - 2 - Send Basic report only when Load condition is not changed by Z-WAVE Command - - - - - - - After smart plug being included into a Z-Wave network, the LED in the device will indicator the state of load. - 0 - The LED will follow the status(on/off) of its load - 1 - When the state of Switch's load changed, The LED will follow the status(on/off) of its load, but the red LED will turn off after 5 seconds if there is no any switch action. - - - - - - - Power threshold to be interpereted, when the change value of load power exceeds the setting threshold, the smart plug will send meter report to association device(Group Lifeline) - - - - - Power percentage threshold to be interpreted, when change value of the load power exceeds the setting threshold, the smart plug will send meter report to association device(Group Lifeline). - - - - - The interval of sending power report to association device(Group Lifeline). - 0 - The function is disabled. - - - - - The interval of sending power report to association device(Group Lifeline). - 0 - The function is disabled. - - - - - The interval of sending voltage report to association device(Group Lifeline). - 0 - The function is disabled. - - - - - The interval of sending electricity report to association device(Group Lifeline). - 0 - The function is disabled. - - - - - - - - - - - - + + + http://www.openzwave.com/device-database/0208:000A:0100 + images/hank/hkzw-so05-smartplug.png + https://products.z-wavealliance.org/products/1891/ + Smart Plug + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1891/HKZW-SO05 Manual.pdf + CEPT (Europe) + 1) Insert the Plug into a socket, +2) Press and hold the Z button for more than 20 seconds, +3) If holding time more than 20seconds, the RGB LED indicator will keep yellow for 2 seconds, which means resetting is completed. +Use this procedure only in the event that the network primary controller is missing or otherwise inoperable. + + 1) Connect the power supply. +2) Set the Z-Wave network main controller into inclusion mode (see Z-Wave network controller operating manual). +3) Triple click the Z-button or power up the device , RGB LED indicator should blink fast in blue. +4) Smart Plug should be recognized and included into the Z-Wave network. + + HKZW-SO05 + Smart plug is a Z-Wave Switch plugin module specifically used to enable Z-Wave command and control (on/off) of any plug-in tool. It can report wattage consumption or kWh energy usage, and can indicate the power level with a RGB LED. +Smart Plug is also a security Z-Wave device and supports the Over The Air (OTA) feature for the product’s firmware upgrade . + + 1) Insert the Plug into a socket. +2) Set the Z-Wave network controller into the exclusion mode (see Z-Wave controller operating manual). +3) Triple click the Z button. +4) RGB LED indicator will blink orange till the removing process is completed, than the indicator will keep orange for 3 seconds. + + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1891/xml + + + + + + + Smart Plug keep detecting the load power, once the current exceeds 10.5a for more than 5s, smart plug's relay will turn off + + + + + Define how the plug reacts after the power supply is back on. + 0 - Smart Plug memorizes its state after a power failure. + 1 - Smart Plug does not memorize its state after a power failure. Connected device will be on after the power supply is reconnected. + 2 - Smart Plug does not memorize its state after a power failure. Connected device will be off after the power supply is reconnected. + + + + + + + + Smart Plug can send notifications to association device(Group Lifeline) when state of smart plug's load change + 0 - The function is disabled + 1 - Send Basic report. + 2 - Send Basic report only when Load condition is not changed by Z-WAVE Command + + + + + + + After smart plug being included into a Z-Wave network, the LED in the device will indicator the state of load. + 0 - The LED will follow the status(on/off) of its load + 1 - When the state of Switch's load changed, The LED will follow the status(on/off) of its load, but the red LED will turn off after 5 seconds if there is no any switch action. + + + + + + + Power threshold to be interpereted, when the change value of load power exceeds the setting threshold, the smart plug will send meter report to association device(Group Lifeline) + + + + + Power percentage threshold to be interpreted, when change value of the load power exceeds the setting threshold, the smart plug will send meter report to association device(Group Lifeline). + + + + + The interval of sending power report to association device(Group Lifeline). + 0 - The function is disabled. + + + + + The interval of sending power report to association device(Group Lifeline). + 0 - The function is disabled. + + + + + The interval of sending voltage report to association device(Group Lifeline). + 0 - The function is disabled. + + + + + The interval of sending electricity report to association device(Group Lifeline). + 0 - The function is disabled. + + + + + + + + + + diff --git a/config/hank/scenecontroller1.xml b/config/hank/scenecontroller1.xml index 900273d88b..d51df3676a 100644 --- a/config/hank/scenecontroller1.xml +++ b/config/hank/scenecontroller1.xml @@ -1,26 +1,63 @@ - - - - - - Lock/unlock all configuration parameters - - - - - - - - - - - - - - + + + Lock/unlock all configuration parameters + + + + + + + + + + + + diff --git a/config/hank/scenecontroller4.xml b/config/hank/scenecontroller4.xml index 41d02477bd..8a4f737a87 100644 --- a/config/hank/scenecontroller4.xml +++ b/config/hank/scenecontroller4.xml @@ -1,32 +1,73 @@ - - - - - - Lock/unlock all configuration parameters - - - - - - - - - - - - - - - - - - - - + + + Lock/unlock all configuration parameters + + + + + + + + + + + + + + + + + + diff --git a/config/heiman/HS1CA-Z.xml b/config/heiman/HS1CA-Z.xml index f23f767db1..950c205ed9 100644 --- a/config/heiman/HS1CA-Z.xml +++ b/config/heiman/HS1CA-Z.xml @@ -1,16 +1,40 @@ - - - - - - - - - - - +--> + + http://www.openzwave.com/device-database/0260:1000:8005 + images/zipato/HS1CA-Z.png + https://products.z-wavealliance.org/products/2699/ + Zipato Carbon Monoxide Sensor (Z-Wave) is designed to give early warning of higher carbon monoxide level, based on Z-Wave technology. Z-Wave is a wireless communication protocol designed for remote control of appliances in residential automated homes and light commercial environments. + Press button on sensor 3 times within 1.5s, Green LED will blink 3 times within 1 second. + +If Inclusion Process is successful, Green led will turn off. + Wake up Notification is transmitted every 24 hours by default. +Wake up Notification is transmitted after Notification Report is Transmitted + CEPT (Europe) + Remove battery. +Insert battery while holding button on sensor. +Please use this procedure only when the network primary +controller is missing or otherwise inoperable. + Press button on sensor 3 times within 1.5s, Green LED will blink 3 times within 1 second. + +If Inclusion Process is successful, Green led will turn off. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2699/hm-hs1ca-z-Smart-Carbon-Monoxide-Sensor-Z-Wave-User-Manual-1.0.pdf + Zipato Carbon Monoxide Sensor + hm-hs1ca-z.eu + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1940/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2699/xml + + + + + + + + + + + diff --git a/config/heiman/HS1CG-Z.xml b/config/heiman/HS1CG-Z.xml index c45f3989e5..09858d990c 100644 --- a/config/heiman/HS1CG-Z.xml +++ b/config/heiman/HS1CG-Z.xml @@ -1,15 +1,35 @@ - - - - - - - - - - +--> + + http://www.openzwave.com/device-database/0260:1000:8003 + images/zipato/HS1CG-Z.png + https://products.z-wavealliance.org/products/2473/ + Smart Combustible Gas Sensor in a convenient wall plug form factor for easy installation. +Built-in audio and led notification systems for gas leakage detection events. + hm-hs1cg-z.eu + - Press the Net_Button 3 times within 1.5s +- If remove Process is successful, Green LED is Blinking 6 times, then turn on + CEPT (Europe) + -Long press Net_Button at least 10 seconds in the device. +-Device Reset Locally notification is Transmitted. +Please use this procedure only when the network primary controller is missing or otherwise inoperable. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2473/ZipatoSmartCombustibleGasSensorManual.pdf + Smart Combustible Gas Sensor + - Press the Net_Button 3 times within 1.5s, Green LED is Blinking 3 times within 1 second. +- If add Process is successful, Green LED will turn on. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2070/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2473/xml + + + + + + + + + + diff --git a/config/heiman/HS1DS-Z.xml b/config/heiman/HS1DS-Z.xml index f9eb949e5b..f6e8823a21 100644 --- a/config/heiman/HS1DS-Z.xml +++ b/config/heiman/HS1DS-Z.xml @@ -1,18 +1,44 @@ - - - - - - - - - - - - +--> + + http://www.openzwave.com/device-database/0260:0168:0168 + images/heiman/HS1DS-Z.png + https://products.z-wavealliance.org/products/3016/ + - Click [Add] icon in Z-Wave Controller . +- Press the Networking_Button 3 times within 1.5s, Green LED is Blinking 4 times within 1 second. +- If Inclusion Process is successful, Green led will turn off. + + - Wake up Notification is transmitted every 24 hours by default. +- Wake up Notification is transmitted after Notification Report is Transmitted + - Click [Remove] icon in Z-Wave Controller +- Press the Networking_Button 3 times within 1.5s +- If Exclusion Process is successful, Green led is Blinking 6 times, then turn off. + + Smart Door Sensor + Long press Networking_Button while installing batteries in the Device +-Device Reset Locally notification is Transmitted +-Green LED Turns off after 2 seconds. +Please use this procedure only when the network primary controller is missing or otherwise inoperable. + + The smart door sensor adopts Z-Wave protocol, it can detect the open or close state of door or window. when the door sensor is armed, when the door or window is opened, it will send alarm notifications to gateway immediately. + CEPT (Europe) + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3016/HS3DS-Z-S2documentation.pdf + HS3DS-Z + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1797/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3016/xml + + + + + + + + + + + + - diff --git a/config/heiman/HS1HT-Z.xml b/config/heiman/HS1HT-Z.xml index 02e2220bd0..d5bf8cda26 100644 --- a/config/heiman/HS1HT-Z.xml +++ b/config/heiman/HS1HT-Z.xml @@ -1,16 +1,39 @@ - - - - - - - - - - +--> + + http://www.openzwave.com/device-database/0260:1000:8007 + images/heiman/HS1HT-Z.png + https://products.z-wavealliance.org/products/3015/ + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3015/HS1HT-Z-S2documentation.pdf + - Click [Remove] icon in Z-Wave Controller. +- Press the Net_Button 3 times within 1.5s +- If Exclusion Process is successful, Green LED is Blinking 6 times, then turn off + + Smart Temperature & Humidity Sensor + - Click [Add] icon in Z-Wave Controller. +- Press the Net_Button 3 times within 1.5s, Green LED is Blinking 3 times within 1 second. +- If Inclusion Process is successful, Green LED will turn off. + + -Long press Net_Button at least 10 seconds in the product. +- Device Reset Locally notification is Transmitted. +Please use this procedure only when the network primary controller is missing or otherwise inoperable. + CEPT (Europe) + Wake up Notification is transmitted every 300 seconds by default. + The smart humidity and temperature sensor adopts Z-Wave protocol. It is used to detect humidity and temperature. When the humidity or temperature exceeds the alarm thresholds, it will send alarm notifications to gateway immediately. + HS1HT-Z + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2321/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3015/xml + + + + + + + + + + - diff --git a/config/heiman/HS1MS-Z.xml b/config/heiman/HS1MS-Z.xml index 360e66c51e..84c9969a03 100644 --- a/config/heiman/HS1MS-Z.xml +++ b/config/heiman/HS1MS-Z.xml @@ -1,16 +1,37 @@ - - - - - - - - - - +--> + + http://www.openzwave.com/device-database/0260:1000:8001 + images/heiman/HS1MS-Z.png + https://products.z-wavealliance.org/products/1801/ + CEPT (Europe) + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1801/HSIMS-Z.pdf + - Click [Remove] icon in Z-Wave PC Controller Program +- Press a Func_Button 3 times quickly in HS1MS-Z +- If Exclusion Process is successful, Green LED is Blinking 6 times, then turn off in HS1MS-Z + Smart Motion Sensor + The smart motion sensor is designed to detect motion indoors. When the smart motion sensor detects people or animals moving, it will report the information to the users mobile phone immediately. it is very easy to install, users should only paste the smart motion sensor on the wall, download the application and then connect the smart motion sensor to a smartphone via WiFi. Users will know the situation of their houses remotely. The battery life is more than 1 year and the battery is also replaceable. + - Wake up Notification is transmitted every 24 hours by default. +- Wake up Notification is transmitted after Notification Report is Transmitted + HS1MS-Z + - Click [Add] icon in Z-Wave PC Controller Program +- Press a Func_Button 3 time in HS1MS-Z (Motion Sensor), Green LED is Blinking 3 times within 1 second. +- If Inclusion Process is successful, Green LED will turn off. + Long press Func_Button while installing batteries in HS1MS-Z +- Device Reset Locally notification is Transmitted +- Please use the reset procedure only when the primary controller is missing or inoperable + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1801/xml + + + + + + + + + + - diff --git a/config/heiman/HS1SA-Z.xml b/config/heiman/HS1SA-Z.xml index 77834515a6..c9955f30dd 100644 --- a/config/heiman/HS1SA-Z.xml +++ b/config/heiman/HS1SA-Z.xml @@ -1,16 +1,42 @@ - - - - - - - - - - +--> + + http://www.openzwave.com/device-database/0260:1000:8002 + images/heiman/HS1SA-Z.png + https://products.z-wavealliance.org/products/3006/ + The Smart Smoke Alarm adopts Z-Wave protocol, when the sensor detects smoke to the set level, it will issue acoustic-optic alarm to alert the users and also send alarm notifications to gateway immediately.It's suitable to be installed in living room, office,warehouse,and etc. + - Click [Add] icon in Z-Wave Controller . +- Press the Net_Button 3 times within 1.5s, Green LED is Blinking 3 times within 1 second. +- If Inclusion Process is successful, Green led will turn off. + + - Click [Remove] icon in Z-Wave Controller +- Press the Net_Button 3 times within 1.5s +- If Exclusion Process is successful, Green led is Blinking 6 times, then turn off. + + - Wake up Notification is transmitted every 24 hours by default. +- Wake up Notification is transmitted after Notification Report is Transmitted + --Long press Net_Button while installing batteries in the product. +- Device Reset Locally notification is Transmitted. +Please use this procedure only when the network primary controller is missing or otherwise inoperable. + + HS1SA-Z + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3006/HS1SA-Z S2-documentation_3.pdf + Smart Smoke Alarm + CEPT (Europe) + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1936/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2710/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3006/xml + + + + + + + + + + - diff --git a/config/heiman/HS1WL-Z.xml b/config/heiman/HS1WL-Z.xml index 034652d693..58a5fd5be0 100644 --- a/config/heiman/HS1WL-Z.xml +++ b/config/heiman/HS1WL-Z.xml @@ -1,18 +1,44 @@ - - - - - - - - - - - - +--> + + http://www.openzwave.com/device-database/0260:1000:8004 + images/heiman/HS1WL-Z.png + https://products.z-wavealliance.org/products/3027/ + The Smart Water Leakage Sensor can protect your house from potential water damage.It can be placed near plumbing,sinks,aquariums,pumps,refrigerators,dishwashers,toilets,basements,washing machines,water heaters,and garages. + - Wake up Notification is transmitted every 24 hours by default. +- Wake up Notification is transmitted after Notification Report is Transmitted + - Click [Add] icon in Z-Wave Controller . +- Press the Networking_Button 3 times within 1.5s, Green LED is Blinking 4 times within 1 second. +- If Inclusion Process is successful, Green led will turn off. + + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3027/HS3WL-Z-S2documentation.pdf + HS3WL-Z + - Click [Remove] icon in Z-Wave Controller +- Press the Networking_Button 3 times within 1.5s +- If Exclusion Process is successful, Green led is Blinking 6 times, then turn off. + + -Long press Networking_Button while installing batteries in the Device +-Device Reset Locally notification is Transmitted +-Green LED Turns off after 2 seconds. +Please use this procedure only when the network primary controller is missing or otherwise inoperable. + CEPT (Europe) + Smart Water Leakage Sensor + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2322/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2709/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3027/xml + + + + + + + + + + + + - diff --git a/config/heiman/HS2SK-Z.xml b/config/heiman/HS2SK-Z.xml index b95ae157a9..0ef7886a9c 100644 --- a/config/heiman/HS2SK-Z.xml +++ b/config/heiman/HS2SK-Z.xml @@ -1,13 +1,40 @@ - - - - - - - - +--> + + http://www.openzwave.com/device-database/0260:1000:8006 + images/heiman/HS2SK-Z.png + https://products.z-wavealliance.org/products/3017/ + CEPT (Europe) + Smart Metering Plug + -Long press SW_Button at least 10 seconds in HS2SK-Z. +- Device Reset Locally notification is Transmitted. +-Please use this procedure only when the network primary controller is missing or otherwise inoperable. + + The smart metering plug, adopts flame-retardant engineering material and Z-Wave protocol. it can be controlled by APP remotely. It also supports power metering and timing switch, and the function of power, voltage, current overload protection. + HS2SK-Z + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3017/HS2SK-Z-S2documentation.pdf + - Click [Remove] icon in Z-Wave Controller. +- Press the SW_Button 3 times within 1.5s +- If remove Process is successful, Green LED is Blinking 6 times, then turn off. + + - Click [Add] icon in Z-Wave Controller. +- Press the SW_Button 3 times within 1.5s, Green LED is Blinking 3 times within 1 second. +- If add Process is successful, Green LED will turn off. + + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1941/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2315/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3017/xml + + https://products.z-wavealliance.org/products/2315/ + HS2SK-Z + CEPT (Europe) + + + + + + + - diff --git a/config/heltun/he-zw-sw-5a-1.xml b/config/heltun/he-zw-sw-5a-1.xml new file mode 100644 index 0000000000..5e39b27efd --- /dev/null +++ b/config/heltun/he-zw-sw-5a-1.xml @@ -0,0 +1,368 @@ + + + + + + + + + Backlight 1 control source + + + + + + + + Backlight 2 control source + + + + + + + + Backlight 3 control source + + + + + + + + Backlight 4 control source + + + + + + + + Backlight 5 control source + + + + + + + + + Relay 1 control source + + + + + + + + + + + Relay 2 control source + + + + + + + + + + + Relay 3 control source + + + + + + + + + + + Relay 4 control source + + + + + + + + + + + Relay 5 control source + + + + + + + + + + + + Click control mode for touch button 1 + + + + + + + + + + + + Click control mode for touch button 2 + + + + + + + + + + + + Click control mode for touch button 3 + + + + + + + + + + + + Click control mode for touch button 4 + + + + + + + + + + + + Click control mode for touch button 5 + + + + + + + + + + + + + Hold control mode for touch button 1 + + + + + + + + + Hold control mode for touch button 2 + + + + + + + + + Hold control mode for touch button 3 + + + + + + + + + Hold control mode for touch button 4 + + + + + + + + + Hold control mode for touch button 5 + + + + + + + + + + Timer mode duration for button 1 + + + + + Timer mode duration for button 2 + + + + + Timer mode duration for button 3 + + + + + Timer mode duration for button 4 + + + + + Timer mode duration for button 5 + + + + + + Power of the Relay 1 load in W + + + + + Power of the Relay 2 load in W + + + + + Power of the Relay 3 load in W + + + + + Power of the Relay 4 load in W + + + + + Power of the Relay 5 load in W + + + + + + Red colour backlight brightness + + + + + + + + + + Blue colour backlight brightness + + + + + + + + + + Red colour auto brightness level 1 max lumens + + + + + + Red colour auto brightness level 2 max lumens + + + + + + Blue colour auto brightness level 1 max lumens + + + + + + Blue colour auto brightness level 2 max lumens + + + + + + Active state backlight colour + + + + + + + + Temperature sensor calibration + + + + + + Temperature difference to send to controller, value X 10 + + + + + + Touch buttons sensitivity. 10=Supper sensitive. 60=lowest sensitivity. + + + + + + If Fibaro Home Center Lite or Fibaro Home Center 2 is used as a gateway for correct + communication of the devices set this parameter 1. For other gateways choose 0. + Factory default value: 0. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/config/heltun/he-zw-therm-fc1.xml b/config/heltun/he-zw-therm-fc1.xml new file mode 100644 index 0000000000..9ecf7c84f4 --- /dev/null +++ b/config/heltun/he-zw-therm-fc1.xml @@ -0,0 +1,382 @@ + + + + + + + + + 0 + true + + + + + + + + + + + + + + + + + + + + + Degree Mode 0=C, 1=F + + + + + + + + Air Temperature Calibration in degree x10 + + + + + + Temperature Hysteresis in degree, x10 + + + + + + Temperature difference to send to controller, value x10 + + + + + + Time correction by controller + + + + + + + + Time format 0=24hour, 1=12hour (AM/PM) + + + + + + + + Manually set week day + + + + + + + + + + + + + Manually set time hour + + + + + + Maually set time minute + + + + + + The brightness level can be selected in the active state from values 1 (lowest brightness) to 4 + (highest brightness) but the level cannot be lower than the level of brightness for the inactive + state (param 11). + + + + + + This parameter defines the brightness level of the display in the inactive state. The level can + be selected from values 1 to 4 but the level cannot be higher than the level of brightness for + the active state (param 10). + + + + + + Auto LCD brightness control + + + + + + + + Auto brightness level 1 max lumens + + + + + + Auto brightness level 2 max lumens + + + + + + Auto brightness level 3 max lumens + + + + + + If Fibaro Home Center Lite or Fibaro Home Center 2 is used as a gateway for correct + communication of the devices set this parameter 1. For other gateways choose 0. + Factory default value: 0. + + + + + + + + Touch buttons sensitivity. 20=Super sensitive. 70=lowest sensitivity. + + + + + + Power of the Relay 1 load in W + + + + + Power of the Relay 2 load in W + + + + + Power of the Relay 3 load in W + + + + + Power of the Relay 4 load in W + + + + + Power of the Relay 5 load in W + + + + + + Morning start time. Format: HHMM. e.g.08:00 should be sent as 0800 + + + + + + Day start time. Format: HHMM. + + + + + + Evening start time. Format: HHMM. + + + + + + Night start time. Format: HHMM. + + + + + + Monday morning temperature, value x10 + + + + + + Monday day temperature, value x10 + + + + + + Monday evening temperature, value x10 + + + + + + Monday night temperature, value x10 + + + + + + Tuesday morning temperature, value x10 + + + + + + Tuesday day temperature, value x10 + + + + + + Tuesday evening temperature, value x10 + + + + + + Tuesday night temperature, value x10 + + + + + + Wednesday morning temperature, value x10 + + + + + + Wednesday day temperature, value x10 + + + + + + Wednesday evening temperature, value x10 + + + + + + Wednesday night temperature, value x10 + + + + + + Thursday morning temperature, value x10 + + + + + + Thursday day temperature, value x10 + + + + + + Thursday evening temperature, value x10 + + + + + + Thursday night temperature, value x10 + + + + + + Friday morning temperature, value x10 + + + + + + Friday day temperature, value x10 + + + + + + Friday evening temperature, value x10 + + + + + + Friday night temperature, value x10 + + + + + + Saturday morning temperature, value x10 + + + + + + Saturday day temperature, value x10 + + + + + + Saturday evening temperature, value x10 + + + + + + Saturday night temperature, value x10 + + + + + + Sunday morning temperature, value x10 + + + + + + Sunday day temperature, value x10 + + + + + + Sunday evening temperature, value x10 + + + + + + Sunday night temperature, value x10 + + + + + + + + + + + + + + diff --git a/config/homeseer/hs-ds100plus.xml b/config/homeseer/hs-ds100plus.xml new file mode 100644 index 0000000000..e2f816f20a --- /dev/null +++ b/config/homeseer/hs-ds100plus.xml @@ -0,0 +1,58 @@ + + + Door/Window Sensor + Door/Window Sensor is a wireless reed sensor powered by AAA battery. It is used for detecting the opening or closing of doors, windows. It can communicate with an associated Z-Wave device, such as Siren, Smart Switch, etc. + http://www.openzwave.com/device-database/000C:0008:0201 + https://homeseer.com/sensors/ + https://homeseer.com/support-home/ + images/homeseer/hs-ds100plus.png + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2958/DoorWindowSensorEngineeringSpecification.pdf + + 1. Insert the AAA battery. +2. Set the Z-Wave network main controller into learning mode. +3. Triple or single short press the Z-button. +4. If the add for inclusion is successful, the LED will blink less than 5 seconds and then keep on 3 seconds. Otherwise, the LED will blink 5 seconds and then turn off, in which case you need to repeat the process from step 2. + + 1. Insert the AAA battery. +2. Pressing and holding the Z button for more than 20 seconds, +3. Led will keep on until the Z-Button is released, and it will reset to factory default when the button is released. + +Using this procedure only in the event that the network primary controller is missing or otherwise inoperable. + + 1. Insert the AAA battery. +2. Set the Z-Wave network main controller into learning mode. +3. Triple clicking the Z-button. +4. If the remove for exclusion, the LED will turn off within 1 second. Otherwise, the LED will blink 5 seconds and then turn off, in which case you need to repeat the process from step 2. + + https://products.z-wavealliance.org/products/2958/ + U.S. / Canada / Mexico + HS-DS100+ + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/Products/2958/XML + + + + + + Door/Window Sensor can reverse its value of BASIC SET when the magnet is triggered. + + + + + + This parameter defines a battery level as the “low battery”. + + + + + + + + + + + + + + + diff --git a/config/homeseer/hs-fc200plus.xml b/config/homeseer/hs-fc200plus.xml index 124701df20..a0a00563b0 100644 --- a/config/homeseer/hs-fc200plus.xml +++ b/config/homeseer/hs-fc200plus.xml @@ -1,4 +1,38 @@ - + + + http://www.openzwave.com/device-database/000C:0001:0203 + images/homeseer/hs-fc200plus.png + https://products.z-wavealliance.org/products/2957/ + HS-FC200+ is a Z-Wave controllable wired fan controller for use with 3-speed or 4-speed ceiling fans. It has a vertical row of LED’s that indicate the fan speed level. + +• Works with 3-speed or 4-speed fans only +• 4 segment LED dim level indicator +• Remotely or manually turns ON or OFF, or fan speed level +• Fits standard wall plates (wall plate not included) +• Works with any certified gateway supporting Z-Wave + Inclusion: Add the device into your network by a Z-Wave certified controller. HS-FC200+ supports the latest S2 security offered by Z-Wave certified controllers. If your controller supports S2, please refer to the user guide of the controller for detailed instructions on adding devices to the network. You should be able to add HS-FC200+ into your network using the unique QR code or the DSK 5 digit pin located on the product or packaging. In addition, the device can be added or removed using the following 2-step procedure: + +1. Put your Z-Wave controller into Inclusion mode. Consult your controller manual if you're unsure how to do this. +2. Tap the paddle of your new HomeSeer switch to begin the inclusion process. This will take a few moments to complete. + HS-FC200+ + Exclusion: Remove the device from your network by a Z-Wave certified controller. HS-FC200+ supports the latest S2 security offered by Z-Wave certified controllers. If your controller supports S2, please refer to the user guide of the controller for detailed instructions on removing devices from the network. You should be able to remove HS-FC200+ into your network using the unique QR code or the DSK 5 digit pin located on the product or packaging. In addition, the device can be added or removed using the following 2-step procedure: + +1. Put your Z-Wave controller into Exclusion mode. Consult your controller manual if you're unsure how to do this. +2. Tap the paddle of your new HomeSeer switch to begin the Exclusion process. This will take a few moments to complete. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2957/HS FC200 Manual Market Cert v1.pdf + U.S. / Canada / Mexico + Z-Wave RGB Fan Controller + To be used only in the event that the network primary controller is lost or otherwise inoperable. + +(1) Turn switch on by tapping the top of the paddle once. +(2) Quickly ap top of the paddle 3 times. +(3) Quickly tap bottom of paddle 3 times. +(4) If the LED turns off then on again, switch is reset. If not, repeat manual rest. + + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2957/xml + + - + Period to send Trigger Off command after PIR is triggered. - + When the lux level falls below this threshold and the PIR gets triggered, the unit emits a Basic Set Command (Value=0xFF) and turns on its floodlight. This overwrites the Lux level set by the Lux knob. @@ -16,19 +35,19 @@ If the level is set to 0, the unit will not turn on its floodlight. The sensor will only send a notification report to the controller. - + sets the interval of periodic lux level report to the controller - + - - + + - + diff --git a/config/homeseer/hs-ls100plus.xml b/config/homeseer/hs-ls100plus.xml index fd626a6a4c..068947be1b 100644 --- a/config/homeseer/hs-ls100plus.xml +++ b/config/homeseer/hs-ls100plus.xml @@ -1,6 +1,53 @@ - - - - - - Enable / disable the basic set command send to group 2 - - - - - + + + Enable / disable the basic set command send to group 2 + + + + + Define BASIC SET VALUE to nodes associated with group 2 when flooding alarm is triggered and is canceled. - - - - - Leak report interval, minutes. O to disable. - - - + + + + + Leak report interval, minutes. O to disable. + + + When the value is Disable, the product will not sends a vibration alarm after moving or shaking. When the value is Enable, the product will sends a vibration alarm after moving or shaking. - - - - - Temperature report interval, minutes. O to disable. - - - + + + + + Temperature report interval, minutes. O to disable. + + + Set the high temperature alarm trigger value. Available: -670 to 2570 (-67.0 to 257.0 F) Default: 1040 (104.0 F) - - - + + + Set the low temperature alarm trigger value. Available: -670 to 2570 (-67.0 to 257.0 F) Default: 320 (32.0 F) - - - + + + When the value is Disable, the product will not alarm when being triggered. When the value is Enable, the product will alarm when being triggered. - - - - - Low battery reporting threshold, %. - - - - - - - - - - - - - - - + + + + + Low battery reporting threshold, %. + + + + + + + + + + + + + + diff --git a/config/homeseer/hs-ms100plus.xml b/config/homeseer/hs-ms100plus.xml index a74c371425..4c2b882ab9 100644 --- a/config/homeseer/hs-ms100plus.xml +++ b/config/homeseer/hs-ms100plus.xml @@ -1,59 +1,106 @@ - - - - - - - Motion Sensor Sensitivity. 0 - Sensor is OFF, 8 - Max sensitivity. - - - - - - - - - - - - Enable / disable the basic set command send to group 2 - - - - - - Define BASIC SET VALUE to nodes associated with group 2 when motion alarm is triggered and is canceled. - - - - - - when the value is Disable, the product will not sends a vibration alarm after moving or shaking; - when the value is Enable, the product will sends a vibration alarm after moving or shaking - - - - - Motion Timeout Interval, seconds - - - Low battery reporting threshold, % - - - - - - - - - - - - - - - - + + + http://www.openzwave.com/device-database/000C:0009:0201 + images/homeseer/hs-ms100plus.png + https://products.z-wavealliance.org/products/2729/ + 1)Power on the device, +2) Press and hold the Z button for more than 20 seconds, +3) If holding time more than 20seconds, the LED indicator will keep on for 2 seconds, which means resetting is complete. +4) The reset feature works only when the device has been included into a Z-Wave network. + +Use this procedure only in the event that the network primary controller is missing or otherwise inoperable. + + + + U.S. / Canada / Mexico + 1) Open the cover. +2) Place the device within the direct range of your Z-Wave controller. +3) Set the main controller in add mode (see the controller’s manual). +4) Click the Z-button once or triple click the Z-button quickly, the LED indicator should blink fast. +5) Wait for the adding process to end. +6) Successful adding will be confirmed by the Z-Wave controller’s message. + + + HS-MS100+ + 1) Open the cover. +2) Place the device within the direct range of your Z-Wave controller. +3) Set the main controller remove mode (see the controller’s manual). +4) Triple click the Z-button quickly, the LED indicator should blink fast. +5) Wait for the removing process to end. +6) Successful adding will be confirmed by the Z-Wave controller’s message. + + Motion sensor can be included and operated in any Z-Wave network with other Z-Wave certified devices. + +The features list: +1) Z-Wave Plus certified for wide compatibility (500 serials product). +2) Supports security 0 and security 2 protected mode with AES-128 encryption. +3) Motion sensor. +4) Tamper alarm by shock sensor. +5) The battery life is up to 1 year. +6) Low battery alarm. +7) Support firmware OTA. + + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2729/User Manual for motion sensor-revised .pdf + Press and hold the Z button for more than 5 seconds and release. + Motion Sensor + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2729/xml + + + + + + + Motion Sensor Sensitivity. 0 - Sensor is OFF, 8 - Max sensitivity. + + + + + + + + + + + + Enable / disable the basic set command send to group 2 + + + + + + Define BASIC SET VALUE to nodes associated with group 2 when motion alarm is triggered and is canceled. + + + + + + when the value is Disable, the product will not sends a vibration alarm after moving or shaking; + when the value is Enable, the product will sends a vibration alarm after moving or shaking + + + + + Motion Timeout Interval, seconds + + + Low battery reporting threshold, % + + + + + + + + + + + + + + + + diff --git a/config/homeseer/hs-wd100plus.xml b/config/homeseer/hs-wd100plus.xml index edb797e411..2c39cd035a 100644 --- a/config/homeseer/hs-wd100plus.xml +++ b/config/homeseer/hs-wd100plus.xml @@ -1,73 +1,66 @@ - - - - - - Change the top of the switch to OFF and the bottom of the switch to ON if the switch was installed upside down. - - - - - Indicates how much each level dims/brightens as a portion of the whole range when set remotely. - - - Indicates the time duration of each level when set remotely. - - - - - - - - - - - - - - - - - - - - - - - - - Indicates how much each level dims/brightens as a portion of the whole range when set locally. - - - Indicates the time duration of each level when set locally. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + http://www.openzwave.com/device-database/000C:3034:4447 + images/homeseer/hs-wd100plus.png + https://products.z-wavealliance.org/products/2874/ + Please use this procedure only in the event that the network primary controller is lost or otherwise inoperable. + +All Configuration Parameters can all be restored to their factory default settings by using your primary controller to delete/reset the device. +To manually reset, tap the ON button twice quickly and then tap the OFF button twice quickly. Repeat the procedure to restore the settings to the factory default. + + + Z-Wave Wall Dimmer + U.S. / Canada / Mexico + - Works with incandescent and dimmable florescent (CFL) and LED lighting +- ON/OFF/DIM status LED indicator +- Fits into standard single or multiple gang junction box +- Keypad can be replaced manually to match color with other wall switches +- Over-The-Air firmware upgrade available with compatible gateway, Z-Wave static controller, or PC and software +- Internal resettable fuse to protect from surge current +- Manual reset capability +- Supports Central Scene +- Supports S2 Security + + 1. Turn the connected lights ON/OFF by tapping the switch. Tapping and releasing the upper part of the rocker turns the appliance ON. Tapping and releasing the lower part of the rocker turns the appliance OFF. +2. Add(Include) the module to/from your Z-Wave network with your primary controller. Please refer to the instructions manual of your gateway or remote controller for details and procedures on how these actions can be done. +3. Normally, the sequence is as follows: when the inclusion process is prompted by your primary controller, single click and release the rocker switch to ON or OFF position. The controller should show that the action was successful. If the controller shows it was a fail, repeat the procedure. + HS-WD100+ + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2874/HS-WD100-Manual-6a.pdf + 1. Turn the connected appliance ON/OFF by tapping the switch. Tapping and releasing the upper part of the rocker turns the appliance ON. Tapping and releasing the lower part of the rocker turns the appliance OFF. +2. Delete(Exclude) the module to/from your Z-Wave network with your primary controller. Please refer to the instructions manual of your gateway or remote controller for details and procedures on how these actions can be done. +3. Normally, the sequence is as follows: when the exclusion process is prompted by your primary controller, single click and release the rocker switch. The controller should show that the action was successful. If the controller shows it was a fail, repeat the procedure. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1730/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1731/xml + Apply PR #1546 from kaburke + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2563/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2874/xml + + + + + + Change the top of the switch to OFF and the bottom of the switch to ON if the switch was installed upside down. + + + + + Indicates how much each level dims/brightens as a portion of the whole range when set remotely. + + + Indicates the time duration of each level when set remotely. + + + Indicates how much each level dims/brightens as a portion of the whole range when set locally. + + + Indicates the time duration of each level when set locally. + + + + + + + + diff --git a/config/homeseer/hs-wd200plus.xml b/config/homeseer/hs-wd200plus.xml index 5c9251bc34..4c73e3c0b3 100644 --- a/config/homeseer/hs-wd200plus.xml +++ b/config/homeseer/hs-wd200plus.xml @@ -1,120 +1,154 @@ - - - - - - Sets bottom LED operation (in normal mode) - - - - - Change the top of the switch to OFF and the bottom of the switch to ON if the switch was installed upside down. - - - - - Ramp rate in seconds. 0 is no delay - - - Ramp rate in seconds. 0 is no delay - - - Normal mode (load status) or status mode (custom status) - - - - - Sets the Normal mode LED color - - - - - - - - - - Sets the Status mode LED color - - - - - - - - - - - Sets the Status mode LED color - - - - - - - - - - - Sets the Status mode LED color - - - - - - - - - - - Sets the Status mode LED color - - - - - - - - - - - Sets the Status mode LED color - - - - - - - - - - - Sets the Status mode LED color - - - - - - - - - - - Sets the Status mode LED color - - - - - - - - - - - 100ms blink intervals. 0 is off - - - Bitmask defines specific LEDs to enable for blinking: Note: this decimal value is derived from a hex code calculation based on the following: + + + http://www.openzwave.com/device-database/000C:3036:4447 + images/homeseer/hs-wd200plus.png + https://products.z-wavealliance.org/products/2676/ + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2676/HS-WD200-Manual-4.pdf + 1. Turn the connected lights ON/OFF by tapping the switch. Tapping and releasing the upper part of the rocker turns the appliance ON. Tapping and releasing the lower part of the rocker turns the appliance OFF. +2. Add(Include) the module to/from your Z-Wave network with your primary controller. Please refer to the instructions manual of your gateway or remote controller for details and procedures on how these actions can be done. +3. Normally, the sequence is as follows: when the inclusion process is prompted by your primary controller, single click and release the rocker switch to ON or OFF position. The controller should show that the action was successful. If the controller shows it was a fail, repeat the procedure. + Please use this procedure only in the event that the network primary controller is lost or otherwise inoperable. + +All Configuration Parameters can all be restored to their factory default settings by using your primary controller to delete/reset the device. +To manually reset, tap the ON button twice quickly and then tap the OFF button twice quickly. Repeat the procedure to restore the settings to the factory default. + + + U.S. / Canada / Mexico + - Works with incandescent and dimmable florescent (CFL) or most LED lighting +- ON/OFF status and location LED indicator +- Includes Z-Wave controllable RGB LED indicators +- Fits into standard single or multiple gang junction box +- Keypad can be replaced manually to match color with other wall switches +- Over-The-Air firmware upgrade available with compatible gateway, Z-Wave static controller, or PC and software +- Internal resettable fuse to protect from surge current +- Manual reset capability +- Support Central Scene +- Includes Controllable RGB LED Indicators + + Z-Wave Wall Dimmer with RGB LED + 1. Turn the connected appliance ON/OFF by tapping the switch. Tapping and releasing the upper part of the rocker turns the appliance ON. Tapping and releasing the lower part of the rocker turns the appliance OFF. +2. Delete(Exclude) the module to/from your Z-Wave network with your primary controller. Please refer to the instructions manual of your gateway or remote controller for details and procedures on how these actions can be done. +3. Normally, the sequence is as follows: when the exclusion process is prompted by your primary controller, single click and release the rocker switch. The controller should show that the action was successful. If the controller shows it was a fail, repeat the procedure. + HS-WD200+ + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2676/xml + + + + + + Sets bottom LED operation (in normal mode) + + + + + Change the top of the switch to OFF and the bottom of the switch to ON if the switch was installed upside down. + + + + + Ramp rate in seconds. 0 is no delay + + + Ramp rate in seconds. 0 is no delay + + + Normal mode (load status) or status mode (custom status) + + + + + Sets the Normal mode LED color + + + + + + + + + + Sets the Status mode LED color + + + + + + + + + + + Sets the Status mode LED color + + + + + + + + + + + Sets the Status mode LED color + + + + + + + + + + + Sets the Status mode LED color + + + + + + + + + + + Sets the Status mode LED color + + + + + + + + + + + Sets the Status mode LED color + + + + + + + + + + + Sets the Status mode LED color + + + + + + + + + + + 100ms blink intervals. 0 is off + + + Bitmask defines specific LEDs to enable for blinking: Note: this decimal value is derived from a hex code calculation based on the following: Bit 0 = led 1 Bit 1 = led 2 Bit 2 = led 3 @@ -124,12 +158,12 @@ Bit 6 = led 7 IE: value of 1 = first LED, 64 = led 7 - - - - - - - - + + + + + + + + diff --git a/config/homeseer/hs-ws100plus.xml b/config/homeseer/hs-ws100plus.xml index c6c2cbc8d0..335544df07 100644 --- a/config/homeseer/hs-ws100plus.xml +++ b/config/homeseer/hs-ws100plus.xml @@ -1,23 +1,55 @@ - - - - - - Change the top of the switch to OFF and the bottom of the switch to ON if the switch was installed upside down. - - - - - Set the LED policy: on if the load is on, off if the load is on, or off all the time - - - - - - - - - - - + + + http://www.openzwave.com/device-database/000C:3033:4447 + images/homeseer/hs-ws100plus.png + https://products.z-wavealliance.org/products/2894/ + HS-WS100+ + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2894/HS-WS100-Manual-v6.pdf + HS-WS100+ In Wall On/Off Switch +- Works with incandescent, florescent (CFL), or most LED lighting and appliances +- ON/OFF status and location LED indicator +- Fits into standard single or multiple gang junction box +- Keypad can be replaced manually to match color with other wall switches +- Over-The-Air firmware upgrade available with compatible gateway, Z-Wave static controller, or PC and software. +- Internal resettable fuse to protect from surge current +- Manual reset capability +- Support Central Scene + U.S. / Canada / Mexico + 1. Turn the connected appliance ON/OFF by tapping the switch. Tapping and releasing the upper part of the rocker turns the appliance ON. Tapping and releasing the lower part of the rocker turns the appliance OFF. +2. Add(Include) the module to/from your Z-Wave network with your primary controller. Please refer to the instructions manual of your gateway or remote controller for details and procedures on how these actions can be done. +3. Normally, the sequence is as follows: when the inclusion process is prompted by your primary controller, single click and release the rocker switch to ON or OFF position. The controller should show that the action was successful. If the controller shows it was a fail, repeat the procedure. + 1. Turn the connected appliance ON/OFF by tapping the switch. Tapping and releasing the upper part of the rocker turns the appliance ON. Tapping and releasing the lower part of the rocker turns the appliance OFF. +2. Delete(Exclude) the module to/from your Z-Wave network with your primary controller. Please refer to the instructions manual of your gateway or remote controller for details and procedures on how these actions can be done. Normally, the sequence is as follows: when the exclusion process is prompted by your primary controller, single click and release the rocker switch. The controller should show that the action was successful. If the controller shows it was a fail, repeat the procedure. + Please use this procedure only in the event that the network primary controller is lost or otherwise inoperable. + +All Configuration Parameters can all be restored to their factory +default settings by using your primary controller to delete/reset +the device. To manually reset, tap the ON button twice quickly and then tap the OFF button twice quickly. Repeat the procedure to restore the settings to the factory default. + + Z-Wave Wall Switch + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2554/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2894/xml + + + + + + Change the top of the switch to OFF and the bottom of the switch to ON if the switch was installed upside down. + + + + + Set the LED policy: on if the load is on, off if the load is on, or off all the time + + + + + + + + + + + diff --git a/config/homeseer/hs-ws200plus.xml b/config/homeseer/hs-ws200plus.xml index 69808fa312..1d379867b0 100644 --- a/config/homeseer/hs-ws200plus.xml +++ b/config/homeseer/hs-ws200plus.xml @@ -1,54 +1,86 @@ - - - - - - Sets bottom LED operation (in normal mode) - - - - - Change the top of the switch to OFF and the bottom of the switch to ON if the switch was installed upside down. - - - - - Normal mode (load status) or status mode (custom status) - - - - - Sets the Normal mode LED color - - - - - - - - - - Sets the Status mode LED color - - - - - - - - - - - Sets the blink frequency of the LED + + + http://www.openzwave.com/device-database/000C:3035:4447 + images/homeseer/hs-ws200plus.png + https://products.z-wavealliance.org/products/2675/ + 1. Turn the connected appliance ON/OFF by tapping the switch. Tapping and releasing the upper part of the rocker turns the appliance ON. Tapping and releasing the lower part of the rocker turns the appliance OFF. +2. Delete(Exclude) the module to/from your Z-Wave network with your primary controller. Please refer to the instructions manual of your gateway or remote controller for details and procedures on how these actions can be done. Normally, the sequence is as follows: when the exclusion process is prompted by your primary controller, single click and release the rocker switch. The controller should show that the action was successful. If the controller shows it was a fail, repeat the procedure. + U.S. / Canada / Mexico + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2675/HS-WS200-Manual-v4.pdf + Please use this procedure only in the event that the network primary controller is lost or otherwise inoperable. + +All Configuration Parameters can all be restored to their factory +default settings by using your primary controller to delete/reset +the device. To manually reset, tap the ON button twice quickly and then tap the OFF button twice quickly. Repeat the procedure to restore the settings to the factory default. + + HS-WS200+ In Wall On/Off Switch +- Works with incandescent, florescent (CFL), or most LED lighting and appliances +- ON/OFF status and location LED indicator +- Includes Z-Wave controllable RGB LED indicator +- Fits into standard single or multiple gang junction box +- Keypad can be replaced manually to match color with other wall switches +- Over-The-Air firmware upgrade available with compatible gateway, Z-Wave static controller, or PC and software. +- Internal resettable fuse to protect from surge current +- Manual reset capability +- Support Central Scene + Z-Wave Wall Switch with RGB LED + HS-WS200+ + 1. Turn the connected appliance ON/OFF by tapping the switch. Tapping and releasing the upper part of the rocker turns the appliance ON. Tapping and releasing the lower part of the rocker turns the appliance OFF. +2. Add(Include) the module to/from your Z-Wave network with your primary controller. Please refer to the instructions manual of your gateway or remote controller for details and procedures on how these actions can be done. +3. Normally, the sequence is as follows: when the inclusion process is prompted by your primary controller, single click and release the rocker switch to ON or OFF position. The controller should show that the action was successful. If the controller shows it was a fail, repeat the procedure. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2675/xml + + + + + + Sets bottom LED operation (in normal mode) + + + + + Change the top of the switch to OFF and the bottom of the switch to ON if the switch was installed upside down. + + + + + Normal mode (load status) or status mode (custom status) + + + + + Sets the Normal mode LED color + + + + + + + + + + Sets the Status mode LED color + + + + + + + + + + + Sets the blink frequency of the LED 0 = No Blink 1 = 100ms ON then 100ms OFF - - - - - - - - + + + + + + + + diff --git a/config/homeseer/hsm200.xml b/config/homeseer/hsm200.xml index bb11fcb70b..e6a0796931 100644 --- a/config/homeseer/hsm200.xml +++ b/config/homeseer/hsm200.xml @@ -1,30 +1,37 @@ - + http://www.openzwave.com/device-database/001E:0001:0004 images/homeseer/hsm200.png - https://products.z-wavealliance.org/products/1254/ - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1254/HomeSeer-HSM200-Guide-ndc.pdf - Z-Wave Multi-Sensor HSM200 - There are two methods for exclusion: -1) Put the controller into exclusion mode, then press and release the push button on the side of the HSM200. The LED will blink aqua when no longer joined to the network. -2) (Use this procedure only when your primary controller is missing or otherwise inoperable.) Press and hold the push button. The LED will blink blue faster and faster and then shift to yellow and continue to blink faster and faster. Once the LED goes out, the HSM200 is reset to the factory defaults and will blink aqua. -Method 1 is recommended. Method 2 should only to be used in the event that the primary controller is missing or otherwise inoperable. - When the HSM200 has not yet been joined to a Z-Wave network, the LED blinks aqua. + https://products.z-wavealliance.org/products/2794/ + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2794/EZMultiPliOwnerManual.pdf + EZmultiPli + When EZMultiPli is first plugged into the wall outlet, the LED should blink an aqua color. This indicates that it is not currently joined (or paired) to a Z-Wave network. If the LED is blinking white each time motion is detected, then it is already joined to a Z-Wave network. If the LED is blinking white you will need to exclude it from the other Z-Wave network before attempting to join a new one. +Follow the procedure of the Z-Wave primary controller to begin the exclusion process. Once the primary controller is ready to receive the exclusion command, press and release the push button on the side of EZMultiPli. The primary controller should give an indication that the reset process has completed. EZMultiPlis LED will blink aqua when it is ready to be added to a Z-Wave network. + SmartStart or press and release the button on the side. +LED blinks slowly light blue when not included. +Once included, the LED blinks white when motion is detected for about 5 minutes to test the motion detection area. + Factory Reset +If the exclusion process above is not working or the controller EZMultiPli was originally joined to is lost or not available, the following process can be used to factory reset EZMultiPli. -To Include: Put the controller into learn mode, (in the HomeSeer Z-Wave Plug-in, choose controller functions and add/include device.) then press and release the push button on the side of the HSM200. The LED will blink blue while the HSM200 is trying to join the Z-Wave network. Once joined to the network, the HSM200 enters a motion sensor test mode and the LED will blink white each time motion is detected. This mode lasts for about 5 minutes and then the LED will go out. -If the HSM200 is unable to join the network, it will return to blinking aqua. - Excluding from a Z-Wave network will return the device to factory defaults. See the Product Exclusion Description for details. +Press and continue to hold the push button in for about 60 seconds. The LED will blink blue faster and faster and then shift to yellow and continue to blink faster and faster. Once the LED goes out, EZMultiPli is reset to the factory defaults and will blink aqua indicating it is ready to be added to a Z-Wave network. - HSM200 - The HSM200 senses motion, temperature and light level, can function as a night light, and can also be programmed to display up to 7 different glowing colors when things happen in the home! - -Since the HSM200 is line powered, there are no batteries to change and the unit automatically operates as a Z-Wave network repeater. Installation is fast and easy. Just plug into any available 120v outlet and tap the button on the side to join it to your Z-Wave network. - -HSM200 is compatible with any HomeSeer HS3-based system, including the full line of HomeTrollers, and Z-Wave systems from 3rd parties. HomeSeer users can create events to display different colors when motion is sensed, doors are opened, water leaks are detected or just about anything else happens in the home. Color options include red, green, blue, yellow, magenta, cyan and white. The unit can also be programmed to work as a night light after hours. + EZMultiPli + Notify caregivers when a loved one does not get up at their usual time or gets up multiple times during the night. Easily installed in a kitchen, bathroom, bedroom or hallway - just plug it in! The wide angle motion sensor detects motion when placed at floor level in a normal wall outlet or at counter height in a kitchen or bath. Never needs batteries! + +Receive an email or text when motion is detected or the temperature is dangerously low while you are away. Turn on lights and sirens automatically. + +Save energy by automatically turning off lights in unoccupied rooms or hallways. + +Set the color LED night light to inform you that your garage door is open, there is a severe weather alert or any indicator you can imagine! + +Operates as a Z-Wave range extender utilizing fifth generation Z-Wave technology to enhance the reliability and speed of every device on a Z-Wave network. + +Version 2.0 firmware adds AES-128 security S2 and SmartStart U.S. / Canada / Mexico Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1124/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1254/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2794/xml http://store.homeseer.com/store/X-P1882.aspx diff --git a/config/honeywell/39351-ZW3005.xml b/config/honeywell/39351-ZW3005.xml index 833c55ec0d..8929ac7aec 100644 --- a/config/honeywell/39351-ZW3005.xml +++ b/config/honeywell/39351-ZW3005.xml @@ -1,45 +1,74 @@ - - - - - - - Sets when the LED on the switch is lit. - - - - - - Change the top of the switch to OFF and the bottom of the switch to ON, if the switch was installed upside down. - - - - - - Indicates how many levels the dimmer will change for each dimming step. - - - This value indicates in 10 millisecond resolution, how often the dim level will change. For example, if you set this parameter to 1, then every 10ms the dim level will change. If you set it to 255, then every 2.55 seconds the dim level will change. - - - Indicates how many levels the dimmer will change for each dimming step. - - - This value indicates in 10 millisecond resolution, how often the dim level will change. For example, if you set this parameter to 1, then every 10ms the dim level will change. If you set it to 255, then every 2.55 seconds the dim level will change. - - - Indicates how many levels the dimmer will change for each dimming step. - - - This value indicates in 10 millisecond resolution, how often the dim level will change. For example, if you set this parameter to 1, then every 10ms the dim level will change. If you set it to 255, then every 2.55 seconds the dim level will change. - - - - - - - - - - - + + + http://www.openzwave.com/device-database/0039:3038:4944 + images/honeywell/39351-ZW3005.png + https://products.z-wavealliance.org/products/2724/ + 39351 / ZW3005 + 1. Follow the instructions for your Z-Wave certified controller to +include a device to the Z-Wave network. +2. Once the controller is ready to add your device, +press and release the top or bottom of the wireless smart +switch (rocker) to add it in the network. +Please reference the controller’s manual for instructions. + Quickly press ON (Top) button three (3) times then immediately +press the OFF (Bottom) button three (3) times. The LED will flash +ON/OFF 5 times when completed successfully. +NOTE: This should only be used in the event your network’s +primary controller is missing or otherwise inoperable. + 1. Follow the instructions for your Z-Wave certified controller to +remove a device from the Z-Wave network. +2. Once the controller is ready to Exclude your device, press +and release the top or bottom of the wireless smart dimmer +(rocker) to remove it from the network. + In-Wall Dimmer + U.S. / Canada / Mexico + Transform any home into a smart home with the Honeywell In-Wall Dimmer. The In-Wall Dimmer can easily replace any standard in-wall switch and remotely controls a light in your home. Your home will be equipped with ultimate flexibility with the Honeywell Z-Wave Dimmer, capable of being used by itself or with up to four add-on switches. Screw terminal installation provides improved space efficiency when replacing existing switches and the integrated LED indicator light allows you to easily locate the switch in a dark room. The Honeywell Z-Wave In-Wall Dimmer is compatible with any Z-Wave certified gateway, providing access to many popular home automation systems. Take control of your home lighting with Honeywell Z-Wave Smart Controls! + + + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2724/39351-QSG-v1-para.pdf + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2724/xml + + + + + + Sets when the LED on the switch is lit. + + + + + + Change the top of the switch to OFF and the bottom of the switch to ON, if the switch was installed upside down. + + + + + + Indicates how many levels the dimmer will change for each dimming step. + + + This value indicates in 10 millisecond resolution, how often the dim level will change. For example, if you set this parameter to 1, then every 10ms the dim level will change. If you set it to 255, then every 2.55 seconds the dim level will change. + + + Indicates how many levels the dimmer will change for each dimming step. + + + This value indicates in 10 millisecond resolution, how often the dim level will change. For example, if you set this parameter to 1, then every 10ms the dim level will change. If you set it to 255, then every 2.55 seconds the dim level will change. + + + Indicates how many levels the dimmer will change for each dimming step. + + + This value indicates in 10 millisecond resolution, how often the dim level will change. For example, if you set this parameter to 1, then every 10ms the dim level will change. If you set it to 255, then every 2.55 seconds the dim level will change. + + + + + + + + + + + diff --git a/config/honeywell/th6320zw2003.xml b/config/honeywell/th6320zw2003.xml index 72ef8aa3ab..3dddc7753a 100644 --- a/config/honeywell/th6320zw2003.xml +++ b/config/honeywell/th6320zw2003.xml @@ -1,4 +1,43 @@ - + + + http://www.openzwave.com/device-database/0039:0008:0011 + images/honeywell/th6320zw2003.png + https://products.z-wavealliance.org/products/2893/ + T6 Pro Z-Wave Programmable Thermostat + To include the thermostat in to Z-Wave network, go to thermostat MENU/ Z-Wave SETUP. +• Touch Select. You will be asked to set your primary controller to INCLUDE MODE. Please refer to the user manual of your Z-Wave controller. +• After inclusion procedure has been initiated on your Z-Wave controller, touch Select on the thermostat. +• If the inclusion procedure is successful, "INCLUDED", the node ID, and the Z-Wave connected status icon appear on the screen. +If the procedure fails, “FAILED TO INCLUDE” appears on the screen. +• Your controller will indicate whether the thermostat was successfully added to its network. Please refer to the user manual of your Z-Wave controller. + The Honeywell T6 Pro Z-Wave Programmable Thermostat is a Z-Wave Plus certified, universal thermostat capable to control up to three heat and two cool stages of heat pump, (incl. dual fuel heat pump systems) and up to two heat and two cool stages of conventional system (3H/2C HP, 2H/2C Conv.) +- 3 x AA battery or 24VAC powered +- Easy wiring, easy configuration +- Flexible local thermostat scheduling options +- Attractive look, large Easy-To-Read touchscreen +- Displays and reports ambient temperature and % Relative Indoor Humidity +- Displays and reports HVAC system status, battery power status, Z-Wave signal status +- Large amount of supported Z-Wave command classes +- Remotely configurable via Z-Wave configuration command class +- Advanced HVAC configuration parameters + U.S. / Canada / Mexico + TH6320ZW2003 + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2893/33-00414-01-min.pdf + To exclude the thermostat from Z-Wave network, go to thermostat MENU/ Z-Wave SETUP. +• Touch Select. You will be asked to set your primary +controller to EXCLUDE MODE. Please refer to the user manual of your Z-Wave controller. +• After exclusion procedure has been initiated on your Z-Wave controller, touch Select on the thermostat. +• If the exclusion procedure is successful, "EXCLUDED", and the Z-Wave excluded status icon appear on the screen. +If the procedure fails, “FAILED TO EXCLUDE” appears on the screen. +• Your controller will indicate whether the thermostat was successfully excluded from its network. Please refer to the user manual of your Z-Wave controller. + To reset the thermostat to factory default setting, go to Installer setup – advanced menu. To access the advanced menu, press and hold the thermostat Menu button for 5 seconds. +Touch < or > to go to RESET menu. Press Select. Touch < or > to go to FACTORY. Press Select. Touch Yes to reset the thermostat to factory default settings.. +Please use the reset procedure only when the primary controller is missing or inoperable. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2583/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2893/xml + + diff --git a/config/horstmann/scsc17.xml b/config/horstmann/scsc17.xml index f6404be2f6..be52ff8705 100644 --- a/config/horstmann/scsc17.xml +++ b/config/horstmann/scsc17.xml @@ -1,17 +1,16 @@ - + http://www.openzwave.com/device-database/0059:0001:0004 images/horstmann/scsc17.png - https://products.z-wavealliance.org/products/864/ + https://products.z-wavealliance.org/products/1740/ http://www.horstmann.co.uk/central-heating.php C17-ZW CEPT (Europe) - C-Stat – Electronic Programmable Room Thermostat - C-Stat is an electronic programmable thermostat that combines time and temperature control in a completely new design with particular attention paid to the styling and the user interface which features easy to use menu driven programming and a clear, 70mm blue backlit display. - -The new 6-model range offers standard battery and mains powered units in addition to a wireless version - the C-Stat ZW - which is battery powered and has wireless connectivity using proven Z-Wave technology to communicate with its receiver. All three versions feature models with 24 hour or 7 day programming with up to six temperature settings per day. The mains powered version has a battery back up to preserve settings. + C-Stat + C-Stat Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/864/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1740/xml diff --git a/config/horstmann/srt321.xml b/config/horstmann/srt321.xml index c95b5b1114..7d93c7ac9b 100644 --- a/config/horstmann/srt321.xml +++ b/config/horstmann/srt321.xml @@ -1,5 +1,37 @@ - - + + + http://www.openzwave.com/device-database/0059:0005:0001 + images/horstmann/srt321.png + https://products.z-wavealliance.org/products/1563/ + STEP 1: On the SRT321, Set DIL switch 1 on the back of the unit to 'ON' position, scroll through the function menu by rotating the dial, select "E" and press the dial to activate Exclusion process. Now the character "E" starts flashing. +STEP 2: On the 3rd party device, select Exclusion for removing device from SRT321's network. +After successful Exclusion SRT321 displayed "EP" other wise displayed "EF" (Exclusion fail). +Note: Once the character starts flashing the installer has 60 seconds to activate the 3rd party device. +After successful Exclusion set DIL switch 1 to 'OFF' position to operate SRT321 in normal operation. +If the Exclusion process has failed more than once, try moving the SRT321 to another position and repeat the Exclusion steps. + SRT-321 (Thermostat-HVAC) + CEPT (Europe) + STEP 1: On the SRT321, set DIL switch 1 on the back of the unit to 'ON' position, scroll through the function menu by rotating the dial, select "I" and press the dial to activate Inclusion process. Now the character "I" starts flashing. +STEP 2: On the 3rd party device, select Inclusion for adding a device into SRT321's network. +After successful inclusion SRT321 displayed "IP" other wise displayed "IF" (Inclusion fail). +Note: Once the character starts flashing the installer has 60 seconds to activate the 3rd party device. +After successful Inclusion set DIL switch 1 to 'OFF' position to operate SRT321 in normal operation. +If the inclusion process fails more than once, the 3rd party device may be already included in another network. So first exclude and then include the device. + Please use this procedure only when the primary controller is missing or otherwise inoperable. +To reset the thermostat Set DIL switch 1 on the back of the unit to 'ON' position, scroll through the function menu by rotating the dial, select "P" and press the dial twice on the target device to execute reset. +Note: After successful operation device displayed "PP". +It will put the device in factory default, that include setting all the configuration, Association to factory default and removing the device from Z-Wave network. + MAX10U-734 + SRT321 will wake-up regularly and announce the wakeup state by sending Wakeup Notification to the configured node ID if Wakeup Interval and valid node ID is set. +To forcefully wake up the device to send Wakeup notification do the following steps: Set DIL switch 1 on the back of the unit to 'ON' position, and than back to the 'OFF' position. +Note: It is possible to set the node ID to 255 to send wakeup notifications as broadcast. In this mode device takes more time to go to sleep and drains battery faster, but can notify all it's direct neighbors about a wakeup. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1563/SRT321 User MAnual.pdf + The thermostat includes TPI software that optimises boiler firing to minimise overshooting of temperature in a heated environment. It has been proved that TPI controllers provide considerable energy savings over standard heating controllers. By using interoperable radio solutions the user can remotely change the set point, read the temperature or receive battery reports. It makes this device an ideal partner for use with a home gateway for web enabled apps allowing you to remotely control your heating while on the move. You no longer have to worry about returning to a cold house as long as you have a phone or tablet PC handy. +By combining ease of use, ease of installation and intelligent control this thermostat is suitable for use in most heating systems. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1563/xml + + diff --git a/config/horstmann/ssr303.xml b/config/horstmann/ssr303.xml index f736798959..19a6b350ba 100644 --- a/config/horstmann/ssr303.xml +++ b/config/horstmann/ssr303.xml @@ -1,5 +1,35 @@ - - + + + http://www.openzwave.com/device-database/0059:0005:0003 + images/horstmann/ssr303.png + https://products.z-wavealliance.org/products/1618/ + CEPT (Europe) + The SSR 303 is a single channel relay/switch, it forms part of central heating control system, it can be operated by any third party controllers/Thermostat using ‘Binary Switch CC’ commands. + +SSR 303 will act as a repeater once added into the Z- Wave network, providing an alternative communication route for units which otherwise would not be within communication distance of each other. + +SSR 303 has a fail-safe mode where by the relay is turned OFF if another 'Thermostat Mode SET' command has not been received within 60 minutes. + STEP 1: Ensure the Network LED is flashing on the SSR 303, if not follow ‘Exclusion’ steps first. +STEP 2: Put the 3rd party controller into inclusion mode. +STEP 3: Press and hold the network button on the SSR 303 until the ‘ON’ LED’s start flashing. +The SSR 303 has been added onto the network when the ‘OFF’ LED goes solid red. + +NOTE: If the ON LED does not flash then the add process has been unsuccessful. + MAX10Z-384 + STEP 1: Put the 3rd party controller into exclusion mode. +STEP 2: Press and hold the network button on the SSR 303. +The SSR 303 has been removed from the network when the Network LED starts flashing. + +NOTE: If the Network LED does not flash the remove process has been unsuccessful. + SSR 303 (Single Channel On/Off Power switch) + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1618/SSR 303 User Manual.pdf + "Please use this procedure only when the primary controller is missing or otherwise inoperable." + +Follow ‘Exclusion’ steps. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1618/xml + + diff --git a/config/idlock/idlock101.xml b/config/idlock/idlock101.xml index f9f9e3b861..f6ec4d1138 100644 --- a/config/idlock/idlock101.xml +++ b/config/idlock/idlock101.xml @@ -1,39 +1,75 @@ - - - - - - - - - Door Lock Mode - Autolock Mode, Manuallock mode, Activate Away Mode, Deactivate Away Mode. - Default Value : 1 ( Disable Away / Auto Lock Mode ) - - - - - - - - - RFID Registration Configuration - IDLocks can use up to 50 RFID cards. In order to use a RFID, RFID has to be registered by z-wave configuration command class. - Configuration Set in case of starting to register from backend side ( Ex. App) - - - - - - - - - - - - - - - - - + + + http://www.openzwave.com/device-database/0230:0001:0003 + images/idlock/idlock101.png + https://products.z-wavealliance.org/products/1512/ + Exclusion – (Puts your device in exclusion mode) +• Push and hold button until all LEDs on keypad activates. (with ID Lock in an unlocked state) +• Release button and press “8” on keypad. +Exclusion mode starts immediately. LED indicator below logo signals this by flashing blue. + 01A + CEPT (Europe) + Device reset – (This will reset RF interface module to factory default settings) +Warning: Please do only proceed with the following reset procedure, if primary network controller is missing or otherwise +inoperable. + +RESET Z-WAVE MODULE: +Activate doorlock service menu, by holding inside push button for 5sec while door is in OPEN state. + +Outside touchpanel activates > Push "0" + +FACTORY RESET DOORLOCK FIRMWARE: +1. Push innside pushbutton continously for five Seconds after inserting batteries. +2. Receive reset sound +3. Receive confirmation sound + + + Activate by touching numpad with two fingers or handpalm + Inclusion – (Puts your device in inclusion mode) +• Push and hold button until all LEDs on keypad activates. (with ID Lock in an unlocked state) +• Release button and press “8” on keypad. +Inclusion mode starts immediately. LED indicator below logo signals this by flashing blue. + UART console communication module turns your ID Lock digital doorlock into a Z-Wave Plus enabled digital doorlock. + +It enables your ID Lock to operate in a Z-Wave network with numerous access control funtions and notifications. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1512/IDL Operational Manual EN v1.2.pdf + ID Lock Z-Wave module + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1512/xml + + + + + + + + + Door Lock Mode + Autolock Mode, Manuallock mode, Activate Away Mode, Deactivate Away Mode. + Default Value : 1 ( Disable Away / Auto Lock Mode ) + + + + + + + + + RFID Registration Configuration + IDLocks can use up to 50 RFID cards. In order to use a RFID, RFID has to be registered by z-wave configuration command class. + Configuration Set in case of starting to register from backend side ( Ex. App) + + + + + + + + + + + + + + + diff --git a/config/idlock/idlock150.xml b/config/idlock/idlock150.xml index 87cf841078..a9ebaa849e 100644 --- a/config/idlock/idlock150.xml +++ b/config/idlock/idlock150.xml @@ -1,110 +1,179 @@ - - - + + + ID Lock 150 Z-Wave module + A module enabling your ID Lock digital door lock to a Z-Wave Plus enabled digital door Lock. - - - - - Door Lock Mode - Autolock Mode, Manual lock mode, Activate Away Mode, Deactivate Away Mode - Default Value : 1 ( Disable Away / Auto Lock Mode ) - - - - - - - - - RFID Registration Configuration - IDLocks can use up to 50 RFID cards. In order to use a RFID, RFID has to be registered by z-wave configuration command class. +The module is compatible with ID Lock 101 and ID Lock 150. - RFID Configuration with Z-wave is only valid for ID Lock 101. +It enables your ID Lock to operate in a Z-Wave network with numerous access control funtions and notifications. + http://www.openzwave.com/device-database/0373:0001:0003 + https://idlock.no/z-wave/ + https://idlock.no/kundesenter/ + images/idlock/idlock150.png + https://idlock.no/wp-content/uploads/2019/08/IDLock150_ZWave_UserManual_v3.02.pdf + Activate by touching the touch panel with finger(s), the palm of the hand on the outside unit or by pushing the key button on the inside unit. + Inclusion – (Puts your device in inclusion mode) - Configuration Parameters are as below. Default value is 0x05 (Not in progress). - ID Lock 150 will always report 0x05 as this feature is not supported by this door lock model. +• Push and hold key button until all LEDs on touch panel activates (with ID Lock in an unlocked state). +• Release button. +• Enter Master PIN followed by * on touch panel. +• Press digit "2" for settings followed by * on touch panel. +• Press digit “5” on touch panel. - Configuration Set in case of starting to register from gateway - - - - - - - - - Door Hinge Position - Default Value : 0 (Right Handle) - - - - - - - Door Audio Volume Level - This parameter is a set only parameter. If the value is changed locally on the door lock, this value will not change. - Default Value : 5 - - - - - - - - - - - - Door ReLock Mode - Default Value: 1 (Enabled) - - - - - - - Service PIN Mode - A configuration get command on this parameter returns the latest set parameter value (set by Z-wave). - This is a set only value, if changed locally on keypad these values are not changed on Z-wave module. Value 5, 6 and 7 are for future use on door lock. - Default Value: 0 (Deactivated) - - - - - - - - - - - - - - - Door Lock Model Type - This configuration is only accepted by configuration get command - It is a read only parameter. Default value depends on the door lock model type. - - - - - Configuration Report for retriving the RFID information - Byte 1: Para1 (msb) - Byte 2: Para2 - Byte 3: Para3 - Byte 4: Para4 (lsb) - - +Inclusion mode starts immediately. LED indicator below logo signals this by flashing blue. + Exclusion – (Puts your device in exclusion mode) - +• Push and hold key button until all LEDs on touch panel activates (with ID Lock in an unlocked state). +• Release button. +• Enter Master PIN followed by * on touch panel. +• Press digit "2" for settings followed by * on touch panel. +• Press digit “5” on touch panel. - - - - - - - - +Exclusion mode starts immediately. LED indicator below logo signals this by flashing blue. + Device reset – (This will reset RF interface module to factory default settings) +Warning: Please do only proceed with the following reset procedure, if primary network controller is missing or otherwise inoperable. + +RESET Z-WAVE MODULE: + +• Push and hold key button until all LEDs on touch panel activates (with ID Lock in an unlocked state). +• Release button. +• Enter Master PIN followed by * on keypad. +• Press digit "2" for settings followed by * on keypad. +• Press digit “0” on keypad. + +If the Z-wave module is not included in a Z-wave network the door lock will also return to factory settings when following the above procedure. + +FACTORY RESET DOOR LOCK FIRMWARE: + +• Push and hold inside lock/unlock button while inserting the fourth battery. +• Receive reset sound. +• Release button. +• Receive confirmation sound. + https://products.z-wavealliance.org/products/2780/ + CEPT (Europe) + ID-150 + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2780/xml + Update as per the 1.4.9/1.6 firmware specification + + + + + + + + + Door Lock Mode + Autolock Mode, Manual lock mode, Activate Away Mode, Deactivate Away Mode + Default Value : 1 ( Auto lock, Away off ) + + + + + + + + + RFID Mode + RFID activated + RFID deactivated + Default Value: 5 (RFID activated) + + + + + + + Door Hinge Position + Default Value : 0 (Right hinged operation) + + + + + + + Door Audio Volume Level + This parameter is a set only parameter. If the value is changed locally on the door lock, this value will not change. + Default Value : 5 + + + + + + + + + + + + Door ReLock Mode + Default Value: 1 (Enabled) + + + + + + + Service PIN Mode + A configuration get command on this parameter returns the latest set parameter value (set by Z-wave). + This is a set only value, if changed locally on keypad these values are not changed on Z-wave module. Value 5 and 6 are for future use on door lock. + Disabled: Disables both PIN and Service PIN menu on door lock + + Default Value: 0 (Deactivated) + + + + + + + + + + + + + + + + Door Lock Model Type + This configuration is only accepted by configuration get command + It is a read only parameter. Default value depends on the door lock model type. + + + + + Updater Mode + + Enables use of the Updater app. + Default Value: 0 (Off, no sound) + + + + + + + + + Master PIN Unlock Mode + + + + + + + Configuration Report for retriving the RFID information + Byte 1: Para1 (msb) + Byte 2: Para2 + Byte 3: Para3 + Byte 4: Para4 (lsb) + + + + + + + + + + diff --git a/config/images/2gig/ct100.png b/config/images/2gig/ct100.png index 894f7f8445..ec9fd0b25a 100644 Binary files a/config/images/2gig/ct100.png and b/config/images/2gig/ct100.png differ diff --git a/config/images/BeNext/TagReader500.png b/config/images/BeNext/TagReader500.png new file mode 100644 index 0000000000..5d3fc3428c Binary files /dev/null and b/config/images/BeNext/TagReader500.png differ diff --git a/config/images/aeotec/dsc14104.png b/config/images/aeotec/dsc14104.png new file mode 100644 index 0000000000..59c6778bbe Binary files /dev/null and b/config/images/aeotec/dsc14104.png differ diff --git a/config/images/aeotec/dsc35103.png b/config/images/aeotec/dsc35103.png new file mode 100644 index 0000000000..59c6778bbe Binary files /dev/null and b/config/images/aeotec/dsc35103.png differ diff --git a/config/images/aeotec/zw056.png b/config/images/aeotec/zw056.png index 3e849f6f3d..80e6a56acb 100644 Binary files a/config/images/aeotec/zw056.png and b/config/images/aeotec/zw056.png differ diff --git a/config/images/aeotec/zw095.png b/config/images/aeotec/zw095.png index ebd4c67921..2f99fb3c3e 100644 Binary files a/config/images/aeotec/zw095.png and b/config/images/aeotec/zw095.png differ diff --git a/config/images/aeotec/zw096.png b/config/images/aeotec/zw096.png index f43ae0a75b..6e6e7c2bb8 100644 Binary files a/config/images/aeotec/zw096.png and b/config/images/aeotec/zw096.png differ diff --git a/config/images/aeotec/zw098.png b/config/images/aeotec/zw098.png index 46b01baa01..fcfc7426e3 100644 Binary files a/config/images/aeotec/zw098.png and b/config/images/aeotec/zw098.png differ diff --git a/config/images/aeotec/zw099.png b/config/images/aeotec/zw099.png new file mode 100644 index 0000000000..2e3a1c89a4 Binary files /dev/null and b/config/images/aeotec/zw099.png differ diff --git a/config/images/aeotec/zw111.png b/config/images/aeotec/zw111.png new file mode 100644 index 0000000000..d285be89ad Binary files /dev/null and b/config/images/aeotec/zw111.png differ diff --git a/config/images/aeotec/zw112.png b/config/images/aeotec/zw112.png new file mode 100644 index 0000000000..4efcec7531 Binary files /dev/null and b/config/images/aeotec/zw112.png differ diff --git a/config/images/aeotec/zw116.png b/config/images/aeotec/zw116.png new file mode 100644 index 0000000000..d285be89ad Binary files /dev/null and b/config/images/aeotec/zw116.png differ diff --git a/config/images/aeotec/zw117.png b/config/images/aeotec/zw117.png new file mode 100644 index 0000000000..8094d4f09e Binary files /dev/null and b/config/images/aeotec/zw117.png differ diff --git a/config/images/aeotec/zw120.png b/config/images/aeotec/zw120.png new file mode 100644 index 0000000000..61bdf9a903 Binary files /dev/null and b/config/images/aeotec/zw120.png differ diff --git a/config/images/aeotec/zw121.png b/config/images/aeotec/zw121.png new file mode 100644 index 0000000000..11eb27f801 Binary files /dev/null and b/config/images/aeotec/zw121.png differ diff --git a/config/images/aeotec/zw122.png b/config/images/aeotec/zw122.png new file mode 100644 index 0000000000..b1383c79c1 Binary files /dev/null and b/config/images/aeotec/zw122.png differ diff --git a/config/images/aeotec/zw129.png b/config/images/aeotec/zw129.png new file mode 100644 index 0000000000..7505874ebc Binary files /dev/null and b/config/images/aeotec/zw129.png differ diff --git a/config/images/aeotec/zw130.png b/config/images/aeotec/zw130.png new file mode 100644 index 0000000000..0108d745cf Binary files /dev/null and b/config/images/aeotec/zw130.png differ diff --git a/config/images/aeotec/zw132.png b/config/images/aeotec/zw132.png new file mode 100644 index 0000000000..90d2a6b7cf Binary files /dev/null and b/config/images/aeotec/zw132.png differ diff --git a/config/images/aeotec/zw139.png b/config/images/aeotec/zw139.png new file mode 100644 index 0000000000..d285be89ad Binary files /dev/null and b/config/images/aeotec/zw139.png differ diff --git a/config/images/aeotec/zw140.png b/config/images/aeotec/zw140.png new file mode 100644 index 0000000000..90d2a6b7cf Binary files /dev/null and b/config/images/aeotec/zw140.png differ diff --git a/config/images/aeotec/zw141.png b/config/images/aeotec/zw141.png new file mode 100644 index 0000000000..90d2a6b7cf Binary files /dev/null and b/config/images/aeotec/zw141.png differ diff --git a/config/images/aeotec/zw162.png b/config/images/aeotec/zw162.png new file mode 100644 index 0000000000..27ff27ccdb Binary files /dev/null and b/config/images/aeotec/zw162.png differ diff --git a/config/images/aeotec/zw164.png b/config/images/aeotec/zw164.png new file mode 100644 index 0000000000..17be7a7963 Binary files /dev/null and b/config/images/aeotec/zw164.png differ diff --git a/config/images/aeotec/zw187.png b/config/images/aeotec/zw187.png new file mode 100644 index 0000000000..3d0b99a80e Binary files /dev/null and b/config/images/aeotec/zw187.png differ diff --git a/config/images/aeotec/zw189.png b/config/images/aeotec/zw189.png new file mode 100644 index 0000000000..8094d4f09e Binary files /dev/null and b/config/images/aeotec/zw189.png differ diff --git a/config/images/aeotec/zw195.png b/config/images/aeotec/zw195.png new file mode 100644 index 0000000000..df8cd6ce98 Binary files /dev/null and b/config/images/aeotec/zw195.png differ diff --git a/config/images/aeotec/zwa001.png b/config/images/aeotec/zwa001.png new file mode 100644 index 0000000000..a48b9fbbd9 Binary files /dev/null and b/config/images/aeotec/zwa001.png differ diff --git a/config/images/aeotec/zwa002.png b/config/images/aeotec/zwa002.png new file mode 100644 index 0000000000..c5603e56f6 Binary files /dev/null and b/config/images/aeotec/zwa002.png differ diff --git a/config/images/aeotec/zwa003.png b/config/images/aeotec/zwa003.png new file mode 100644 index 0000000000..f7dcb051bb Binary files /dev/null and b/config/images/aeotec/zwa003.png differ diff --git a/config/images/aeotec/zwa004.png b/config/images/aeotec/zwa004.png new file mode 100644 index 0000000000..67eb10dc3d Binary files /dev/null and b/config/images/aeotec/zwa004.png differ diff --git a/config/images/aeotec/zwa005.png b/config/images/aeotec/zwa005.png new file mode 100644 index 0000000000..e07210f15c Binary files /dev/null and b/config/images/aeotec/zwa005.png differ diff --git a/config/images/aeotec/zwa006.png b/config/images/aeotec/zwa006.png new file mode 100644 index 0000000000..99672a6e13 Binary files /dev/null and b/config/images/aeotec/zwa006.png differ diff --git a/config/images/alfred/DB2.png b/config/images/alfred/DB2.png new file mode 100644 index 0000000000..8924c88b67 Binary files /dev/null and b/config/images/alfred/DB2.png differ diff --git a/config/images/assa_abloy/ConexisL1.png b/config/images/assa_abloy/ConexisL1.png new file mode 100644 index 0000000000..fecc07e316 Binary files /dev/null and b/config/images/assa_abloy/ConexisL1.png differ diff --git a/config/images/assa_abloy/KeyfreeConnected-plus.png b/config/images/assa_abloy/KeyfreeConnected-plus.png new file mode 100644 index 0000000000..20cf676ecc Binary files /dev/null and b/config/images/assa_abloy/KeyfreeConnected-plus.png differ diff --git a/config/images/assa_abloy/PushButtonDeadbolt.png b/config/images/assa_abloy/PushButtonDeadbolt.png index 6f0a2e1492..7d250a8661 100644 Binary files a/config/images/assa_abloy/PushButtonDeadbolt.png and b/config/images/assa_abloy/PushButtonDeadbolt.png differ diff --git a/config/images/assa_abloy/TouchDeadbolt.png b/config/images/assa_abloy/TouchDeadbolt.png index 918827a583..a4346c8c73 100644 Binary files a/config/images/assa_abloy/TouchDeadbolt.png and b/config/images/assa_abloy/TouchDeadbolt.png differ diff --git a/config/images/assa_abloy/nexTouch.png b/config/images/assa_abloy/nexTouch.png new file mode 100644 index 0000000000..d35c108927 Binary files /dev/null and b/config/images/assa_abloy/nexTouch.png differ diff --git a/config/images/august/asl-03.png b/config/images/august/asl-03.png new file mode 100644 index 0000000000..b70caa420f Binary files /dev/null and b/config/images/august/asl-03.png differ diff --git a/config/images/devolo/mt02755.png b/config/images/devolo/mt02755.png new file mode 100644 index 0000000000..7f3c15e19e Binary files /dev/null and b/config/images/devolo/mt02755.png differ diff --git a/config/images/devolo/mt02758.png b/config/images/devolo/mt02758.png new file mode 100644 index 0000000000..82ca914b73 Binary files /dev/null and b/config/images/devolo/mt02758.png differ diff --git a/config/images/devolo/mt2756.png b/config/images/devolo/mt2756.png new file mode 100644 index 0000000000..77601e8bff Binary files /dev/null and b/config/images/devolo/mt2756.png differ diff --git a/config/images/dome/0002.png b/config/images/dome/0002.png new file mode 100644 index 0000000000..30a1bcd461 Binary files /dev/null and b/config/images/dome/0002.png differ diff --git a/config/images/dome/0085.png b/config/images/dome/0085.png new file mode 100644 index 0000000000..f24bd81697 Binary files /dev/null and b/config/images/dome/0085.png differ diff --git a/config/images/dome/0086.png b/config/images/dome/0086.png new file mode 100644 index 0000000000..d2061918bd Binary files /dev/null and b/config/images/dome/0086.png differ diff --git a/config/images/dome/0088.png b/config/images/dome/0088.png new file mode 100644 index 0000000000..1fbd88afb2 Binary files /dev/null and b/config/images/dome/0088.png differ diff --git a/config/images/dome/0201.png b/config/images/dome/0201.png new file mode 100644 index 0000000000..bfb8f64b62 Binary files /dev/null and b/config/images/dome/0201.png differ diff --git a/config/images/domitech/zb22uk.png b/config/images/domitech/zb22uk.png new file mode 100644 index 0000000000..d401f1a24b Binary files /dev/null and b/config/images/domitech/zb22uk.png differ diff --git a/config/images/domitech/ze27eu.png b/config/images/domitech/ze27eu.png new file mode 100644 index 0000000000..442dbfc04b Binary files /dev/null and b/config/images/domitech/ze27eu.png differ diff --git a/config/images/dragontech/wd-100.png b/config/images/dragontech/wd-100.png index 3ac10659e7..37785fde85 100644 Binary files a/config/images/dragontech/wd-100.png and b/config/images/dragontech/wd-100.png differ diff --git a/config/images/ecolink/doorwindow.png b/config/images/ecolink/doorwindow.png index 1587d3b9e1..a546a9ec38 100644 Binary files a/config/images/ecolink/doorwindow.png and b/config/images/ecolink/doorwindow.png differ diff --git a/config/images/ecolink/firefighter.png b/config/images/ecolink/firefighter.png new file mode 100644 index 0000000000..0840787f50 Binary files /dev/null and b/config/images/ecolink/firefighter.png differ diff --git a/config/images/ecolink/floodfreeze.png b/config/images/ecolink/floodfreeze.png new file mode 100644 index 0000000000..bb6c6516f5 Binary files /dev/null and b/config/images/ecolink/floodfreeze.png differ diff --git a/config/images/ecolink/motion.png b/config/images/ecolink/motion.png index 1a8c2bf7b6..9e9ac45954 100644 Binary files a/config/images/ecolink/motion.png and b/config/images/ecolink/motion.png differ diff --git a/config/images/ecolink/tiltsensor.png b/config/images/ecolink/tiltsensor.png index bf5b60dc41..a020a35b82 100644 Binary files a/config/images/ecolink/tiltsensor.png and b/config/images/ecolink/tiltsensor.png differ diff --git a/config/images/enerwave/zw15rmplus.png b/config/images/enerwave/zw15rmplus.png new file mode 100644 index 0000000000..5d9f000524 Binary files /dev/null and b/config/images/enerwave/zw15rmplus.png differ diff --git a/config/images/enerwave/zw20rm.png b/config/images/enerwave/zw20rm.png new file mode 100644 index 0000000000..659b445915 Binary files /dev/null and b/config/images/enerwave/zw20rm.png differ diff --git a/config/images/enerwave/zwn-bpc.png b/config/images/enerwave/zwn-bpc.png new file mode 100644 index 0000000000..87caa3257e Binary files /dev/null and b/config/images/enerwave/zwn-bpc.png differ diff --git a/config/images/enerwave/zwnrsm1plus.png b/config/images/enerwave/zwnrsm1plus.png new file mode 100644 index 0000000000..6172bc114d Binary files /dev/null and b/config/images/enerwave/zwnrsm1plus.png differ diff --git a/config/images/eurotronic/eur_cometz.png b/config/images/eurotronic/eur_cometz.png new file mode 100644 index 0000000000..59c6778bbe Binary files /dev/null and b/config/images/eurotronic/eur_cometz.png differ diff --git a/config/images/eurotronic/eur_spiritz.png b/config/images/eurotronic/eur_spiritz.png new file mode 100644 index 0000000000..f150486df3 Binary files /dev/null and b/config/images/eurotronic/eur_spiritz.png differ diff --git a/config/images/everspring/ad147.png b/config/images/everspring/ad147.png index 526604cffa..dbe59ab720 100644 Binary files a/config/images/everspring/ad147.png and b/config/images/everspring/ad147.png differ diff --git a/config/images/everspring/sp815.png b/config/images/everspring/sp815.png new file mode 100644 index 0000000000..e6e9afd7fc Binary files /dev/null and b/config/images/everspring/sp815.png differ diff --git a/config/images/everspring/sp816.png b/config/images/everspring/sp816.png new file mode 100644 index 0000000000..9923615d7b Binary files /dev/null and b/config/images/everspring/sp816.png differ diff --git a/config/images/fibaro/fgbs222.png b/config/images/fibaro/fgbs222.png new file mode 100644 index 0000000000..77dc0c808b Binary files /dev/null and b/config/images/fibaro/fgbs222.png differ diff --git a/config/images/fibaro/fgcd001.png b/config/images/fibaro/fgcd001.png new file mode 100644 index 0000000000..0fa6219f48 Binary files /dev/null and b/config/images/fibaro/fgcd001.png differ diff --git a/config/images/fibaro/fgd212.png b/config/images/fibaro/fgd212.png index 5923c9f3cd..01e43ddca2 100644 Binary files a/config/images/fibaro/fgd212.png and b/config/images/fibaro/fgd212.png differ diff --git a/config/images/fibaro/fgdw2.png b/config/images/fibaro/fgdw2.png new file mode 100644 index 0000000000..6f3d33439e Binary files /dev/null and b/config/images/fibaro/fgdw2.png differ diff --git a/config/images/fibaro/fgfs101zw5.png b/config/images/fibaro/fgfs101zw5.png index fce65640b5..37e62f809f 100644 Binary files a/config/images/fibaro/fgfs101zw5.png and b/config/images/fibaro/fgfs101zw5.png differ diff --git a/config/images/fibaro/fggc001.png b/config/images/fibaro/fggc001.png new file mode 100644 index 0000000000..d32c04bd66 Binary files /dev/null and b/config/images/fibaro/fggc001.png differ diff --git a/config/images/fibaro/fgk10x.png b/config/images/fibaro/fgk10x.png new file mode 100644 index 0000000000..e6508e0816 Binary files /dev/null and b/config/images/fibaro/fgk10x.png differ diff --git a/config/images/fibaro/fgkf601.png b/config/images/fibaro/fgkf601.png new file mode 100644 index 0000000000..9a8b8595d0 Binary files /dev/null and b/config/images/fibaro/fgkf601.png differ diff --git a/config/images/fibaro/fgmszw5.png b/config/images/fibaro/fgmszw5.png index 4be05de962..181a25530a 100644 Binary files a/config/images/fibaro/fgmszw5.png and b/config/images/fibaro/fgmszw5.png differ diff --git a/config/images/fibaro/fgpb101.png b/config/images/fibaro/fgpb101.png new file mode 100644 index 0000000000..f934680ab9 Binary files /dev/null and b/config/images/fibaro/fgpb101.png differ diff --git a/config/images/fibaro/fgr223.png b/config/images/fibaro/fgr223.png new file mode 100644 index 0000000000..c1c7629b60 Binary files /dev/null and b/config/images/fibaro/fgr223.png differ diff --git a/config/images/fibaro/fgs213.png b/config/images/fibaro/fgs213.png new file mode 100644 index 0000000000..4e7810ee6d Binary files /dev/null and b/config/images/fibaro/fgs213.png differ diff --git a/config/images/fibaro/fgs223.png b/config/images/fibaro/fgs223.png new file mode 100644 index 0000000000..4afcf393a8 Binary files /dev/null and b/config/images/fibaro/fgs223.png differ diff --git a/config/images/fibaro/fgsd002.png b/config/images/fibaro/fgsd002.png index 99a0b84a8c..6ef9bbdeb1 100644 Binary files a/config/images/fibaro/fgsd002.png and b/config/images/fibaro/fgsd002.png differ diff --git a/config/images/fibaro/fgt001.png b/config/images/fibaro/fgt001.png new file mode 100644 index 0000000000..3f66a12cb5 Binary files /dev/null and b/config/images/fibaro/fgt001.png differ diff --git a/config/images/fibaro/fgwd111.png b/config/images/fibaro/fgwd111.png new file mode 100644 index 0000000000..b353a48ecc Binary files /dev/null and b/config/images/fibaro/fgwd111.png differ diff --git a/config/images/fibaro/fgwoe.png b/config/images/fibaro/fgwoe.png new file mode 100644 index 0000000000..f31bc499ae Binary files /dev/null and b/config/images/fibaro/fgwoe.png differ diff --git a/config/images/fibaro/fgwpfzw5.png b/config/images/fibaro/fgwpfzw5.png new file mode 100644 index 0000000000..5e71cf77bb Binary files /dev/null and b/config/images/fibaro/fgwpfzw5.png differ diff --git a/config/images/fibaro/fgwpg111.png b/config/images/fibaro/fgwpg111.png new file mode 100644 index 0000000000..1263fdc0bf Binary files /dev/null and b/config/images/fibaro/fgwpg111.png differ diff --git a/config/images/fibaro/fgwr111.png b/config/images/fibaro/fgwr111.png new file mode 100644 index 0000000000..da035da117 Binary files /dev/null and b/config/images/fibaro/fgwr111.png differ diff --git a/config/images/forest/fs2z5232000002.png b/config/images/forest/fs2z5232000002.png index 41b341667e..7e9bccd65e 100644 Binary files a/config/images/forest/fs2z5232000002.png and b/config/images/forest/fs2z5232000002.png differ diff --git a/config/images/fortrezz/fmi.png b/config/images/fortrezz/fmi.png new file mode 100644 index 0000000000..a256a242e6 Binary files /dev/null and b/config/images/fortrezz/fmi.png differ diff --git a/config/images/fortrezz/mimo2plus.png b/config/images/fortrezz/mimo2plus.png new file mode 100644 index 0000000000..96cac59d68 Binary files /dev/null and b/config/images/fortrezz/mimo2plus.png differ diff --git a/config/images/fortrezz/mimolite.png b/config/images/fortrezz/mimolite.png new file mode 100644 index 0000000000..0caf04c8c1 Binary files /dev/null and b/config/images/fortrezz/mimolite.png differ diff --git a/config/images/ge/12724-dimmer.png b/config/images/ge/12724-dimmer.png index 9d8afa3d93..4057005ac7 100644 Binary files a/config/images/ge/12724-dimmer.png and b/config/images/ge/12724-dimmer.png differ diff --git a/config/images/ge/14282-plugin-switch.png b/config/images/ge/14282-plugin-switch.png index 4a0b5c119c..1a62ea679c 100644 Binary files a/config/images/ge/14282-plugin-switch.png and b/config/images/ge/14282-plugin-switch.png differ diff --git a/config/images/ge/14284.png b/config/images/ge/14284.png new file mode 100644 index 0000000000..aff35b0686 Binary files /dev/null and b/config/images/ge/14284.png differ diff --git a/config/images/ge/14288-outlet.png b/config/images/ge/14288-outlet.png new file mode 100644 index 0000000000..46d3ca931a Binary files /dev/null and b/config/images/ge/14288-outlet.png differ diff --git a/config/images/ge/14291-switch.png b/config/images/ge/14291-switch.png index 6a55b4c912..780264fa77 100644 Binary files a/config/images/ge/14291-switch.png and b/config/images/ge/14291-switch.png differ diff --git a/config/images/ge/14292-toggle-switch.png b/config/images/ge/14292-toggle-switch.png new file mode 100644 index 0000000000..569d9d0a11 Binary files /dev/null and b/config/images/ge/14292-toggle-switch.png differ diff --git a/config/images/ge/14294-dimmer.png b/config/images/ge/14294-dimmer.png index 6a55b4c912..d50afdbcd9 100644 Binary files a/config/images/ge/14294-dimmer.png and b/config/images/ge/14294-dimmer.png differ diff --git a/config/images/ge/14295-dimmer-toggle.png b/config/images/ge/14295-dimmer-toggle.png new file mode 100644 index 0000000000..9a36a69469 Binary files /dev/null and b/config/images/ge/14295-dimmer-toggle.png differ diff --git a/config/images/ge/26931-motion-switch.png b/config/images/ge/26931-motion-switch.png new file mode 100644 index 0000000000..8c0eec35a9 Binary files /dev/null and b/config/images/ge/26931-motion-switch.png differ diff --git a/config/images/ge/26933-motion-dimmer.png b/config/images/ge/26933-motion-dimmer.png new file mode 100644 index 0000000000..751c7cfac0 Binary files /dev/null and b/config/images/ge/26933-motion-dimmer.png differ diff --git a/config/images/ge/28167-plugin-dimmer.png b/config/images/ge/28167-plugin-dimmer.png index dcc1d0a8e7..49fc19840b 100644 Binary files a/config/images/ge/28167-plugin-dimmer.png and b/config/images/ge/28167-plugin-dimmer.png differ diff --git a/config/images/ge/28169-plugin-switch.png b/config/images/ge/28169-plugin-switch.png index 225782c35f..c4157ca2d5 100644 Binary files a/config/images/ge/28169-plugin-switch.png and b/config/images/ge/28169-plugin-switch.png differ diff --git a/config/images/ge/46201-switch.png b/config/images/ge/46201-switch.png new file mode 100644 index 0000000000..9a58c2e80e Binary files /dev/null and b/config/images/ge/46201-switch.png differ diff --git a/config/images/ge/hinge-pin.png b/config/images/ge/hinge-pin.png new file mode 100644 index 0000000000..aea76974ee Binary files /dev/null and b/config/images/ge/hinge-pin.png differ diff --git a/config/images/ge/receptacle.png b/config/images/ge/receptacle.png index f5de3e6702..46d3ca931a 100644 Binary files a/config/images/ge/receptacle.png and b/config/images/ge/receptacle.png differ diff --git a/config/images/ge/ze26i.png b/config/images/ge/ze26i.png new file mode 100644 index 0000000000..0be0494ea5 Binary files /dev/null and b/config/images/ge/ze26i.png differ diff --git a/config/images/ge/zw6302.png b/config/images/ge/zw6302.png new file mode 100644 index 0000000000..d47c187c91 Binary files /dev/null and b/config/images/ge/zw6302.png differ diff --git a/config/images/gr/gr-302n.png b/config/images/gr/gr-302n.png new file mode 100644 index 0000000000..dc316ec5fd Binary files /dev/null and b/config/images/gr/gr-302n.png differ diff --git a/config/images/gr/gr105n.png b/config/images/gr/gr105n.png new file mode 100644 index 0000000000..30a1bcd461 Binary files /dev/null and b/config/images/gr/gr105n.png differ diff --git a/config/images/graber/brz1.png b/config/images/graber/brz1.png new file mode 100644 index 0000000000..bf272cc60f Binary files /dev/null and b/config/images/graber/brz1.png differ diff --git a/config/images/graber/csz1.png b/config/images/graber/csz1.png new file mode 100644 index 0000000000..bf272cc60f Binary files /dev/null and b/config/images/graber/csz1.png differ diff --git a/config/images/graber/rsz1.png b/config/images/graber/rsz1.png new file mode 100644 index 0000000000..bf272cc60f Binary files /dev/null and b/config/images/graber/rsz1.png differ diff --git a/config/images/graber/vcz1.png b/config/images/graber/vcz1.png new file mode 100644 index 0000000000..bf272cc60f Binary files /dev/null and b/config/images/graber/vcz1.png differ diff --git a/config/images/guardtec/gkw2000d.png b/config/images/guardtec/gkw2000d.png new file mode 100644 index 0000000000..48a0d02183 Binary files /dev/null and b/config/images/guardtec/gkw2000d.png differ diff --git a/config/images/hank/hkzw-dws01.png b/config/images/hank/hkzw-dws01.png new file mode 100644 index 0000000000..bc33783c1d Binary files /dev/null and b/config/images/hank/hkzw-dws01.png differ diff --git a/config/images/hank/hkzw-fld01.png b/config/images/hank/hkzw-fld01.png new file mode 100644 index 0000000000..aa5841cc7e Binary files /dev/null and b/config/images/hank/hkzw-fld01.png differ diff --git a/config/images/hank/hkzw-ms01.png b/config/images/hank/hkzw-ms01.png new file mode 100644 index 0000000000..dbf7604c58 Binary files /dev/null and b/config/images/hank/hkzw-ms01.png differ diff --git a/config/images/hank/hkzw-ms02-200.png b/config/images/hank/hkzw-ms02-200.png new file mode 100644 index 0000000000..7c2788aeab Binary files /dev/null and b/config/images/hank/hkzw-ms02-200.png differ diff --git a/config/images/hank/hkzw-rgb01.png b/config/images/hank/hkzw-rgb01.png new file mode 100644 index 0000000000..09391ebcb1 Binary files /dev/null and b/config/images/hank/hkzw-rgb01.png differ diff --git a/config/images/hank/hkzw-so01-smartplug.png b/config/images/hank/hkzw-so01-smartplug.png new file mode 100644 index 0000000000..f0930ca958 Binary files /dev/null and b/config/images/hank/hkzw-so01-smartplug.png differ diff --git a/config/images/hank/hkzw-so03.png b/config/images/hank/hkzw-so03.png new file mode 100644 index 0000000000..191a16621f Binary files /dev/null and b/config/images/hank/hkzw-so03.png differ diff --git a/config/images/hank/hkzw-so05-smartplug.png b/config/images/hank/hkzw-so05-smartplug.png new file mode 100644 index 0000000000..3fd0dd9f9f Binary files /dev/null and b/config/images/hank/hkzw-so05-smartplug.png differ diff --git a/config/images/hank/scenecontroller1.png b/config/images/hank/scenecontroller1.png new file mode 100644 index 0000000000..6b66ea127c Binary files /dev/null and b/config/images/hank/scenecontroller1.png differ diff --git a/config/images/hank/scenecontroller4.png b/config/images/hank/scenecontroller4.png new file mode 100644 index 0000000000..ea02d0d112 Binary files /dev/null and b/config/images/hank/scenecontroller4.png differ diff --git a/config/images/heiman/HS1CA-Z.png b/config/images/heiman/HS1CA-Z.png new file mode 100644 index 0000000000..43cdf327ca Binary files /dev/null and b/config/images/heiman/HS1CA-Z.png differ diff --git a/config/images/heiman/HS1CG-Z.png b/config/images/heiman/HS1CG-Z.png new file mode 100644 index 0000000000..5a027164fb Binary files /dev/null and b/config/images/heiman/HS1CG-Z.png differ diff --git a/config/images/heiman/HS1DS-Z.png b/config/images/heiman/HS1DS-Z.png new file mode 100644 index 0000000000..97fcbb8230 Binary files /dev/null and b/config/images/heiman/HS1DS-Z.png differ diff --git a/config/images/heiman/HS1HT-Z.png b/config/images/heiman/HS1HT-Z.png new file mode 100644 index 0000000000..83b261cea0 Binary files /dev/null and b/config/images/heiman/HS1HT-Z.png differ diff --git a/config/images/heiman/HS1MS-Z.png b/config/images/heiman/HS1MS-Z.png new file mode 100644 index 0000000000..2938c96dc6 Binary files /dev/null and b/config/images/heiman/HS1MS-Z.png differ diff --git a/config/images/heiman/HS1SA-Z.png b/config/images/heiman/HS1SA-Z.png new file mode 100644 index 0000000000..9ab0a3bb43 Binary files /dev/null and b/config/images/heiman/HS1SA-Z.png differ diff --git a/config/images/heiman/HS1WL-Z.png b/config/images/heiman/HS1WL-Z.png new file mode 100644 index 0000000000..01721b854d Binary files /dev/null and b/config/images/heiman/HS1WL-Z.png differ diff --git a/config/images/heiman/HS2SK-Z.png b/config/images/heiman/HS2SK-Z.png new file mode 100644 index 0000000000..ed3e6ca130 Binary files /dev/null and b/config/images/heiman/HS2SK-Z.png differ diff --git a/config/images/homeseer/hs-ds100plus.png b/config/images/homeseer/hs-ds100plus.png new file mode 100644 index 0000000000..6a717d0675 Binary files /dev/null and b/config/images/homeseer/hs-ds100plus.png differ diff --git a/config/images/homeseer/hs-fc200plus.png b/config/images/homeseer/hs-fc200plus.png new file mode 100644 index 0000000000..d5daa1818d Binary files /dev/null and b/config/images/homeseer/hs-fc200plus.png differ diff --git a/config/images/homeseer/hs-fls100plus.png b/config/images/homeseer/hs-fls100plus.png new file mode 100644 index 0000000000..c3b347ade2 Binary files /dev/null and b/config/images/homeseer/hs-fls100plus.png differ diff --git a/config/images/homeseer/hs-ls100plus.png b/config/images/homeseer/hs-ls100plus.png new file mode 100644 index 0000000000..c3342e8b3d Binary files /dev/null and b/config/images/homeseer/hs-ls100plus.png differ diff --git a/config/images/homeseer/hs-ms100plus.png b/config/images/homeseer/hs-ms100plus.png new file mode 100644 index 0000000000..fa712ca6fd Binary files /dev/null and b/config/images/homeseer/hs-ms100plus.png differ diff --git a/config/images/homeseer/hs-wd100plus.png b/config/images/homeseer/hs-wd100plus.png new file mode 100644 index 0000000000..5cf3db40ed Binary files /dev/null and b/config/images/homeseer/hs-wd100plus.png differ diff --git a/config/images/homeseer/hs-wd200plus.png b/config/images/homeseer/hs-wd200plus.png new file mode 100644 index 0000000000..5cf3db40ed Binary files /dev/null and b/config/images/homeseer/hs-wd200plus.png differ diff --git a/config/images/homeseer/hs-ws100plus.png b/config/images/homeseer/hs-ws100plus.png new file mode 100644 index 0000000000..f1bb909d85 Binary files /dev/null and b/config/images/homeseer/hs-ws100plus.png differ diff --git a/config/images/homeseer/hs-ws200plus.png b/config/images/homeseer/hs-ws200plus.png new file mode 100644 index 0000000000..f1bb909d85 Binary files /dev/null and b/config/images/homeseer/hs-ws200plus.png differ diff --git a/config/images/homeseer/hsm200.png b/config/images/homeseer/hsm200.png index bc032602b5..d41f2d36dd 100644 Binary files a/config/images/homeseer/hsm200.png and b/config/images/homeseer/hsm200.png differ diff --git a/config/images/honeywell/39351-ZW3005.png b/config/images/honeywell/39351-ZW3005.png new file mode 100644 index 0000000000..d50afdbcd9 Binary files /dev/null and b/config/images/honeywell/39351-ZW3005.png differ diff --git a/config/images/honeywell/th6320zw2003.png b/config/images/honeywell/th6320zw2003.png new file mode 100644 index 0000000000..0719604d77 Binary files /dev/null and b/config/images/honeywell/th6320zw2003.png differ diff --git a/config/images/horstmann/scsc17.png b/config/images/horstmann/scsc17.png index bc631b64d3..59c6778bbe 100644 Binary files a/config/images/horstmann/scsc17.png and b/config/images/horstmann/scsc17.png differ diff --git a/config/images/horstmann/srt321.png b/config/images/horstmann/srt321.png new file mode 100644 index 0000000000..068e987382 Binary files /dev/null and b/config/images/horstmann/srt321.png differ diff --git a/config/images/horstmann/ssr303.png b/config/images/horstmann/ssr303.png new file mode 100644 index 0000000000..8e8ad2fe17 Binary files /dev/null and b/config/images/horstmann/ssr303.png differ diff --git a/config/images/idlock/idlock101.png b/config/images/idlock/idlock101.png new file mode 100644 index 0000000000..6f6ad0ae45 Binary files /dev/null and b/config/images/idlock/idlock101.png differ diff --git a/config/images/idlock/idlock150.png b/config/images/idlock/idlock150.png new file mode 100644 index 0000000000..433e57091e Binary files /dev/null and b/config/images/idlock/idlock150.png differ diff --git a/config/images/inovelli/lzw30-sn.png b/config/images/inovelli/lzw30-sn.png new file mode 100644 index 0000000000..0752c20d80 Binary files /dev/null and b/config/images/inovelli/lzw30-sn.png differ diff --git a/config/images/inovelli/lzw30.png b/config/images/inovelli/lzw30.png new file mode 100644 index 0000000000..5f55d720d2 Binary files /dev/null and b/config/images/inovelli/lzw30.png differ diff --git a/config/images/inovelli/simple_module.png b/config/images/inovelli/simple_module.png new file mode 100644 index 0000000000..42b55313a9 Binary files /dev/null and b/config/images/inovelli/simple_module.png differ diff --git a/config/images/kaipule/im20.png b/config/images/kaipule/im20.png new file mode 100644 index 0000000000..d7c1487c17 Binary files /dev/null and b/config/images/kaipule/im20.png differ diff --git a/config/images/kwikset/smartcode.png b/config/images/kwikset/smartcode.png index 9ff384a13b..be0e552290 100644 Binary files a/config/images/kwikset/smartcode.png and b/config/images/kwikset/smartcode.png differ diff --git a/config/images/leviton/dz15s.png b/config/images/leviton/dz15s.png new file mode 100644 index 0000000000..c0b0605476 Binary files /dev/null and b/config/images/leviton/dz15s.png differ diff --git a/config/images/leviton/dz6hd.png b/config/images/leviton/dz6hd.png new file mode 100644 index 0000000000..3696b3fbdc Binary files /dev/null and b/config/images/leviton/dz6hd.png differ diff --git a/config/images/leviton/dzpd3.png b/config/images/leviton/dzpd3.png new file mode 100644 index 0000000000..02fb13f2cc Binary files /dev/null and b/config/images/leviton/dzpd3.png differ diff --git a/config/images/linear/WD500Z5-1.png b/config/images/linear/WD500Z5-1.png new file mode 100644 index 0000000000..16179a378b Binary files /dev/null and b/config/images/linear/WD500Z5-1.png differ diff --git a/config/images/linear/gd00z-7.png b/config/images/linear/gd00z-7.png new file mode 100644 index 0000000000..6f4f9145e3 Binary files /dev/null and b/config/images/linear/gd00z-7.png differ diff --git a/config/images/logicsoft/ZHC5010.png b/config/images/logicsoft/ZHC5010.png new file mode 100644 index 0000000000..58519f890e Binary files /dev/null and b/config/images/logicsoft/ZHC5010.png differ diff --git a/config/images/mcohome/mh7h.png b/config/images/mcohome/mh7h.png new file mode 100644 index 0000000000..9215f85ff4 Binary files /dev/null and b/config/images/mcohome/mh7h.png differ diff --git a/config/images/mcohome/mhp220.png b/config/images/mcohome/mhp220.png new file mode 100644 index 0000000000..8d8b4a3acc Binary files /dev/null and b/config/images/mcohome/mhp220.png differ diff --git a/config/images/mcohome/mhp511.png b/config/images/mcohome/mhp511.png new file mode 100644 index 0000000000..73f39d0a24 Binary files /dev/null and b/config/images/mcohome/mhp511.png differ diff --git a/config/images/nodon/msp31xxMicroSmartPlug.png b/config/images/nodon/msp31xxMicroSmartPlug.png new file mode 100644 index 0000000000..62eb003604 Binary files /dev/null and b/config/images/nodon/msp31xxMicroSmartPlug.png differ diff --git a/config/images/oomi/ft100.png b/config/images/oomi/ft100.png new file mode 100644 index 0000000000..329d37ee8e Binary files /dev/null and b/config/images/oomi/ft100.png differ diff --git a/config/images/oomi/ft111.png b/config/images/oomi/ft111.png new file mode 100644 index 0000000000..d285be89ad Binary files /dev/null and b/config/images/oomi/ft111.png differ diff --git a/config/images/permundo/psc132zw.png b/config/images/permundo/psc132zw.png new file mode 100644 index 0000000000..509cfc8812 Binary files /dev/null and b/config/images/permundo/psc132zw.png differ diff --git a/config/images/permundo/psc234zw.png b/config/images/permundo/psc234zw.png new file mode 100644 index 0000000000..038dc9966e Binary files /dev/null and b/config/images/permundo/psc234zw.png differ diff --git a/config/images/philio/pad02.png b/config/images/philio/pad02.png new file mode 100644 index 0000000000..e3060a890e Binary files /dev/null and b/config/images/philio/pad02.png differ diff --git a/config/images/philio/pan16.png b/config/images/philio/pan16.png new file mode 100644 index 0000000000..922b0f0c0d Binary files /dev/null and b/config/images/philio/pan16.png differ diff --git a/config/images/philio/phpab01.png b/config/images/philio/phpab01.png new file mode 100644 index 0000000000..8a8c7d9642 Binary files /dev/null and b/config/images/philio/phpab01.png differ diff --git a/config/images/philio/phpat02.png b/config/images/philio/phpat02.png index 4348857273..5594563ed9 100644 Binary files a/config/images/philio/phpat02.png and b/config/images/philio/phpat02.png differ diff --git a/config/images/philio/phpsg01.png b/config/images/philio/phpsg01.png index abac61b113..1b0ebe15d3 100644 Binary files a/config/images/philio/phpsg01.png and b/config/images/philio/phpsg01.png differ diff --git a/config/images/philio/pse02.png b/config/images/philio/pse02.png new file mode 100644 index 0000000000..b2c5cddcd0 Binary files /dev/null and b/config/images/philio/pse02.png differ diff --git a/config/images/philio/psp05.png b/config/images/philio/psp05.png new file mode 100644 index 0000000000..c076fc43fe Binary files /dev/null and b/config/images/philio/psp05.png differ diff --git a/config/images/philio/pst02-1c.png b/config/images/philio/pst02-1c.png index c6dfcbde22..e0de889b91 100644 Binary files a/config/images/philio/pst02-1c.png and b/config/images/philio/pst02-1c.png differ diff --git a/config/images/philio/pst02-b.png b/config/images/philio/pst02-b.png index 82c4a4e8c8..e0de889b91 100644 Binary files a/config/images/philio/pst02-b.png and b/config/images/philio/pst02-b.png differ diff --git a/config/images/polycontrol/doorlock.png b/config/images/polycontrol/doorlock.png index 6877601497..2fbd775e4a 100644 Binary files a/config/images/polycontrol/doorlock.png and b/config/images/polycontrol/doorlock.png differ diff --git a/config/images/polycontrol/doorlockv3.png b/config/images/polycontrol/doorlockv3.png new file mode 100644 index 0000000000..5d760f2ead Binary files /dev/null and b/config/images/polycontrol/doorlockv3.png differ diff --git a/config/images/popp/004407.png b/config/images/popp/004407.png new file mode 100644 index 0000000000..79e4a8ad3f Binary files /dev/null and b/config/images/popp/004407.png differ diff --git a/config/images/popp/009303.png b/config/images/popp/009303.png new file mode 100644 index 0000000000..91eedc2ae9 Binary files /dev/null and b/config/images/popp/009303.png differ diff --git a/config/images/popp/009402.png b/config/images/popp/009402.png new file mode 100644 index 0000000000..01236ec139 Binary files /dev/null and b/config/images/popp/009402.png differ diff --git a/config/images/popp/012501.png b/config/images/popp/012501.png new file mode 100644 index 0000000000..c9b4116689 Binary files /dev/null and b/config/images/popp/012501.png differ diff --git a/config/images/popp/700045.png b/config/images/popp/700045.png new file mode 100644 index 0000000000..d72941f8ac Binary files /dev/null and b/config/images/popp/700045.png differ diff --git a/config/images/popp/700168.png b/config/images/popp/700168.png new file mode 100644 index 0000000000..49da7e84ef Binary files /dev/null and b/config/images/popp/700168.png differ diff --git a/config/images/popp/700397.png b/config/images/popp/700397.png new file mode 100644 index 0000000000..ef11c2459b Binary files /dev/null and b/config/images/popp/700397.png differ diff --git a/config/images/popp/dwt.png b/config/images/popp/dwt.png new file mode 100644 index 0000000000..893935c3c4 Binary files /dev/null and b/config/images/popp/dwt.png differ diff --git a/config/images/popp/smoke-detector.png b/config/images/popp/smoke-detector.png new file mode 100644 index 0000000000..7326ed8baf Binary files /dev/null and b/config/images/popp/smoke-detector.png differ diff --git a/config/images/popp/solar-siren.png b/config/images/popp/solar-siren.png new file mode 100644 index 0000000000..87ea46ddbd Binary files /dev/null and b/config/images/popp/solar-siren.png differ diff --git a/config/images/popp/zweather.png b/config/images/popp/zweather.png new file mode 100644 index 0000000000..4e155740ab Binary files /dev/null and b/config/images/popp/zweather.png differ diff --git a/config/images/qubino/ZMNHADx.png b/config/images/qubino/ZMNHADx.png new file mode 100644 index 0000000000..af7137e288 Binary files /dev/null and b/config/images/qubino/ZMNHADx.png differ diff --git a/config/images/qubino/ZMNHBDx.png b/config/images/qubino/ZMNHBDx.png new file mode 100644 index 0000000000..291566fac1 Binary files /dev/null and b/config/images/qubino/ZMNHBDx.png differ diff --git a/config/images/qubino/ZMNHCDx.png b/config/images/qubino/ZMNHCDx.png new file mode 100644 index 0000000000..df3a1b7040 Binary files /dev/null and b/config/images/qubino/ZMNHCDx.png differ diff --git a/config/images/qubino/ZMNHDDx.png b/config/images/qubino/ZMNHDDx.png new file mode 100644 index 0000000000..e7f9564e77 Binary files /dev/null and b/config/images/qubino/ZMNHDDx.png differ diff --git a/config/images/qubino/ZMNHIDx.png b/config/images/qubino/ZMNHIDx.png new file mode 100644 index 0000000000..ae97439fd9 Binary files /dev/null and b/config/images/qubino/ZMNHIDx.png differ diff --git a/config/images/qubino/ZMNHNDx.png b/config/images/qubino/ZMNHNDx.png index fb7006db30..372a5c1299 100644 Binary files a/config/images/qubino/ZMNHNDx.png and b/config/images/qubino/ZMNHNDx.png differ diff --git a/config/images/qubino/ZMNHODx.png b/config/images/qubino/ZMNHODx.png new file mode 100644 index 0000000000..372a5c1299 Binary files /dev/null and b/config/images/qubino/ZMNHODx.png differ diff --git a/config/images/qubino/ZMNHSDx.png b/config/images/qubino/ZMNHSDx.png new file mode 100644 index 0000000000..e0043c1d2f Binary files /dev/null and b/config/images/qubino/ZMNHSDx.png differ diff --git a/config/images/qubino/ZMNHTDx.png b/config/images/qubino/ZMNHTDx.png new file mode 100644 index 0000000000..308a4bb3a3 Binary files /dev/null and b/config/images/qubino/ZMNHTDx.png differ diff --git a/config/images/qubino/ZMNHVDx.png b/config/images/qubino/ZMNHVDx.png new file mode 100644 index 0000000000..ae97439fd9 Binary files /dev/null and b/config/images/qubino/ZMNHVDx.png differ diff --git a/config/images/qubino/ZMNHWD1.png b/config/images/qubino/ZMNHWD1.png new file mode 100644 index 0000000000..9d3123a5e0 Binary files /dev/null and b/config/images/qubino/ZMNHWD1.png differ diff --git a/config/images/qubino/ZMNHYDx.png b/config/images/qubino/ZMNHYDx.png new file mode 100644 index 0000000000..1e5fb1a70e Binary files /dev/null and b/config/images/qubino/ZMNHYDx.png differ diff --git a/config/images/qubino/zmnhxdx.png b/config/images/qubino/zmnhxdx.png new file mode 100644 index 0000000000..e76f632ec9 Binary files /dev/null and b/config/images/qubino/zmnhxdx.png differ diff --git a/config/images/remotec/zrc-100eu.png b/config/images/remotec/zrc-100eu.png new file mode 100644 index 0000000000..7ab7cd3395 Binary files /dev/null and b/config/images/remotec/zrc-100eu.png differ diff --git a/config/images/remotec/zrc-90.png b/config/images/remotec/zrc-90.png new file mode 100644 index 0000000000..7df473505f Binary files /dev/null and b/config/images/remotec/zrc-90.png differ diff --git a/config/images/remotec/zts-500.png b/config/images/remotec/zts-500.png new file mode 100644 index 0000000000..d83320ea7c Binary files /dev/null and b/config/images/remotec/zts-500.png differ diff --git a/config/images/remotec/zxt-120.png b/config/images/remotec/zxt-120.png index d11ab3942e..59c6778bbe 100644 Binary files a/config/images/remotec/zxt-120.png and b/config/images/remotec/zxt-120.png differ diff --git a/config/images/remotec/zxt-310.png b/config/images/remotec/zxt-310.png new file mode 100644 index 0000000000..8fb6912354 Binary files /dev/null and b/config/images/remotec/zxt-310.png differ diff --git a/config/images/remotec/zxt-600.png b/config/images/remotec/zxt-600.png new file mode 100644 index 0000000000..18337365cc Binary files /dev/null and b/config/images/remotec/zxt-600.png differ diff --git a/config/images/schlage/BE468ZP.png b/config/images/schlage/BE468ZP.png new file mode 100644 index 0000000000..49dfaf487b Binary files /dev/null and b/config/images/schlage/BE468ZP.png differ diff --git a/config/images/schlage/BE469ZP.png b/config/images/schlage/BE469ZP.png new file mode 100644 index 0000000000..602dd667f6 Binary files /dev/null and b/config/images/schlage/BE469ZP.png differ diff --git a/config/images/sensative/strips.png b/config/images/sensative/strips.png new file mode 100644 index 0000000000..ced80fffc4 Binary files /dev/null and b/config/images/sensative/strips.png differ diff --git a/config/images/sensative/stripscomfort.png b/config/images/sensative/stripscomfort.png new file mode 100644 index 0000000000..8ab430fb80 Binary files /dev/null and b/config/images/sensative/stripscomfort.png differ diff --git a/config/images/shenzen_neo/nas-ab01z.png b/config/images/shenzen_neo/nas-ab01z.png new file mode 100644 index 0000000000..c39f0a1878 Binary files /dev/null and b/config/images/shenzen_neo/nas-ab01z.png differ diff --git a/config/images/shenzen_neo/nas-ds01z.png b/config/images/shenzen_neo/nas-ds01z.png new file mode 100644 index 0000000000..1a2b2d389c Binary files /dev/null and b/config/images/shenzen_neo/nas-ds01z.png differ diff --git a/config/images/shenzen_neo/nas-pd01z.png b/config/images/shenzen_neo/nas-pd01z.png new file mode 100644 index 0000000000..da6df42b89 Binary files /dev/null and b/config/images/shenzen_neo/nas-pd01z.png differ diff --git a/config/images/shenzen_neo/nas-wr01z.png b/config/images/shenzen_neo/nas-wr01z.png new file mode 100644 index 0000000000..531014e00e Binary files /dev/null and b/config/images/shenzen_neo/nas-wr01z.png differ diff --git a/config/images/shenzen_neo/nas-ws02z.png b/config/images/shenzen_neo/nas-ws02z.png new file mode 100644 index 0000000000..2196cf9280 Binary files /dev/null and b/config/images/shenzen_neo/nas-ws02z.png differ diff --git a/config/images/simon/10002034-13X.png b/config/images/simon/10002034-13X.png new file mode 100644 index 0000000000..884c30c4d8 Binary files /dev/null and b/config/images/simon/10002034-13X.png differ diff --git a/config/images/steinel/is140-2.png b/config/images/steinel/is140-2.png new file mode 100644 index 0000000000..eb5f927d5d Binary files /dev/null and b/config/images/steinel/is140-2.png differ diff --git a/config/images/steinel/l810-led-ihf.png b/config/images/steinel/l810-led-ihf.png new file mode 100644 index 0000000000..e9dbda6ba1 Binary files /dev/null and b/config/images/steinel/l810-led-ihf.png differ diff --git a/config/images/steinel/rs-led-d2.png b/config/images/steinel/rs-led-d2.png new file mode 100644 index 0000000000..7b683089d4 Binary files /dev/null and b/config/images/steinel/rs-led-d2.png differ diff --git a/config/images/steinel/xled-home-2.png b/config/images/steinel/xled-home-2.png new file mode 100644 index 0000000000..88cd1dbe73 Binary files /dev/null and b/config/images/steinel/xled-home-2.png differ diff --git a/config/images/stelpro/stzw402.png b/config/images/stelpro/stzw402.png new file mode 100644 index 0000000000..42fc869936 Binary files /dev/null and b/config/images/stelpro/stzw402.png differ diff --git a/config/images/sunricher/srzv9001k8.png b/config/images/sunricher/srzv9001k8.png new file mode 100644 index 0000000000..5d3d881a26 Binary files /dev/null and b/config/images/sunricher/srzv9001k8.png differ diff --git a/config/images/sunricher/srzv9001t4dimeu.png b/config/images/sunricher/srzv9001t4dimeu.png new file mode 100644 index 0000000000..46bbf34e8f Binary files /dev/null and b/config/images/sunricher/srzv9001t4dimeu.png differ diff --git a/config/images/sunricher/srzv9003t4rgbweu.png b/config/images/sunricher/srzv9003t4rgbweu.png new file mode 100644 index 0000000000..c7906808d9 Binary files /dev/null and b/config/images/sunricher/srzv9003t4rgbweu.png differ diff --git a/config/images/sunricher/srzv9101sachpeu.png b/config/images/sunricher/srzv9101sachpeu.png new file mode 100644 index 0000000000..186b3e3f3b Binary files /dev/null and b/config/images/sunricher/srzv9101sachpeu.png differ diff --git a/config/images/sunricher/zv9101.png b/config/images/sunricher/zv9101.png new file mode 100644 index 0000000000..86ae7b2a09 Binary files /dev/null and b/config/images/sunricher/zv9101.png differ diff --git a/config/images/telldus/tzwp100.png b/config/images/telldus/tzwp100.png new file mode 100644 index 0000000000..69a6666bc3 Binary files /dev/null and b/config/images/telldus/tzwp100.png differ diff --git a/config/images/telldus/tzwp102.png b/config/images/telldus/tzwp102.png new file mode 100644 index 0000000000..3b1793ef81 Binary files /dev/null and b/config/images/telldus/tzwp102.png differ diff --git a/config/images/thermofloor/heatit056.png b/config/images/thermofloor/heatit056.png new file mode 100644 index 0000000000..20204eade3 Binary files /dev/null and b/config/images/thermofloor/heatit056.png differ diff --git a/config/images/vision/zd2105us5.png b/config/images/vision/zd2105us5.png new file mode 100644 index 0000000000..9045879740 Binary files /dev/null and b/config/images/vision/zd2105us5.png differ diff --git a/config/images/vision/zd2201.png b/config/images/vision/zd2201.png new file mode 100644 index 0000000000..3c1c76c568 Binary files /dev/null and b/config/images/vision/zd2201.png differ diff --git a/config/images/vision/zl7431.png b/config/images/vision/zl7431.png new file mode 100644 index 0000000000..59c6778bbe Binary files /dev/null and b/config/images/vision/zl7431.png differ diff --git a/config/images/vision/zl7432us.png b/config/images/vision/zl7432us.png new file mode 100644 index 0000000000..59c6778bbe Binary files /dev/null and b/config/images/vision/zl7432us.png differ diff --git a/config/images/vision/zm1602eu5.png b/config/images/vision/zm1602eu5.png new file mode 100644 index 0000000000..bea388d2da Binary files /dev/null and b/config/images/vision/zm1602eu5.png differ diff --git a/config/images/vision/zp3102.png b/config/images/vision/zp3102.png index ef546df640..c73f0418e9 100644 Binary files a/config/images/vision/zp3102.png and b/config/images/vision/zp3102.png differ diff --git a/config/images/vision/zp3111.png b/config/images/vision/zp3111.png new file mode 100644 index 0000000000..1bbd39401b Binary files /dev/null and b/config/images/vision/zp3111.png differ diff --git a/config/images/wenzhou/tz56.png b/config/images/wenzhou/tz56.png new file mode 100644 index 0000000000..ce3ec1995b Binary files /dev/null and b/config/images/wenzhou/tz56.png differ diff --git a/config/images/wenzhou/tz68.png b/config/images/wenzhou/tz68.png index 3f328f128b..17cccd668f 100644 Binary files a/config/images/wenzhou/tz68.png and b/config/images/wenzhou/tz68.png differ diff --git a/config/images/wenzhou/tz69.png b/config/images/wenzhou/tz69.png new file mode 100644 index 0000000000..82cbca615e Binary files /dev/null and b/config/images/wenzhou/tz69.png differ diff --git a/config/images/widom/WDS.png b/config/images/widom/WDS.png new file mode 100644 index 0000000000..fee8aa82d4 Binary files /dev/null and b/config/images/widom/WDS.png differ diff --git a/config/images/zipato/HS1CA-Z.png b/config/images/zipato/HS1CA-Z.png new file mode 100644 index 0000000000..4cba740caa Binary files /dev/null and b/config/images/zipato/HS1CA-Z.png differ diff --git a/config/images/zipato/HS1CG-Z.png b/config/images/zipato/HS1CG-Z.png new file mode 100644 index 0000000000..56a3f236b4 Binary files /dev/null and b/config/images/zipato/HS1CG-Z.png differ diff --git a/config/images/zipato/HS1SA-Z.png b/config/images/zipato/HS1SA-Z.png new file mode 100644 index 0000000000..41ee539193 Binary files /dev/null and b/config/images/zipato/HS1SA-Z.png differ diff --git a/config/images/zipato/HS1WL-Z.png b/config/images/zipato/HS1WL-Z.png new file mode 100644 index 0000000000..e1e62864d3 Binary files /dev/null and b/config/images/zipato/HS1WL-Z.png differ diff --git a/config/images/zipato/RGBBulb.png b/config/images/zipato/RGBBulb.png index 874a1ab8ea..8cf2d9783a 100644 Binary files a/config/images/zipato/RGBBulb.png and b/config/images/zipato/RGBBulb.png differ diff --git a/config/images/zipato/pan04.png b/config/images/zipato/pan04.png new file mode 100644 index 0000000000..1a20fa4d15 Binary files /dev/null and b/config/images/zipato/pan04.png differ diff --git a/config/images/zipato/phpab01.png b/config/images/zipato/phpab01.png new file mode 100644 index 0000000000..8a8c7d9642 Binary files /dev/null and b/config/images/zipato/phpab01.png differ diff --git a/config/images/zipato/pse02.png b/config/images/zipato/pse02.png new file mode 100644 index 0000000000..d235aa5bf9 Binary files /dev/null and b/config/images/zipato/pse02.png differ diff --git a/config/images/zipato/pst02.png b/config/images/zipato/pst02.png new file mode 100644 index 0000000000..c6dfcbde22 Binary files /dev/null and b/config/images/zipato/pst02.png differ diff --git a/config/images/zipato/vszd2102.png b/config/images/zipato/vszd2102.png new file mode 100644 index 0000000000..e08461f31f Binary files /dev/null and b/config/images/zipato/vszd2102.png differ diff --git a/config/images/zipato/zd2301.png b/config/images/zipato/zd2301.png new file mode 100644 index 0000000000..1d4535ceda Binary files /dev/null and b/config/images/zipato/zd2301.png differ diff --git a/config/images/zipato/zp3102.png b/config/images/zipato/zp3102.png new file mode 100644 index 0000000000..043844df4e Binary files /dev/null and b/config/images/zipato/zp3102.png differ diff --git a/config/images/zooz/zen06.png b/config/images/zooz/zen06.png new file mode 100644 index 0000000000..29f01b980d Binary files /dev/null and b/config/images/zooz/zen06.png differ diff --git a/config/images/zooz/zen15.png b/config/images/zooz/zen15.png new file mode 100644 index 0000000000..7106f35991 Binary files /dev/null and b/config/images/zooz/zen15.png differ diff --git a/config/images/zooz/zen20.png b/config/images/zooz/zen20.png new file mode 100644 index 0000000000..7c7a019724 Binary files /dev/null and b/config/images/zooz/zen20.png differ diff --git a/config/images/zooz/zen20v2.png b/config/images/zooz/zen20v2.png new file mode 100644 index 0000000000..1d11e5855e Binary files /dev/null and b/config/images/zooz/zen20v2.png differ diff --git a/config/images/zooz/zen21.png b/config/images/zooz/zen21.png new file mode 100644 index 0000000000..04ef7d16a9 Binary files /dev/null and b/config/images/zooz/zen21.png differ diff --git a/config/images/zooz/zen22.png b/config/images/zooz/zen22.png new file mode 100644 index 0000000000..588fe9c479 Binary files /dev/null and b/config/images/zooz/zen22.png differ diff --git a/config/images/zooz/zen26.png b/config/images/zooz/zen26.png new file mode 100644 index 0000000000..d27af0c777 Binary files /dev/null and b/config/images/zooz/zen26.png differ diff --git a/config/images/zooz/zen27.png b/config/images/zooz/zen27.png new file mode 100644 index 0000000000..60a428d05f Binary files /dev/null and b/config/images/zooz/zen27.png differ diff --git a/config/images/zooz/zse09.png b/config/images/zooz/zse09.png new file mode 100644 index 0000000000..09854c188a Binary files /dev/null and b/config/images/zooz/zse09.png differ diff --git a/config/images/zooz/zse19.png b/config/images/zooz/zse19.png new file mode 100644 index 0000000000..1100051b12 Binary files /dev/null and b/config/images/zooz/zse19.png differ diff --git a/config/images/zooz/zse29.png b/config/images/zooz/zse29.png new file mode 100644 index 0000000000..bf837e1d30 Binary files /dev/null and b/config/images/zooz/zse29.png differ diff --git a/config/images/zooz/zse30.png b/config/images/zooz/zse30.png new file mode 100644 index 0000000000..16f73da183 Binary files /dev/null and b/config/images/zooz/zse30.png differ diff --git a/config/images/zooz/zse33.png b/config/images/zooz/zse33.png new file mode 100644 index 0000000000..7d68afdc4b Binary files /dev/null and b/config/images/zooz/zse33.png differ diff --git a/config/images/zooz/zse40.png b/config/images/zooz/zse40.png new file mode 100644 index 0000000000..f7714460be Binary files /dev/null and b/config/images/zooz/zse40.png differ diff --git a/config/images/zwave.me/ZUno.png b/config/images/zwave.me/ZUno.png new file mode 100644 index 0000000000..0aefa780c9 Binary files /dev/null and b/config/images/zwave.me/ZUno.png differ diff --git a/config/images/zwp/WD-100.png b/config/images/zwp/WD-100.png new file mode 100644 index 0000000000..1ef7a69025 Binary files /dev/null and b/config/images/zwp/WD-100.png differ diff --git a/config/inovelli/lzw30-sn.xml b/config/inovelli/lzw30-sn.xml new file mode 100644 index 0000000000..45ced8039f --- /dev/null +++ b/config/inovelli/lzw30-sn.xml @@ -0,0 +1,129 @@ + + + http://www.openzwave.com/device-database/031E:0001:0002 + images/inovelli/lzw30-sn.png + https://products.z-wavealliance.org/products/3451 + https://inovelli.com/shop/smart-light-switches/zwave-smart-switches-gen2/z-wave-on-off-switch-neutral-required-scenes-notifications/ + https://inovelli.com/shop/smart-light-switches/zwave-smart-switches-gen2/z-wave-on-off-switch-neutral-required-scenes-notifications/ + To Exclude your switch, put your HUB in exclusion mode and press the Configuration Button three (3) times. + U.S. / Canada / Mexico + https://products.z-wavealliance.org/ProductManual/File?folder=&filename=MarketCertificationFiles/3451/LZW30-SN%20Manual.pdf + You may factory reset the switch by holding down the Config Button for twenty (20) or more seconds. The LED Bar will turn Red and blink three (3) times to confirm. + +However, we recommend using a certified Z-Wave controller to remove the device from your network for factory resetting the switch. + +Only use either of these procedures in the event that the network primary controller is missing or otherwise inoperable. + + The Inovelli Red Series On/Off is a Z-Wave in-wall switch that controls attached LED, CFL, & Incandescent lighting which can be highly customized to your liking at the switch itself with our unique config button and advanced firmware. In addition, the Red Series comes with advanced features such as scene support, power monitoring, notifications, local protection, etc. + LZW30-SN Switch + LZW30-SN + To include your switch, start the inclusion process on your HUB and tap the Configuration Button three (3) times. + +Please Note: If this doesn't work, you can check to see if your switch is within Z-Wave Range by holding down the Configuration Button for 5-10 seconds (if it's not within range, the LED Bar will indicate Red and if it is within Range, the LED Bar will indicate Green). If your switch indicates Red, please move the switch closer to the HUB. If your switch indicates Green, please try running an Exclusion to reset your switch. + + Adding Metadata + + + + + + + When Power is restored + Range: 0-2 + Default: 0 + + + + + + + + Inverts the orientation of the switch. Useful when the switch is installed upside down. Essentially up becomes down and down becomes up. + Range: 0-1 + Default: 0 + + + + + + + Automatically turns the switch off after this many seconds. When the switch is turned on a timer is started that is the duration of this setting. When the timer expires, the switch is turned off. + Range: 0-32767 + Default: 0 + + + + + When should the switch send commands to associated devices? 01 - local 02 - 3way 03 - 3way & local 04 - z-wave hub 05 - z-wave hub & local 06 - z-wave hub & 3-way 07 - z-wave hub & local & 3way 08 - timer 09 - timer & local 10 - timer & 3-way 11 - timer & 3-way & local 12 - timer & z-wave hub 13 - timer & z-wave hub & local 14 - timer & z-wave hub & 3-way 15 - all + Range: 0-15 + Default: 15 + + + + + This is the color of the LED strip. + Range: 0 to 255 + Default: 170 + + + + + This is the intensity of the LED strip. + Range: 0-10 + Default: 5 + + + + + This is the intensity of the LED strip when the switch is off. This is useful for users to see the light switch location when the lights are off. + Range: 0 - 10 + Default: 0 + + + + + Please see website for documentation. + Range: 0-83823359 + Default: 0 + + + + + The power level change that will result in a new power report being sent. The value is a percentage of the previous report. 0 = disabled. + Range: 0-100 + Default: 10 + + + + + Time period between consecutive power & energy reports being sent (in seconds). The timer is reset after each report is sent. + Range: 0 to 32767 + Default: 3600 + + + + + The energy level change that will result in a new energy report being sent. The value is a percentage of the previous report. + Range: 0-100 + Default: 10 + + + + + + + + + + + + + + + + + + + + + diff --git a/config/inovelli/lzw30.xml b/config/inovelli/lzw30.xml new file mode 100644 index 0000000000..357e6641dc --- /dev/null +++ b/config/inovelli/lzw30.xml @@ -0,0 +1,93 @@ + + + http://www.openzwave.com/device-database/031E:0001:0004 + images/inovelli/lzw30.png + https://products.z-wavealliance.org/products/3452 + https://inovelli.com/shop/smart-light-switches/zwave-smart-switches-gen2/pre-order-z-wave-on-off-switch-base-model/ + https://inovelli.com/shop/smart-light-switches/zwave-smart-switches-gen2/pre-order-z-wave-on-off-switch-base-model + To Exclude your switch, put your HUB in exclusion mode and press the Configuration Button three (3) times. + U.S. / Canada / Mexico + https://products.z-wavealliance.org/ProductManual/File?folder=&filename=MarketCertificationFiles/3452/LZW30%20Manual.pdf + You may factory reset the switch by holding down the Config Button for twenty (20) or more seconds. The LED Bar will turn Red and blink three (3) times to confirm. + +However, we recommend using a certified Z-Wave controller to remove the device from your network for factory resetting the switch. + +Only use either of these procedures in the event that the network primary controller is missing or otherwise inoperable. + + The Inovelli On/Off switch is a Z-Wave device that controls attached LED, CFL, & Incandescent lighting which can be highly customized to your liking at the switch itself with our unique config button and advanced firmware. + LZW30 Switch + LZW30 + To include your switch, start the inclusion process on your HUB and tap the Configuration Button three (3) times. + +Please Note: If this doesn't work, you can check to see if your switch is within Z-Wave Range by holding down the Configuration Button for 5-10 seconds (if it's not within range, the LED Bar will indicate Red and if it is within Range, the LED Bar will indicate Green). If your switch indicates Red, please move the switch closer to the HUB. If your switch indicates Green, please try running an Exclusion to reset your switch. + + + Adding Metadata + + + + + + + When Power is restored + Range: 0-2 + Default: 0 + + + + + + + + Inverts the orientation of the switch. Useful when the switch is installed upside down. Essentially up becomes down and down becomes up. + Range: 0-1 + Default: 0 + + + + + + + Automatically turns the switch off after this many seconds. When the switch is turned on a timer is started that is the duration of this setting. When the timer expires, the switch is turned off. + Range: 0-32767 + Default: 0 + + + + + When should the switch send commands to associated devices? 01 - local 02 - 3way 03 - 3way & local 04 - z-wave hub 05 - z-wave hub & local 06 - z-wave hub & 3-way 07 - z-wave hub & local & 3way 08 - timer 09 - timer & local 10 - timer & 3-way 11 - timer & 3-way & local 12 - timer & z-wave hub 13 - timer & z-wave hub & local 14 - timer & z-wave hub & 3-way 15 - all + Range: 0-15 + Default: 15 + + + + + This is the color of the LED strip. + Range: 0 to 255 + Default: 170 + + + + + This is the intensity of the LED strip. + Range: 0-10 + Default: 5 + + + + + This is the intensity of the LED strip when the switch is off. This is useful for users to see the light switch location when the lights are off. + Range: 0 - 10 + Default: 0 + + + + + + + + + + + + diff --git a/config/inovelli/simple_module.xml b/config/inovelli/simple_module.xml index dc9401d5f4..09b8cf3126 100644 --- a/config/inovelli/simple_module.xml +++ b/config/inovelli/simple_module.xml @@ -1,12 +1,41 @@ - - + + + http://www.openzwave.com/device-database/0312:241C:B211 + images/inovelli/simple_module.png + https://products.z-wavealliance.org/products/2461/ + Press and hold the top button for at least 3 seconds while you plug the smart switch into a receptacle. +Use this procedure only in the event that the network primary controller is missing or otherwise inoperable. + ZW37 + Smart Plug Switch (2 channel) + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2461/ZW37-Manual70615.pdf + The 2 ports smart plug provides one Z-Wave outlet for remote controlled by controller through Z-Wave gateway for internet of thing service and can be configured in Z-Wave sensor network, + 1. Follow the instructions for your Z-Wave certified controller to include + a device to the Z-Wave network. +2. Once the controller is ready to include your device, press up and + release the toggle to include it in the network. + U.S. / Canada / Mexico + 1. Follow the instructions for your Z-Wave certified controller to exclude + a device from the Z-Wave network. +2. Once the controller is ready to Exclude your device, press up and + release the toggle to exclude it from the network. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2352/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2357/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2358/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2379/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2385/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2461/xml + + https://products.z-wavealliance.org/products/2379/ + NZW39 + U.S. / Canada / Mexico + - - + - + diff --git a/config/kaipule/im20.xml b/config/kaipule/im20.xml index 3854173037..78a9bd1801 100644 --- a/config/kaipule/im20.xml +++ b/config/kaipule/im20.xml @@ -1,31 +1,50 @@ - - - - - - Basic Set parameter setting, the receivers make relevant adjustment according to parameter value - - - + + + Basic Set parameter setting, the receivers make relevant adjustment according to parameter value + + + If there is any device under Association Group2, the door sensor will send Basic Set = value command to Group2, and send Basic Set = 0x00 command to turn-off light after t seconds, Set value = t, means to send Basic Set command after t seconds. - - - + + + Under normal working status (without trigger), the door sensor will automatically send report to the Gateway about its current tamper and open/close status. Set value = t, means t hours, (t=0, means no status report). 0-24 hours (Default 6 hours) - - - - - - - - - + + + + + + + + + diff --git a/config/kwikset/smartcode.xml b/config/kwikset/smartcode.xml index bf02e32d2e..f511295c79 100644 --- a/config/kwikset/smartcode.xml +++ b/config/kwikset/smartcode.xml @@ -1,7 +1,7 @@ +--> http://www.openzwave.com/device-database/0090:0001:0001 images/kwikset/smartcode.png @@ -9,14 +9,17 @@ http://s7d5.scene7.com/is/content/BDHHI/z-wave-configuration U.S. / Canada / Mexico 910 http://www.kwikset.com/Products/Details/Electronic-Locks/910TRL-ZW-15-SMT.aspx - The SmartCode Deadbolt with Home Connect Technology featuring Z-Wave enables the door lock to wirelessly communicate with other devices in home. The lock allows the user through a web enabled device to remotely check the door lock status, lock or unlock the door and receive text or email messages. + Weiser introduces the SmartCode™ 10 Touchpad Electronic Deadbolt with Z-Wave. -- The motor-driven deadbolt latch allows for true remote locking and unlocking. -- SmartKey cylinders feature a stainless steel side locking bar, racks and pins for increased strength and security -- Patented side locking bar technology offers improved security by protecting against lock bumping, an attack technique used to defeat conventional pin & tumbler locks -- Lifetime mechanical and finish warranty. 1 year electronics warranty. +10 digit backlit keypad with one touch locking +Dramatically reduced, all-metal interior +30 user codes plus master code +BHMA grade 2 certified +20 minute fire rating - UL certified +Full 128-bit encryption security +SmartKey: Re-key the lock in seconds http://www.kwikset.com/Customer-Support/Overview.aspx - SmartCode Deadbolt with Home Connect Technology + SmartCode 10 Touchpad Electronic Deadbolt Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/157/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/172/xml @@ -25,7 +28,37 @@ http://s7d5.scene7.com/is/content/BDHHI/z-wave-configuration Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/749/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/781/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/945/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1981/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2109/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2188/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2237/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2369/xml + https://products.z-wavealliance.org/products/2188/ + Even though the lock is sleeping, all buttons are active and can be used to initiate any lock activity. +For the RF side, it will wake up every 1 second to check if there are any requests from your smart home controller. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2369/Install Guide GED1800 04112017.pdf + 916 + Initiate the process to add the lock to your system at your smart home controller. +When prompted by your smart home system to add the lock, press button “A” on the lock interior one time. The red LED will illuminate when the lock enters Add Mode. +Please allow time for the controller to add the lock to your system. + Follow your smart home system’s instructions to remove the lock from the network. When prompted by the system, press button A” on the lock interior once. The red LED will illuminate when the lock enters Remove mode. + U.S. / Canada / Mexico + A factory reset will delete all user codes associated with the lock and will remove itself from your smart home system. +Please only perform a factory reset when the primary controller is missing or inoperable. + +To perform a factory reset, please perform the following: +1. Remove the battery pack +2. Press and HOLD the Program button while reinserting the battery pack. +3. Keep holding the button for 30 seconds until the lock beeps and the status LED flashes red. +4. Press the Program button once more. The status LED will flash green and red several times. +5. After a few seconds, the lock will initiate the door handing process. + https://products.z-wavealliance.org/products/2237/ + U.S. / Canada / Mexico + 914 + https://products.z-wavealliance.org/products/2369/ + GED1800 + U.S. / Canada / Mexico diff --git a/config/leviton/dz15s.xml b/config/leviton/dz15s.xml index 54fd034dc4..8e03723bce 100644 --- a/config/leviton/dz15s.xml +++ b/config/leviton/dz15s.xml @@ -1,8 +1,55 @@ - +--> + + http://www.openzwave.com/device-database/001D:0001:3401 + images/leviton/dz15s.png + https://products.z-wavealliance.org/products/1957/ + When removing a device from a Z-Wave® network best practice is to use the exclusion command found in the Z-Wave® controller. +• Enter Programming Mode by holding the control button for 7 seconds, the Locator LED will turn amber. +• Follow directions in the Z-Wave® controller to enter exclusion mode. +• Tap the control button one time. The Locator LED will quickly flash green. +The Z-Wave® controller will exclude the Decora Smart device. +• The Z-Wave® controller will confirm successful exclusion from the network. + DZ15S + The wireless Leviton DZPA1 is a Z-Wave enabled plug-in outlet designed for use for most residential applications to control plug-in lamps, holiday lighting, or small appliances. The DZPA1 Plug-In Outlet is fully compatible with Z-Wave Plus certified controllers. Offers manual control to turn loads on/off. Manufacturer Parameters allow custom configuration via Z-Wave commands. Rated for 5A LED and CFL bulbs, 1800W incandescent bulbs, 1800W Fluorescent, 15A Resistive, and 1/2 HP Motor. These Z-Wave Plus devices support beaming, network wide inclusion, and over the air updates. + Leviton Decora SmartTM Z-Wave® devices support two methods of inclusion. +When using a Z-Wave PlusTM certified controller choose Network Wide Inclusion. +Network Wide Inclusion: +Network Wide Inclusion allows your device to be added to the network using devices already in the network to assist with communication. Work your way from the closest devices to the controller outward. +• Enter Programming Mode by holding the control button for 7 seconds, the Locator LED will blink amber. +• Tap the control button one time. +The Locator LED will quickly flash green. +• The Decora SmartTM Z-Wave® device is ready to learn into the Z-Wave® network. +• Follow directions in the Z-Wave® controller to complete the adding process. +• Upon successful addition to network the LED will turn off and then blink green 3 times. +• If the adding process is not successful the LED will flash red 3 times. +Traditional Inclusion: +For older controllers Traditional Inclusion is supported. Depending on the age of the controller the controller will need to be 3 to 35 feet from the device when including. +• Enter Programming Mode by holding the control button for 7 seconds, the Locator LED will blink amber. +• The Decora SmartTM Z-Wave® device is ready to add to the Z-Wave® network. +• Follow directions in the Z-Wave® controller to enter learn mode. +• Tap the control button one time. The Locator LED will quickly flash green. +The Z-Wave® controller will begin to pair with the Decora Smart device. +• Upon successful addition to the network the LED will turn off and then blink green 3 times. +• If the adding process is not successful the LED will flash red 3 times. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1959/DI-000-DZPA1-02B-X4.pdf + When removing a device from a network it is best practice to use the Exclusion process. In situations where a device needs to be returned to factory default follow the following steps. A reset should only be used when a controller is inoperable or missing: +• Holding the control button for a total of 14 seconds. +- After the first 7 seconds the LED turns amber. +- The Locator LED will quickly flash red/amber after 14 seconds. +• Release the control button and the device will reset. + Plug-In Outlet + U.S. / Canada / Mexico + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1957/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1959/xml + + https://products.z-wavealliance.org/products/1959/ + DZPA1 + U.S. / Canada / Mexico + diff --git a/config/leviton/dz6hd.xml b/config/leviton/dz6hd.xml index bdfa3eee68..942a1dd3ac 100644 --- a/config/leviton/dz6hd.xml +++ b/config/leviton/dz6hd.xml @@ -1,7 +1,54 @@ +--> + + http://www.openzwave.com/device-database/001D:0001:3201 + images/leviton/dz6hd.png + https://products.z-wavealliance.org/products/1910/ + When removing a device from a network it is best practice to use the Exclusion process. In situations where a device needs to be returned to factory default follow the following steps. A reset should only be used when a controller is inoperable or missing. +• Hold the top of the paddle for a total of 14 seconds. +• After the first 7 seconds the LED turns amber. +• The Locator LED will quickly flash red/amber after 14 seconds. +• Release the top of the paddle and the device will reset. + Leviton Decora Smart™ Z-Wave® devices support two methods of inclusion. When using a Z-Wave Plus® certified controller choose Network Wide Inclusion. +Network Wide Inclusion: +Network Wide Inclusion allows your device to be included into the network using devices already in the network to assist with communication. Work your way from the closest devices to the controller outward. +• Enter Programming Mode by holding the top of the paddle for 7 seconds, the Locator LED will blink amber. +• Tap the top of the paddle one time. +The Locator LED will quickly flash green. +• The Decora Smart™ Z-Wave® device is ready to learn into the Z-Wave® network. +• Follow directions in the Z-Wave controller to complete the adding process. +• Upon successful addition to network the LED will turn off and then blink green 3 times. +• If the adding process is not successful the LED will flash red 3 times. +Traditional Inclusion: +For older controllers Traditional Inclusion is supported. Depending on the age of the controller the controller will need to be 3 to 35 feet from the device when including. +• Enter Programming Mode by holding the top of the paddle for 7 seconds, the Locator LED will blink amber. +• The Decora SmartTM Z-Wave® device is ready to add to the Z-Wave® network. +• Follow directions in the Z-Wave® controller to enter learn mode. +• Tap the top of the paddle one time. The Locator LED will quickly flash green. The Z-Wave® controller will begin to pair with the Decora Smart™ device. +• Upon successful addition to the network the LED will turn off and then blink green 3 times. +• If the adding process is not successful the LED will flash red 3 times. + + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1956/DI-000-DZ1KD-02A-X4.pdf + DZ6HD + 1000W Dimmer + The wireless Leviton DZ1KD is a Z-Wave enabled dimmer designed for use for most residential lighting applications to control LED, CFL, and incandescent bulbs. The DZ1KD Dimmer is fully compatible with Z-Wave Plus certified controllers. Provides full range dimming with adjustable fade rates. Manufacturer Parameters allow custom configuration via Z-Wave commands. Offers manual control to turn lights on/off and set brightness level, with an LED feedback to display brightness level. Facilitates single pole or three-way multi-location applications. Rated for 450W LED and CFL dimmable bulbs and 1000W incandescent bulbs, requires neutral connection. These Z-Wave Plus devices support beaming, network wide inclusion, and over the air updates. White and Light Almond color faces included, Decora wallplate sold separately. + U.S. / Canada / Mexico + When removing a device from a Z-Wave® network best practice is to use the exclusion command found in the Z-Wave® controller. +• Enter Programming Mode by holding the top of the paddle for 7 seconds, the Locator LED will blink amber. +• Follow directions in the Z-Wave® controller to enter exclusion mode +• Tap the top of the paddle one time. The Locator LED will quickly flash green. +The Z-Wave® controller will exclude the Decora Smart™ device +• The Z-Wave® controller will confirm successful exclusion from the network. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1910/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1956/xml + + https://products.z-wavealliance.org/products/1956/ + U.S. / Canada / Mexico + DZ1KD + diff --git a/config/leviton/dzpd3.xml b/config/leviton/dzpd3.xml index 301f6beb9f..434ba6faad 100644 --- a/config/leviton/dzpd3.xml +++ b/config/leviton/dzpd3.xml @@ -1,6 +1,52 @@ +--> + + http://www.openzwave.com/device-database/001D:0001:3501 + images/leviton/dzpd3.png + https://products.z-wavealliance.org/products/1958/ + DZPD3 + When removing a device from a Z-Wave® network best practice is to use the exclusion command found in the Z-Wave® controller. +• Enter Programming Mode by holding the control button for 7 seconds, the Locator LED will turn amber. +• Follow directions in the Z-Wave® controller to enter exclusion mode. +• Tap the control button one time. The Locator LED will quickly flash green. +The Z-Wave® controller will exclude the Decora Smart device. +• The Z-Wave® controller will confirm successful exclusion from the network. + Leviton Decora Smart Z-Wave® devices support two methods of inclusion. +When using a Z-Wave Plus certified controller choose Network Wide Inclusion. +Network Wide Inclusion: +Network Wide Inclusion allows your device to be added to the network using devices already in the network to assist with communication. Work your way from the closest devices to the controller outward. +• Enter Programming Mode by holding the control button for 7 seconds, the Locator LED will blink amber. +• Tap the control button one time. +The Locator LED will quickly flash green. +• The Decora Smart Z-Wave® device is ready to learn into the Z-Wave® network. +• Follow directions in the Z-Wave® controller to complete the adding process. +• Upon successful addition to network the LED will turn off and then blink green 3 times. +• If the adding process is not successful the LED will flash red 3 times. +Traditional Inclusion: +For older controllers Traditional Inclusion is supported. Depending on the age of the controller the controller will need to be 3 to 35 feet from the device when including. +• Enter Programming Mode by holding the control button for 7 seconds, the Locator LED will blink amber. +• The Decora Smart Z-Wave® device is ready to add to the Z-Wave® network. +• Follow directions in the Z-Wave® controller to enter learn mode. +• Tap the control button one time. The Locator LED will quickly flash green. +The Z-Wave® controller will begin to pair with the Decora Smart device. +• Upon successful addition to the network the LED will turn off and then blink green 3 times. +• If the adding process is not successful the LED will flash red 3 times. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1958/DI-000-DZPD3-02B-X4.pdf + The wireless Leviton DZPD3 is a Z-Wave enabled plug-in dimmer designed for use for most residential lighting applications to control LED, CFL, and incandescent bulbs. The DZPD3 Dimmer is fully compatible with Z-Wave Plus certified controllers. Provides full range dimming with adjustable fade rates. Manufacturer Parameters allow custom configuration via Z-Wave commands. Rated for 100W LED and CFL dimmable bulbs and 300W incandescent bulbs. These Z-Wave Plus devices support beaming, network wide inclusion, and over the air updates. + When removing a device from a network it is best practice to use the Exclusion process. In +situations where a device needs to be returned to factory default follow the following steps. +A reset should only be used when a controller is inoperable or missing: +• Holding the control button for a total of 14 seconds. +- After the first 7 seconds the LED turns amber. +- The Locator LED will quickly flash red/amber after 14 seconds. +• Release the control button and the device will reset. + U.S. / Canada / Mexico + Plug-In Dimmer + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1958/xml + + diff --git a/config/linear/WD500Z5-1.xml b/config/linear/WD500Z5-1.xml index 9393445f42..7c1c9b1959 100644 --- a/config/linear/WD500Z5-1.xml +++ b/config/linear/WD500Z5-1.xml @@ -1,53 +1,77 @@ - - - - - - By default, the Dimmer LED will turn OFF when the load attached is turned ON. - - - - - - - - Change the top of the switch to OFF and the bottom of the switch to ON. - - - - - This dimmer will always start dimming from its current level, ignoring any commanded start level. - - - - - Dim Step can be set to a value of 1 to 99. This value indicates how many levels the dimmer will change each time the Dim Timer expires. - - - The Dim Timer (how fast the dim steps happen). It can be set to a value of 1 to 255. This value indicates in 10 millisecond resolution, how often the dim level will change. - - - Dim Step can be set to a value of 1 to 99. This value indicates how many levels the dimmer will change each time the Dim Timer expires. - - - The Dim Timer (how fast the dim steps happen). It can be set to a value of 1 to 255. This value indicates in 10 millisecond resolution, how often the dim level will change. - - - Dim Step can be set to a value of 1 to 99. This value indicates how many levels the dimmer will change each time the Dim Timer expires. - - - The Dim Timer (how fast the dim steps happen). It can be set to a value of 1 to 255. This value indicates in 10 millisecond resolution, how often the dim level will change. - +--> + + http://www.openzwave.com/device-database/014F:3530:5744 + images/linear/WD500Z5-1.png + https://products.z-wavealliance.org/products/1883/ + Adding to a Network: +1. With your Controller in Discovery or Add Mode, tap the switch. The LED will blink slowly when in ADD Mode. +2. You should see an indication on your Controller that the “device was added” to the network and the LED will stop blinking. +3. The device will appear in the list of Switches. It should display as a switch. + WD500Z5-1 + To Reset Unit (If Required): +Use only in the event that your primary Controller is lost or otherwise inoperable, to reset the GoControl Dimmer and clear all network information, follow these steps: +1. Tap the top of the switch five (5) times. +2. Press and hold the bottom of the switch for 15 seconds. The LED will increasingly blink faster to indicate that a Reset is taking place. + + + The WD500Z5-1 is an in-wall lighting dimmer switch designed to operate with LED, halogen and incandescent lights. Not only can this switch control the connected load, with Central Scene support it can run up to 6 scenes created by the Hub it is the most versatile Home Automation light switch available. With OTA upgrading supported, this light switch may be the last one ever installed in a home. + WD500Z5-1 + Removing from a Network: +1. Set the Controller into Removal Mode and follow its instruction to delete the GoControl Dimmer from the Controller. +2. Remove the switch by tapping the paddle 2 times. The LED will begin blinking slowly for 10 seconds indicating that it has been removed. +3. You should see an indication on your Controller that the “device was removed” from the network. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1883/10008092X18 WD500Z5-1_WD1000Z5-1 Instructions.pdf + U.S. / Canada / Mexico + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1883/xml + + + + + + By default, the Dimmer LED will turn OFF when the load attached is turned ON. + + + + + + + + Change the top of the switch to OFF and the bottom of the switch to ON. + + + + + This dimmer will always start dimming from its current level, ignoring any commanded start level. + + + + + Dim Step can be set to a value of 1 to 99. This value indicates how many levels the dimmer will change each time the Dim Timer expires. + + + The Dim Timer (how fast the dim steps happen). It can be set to a value of 1 to 255. This value indicates in 10 millisecond resolution, how often the dim level will change. + + + Dim Step can be set to a value of 1 to 99. This value indicates how many levels the dimmer will change each time the Dim Timer expires. + + + The Dim Timer (how fast the dim steps happen). It can be set to a value of 1 to 255. This value indicates in 10 millisecond resolution, how often the dim level will change. + + + Dim Step can be set to a value of 1 to 99. This value indicates how many levels the dimmer will change each time the Dim Timer expires. + + + The Dim Timer (how fast the dim steps happen). It can be set to a value of 1 to 255. This value indicates in 10 millisecond resolution, how often the dim level will change. + + + + + + + - - - - - - - diff --git a/config/linear/WS15Z-1.xml b/config/linear/WS15Z-1.xml index fc4921a230..c9896a1dd8 100644 --- a/config/linear/WS15Z-1.xml +++ b/config/linear/WS15Z-1.xml @@ -1,5 +1,5 @@ - + @@ -11,4 +11,9 @@ Change the top of the switch to OFF and the bottom of the switch to ON. + + + + + diff --git a/config/linear/WT00Z-1.xml b/config/linear/WT00Z-1.xml index 619158a338..edee5c5335 100644 --- a/config/linear/WT00Z-1.xml +++ b/config/linear/WT00Z-1.xml @@ -1,5 +1,5 @@ - + @@ -23,5 +23,11 @@ The Dim Timer (how fast the dim steps happen). It can be set to a value of 1 to 255. This value indicates in 10 millisecond resolution, how often the dim level will change. + + + + + + diff --git a/config/linear/gd00z-7.xml b/config/linear/gd00z-7.xml new file mode 100644 index 0000000000..f4d1b36da0 --- /dev/null +++ b/config/linear/gd00z-7.xml @@ -0,0 +1,22 @@ + + + http://www.openzwave.com/device-database/014F:3531:4744 + images/linear/gd00z-7.png + https://products.z-wavealliance.org/products/2904/ + Z-Wave Garage Door Controller + 1. Place your Z-Wave Controller into Exclude mode. +2. Press and release the link button on the GD00Z-6. + 1. Place your Z-Wave Controller into Include mode. +2. Press and release the link button on the GD00Z-6. + U.S. / Canada / Mexico + GD00Z-6 + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2904/10015084AX1 UG.pdf + The GoControl GD00Z-6 is the next iteration of the best selling line of Z-Wave controlled remote garage door status indicator and activator. Adding S2 security and OTA capability, the GD00Z-6 continues to Nortek’s leadership positing in the IOT market. Open or close a sectional garage door remotely through a Z-Wave certified Gateway or Security Panel. Compatible with virtually any garage door opener connected to a sectional garage door. Audible and visual warnings prior to remotely-activated door movement, meeting UL 325 safety requirements. Included tilt sensor reports door "open" or "close" information. + Reset the GD00Z-6 by pressing the LINK button 5 times. A quick beep followed by a longer beep will indicate the reset. +Reset should only be used in the case of a missing or inoperative primary controller. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2635/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2904/xml + + + diff --git a/config/logicsoft/ZHC5010.xml b/config/logicsoft/ZHC5010.xml index f10a777d13..62e99660ec 100644 --- a/config/logicsoft/ZHC5010.xml +++ b/config/logicsoft/ZHC5010.xml @@ -1,4 +1,20 @@ - + + + http://www.openzwave.com/device-database/0234:010A:0003 + images/logicsoft/ZHC5010.png + https://products.z-wavealliance.org/products/1779/ + Wall Switch + CEPT (Europe) + ZHC5010 can be factory reset by pressing the small button in the middle of the module (normally covered by small plastic cover) for at least 10 seconds. Please use this procedure only when the network primary controller is missing or otherwise inoperable. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1779/ZHC5010-Manual-EN-Rev11.pdf + Pushing the upper left button 3 times, (triple click) will activate Inclusion Mode on the device. It is also possible to activate Inclusion Mode by triple clicking the switch in the middle of the module (normally covered by the middle plastic cover, this can be removed by means of a little screwdriver). + Pushing the upper left button 3 times, (triple click) will activate Exclusion Mode on the device. It is also possible to activate Exclusion Mode by triple clicking the switch in the middle of the module (normally covered by the middle plastic cover, this can be removed by means of a little screwdriver). + ZHC5010 + ZHC5010 is a wall switch module with four buttons, four LEDs, a built-in relay switch and is designed to fit into standard Danish LK FUGA® wall boxes. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1779/xml + + Configuration of Pair Mode for the upper two buttons (button #1 and #2). diff --git a/config/manufacturer_specific.xml b/config/manufacturer_specific.xml index 98de0931b5..e1182f5ac2 100644 --- a/config/manufacturer_specific.xml +++ b/config/manufacturer_specific.xml @@ -1,5 +1,5 @@ - + @@ -205,6 +205,7 @@ + @@ -214,6 +215,15 @@ + + + + + + + + + @@ -467,6 +477,7 @@ + @@ -654,6 +665,7 @@ + @@ -674,6 +686,7 @@ + @@ -693,6 +706,9 @@ + + + @@ -748,6 +764,7 @@ + @@ -755,12 +772,13 @@ + - + @@ -789,7 +807,7 @@ - + @@ -802,7 +820,9 @@ - + + + @@ -812,6 +832,7 @@ + @@ -839,6 +860,8 @@ + + @@ -870,6 +893,7 @@ + @@ -914,7 +938,7 @@ - + @@ -951,7 +975,10 @@ - + + + + @@ -982,7 +1009,6 @@ - @@ -1001,6 +1027,7 @@ + @@ -1056,8 +1083,9 @@ - + + @@ -1101,6 +1129,9 @@ + + + @@ -1115,12 +1146,15 @@ + + + @@ -1205,8 +1239,8 @@ - - + + @@ -1218,6 +1252,7 @@ + @@ -1256,6 +1291,7 @@ + @@ -1300,6 +1336,7 @@ + @@ -1323,6 +1360,7 @@ + @@ -1341,7 +1379,7 @@ - + @@ -1402,6 +1440,7 @@ + @@ -1437,21 +1476,24 @@ - + + + - - - - - - - - + + + + + + + + + @@ -1493,9 +1535,9 @@ - + - + @@ -1598,10 +1640,12 @@ - + + + @@ -1637,7 +1681,7 @@ - + @@ -1682,7 +1726,7 @@ - + @@ -1722,6 +1766,7 @@ + @@ -1814,6 +1859,8 @@ + + @@ -1825,6 +1872,7 @@ + diff --git a/config/manufacturer_specific.xsd b/config/manufacturer_specific.xsd index 68bd90a2c2..9481602895 100644 --- a/config/manufacturer_specific.xsd +++ b/config/manufacturer_specific.xsd @@ -29,7 +29,14 @@ - + + + + + + + + diff --git a/config/mcohome/mh7h.xml b/config/mcohome/mh7h.xml index 8ff1fe9db0..7e8231edb1 100644 --- a/config/mcohome/mh7h.xml +++ b/config/mcohome/mh7h.xml @@ -1,4 +1,49 @@ - + + + http://www.openzwave.com/device-database/015F:5102:0702 + images/mcohome/mh7h.png + https://products.z-wavealliance.org/products/2900/ + Heating Thermostat + CEPT (Europe) + In normal working interface, press & hold S4 to enter interface for adding or removing of Z-Wave network. Before device removed from network, a Node ID will display on the screen. Then press S4 once. If removing is succeed, “- - -”will display on the screen in a few seconds. + +A node ID can always inform us whether the device is in the network or not.When removed, the device will restore its factory setting. + + A parameter P18 in the secret menu can be used to restore factory setting locally. Please use this procedure only when the network primary controller is missing or otherwise inoperable. ; And a parameter FF can be used to restore the factory setting via Z-Wave. + MH7H-WH/EH + MH7H-WH is mainly applied to control wall mounted boiler, water valve/pump etc. , while MH7H-EH is for electrical heating system.The device is of high reliability and practicability, which can be included and operated in any Z-Wave network with other Z-Wave certified devices from any other manufacturers. All non-battery operated nodes within the network will act as repeaters regardless of vendor to increase reliability of the network. + +Features: + Capacitive touch buttons + Tempered glass panel, PC alloy enclosure + Precise temperature calibration function + Attractive appearance + Clear display, easy to operate + +Specification: + Power Supply:AC85-260V, 50/60HZ + Output: MH7H-WH ≤5A ; MH7H-EH≤ 16A + Self Consumption:≤1W + External Temp. Sensor(optional): NTC R25℃=15KΩ + B25℃/50℃=3550K + Working Environment:0-50℃; 0-90% RH(Non- + condensation) + Temperature Setting:5-37 ℃(41-99℉)(Adjustable) + Dimension:86* 86*15mm + Hole Pitch:60-61mm + + + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2900/MH7H User Manual.pdf + In normal working interface, press & hold S4 to enter interface for adding or removing of Z-Wave network. Before device added into network, “- - -” will display on the screen. Then press S4 once, device will enter learning mode to get a node ID. If adding is succeed, a node ID will display on the screen in a few seconds. + +A node ID can always inform us whether the device is in the network or not. + +After adding, turn off the device and then turn it on. Now the device is ready to be operated by controller/ gateway in Z-Wave network. + + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2900/xml + + diff --git a/config/mcohome/mhp220.xml b/config/mcohome/mhp220.xml new file mode 100644 index 0000000000..cbbfa8d61f --- /dev/null +++ b/config/mcohome/mhp220.xml @@ -0,0 +1,111 @@ + + + http://www.openzwave.com/device-database/015F:5101:220A + images/mcohome/mhp220.png + https://products.z-wavealliance.org/products/3011/ + MH-P220 + Restoring Factory Settings: +The default configuration can be restored by: +* Sending commands through controller/gateway (the command classes which support this function is Configuration Command Class). The parameter are as follows: + +Parameter Number 0xFF +Size 1 BYTE +Default value N/A +Configuration value 0x55 +Set 0xFF as 0x55 will restore Factory Settings. + +* Or press the inner button on the module 10 times in quick succession.Please use this procedure only when the network primary controller is missing or otherwise inoperable. + + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3011/MH-P220UserManual.pdf + U.S. / Canada / Mexico + Remove the device from Z-Wave network: +1. Set controller into REMOVE mode. Follow the instructions provided by the controller/gateway manufacturer. +2. Press the momentary button on the device 3 times, or the connected external button S1 3 times in quick succession. +Note: If the REMOVE is successful, the INDICATION LED will blink 6 times. If not, INDICATION LED will be solid on or off depending on switch’s state. + + Micro Dimmer MHP-220 + This in-wall module is with compact design as well as stable performance, which can suit for any of the installation box and various operation situation. It supports basic command class, and also can act as repeater regardless of vendor to increase reliability of the network. + Add the device into Z-Wave network: +1. Set controller into ADD mode. Follow the instructions provided by the controller/gateway manufacturer. +2. Press the momentary button on the device 3 times, or the connected external button S1 3 times in quick succession. +Note: If the ADD is successful, the INDICATION LED will blink 6 times. If not, INDICATION LED will be solid on or off depending on switch’s state. + + + Initial Metadata Import from Z-Wave Alliance Database - file based on 1.4 version by @tonbor PR #1853 + + + + + + + Dimmer state saved or not when power down + + + External switch type + + + 2-state Switches + + + ALL ON/ALL OFF + + + Minimum brightness level + + + Maximum brightness level + + + Single dimming step time(Manual) + + + Single dimming step size (Manual) + + + Single dimming step time (Auto) + + + Single dimming step size (Auto) + + + Timer function (Auto-off) + + + One click of S1 + + + Double click of S1 + + + Operation report from Switch1 to Association Group 2 and 3 + + + Operation report from Switch1 to Association Group 2 + + + Switch 2 function + + + Operation report from Switch2 to Association Group 4 + + + Scene ID sent to AG1 when one click of S2 + + + Scene ID sent to AG1 when double click of S2 + + + Scene ID sent to AG1 when hold S2 + + + + + + + + + + + + + diff --git a/config/mcohome/mhp511.xml b/config/mcohome/mhp511.xml new file mode 100644 index 0000000000..476ba6c854 --- /dev/null +++ b/config/mcohome/mhp511.xml @@ -0,0 +1,151 @@ + + + + MH-P511 Touch Panel Dimmer Switch + MCOHome Touch Panel Dimmer Switch is a wall switch with built-in dimmer & Z-Wave module together in one compact unit. It supports basic command class,association command class, which can control all associated devices synchronously. This product can be included and operated in any Z-Wave network with other Z-Wave certified devices from any other manufacturers. + http://www.openzwave.com/device-database/015f:1453:511a + http://www.mcohome.com/show_list.php?id=13&sid=47 + http://www.mcohome.com/show_list.php?id=17&pcate=13&mid=47 + images/mcohome/mhp511.png + https://smarthome.hancan.com.au/wp-content/uploads/2018/02/MH-P511_UM_V.02.pdf + Press the key on the panel 3 times in quick succession (within approx 1.5sec) + Press the key on the panel 3 times in quick succession (within approx 1.5sec) + Write 0x55 to Configuration Parameter Index 255 + Australia / New Zealand + MH-P511-AU + + Initial creation of config file from import of data from User Manual + + + + + + Dimmer state saved or not when power down + + + + + Beep + + + + + + LED Backlit brightness level. + 0 = Off; + 10 = Max brightness + + + + All On / All Off + + + + + + + Minimum brightness level (should be less than Maximum brightness level) + + + Maximum brightness level (should be greater than Minimum brightness level) + + + + Manual single dimming step time, in 10ms steps. + Manual control achieved by holding external button. + + + + + Manual single dimming step size. + Manual control achieved by holding external button. + Modification isn’t recommended! + + + + + Auto single dimming step time, in 10ms steps. + Auto control achieved by double click external button. + + + + + Auto single dimming step size. + Auto control achieved by double click external button. + Modification isn’t recommended! + + + + + Timer function (Auto-off). + 0 = function disabled + 1 - 255 = 1s - 255s auto-off delay + + + + + One click of external button (S1). + 0 = either (switch Off) or (switch On to last saved brightness level) + 1 - 99 = either (switch Off) or (switch On to set percentage brightness level) + + + + Double click of external button (S1) + + + + + + Operation report from external button (S1) to Association Group 2 & 3 + Device send Basic Set to AG2; Send Multilevel Set to AG3 + + + + + + + + + + Operation report from external button (S1) to Association Group 2 + + + + + + 0 = Scene Activation disabled + 1 - 255 = send Activation CC to AG1 with specified Scene ID + + + + + For momentary button only + 0 = Scene Activation disabled + 1 - 255 = send Activation CC to AG1 with specified Scene ID + + + + + For momentary button only + 0 = Scene Activation disabled + 1 - 255 = send Activation CC to AG1 with specified Scene ID + + + + Restore factory setting + + + + + + + + + + + + + + \ No newline at end of file diff --git a/config/nodon/crc3100OctanRemote.xml b/config/nodon/crc3100OctanRemote.xml index f85a6a431e..4dc3129c4f 100644 --- a/config/nodon/crc3100OctanRemote.xml +++ b/config/nodon/crc3100OctanRemote.xml @@ -1,14 +1,14 @@ - + http://www.openzwave.com/device-database/0165:0001:0002 images/nodon/crc3100OctanRemote.png - https://products.z-wavealliance.org/products/1326/ + https://products.z-wavealliance.org/products/1923/ Simultaneously push on buttons 3 and 4, during 1 second. The LED will blink red and green to validate the factory reset. A factory reset will completely delete the memory of the remote control and restore all parameters to default value. In "Standalone" Mode, make sure to remove all the devices added or associated in the remote control's network before performing a factory reset. In "Gateway" Mode, use the factory reset procedure only when the primary controller (i.e the Gateway) is missing or defective. Reset the remote control does not mean that it has been removed from the primary controller memory. Remove the remote control (through the primary controller) before performing a factory reset. - CEPT (Europe) + CEPT (Europe) / U.S. / Canada / Mexico OCTAN Remote CRC-3-1-0X The OCTAN Remote NodOn® controls any compatible receivers Z-Wave® or Z-Wave Plus®, such as the Smart Plug NodOn®. It can address, directly, up to 4 groups of 8 devices and sent up to 16 different scenes to a Home Automation Gateway. This controller can operate on its own (“Standalone” Mode) or as gateway’s assistant (“Gateway” Mode). The product integrates a LED, which give an intuitive feedback for each operation you perform. @@ -21,18 +21,21 @@ The OCTAN Remote NodOn® is based on brand new 500 series Z-Wave® module from S Longer range (up to 40 meters indoor), lower power consumption, higher data rate transmission, and many more new features. When the product in "Gateway" mode, any action on button will send a wake up notification to the gateway. - 1- Push 3 times (quickly) on the button 2. The LED blinks in blue. + 1- Push 3 times (quickly) on the button 4. The LED blinks in blue. -2- Place the device you want to remove in “Learning” Mode. To do so, please refer to your device’s user guide. The LED blinks in green to confirm the exclusion. +2- Place the device you want to remove in "Learning" Mode, within 10 seconds. To do so, please refer to your device's user guide. + +3- The LED blinks in green to confirm the exclusion. - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1326/NodOn-CRC-3-1-xx-UserGuide-150528-EN-online.pdf - 1- Push 3 times (quickly) on the button 3. The LED blinks in blue. - -2- Place the device you want to add in “Learning” Mode. To do so, please refer to your device’s user guide. The LED blinks in green to confirm the inclusion. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1923/NodOn-CRC-3-1-xx-UserGuide-150528-EN-online.pdf + 1- Push 3 times (quickly) on the button 1. The LED blinks in blue. + +2- Place the device you want to add in "Learning" Mode, within 10 seconds. To do so, please refer to your device's user guide. -Note: If you wish to include and associate a device, please refer to "Other Special Features" +3- The LED blinks in green to confirm the inclusion. Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1326/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1923/xml diff --git a/config/nodon/crc360xSofremote.xml b/config/nodon/crc360xSofremote.xml index 4ad907f823..b3e8d1129d 100644 --- a/config/nodon/crc360xSofremote.xml +++ b/config/nodon/crc360xSofremote.xml @@ -1,27 +1,29 @@ - + http://www.openzwave.com/device-database/0165:0002:0002 images/nodon/crc360xSofremote.png - https://products.z-wavealliance.org/products/1418/ + https://products.z-wavealliance.org/products/1924/ Simultaneously push on buttons 3 and 4, during 1 second. The LED will blink red and green to validate the factory reset. A factory reset will completely delete the memory of the Soft Remote and restore all parameters to default value. In "Standalone" Mode, make sure to remove all the devices added or associated in the Soft Remote's network before performing a factory reset. In "Gateway" Mode, use the factory reset procedure only when the primary controller (i.e the Gateway) is missing or defective. Reset the Soft Remote does not mean that it has been removed from the primary controller memory. Remove the Soft Remote (through the primary controller) before performing a factory reset. CRC-3-6-0X - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1418/nodon-crc-3-6-xx-userguide-150707-en-interactive.pdf + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1924/NodOn-CRC-3-6-xx-UserGuide-160816-EN-interactive.pdf When the product in "Gateway" mode, any action on button will send a wake up notification to the gateway. - CEPT (Europe) - 1- Push 3 times (quickly) on the button 2. The LED blinks in blue. + CEPT (Europe) / U.S. / Canada / Mexico + 1- Push 3 times (quickly) on the button 4. The LED blinks in blue. -2- Place the device you want to remove in “Learning” Mode. To do so, please refer to your device’s user guide. The LED blinks in green to confirm the exclusion. +2- Place the device you want to remove in "Learning" Mode, within 10 seconds. To do so, please refer to your device's user guide. + +3- The LED blinks in green to confirm the exclusion. NodOn® Soft Remote - 1- Push 3 times (quickly) on the button 3. The LED blinks in blue. - -2- Place the device you want to add in “Learning” Mode. To do so, please refer to your device’s user guide. The LED blinks in green to confirm the inclusion. + 1- Push 3 times (quickly) on the button 1. The LED blinks in blue. + +2- Place the device you want to add in "Learning" Mode, within 10 seconds. To do so, please refer to your device's user guide. -Note: If you wish to include and associate a device, please refer to "Other Special Features" +3- The LED blinks in green to confirm the inclusion. The NodOn® Soft Remote controls any compatible receivers Z-Wave® or Z-Wave Plus®, such as the Smart Plug NodOn®. It can address, directly, up to 4 groups of 8 devices and sent up to 16 different scenes to a Home Automation Gateway. This controller can operate on its own (“Standalone” Mode) or as gateway’s assistant (“Gateway” Mode). The product integrates a LED, which give an intuitive feedback for each operation you perform. Based on an innovative technology, the NodOn® Soft Remote is only powered with a CR2032 battery, offering 2 years’ autonomy. @@ -30,6 +32,7 @@ The NodOn® Soft Remote is based on brand new 500 series Z-Wave® module from Si Longer range (up to 40 meters indoor), lower power consumption, higher data rate transmission, and many more new features. Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1418/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1924/xml diff --git a/config/nodon/msp31xxMicroSmartPlug.xml b/config/nodon/msp31xxMicroSmartPlug.xml index 969e39551f..90227f60c6 100644 --- a/config/nodon/msp31xxMicroSmartPlug.xml +++ b/config/nodon/msp31xxMicroSmartPlug.xml @@ -1,109 +1,129 @@ - - + + + http://www.openzwave.com/device-database/0165:0003:0001 + images/nodon/msp31xxMicroSmartPlug.png + https://products.z-wavealliance.org/products/1701/ + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1701/NodOn-MSP-3-1-xx-UserGuide-160314-EN-interactive.pdf + To reset, long press during more than 5 seconds then release. +Please use this procedure only when the primary controller is missing or otherwise inoperable. + To include/add to the Z-Wave network, long press during 2 seconds to send several NIF during 30 seconds or a triple press to send a single NIF + Z-Wave Plus Micro Smart Plug ON/OFF + To exclude/remove from the Z-Wave network, long press during 2 seconds to send several NIF during 30 seconds or a triple press to send a single NIF + The NodOn Micro Smart Plug can be controlled by any kind of Z-Wave® (or Z-Wave Plus®) gateway or other Z-Wave® controller (standalone mode) such as the NodOn® Soft Remote or Octan Remote. +It existed in both standard, Type E (French) or Schuko (German). Its very small design and volume allow easy integration, without obstructing nearby power holes on a power strip. Furthermore, it can perform Power and Energy Metering. +The NodOn Smart Plug is based on brand new 500 series Z-Wave® module from Sigma Designs®, and support all the new features of Z-Wave Plus® standard: +Longer range (up to 40m), lower power consumption, higher data rate transmission, and many more new features. + MSP-3-1-X1 + CEPT (Europe) + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1701/xml + + + - - - After Power-On-Reset of the device, the Channel Output State is set in Default State - - - - - - + + + After Power-On-Reset of the device, the Channel Output State is set in Default State + + + + + + This parameter allows Basic Set Commands to be sent when the channel output state changes (ON or OFF). Only the two least significant bits can be addressed. Bit 0: Enable or disable Basic Set Commands sent to associated nodes of Group 2, when Channel Output State changes. Bit 1: Enable or disable Basic Set Commands sent to associated nodes of Group 3, when Channel Output State changes. - - - This parameter forces the channel output state to be always ON. It is not possible to turn OFF the channel output, which means that: + + + This parameter forces the channel output state to be always ON. It is not possible to turn OFF the channel output, which means that: * All Switch OFF Command is rejected * Basic Set OFF Command is rejected * Binary Switch OFF Command is rejected * Local Control does not toggle channel output state * Product cannot be triggered by unsolicited Notification Report Command and enters in Alarm Mode - - - - - Go to www.nodon.fr/support/msp3/alarm to configure alarm - - - Go to www.nodon.fr/support/msp3/alarm to configure alarm - - - Go to www.nodon.fr/support/msp3/alarm to configure alarm - - - Go to www.nodon.fr/support/msp3/alarm to configure alarm - - - Go to www.nodon.fr/support/msp3/alarm to configure alarm - - - Go to www.nodon.fr/support/msp3/alarm to configure alarm - - - Go to www.nodon.fr/support/msp3/alarm to configure alarm - - - Go to www.nodon.fr/support/msp3/alarm to configure alarm - - - Go to www.nodon.fr/support/msp3/alarm to configure alarm - - - Go to www.nodon.fr/support/msp3/alarm to configure alarm - - - Go to www.nodon.fr/support/msp3/alarm to configure alarm - - - Go to www.nodon.fr/support/msp3/alarm to configure alarm - - - Go to www.nodon.fr/support/msp3/alarm to configure alarm - - - Go to www.nodon.fr/support/msp3/alarm to configure alarm - - - Go to www.nodon.fr/support/msp3/alarm to configure alarm - - - Go to www.nodon.fr/support/msp3/alarm to configure alarm - - - 0 is disabled. 1-100 sends report on x% variation - - - 0 is disabled. 1-4000 sends report on x W overload - - - 0 is disabled. 1-65535 sends report every x seconds - - - 0 is disabled. 1-65535 sends report every x seconds - - - 0 is disabled. 1-65535 x W - - - 0 is disabled. 1-65535 x W - - - 0 disbaled. 1 Send Off to group 4. 3 Send On to group 4. 4 Send Off to group 5. 12 Send On to group 5. Values can be summed - - - - - - - - - - - - - + + + + + Go to www.nodon.fr/support/msp3/alarm to configure alarm + + + Go to www.nodon.fr/support/msp3/alarm to configure alarm + + + Go to www.nodon.fr/support/msp3/alarm to configure alarm + + + Go to www.nodon.fr/support/msp3/alarm to configure alarm + + + Go to www.nodon.fr/support/msp3/alarm to configure alarm + + + Go to www.nodon.fr/support/msp3/alarm to configure alarm + + + Go to www.nodon.fr/support/msp3/alarm to configure alarm + + + Go to www.nodon.fr/support/msp3/alarm to configure alarm + + + Go to www.nodon.fr/support/msp3/alarm to configure alarm + + + Go to www.nodon.fr/support/msp3/alarm to configure alarm + + + Go to www.nodon.fr/support/msp3/alarm to configure alarm + + + Go to www.nodon.fr/support/msp3/alarm to configure alarm + + + Go to www.nodon.fr/support/msp3/alarm to configure alarm + + + Go to www.nodon.fr/support/msp3/alarm to configure alarm + + + Go to www.nodon.fr/support/msp3/alarm to configure alarm + + + Go to www.nodon.fr/support/msp3/alarm to configure alarm + + + 0 is disabled. 1-100 sends report on x% variation + + + 0 is disabled. 1-4000 sends report on x W overload + + + 0 is disabled. 1-65535 sends report every x seconds + + + 0 is disabled. 1-65535 sends report every x seconds + + + 0 is disabled. 1-65535 x W + + + 0 is disabled. 1-65535 x W + + + 0 disbaled. 1 Send Off to group 4. 3 Send On to group 4. 4 Send Off to group 5. 12 Send On to group 5. Values can be summed + + + + + + + + + + + + + diff --git a/config/oomi/ft100.xml b/config/oomi/ft100.xml index 9013d5efd7..eb2dfc27fe 100644 --- a/config/oomi/ft100.xml +++ b/config/oomi/ft100.xml @@ -1,4 +1,25 @@ - + + + http://www.openzwave.com/device-database/016A:0064:0102 + images/oomi/ft100.png + https://products.z-wavealliance.org/products/1534/ + Oomi MultiSensor looks like a motion sensor and it acts like one too. But it’s also so much more. Installing this 1 piece of Z-Wave® technology is the same as installing 6 pieces of Z-Wave technology. Your home control network will immediately understand motion, temperature, humidity, light, Ultraviolet and Vibration readings wherever MultiSensor installed. Those intelligent readings will equate to intelligence automation. And intelligent automation will give you the perfect, smart home. + Pressing the Z-Wave button once will trigger sending the Wake up notification command. If press and hold the Z-Wave button for 3 seconds, the MultiSensor will wake up for 10 minutes. + U.S. / Canada / Mexico + FT100-A + Turn the primary controller of Z-Wave network into exclusion mode, short press the product’s Z-Wave button that you can find in back of the product. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2592/Oomi MultiSensor manual3.pdf + Turn the primary controller of Z-Wave network into inclusion mode, short press the product’s Z-Wave button that you can find in the back of the product. + Press and hold the Z-Wave button that you can find in back of the product for 20 seconds and then release. This procedure should only be used when the primary controller is inoperable. + MultiSensor + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1534/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2592/xml + + https://products.z-wavealliance.org/products/2592/ + China + FT100-K + - - - - - Output Load will be turned off automatically after 30 seconds and if the current overrun 1.5A. - - - - - Output load will be closed after 30 seconds if the temperature inside the product exceeds 100C. - - - - - Configure the output load status after re-power on - - - - - - To set which notification would be sent to the associated nodes in association group 1 when the state of output load is changed - - - - - - - - To set which notification would be sent to the associated nodes in association group 3 when using the external switch 1 to switch the loads - - - - - To set which notification would be sent to the associated nodes in association group 4 when using the external switch 2 to switch the loads - - - - - State appointment +--> + + http://www.openzwave.com/device-database/016A:006F:0103 + images/oomi/ft111.png + https://products.z-wavealliance.org/products/2258/ + Turn the primary controller of Z-Wave network into exclusion mode, short press the product’s Action button that you can find on the product's housing. + Turn the primary controller of Z-Wave network into inclusion mode, short press the product’s Action button that you can find on the product's housing. + Press and hold the Action button that you can find on the product's housing for 20 seconds and then release. This procedure should only be used when the primary controller is inoperable. + Oomi In-Wall Dimmer is a Z-Wave Smart Dimmer specifically used to enable Z-Wave command and control (on/off/dim) of any wall switches. It can report immediate wattage consumption or kWh energy usage over a period of time. In the event of power failure, non-volatile memory retains all programmed information relating to the unit’s operating status. +It can connect to 2 external manual switches to control the load ON/OFF independently. Its surface has a pin socket, which can be used for connecting to the touch panel, so you can also use the touch panel to control the Nano Dimmer. +The In-Wall Dimmer is also a security Z-Wave plus device and supports Over The Air (OTA) feature for the products firmware upgrade. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2765/Oomi In-Wall Dimmer manual (FT111-K) - 2.pdf + U.S. / Canada / Mexico + FT111-A + In-Wall Dimmer + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2258/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2273/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2765/xml + + https://products.z-wavealliance.org/products/2273/ + FT111-B + Australia / New Zealand + https://products.z-wavealliance.org/products/2765/ + FT111-K + China + + + + + Output Load will be turned off automatically after 30 seconds and if the current overrun 1.5A. + + + + + Output load will be closed after 30 seconds if the temperature inside the product exceeds 100C. + + + + + Configure the output load status after re-power on + + + + + + To set which notification would be sent to the associated nodes in association group 1 when the state of output load is changed + + + + + + + + To set which notification would be sent to the associated nodes in association group 3 when using the external switch 1 to switch the loads + + + + + To set which notification would be sent to the associated nodes in association group 4 when using the external switch 2 to switch the loads + + + + + State appointment Set the ON time of output load. Value1 = 0, disable or = non zero, enable (day, bit0 - bit6 represent Mon to Sun). Value2 = ON (hour) Value3 = ON (minute) Value4 = ON (brightness level) - - - State appointment + + + State appointment Set the ON time of output load. Value1 = 0, disable or = non zero, enable (day, bit0 - bit6 represent Mon to Sun). Value2 = ON (hour) Value3 = ON (minute) Value4 = ON (brightness level) - - - Enables/disables parameter 91 and 92 - - - - - The value represents the minimum change in wattage for a Report to be sent (default 25 W) - - - The value represents the minimum percentage change in wattage for a Report to be sent (Default 5) - - - Set report types for groups 1, 2 and 3 to default. - - - + + + Enables/disables parameter 91 and 92 + + + + + The value represents the minimum change in wattage for a Report to be sent (default 25 W) + + + The value represents the minimum percentage change in wattage for a Report to be sent (Default 5) + + + Set report types for groups 1, 2 and 3 to default. + + + Defines the type of report sent for reporting group 1. 1 is meter report for voltage. 2 is meter report for current. @@ -88,9 +112,9 @@ https://products.z-wavealliance.org/products/2765 bit 1 watt bit 0 kWh - - - + + + Defines the type of report sent for reporting group 2. 1 is meter report for voltage. 2 is meter report for current. @@ -105,9 +129,9 @@ https://products.z-wavealliance.org/products/2765 bit 1 watt bit 0 kWh - - - + + + Defines the type of report sent for reporting group 3. 1 is meter report for voltage. 2 is meter report for current. @@ -122,104 +146,104 @@ https://products.z-wavealliance.org/products/2765 bit 1 watt bit 0 kWh - - - Set time interval for sending reports for groups 1, 2 and 3 to default. - - - Defines the time interval when the defined report for group 1 is sent. - - - Defines the time interval when the defined report for group 2 is sent. - - - Defines the time interval when the defined report for group 3 is sent. - - - When the mode is determined, this mode value will not be reset after exclusion - - - - - - - - When the mode is determined, this mode value will not be reset after exclusion - - - - - - - - Get the state of touch panel port - - - - - Set the control destination for external switch S1 - - - - - - Set the control destination for external switch S2 - - - - - - Set the default dimming rate - - - Get the current working mode - - - - - - Set the dimming principle - - - - - To get what type of load the Dimmer is connected to - - - - - - - Set the min brightness level that the load can reach to - - - Set the max brightness level that the load can reach to - - - Set the recognition way of load - - - - - - Enable/disable Configuration Locked - - - - - Reset to factory defaults - - - - - - - - - - - - - - + + + Set time interval for sending reports for groups 1, 2 and 3 to default. + + + Defines the time interval when the defined report for group 1 is sent. + + + Defines the time interval when the defined report for group 2 is sent. + + + Defines the time interval when the defined report for group 3 is sent. + + + When the mode is determined, this mode value will not be reset after exclusion + + + + + + + + When the mode is determined, this mode value will not be reset after exclusion + + + + + + + + Get the state of touch panel port + + + + + Set the control destination for external switch S1 + + + + + + Set the control destination for external switch S2 + + + + + + Set the default dimming rate + + + Get the current working mode + + + + + + Set the dimming principle + + + + + To get what type of load the Dimmer is connected to + + + + + + + Set the min brightness level that the load can reach to + + + Set the max brightness level that the load can reach to + + + Set the recognition way of load + + + + + + Enable/disable Configuration Locked + + + + + Reset to factory defaults + + + + + + + + + + + + + + diff --git a/config/options.xml b/config/options.xml index 7d05169a9e..6707030ff0 100644 --- a/config/options.xml +++ b/config/options.xml @@ -1,12 +1,40 @@ + + diff --git a/config/permundo/psc132zw.xml b/config/permundo/psc132zw.xml new file mode 100644 index 0000000000..d44c99309d --- /dev/null +++ b/config/permundo/psc132zw.xml @@ -0,0 +1,43 @@ + + + http://www.openzwave.com/device-database/0245:0002:0003 + images/permundo/psc132zw.png + https://products.z-wavealliance.org/products/1593/ + Smart Mini Plug + When a PS132ZW that is not associated to a Z-Wave network is inserted into the mains outlet, it will flash once red followed by 2 green flashes followed by steady red flashing. The PSC132ZW can now be added to (=inclusion) or removed from (=exclusion) a Z-Wave network: +1) start inclusion/exclusion on the primary + controller +2) hold the touch button until the led + shows green light +3) release the touch button +The PSC234 will confirm successful removal/exclusion by steady red flashing. At the time of exclusion the device is factory reset. + + The wireless flush-mount switching actuator PSC132ZW allows you to remotely control electrical appliances. It features a metering function to measure the power consumption and the accumulated energy usage of connected equipment. The built-in metering unit is of high quality: it calculates the true-power and also works for small loads from 1W upwards. This feature is important to have a correct measurement value also for electronic loads like led lamps. +The PSC132ZW has a built-in safety features that will switch-off the output in case of too high temperature or overload. +Additionally the PSC132 has a feature to switch the load on at zero voltage and switch the load off at zero current. This leads to a very high number of possible switching cycles also for difficult loads like led-lamps or motors, e.g. pumps. + + Please use this procedure only if the primary controller is missing or inoperable: +The device can be put into factory default state manually by the following procedure: +1) hold the touch-button until the led + shows red light +2) release the touch-button and hold the + touch-button again until the led starts + to flash green +The PSC132ZW confirms the successful completion of the factory reset procedure by steady red flashing. + + PSC132ZW + CEPT (Europe) + When a PS132ZW that is not associated to a Z-Wave network is inserted into the mains outlet, it will flash once red followed by 2 green flashes followed by steady red flashing. The PSC132ZW can now be added to (=inclusion) or removed from (=exclusion) a Z-Wave network: +1) start inclusion/exclusion on the primary + controller +2) hold the touch button until the led + shows green light +3) release the touch button +The PSC234 will confirm successful addition to the network by 5 green flashes. + + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1593/PSC132ZW_V07_EN.pdf + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1593/xml + + + diff --git a/config/permundo/psc234zw.xml b/config/permundo/psc234zw.xml new file mode 100644 index 0000000000..bad7c17d98 --- /dev/null +++ b/config/permundo/psc234zw.xml @@ -0,0 +1,44 @@ + + + http://www.openzwave.com/device-database/0245:0001:0003 + images/permundo/psc234zw.png + https://products.z-wavealliance.org/products/1575/ + The wireless plug socket PSC234ZW allows you to remotely control electrical appliances. It features a metering function to measure the power consumption and the accumulated energy usage of connected equipment. The built-in metering unit is of high quality: it calculates the true-power and also works for small loads from 1W upwards. This feature is important to have a correct measurement value also for electronic loads like led lamps. +The PSC234ZW has a built-in safety features that will switch-off the output in case of too high temperature or overload. +Additionally the PSC234 has a feature to switch the load on at zero voltage and switch the load off at zero current. This leads to a very high number of possible switching cycles also for difficult loads like led-lamps or motors, e.g. pumps. + + PSC234ZW + Smart Plug + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1575/PSC234ZW_V06.pdf + Please use this procedure only if the primary controller is missing or inoperable: +The device can be put into factory default state manually by the following procedure: +1) hold the touch-button until the led + shows red light +2) release the touch-button and hold the + touch-button again until the led starts + to flash green +The PSC234 confirms the successful completion of the factory reset procedure by steady red flashing. + + When a PSC234 that is not associated to a Z-Wave network, is inserted into the mains outlet, it will flash once red followed by 2 green flashed followed by steady red flashing. The PSC234 can now be added to (=inclusion) or removed from (=exclusion) a Z-Wave network: +1) start inclusion/exclusion on the primary + controller +2) hold the touch button until the led + shows green light +3) release the touch button + The PSC234 will confirm successful removal/exclusion by steady red flashing. At the time of exclusion the device is factory reset. + CEPT (Europe) + When a PSC234 that is not associated to a Z-Wave Network, is inserted into the mains outlet, it will flash once red followed by 2 green flashed followed by steady red flashing. The PSC234 can now be added to (=inclusion) or removed from (=exclusion) a Z-Wave network: +1) start inclusion/exclusion on the primary + controller +2) hold the touch button until the led + shows green light +3) release the touch button +The PSC234 will confirm successful addition to the network by 5 green flashes. +The PSC234 will confirm successful removal/exclusion by steady red flashing. At the time of exclusion the device is factory reset. + + + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1575/xml + + + diff --git a/config/philio/pad02.xml b/config/philio/pad02.xml index 20f56da6e5..1cfb8773a9 100644 --- a/config/philio/pad02.xml +++ b/config/philio/pad02.xml @@ -1,46 +1,73 @@ - - - - - - + + + Whenever dimmer on/off state changes, it will send MULTILEVEL_SWITCH_ REPORT to the nodes of group1. The default setting is Enable the function. - - - - - + + + + + Show dimmer State: When dimmer is on, LED is on. When dimmer is off, LED is off. Show Night mode: When dimmer is on, LED is off. When dimmer is off, LED is on. One flash mode: When dimmer on/off state changes, LED will light on one second and then off. - - - - - - + + + + + + Whenever the AC power return from lost, PAD02 will restore the switch state which could be Dimmer off, Last dimmer state, Dimmer on. The default setting is Last dimmer state. - - - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/config/philio/pan05.xml b/config/philio/pan05.xml index 4877f23cd8..f53719958f 100644 --- a/config/philio/pan05.xml +++ b/config/philio/pan05.xml @@ -1,28 +1,34 @@ - + http://www.openzwave.com/device-database/013C:0010:0001 images/philio/pan05.png - https://products.z-wavealliance.org/products/1149/ + https://products.z-wavealliance.org/products/1663/ CEPT (Europe) - 1. Put your Z-Wave controller into exclusion mode by following the instructions provided by the controller manufacturer. -2. Pressing Include button of PAN05 three times within 2 seconds will enter inclusion mode. - This in-wall switch module is a transceiver which is a security enabled device which based on Z-Wave Plus technology, and it is fully compatible with any Z-Wave™ enabled network. Mini size design let the module can easily hide itself into the wall box and that will be good for the house decoration. Since PAN05 supports Security Command Class, it can learn with Secured controller. Its functionality and supported command classes is identical when included as a secure and non-secure device. + 1.Put your Z-Wave controller into exclusion mode by following the instructions provided by the controller manufacturer. +2.Pressing Include button of PAN05 three times within 2 seconds will enter exclusion mode. +3.Node ID has been excluded. + This in-wall switch module is a transceiver which is a security enabled device which based on Z-Wave Plus technology, and it is fully compatible with any Z-WaveTM enabled network. Mini size design let the module can easily hide itself into the wall box and that will be good for the house decoration. Since PAN05 supports Security Command Class, it can learn with Secured controller. Its functionality and supported command classes is identical when included as a secure and non-secure device. +There are many kind of application by using the module to switch Load On and Off, one main application is the light control. If connect the COM terminal directly to AC Line terminal, the new smart relay calibration technology can reduce the inrush current caused by the load and let the module work perfectly with many kind of light like incandescent, fluorescent and LED light. This module can also connect to alternative power supply like DC 12V to switch on/off 12V MR-16 light. -There are many kind of application by using the module to switch Load On and Off, one main application is the light control. If connect the COM terminal directly to AC Line terminal, the new smart relay calibration technology can reduce the inrush current caused by the load and let the module work perfectly with many kind of light like incandescent, fluorescent and LED light. This module can also connect to alternative power supply like DC 12V to switch on/off 12V MR-16 light. +Adding to Z-WaveTM Network +In the front casing, there is an on/off button with LED indicator below which is used to toggle switch on and off or carries out add, remove, reset or association. When first power applied, its LED flashes on and off alternately and repeatedly at 0.5 second intervals. It implies that it has not been assigned a node ID and start auto inclusion. - - 1. Put your Z-Wave controller into inclusion mode by following the instructions provided by the controller manufacturer. -2. Pressing Include button of PAN05 three times within 2 seconds will enter inclusion mode. - - This procedure should only be used in the event that the primary controller is lost or otherwise inoperable. -1. Pressing Include button of PAN05 three times within 2 seconds will enter inclusion mode. -2. Within 1 second, press Include button of PAN05 again for 5 seconds. -3. IDs are excluded. - In Wall Single relay (1 way) switch module - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1149/PAN05-1-2-3A manual-20140923.pdf - PAN05-1A +Auto Inclusion +The function of auto inclusion will be executed as long as the in wall switch does not have Node ID and just connect the switch to main power. +Note: Auto inclusion timeout is 2 minute during which the node information of explorer frame will be emitted once every several seconds. Unlike “Add” function as shown in the table below, the execution of auto inclusion is free from pressing the On/Off button on the Switch. + 1.Put your Z-Wave controller into inclusion mode by following the instructions provided by the controller manufacturer. +2.Pressing Include button of PAN05 three times within 2 seconds will enter inclusion mode. + Use this procedure only in the event that the primary controller is lost or otherwise inoperable. +1.Pressing Include button of PAN05 three times within 2 seconds will enter inclusion mode. +2.Within 1 second, press Include button of PAN05 again for 5 seconds. +3.IDs are excluded. + In Wall Single relay(1way) switch module + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1663/PAN05-1-2-3B manual-20160215.pdf + PAN05-1B Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1149/xml + Fix WhiteSpace Error + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1663/xml @@ -75,7 +81,7 @@ There are many kind of application by using the module to switch Load On and Off - + diff --git a/config/philio/pan08.xml b/config/philio/pan08.xml index a39feca415..2f56108506 100644 --- a/config/philio/pan08.xml +++ b/config/philio/pan08.xml @@ -1,4 +1,4 @@ - + http://www.openzwave.com/device-database/013C:0006:0001 images/philio/pan08.png @@ -6,8 +6,7 @@ CEPT (Europe) / U.S. / Canada / Mexico http://www.philio-tech.com/p_switch.htm The in-wall Roller Shutter Controller is designed to switch rise/lower roller shutter connected to its terminals using radio waves, controllers and a push button directly connected to this Roller Controller. -This in-wall Roller Shutter Controller is a transceiver which is a Z-Wave Plus™ - enabled device and is fully compatible with any Z-Wave™ enabled network. Slim design let the Controller can easily hide itself into the wall box and that will be good for the house decoration. +This in-wall Roller Shutter Controller is a transceiver which is a Z-Wave Plus™ enabled device and is fully compatible with any Z-Wave™ enabled network. Slim design let the Controller can easily hide itself into the wall box and that will be good for the house decoration. The new smart relay calibration technology can reduce the inrush current caused by the load and let the module work perfectly with many kind of Roller Shutter. This in-wall Roller Shutter Controller is able to detect position of the Shutter by using the patterned power measuring method, so it can be remote controlled not only fully up or down, but also can be adjusted to ex. 30% or 50%. And when manual controlled by push button, the controller also can memorize the position and send the new shutter position to its controller (ex. IP-Gateway). Roller shutter controller @@ -16,18 +15,20 @@ This in-wall Roller Shutter Controller is able to detect position of the Shutter Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/880/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/891/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1164/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2580/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2914/xml - https://products.z-wavealliance.org/products/1164/ + https://products.z-wavealliance.org/products/2914/ Use this procedure only in the event that the primary controller is lost or otherwise inoperable. 1. Pressing Include button three times within 2 seconds will enter inclusion mode. 2. Within 1 second, press Include button again for 5 seconds. - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1164/PAN08-1A manual-20141027.doc - CEPT (Europe) + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2914/PAN08 manual-20180423.pdf + CEPT (Europe) / Brazil / Japan 1. Put your Z-Wave controller into inclusion mode by following the instructions provided by the controller manufacturer. 2. Pressing Include button three times within 2 seconds will enter inclusion mode. 1. Put your Z-Wave controller into exclusion mode by following the instructions provided by the controller manufacturer. 2. Pressing Include button three times within 2 seconds will enter exclusion mode. - PAN08-1A + PAN08-3 diff --git a/config/philio/pan11.xml b/config/philio/pan11.xml index ade7b0d63c..e667477929 100644 --- a/config/philio/pan11.xml +++ b/config/philio/pan11.xml @@ -1,29 +1,38 @@ - + http://www.openzwave.com/device-database/013C:0011:0001 images/philio/pan11.png - https://products.z-wavealliance.org/products/1088/ + https://products.z-wavealliance.org/products/1598/ CEPT (Europe) - (Use this procedure only in the event that the primary controller is lost or otherwise inoperable.) + Use this procedure only in the event that the primary controller is lost or otherwise inoperable. -1. Pressing On/Off button three times within 2 seconds will enter inclusion mode on the switch. +1. Pressing On/Off button three times within 2 seconds will enter inclusion mode. Use this procedure only in the event that the primary controller is lost or otherwise inoperable. 2. Within 1 second, press On/Off button again for 5 seconds. - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1088/PAN11-1B manual-20140816.pdf - 1. Put your Z-Wave controller into inclusion mode by following the instructions provided by the controller manufacturer. -2. Pressing On/Off button three times within 2 seconds will enter inclusion - mode on the switch. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1598/PAN11-1B manual-20151204.pdf + 1. Put your Z-Wave controller into inclusion mode by following the instructions provided by the controller manufacturer. +2. Pressing On/Off button three times within 2 seconds will enter inclusion mode. Smart Energy Plug In Switch - 1. Put your Z-Wave controller into exclusion mode by following the instructions provided by the controller manufacturer. -2. Pressing On/Off button three times within 2 seconds will enter exclusion - mode on the switch. - PAN11-1A - This plug-in ON/OFF switch PAN11 is a security enabled wireless switch, based on Z-Wave Plus™ technology. Z-Wave Plus™ enabled devices displaying the Z-Wave Plus™ logo can also be used with it regardless of the manufacturer, and can also be used in other manufacturer’s Z-Wave™ enabled networks. Remote On/Off control of the connected load is possible with other manufacturer’s wireless controller. Each switch is designed to act as a repeater. Repeaters will re-transmit the RF signal to ensure that the signal is received by its intended destination by routing the signal around obstacles and radio dead spots. Because PAN11 supports Security Command Class, it can learn with Secured controller. Its functionality and supported command classes is identical when included as a secure and non-secure device. + 1. Put your Z-Wave controller into exclusion mode by following the instructions provided by the controller manufacturer. +2. Pressing On/Off button three times within 2 seconds will enter exclusion mode. + PAN11-1B + This plug-in ON/OFF switch PAN11 is a security enabled wireless switch, based on Z-Wave Plus technology. Z-Wave PlusTM enabled devices displaying the Z-Wave PlusTM logo can also be used with it regardless of the manufacturer, and can also be used in other manufacturer’s Z-WaveTM enabled networks. Remote On/Off control of the connected load is possible with other manufacturer’s wireless Controller. Each switch is designed to act as a repeater. Repeaters will re-transmit the RF signal to ensure that the signal is received by its intended destination by routing the signal around obstacles and radio dead spots. Because PAN11 supports Security Command Class, it can learn with Secured controller. Its functionality and supported command classes is identical when included as a secure and non-secure device. -This plug-in ON/OFF switch is able to detect instance wattage (3000W/CE/CN, 1500W/UL/TW/JP) and overload current (14.5A) of connected lights or appliances. When detecting overload state, the Switch will be disabled and its On/Off button will be lockout of which LED will flash quickly. However, unplug and re-connect the switch will reset its overload condition to normal status. +This plug-in ON/OFF switch is able to detect instance wattage (3000W/CE/CN, 1560W/UL/TW/JP) and overload current (14.5A with resistive load) of connected lights or appliances. When detecting overload state, the Switch will be disabled and its On/Off button will be lockout of which LED will flash quickly. However, unplug and re-connect the switch will reset its overload condition to normal status. + +Adding to Z-WaveTM Network + +In the front casing, there is an On/Off button with LED indicator which is used to toggle switch on and off or carry out inclusion, exclusion, reset or association. When first power is applied, its LED flashes on and off alternately and repeatedly at 0.5 second intervals. It implies that it has not been assigned a node ID and start auto inclusion. + +Auto Inclusion + +The function of auto inclusion will be executed as long as the switch does not have Node ID and just plug the switch into a wall outlet. + +Note: Auto inclusion timeout is 2 minute during which the node information of explorer frame will be emitted once several seconds. Unlike “inclusion” function as shown in the table below, the execution of auto inclusion is free from pressing the On/Off button on the Switch. Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1088/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1598/xml diff --git a/config/philio/pan16.xml b/config/philio/pan16.xml index 794cc1aca8..8c5d843e85 100644 --- a/config/philio/pan16.xml +++ b/config/philio/pan16.xml @@ -1,69 +1,100 @@ - - - - - - The interval at which the device reports its instant power consumption to Group 1 nodes. Unit: 5 secs, Min: 1, Max: 32767, Default: 720 (= 1 hr) - - - The interval at which the device reports its accumulated energy consumption, in kWh, to all Group 1 nodes. Unit: 10 minutes, min: 1, max: 32767, default: 6 (= 1 hr) - - - When the current through the device exceeds this threshold, a current meter report will be sent to Group 1 nodes. min: 10, max: 1100, default: 1100 (= 11 A) - - - When the energy consumption through the device exceeds this threshold, a kWh report will be sent to Group 1 nodes. min: 1, max: 10000, default: 10000 kWh - - - After loss of power, device state will be set according to this parameter, default: Previous state. - - - - - - When set to Disable, all commands to switch off the device are ignored, both via radio and the include button. default: Enable - - - - - Controls the light indicator in the device + + + The interval at which the device reports its instant power consumption to Group 1 nodes. Unit: 5 secs, Min: 1, Max: 32767, Default: 720 (= 1 hr) + + + The interval at which the device reports its accumulated energy consumption, in kWh, to all Group 1 nodes. Unit: 10 minutes, min: 1, max: 32767, default: 6 (= 1 hr) + + + When the current through the device exceeds this threshold, a current meter report will be sent to Group 1 nodes. min: 10, max: 1100, default: 1100 (= 11 A) + + + When the energy consumption through the device exceeds this threshold, a kWh report will be sent to Group 1 nodes. min: 1, max: 10000, default: 10000 kWh + + + After loss of power, device state will be set according to this parameter, default: Previous state. + + + + + + When set to Disable, all commands to switch off the device are ignored, both via radio and the include button. default: Enable + + + + + Controls the light indicator in the device Switch State: When switch is on, LED is on. When switch is off, LED is off. (default) Night mode: When switch is on, LED is off. When switch is off, LED is on. One flash: When the device changes state, the LED illuminates for one second. - - - - - - Controls the auto-off timer + + + + + + Controls the auto-off timer 0: The auto off timer is disabled (default) 1-32767: After switching on, the device will automatically switch off after this time - - - Controls how the device reacts to the SWITCH_ALL_OFF command + + + Controls how the device reacts to the SWITCH_ALL_OFF command Off: The device switches off (default) Ignore: The switch off command is ignored Toggle: It switches to the inverse of current state On: The device switches on - - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/config/philio/phpab01.xml b/config/philio/phpab01.xml index 9a365c033d..aae77e23ba 100644 --- a/config/philio/phpab01.xml +++ b/config/philio/phpab01.xml @@ -1,5 +1,27 @@ - - + + + http://www.openzwave.com/device-database/013C:001A:0006 + images/zipato/phpab01.png + https://products.z-wavealliance.org/products/2420/ + This product can be operated in any Z-Wave network with other Z-Wave certified devices from other manufacturers. All non-battery operated nodes within the network will act as repeaters regardless of vendor to increase reliability of the network. Zipato Energy Meter monitors total electricity consumption of connected appliances and reports it to Zipato or any other Z-Wave enabled controller in real time. Small and compact size allows easy installation in majority of electricity distribution boxes. It supports two loads upto 6000W each (@ 120V). + ph-pab01 + Put your Z-Wave controller into inclusion mode by following the instructions provided by the controller manufacturer. +Pressing On/Off (Include) button three times within 2 seconds will enter inclusion mode. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2420/ph-pab01 - MM Energy Meter User Manual v1.1 - Print.pdf + CEPT (Europe) + Micromodule Energy Meter, Z-Wave + Use this procedure only in the event that the network primary controller is missing or otherwise inoperable. +Pressing On/Off (Include) button three times within 2 seconds will enter inclusion mode. +Within 1 second, press and hold On/Off (Include) button again for 5 seconds until LED is off. +IDs are excluded. + Put your Z-Wave controller into exclusion mode by following the instructions provided by the controller manufacturer. +Pressing On/Off (Include) button three times within 2 seconds will enter exclusion mode. +Node ID has been excluded. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1599/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2420/xml + + diff --git a/config/philio/phpat02.xml b/config/philio/phpat02.xml index 4f2c821f07..de3c8e4748 100644 --- a/config/philio/phpat02.xml +++ b/config/philio/phpat02.xml @@ -1,31 +1,36 @@ - + http://www.openzwave.com/device-database/013C:001F:0002 images/philio/phpat02.png - https://products.z-wavealliance.org/products/1450/ - PAT02-1A - CEPT (Europe) - The flood multisensor PAT02 has flood, temperature and humidity, 3 sensors function in one, based on Z-Wave™ technology. Using Z-Wave™ plus technology, it supports security and Over-The-Air updating. - Flood Multisensor - When the device power on, the device will wake about 20 seconds. In this duration, the controller can communicate with the device. Normally the device is always sleeping to save the battery energy. - - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1450/PAT02_Manual.pdf - 1. Have Z-Wave™ Controller entered exclusion mode. -2. Pressing tamper key three times within 1.5 seconds to enter the exclusion mode. + https://products.z-wavealliance.org/products/2875/ + PAT02-5A + CEPT (Europe) / Russia / Russia + This is a Z-WaveTM plus product, it supports security OTA with the newest features of the Z-Wave technology. Z-Wave is a wireless communication protocol designed for home automation, specifically to remotely control applications in residential and light commercial environments. The technology uses a low-power RF radio embedded or retrofitted into home electronics devices and systems, such as lighting, home access control, entertainment systems and household appliances + Датчик протечки (Leakage sensor) + After the device adding to the network, it will wake-up once per day in default. When it wake-up it will broadcast the “Wake Up Notification” message to the network, and wake-up 10 seconds for receive the setting commands. +The wake-up interval minimum setting is 30 minutes, and maximum setting is 120 hours. And the interval step is 30 minutes. + +Press the tamper key once. The device will wake-up 10 seconds. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2875/PAT02_Manual.pdf + 1. Have Z-WaveTM Controller entered exclusion mode. + 2. Pressing tamper key three times within 1.5 seconds to enter the exclusion mode. Node ID has been excluded. - Notice: Use this procedure only in the event that the primary controller is lost or otherwise inoperable. -1. Pressing tamper key four times within 1.5 seconds and do not release the tamper key in the 4th pressed, and the LED will light ON. -2. After 3 seconds the LED will turn OFF, after that within 2 seconds, release the tamper key. If successful, the LED will light ON one second. Otherwise, the LED will flash once. -3. IDs are excluded and all settings will reset to factory default. - 1. Have Z-Wave™ Controller entered inclusion mode. -2. Pressing the tamper key three times within 1.5 seconds to enter the inclusion mode. -3. After add successful, the device will wake to receive the setting command from Z-Wave™ Controller about 20 seconds. + Notice: Use this procedure only in the event that the primary controller is lost or otherwise inoperable. + 1. Pressing tamper key four times within 1.5 seconds and do not release the tamper key in the 4th pressed, and the LED will light ON. + 2. After 3 seconds the LED will turn OFF, after that within 2 seconds, release the tamper key. If successful, the LED will light ON one second. Otherwise, the LED will flash once. + 3. IDs are excluded and all settings will reset to factory default. + + 1. Have Z-WaveTM Controller entered inclusion mode. + 2. Pressing the tamper key three times within 1.5 seconds to enter the inclusion mode. + 3. After add successful, the device will wake to receive the setting command from Z-WaveTM Controller about 20 seconds. Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1186/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1299/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1450/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2834/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2875/xml diff --git a/config/philio/phpsg01.xml b/config/philio/phpsg01.xml index 688c415126..98bb9f72d6 100644 --- a/config/philio/phpsg01.xml +++ b/config/philio/phpsg01.xml @@ -1,26 +1,37 @@ - + http://www.openzwave.com/device-database/013C:001E:0002 images/philio/phpsg01.png - https://products.z-wavealliance.org/products/1167/ - Smoke Sensor - The Smoke Sensor PSG01 is designed to give early warning of developing fires by giving off the alarm sounds from its build-in alarm horn, based on Z-Wave™ technology. -It is a Z-Wave™ plus product, it supports the security, OTA... Those newest features of the Z-Wave™ technology. Z-Wave™ is a wireless communication protocol designed for home automation, specifically to remotely control applications in residential and light commercial environments. The technology uses a low-power RF radio embedded or retrofitted into home electronics devices and systems, such as lighting, home access control, entertainment systems and household appliances. - 1. Have Z-Wave™ Controller entered inclusion mode. -2. Pressing button three times within 1.5 seconds to enter the inclusion mode. -3. After add successful, the device will wake to receive the setting command from Z-Wave™ Controller about 20 seconds. - 1. Have Z-Wave™ Controller entered exclusion mode. -2. Pressing button three times within 1.5 seconds to enter the exclusion mode. Node ID has been removed. - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1167/PSG01_Manual.pdf - Notice: Use this procedure only in the event that the primary controller is lost or otherwise inoperable. -1. Pressing button four times within 1.5 seconds and do not release the button in the 4 th pressed, and the red LED will light ON. -2. After the red LED flash 9 times, release the button within 2 seconds. -3. IDs are removed and all settings will reset to factory default. - PSG01 - CEPT (Europe) - After the device adding to the network, it will wake-up once per day in default. When it wake-up it will broadcast the “Wake Up Notification” message to the network, and wake-up 10 seconds for receive the setting commands. The wake-up interval minimum setting is 30 minutes, and maximum setting is 120 hours. And the interval step is 30 minutes. If the user want to wake-up the device immediately, please press the button once. The device will wake-up 10 seconds. + https://products.z-wavealliance.org/products/2868/ + Датчика дыма (Smoke sensor) + This is the Z-WaveTM plus Smoke Sensor, it supports security OTA with the newest features of the Z-Wave technology. Z-Wave is a wireless +communication protocol designed for home automation, specifically to +remotely control applications in residential and light commercial +environments. The technology uses a low-power RF radio embedded or +retrofitted into home electronics devices and systems, such as lighting, +home access control, entertainment systems and household appliances. + 1. Have Z-Wave Controller entered inclusion mode. + 2. Pressing button three times within 1.5 seconds will enter the inclusion mode. + 3. After add successful, the device will wake to receive the setting command from Z-Wave Controller, about 20 seconds. + + 1. Have Z-Wave Controller entered exclusion mode. + 2. Pressing button three times within 1.5 seconds to enter the exclusion mode. Node ID has been removed. + + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2868/PSG01_Manual-2015-06-12.pdf + Notice: Use this procedure only in the event that the primary controller is lost or otherwise inoperable. + 1. Pressing button four times within 1.5 seconds and do not release the button in the 4th press, the red LED will light be ON. + 2. After the red LED flash 9 times, release the button within 2 seconds. + 3. IDs are removed and all settings will reset to factory default. + PSG01 + CEPT (Europe) / Russia / Russia + After the device is added to the network, it will wake-up once per day in default. When it wakes-up it will broadcast the “Wake Up Notification” message to the network, and wake-up 10 seconds to receive the setting commands. +The wake-up interval minimum setting is 30 minutes, the maximum setting is 120 hours, the interval step is 30 minutes. + +If the user wants to wake-up the device immediately, please press the button once. The device will wake-up 10 seconds. Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1167/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2835/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2868/xml diff --git a/config/philio/pse02.xml b/config/philio/pse02.xml index 7cd99d5bbf..62de4031c3 100644 --- a/config/philio/pse02.xml +++ b/config/philio/pse02.xml @@ -1,5 +1,29 @@ - - + + + http://www.openzwave.com/device-database/013C:000A:0004 + images/zipato/pse02.png + https://products.z-wavealliance.org/products/2419/ + 1. Have Z-Wave Controller entered inclusion mode. +2. Pressing tamper key three times within 1.5 seconds +to enter the inclusion mode. +3. After add successful, the LED will light ON 1 second + Notice: Use this procedure only in the event that the primary controller is lost or otherwise inoperable. +1. Pressing tamper key four times within 1.5 seconds and do not release the tamper key in the 4 pressed, and the LED will light ON. +2. After 3 seconds the LED will turn OFF, after that within 2 seconds, release the tamper key. If successful, the LED will light ON one second. Otherwise, the LED will flash once. +3. IDs are excluded and all settings will reset to factory default. + Indoor Siren, Multisound, Z-wave + 1. Have Z-Wave Controller entered exclusion mode. +2. Pressing tamper key three times within 1.5 seconds to enter the exclusion mode. +Node ID has been excluded. + Zipato Indoor Siren is a wireless siren, based on Z-Wave technology. It is the Z-Wave plus product, it supports the security, OTA... all the newest features of the Z-Wave technology. + ph-pse02.eu + CEPT (Europe) + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2419/Zipato_Siren-UserManual.pdf + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2266/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2419/xml + + diff --git a/config/philio/psm02.xml b/config/philio/psm02.xml index 1535d799ee..c5a64f963d 100644 --- a/config/philio/psm02.xml +++ b/config/philio/psm02.xml @@ -1,4 +1,4 @@ - + http://www.openzwave.com/device-database/013C:0002:0002 images/philio/psm02.png @@ -27,6 +27,7 @@ Features Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/821/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/835/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/836/xml + Fix Philio door sensors #1898 http://philio-tech.com/ @@ -139,9 +140,6 @@ Features - - false - diff --git a/config/philio/psp05.xml b/config/philio/psp05.xml index b5a826c50e..fb4a5300a5 100644 --- a/config/philio/psp05.xml +++ b/config/philio/psp05.xml @@ -1,22 +1,45 @@ - - - +--> + + http://www.openzwave.com/device-database/013C:0050:0002 + images/philio/psp05.png + https://products.z-wavealliance.org/products/2068/ + CEPT (Europe) / Australia / New Zealand / U.S. / Canada / Mexico + PSP05 + The PIR sensor PSP05 has PIR sensor function,based on Z-Wave™ technology. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2068/PSP05_manual.pdf + There is a button on PSP05. +1. Pressing button for about 5 seconds. +2. IDs are excluded and all settings will reset to factory default. +Notice: Use this procedure only in the event that the primary controller is lost or otherwise inoperable. + There is a button on PSP05. +1. Have Z-Wave™ Controller entered inclusion mode. +2. Pressing button once to enter the inclusion mode. +3. After add successful, the device will wake to receive the setting command from Z-Wave™ Controller about 20 seconds. + There is a button on PSP05. +1. Have Z-Wave™ Controller entered exclusion mode. +2. Pressing button once to enter the exclusion mode. + Single Function PIR Sensor + There is a button on PSP05. +Press the button once, the device will awake 10 seconds. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2002/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2037/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2068/xml + + - - + Setting the BASIC command value to turn on the light. The 0xFF (-1) means turn on the light. For dimmer equipment 1 to 100 means the light strength. 0 means turn off the light. - - + 0 means disable the PIR motion. 1 means the lowest sensitivity. @@ -24,9 +47,8 @@ http://products.z-wavealliance.org/ProductManual/File?folder=&filename=Manuals/2 High sensitivity means can detected long distance, but if there is more noise signal in the invironment, it wil re-trigger too frequent. - - - + + Multi-Sensor Function switch. Using bit to control. Bit 0: Reserved always 0 Bit 1: Reserved always 0 @@ -38,9 +60,8 @@ http://products.z-wavealliance.org/ProductManual/File?folder=&filename=Manuals/2 Bit 7: Reserve. - - - + + Customer function switch, using bit control. Bit 0: Reserve. Bit 1: Enable sending motion OFF report (0:Disable, 1:Enable). @@ -54,45 +75,38 @@ http://products.z-wavealliance.org/ProductManual/File?folder=&filename=Manuals/2 ozw recommended setting: 00010110 : 22 - - - + + In the normal mode, after the PIR motion detected, setting the re-detect time, 8 seconds per tick, default tick is 3 (24 seconds). Setting the suitable value to prevent received the trigger signal too frequency. Also can save the battery energy. Notice: If this value bigger than the configuration setting NO. 9. There is a period after the light turned off and the PIR not start detecting. - - - + + After turn on the lighting, setting the delay time to turn off the lighting when the PIR motion is not detected. 8 seconds per tick, default tick is 4 (32 seconds). 0 means never send turn off light command. - - + The interval time for auto report the battery level. 0 means turn off auto report battery. The default value is 12. The tick time can setting by the configuration No.20. - - + The interval time for auto report each tick. Setting this configuration will effect configuration No.10, No.11, No.12 and No.13. Caution: Setting to 0 means turn off all auto report function. - - - - + + - diff --git a/config/philio/psr04.xml b/config/philio/psr04.xml index 07d5b55b40..c1068fb0cb 100644 --- a/config/philio/psr04.xml +++ b/config/philio/psr04.xml @@ -1,8 +1,8 @@ - + http://www.openzwave.com/device-database/013C:0022:0009 images/philio/psr04.png - https://products.z-wavealliance.org/products/1448/ + https://products.z-wavealliance.org/products/2573/ 1. Have Z-Wave™ Controller entered inclusion mode. 2. Rotate to area A and then press button three times within 1.5 seconds to enter the inclusion mode. 3. After add successful, the device will wake to receive the setting command from Z-Wave™ Controller about 20 seconds. @@ -16,15 +16,16 @@ magnetic back let the switch can be fixed on the wall. This product can be included and operated in any Z-Wave™ network with other Z-Wave™ certified devices from other manufacturers and/or other applications. PSR04 Smart Color Button - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1448/PSR04_Manual-2015-08-11.pdf + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2573/PSR04_manual.pdf Notice: Use this procedure only in the event that the primary controller is lost or otherwise inoperable. 1. Rotate to area A and then press button four times within 1.5 seconds and do not release the button in the 4 th pressed, and the red LED will light ON. 2. After the red LED goes out, release the button within 2 seconds. 3. IDs are removed and all settings will reset to factory default. - CEPT (Europe) + CEPT (Europe) / Brazil Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1300/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1448/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2573/xml diff --git a/config/philio/pst02-1c.xml b/config/philio/pst02-1c.xml index 75249b9dd2..86550dbfb8 100644 --- a/config/philio/pst02-1c.xml +++ b/config/philio/pst02-1c.xml @@ -1,33 +1,46 @@ - + http://www.openzwave.com/device-database/013C:000E:0002 images/philio/pst02-1c.png - https://products.z-wavealliance.org/products/1092/ - The slim multisensor PST02 has door/window, temperature and illumination, 3 sensors function in one,based on Z-Wave technology. - There are two tamper keys in the device, one is in the back side, another is in the front side. Both of them can add, remove, reset or association from Z-Wave network. -To reset the device: -Notice: Use this procedure only in the event that the primary controller is lost or otherwise inoperable. -1. Pressing tamper key four times within 1.5 seconds and do not release the tamper key in the 4th pressed, and the LED will light ON. -2. After 3 seconds the LED will turn OFF, after that within 2 seconds, release the tamper key. If successful, the LED will light ON one second. Otherwise, the LED will flash once. + https://products.z-wavealliance.org/products/2872/ + The slim multisensor PST02-1C has door/window, temperature and illumination, 3 sensors function in one,based on Z-Wave technology +It is the Z-WaveTM plus product, it support the security, OTA... Those +newest features of the Z-WaveTM technology. Z-WaveTM is a wireless +communication protocol designed for home automation, specifically to +remotely control applications in residential and light commercial +environments. The technology uses a low-power RF radio embedded or +retrofitted into home electronics devices and systems, such as lighting, +home access control, entertainment systems and household appliances. + Notice: Use this procedure only in the event +that the primary controller is lost or otherwise inoperable. +1. Pressing tamper key four times within 1.5 seconds and do not release the tamper key on the 4th press, the LED lite will ON. +2. After 3 seconds the LED will turn OFF, after that within 2 seconds, release the tamper key. If successful, the LED will light ON one second. +Otherwise, the LED will flash once. 3. IDs are excluded and all settings will reset to factory default. - PST02-1C - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1092/PST02_Manual-2014-08-15B.pdf - There are two tamper keys in the device, one is in the back side, another is in the front side. Both of them can add, remove, reset or association from Z-Wave network. -Press any key once, the device will awake 10 seconds. - There are two tamper keys in the device, one is in the back side, another is in the front side. Both of them can add, remove, reset or association from Z-Wave network. -To add into a Z-Wave network: -1. Have Z-Wave Controller entered inclusion mode. -2. Pressing tamper key three times within 1.5 seconds to enter the inclusion mode. -3. After add successful, the device will wake to receive the setting command from Z-Wave Controller about 20 seconds. - Slim Multisensor - CEPT (Europe) - There are two tamper keys in the device, one is in the back side, another is in the front side. Both of them can add, remove, reset or association from Z-Wave network. -To remove the device from a Z-Wave network: -1. Have Z-Wave Controller entered exclusion mode. -2. Pressing tamper key three times within 1.5 seconds to enter the exclusion mode. + PST02-5C + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2872/PST02_UserManual.pdf + After the device adding to the network, it will wake-up once per day in +default. When it wakes-up it will broadcast the “Wake Up Notification” +message to the network, and wake-up 10 seconds to receive the +setting commands. +The wake-up interval minimum setting is 30 minutes, and maximum +setting is 120 hours. And the interval step is 30 minutes. +If the user want to wake-up the device immediately, please remove the +front cover, and press the tamper key once. The device will wake-up 10 +seconds. + 1. Have Z-WaveTM Controller enter inclusion mode. +2. Pressing tamper key three times within 1.5 seconds +will enter the inclusion mode. +3. After add successful, the device will wake to receive the setting command from Z-WaveTM Controller, about 20 seconds + Датчик открытия (Door sensor) + CEPT (Europe) / Russia / Russia + 1. Have Z-WaveTM Controller enter exclusion mode. +2. Pressing tamper key three times within 1.5 seconds will enter the exclusion mode. Node ID has been excluded. Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1092/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2839/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2872/xml diff --git a/config/philio/pst02-b.xml b/config/philio/pst02-b.xml index 463c4b4e45..2a2d81ae04 100644 --- a/config/philio/pst02-b.xml +++ b/config/philio/pst02-b.xml @@ -1,33 +1,59 @@ - + http://www.openzwave.com/device-database/013C:000D:0002 images/philio/pst02-b.png - https://products.z-wavealliance.org/products/1090/ - There are two tamper keys in the device, one is in the back side, another is in the front side. Both of them can add, remove, reset or association from Z-Wave network. -To add into a Z-Wave network: -1. Have Z-Wave Controller entered inclusion mode. -2. Pressing tamper key three times within 1.5 seconds to enter the inclusion mode. -3. After add successful, the device will wake to receive the setting command from Z-Wave Controller about 20 seconds. - PST02-1B - There are two tamper keys in the device, one is in the back side, another is in the front side. Both of them can add, remove, reset or association from Z-Wave network. -To reset the device: -Notice: Use this procedure only in the event that the primary controller is lost or otherwise inoperable. -1. Pressing tamper key four times within 1.5 seconds and do not release the tamper key in the 4th pressed, and the LED will light ON. -2. After 3 seconds the LED will turn OFF, after that within 2 seconds, release the tamper key. If successful, the LED will light ON one second. Otherwise, the LED will flash once. -3. IDs are excluded and all settings will reset to factory default. - There are two tamper keys in the device, one is in the back side, another is in the front side. Both of them can add, remove, reset or association from Z-Wave network. -Press any key once, the device will awake 10 seconds. - Slim Multisensor - The slim multisensor PST02 has PIR, temperature and illumination, 3 sensors function in one,based on Z-Wave technology. - There are two tamper keys in the device, one is in the back side, another is in the front side. Both of them can add, remove, reset or association from Z-Wave network. -To remove the device from a Z-Wave network: -1. Have Z-Wave Controller entered exclusion mode. -2. Pressing tamper key three times within 1.5 seconds to enter the exclusion mode. + https://products.z-wavealliance.org/products/2860/ + There are two tamper keys in the device, one is in the back side, +another is in the front side. Both of them can add, remove or reset from Z-WaveTM network. +1. Have Z-WaveTM Controller entered inclusion mode. +2. Pressing tamper key three times within 1.5 seconds +to enter the inclusion mode. +3. After add successful, the device will wake to +receive the setting command from Z-WaveTM +Controller about 20 seconds + + PST02-5B + 1. Pressing tamper key four times within 1.5 seconds +and do not release the tamper key in the 4th +pressed, and the LED will light ON. +2. After 3 seconds the LED will turn OFF, after that +within 2 seconds, release the tamper key. If +successful, the LED will light ON one second. +Otherwise, the LED will flash once. +3. IDs are excluded and all settings will reset to +factory default. + +*Please use this procedure only when the network primary controller is missing or otherwise inoperable. + After the device adding to the network, it will wake-up once per day in +default. When it wake-up it will broadcast the “Wake Up Notification” +message to the network, and wake-up 10 seconds for receive the +setting commands. +The wake-up interval minimum setting is 30 minutes, and maximum +setting is 120 hours. And the interval step is 30 minutes. +If the user want to wake-up the device immediately, please remove the +front cover,and press the tamper key once. The device will wake-up 10 +seconds. + Датчик движения (Motion Sensor) + The slim multisensorPST02-5B has PIR, temperature and illumination, 3 sensors function in one,based on Z-Wave technology +It is the Z-WaveTM plus product, it support the security, OTA... Those +newest features of the Z-WaveTM technology. Z-WaveTM is a wireless +communication protocol designed for home automation, specifically to +remotely control applications in residential and light commercial +environments. The technology uses a low-power RF radio embedded or +retrofitted into home electronics devices and systems, such as lighting, +home access control, entertainment systems and household appliances. + There are two tamper keys in the device, one is in the back side, +another is in the front side. Both of them can add, remove or reset from Z-WaveTM network. +1. Have Z-WaveTM Controller entered exclusion mode. +2. Pressing tamper key three times within 1.5 seconds +to enter the exclusion mode. Node ID has been excluded. - CEPT (Europe) - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1090/PST02_Manual-2014-08-15B.pdf + CEPT (Europe) / Russia / Russia + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2860/PST02_UserManual.pdf Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1090/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2833/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2860/xml diff --git a/config/philio/pst02.xml b/config/philio/pst02.xml index 90a5d1c863..a365976150 100644 --- a/config/philio/pst02.xml +++ b/config/philio/pst02.xml @@ -1,8 +1,8 @@ - + http://www.openzwave.com/device-database/013C:000C:0002 images/philio/pst02.png - https://products.z-wavealliance.org/products/1449/ + https://products.z-wavealliance.org/products/2568/ There are two tamper keys in the device, one is in the back side, another is in the front side. Both of them can add, remove, reset or association from Z-Wave network. To remove the device from a Z-Wave network: 1. Have Z-Wave Controller entered exclusion mode. @@ -17,18 +17,22 @@ To add into a Z-Wave network: 1. Have Z-Wave Controller entered inclusion mode. 2. Pressing tamper key three times within 1.5 seconds to enter the inclusion mode. 3. After add successful, the device will wake to receive the setting command from Z-Wave Controller about 20 seconds. - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1449/PST02_Manual.pdf - CEPT (Europe) + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2568/PST02_Manual.pdf + CEPT (Europe) / Australia / New Zealand There are two tamper keys in the device, one is in the back side, another is in the front side. Both of them can add, remove, reset or association from Z-Wave network. To reset the device: Notice: Use this procedure only in the event that the primary controller is lost or otherwise inoperable. 1. Pressing tamper key four times within 1.5 seconds and do not release the tamper key in the 4th pressed, and the LED will light ON. 2. After 3 seconds the LED will turn OFF, after that within 2 seconds, release the tamper key. If successful, the LED will light ON one second. Otherwise, the LED will flash once. 3. IDs are excluded and all settings will reset to factory default. - PST02-1A + PST02-A Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1087/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1449/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2433/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2434/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2568/xml + Fix Philio door sensors #1898 @@ -158,9 +162,6 @@ Notice: Use this procedure only in the event that the primary controller is lost - - false - diff --git a/config/polycontrol/doorlock.xml b/config/polycontrol/doorlock.xml index 90dcacf543..092f69739e 100644 --- a/config/polycontrol/doorlock.xml +++ b/config/polycontrol/doorlock.xml @@ -1,9 +1,9 @@ - + http://www.openzwave.com/device-database/010E:0002:0008 images/polycontrol/doorlock.png - https://products.z-wavealliance.org/products/1251/ - DanalockBTZE100Circle + https://products.z-wavealliance.org/products/1855/ + Danalock V2 BTZJ To remove or exclude the danalock into a Z-Wave network Set the controller in exclusion mode Touch the User Button until you hear two beeps. @@ -12,9 +12,9 @@ Set the controller in inclusion mode Touch the User Button until you hear two beeps. The danalock can be set to factory settings by holding the User Button for ten beeps. Please use this procedure only when the primary controller is missing or otherwise inoperable. - Danalock - U.S. / Canada / Mexico / CEPT (Europe) - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1251/Danalock Product manual.pdf + Danalock V2 BTZJ + U.S. / Canada / Mexico / CEPT (Europe) / U.S. / Canada / Mexico / U.S. / Canada / Mexico / U.S. / Canada / Mexico / Japan + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1855/Danalock_V2_Product_manual_Z_Wave_V_1.0.4.pdf Z-Wave Controlled door lock with keypad, and Bluetooth Smart. Operated by Z-Wave. Connect Danalock to your Z-Wave gateway - Danalock interfaces with your existing Z-Wave network through the Danalock smartphone app. @@ -24,6 +24,10 @@ Operate Danalock remotely by accessing your Z-Wave network from anywhere in the Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1238/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1251/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1532/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1764/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1769/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1855/xml diff --git a/config/polycontrol/doorlockv3.xml b/config/polycontrol/doorlockv3.xml index b4def3c82a..e07794d0a1 100644 --- a/config/polycontrol/doorlockv3.xml +++ b/config/polycontrol/doorlockv3.xml @@ -1,4 +1,42 @@ - + + + http://www.openzwave.com/device-database/010E:0001:0009 + images/polycontrol/doorlockv3.png + https://products.z-wavealliance.org/products/3340/ + Danalock V3-BTZU-IL + 1. Set the controller in inclusion mode +2. Push the switch once. +3. Wait 5 seconds. + 1. Set the controller in exclusion mode +2. Push the switch once. +3. Wait 5 seconds. + Danalock V3-BTZU-IL + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3340/Danalock_V3_Product_manual_Z_Wave_V_0.9.4.pdf + The Danalock can be set to factory settings by pushing the switch ten times. Please use this procedure only when the primary controller is missing or otherwise inoperable. + CEPT (Europe) / U.S. / Canada / Mexico / Australia / New Zealand / Japan / Australia / New Zealand / CEPT (Europe) / U.S. / Canada / Mexico / Australia / New Zealand / Japan / Brazil / South Korea / Russia / Israel + Danalock supports: +- S0/S2 Z-Wave Security +- Bluetooth Smart +- Twist Assist +- Auto Lock +- Hold And Release +- Back To Back + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2556/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2601/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2629/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2630/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2644/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3217/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3295/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3311/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3312/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3337/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3338/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3339/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3340/xml + + - - - + + + Value of On-Command - - - + + + Value of Off-Command - - - - - - - - - + + + + + + + + + - diff --git a/config/popp/009303.xml b/config/popp/009303.xml index de5a0b0ce8..6f5043bb97 100644 --- a/config/popp/009303.xml +++ b/config/popp/009303.xml @@ -1,96 +1,112 @@ - - + + + http://www.openzwave.com/device-database/0154:0101:0100 + images/popp/009303.png + https://products.z-wavealliance.org/products/2110/ + Place your primary controller in inclusion mode by following the manufacturer's instructions, then activate inclusion on the wall controller by pressing any one of the four buttons for one second. Inclusion mode is indicated by the red/green blinking of the LEDs until the timeout occurs after 10 seconds. + The Wall Scene Controller is a Z-Wave device that can both control other Z-Wave devices and activate scenes. Although it is controlling other devices, the Wall Controller cannot act as Z-Wave network controller (primary or secondary) and will always need a Z-Wave network controller to be included into a Z-Wave network. The device can be used in different modes that are selected by configuration parameters: - +Control of groups of other Z-Wave devices using 'ON', 'OFF' and Dim commands. Activation of predefined scenes in Gateways or other Z-Wave devices. This device support secure communication when included by a controller that also supports secure communication. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2110/WallSceneControllerPopp.pdf + POPE009303 + (1) Turn the device into Management Mode by keeping all four buttons pushed for 5 seconds, (2) click on Button 2. + Re-Inclusion and Exclusion are performed by pushing button 1 in management mode. Pushing all four buttons for 5 sec. turns the device into management mode (indicated by blinking green LED). + CEPT (Europe) + Use this procedure only if the primary controller is missing or otherwise inoperable. +(1) Turn the device into Management Mode by keeping all four buttons pushed for 5 seconds, (2) click on Button 3, (3) keep button 4 pushed for 4 seconds. + Wall Scene Controller + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2110/xml + + + - - - In separate mode button 1 works with group A, button 3 with groups C. Click is On, Hold is dimming Up, Double click is Off, Click-Hold is dimming Down. In pair button 1/3 are Up/Down correspondingly. Click is On/Off, Hold is dimming Up/Down. Single clicks works with group A, double click with group C. - - - - - - In separate mode button 2 works with control group B, button 4 with control group D. Click is On, Hold is dimming Up, Double click is Off, Click-Hold is dimming Down. In pair button B/D are Up/Down correspondingly. Click is On/Off, Hold is dimming Up/Down. Single clicks works with group B, double click with group D. - - - - - - This parameter defines the command to be sent to devices of control group A when the related button is pressed - - - - - - - - - - - This parameter defines the command to be sent to devices of control group B when the related button is pressed - - - - - - - - - - - This parameter defines the command to be sent to devices of control group C when the related button is pressed - - - - - - - - - - - This parameter defines the command to be sent to devices of control group D when the related button is pressed - - - - - - - - - - - - - - - - - - - - If the KFOB wakes up and there is no controller nearby, several unsuccessful communication attempts will drain battery - - - - - - - - - - - - - - - - - - - - - + + + In separate mode button 1 works with group A, button 3 with groups C. Click is On, Hold is dimming Up, Double click is Off, Click-Hold is dimming Down. In pair button 1/3 are Up/Down correspondingly. Click is On/Off, Hold is dimming Up/Down. Single clicks works with group A, double click with group C. + + + + + + In separate mode button 2 works with control group B, button 4 with control group D. Click is On, Hold is dimming Up, Double click is Off, Click-Hold is dimming Down. In pair button B/D are Up/Down correspondingly. Click is On/Off, Hold is dimming Up/Down. Single clicks works with group B, double click with group D. + + + + + + This parameter defines the command to be sent to devices of control group A when the related button is pressed + + + + + + + + + + + This parameter defines the command to be sent to devices of control group B when the related button is pressed + + + + + + + + + + + This parameter defines the command to be sent to devices of control group C when the related button is pressed + + + + + + + + + + + This parameter defines the command to be sent to devices of control group D when the related button is pressed + + + + + + + + + + + + + + + + + + + + If the KFOB wakes up and there is no controller nearby, several unsuccessful communication attempts will drain battery + + + + + + + + + + + + + + + + + + + diff --git a/config/popp/009402.xml b/config/popp/009402.xml index 6d59e0da93..272588a71c 100644 --- a/config/popp/009402.xml +++ b/config/popp/009402.xml @@ -1,7 +1,28 @@ - - - - - - - The additional siren is creating a different acoustic signal differentiate from the smoke alarm. This sound is partly on and partly off. This parameter defines the total length of the interval in seconds. - - - The additional siren is creating a different acoustic signal differentiate from the smoke alarm. This sound is partly on and partly off. This parameter defines the total length of the sound versus silence within this interval. Please make sure this value is always smaller (shorter time) than parameter 1 that defines the whole sequence. - - - This value is sent as BASIC Set to Association Group 3 when an Smoke Alarm occurs. - - - This value is sent as BASIC Set to Association Group 3 when an Smoke Alarm is cleared. - - - - - - - - - - - + + + The additional siren is creating a different acoustic signal differentiate from the smoke alarm. This sound is partly on and partly off. This parameter defines the total length of the interval in seconds. + + + The additional siren is creating a different acoustic signal differentiate from the smoke alarm. This sound is partly on and partly off. This parameter defines the total length of the sound versus silence within this interval. Please make sure this value is always smaller (shorter time) than parameter 1 that defines the whole sequence. + + + This value is sent as BASIC Set to Association Group 3 when an Smoke Alarm occurs. + + + This value is sent as BASIC Set to Association Group 3 when an Smoke Alarm is cleared. + + + + + + + + + + - diff --git a/config/popp/012501.xml b/config/popp/012501.xml index 70df1afb33..1adab6edaf 100644 --- a/config/popp/012501.xml +++ b/config/popp/012501.xml @@ -1,31 +1,44 @@ - - - - - - + + + 0: No automated close after command open. 1 - 127: Close again after x seconds (Default 3) - - - 0 - 99 (Default 0) - - - 0 - 99 (Default 99) - - - - - - - - - - + + + 0 - 99 (Default 0) + + + 0 - 99 (Default 99) + + + + + + + + + - diff --git a/config/popp/700045.xml b/config/popp/700045.xml index 7b7c9354a5..8330880384 100644 --- a/config/popp/700045.xml +++ b/config/popp/700045.xml @@ -1,54 +1,75 @@ - - - - - - + + + After this time a CLOSE command is sent to the controlled door lock. On default no CLOSE command is sent assuming that the strike lock has its own timeout set. Default Value: 0 - - - + + + After this time the Door Bell will receive an OF command regardless of the actual button is pressed or not. Default Value: 3 - - - + + + This value is sent into Association Group 3 when the door bell button is pressed. Default Value: 255 - - - + + + This value is sent into Association Group 3 when the door bell button is released or the timeout has reached. Default Value: 0 - - - This parameter defines if different user codes shall cause individual or similar scene ID sent to the main controller. - - - - - Buzzer Confirmation - - - - - - - - - - - - + + + This parameter defines if different user codes shall cause individual or similar scene ID sent to the main controller. + + + + + Buzzer Confirmation + + + + + + + + + + + + - diff --git a/config/popp/700168.xml b/config/popp/700168.xml index aed4172e20..4ba38e29f0 100644 --- a/config/popp/700168.xml +++ b/config/popp/700168.xml @@ -1,63 +1,79 @@ - - - + + + http://www.openzwave.com/device-database/0154:0011:0004 + images/popp/700168.png + https://products.z-wavealliance.org/products/2418/ + Push the button inside the device for at least 10 seconds. +Use this procedure only in the event that the network primary controller is missing or otherwise inoperable. + Push the Z-Wave button one time. You find the Z-Wave button by removing the electronics module from the base. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2418/POPE700168_Manual.pdf + This device measures the rain level on a certain position. The device is IP55 rated and can be used outside the home in the garden or on any other place exposed to rain. The device has a funnel on the top-side that will collect the rain on a certain diameter. The internal mechanics and electronics counts the rain level and will report it every about 4 minutes if and only if there is rain. The device also monitors a heavy rain condition (10 l/sqm within 5 minutes) and will send out alarm messages when detected. + CEPT (Europe) + Z-Wave Rain Sensor + Push the Z-Wave button one time. You find the Z-Wave button by removing the electronics module from the base. + 700168 + Push the Z-Wave button one time. You find the Z-Wave button by removing the electronics module from the base. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2418/xml + + + - - - + + + Ths values shows the total count of rain from the moment of inclusion in mm water level. By writing this value this counter can be reset. Default Value: 0 - - - + + + This BASIC Set Command value is sent out into Association Group 2 when the device detects start of rain. Default Value: 99 - - - + + + This BASIC Set Command value is sent out into Association Group 2 when the device detects stop of rain. Default Value: 0 - - - + + + This multiplier allows to adapt the display to certain controllers not being able to handle very low numbers. Default Value: 1 - - - - - - - - + + + + + + + This threshold defines when a heavy rain condition is hit. In most countries this is defined as > 15 mm rain per hour. The default value however is to turn this function off. Default Value: 255 - - - + + + This BASIC Set Command value is sent out into Association Group 3 when the device detects start of heavy rain. Default Value: 99 - - - + + + This BASIC Set Command value is sent out into Association Group 3 when the device detects stop of heavy rain. Default Value: 0 - - - - - - - - - - + + + + + + + + + + diff --git a/config/popp/700397.xml b/config/popp/700397.xml index d8ab8b358f..34c42e8b95 100644 --- a/config/popp/700397.xml +++ b/config/popp/700397.xml @@ -1,129 +1,133 @@ - - - - - - Defines when the LED shall shine and how - - - - - - + + + Defines when the LED shall shine and how + + + + + If not zero, automatically switch device off after an user defined time. 0 -> Disabled (default) 1-65535 -> Enabled time in seconds. - - - - + + + Defines how to interpret RF Off-Command. Ignore - to switch on the light by motion detectors and switch it off after some amount of time; in case of multiple motion detectors each would try to switch the light off that would break logic; Switch on - to switch on the light on both On and Off paddle press on the remote and switch it off after some amount of time. Button off click will still work (if button operations are not disabled). - - - - - - - - This parameter defines if the local button shall control (switch) the load or it is only used to send out scene control commands to the central controller. - - - - - - Defines if the switch should restore switch state to the last prior to device power off (power cycle). - - - - - - Defines the behavior of the LED when the load is switched off - - - - - - - Defines the behavior of the LED when the load is switched on - - - - - - - + + + + + + + This parameter defines if the local button shall control (switch) the load or it is only used to send out scene control commands to the central controller. + + + + + Defines if the switch should restore switch state to the last prior to device power off (power cycle). + + + + + Defines the behavior of the LED when the load is switched off + + + + + + Defines the behavior of the LED when the load is switched on + + + + + + Report the voltage when the voltage has changed by more then X * 1 V. When disabled the device will report every 10 minutes regardless of current voltage. 0 -> Disabled 100 -> Default 0 - 250 -> Volt - - - - + + + Report the current when the current has changed by more then X *0,01 A. When disabled the device will report every 10 minutes regardless of current change. 0 -> Disabled 10 -> default 0 - 255 -> * 0,01 A - - - - + + + Report the power when the power has changed by more then X Watt. When disabled the device will report every 10 minutes regardless of power consumption change. 0 -> Disabled 50 -> Default 1 - 255 -> Watts - - - - + + + When the power draw exceeds the value set in this parameter for a time set in parameter 28 the soft circuit breaker will disconnect the load. 0 -> Disabled 3600 -> Default 1 - 3600 -> Watts - - - - Once the soft circuit breaker tipps and the load is disconnected the load will be automatically reconnected after X seconds. + + + Once the soft circuit breaker tipps and the load is disconnected the load will be automatically reconnected after X seconds. When disabled the load must be repowered manually or with wireless command. 0 -> Disabled (default) 1 - 255 -> Seconds - - - - This delay time defines how fast the soft circuit breaker wil react when the threshold power is exceeded. + + + This delay time defines how fast the soft circuit breaker wil react when the threshold power is exceeded. The power is cut off only if the power draw remains over the threshold level for the defines time. 0 -> Disabled 10 -> Default 1 - 255 -> * 0,1 sec - - - - - - - - - - - + + + + + + + + + diff --git a/config/popp/dwt.xml b/config/popp/dwt.xml new file mode 100644 index 0000000000..79f41a5d92 --- /dev/null +++ b/config/popp/dwt.xml @@ -0,0 +1,140 @@ + + + http://www.openzwave.com/device-database/0154:0007:0004 + images/popp/dwt.png + https://products.z-wavealliance.org/products/3345/ + CEPT (Europe) + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=MarketCertificationFiles/3345/DoorWindowSensor_POPE700892_UserManual.pdf + POPP Door/Window Sensor is a small window position sensor for your smart home, it monitors window and their exact opening position and lets your know when a window is tilted or completely opened. It also supports connecting external binary sensors through the dry binary contact of the Door/ Window sensor. + Tripple click the tamper switch + Window/Door Sensor with Tilt Detection + Tripple click the tamper switch + Once Cover is removed and tamper switch is tripped, push the tamper for 5 seconds until red LED blinks. Then release tamper and push it again for 5 seconds until LED blinks + POPE700892 + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3345/xml + + + + + + + + Defines if the internal magnet sensor or the external terminal input is detected and used to issue alarm notification. There is always one input active only. The other sensor input the deactivated. + Default Value: Internal Magnet Sensor Used + + + + + + + Defines the polarity of the magnet sensor. + Default Value: Closed when Magnet in proximity + + + + + + + Defines when the red LED will indicate events. Disabling all indications may extend battery life. + Default Value: 7 (Bit 0, 1 and 2) + + Bit 0: No Indications + Bit 1: Open/Close Status Change + Bit 2: Wake Up + Bit 4: Device Tampering + + + + + Allows to enable the activation of a Z-Wave range test with double clicking the tamper switch. + Default Value: Disabled + + + + + + + Defines the status of the magnet switch that causes sending a BASIC command to all devices of Association Group 2. + Default Value: Switch after Open and Close + + + + + + + + Defines which commands is sent to 2nd Association Group. + Default Value: On and Off + + + + + + + + This is the BASIC command value sent in case of an On event. + Default Value: 255 + Value Range: 0 - 99 and 255 + + + + + This is the BASIC command value sent in case of an Off event. + Default Value: 0 + Value Range: 0 - 99 and 255 + + + + + Off command is sent after a delay in seconds + Default Value: 0 + + + + + Off command is sent after a delay in seconds + Default Value: 0 + + + + + Time a tamper alarm is delayed in seconds. + Default Value: 0 + + + + + Defines if the alarm cancellation event is reported. + Default Value: Send Report + + + + + + + Enables/disables the central scene function. + Default Value: Disabled + + + + + + + Enables/disables tilt function. + Default Value: Enabled + + + + + + + + + + + + + + + diff --git a/config/popp/smoke-detector.xml b/config/popp/smoke-detector.xml index 301bc813fd..6d7c9b4ad5 100644 --- a/config/popp/smoke-detector.xml +++ b/config/popp/smoke-detector.xml @@ -1,47 +1,63 @@ - - - - + + + http://www.openzwave.com/device-database/0154:0201:0100 + images/popp/smoke-detector.png + https://products.z-wavealliance.org/products/2111/ + CEPT (Europe) + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2111/POPE004001_en.pdf + This products consists of a standard photo electric Smoke detector with a pluggable Z-Wave wireless interface module. +The Smoke detector will also work as a stand alone product and is certified according to EN 14604. The +smoke chamber of the detector has a stainless steel reel with antistatic plastic chamber. +A button allows on-device test of smoke chamber, electronics and battery. The device also offers a built-in self test and +an electronic smoke chamber test to avoid the use of test aerosol. A low battery warning will last for 30 days but full +function of the detector is guaranteed during this time. +The Z-Wave module allows to report the smoke and low battery alarm wirelessly to a central controller. The detector can +also be used as a wireless siren for alarm system or other applications. The wireless module is operated by the 9V battery +of the smoke detector. An optional external power supply allows external powering the unit. +According to VdS 3515 (Smoke Detectors with Wireless Communication) this device will send alarm signals to all other +smoke detectors registered in association group 2 to turn on their siren. This function ensures that all smoke detectors +will issue noise if one of them detected a smoke. + To Exclude, hit the little button on the wireless module for 1 second + Smoke Detector and Siren + To Include, hit the little button on the wireless module for 1 second + To reset the device keep the button pushed for 10 seconds. After 5 seconds the led starts flashing and after another 5 +seconds there is a short beep signaling the successful reset back to factory defaults. Use this procedure only when the network primary controller is missing or otherwise inoperable. + POPE004001 + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2111/xml + + + - - - The additional siren is creating a different acoustic signal differentiate from the smoke alarm. This sound is partly on and partly off. This parameter defines the total length of the interval in seconds. - - - - The additional siren is creating a different acoustic signal differentiate from the smoke alarm. This sound is partly on and partly off. This parameter defines the total length of the sound versus silence within this interval. - - - - Value of On-Command - - - - Value of Off-Command - - - - This smoke detector can automatically inform other smoke detectors of same type about smoke alarms. They will then also turn on the siren. This function is a requirement of wireless networked smoke detectors. - - - - - - This smoke detector can automatically inform other smoke detectors of same type about battery alarms. They will then also turn on the siren. This function is a requirement of wireless networked smoke detectors. - - - - - - - - - - - - - - + + + The additional siren is creating a different acoustic signal differentiate from the smoke alarm. This sound is partly on and partly off. This parameter defines the total length of the interval in seconds. + + + The additional siren is creating a different acoustic signal differentiate from the smoke alarm. This sound is partly on and partly off. This parameter defines the total length of the sound versus silence within this interval. + + + Value of On-Command + + + Value of Off-Command + + + This smoke detector can automatically inform other smoke detectors of same type about smoke alarms. They will then also turn on the siren. This function is a requirement of wireless networked smoke detectors. + + + + + This smoke detector can automatically inform other smoke detectors of same type about battery alarms. They will then also turn on the siren. This function is a requirement of wireless networked smoke detectors. + + + + + + + + + + - diff --git a/config/popp/solar-siren.xml b/config/popp/solar-siren.xml index 3fa349730a..979952bcbb 100644 --- a/config/popp/solar-siren.xml +++ b/config/popp/solar-siren.xml @@ -1,51 +1,59 @@ - - + + + http://www.openzwave.com/device-database/0154:0002:0004 + images/popp/solar-siren.png + https://products.z-wavealliance.org/products/2085/ + POPE005107 + Outdoor Solar Siren + 1. Open the case and turn on the power switch 2. Remove the metal mounting plate from the device. 3. Turn your controller into inclusion mode with a short single click on the internal inclusion button. + + This device also allows to be reset without any involvement of a Z-Wave controller. This procedure should only be used when the primary controller is inoperable. - +To reset the device keep the inclusion button pushed for 10 seconds. After 5 seconds the LED starts flashing and after another 5 seconds there is a short beep signaling the successful reset back to factory defaults. Use this procedure only when the network primary controller is missing or otherwise inoperable. + This solar powered outdoor siren can be used without any additional power supply or batteries. It can be installed on any place on the outside of the house and can be controlled using Z-Wave. The device will issue a very loud sound (105 dBm) and in parallel some stroboscope light as well. The siren is self-protecting. Removing the main device from the mounting unit immediately starts the siren and also reports the tamper attempt to the Z-Wave central controller. All communication between the Z-Wave controller and the siren is encrypted and secured to protect against manipulation. Thanks to the large solar panel the siren can be mounted on nearly every place outside the house, with direct or indirect sun light. The siren is maintenance-free and water-proofed (IP56). The average solar energy of one day keeps the device alive for up to 50 days (without using the siren). Additionally an internal temperature sensor reports the temperature inside the siren’s enclosure. + CEPT (Europe) + 1. Open the case and turn on the power switch 2. Remove the metal mounting plate from the device. 3. Turn your controller into exclusion mode with a short single click on the internal inclusion button. + + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2085/005107_en.pdf + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2085/xml + + + - - - Sets the tamper triggering mode when removed from the holder - - - - - - - Temperature correction. For positive value 10 = 1 C, for negative value x = 256 - (TC * 10). Example, if need shift -2.6C, value calculate: 256 - (2.6 * 10) = 230 Default: 0 - - - - Threshold temperature to send unsolicited report. 10 = 1C - - - - If the value is set, after N wake up number (measurement is every 4 minutes) the temperature report will be sent. By default it's 15 = every 1 hour - - - - Siren only, flash only, flash + siren - - - - - - - If the value is set, the siren will be switched off automatically after a defined alarm time. + + + Sets the tamper triggering mode when removed from the holder + + + + + + Temperature correction. For positive value 10 = 1 C, for negative value x = 256 - (TC * 10). Example, if need shift -2.6C, value calculate: 256 - (2.6 * 10) = 230 Default: 0 + + + Threshold temperature to send unsolicited report. 10 = 1C + + + If the value is set, after N wake up number (measurement is every 4 minutes) the temperature report will be sent. By default it's 15 = every 1 hour + + + Siren only, flash only, flash + siren + + + + + + If the value is set, the siren will be switched off automatically after a defined alarm time. 0: No auto off - - - - - - - - - - - - + + + + + + + + - diff --git a/config/popp/zweather.xml b/config/popp/zweather.xml index da9de5b482..6366815b77 100644 --- a/config/popp/zweather.xml +++ b/config/popp/zweather.xml @@ -1,32 +1,54 @@ - - - + + + http://www.openzwave.com/device-database/0154:0400:0100 + images/popp/zweather.png + https://products.z-wavealliance.org/products/2102/ + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2102/POPE005206_en.pdf + Push the button 3 times within 1.5 seconds. + Hold the button longer than 1.5 seconds and then release. +The LED blinks longer than when pressing the button once. +Z-Weather performs a factory reset and all configuration parameters are reset to their default values. Use this procedure only when the network primary controller is missing or otherwise inoperable. + + Z-Weather + POPE005206 + CEPT (Europe) + Push the button 3 times within 1.5 seconds. The LED blinks once indicating that Z-Weather is. Z-Weather sends a Z-Wave Wakeup-Notification if has been added to the network. If Z-Weather has not yet been added to the network, no action is performed. + Z-Weather is a multisensor device monitoring outside weather and environmental conditions. It continually measures the wind speed and can, for example, trigger closing of the awning and blinds if it is too windy. It also measures the amount of rotation, enabling calculation of the wind yield per day or per year. In addition, Z-Weather includes sensors for humidity, temperature, pressure and dew point, essentially providing the core sensors of a weather station. +Z-Weather is powered by a solar cell and stores energy on an internal capacitor, enabling continuous operation, even with no wind for a couple of days. It does not use any batteries and is completely maintenance free. Using the built-in solar cell it also measures the ambient light and the solar yield. This information can be used to turn on the outdoor light at dusk time and turn the light off in the morning. +Z-Weather‘s wind yield and solar yield metering can be used as a calculation base for planning a wind generator or a solar panel on the roof of a house. + + Push the button 3 times within 1.5 seconds. If the LED is not blinking after releasing the button, Z-Weather has not enough energy and must be charged for several hours in bright sunlight. + + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2102/xml + + + - - - + + + Crossing this parameter on the rising edge, Z-Weather sends a basic set to the associated groups, serves the lifeline and sends a wake up notification. Valid values: 0-30 m/s, where 0 means no notification on too much wind. Default: 6 - - - + + + Crossing this parameter from night to day, association group 3 is informed. Crossing this parameter from day to night, association group 4 is informed. Valid values: 0-100 %, where 0 means off. Default: 37 (street lightning) - - - - - - - - - - - + + + + + + + + + + + - diff --git a/config/qubino/ZMNHADx.xml b/config/qubino/ZMNHADx.xml index 50bae1c47e..a05ca1142b 100644 --- a/config/qubino/ZMNHADx.xml +++ b/config/qubino/ZMNHADx.xml @@ -1,4 +1,60 @@ - + + + http://www.openzwave.com/device-database/0159:0052:0002 + images/qubino/ZMNHADx.png + https://products.z-wavealliance.org/products/2795/ + ZMNHAD1 + REMOVAL FROM A ZWAVE NETWORK (Z-WAVE EXCLUSION) + +1. Connect the device to the power supply +2. Make sure the device is within direct range of your Z-Wave gateway (hub) or use a hand-held Z-Wave remote to perform exclusion +3. Enable add/remove mode on your Z-Wave gateway (hub) +4. Toggle the switch connected to the I1 terminal 3 times within 5 seconds +OR +If the device is powered by 24 V SELV supply, press and hold the S (Service) button between 2 and 6 seconds +5. The device will be removed from your network but any custom configuration parameters will not be erased + + FACTORY RESET + +1. Connect the device to the power supply +2. Within the first minute (60 seconds) the device is connected to the power supply, toggle the switch connected to the I1 terminal 5 times within 5 seconds (5 times change switch state) +OR +If the device is powered by 24 V SELV supply, press and hold the S (Service) button for more than 6 seconds + +*By resetting the device, all custom parameters previously set on the device will return to their default values, and the owner ID will be deleted. Use this reset procedure only when the main gateway (hub) is missing or otherwise inoperable. + + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2795/Qubino_Flush 1 Relay PLUS extended manual_eng_2.2.pdf + Flush 1 Relay + CEPT (Europe) + AUTOMATICALLY ADDING THE DEVICE TO A Z-WAVE NETWORK (AUTO INCLUSION) + +1. Enable add/remove mode on your Z-Wave gateway (hub) +2. Connect the device to the power supply (with the temperature sensor already connected – sold separately*). +3. Auto-inclusion will be initiated within 5 seconds of connection to the power supply and the device will automatically enrol in your network + +MANUALLY ADDING THE DEVICE TO A Z-WAVE NETWORK (MANUAL INCLUSION) + +1. Enable add/remove mode on your Z-Wave gateway (hub) +2. Connect the device to the power supply (with the temperature sensor already connected*) +3. Toggle the switch connected to the I1 terminal 3 times within 5 seconds +OR +If the device is powered by 24 V SELV supply, press and hold the S (Service) button between 2 and 6 seconds +4. A new multi-channel device will appear on your dashboard +*If connecting the temperature sensor, switch off the power supply and make sure the device is excluded from your network BEFORE connecting the sensor. + + +*Make sure the device is excluded from your network before connecting the temperature sensor. Switch off the power supply, connect the temperature sensor, and re-include the device to your network. + + The Flush 1 Relay controls on/off function for one electrical device. It measures power consumption of the connected device, and can be paired with a digital temperature sensor (sold separately). It supports push-button/momentary switches and toggle switches (default). + +The connection of a digital temperature sensor means you can create complex scenes and control any device relative to a set temperature range. The Qubino Flush 1 Relay also acts as a Z-Wave repeater to improve the range and stability of the Z-Wave network. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2795/xml + Fix for 'module does not work on 1.6' - https://github.com/OpenZWave/open-zwave/issues/1820 + Add Instance Labels for i2, i3 and Temp Sensor Channels + Workaround for MCA assocation issue https://github.com/OpenZWave/open-zwave/issues/1895 + + - + + + + false + @@ -108,6 +167,10 @@ true + + + + @@ -115,20 +178,4 @@ false - - - - - - - false - - - - - - - false - - diff --git a/config/qubino/ZMNHBDx.xml b/config/qubino/ZMNHBDx.xml index 58381a9896..85c6d7c517 100644 --- a/config/qubino/ZMNHBDx.xml +++ b/config/qubino/ZMNHBDx.xml @@ -1,4 +1,42 @@ - + + + http://www.openzwave.com/device-database/0159:0051:0002 + images/qubino/ZMNHBDx.png + https://products.z-wavealliance.org/products/1528/ + ZMNHB + Please use this procedure only in the event that your network primary controller is missing or otherwise inoperable. + +If the service button S is pressed for mor ethan 6 seconds the module will be reset to the factory defoult state + Module Exclusion/Reset (Removing from Z-Wave network) +• Connect module to power supply +• bring module within maximum 1 meter (3feet) of the main controller, +• enable add/remove mode on main controller, +• press service button S for more than 6 second or +• press push button I1 five times within 3s ( 5 times change switch state within 3 seconds) in the first 60 seconds after the module is connected to the power supply. +By this function all parameters of the module are set to default values and own ID is deleted. +If service button S is pressed more than 2 and less than 6second module is excluded, but configuration parameters are not set to default values + + Flush 2 relays module is used for switching on or off two electrical devices (e.g. lights, fans, etc ...). The module can be controlled either through Z-Wave network or through the wall switches. +The module is designed to be mounted inside a “flush mounting box”, hidden behind a traditional wall switch. +Module measures power consumption of two electrical devices and supports connection of digital temperature sensor. It is designed to act as repeater in order to improve range and stability of Z-wave network. + + CEPT (Europe) + Module Inclusion (Adding to Z-Wave network) +• Connect module to power supply (with +temperature sensor connected - if purchased), +• enable add/remove mode on main controller +• auto-inclusion (works for about 5 seconds after connected to power supply) or +• press service button S for more than 2 second or +• press push button I1 three times within 3s (3 times change switch state within 3 seconds). +NOTE1: For auto-inclusion procedure, first set main controller into inclusion mode and then connect module to power supply. +NOTE2: When connecting temperature sensor to module that has already been included, you have to exclude module first. Switch off power supply , connect the sensor and re-include the module. + + Qubino Flush 2 relays + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1528/Qubino_Flush 2 Relay PLUS extended manual_eng_2.2.pdf + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1528/xml + + diff --git a/config/qubino/ZMNHCDx.xml b/config/qubino/ZMNHCDx.xml index eb4f9fe1e7..e3101023c4 100644 --- a/config/qubino/ZMNHCDx.xml +++ b/config/qubino/ZMNHCDx.xml @@ -1,4 +1,48 @@ - + + + http://www.openzwave.com/device-database/0159:0052:0003 + images/qubino/ZMNHCDx.png + https://products.z-wavealliance.org/products/2505/ + • Connect module to power supply (with +temperature sensor connected - if purchased), +• auto-inclusion (works for about 5 seconds after connected to power supply) or +• press push button I1 three times within 3s (3 times change switch state within 3 seconds) or +• press service button S (only applicable for 24 V SELV supply voltage) for more than 2 second. + +NOTE1: For auto-inclusion procedure, first set main controller into inclusion mode and then connect module to power supply. + +NOTE2: When connecting temperature sensor to module that has already been included, you have to exclude module first. Switch off power supply, connect the sensor and re-include the module. + + • Connect module to power supply +• bring module within maximum 1 meter (3 feet) of the main controller, +• enable add/remove mode on main controller, +• press push button I1 five times within 3s (5 times change switch state within 3 seconds) in the first 60 seconds after the module is connected to the power supply or +• press service button S (only applicable for 24 V SELV supply voltage) for more than 6 second. +By this function all parameters of the module are set to default values and own ID is deleted. + +If push button I1 is pressed three times within 3s (or service button S is pressed more than 2 and less than 6 seconds) module is excluded, but configuration parameters are not set to default values. + +NOTE: Please use this procedure only when the network primary controller is missing or otherwise inoperable. + +NOTE: If the module is included with parameters 71 with value different to default and module reset is done, wait at least 30s before next inclusion + + • press push button I1 five times within 3s (5 times change switch state within 3 seconds) in the first 60 seconds after the module is connected to the power supply or +• press service button S (only applicable for 24 V SELV supply voltage) for more than 6 second. + +NOTE: Please use this procedure only when the network primary controller is missing or otherwise inoperable. + + This Z-Wave module is used to control the motor of blinds, rollers, shades, venetian blinds, etc … The module can be controlled either through a Z-Wave network or through the wall switch. Precise positioning is supported for motors equipped with mechanical or electronic end switches. The module is designed to be mounted inside a “flush mounting box”, hidden behind a traditional wall switch. Module measures power consumption of motor and support connection of digital temperature sensor. It is designed to act as repeater in order to improve range and stability of Z-Wave network. + + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2505/Qubino_Flush Shutter PLUS extended manual_eng_2.2.pdf + ZMNHCD3 + Flush Shutter + CEPT (Europe) / Australia / New Zealand / U.S. / Canada / Mexico + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2376/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2504/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2505/xml + + + + + + With this parameter, you can select between push-button (momentary) and on/off toggle switch types. + + + + + With this parameter, you can change the device presentation on the user interface. + + + + + + 0 - Auto OFF Disabled. + 1 - 32536 = 1 - 32536 seconds - Auto OFF timer enabled for a given amount of seconds. + Default value 0. + + + + + 0 - Auto ON Disabled. + 1 - 32536 = 1 - 32536 seconds - Auto ON timer enabled for a given amount of seconds. + Default value 0. + + + + + If the Double click function is enabled, a fast double click on the push-button will set the dimming level to the maximum dimming value. + + + + + + Default value 0. + + + + + Set value from 0 - 100 (0% - 100%). + 0 - Reporting Disabled. + 1 - 100 = 1% - 100% Reporting enabled. + Power report is send (push) only when actual power in Watts in real time change for more than set percentage comparing to previous actual power in Watts, step is 1%. + Default value 5. + + + Set value means time interval (0 - 32767) in seconds, when power report is send. + 0 - Reporting Disabled. + 1 second to 32767 seconds reporting enabled. + Power report is send with time interval set by entered value. + Default value 300 (power report in Watts is send each 300s). + + + 1 - 98 = 1% - 98%, step is 1%. Minimum dimming values is set by entered value. + Default value 1 (Minimum dimming value is 1%). + + + 2 - 99 = 2% - 99%, step is 1%. Maximum dimming values is set by entered value. + Default value 99 (Maximum dimming value is 99%). + + + Set value means time of moving the Dimmer between min. and max. dimming values by short press of push button I1 or controlled through. + 1- 255 = 10mseconds - 2550mseconds (2,55s), step is 10mseconds. + Default value 100 (Dimming time between min. and max. dimming values is 1s). + + + + Choose the time during which the Dimmer will move between the min. and max. dimming values during a continuous press of the push-button I1, by an associated device or through the UI controls (BasicSet, SwitchMultilevelSet) + default value 3 = 3s. + 1-127 = 1 second – 127 seconds. + 128 – 253 = 1 minute – 126 minutes. + + + + + Choose whether the device should use (or disregard) the start dimming level value. + If the device is configured to use the start level, it should start the dimming process from the currently set dimming level. + This parameter is used with association group 3 + + + + + + + Choose the time during which the device will transition from the current value to the new target value. + This parameter applies to the association group 3. + default value 0 (dimming duration according to parameter 66). + 1 - 127 (from 1 to 127 seconds). + + + + + + The function allows for turning off the controlled device in case of exceeding the defined power for more than 5s. + Controlled device can be turned back on by input I1 or sending a control frame. + 0 = function not active + 1–200=1W–200W + + + + + Choose when will be the calibration procedure triggered. + + + + + + + + Whit this parameter you can check the calibration status. + + + + + + + This parameter defines the module behaviour in case it receives any Alarm/Notification events. + + + + + + + + + This parameter defines the time interval of the blinking state, once the module receives an alarm/notification event. + Minimum step increase is 1 minute. + 1 - 127 (from 1 to 125 minutes). + + + + + + + + + + + + + + + + + + true + + + diff --git a/config/qubino/ZMNHIDxS2.xml b/config/qubino/ZMNHIDxS2.xml index 6d5baa9c1e..68c6e1aecc 100644 --- a/config/qubino/ZMNHIDxS2.xml +++ b/config/qubino/ZMNHIDxS2.xml @@ -7,289 +7,425 @@ ZMNHID4 869,0 MHz ZMNHID5 916,0 MHz ref: http://qubino.com/download/1061/ ---> - - - - - - - - - - - - - - - 2 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Flush on off thermostat module responds to commands ALL ON / ALL OFF that may be sent by the main controller or by other controller belonging to the system. - - - - - - - +--> + + + http://www.openzwave.com/device-database/0159:0051:0005 + images/qubino/ZMNHIDx.png + + + 1. Connect the device to the power supply + 2. Make sure the device is within direct range of your Z-Wave gateway (hub) or use a hand-held Z-Wave remote to perform exclusion + 3. Enable add/remove mode on your Z-Wave gateway (hub) + 4. Toggle the switch connected to the I1 terminal 3 times within 3 seconds + OR + If the device is powered by 24 V SELV supply, press and hold the S (Service) button between 2 and 6 seconds + 5. The device will be removed from your network but any custom configuration parameters will not be erased + + The Qubino Flush On/Off Thermostat 2 is ideal for remotely controlling electric + or water-based underfloor heating systems, electric water heaters, hot water pumps, electric radiators, and + similar devices. + + + CEPT (Europe) + + 1. Enable add/remove mode on your Z-Wave gateway (hub) + 2. Connect the device to the power supply (with the temperature sensor already connected*) + 3. Toggle the switch connected to the I1 terminal 3 times within 3 seconds. The device has to get On/Off signal 3 times, meaning 3 times push on the push button or 6 times press of the switch. + OR + If the device is powered by 24 V SELV supply, press and hold the S (Service) button between 2 and 6 seconds + 4. A new multi-channel device will appear on your dashboard + *If connecting the temperature sensor, switch off the power supply and make sure the device is excluded from your network BEFORE connecting the sensor. + + ZMNHID1 + Qubino Flush On Off thermostat Z-Wave+ H1S2P1 + + 1. Connect the device to the power supply + 2. Within the first minute (60 seconds) the device is connected to the power supply, toggle the switch connected to the I1 terminal 5 times within 3 seconds (5 times change switch state) + OR + If the device is powered by 24 V SELV supply, press and hold the S (Service) button for more than 6 seconds + + + Add missing parameter 59 + + + + + + + + + + + + + + + + + + 2 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Flush on off thermostat module responds to commands ALL ON / ALL OFF that may be sent by the main + controller or by other controller belonging to the system. + + + + + + + + When I1 is pressed set point will be set according to the value of this parameter. Default value 1. 32767 - input I1 does not influence on the set point From 0 to 990 - set point from 0.0 C to 99.0 C From 1001 to 1150 - set point from -0.1 C to -15.0 C - - - + + + When I3 is pressed set point will be set according to the value of this parameter. Default value 32767. 32767 - input I2 does not influence on the set point From 0 to 990 - set point from 0.0 C to 99.0 C From 1001 to 1150 - set point from -0.1 C to -15.0 C - - - + + + When I3 is pressed set point will be set according to the value of this parameter. Default value 32767. 32767 - input I3 does not influence on the set point From 0 to 990 - set point from 0.0 C to 99.0 C From 1001 to 1150 - set point from -0.1 C to -15.0 C - - - Set value from 0 - 100 (0% - 100%). 0 - Reporting Disabled. 1 - 100 = 1% - 100% Reporting enabled. Power report is send (push) only when actual power in Watts in real time change for more than set percentage comparing to previous actual power in Watts, step is 1%. Default value 0 - - - Set value means time interval (0 - 65535) in seconds, when power report is send. 0 - Reporting Disabled. + + + Set value from 0 - 100 (0% - 100%). 0 - Reporting Disabled. 1 - 100 = 1% - 100% Reporting enabled. + Power report is send (push) only when actual power in Watts in real time change for more than set + percentage comparing to previous actual power in Watts, step is 1%. Default value 0 + + + + Set value means time interval (0 - 65535) in seconds, when power report is send. 0 - Reporting + Disabled. 1 - 65535 = 1 second - 65535 seconds. Reporting enabled. Power report is send with time interval set by entered value. - Default value 0 - - - This parameter defines temperature min difference between real measured temperature and set-point temperature to turn heating on. - The parameter can be set from 0 to 1127 where 0 to 127 means from 0.0 C to 12.7 C and from 1001 to 1127 means from - 0.1 C to -12.7 C. + Default value 0 + + + + This parameter defines temperature min difference between real measured temperature and set-point + temperature to turn heating on. + The parameter can be set from 0 to 1127 where 0 to 127 means from 0.0 C to 12.7 C and from 1001 to 1127 + means from - 0.1 C to -12.7 C. Default value 132 (-0.5 C) - - - This parameter defines temperature min difference between real measured temperature and set-point temperature to turn heating off. - The parameter can be set from 0 to 1127 where 0 to 127 means from 0.0 C to 12.7 C and from 1001 to 1127 means from - 0.1 C to -12.7 C. + + + This parameter defines temperature min difference between real measured temperature and set-point + temperature to turn heating off. + The parameter can be set from 0 to 1127 where 0 to 127 means from 0.0 C to 12.7 C and from 1001 to 1127 + means from - 0.1 C to -12.7 C. Default value 5 (+0.5 C) - - - Set value means at which temperature the device will be turned on even if the thermostat was manually set to off. + + + Set value means at which temperature the device will be turned on even if the thermostat was manually + set to off. 0 - 127 = 0.0C - 12.7 C. 1001 - 1127 = -0.1C - 12.6 C. 255 - Antifreeze functionality disabled. Default value 50 (5.0 C). - - - + + + + This parameter determines how the device will operate if it will operate in the heating mode or in the + cooling mode. + The range of the hysteresis will remain the same, only operation will change from heating to cooling and + vice versa + + + + + + Default value 50 (Minimum Temperature alarm is 5.0C) 1 - 1000 = 0.1C - 100.0C, step is 0.1C. 1001 - 1150 = -0.1 C - 15 C - Too low temperature limit is set by entered value. In case is set value out of this range, module is changing set value automatically to default value. + Too low temperature limit is set by entered value. In case is set value out of this range, module is + changing set value automatically to default value. - - - + + + Default value 700 (Minimum Temperature alarm is 70.0C) 1 - 1000 = 0.1C - 100.0C, step is 0.1C. - Too high temperature limit is set by entered value. In case is set value out of this range, module is changing automatically set value to default value. + Too high temperature limit is set by entered value. In case is set value out of this range, module is + changing automatically set value to default value. - - - Set value means the type of the device that is connected to the relay output. The device type can be normally open (NO) or normally close (NC). + + + Set value means the type of the device that is connected to the relay output. The device type can be + normally open (NO) or normally close (NC). Available config. parameters (data type is 1 Byte DEC): default value 0 0 - When system is turned off the output is 0 V. - 1 - When system is turned off the output is 230 V. - - - - - + 1 - When system is turned off the output is 230 V. + + + + + + Default value 0 1 - 32000 seconds - If the value of the parameter is different to 0, means that the influence of this input to heating or cooling will react after inserted time. - This parameter has influence only when the window sensor functionality is selected by the parameter no. 11. + If the value of the parameter is different to 0, means that the influence of this input to heating or + cooling will react after inserted time. + This parameter has influence only when the window sensor functionality is selected by the parameter no. + 11. - - - + + + Default value 0 1 - 32000 seconds - If the value of the parameter is different to 0, means that the influence of this input to heating or cooling will react after inserted time. - This parameter has influence only when the window sensor functionality is selected by the parameter no. 11. + If the value of the parameter is different to 0, means that the influence of this input to heating or + cooling will react after inserted time. + This parameter has influence only when the window sensor functionality is selected by the parameter no. + 11. - - - + + + Default value 0 1 - 32000 seconds - If the value of the parameter is different to 0, means that the influence of this input to heating or cooling will react after inserted time. - This parameter has influence only when the condense sensor functionality is selected by the parameter no. 12. + If the value of the parameter is different to 0, means that the influence of this input to heating or + cooling will react after inserted time. + This parameter has influence only when the condense sensor functionality is selected by the parameter + no. 12. - - - + + + Default value 0 1 - 32000 seconds - If the value of the parameter is different to 0, means that the influence of this input to heating or cooling will react after inserted time. - This parameter has influence only when the condense sensor functionality is selected by the parameter no. 12. + If the value of the parameter is different to 0, means that the influence of this input to heating or + cooling will react after inserted time. + This parameter has influence only when the condense sensor functionality is selected by the parameter + no. 12. - - - + + + Default value 0 1 - 32000 seconds - If the value of the parameter is different to 0, means that the influence of this input to heating or cooling will react after inserted time. - This parameter has influence only when the flood sensor functionality is selected by the parameter no. 13. + If the value of the parameter is different to 0, means that the influence of this input to heating or + cooling will react after inserted time. + This parameter has influence only when the flood sensor functionality is selected by the parameter no. + 13. - - - + + + Default value 0 1 - 32000 seconds - If the value of the parameter is different to 0, means that the influence of this input to heating or cooling will react after inserted time. - This parameter has influence only when the flood sensor functionality is selected by the parameter no. 13. + If the value of the parameter is different to 0, means that the influence of this input to heating or + cooling will react after inserted time. + This parameter has influence only when the flood sensor functionality is selected by the parameter no. + 13. - - - + + + Enabling I1 means that Endpoint (I1) will be present on UI. Disabling it will result in hiding the endpoint according to the parameter set value. Additionally, a Notification Type and Event can be selected for the endpoint. - NOTE 1: After parameter change, first exclude module (without setting parameters to default value) and then re include the module! + NOTE 1: After parameter change, first exclude module (without setting parameters to default value) and + then re include the module! NOTE 2: When the parameter is set to value 9 the notifications are send for Home Security. - - - - - - - - - - - + + + + + + + + + + + Enabling I2 means that Endpoint (I2) will be present on UI. Disabling it will result in hiding the endpoint according to the parameter set value. Additionally, a Notification Type and Event can be selected for the endpoint. - NOTE 1: After parameter change, first exclude module (without setting parameters to default value) and then re include the module! + NOTE 1: After parameter change, first exclude module (without setting parameters to default value) and + then re include the module! NOTE 2: When the parameter is set to value 9 the notifications are send for Home Security. - - - - - - - - - - - + + + + + + + + + + + Enabling I3 means that Endpoint (I3) will be present on UI. Disabling it will result in hiding the endpoint according to the parameter set value. Additionally, a Notification Type and Event can be selected for the endpoint. - NOTE 1: After parameter change, first exclude module (without setting parameters to default value) and then re include the module! + NOTE 1: After parameter change, first exclude module (without setting parameters to default value) and + then re include the module! NOTE 2: When the parameter is set to value 9 the notifications are send for Home Security. - - - - - - - - - - - + + + + + + + + + + + Set value is added or subtracted to actual measured value by sensor. From 1 to 100 = value from 0.1C to 10.0C is added to actual measured temperature. From 1001 to 1100 = value from -0.1 C to -10.0 C is subtracted to actual measured temperature. - Default value 32536. 32536 offset is 0.0C. + Default value 32536. 32536 offset is 0.0C. - - - If digital temperature sensor is connected, module reports measured temperature on temperature change defined by this parameter. + + + If digital temperature sensor is connected, module reports measured temperature on temperature change + defined by this parameter. 0 = reporting disabled. 1 to 127 = 0,1C to 12,7C, step is 0,1C. - Default value is 5 = 0,5C - - - - If digital temperature sensor is not connected, module can grab measured temperature from external secondary module. + Default value is 5 = 0,5C + + + + + If digital temperature sensor is not connected, module can grab measured temperature from external + secondary module. Default value is 0. - - - - - - - - - If digital temperature sensor is not connected, module can grab measured temperature from external battery powered room sensor defined by this paramater. + + + + + + + + + If digital temperature sensor is not connected, module can grab measured temperature from external + battery powered room sensor defined by this paramater. 0 = external battery powered room sensor not in function. 1 to 254 = Node ID of external battery powered room sensor. - Default value is 0 - - - - - - - - - - - - - - - - + Default value is 0 + + + + + + + + + + + + + + + + + diff --git a/config/qubino/ZMNHNDx.xml b/config/qubino/ZMNHNDx.xml index ffe3adce5c..1293321150 100644 --- a/config/qubino/ZMNHNDx.xml +++ b/config/qubino/ZMNHNDx.xml @@ -1,47 +1,47 @@ - + http://www.openzwave.com/device-database/0159:0053:0002 images/qubino/ZMNHNDx.png - https://products.z-wavealliance.org/products/1336/ - Module Exclusion/Reset (Removing from Z-Wave network) -• Connect module to power supply + https://products.z-wavealliance.org/products/2536/ + • Connect module to power supply • bring module within maximum 1 meter (3 feet) of the main controller, -• enable add/remove mode on main controller +• enable add/remove mode on main controller, • press service button S for more than 6 second or • press push button I1 five times within 3s (5 times change switch state within 3 seconds) in the first 60 seconds after the module is connected to the power supply. +By this function all parameters of the module are set to default values and own ID is deleted. +If service button S is pressed more than 2 and less than 6 seconds (or if push button I1 is pressed three times within 3s) module is excluded, but configuration parameters are not set to default values. -By this function all parameters of the module are set to default values and own ID is deleted -If service button S is pressed more than 2 and less than 6 second module is excluded, but configuration parameters are not set to default values. +NOTE: If the module is included with parameters 71 with value different to default and module reset is done, wait at least 30s before next inclusion. + +NOTE: Please use this procedure only when the network primary controller is missing or otherwise inoperable. CEPT (Europe) - Qubino Flush 1D relay with voltage free (dry contact) output contact. -This Z-Wave module is used for switching on or off the electrical device (e.g. light, fan, etc ...). The module can be controlled either through Z-wave network or through the wall switch. -The module is designed to be mounted inside a “flush mounting box”, hidden behind a traditional wall switch. -Module supports connection of digital temperature sensor. It is designed to act as repeater in order to improve range and stability of Z-wave network. - -Output contact is voltage free (dry contact), so also loads with different power supply can be connected to the module. - -FEATURES: -- The module has the option to connect a digital temperature sensor -- small dimensions (WxHxD) 41,8x36,8x15,4mm -- power supply is 110 - 230 VAC ±10% 50/60Hz, 24-30VDC -- Electrical consumption 0,4W - Module Inclusion (Adding to Z-wave network) -• Connect module to power supply (with + The Qubino Flush Shutter DC is ideal for controlling the 12–24V DC motors of blinds, rollers, shades, venetian blinds and similar sunscreens. You can control it either remotely through the Z-Wave network or through wall switches. It also measures power consumption and supports the connection of a digital temperature sensor. + • Connect module to power supply (with temperature sensor connected - if purchased), • auto-inclusion (works for about 5 seconds after connected to power supply) or • press service button S for more than 2 second or • press push button I1 three times within 3s (3 times change switch state within 3 seconds). -NOTE: When connecting temperature sensor to module that has already been included, you have to exclude module first. Connect the sensor and re-include the module. + +NOTE1: For auto-inclusion procedure, first set main controller into inclusion mode and then connect module to power supply. + +NOTE2: When connecting temperature sensor to module that has already been included, you have to exclude module first. Switch off power supply, connect the sensor and re-include the module. - Please use this procedure only in the event that your network primary controller is missing or otherwise inoperable. + press service button S for more than 6 second or +• press push button I1 five times within 3s (5 times change switch state within 3 seconds) in the first 60 seconds after the module is connected to the power supply. +By this function all parameters of the module are set to default values and own ID is deleted. +If service button S is pressed more than 2 and less than 6 seconds (or if push button I1 is pressed three times within 3s) module is excluded, but configuration parameters are not set to default values. + +NOTE: Please use this procedure only when the network primary controller is missing or otherwise inoperable. -If the service button S is pressed for more than 6 seconds the module will be reset to the factory defoult state. - Qubino Flush 1D relay - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1336/Qubino_Flush 1D Relay PLUS extended manual_eng_2.2.pdf - ZMNHN + + Flush Shutter DC + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2536/Qubino_Flush Shutter DC PLUS extended manual_eng_2.2.pdf + ZMNHOD1 Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1336/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2536/xml + Enable MapRootToEndPoint in MultiChannel Class + + + true + + diff --git a/config/qubino/ZMNHODx.xml b/config/qubino/ZMNHODx.xml index e16c46d3b7..233bbf5ab3 100644 --- a/config/qubino/ZMNHODx.xml +++ b/config/qubino/ZMNHODx.xml @@ -1,6 +1,42 @@ - - - - - - Responds to commands ALL ON / ALL OFF that may be sent by the main controller or by other controller belonging to the system. - - - - - - - Set value from 0 - 100 (0% - 100%). 0 - Reporting Disabled. 1 to 100 = 1% to 100% Reporting enabled. + + + Responds to commands ALL ON / ALL OFF that may be sent by the main controller or by other controller belonging to the system. + + + + + + + Set value from 0 - 100 (0% - 100%). 0 - Reporting Disabled. 1 to 100 = 1% to 100% Reporting enabled. Power report is send (push) only when actual power (in Watts) in real time changes for more than set percentage comparing to previous actual power in Watts, step is 1%. Default value 1 - - - - Set value means time interval (0 - 32767) in seconds, when power report is send. + + + Set value means time interval (0 - 32767) in seconds, when power report is send. 0 - Reporting Disabled. 1 - 32767) = 1second - 32767) seconds, Reporting enabled. Power report is send with time interval set by entered value. - - - - Module may include power and energy used by module itself in reports sent to the main controller - - - - - - Defines selection between two available operating modes. 0 Shutter mode + + + Module may include power and energy used by module itself in reports sent to the main controller + + + + + Defines selection between two available operating modes. 0 Shutter mode 1 Venetian mode (up/down and slate tilting) Note: When setting parameter, module needs to be reconfigured! Please check detailed description in this manual. - - - - - - + + + + + Defines the time necessary for slats to make full turn (180 degrees). 0 Tilting time disabled 1 to 32767 = 0,01seconds to 327,67 seconds Note: If time set is too high, this will result that after full turn, shutter will start move up or down, for time remaining. - - - - + + + This parameter defines slats position after up/down movement through UI or push buttons, return to previously set position only in case of 0 - UI control. 1 - UI control, momentary switch operation, or when the limit switch is reached. 2 - UI control, Push button, Limit switch is reached, after receiving a STOP control frame from UI. ( Default value 2 ) - - - - - - - + + + + + + Defines shutter motor moving time of complete opening or complete closing. 0 - moving time disabled (working with limit switches) 1 - 32767 = 0,1seconds - 3276,7seconds. After that time motor is stopped (relay goes to off state) See complete note in documentation. - - - - Power threshold to be interpreted when motor reach the limit switch. + + + Power threshold to be interpreted when motor reach the limit switch. Available settings: 5 to 100 (0,5 W to 10 W), step is 0,1W. - - - - By modifying the parameters setting, Shutter enters the calibration mode. + + + By modifying the parameters setting, Shutter enters the calibration mode. (after shutter performs the calibration process, completing full cycle - up, down and up, set the parameter value back to default. ) - - - - - - + + + + + Defines if reporting regarding power level, multilevel, etc.., are reported to controller or not. - - - - - - Defines the max time before motor power consumption is read after one of the relays is switched ON. + + + + + Defines the max time before motor power consumption is read after one of the relays is switched ON. If there is no power consumption during this max time (motor not connected, damaged or requires higher time to start, motor in end position,...) the relay will switch OFF. Available settings: 3 - 50 = 0,3 seconds - 5 seconds (100ms resolution). - - - - Defines the max time at limit switch, when power consumption is below power threshold. + + + Defines the max time at limit switch, when power consumption is below power threshold. If the power consumption during this time is below power threshold (par. 76), the active output will switch off, means that limit switch is reached. Available settings: 3 - 50 = 0,3 seconds - 5 seconds (100ms resolution). - - - - Defines the time delay between output relay switching (time between switching up/down and vice versa). + + + Defines the time delay between output relay switching (time between switching up/down and vice versa). Available settings: 1 - 30 = 0,1 seconds - 3 seconds (100ms resolution). - - - - + + + From 1 to 100 - value from 0.1 C to 10.0 C is added to actual measured temperature. From 1001 to 1100 - value from -0.1 C to -10.0 C is subtracted to actual measured temperature. - - - - If digital temperature sensor is connected, module reports measured temperature on temperature change defined by this parameter. + + + If digital temperature sensor is connected, module reports measured temperature on temperature change defined by this parameter. Available settings: 0 - Reporting disabled. 1 - 127 = 0,1C - 12,7C, step is 0,1C. - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/config/qubino/ZMNHQDx.xml b/config/qubino/ZMNHQDx.xml new file mode 100644 index 0000000000..c17c8d895b --- /dev/null +++ b/config/qubino/ZMNHQDx.xml @@ -0,0 +1,105 @@ + + + + LUXY Smart Light + The Qubino LUXY Smart Light is ideal for gentle illumination of any room and for visual and sound notifications. + http://www.openzwave.com/device-database/0159:0051:0008 + https://qubino.com + https://support.qubino.com/support/home + + + Manual inclusion is triggered by the following procedure: + Full white needs to be active (c-button 2). The user can select it by quickly pressing the c-button2 once. + When full white is enabled, press c-button3 and hold it for 5 seconds (while white is glowing, hold c-button3 for 5 seconds). + After 5 seconds, the device starts flashing, with the following pattern: green 1 second on, 0.5 second off. + Once the device receives a nodeId or after 10 seconds, it stops flashing and turns green. + + + + Exclusion is triggered by the following procedure: + Full white needs to be active (c-button 2). + When full white is enabled, press c-button3 and hold it for 5 seconds (while white is glowing hold c-button3 for 5 seconds). + After 5 seconds, the device starts flashing with the following pattern: red 1 second on, 0.5 second off. + Once the device loses its nodeId or after 10 seconds, it stops flashing and turns red. + + + + Reset is triggered after the following procedure: + Full white needs to be active (c-button 2). + When full white is enabled, press c-button5 and hold it for 10 seconds. + After 10 seconds, the device starts flashing with the following pattern: blue 1 second on, 0.5 second off. + After 10 seconds the device stops flashing and turns blue. + The procedure is available always. + + + + + + + + + + + + Defines the type of input device, connected to digital input. + + + + + + + + With this parameter, you can determine, how to turn off the alarm. + + + + + + + Default value = 10. + 0 – 32534 = 0-32534 seconds after which the LED will be turned off. + 32535 – never turns off. + + + + + + Default value = 0. + 0 – disabled. + 1 – 32535 = 1 – 32535 seconds after which the device turns on. + + + + + + Default value = 0 + 0 – disabled + 1 – 32535 = 1 – 32535 seconds after which the device turns off + + + + + With this parameter, the user can select if the state of the device should be restored, after a power failure. + + + + + + With this parameter, the user can select the operating mode of the beeper. + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/config/qubino/ZMNHSDx.xml b/config/qubino/ZMNHSDx.xml index fa0b88bdd4..066509c7d2 100644 --- a/config/qubino/ZMNHSDx.xml +++ b/config/qubino/ZMNHSDx.xml @@ -1,4 +1,44 @@ - + + + http://www.openzwave.com/device-database/0159:0052:0001 + images/qubino/ZMNHSDx.png + https://products.z-wavealliance.org/products/2252/ + CEPT (Europe) + • Press push button I1 five times within 3s (5 times change switch state within 3 seconds) in the first 60 seconds after the module is connected to the power supply or +• press service button S (only applicable for 24 V SELV supply voltage) for more than 6 second. + +Please use this procedure only when the network primary controller is missing or otherwise inoperable. + + • Connect module to power supply (with +temperature sensor connected - if purchased), +• enable add/remove mode on main controller +• auto-inclusion (works for about 5 seconds after connected to power supply) or +• press service button S for more than 2 second or +• press push button I1 three times within 3s (3 times change switch state within 3 seconds). + +NOTE1: For auto-inclusion procedure, first set main controller into inclusion mode and then connect module to power supply. +NOTE2: When connecting temperature sensor to module that has already been included, you have to exclude module first. Switch off power supply, connect the sensor and re-include the module. + + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2252/Qubino_DIN Dimmer PLUS extended manual_eng_2.3.pdf + DIN Dimmer + DIN Dimmer is a DIN rail mounted dimmer for light bulbs. You can control it either remotely through the Z-Wave network or through wall switches. It also measures power consumption and supports the connection of a digital temperature sensor. + ZMNHSD1 + • Connect module to power supply +• bring module within maximum 1 meter (3 feet) of the main controller, +• enable add/remove mode on main controller, +• press push button I1 five times within 3s (5 times change switch state within 3 seconds) in the first 60 seconds after the module is connected to the power supply or +• press service button S (only applicable for 24 V SELV supply voltage) for more than 6 second. +By this function all parameters of the module are set to default values and own ID is deleted. +If push button I1 is pressed three times within 3s (or service button S is pressed more than 2 and less than 6 seconds) module is excluded, but configuration parameters are not set to default values. + +NOTE 1: If the module is included with parameter 1 value 3, 4 or 5 and module reset is done, wait at least 30s before next inclusion. + +NOTE 2: Please use this procedure only when the network primary controller is missing or otherwise inoperable. + + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2252/xml + + + + + true + + + + + diff --git a/config/qubino/ZMNHUD1.xml b/config/qubino/ZMNHUD1.xml index dd0fd6dca6..698bcf69d8 100644 --- a/config/qubino/ZMNHUD1.xml +++ b/config/qubino/ZMNHUD1.xml @@ -1,4 +1,4 @@ - + @@ -12,7 +12,7 @@ - + @@ -22,7 +22,7 @@ - + diff --git a/config/qubino/ZMNHVDx.xml b/config/qubino/ZMNHVDx.xml index a1888dff08..faf3e6b85d 100644 --- a/config/qubino/ZMNHVDx.xml +++ b/config/qubino/ZMNHVDx.xml @@ -1,6 +1,49 @@ - - - - - - NOTE: After parameter change to value 3, 4 or 5 first exclude module (without setting parameters to default value) then wait at least 30s and then re include the module! - - - - - - - - - Responds to commands ALL ON / ALL OFF that may be sent by the main controller or by other controller belonging to the system. - - - - - - - 0 => Auto OFF disabled. 1 - 32535 => 1 second (0,01s) - 32535 seconds (325,35s). Auto OFF enabled with define time, step is 1s or 10ms according to parameter 15. Default value 0 - - - 0 - Auto OFF disabled. 1 - 32535 => 1 second (0,01s) - 32535 seconds (325,35s). Auto ON enabled with define time, step is 1s or 10ms according to parameter 15. Default value 0 - - - - - - - - - - - - - + + + NOTE: After parameter change to value 3, 4 or 5 first exclude module (without setting parameters to default value) then wait at least 30s and then re include the module! + + + + + + + + + Responds to commands ALL ON / ALL OFF that may be sent by the main controller or by other controller belonging to the system. + + + + + + + 0 => Auto OFF disabled. 1 - 32535 => 1 second (0,01s) - 32535 seconds (325,35s). Auto OFF enabled with define time, step is 1s or 10ms according to parameter 15. Default value 0 + + + 0 - Auto OFF disabled. 1 - 32535 => 1 second (0,01s) - 32535 seconds (325,35s). Auto ON enabled with define time, step is 1s or 10ms according to parameter 15. Default value 0 + + + + + + + + + + + + + This parameter is influencing on the software only when the value of parameter number 1 is set to value 3, 4 or 5. In manual mode regulation (how the input influence on output) is disabled. - - - - - + + + + + NOTE: When ZERO PID inside deadband is forced to zero. Last value means that PID remains on same level as was before entering into deadband. - - - - - + + + + + 0 to 100 => 0 to 100%, step is 1%. Default value 1. NOTE: This parameter defines the zone where PID is not active. If the temperature difference between actual and setpoint is bigger than PID deadband, then the PID will start to regulate the system, otherwise the PID is zero or fixed. - - - + + + 0 to 127 => 0 to 127s, step is 1s. Default value 1. Parameter defines the time between samples. On each sample the controller capture difference between SP-act. - - - + + + 0 to 1000, step is 1. Default value 100. - - - + + + 0 to 1000, step is 1. Default value 1. - - - + + + 0 to 1000, step is 1. Default value 1. - - - 1 - 98 = 1% - 98%, step is 1%. Minimum dimming values is set by entered value. + + + 1 - 98 = 1% - 98%, step is 1%. Minimum dimming values is set by entered value. Default value 1 (Minimum dimming value is 1%). - - - 2 - 99 = 2% - 99%, step is 1%. Maximum dimming values is set by entered value. + + + 2 - 99 = 2% - 99%, step is 1%. Maximum dimming values is set by entered value. Default value 99 (Maximum dimming value is 99%). - - - Set value means time of moving the Dimmer between min. and max. dimming values by short press of push button I1 or controlled through. + + + Set value means time of moving the Dimmer between min. and max. dimming values by short press of push button I1 or controlled through. 1- 255 = 10mseconds - 2550mseconds (2,55s), step is 10mseconds. Default value 100 (Dimming time between min. and max. dimming values is 1s). - - - Time of moving the Dimmer between min. and max dimming values by continues hold of push button I1. + + + Time of moving the Dimmer between min. and max dimming values by continues hold of push button I1. 1- 255 = 1 second - 255 seconds. Default value 3 (Dimming time between min. and max. dimming values is 3s). - - - This parameter is used with association group 4. + + + This parameter is used with association group 4. A receiving device SHOULD respect the start level if the Ignore Start Level bit is 0. A receiving device MUST ignore the start level if the Ignore Start Level bit is 1. Default value 0. - - - - - This parameter is used with association group 3. + + + + + This parameter is used with association group 3. The Duration field MUST specify the time that the transition should take from the current value to the new target value. A supporting device SHOULD respect the specified Duration value. Default value 0. - - - - - + + + + + From 1 to 100 - value from 0.1 C to 10.0 C is added to actual measured temperature. From 1001 to 1100 - value from -0.1 C to -10.0 C is subtracted to actual measured temperature. - - - If digital temperature sensor is connected, module reports measured temperature on temperature change defined by this parameter. + + + If digital temperature sensor is connected, module reports measured temperature on temperature change defined by this parameter. Available settings: 0 - Reporting disabled. 1 - 127 = 0,1C - 12,7C, step is 0,1C. - - - + + + If analogue sensor is connected, module reports measured value on change defined by this parameter. 0 - Reporting disabled. 1 to 10000, step is 0.1. Default value 5 => 0.5C. - - - Parameter is associated with Association group No. 2. + + + Parameter is associated with Association group No. 2. Below this value, the Association No. 2 will report Basic Set 0xFF and above this value will report Basic Set 0xFF. Basic Set is reported only, when the input value changes for more than 10% (1V). Default setting: 5 (0.5V) 1 to 100 => (0,1 to 10V) - - - + + + Value that must correspond to minimum sensor range value. Valid only if parameter 1 is set to values 3, 4 or 5). default value 0 = 0.0C / 0Lux / 0.0%rh @@ -161,9 +204,9 @@ 10001 to 20000 => value from -0,1 to -1000 (resolution 0,1) NOTE: Minimum value must not be higher than maximum value! - - - + + + Value that must correspond to maximum sensor range value. Valid only if parameter 1 is set to values 3, 4 or 5). default value 1000 = 100.0C / 100Lux / 100.0%rh @@ -171,19 +214,19 @@ 10001 to 20000 => value from -0,1 to -1000 (resolution 0,1) NOTE: Maximum value must not be lower than minimum value! - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/config/qubino/ZMNHWD1.xml b/config/qubino/ZMNHWD1.xml index 98c953ad1f..24b85c419d 100644 --- a/config/qubino/ZMNHWD1.xml +++ b/config/qubino/ZMNHWD1.xml @@ -1,30 +1,145 @@ - + + + http://www.openzwave.com/device-database/0159:0054:0001 + images/qubino/ZMNHWD1.png + https://products.z-wavealliance.org/products/2552/ + FACTORY RESET +1. Connect the module to the power supply +2. Press and hold the S (Service) button for at least 10 seconds +NOTE: By resetting the module, all custom parameters previously set on the module will return to their default values, and owner ID will be deleted. Use this reset procedure only when the main controller is missing or otherwise inoperable. + 1. Connect the module to the power supply +2. Make sure the module is within direct range of your Z-Wave controller or use a hand-held Z-Wave remote to perform exclusion +3. Press and release the S (Service) button 3 times within 2 seconds +NOTE: The module will be excluded from your network, but any custom configuration parameters will not be erased. + Flush RGBW Dimmer Switch Color R.G.B.W + Flush RGBW Dimmer / ZMNHWD3 + 1. Connect the module to the power supply +2. Enable inclusion mode on your Z-Wave controller +3. Press and release the S (Service) button 3 times within 2 seconds + Qubino Flush RGBW module is used to control RGB/RGBW strips and LED strips or bulbs to create countless colour options and has 5 special scene effects. It can also control halogen lights and fans. Its extremely small size allows for easy installation behind wall sockets and switches. Controlled devices may be powered by 12 or 24 VDC. All IN and OUT terminals may be user configured for LED control or 100 kΩ signal readouts. + CEPT (Europe) / U.S. / Canada / Mexico + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2552/Qubino_Flush RGBW Dimmer PLUS extended manual_eng_2.2.pdf + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2174/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2552/xml + Add missing parameters and fix exiting + + - - Please power cycle the device when parameter is changed - - - - - Using this parameter, it is possible to select various modes of RGBW Dimmer operation - - - - - - Activation of the programmed scene changing color shades - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + This parameter is used to adjust time between 2 Colours in the Scene. + 1-127 – delay duration is 1 sec to 127 sec. + 1001-1127 – delay duration is from 1 min to 127 min. This parameter has no effect on lighting and Party Scene. + + + Device will be set to status memorized before power cut. + + + + + + Output is turned automatically off after the time, set in this parameter. + 0 – Auto OFF disabled. + 1 – 32536 = 1 second – 32536 seconds Auto OFF. + + + + + Output is turned automatically on after the time, set in this parameter. + 0 – Auto ON disabled. + 1 – 32536 = 1 second – 32536 seconds Auto ON. + + + + + + + NOTE: The minimum level may not be higher than the MAX dimming value. + + + + Default value 10 = 1 s. + 5–25 = from 0.5 to 2.5 seconds + + + + 1–127 = from 1 to 127 seconds. + NOTE: Dimming time depends also on Min and Max dimming value. + - - Using this parameter, it is possible to change Auto scene mode duration. 1 - 127 delay duration is from 1s to 127s, -128 ~ -1 delay duration is from 1min. to -127min + + + NOTE: If the parameter no. 14 is enabled, parameter no. 1,2,3,4 has no effect. + NOTE: After parameter change, first exclude device (without setting parameters to default value) and then re include the device. + + + + + diff --git a/config/qubino/ZMNHXDx.xml b/config/qubino/ZMNHXDx.xml index ff1ce6d6a5..609e8f5dd0 100644 --- a/config/qubino/ZMNHXDx.xml +++ b/config/qubino/ZMNHXDx.xml @@ -1,9 +1,22 @@ - - + + + 3-PHASE SMART METER + USER MANUAL EN.QUBINO 3-PHASE SMART METERThe Qubino 3-Phase Smart Meter is an extremely versatile and powerful Z-Wave devicefor measuring energy in a three-phase electrical power network of up to 3 x 65A. + http://www.openzwave.com/device-database/0159:0007:0054 + https://qubino.com/products/3-phase-smart-meter/ + https://qubino.com/support/ + images/qubino/zmnhxdx.png + https://qubino.com/wp-content/uploads/2019/06/Qubino_3-Phase-Smart-Meter-PLUS-extended-manual_eng_3.4.pdf?cf_id=2255 + Toggle the Service button S between 0.2 and 3seconds + Press and hold the S service button between 0.2 and 3seconds + Press and hold the S service button between 6 seconds and 20 seconds + CEPT (Europe) + ZMNHXDx + + Update to Support OZW 1.6 with Instance Label Names + + - @@ -49,11 +62,6 @@ Qubino: ZMNHXDx 3-phase Smart Meter - - - true - - @@ -61,5 +69,11 @@ Qubino: ZMNHXDx 3-phase Smart Meter true + + + + + + diff --git a/config/qubino/ZMNHYDx.xml b/config/qubino/ZMNHYDx.xml index e0d7ac0773..c19ced0070 100644 --- a/config/qubino/ZMNHYDx.xml +++ b/config/qubino/ZMNHYDx.xml @@ -1,6 +1,37 @@ - - - - - - Smart Meter module responds to commands ALL ON / ALL OFF that may be sent by the main controller or by other controller belonging to the system - - - - - - - + + + Smart Meter module responds to commands ALL ON / ALL OFF that may be sent by the main controller or by other controller belonging to the system + + + + + + + If Smart plug 16A is ON, you can schedule it to turn OFF automatically after a period of time defined in this parameter. The timer is reset to zero each time the device receives an ON command, either remotely (from the gateway (hub) or associated device) or locally from the switch. 0 => Auto OFF disabled. 1 - 32535 => 1 second (0,01s) - 32535 seconds (325,35s). Auto OFF enabled with define time, step is 1s or 10ms according to parameter 15. Default value 0 - - - + + + If Smart plug 16A is OFF, you can schedule it to turn ON automatically after a period of time defined in this parameter. The timer is reset to zero each time the device receives an OFF command, either remotely (from the gateway (hub) or associated device) or locally from the switch. 0 - Auto OFF disabled. 1 - 32535 => 1 second (0,01s) - 32535 seconds (325,35s). Auto ON enabled with define time, step is 1s or 10ms according to parameter 15. Default value 0 - - - + + + Choose if you want to set the timer in seconds or milliseconds in parameters 11 and 12. - - - - - + + + + + This parameter determines if on/off status is saved and restored for the Smart plug 16A after power failure. - - - - - + + + + + Choose by how much power consumption needs to increase or decrease to be reported. Values correspond to percentages so if 20 is set (by default), the device will report any power consumption changes of 20% or more compared to the last reading. Set value from 0 - 100 (0% - 100%). 0 - Reporting Disabled. 1 - 100 = 1% - 100% Reporting enabled. Power report is send (push) only when actual power in Watts in real time change for more than set percentage comparing to previous actual power in Watts, step is 1%. Default value 20. - - - + + + Set value refers to the time interval with which power consumption in Watts is reported (0 - 32535 seconds). If 300 is entered (by default), energy consumption reports will be sent to the gateway (hub) every 300 seconds (or 5 minutes). Set value means time interval (0 - 32767) in seconds, when power report is send. @@ -69,61 +100,58 @@ Power report is send with time interval set by entered value. Default value 300 (power report in Watts is send each 300s). - - - + + + Lower power threshold used in param 52. Can not be higher than param 51 0-4000 (0.0 to 4000.0W, 0 disables) - - - + + + Upper power threshold used in param 52. Can not be higher than param 50 0-4000 (0.0 to 4000.0W, 0 disables) - - - + + + Parameter defines the way 3rd association group devices are controlled, depending on the current power load. - - - - - - - - - - + + + + + + + + + + The function allows for turning off the controlled device in case of exceeding the defined power for more than 3.1s. Controlled device can be turned back on by S-button or sending a control frame. By default this function is inactive. 1-4000 (1-4000W) 0 disables - - - + + + Using this parameter it is possible to enable/disable reporting after the set command (i.e. Basic set). - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/config/remotec/zrc-100eu.xml b/config/remotec/zrc-100eu.xml new file mode 100644 index 0000000000..4f862083d2 --- /dev/null +++ b/config/remotec/zrc-100eu.xml @@ -0,0 +1,14 @@ + + + http://www.openzwave.com/device-database/5254:8380:0001 + images/remotec/zrc-100eu.png + https://products.z-wavealliance.org/products/1639/ + Remotec bw8380eu + CEPT (Europe) + ZRC-100EU / BW8380EU + ZRC-100EU + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1639/xml + + + diff --git a/config/remotec/zrc-90.xml b/config/remotec/zrc-90.xml index d39c29d5f4..0f9e4e9bae 100644 --- a/config/remotec/zrc-90.xml +++ b/config/remotec/zrc-90.xml @@ -1,9 +1,26 @@ - - - - - - - - + + + http://www.openzwave.com/device-database/5254:8510:0001 + images/remotec/zrc-90.png + https://products.z-wavealliance.org/products/1584/ + Press “L+R” buttons simultaneously until LED light up to add the device into ZRC-90 Z-Wave network. + Click once on the “R” button to remove the device from ZRC-90 Z-Wave network. + BW8510EU + The ZRC-90 Scene Master is a Z-Wave Central Scene Controller. When one of the buttons on the ZRC-90 is pushed, your Z-Wave central controller will receive a signal which it can use to trigger unlimited control possibilities. With 8 buttons, each supporting a long-press capability, you can control 16 different actions in your central controller. The ZRC-90 is a great solution for triggering events more quickly than taking out your smart-phone and running a home control app. The Scene Master is ideal for kids, elderlies and guests who may not have full access to your smart home’s mobile application and hence may not have the rights to switch on various lighting, heating, air conditioning and other home appliance. With a convenient snap-in wall mount, the ZRC-90 can also be removed to keep it handy while you go about your home for the ultimate in simple convenience. + ZRC-90EU + Press and keep holding “R” button not less than 10 seconds. +Release “R” button then triple click on “R” button within 2 seconds. + Enter to the Listening mode (Wake up) by click once on “W” button. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1584/F-BW8510xx (ZRC-90xx) User Manual_V1.01_20151030.pdf + CEPT (Europe) + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1584/xml + + + + + + + + diff --git a/config/remotec/zts-500.xml b/config/remotec/zts-500.xml index bc9100bbfb..cda03abb1d 100644 --- a/config/remotec/zts-500.xml +++ b/config/remotec/zts-500.xml @@ -1,4 +1,36 @@ - + + + http://www.openzwave.com/device-database/5254:8170:0200 + images/remotec/zts-500.png + https://products.z-wavealliance.org/products/1767/ + Press and keep holding > or < for 3 seconds to navigate to the System Main (SYS) screen. +Press > to navigate to the Reset (RST) screen. +Press + or - to select Yes. +Press and keep holding > for 2 seconds to confirm your selection. +Press < to cancel and back to the previous screen. +Use the RESET procedure ONLY when the primary Controller is missing or inoperable. + + U.S. / Canada / Mexico + ZTS-500 is a user-friendly Z-Wave programmable smart thermostat. The ZTS-500 is compatible with any Z-Wave certified controller or gateway and is designed to fit perfectly over most original thermostat installation marks without the need for a mounting board. The invisible 4-button back-illuminated interface combines a simple and intuitive interactive experience with a modern fashionable look. The flip-over terminal-board makes installation a breeze, The ZTS-500 allows utilization even in environments where a C wire is not available. With automatic power source detection (24Vac or Battery Power), it decide to maximizing battery life or acting as a range extender in the Z-Wave network, and all your connections will be safe and secure behind AES128 encryption. The ZTS-500’s available multi-color faceplates allow for seamless integration into a variety of interior designs. + From the Standby screen, press > or < to navigate to the Z-Wave screen and the Z-Wave LED will continuously flash. +Tap + to include the ZTS-500US into the network. +- The “✔” symbol will be displayed on screen once the ZTS-500US is added into the network. +The Z-Wave disconnect icon will also be removed from the standby screen. + +- The “x” symbol will be displayed on screen if there is no action (time out) or unable to include the ZTS-500US into the network. + + ZTS-500US + Press and keep holding > or < for 3 seconds to navigate to the System Main (SYS) screen. +On the Z-Wave (Z-w) screen. +Tap + to exclude ZTS-500US from the network. +Press < to cancel and back to the previous screen. + + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1767/F-BW8170US (ZTS-500US) User_Manual_V1.01_Z-Wave validation_20160510.pdf + Z-WAVE SMART THERMOSTAT + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1767/xml + + diff --git a/config/remotec/zxt-120.xml b/config/remotec/zxt-120.xml index ecdbf94263..881c40a13a 100644 --- a/config/remotec/zxt-120.xml +++ b/config/remotec/zxt-120.xml @@ -1,28 +1,28 @@ - + http://www.openzwave.com/device-database/5254:8377:0101 images/remotec/zxt-120.png https://products.z-wavealliance.org/products/715/ BW8377EU - Remotec ZXT-120EU AC Extender - l Fully complaint to Z-Wave command class. -l Built-in AC IR code library with Configuration Learning capability. -l Able to feedback room temperature. -l Build-in 5 direction IR emitters(hemispherical coverage), -l 3.5mm jack for external wired IR emitter (optional). -l Transmit IR control code with a wide range of carrier frequency (15 to 455kHz). -l Programmable power level (LOW or HIGH) for external IR emitter to avoid saturation of IR receivers. -l Dual mode (FLiRS mode when working on battery, Always Listening mode when work on AC power) -l Frequency: US: 908.4MHz, EU:868.4MHz, AU:921.4MHz -l Power Source: USB mini-B,5V DC Jack, or 3xAAA batteries. -l Dismountable battery box. -l Dimension: Extender unit: 70mm (diameter) *18mm(thickness) -l Battery Box: 70mm(diameter) *15.5mm(thickness) + Remotec BW8377IL + Remotec BW8377IL http://www.remotec.com.hk/zaspx/product_content.aspx?aboutno=36&subaboutno=45&main=f CEPT (Europe) Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/715/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1551/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1552/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1830/xml + https://products.z-wavealliance.org/products/1551/ + BW8377AU + Australia / New Zealand + https://products.z-wavealliance.org/products/1552/ + U.S. / Canada / Mexico + BW8377US + https://products.z-wavealliance.org/products/1830/ + BW8377IL + Israel diff --git a/config/remotec/zxt-310.xml b/config/remotec/zxt-310.xml index 1fcc980da5..de62442046 100644 --- a/config/remotec/zxt-310.xml +++ b/config/remotec/zxt-310.xml @@ -1,12 +1,23 @@ - - + + + http://www.openzwave.com/device-database/5254:8371:0100 + images/remotec/zxt-310.png + https://products.z-wavealliance.org/products/1540/ + Z-Wave to IR extender for Audio/Video devices with built-in and cloud-based IR library. + Remotec ZXT-310US + U.S. / Canada / Mexico + BW8371US + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1540/xml + + - + IR code number for built-in code library. Refer "Code list" for details. - + * 1 (0x01) = EP1 * 1 (0x02) = EP2 @@ -16,13 +27,13 @@ * 1 (0x06) = EP6 - + IR output port routing. Please make sure that the "End point selection control" has completed (if necessary) before process the following setup. - + Please make sure that the "End point selection control" has completed (if necessary) before process the following setup. @@ -32,7 +43,7 @@ (default is in high power mode). - + Please make sure that the "End point selection control" has completed (if necessary) before process the following setup. @@ -45,7 +56,7 @@ (Z-Wave Cmd#, e.g. if POWER key is going to be learnt, input the value: 39 (0x27)) - + * 0 (0x00): IR channel idle (default) * 1 (0x01): OK @@ -54,7 +65,7 @@ * 4 (0x04): Learning Fail - + Please make sure that the "End point selection control" has completed (if necessary) before process the following setup. diff --git a/config/remotec/zxt-600.xml b/config/remotec/zxt-600.xml index 8825eca934..b57efd5da9 100644 --- a/config/remotec/zxt-600.xml +++ b/config/remotec/zxt-600.xml @@ -1,4 +1,33 @@ - + + + http://www.openzwave.com/device-database/5254:8490:0100 + images/remotec/zxt-600.png + https://products.z-wavealliance.org/products/2445/ + 1, Refer to your primary controller to enter into the Inclusion Mode or Exclusion Mode +2, When it is prompted to enter it, please triple click the “PROG” button within 1 second. +3, Green Indicator flashes TWICE then stay off + AC MASTER + 1, Refer to your primary controller to enter into the Inclusion Mode or Exclusion Mode +2, When it is prompted to enter it, please triple click the “PROG” button within 1 second. +3, Green Indicator flashes TWICE then stay off + ZXT-600 AC Master is a Z-Wave plus certified IR Bridge for split air conditioner control by receiving Z-Wave command and translating to Infrared command and flawlessly work with any Z-Wave compliant gateway. +With its over 250 brands built-in code library and ever-green up to date cloud IR database supporting advanced code learning search, ZXT-600 can easily set up and smart control most of AC brands and models actively worldwide by Z-Wave gateway. +The battery powered device will allow you to mount it anywhere you want such as wall, ceiling or put it on table and never compromise on the form factor. By supporting OTA function, gateway can enable ZXT-600 to update firmware if newest available. + + Press and Hold “PROG” button for 3 seconds on AC Master, the Green Indicator will light up. DO NOT Release the “PROG” Button until Green Indicator flashes TWICE. +Remark : Please use this procedure only when the network primary controller is missing or otherwise inoperable. + U.S. / Canada / Mexico + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2553/BW8490_Installation_Guide_201700807.pdf + ZXT-600US + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2445/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2553/xml + + https://products.z-wavealliance.org/products/2553/ + Press the "PROG" button to wakeup the unit + ZXT-600EU + CEPT (Europe) + + + + + + diff --git a/config/schlage/BE469ZP.xml b/config/schlage/BE469ZP.xml index 89c84b4872..cf2c64a7f0 100644 --- a/config/schlage/BE469ZP.xml +++ b/config/schlage/BE469ZP.xml @@ -1,33 +1,84 @@ - - - - - + + + http://www.openzwave.com/device-database/003B:0469:0001 + images/schlage/BE469ZP.png + https://products.z-wavealliance.org/products/3130/ + One-button Remove lock from Z-Wave Network (Exclusion) + +1. Place your home automation system or panel into the “Remove” or Exclusion Mode (Refer to the respective documentation for that specific home automation system or panel device for details). +2. Remove the battery cover of the deadbolt. +3. Press then release the button on the PCB. +4. An LED will flash amber indicating the “Remove” or Exclusion process is in progress. +5. When a green LED flashes 3 times, the “Remove” or Exclusion process is completed successfully. +6. If a red LED turns ON, try repeating steps 1-3 + +Interactive Instruction for Remove https://instructions.allegion.com/instr/86/2581 + BE469ZP + U.S. / Canada / Mexico + The Schlage Connect™ Smart Deadbolt combines advanced features and compatibility with your home automation or security system, allowing you to control your lock from anywhere and freeing you from the hassles of lost keys, getting locked out, or hiding a spare for friends and family. + +The lock comes preprogrammed with two access codes and can hold up to 30 unique codes for family members and trusted friends. The fingerprint-resistant touchscreen helps access codes stay private, minimizing tell-tale wear that can tip off possible intruders. + +The Schlage Connect Smart Deadbolt is battery-powered with a low battery warning that gives you weeks of advanced notice before it runs out. With guaranteed fit on standard doors, it’s easy for homeowners to install in minutes with just a screwdriver. The touchscreen continues to work in the event of a power outage, so you don’t have to worry about getting locked out – plus, a back-up key is included with the lock for peace of mind. + +The Schlage Connect Smart Deadbolt incorporates Z-Wave Plus S2 technology, an enhanced security protocol that features an additional layer of AES encryption of wireless signals. The Z-Wave technology allows you to integrate your exterior door locks with other Z-Wave smart home devices, such as cameras, motion detectors, lights and thermostats, bringing the safety, simplicity and style of Schlage to your smart home. + + Schlage Connect Smart Deadbolt + One-button Add lock to Z-Wave Network (Inclusion) + +1. Place your home automation system or panel into the “Add” or Inclusion Mode (Refer to the respective documentation for that specific home automation system or panel device for details). +2. Remove the battery cover of the deadbolt. +3. Press then release the button on the PCB. +4. An LED will flash amber indicating the “Add” or Inclusion process is in progress. +• If the Security Scheme is Security 2 (S2), verify the DSK of the lock at the Z-Wave Controller. The PIN Code portion of the Z-Wave DSK will be needed. +5. When a green LED turns ON, the “Add” or Inclusion has completed successfully. +6. If a red LED turns ON, try repeating steps 1-3 + +Interactive Instruction for Add +https://instructions.allegion.com/instr/86/2543 + + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3130/Connect_QSG_Add_Remove_FDR_Association.pdf + Steps for One-button Factory Default Reset + +1. Remove the battery cover of the deadbolt +2. Press and hold the button on the PCB for 7 (seven) seconds. +While holding the button pressed, after 1 sec LED will be lit for 2 sec. and turn OFF; continue to press and hold the button until the LED will be lit again and release the button. +3. The LED will blink red three times and the green check on the touchscreen will blink if the Factory Default Reset is successful. +4. To check that the lock was reset, press the Schlage Button and enter one of the Default User Codes. If the reset was successful, the Default User Codes will unlock the deadbolt. +NOTE: Please use this procedure only when the network primary controller is missing or otherwise inoperable. + + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3130/xml + + + + + Enable or disable the keypad beeper. - - - - - + + + + + Enable or disable vacation mode. Disables all user codes, preventing all codes from unlocking the deadbolt. Enable for extra security while you are away for an extended period of time. - - - - - + + + + + Enable or disable Lock and Leave Mode. When enabled: Press the Schlage button on the keypad to lock the deadbolt (Default setting). When disabled: Press the Schlage button on the keypad and then enter a user code to lock the deadbolt. - - - - - + + + + + By default the alarm is turned off by default. After intalling, you can turn the alarm on. Alert @@ -46,108 +97,106 @@ Perfect for nighttime or when you are away from home. Least sensitive mode. Sounds 3-minute shrill, steady alarm (90dB). - - - - - - - + + + + + + + Each alarm mode is preset to a sensitivity level of 3. If your alarm is sounding too frequently, or not frequently enough, try changing this setting. If you change the alarm mode, the sensitivity will revert back to the default setting. - - - - - - - - + + + + + + + + Each alarm mode is preset to a sensitivity level of 3. If your alarm is sounding too frequently, or not frequently enough, try changing this setting. If you change the alarm mode, the sensitivity will revert back to the default setting. - - - - - - - - + + + + + + + + Each alarm mode is preset to a sensitivity level of 3. If your alarm is sounding too frequently, or not frequently enough, try changing this setting. If you change the alarm mode, the sensitivity will revert back to the default setting. - - - - - - - - + + + + + + + + This configuration setting controls the ability to ENABLE or DISABLE local control of the built-in alarm function. - - - - - + + + + + Indicates the number of transitions from locked to unlocked or unlocked to locked state via electronic activation. - - - + + + Indicates the number of transitions from locked to unlocked or unlocked to locked state via mechanical activation. - - - + + + Indicates the number of failed electronic activation attempts for this lock. - - - + + + When enabled, the lock will automatically relock 30 seconds after unlocking. (Disabled by default.) - - - - - + + + + + Choose user code length between 4 and 8 digits. IMPORTANT: All user codes must be the same length. - - - + + + Indicates the number of transitions from locked to unlocked or unlocked to locked state via electronic activation that indicated a high preload on the deadbolt. This is a subset of Electronic transition count. High preload occurs when the bolt is obstructed and the motor needs to use more power to throw the bolt. Adjust door and strike plate to ensure the bolt can move freely. This will save battery power. - - - The version of the bootloader in the lock. - - - - - - - - - - - - - - - + + + + diff --git a/config/schlagelink/minikeypad.xml b/config/schlagelink/minikeypad.xml index 2b64771d8d..299b73456e 100644 --- a/config/schlagelink/minikeypad.xml +++ b/config/schlagelink/minikeypad.xml @@ -1,5 +1,5 @@ - + @@ -26,6 +26,11 @@ false + + + true + + diff --git a/config/sensative/strips.xml b/config/sensative/strips.xml index 049c558e3f..808f6eccbd 100644 --- a/config/sensative/strips.xml +++ b/config/sensative/strips.xml @@ -1,24 +1,97 @@ - - - - - - Set Notification type. - - - - - - Set Led indication. - - - - - - - - - - - + + + http://www.openzwave.com/device-database/019A:0003:0003 + images/sensative/strips.png + https://products.z-wavealliance.org/products/3388/ + Please use this procedure only when your Z-Wave controller is missing or otherwise inoperable: + +1. Place the round magnet at the rounded edge of Strips. + +2. When the LED blinks, move the magnet away. Repeat 3 times in total within 10 seconds. + +3. On the 3rd repetition, leave the magnet at the rounded edge for 10s. + +4. A long LED signal indicates success. + Wake up Strips manually for Z-Wave communication: + +1. Place the round magnet at the rounded edge of Strips. + +2. When the LED blinks, move the magnet away. + +3. Repeat 3 times in total within 10 seconds. + + Strips is delivered in "auto-add" mode. +Follow the process below to add Strips in a Z-Wave network. + +1. Start the add mode on the Z-Wave controller. +See the controller’s manual. + +2. Remove both magnets from Strips. Strips blinks twice to confirm the command and successful addition. + +3. A long LED blink indicates that the add process was successful + +4. The Z-Wave controller application should now allow you to monitor your Strips sensor status. + +5. Move the squared magnet as shown in the picture . Check that the Z-Wave system indicates the status correctly. + +6. If the Z-Wave system does not respond, it may be needed to change Strips’ notification type. + +Manual add: +1. Set the controller to add mode (See your controller’s manual). + +2. Place the round magnet at the rounded edge of Strips. +When the LED blinks, move the magnet away. Repeat 3 times in total within 10 seconds. + +3. A long LED blink indicates that the add process was successful. + + 11 01 015 + 1. Set the controller in remove mode (See your controller’s manual). + +2. Place the round magnet at the rounded edge of Strips. +When the LED blinks, move the magnet away. Repeat 3 times in total within 10 seconds. + +3. A long LED blink indicates that the remove process was successful. + Strips Guard is an ultra-thin magnetic sensor designed to monitor windows and doors for your safety. It´s so thin that it can be mounted invisibly in the tiny gap between the frame and the door or window. +It is as easy to mount as a sticker using Strips's adhesive tape. +Strips Guard is Z-Wave plus compliant and can be used with any existing Z-Wave smarthome systems. + Strips-MaZw + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3388/Strips Guard EU R3.pdf + CEPT (Europe) / U.S. / Canada / Mexico / CEPT (Europe) / U.S. / Canada / Mexico / CEPT (Europe) / U.S. / Canada / Mexico / U.S. / Canada / Mexico / CEPT (Europe) / CEPT (Europe) / CEPT (Europe) / U.S. / Canada / Mexico / Australia / New Zealand / India + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1510/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1753/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1790/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1862/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1863/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2073/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2080/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2144/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2146/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2827/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3296/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3297/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3369/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3388/xml + + + + + + Set Notification type. + + + + + + Set Led indication. + + + + + + + + + + diff --git a/config/sensative/stripscomfort.xml b/config/sensative/stripscomfort.xml index 8ea81e17f5..c5a80a8530 100644 --- a/config/sensative/stripscomfort.xml +++ b/config/sensative/stripscomfort.xml @@ -1,83 +1,118 @@ - - - - - - Led alarm reporting - - - - - Temperature and light reporting - - - - - Does not affect temperature alarms - - - - - Temperature reporting unit - - - - - Temperature alarms - - - - - + + + Led alarm reporting + + + + + Temperature and light reporting + + + + + Does not affect temperature alarms + + + + + Temperature reporting unit + + + + + Temperature alarms + + + + + -20 to 60C - - - + + + -20 to 60C - - - Ambient light reporting - - - - - - + + + Ambient light reporting + + + + + + 3 to 64000 - - - + + + 1 to 42000 - - - Leakage alarm - - - - - + + + Leakage alarm + + + + + 1 to 100 (1 = almost dry, 100 = wet) - - - + + + 0-120 (Hours between reports) - - - - - - - - - + + + + + + + + diff --git a/config/shenzen_neo/nas-ab01z.xml b/config/shenzen_neo/nas-ab01z.xml index 2bee9103bf..67dd116b13 100644 --- a/config/shenzen_neo/nas-ab01z.xml +++ b/config/shenzen_neo/nas-ab01z.xml @@ -1,96 +1,149 @@ - - - - - - + + + This parameter defines the output volume when siren plays door bell music. Door Bell music volume is divided into 3 stages - - - - - - + + + + + + This Parameter defines the alarm music duration time when siren receive an alarm sensor notification report or an alarm command from controller. The duration time is divided into 5 stages. - - - - - - - - This parameter defines the door bell music duration time when siren receives a door/window sensor notification report or an alarm command (BASIC_SET = 0x02) from controller. + + + + + + + + This parameter defines the door bell music duration time when siren receives a door/window sensor notification report or an alarm command (BASIC_SET = 0x02) from controller. The door bell music will be played always if this parameter is set to 255. The door bell music will not be played if this parameter is set to 0. Other values are the door bell music playing duration time. - - - This parameter defines the output volume when siren plays alarm music. + + + This parameter defines the output volume when siren plays alarm music. Door Bell music volume is divided into 3 stages - - - - - - This parameter defines the alarm music index for siren play different music when alarm occurs. + + + + + + This parameter defines the alarm music index for siren play different music when alarm occurs. There are 10 different music for user selection - - - - - - - - - - - - - This parameter defines the door bell music index for siren play different music when alarm occurs. + + + + + + + + + + + + + This parameter defines the door bell music index for siren play different music when alarm occurs. There are 10 different music for user selection. - - - - - - - - - - - - - This parameter defines the default music index, volume and the duration time for 3 siren on. + + + + + + + + + + + + + This parameter defines the default music index, volume and the duration time for 3 siren on. This parameter can be selected between ALARM MUSIC and DOOR BELL MUSIC. The settings for ALARM MUSIC MODE defines by Param #1, #2 and #5. The settings for DOOR BELL MUSIC MODE defines by Param #3, #4 and #6 - - - - - This parameter defines the default led enable status when siren is on for ALARM MUSIC MODE - - - - - This parameter defines the default led enable status when siren is on for DOOR BELL MUSIC MODE - - - - - - - - - - - - + + + + + This parameter defines the default led enable status when siren is on for ALARM MUSIC MODE + + + + + This parameter defines the default led enable status when siren is on for DOOR BELL MUSIC MODE + + + + + + + + + + + + diff --git a/config/shenzen_neo/nas-ds01z.xml b/config/shenzen_neo/nas-ds01z.xml index ec1cb21e3a..bc01ea0dfd 100644 --- a/config/shenzen_neo/nas-ds01z.xml +++ b/config/shenzen_neo/nas-ds01z.xml @@ -1,27 +1,80 @@ - - - - - - - This configuration parameter that can be used to adjust the amount of delay before the OFF command is transmitted. This parameter can be configured with the value of 0 through 65535, where 0 means send OFF command immediately and 65535 means 65535 seconds of delay. - - - - Basic Set Command will be sent where contains a value when the door/window is opened or closed, the receiver will take it for consideration; for instance, if a lamp module is received the Basic Set Command of which value is decisive as to how bright of dim level of lamp module shall be. - - - - - - - - - - - - - + + + http://www.openzwave.com/device-database/0258:0082:0003 + images/shenzen_neo/nas-ds01z.png + https://products.z-wavealliance.org/products/1668/ + NAS-DS01Z + Door Sensor + Manual Wakeup the Sensor + +You can press the button once to wake up the device and send wakeup notification to controller. If press successfully, the LED will blink one time. + U.S. / Canada / Mexico + Note: to use the reset procedure only when the primary controller is missing or inoperable. + +Restore the Sensor (Door/Window detector) to Factory Default Settings + +Reset procedure will delete all information on the Z-Wave network and Z-Wave controller or Z-Wave Gateway, and restore the sensor to factory default settings. +1.Remove the device cover. + +2.Make sure the sensor is powered. + +3.Press and hold the button for 10 seconds, + +4.Release the button. + + + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1782/Door-Window User Guide.doc + This product can be included and operated in any Z-Wave network with other Z-Wave certified devices from other manufacturers and/or other applications. All non-battery operated nodes within the network will act as repeaters regardless of vendor to increase reliability of the network. + +In the front casing, there is button that is used to carry out include, exclude or reset factory default settings on PCB Board. + +When power is first supplied, the LED will flash on and off alternately at one second intervals within 5 seconds if the detector has not been added a Z-Wave network. Please get familiar with the terms below before starting the operations. + Add the Sensor (Door/Window detector) to Z-Wave Network + +1.Remove the sensor cover. + +2.Make sure the sensor is powered. + +3.Set Z-Wave controller or Z-Wave gateway into inclusion mode (Refer to the controller or gateway operating manual) +4.Press the button three times within 1.5 second, the device will enter inclusion mode. And the LED will flash on and off alternately five times. + + Delete the Sensor (Door/Window detector) from Z-Wave Network + +1.Remove the device cover. + +2.Make sure the sensor is powered. + +3.Set Z-Wave controller or Z-Wave gateway into exclusion mode (Refer to the controller or gateway operating manual) +4.Press the button three times within 1.5 second, the device will enter exclusion mode. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1668/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1782/xml + + https://products.z-wavealliance.org/products/1782/ + NAS-DS01Z + CEPT (Europe) + + + + + + This configuration parameter that can be used to adjust the amount of delay before the OFF command is transmitted. This parameter can be configured with the value of 0 through 65535, where 0 means send OFF command immediately and 65535 means 65535 seconds of delay. + + + Basic Set Command will be sent where contains a value when the door/window is opened or closed, the receiver will take it for consideration; for instance, if a lamp module is received the Basic Set Command of which value is decisive as to how bright of dim level of lamp module shall be. + + + + + + + + + + + + + diff --git a/config/shenzen_neo/nas-pd01z.xml b/config/shenzen_neo/nas-pd01z.xml index 48fa75c281..33c6d1cd0d 100644 --- a/config/shenzen_neo/nas-pd01z.xml +++ b/config/shenzen_neo/nas-pd01z.xml @@ -1,19 +1,61 @@ - - + + + http://www.openzwave.com/device-database/0258:0083:0003 + images/shenzen_neo/nas-pd01z.png + https://products.z-wavealliance.org/products/1671/ + U.S. / Canada / Mexico + 1.Remove the device cover. + +2.Make sure the sensor is powered. + +3.Set Z‐Wave controller or Z‐Wave gateway into exclusion mode (Refer to the controller or gateway operating manual) +4.Press the button three times within 1.5 second, the device will enter exclusion mode. + Reset procedure will delete all information on the Z‐Wave network and Z‐Wave controller or Z‐Wave Gateway, and restore the sensor to factory default settings. +1.Remove the device cover. + +2.Make sure the sensor is powered. + +3.Press and hold the button for 10 seconds, Led will blink once. + +4.Release the button. + +Note: to use the reset procedure only when the primary controller is missing or inoperable. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1920/Motion Detector User Guide EU V3.3.pdf + Motion Sensor (PIR) + 1.Remove the sensor cover. + +2.Make sure the sensor is powered. + +3.Set Z‐Wave controller or Z‐Wave gateway into inclusion mode (Refer to the controller or gateway operating manual) +4.Press the button three times within 1.5 second, the device will enter inclusion mode. And the LED will flash on and off alternately five times. + This product can be included and operated in any Z‐Wave network with other Z‐Wave certified devices from other manufacturers and/or other applications. All non‐battery operated nodes within the network will act as repeaters regardless of vendor to increase reliability of the network. + +In the Back casing, there is a button that is used to carry out include, exclude, wake up device or reset factory default settings. + +When power is first supplied, the LED will flash on and off alternately at one second intervals within 5 seconds if the detector has not been added a Z‐Wave network. Please get familiar with the terms below before starting the operations. + NAS-PD01Z + You can press the button once to wake up the device and send wakeup notification to controller. If press successfully, the LED will blink one time + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1671/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1920/xml + + https://products.z-wavealliance.org/products/1920/ + NAS-PD01ZE + CEPT (Europe) + - + This parameter defines the sensitivity of PIR detector, it is recommended to test the detector with movements from a farthest end of the coverage area at first time of use. If movements cannot be detected sensitively, simply adjust the sensitivity level with this parameter. This Parameter can be configured with the value 8 trough 255, where 8 means high sensitivity and 255 means lowest sensitivity. - - + This parameter can be determined how long the associated devices should stay ON status. For instance, this parameter is set to 30(second), the PIR detector will send a BASIC_SET Command to an associated device with value basic set level if PIR detector is triggered and the associated device will be turned on 30(second) before it is turned off. This Parameter value must be large than Parameter 6#. @@ -21,68 +63,59 @@ Available Settings:5 to 600(second). - - + Basic Set Command will be sent where contains a value when PIR detector is triggered, the receiver will take it for consideration; for instance, if a lamp module is received the Basic Set Command of which value is decisive as to how bright of dim level of lamp module shall be. This Parameter is used to some associated devices. Available Settings: 0, 1 to 99 or 255. - - + This parameter can be enabled or disabled the PIR detector detecting function. - - - - - + + + + This parameter can be set a lux level value which determines when the light sensor is activated. If the ambient illumination level falls below this value and a person moves across or within the detected area , PIR detector will send a Z-Wave ON command(i.e. BASIC_SET (value = parameter 3) to an associated device and activate it. 0 to 1000(Lux). - - + This Parameter can be used to adjust the interval of being re-triggered after the PIR detector has been triggered. This Parameter value must be less than Parameter 2#. If user set this parameter to default by Configure CC, the parameter #2 will be set to default value. Available Settings: 1 to 8(s). - - + This Parameter can be set the light sensor measure ambient illumination level interval time. NOTE: This Value Must Be less than Wakeup Interval Time. Available Settings: 60 ~ 36000(second). - - + If this parameter is set to Enable, and when Lux level less than the value define by parameter #5, PIR detector will send a BASIC_SET command frame(i.e. BASIC_SET (value = parameter 3) to an associated device and activate it. If Lux Level greater than the value define by parameter #5, PIR detector will not send a BASIC_SET command frame. - - - - - + + + + This parameter defines by how much Lux Level must change, in lux, to be reported to the main controller. - - + This parameter can enabled or disable the PIR led blinking function. - - - - + + + - - - - + + + + diff --git a/config/shenzen_neo/nas-pd02z.xml b/config/shenzen_neo/nas-pd02z.xml index beaada7765..3a5aa9fc31 100644 --- a/config/shenzen_neo/nas-pd02z.xml +++ b/config/shenzen_neo/nas-pd02z.xml @@ -1,8 +1,18 @@ - - + + Fix parameters for temperature model, based on user feedback https://github.com/OpenZWave/open-zwave/issues/1866 + + + @@ -12,7 +22,7 @@ - + This parameter can be determined how long the associated devices should stay ON status. For instance, this parameter is set to 30(second), the PIR detector will send a BASIC_SET Command to an associated device with value basic set level if PIR detector is triggered and the associated device will be turned on 30(second) before it is turned off. @@ -28,7 +38,7 @@ Available Settings: 0, 1 to 99 or 255. - + Enable the motion detection (PIR) function. @@ -36,8 +46,8 @@ - - + + Define the illumination level value which determines when the 'Illumination switch ON function' is activated. @@ -45,7 +55,7 @@ 0 to 1000(Lux). - + Period after motion detection in which the sensor is insensitive for new motion detection. @@ -53,7 +63,7 @@ Available Settings: 1 to 8(s). - + Determine the time between illumination reports, even when value has not changed. @@ -61,7 +71,7 @@ Available Settings: 60 ~ 36000(second). - + Enable the function to switch on a associated device (group 2) once motion has been detected and the illumination level will be less than the value specified in 'Illumination switch ON level'. @@ -69,17 +79,31 @@ - - + + This parameter defines by how much Lux Level must change, in lux, to be reported to the main controller. - - - Enable LED/PIR to blink red when motion detected. + + + This parameter is configured the value that differential between current measured and previous report value. If the differential value larger than the settings, device will report this measured temperature value to nodes associated in lifeline. + + + + This parameter can enabled or disable the PIR led blinking function. - + + + The motion detected event can be sent multiple times/only once until device report motion cleared event. + + + + + + This parameter defines the calibrated scale for ambient light intensity. + + diff --git a/config/shenzen_neo/nas-wr01z.xml b/config/shenzen_neo/nas-wr01z.xml index cf7cf9d863..2733c020b0 100644 --- a/config/shenzen_neo/nas-wr01z.xml +++ b/config/shenzen_neo/nas-wr01z.xml @@ -1,20 +1,60 @@ - - + + + http://www.openzwave.com/device-database/0258:0087:0003 + images/shenzen_neo/nas-wr01z.png + https://products.z-wavealliance.org/products/1670/ + Add the Device (Smart Plug) to Z‐Wave Network +1.Make sure the sensor is powered. +2.Set Z‐Wave controller or Z‐Wave gateway into inclusion mode (Refer to the controller or gateway operating manual) +3.Press the button three times within 1.5 second, the device will enter inclusion mode. And the LED will flash on and off with green alternately five times within 2 seconds. + U.S. / Canada / Mexico + this power plug is connected to power, not battery powered + This product can be included and operated in any Z‐Wave network with other Z‐Wave certified devices from other manufacturers and/or other applications. All non‐battery operated nodes within the network will act as repeaters regardless of vendor to increase reliability of the network. + +In the front casing, there is button that is used to carry out include, exclude or reset factory default settings on PCB Board. + +When power is first supplied, the LED will flash on and off with yellow alternately every 1 second intervals within 5 seconds if the detector has not been added a Z‐Wave network, otherwise the LED will flash on and off 5 times with cyan alternately every 300 millisecond. Please get familiar with the terms below before starting the operations. + +This Plug has function that remembers the relay states, the plug will turn on after power up next time if the plug is turn on before the power cut‐off. + Smart Power Plug + Delete the Device (Smart Plug) from Z‐Wave Network +1.Make sure the sensor is powered. +2.Set Z‐Wave controller or Z‐Wave gateway into exclusion mode (Refer to the controller or gateway operating manual) +3.Press the button three times within 1.5 second, the device will enter exclusion mode. And the LED will flash on and off with yellow alternately five times within 2 seconds. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1783/Smart-Plug User Guide V2.doc + Note: to use the reset procedure only when the primary controller is missing or inoperable. +Restore the Device (Smart Plug) to Factory Default Settings + +Reset procedure will delete all information on the Z‐Wave network and Z‐Wave controller or Z‐Wave Gateway, and restore the sensor to factory default settings. +1.Make sure the sensor is powered. + +2.Press and hold the button more than 10 seconds until the LED blink with red color. + +3.Release the button. + NAS-WR01Z + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1670/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1783/xml + + https://products.z-wavealliance.org/products/1783/ + CEPT (Europe) + NAS-WR01Z + - + This parameter defines Disable/Enable meter report measure data to controller. - + This parameter defines interval time (in seconds) that Meter report data to main controller. - + This parameter defines maximum current (in Amperes) the plug can provide to load that be connected to plug. If the current consumed by load is greater than maximum current, the plug will cut off power, and send NOTIFICATION_EVENT_POWER_MANAGEMENT_OVER_LOAD_DETECTED to associated devices in lifeline. Red Led will blink every seconds until current is normal (less than Parameter #3). @@ -22,13 +62,13 @@ If user set this parameter to default by Configure CC, the parameter #4 will be set to default value. - + This parameter defines maximum current (in Amperes), if the current plug provide to load is greater than this parameter, the plug will send over-current notification to the controller and the LED will turn RED, but plug cannot cut-off power. This parameter value must be less than parameter #3. If user set this parameter to default by Configure CC, the parameter #3 will be set to default value. - + This parameter defines the LED indication Function ON/OFF. If disabled, then LED indication Function and will always be turn-off, while enabled means LED Function is on. @@ -36,12 +76,12 @@ - + This parameter defines by how much power consumed must change to be reported to the Z-Wave Controller or Z-Wave Gateway, in percents. If the rate of power consumed change ratio is greater than this parameter, the plug will report the results, voltage, current, power and energy, that plug measure to Z-Wave Controller or Z-Wave Gateway - + This parameter defined the relay status if remember or not. If remembered, the plug will restore the relay status last power off when the plug supply power next time. @@ -49,7 +89,7 @@ - + This parameter defines the timer function Enable/Disable. If disabled, then time switch function is not available. @@ -59,13 +99,13 @@ - + This parameter defines the time period that plug time switch off. This parameter can be configured 1 - 65535(in minutes). If Parameter #8 is enabled, and relay is turn-on, the relay will be turn-off after delay this parameter. - + This parameter defines the button on/off function is enabled or not on the top of the wall plug. If enabled, users can turn on and off the wall plug by pressing the button on the top of the wall plug. @@ -78,9 +118,9 @@ - - - + + + diff --git a/config/shenzen_neo/nas-ws02z.xml b/config/shenzen_neo/nas-ws02z.xml index 2f650f3617..a8b2ae0b5e 100644 --- a/config/shenzen_neo/nas-ws02z.xml +++ b/config/shenzen_neo/nas-ws02z.xml @@ -1,55 +1,98 @@ - - - - - - If this parameter is set to 0, the beep and LED will be turn on always until water leakage is not detected. - - - - This Parameter defines beep on/off interval time when water leakage is detected. - - - - This parameter defines beep on duration first time when water leakage is detected. - - - - This parameter defines beep on duration after fist beep on when water leakage is detected. - - - - This parameter defines beep on is enabled or disabled when water leakage is detected. + + + http://www.openzwave.com/device-database/0258:0085:0003 + images/shenzen_neo/nas-ws02z.png + https://products.z-wavealliance.org/products/1788/ + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1788/Water Leakage Detector User Manual V2.doc + NAS-WS01Z + Add the Sensor to Z-Wave Network + +1.Remove the sensor cover. + +2.Make sure the sensor is powered. + +3.Set Z-Wave controller or Z-Wave gateway into inclusion mode (Refer to the controller or gateway operating manual) + +4.Press the button three times within 1.5 second, the device will enter inclusion mode. And the LED will flash on and off alternately five times. + In the front casing, there is button that is used to carry out include, exclude or reset factory default settings on PCB Board. + +When power is first supplied, the LED will flash on and off alternately at one second intervals within 5 seconds if the detector has been added a Z-Wave network. Please get familiar with the terms below before starting the operations. + +This product can be included and operated in any Z-Wave network with other Z-Wave certified devices from other manufacturers and/or other applications. All non-battery operated nodes within the network will act as repeaters regardless of vendor to increase reliability of the network. + Water Sensor + Delete the Sensor from Z-Wave Network + +1.Remove the device cover. + +2.Make sure the sensor is powered. + +3.Set Z-Wave controller or Z-Wave gateway into exclusion mode (Refer to the controller or gateway operating manual) + +4.Press the button three times within 1.5 second, the device will enter exclusion mode. + Restore the Sensor to Factory Default Settings + +Note: to use the reset procedure only when the primary controller is missing or inoperable + +Reset procedure will delete all information on the Z-Wave network and Z-Wave controller or Z-Wave Gateway, and restore the sensor to factory default settings. + +1.Remove the device cover. + +2.Make sure the sensor is powered. + +3.Press and hold the button for 10 seconds, led will blink once. + +4.Release the button. + Wakeup the Sensor Manual + +User can press button once to wake-up this sensor to send wakeup notification to controller, the Led will be blink one time. + U.S. / Canada / Mexico + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1788/xml + + + + + + If this parameter is set to 0, the beep and LED will be turn on always until water leakage is not detected. + + + This Parameter defines beep on/off interval time when water leakage is detected. + + + This parameter defines beep on duration first time when water leakage is detected. + + + This parameter defines beep on duration after fist beep on when water leakage is detected. + + + This parameter defines beep on is enabled or disabled when water leakage is detected. 0 indicate beep on is disable, but LED will be turned on when water leakage detected. 1 indicate beep on is enabled, the BEEP and LED will be turned on when water leakage detected. - - - - - - This parameter defines the function than water leakage detect is enabled or disabled. + + + + + This parameter defines the function than water leakage detect is enabled or disabled. 0 indicate disable water leakage detect, 1 indicate enable water leakage detect. - - - - - - Basic Set Command will be sent where contains a value when the leakage is detected, the receiver will take it for consideration; + + + + + Basic Set Command will be sent where contains a value when the leakage is detected, the receiver will take it for consideration; for instance, if a lamp module is received the Basic Set Command of which value is decisive as to how bright of dim level of lamp module shall be. - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + diff --git a/config/simon/10002034-13X.xml b/config/simon/10002034-13X.xml index 4f88c69bd4..6d2527e32c 100644 --- a/config/simon/10002034-13X.xml +++ b/config/simon/10002034-13X.xml @@ -1,8 +1,37 @@ - +--> + + http://www.openzwave.com/device-database/0267:0000:0001 + images/simon/10002034-13X.png + https://products.z-wavealliance.org/products/3279/ + 10003034-13X + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3279/991406.pdf + S100 Switch IO (China) + Simon Electronic Switch IO integrated by Electronic Switch that provides power Switch and Rocker that provides Z-Wave communication attributes. + When the pushbutton is released after a press of (2sec<T<20sec) the device will send a NIF to exclude from Z-Wave network or perform an association with other Z-Wave device. +Main LED will Blink with 0,3 sec period to inform that NIF can be send after release of pushbutton. + +This process does not perform a default reset of configurations. + +Main LED will Blink with 0,3 sec period to inform that NIF can be send after release of pushbutton. + China + When the pushbutton is released after a press of (20sec<T) the device will perform a factory default values operation, excluding it from network and resetíng the configuration parameters. + +Main LED will perform 1 Blink with 5 sec. + +Please use this procedure only when the network primary controller is missing or otherwise inoperable. + When the pushbutton is released after a press of (2sec<T<20sec) the device will send a NIF to include from Z-Wave network or perform an association with other Z-Wave device. +Main LED will Blink with 0,3 sec period to inform that NIF can be send after release of pushbutton. + +This process does not perform a default reset of configurations. + +Main LED will Blink with 0,3 sec period to inform that NIF can be send after release of pushbutton. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3279/xml + + diff --git a/config/steinel/is140-2.xml b/config/steinel/is140-2.xml index a869c87675..a36e17338e 100644 --- a/config/steinel/is140-2.xml +++ b/config/steinel/is140-2.xml @@ -1,40 +1,82 @@ - - - + + + http://www.openzwave.com/device-database/0271:1A72:0002 + images/steinel/is140-2.png + https://products.z-wavealliance.org/products/2310/ + IS 140-2 Z-Wave + 40111677001 + CEPT (Europe) + Are you toying with the idea of fitting a motion detector to your building? The infrared controlled IS 140-2 motion detector gives you all the benefits of a modern detector. Needless to say, we always use the very latest technology for our bestsellers too. For instance, we have given the product in its current generation even more class: larger adjustment angle, even longer reach and even better detection performance. Treat your home to intelligent sensor technology. + +Smart home included. +The optional Smart Friends box and the free Smart Friends app make it easy to set the motion detector via smart phone or tablet. The light connected can also be switched ON or OFF via app. Other Steinel products can also be interconnected. If you wish, this also works via remote control when you are out. That completes your own light management system. +Along with STEINEL products, Smart Friends solutions from PAULMANN, SCHELLENBERG and ABUS can also integrated. Smart homes from a brand-name provider. + Exclusion = Remove + +To start the motion detector's exclusion mode, turn the device's control dial (E) to "Set" and back to "0" within 5 seconds. + +Removing IS 140-2 from the Smart Friends system: +1) In the rooms view, activate the edit mode. +2) Select the device in the chosen room and press the "delete" button. Press delete and follow the instructions in the app. +3) To put the device into exclusion mode, turn the device's control dial (E) to "Set" and back to "0" within 5 seconds. The red status LED (F) lights up to show that this mode is selected. +4) The app displays a confirmation message once exclusion has been successfully completed. + Resetting IS 140-2 to factory settings: + +Please use this procedure only when the network primary controller is missing or otherwise inoperable. + +1) Turn the device's control dial (E) to "Set" and move it to "Reset" within 5 seconds. +2) The status LED (F) briefly flashes to show that the light has been reset. +3) The device is now no longer included in the Z-Wave system and has been returned to factory settings. + Inclusion = Add + +To start the motion detector's inclusion mode, turn the device's control dial (E) to "Set" and back to "0" within 5 seconds. + +Adding IS 140-2 to the Smart Friends system: +1) Download the Smart Friends app from the app store. +2) In the rooms view, activate the edit mode. +3) Select the chosen room and press the "Add device" button. +4) To put the device into inclusion mode, turn the device's control dial (E) to "Set" and back to "0" within 5 seconds. The status LED (F) lights up to show that this mode is selected. +5) The app displays a confirmation message once inclusion has been successfully completed. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2310/IS140-2Z-Wave_5spr_110050437_11.04.17.pdf + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2310/xml + + + - - - + + + Available settings: 5-900 seconds. - - - + + + 2000 - is used as daylight (always night mode). 0 - run Learn ambient light sequence. 2-1999 lux. - - - + + + Potentiometer State. Available settings: 2-100%. - - - External ambient light value. - - - - - Disable local control. - - - - - - - - + + + External ambient light value. + + + + + Disable local control. + + + + + + + + Off behaviour (timeout). 0 - Lamp is switched off and remains so until any new motion event (local or remote) is received. 1 to 100 (Default) timeout: 1 second (1) to 100 seconds (100) in 1-second resolution. @@ -43,9 +85,9 @@ 255 Lamp is switched off for TIME (cfg 1). It does not wait for a motion event and works normally via current motion evaluation. - - - + + + On behaviour (timeout). Similar than Off behaviour. Available settings: 0-255. @@ -53,9 +95,9 @@ It then works normally via current motion evaluation. Notice - during the day, this mode cannot be ended remotely due to motion events not being transmitted - only via local motion sensor if enabled. - - - + + + On behaviour time over (timeout). Available settings: 0-255. 0 No additional waiting for motion. @@ -64,9 +106,9 @@ 201 to 209 (Default) timeout: 1 hour (201) to 9 hours (209) in 1-hour resolution. 255 Never stop waiting before motion. - - - + + + Available settings: 0-255. 0 - Lamp is switched off and remains so until any new motion event (local or remote) is received. 1 to 100 timeout: 1 second (1) to 100 seconds (100) in 1-second resolution. @@ -74,9 +116,9 @@ 201 to 209 (Default) timeout: 1 hour (201) to 9 hours (209) in 1-hour resolution. 255 device ignores ON - OFF sequence and uses OFF behavior. - - - Available settings: 0-255. + + + Available settings: 0-255. 0 - Lamp is switched on and remains so until any new motion event (local or remote) is received. It then works normally via current motion evaluation. Notice - during the day, this mode cannot be ended remotely due to motion events not being transmitted - only via local motion sensor if enabled. @@ -85,14 +127,14 @@ 201 to 209 (Default) timeout: 1 hour (201) to 9 hours (209) in 1-hour resolution. 255 device ignores OFF - ON sequence and uses ON behaviour. - - - + + + Available settings: 10-50. - - - + + + Available settings: 0-255. 0 (Default) BASIC SET to Motion sensor endpoint ignored, BASIC to root is mapped to relay endpoint, motion sensor still enabled. 1 to 100 timeout: 1 second (1) to 100 seconds (100) in 1-second resolution. @@ -100,18 +142,15 @@ 201 to 209 timeout: 1 hour (201) to 9 hours (209) in 1-hour resolution. 255 BASIC SET to Motion sensor endpoint ignored, BASIC to root is mapped to relay endpoint, motion sensor still disabled - - - - - - - - - - - - - + + + + + + + + + + + - diff --git a/config/steinel/l810-led-ihf.xml b/config/steinel/l810-led-ihf.xml index 0aec485d45..0e06b78b9b 100644 --- a/config/steinel/l810-led-ihf.xml +++ b/config/steinel/l810-led-ihf.xml @@ -1,19 +1,59 @@ - - - - - - + + + http://www.openzwave.com/device-database/0271:1A75:0001 + images/steinel/l810-led-ihf.png + https://products.z-wavealliance.org/products/2309/ + 50111677301 + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2309/110050438 BDAL L 810 LED IHF SMARTHOME D-GB-F-I-NL.pdf + A high-quality product is cleverly thought through and made from materials that last. Its value also extends beyond today, it has permanency and constancy. The L 810 iHF outdoor SensorLight is an LED uplight and downlight that translates intelligent technology into form and function. For the first time, we have managed to make a light's sensor completely invisible – without compromising on first-class design and technological perfection. For stunning upward and downward lighting. New: optional manual override for 4 hours. + +Smart home included. +The optional Smart Friends box and the free Smart Friends app make it easy to set the L 810 LED iHF Z-Wave via smart phone or tablet. The light can also be switched ON or OFF via app. Other Steinel products can also be interconnected. If you wish, this also works via remote control when you are out. That completes your own light management system. +Along with STEINEL products, Smart Friends solutions from PAULMANN, SCHELLENBERG and ABUS can also integrated. Smart homes from a brand-name provider. + CEPT (Europe) + L 810 LED iHF Z-Wave + Inclusion = Add +To start the light's inclusion mode, briefly press button (8) + +Adding L 810 LED iHF to the Smart Friends system: +1) Download Smart Friends app from the App Store. +2) In the rooms view, activate the edit mode. +3) Select the chosen room and press the "Add device" button. +4) Briefly press the device's button (8) to set the light to inclusion mode. The status LED (12) lights up to show that this mode is selected. +5) The app displays a confirmation message once inclusion has been successfully completed. + Returning L 810 LED iHF to factory settings: + +Please only perform these steps if the main network controller is missing or not working for other reasons. + +1) Briefly press button (8) and directly afterwards keep it pressed for 5 seconds. +2) Status LED (12) briefly flashes to show that the light has been reset. +3) The device is now no longer included in the Z-Wave system and has been returned to factory settings. + Exclusion = Remove +To start the light's exclusion mode, briefly press button (8) + +Removing L 810 LED iHF from the Smart Friends system: +1) In the rooms view, activate the edit mode. +2) Select the device in the chosen room and press the "delete" button. Press delete and follow the instructions in the app. +3) Briefly press the device's button (8) to set the light to exclusion mode. The red status LED (12) lights up to show that this mode is selected. +4) The app displays a confirmation message once exclusion has been successfully completed. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2309/xml + + + + + + Range: 1-99 (default: 99). - - - + + + Range: 5-900 (default: 180 seconds). - - - + + + Range: 2-2000, 0 (default: 2000 lux / potentiometer state if present). 0 - run Learn ambient light sequence. 2-1999 - threshold [lux]. @@ -21,9 +61,9 @@ Value can be controlled via potentiometer (if present on device) - potentiometer value is then used as the default value and any potentiometer movement rewrites the current setting. - - - + + + Range: 0-60, -1 (default: 0 / potentiometer state if present). 0 - off (dim = basic light completely disabled). 1-60 - time [minutes] (enabled in night mode, starts after lamp is switched off after motion detection). @@ -31,39 +71,39 @@ Dim mode is also disabled when local control is disabled as well as in Slave imode. - - - + + + Range: 100-500 (default: 500 cm / potentiometer state if present). Value can be controlled via potentiometer (if present on device) - potentiometer value is then used as default value and any potentiometer movement rewrites the current setting. - - - + + + Range: 2-100 (default: 100 % / potentiometer state if present). Value can be controlled via potentiometer (if present on device) . potentiometer value is then used as the default value and any potentiometer movement rewrites the current setting. - - - + + + Range: 5-120, 0 (default: 0, disabled). 5-120 - Interval for ambient light measuring when lamp is on (lamp switches off shortly and measures). 0 - function is off. - - - + + + Range: 0/1 (default: 1, disabled). When GLOBAL_LIGHT mode is ON - device overrides its own light sensor values and uses Light Report values from any Z-Wave light sensor instead - this has to be configured appropriately to send light automatically. If the last remote light level value is older than 30 minutes, the internal light value is used again until the next external value is receive. - - - - - + + + + + Range: 0-4 (default: 2, Normal mode with lifeline error signalisation). "Stupid mode" - lamp permanently on (bit 2 = 1): - has higher priority then slave mode. @@ -85,14 +125,14 @@ Be careful with this option, device stops using its own motion sensor in Slave and "Stupid" mode. - - - - - - - - + + + + + + + + Behaviour after BASIC OFF (and similar commands). If a transition (even with zero change) with a non-default duration is to be processed, the transition cannot be interrupted by any motion event in any case. Range: 0-209, 255 (default: 10 seconds). @@ -105,9 +145,9 @@ 210-254 - reserved. 255 - Lamp is switched off for TIME (cfg 1). It does not wait for a motion event and works normally via current motion evaluation. - - - + + + Behaviour after BASIC ON (and similar commands). If a transition (even with zero change) with a non-default duration is to be processed, the transition cannot be interrupted by any motion event in any case. Range: 0-209, 255 (default: 255). @@ -122,9 +162,9 @@ 210-254 - reserved 255 - Lamp is switched on for TIME (cfg 1). It does not wait for a motion event and works normally via current motion evaluation. - - - + + + Time limit to stop waiting for motion after timeout of ON_BEHAVIOUR or OFF_ON_BEHAVIOUR (0-209) to prevent staying ON forever when there is no motion. Range: 0-209, 255 (default: 204, 4 hours). @@ -135,9 +175,9 @@ 201..209 - 1 hour (201) to 9 hours (209) in 1-hour resolution. 255 - Never stop waiting before motion. - - - + + + Behaviour after a rapid sequence of BASIC ON and BASIC OFF commands. The intention is to use a much longer timeout value than the time after a single ON command which should then be followed by a short timeout value. Range: 0-209,255 (default: 204, 4 hours). @@ -150,9 +190,9 @@ 210-254 - reserved. 255 - device ignores ON - OFF sequence and uses OFF behavior. - - - + + + Behaviour after a rapid sequence of BASIC OFF and BASIC ON commands. The intention is to use a much longer timeout value than the time after a single OFF command which should then be followed by a short timeout value. Range: 0-209, 255 (default: 204, 4 hours). @@ -167,16 +207,16 @@ 210-254 - reserved 255 device ignores OFF - ON sequence and uses ON behaviour. - - - + + + Time in [100 miliseconds] of maximum delay between BASIC ON and BASIC OFF (and vice versa) to consider this as a sequence. It is typically 1 second, but can be exceptionally longer due to retransmissions and overload - in this case, a longer interval can be allowed (up to 5 seconds). Range: 10-50 (default: 10, 1 scond). - - - + + + Motion disable timeout after BASIC SET to motion endpoint when the internal motion sensor is not used for evaluating the behaviour of the lamp. Events are, however, still transmitted to the Lifeline, and the device can be controlled via remote motion sensors. Range: 0-209,255 (default: 0, disabled). @@ -189,17 +229,15 @@ 210-254 - reserved. 255 - BASIC SET to Motion sensor endpoint ignored, BASIC to root is mapped to relay endpoint, motion sensor still disabled. - - - - - - - - - - - - - + + + + + + + + + + + diff --git a/config/steinel/rs-led-d2.xml b/config/steinel/rs-led-d2.xml index 4e825be1bb..0493446261 100644 --- a/config/steinel/rs-led-d2.xml +++ b/config/steinel/rs-led-d2.xml @@ -1,52 +1,90 @@ - - - + + + http://www.openzwave.com/device-database/0271:1A74:0001 + images/steinel/rs-led-d2.png + https://products.z-wavealliance.org/products/2243/ + Exclusion: Remove + +Removing RS LED D2 from the Smart Friends system: +1 In the rooms view, activate the edit mode. +2. Select the device in the chosen room and press the "delete" button. Press delete and follow the instructions in the app. +3 Briefly press button e on the device to set it to exclusion mode. The red status LED h lights up to show that this mode is selected. +4 The app displays a confirmation message once exclusion has been successfully completed. + + + Sleek, attractive lines. Opting for the RS LED D2 designer indoor luminaire, you'll be giving your home a real designer highlight with pleasant LED illumination. With its stunning looks and intelligent technology, this light provides the last word in stylish home convenience. Once fitted to the wall or ceiling, the high-frequency sensor switches it 'ON' and 'OFF' in complete silence and all automatically. The light is child's play to install and the function settings on the product are easy to understand too. Your neighbours will be amazed. + +Smart home included. +The optional Smart Friends Box and the free Smart Friends app make it easy to set the RS PRO LED D2 Z-Wave via smart phone or tablet. The light can also be switched ON or OFF via app. Other Steinel products can also be interconnected. If you wish, this also works via remote control when you are out. That completes your own light management system. +Along with STEINEL products, Smart Friends solutions from PAULMANN, SCHELLENBERG and ABUS can also integrated. Smart homes from a brand-name provider. + 6772 + RS LED D2 Z-Wave + CEPT (Europe) + Returning RS LED D2 to factory settings: +Please use this procedure only when the network primary controller is missing or otherwise inoperable. +1 Briefly press button e and directly afterwards keep it pressed for 5 seconds. +2 Status LED h briefly flashes to show that the light has been reset. +3 The device is now no longer included in the Z-Wave system and has been returned to factory settings. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2243/RSLEDD2Z-Wave_5spr_110054844_11.04.17.pdf + Inclusion: Add + +Adding RS LED D2 to the Smart Friends system: +1 Download Smart Friends app from the app store. +2 In the rooms view, activate the edit mode. +3 Select the chosen room and press the "Add device" button. +4 Briefly press button 5 on the device to set it to inclusion mode. Status LED 8 lights up to show that this mode is selected. +5 The app displays a confirmation message once inclusion has been successfully completed. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2243/xml + + + - - - + + + Duration of light after motion detection in seconds. - - - + + + 0 - run Learn ambient light sequence. 2000 - is used as daylight (always night mode). Value can also be controlled via potentiometer - potentiometer value is used as the default value. - - - + + + Adjust motion sensitivity from 2-100. Value can also be controlled via potentiometer. Potentiometer value is used as the default value and any potentiometer movement rewrites the current setting. - - - + + + Interval for ambient light measuring when lamp is on ( lamp switches off shortly and measures ). Range 5-120 0=function is off. - - - + + + When GLOBAL_LIGHT mode is ON - device overrides its own light sensor values and uses Light report values from any Z-Wave light sensor instead - this has to be configured appropriately to send light automatically. If the last remote light level value is older than 30 minutes, the internal light value is used again until the next external value is received. - - - + + + Disable local control. Lamp stops using it's own motion sensor in Slave and Stupid mode. - - - - - - - - + + + + + + + + 0 - Lamp is switched off and remains so until any new motion event (local or remote) is received. 1 to 100 (Default) timeout: 1 second (1) to 100 seconds (100) in 1-second resolution. 101 to 200 timeout: 1 minute (101) to 100 minutes (200) 1-minute resolution. @@ -54,19 +92,19 @@ 255 Lamp is switched off for TIME (cfg 1). It does not wait for a motion event and works normally via current motion evaluation. - - - - + + + + Similar than Off behaviour. Available settings: 0-255. 0 - Lamp is switched on and remains so until any new motion event (local or remote) is received. It then works normally via current motion evaluation. Notice - during the day, this mode cannot be ended remotely due to motion events not being transmitted only via local motion sensor if enabled. - - - + + + Available settings: 0-255. 0 No additional waiting for motion. 1 to 100 timeout: 1 second (1) to 100 seconds (100) in 1-second resolution. @@ -74,9 +112,9 @@ 201 to 209 (Default) timeout: 1 hour (201) to 9 hours (209) in 1-hour resolution. 255 Never stop waiting before motion. - - - + + + Available settings: 0-255. 0 - Lamp is switched off and remains so until any new motion event (local or remote) is received. 1 to 100 timeout: 1 second (1) to 100 seconds (100) in 1-second resolution. @@ -84,9 +122,9 @@ 201 to 209 (Default) timeout: 1 hour (201) to 9 hours (209) in 1-hour resolution. 255 device ignores ON - OFF sequence and uses OFF behavior. - - - + + + Available settings: 0-255. 0 - Lamp is switched on and remains so until any new motion event (local or remote) is received. It then works normally via current motion evaluation. @@ -96,15 +134,15 @@ 201 to 209 (Default) timeout: 1 hour (201) to 9 hours (209) in 1-hour resolution. 255 device ignores OFF - ON sequence and uses ON behaviour. - - - + + + Time in [100 miliseconds] of maximum delay between BASIC ON and BASIC OFF (and vice versa) to consider this as a sequence. It is typically 1 second, but can be exceptionally longer due to retransmissions and overload in this case, a longer interval can be allowed (up to 5 seconds ). - - - + + + Available settings: 0-255. 0 (Default) BASIC SET to Motion sensor endpoint ignored, BASIC to root is mapped to relay endpoint, motion sensor still enabled. 1 to 100 timeout: 1 second (1) to 100 seconds (100) in 1-second resolution. @@ -112,17 +150,15 @@ 201 to 209 timeout: 1 hour (201) to 9 hours (209) in 1-hour resolution. 255 BASIC SET to Motion sensor endpoint ignored, BASIC to root is mapped to relay endpoint, motion sensor still disabled - - - - - - - - - - - - - + + + + + + + + + + + diff --git a/config/steinel/xled-home-2.xml b/config/steinel/xled-home-2.xml index 8683fa8242..15431ac5f5 100644 --- a/config/steinel/xled-home-2.xml +++ b/config/steinel/xled-home-2.xml @@ -1,47 +1,87 @@ - - - + + + http://www.openzwave.com/device-database/0271:1A73:0001 + images/steinel/xled-home-2.png + https://products.z-wavealliance.org/products/2290/ + XLED home 2 Z-Wave + 50111677101 + The moveable sensor-switched outdoor floodlight with fully swivelling LED panel in a classy opal look. The XLED home 2 sensor-switched floodlight comes in a sophisticated design. It is not just an eye-catcher, but also a truly talented mover. Thanks to the fully swiveling LED panel, every corner of the entrance area can be illuminated flexibly and as required. The highly efficient LED technology coupled with the opal cover provides maximum lighting comfort. As an individual floodlight or interconnected with the slave version, the innovative new generation of the XLED home success series is available in white, black, graphite and silver. + +Smart home included. +The optional Smart Friends Box and the free Smart Friends app make it easy to set the XLED home 2 Z-Wave via smart phone or tablet. The floodlight can also be switched ON or OFF via app. Other Steinel products can also be interconnected. If you wish, this also works via remote control when you are out. That completes your own light management system. +Along with STEINEL products, Smart Friends solutions from PAULMANN, SCHELLENBERG and ABUS can also integrated. Smart homes from a brand-name provider. + CEPT (Europe) + To put the device into inclusion mode, turn the device's control dial (F) to "Set" and back to "0" within 5 seconds. The status LED (G) lights up to show that this mode is selected. + + +Adding XLED home 2 to the Smart Friends system: +1) Download the Smart Friends app from the app store. +2) In the rooms view, activate the edit mode. +3) Select the chosen room and press the "Add device" button. +4) To put the device into inclusion mode, turn the device's control dial (F) to "Set" and back to "0" within 5 seconds. The status LED (G) lights up to show that this mode is selected. +5) The app displays a confirmation message once inclusion has been successfully completed. + Resetting XLED home 2 to factory settings: + +Please use this procedure only when the network primary controller is missing or otherwise inoperable. + +1) Turn the device's control dial (F) to "Set" and move it to "Reset" within 5 seconds. +2) The status LED (G) briefly flashes to show that the light has been reset. +3) The device is now no longer included in the Z-Wave system and has been returned to factory settings. + To put the device into exclusion mode, turn the device's control dial (F) to "Set" and back to "0" within 5 seconds. The red status LED (G) lights up to show that this mode is selected. + + +Removing XLED home 2 from the Smart Friends system: +1) In the rooms view, activate the edit mode. +2) Select the device in the chosen room and press the "delete" button. Press delete and follow the instructions in the app. +3) To put the device into exclusion mode, turn the device's control dial (F) to "Set" and back to "0" within 5 seconds. The red status LED (G) lights up to show that this mode is selected. +4) The app displays a confirmation message once exclusion has been successfully completed. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2290/XLEDhome2Z-Wave_5spr_110050436_11.04.17.LowRes.pdf + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2290/xml + + + - - - + + + Available settings: 5-900 seconds. - - - + + + 2000 - is used as daylight (always night mode). 0 - run Learn ambient light sequence. 2-1999 lux. - - - + + + Potentiometer State. Available settings: 2-100%. - - - + + + Available settings: 0,5-120. Interval for ambient light measuring when lamp is on (lamp switches off shortly and measures). 0 - function is off. - - - External ambient light value. - - - - - Disable local control. - - - - - - - - + + + External ambient light value. + + + + + Disable local control. + + + + + + + + Off behaviour (timeout). Available settings: 0-209,255. 0 - Lamp is switched off and remains so until any new motion event (local or remote) is received. @@ -51,9 +91,9 @@ 255 Lamp is switched off for TIME (cfg 1). It does not wait for a motion event and works normally via current motion evaluation. - - - + + + On behaviour (timeout). Similar than Off behaviour. Available settings: 0-209,255. @@ -65,9 +105,9 @@ Notice - during the day, this mode cannot be ended remotely due to motion events not being transmitted - only via local motion sensor if enabled. 255 Lamp is switched on for TIME (cfg 1). It does not wait for a motion event and works normally via current motion evaluation. - - - + + + On behaviour time over (timeout). Available settings: 0-209,255. 0 No additional waiting for motion. @@ -76,9 +116,9 @@ 201 to 209 (Default) timeout: 1 hour (201) to 9 hours (209) in 1-hour resolution. 255 Never stop waiting before motion. - - - + + + Available settings: 0-209,255. 0 - Lamp is switched off and remains so until any new motion event (local or remote) is received. 1 to 100 timeout: 1 second (1) to 100 seconds (100) in 1-second resolution. @@ -86,9 +126,9 @@ 201 to 209 (Default) timeout: 1 hour (201) to 9 hours (209) in 1-hour resolution. 255 device ignores ON - OFF sequence and uses OFF behavior. - - - + + + Available settings: 0-209,255. 0 - Lamp is switched on and remains so until any new motion event (local or remote) is received. It then works normally via current motion evaluation. @@ -98,16 +138,16 @@ 201 to 209 (Default) timeout: 1 hour (201) to 9 hours (209) in 1-hour resolution. 255 device ignores OFF - ON sequence and uses ON behaviour. - - - + + + Available settings: 10-50. Time in [100 miliseconds] of maximum delay between BASIC ON and BASIC OFF (and vice versa) to consider this as a sequence. It is typically 1 second, but can be exceptionally longer due to retransmissions and overload - in this case, a longer interval can be allowed (up to 5 seconds). - - - + + + Available settings: 0-209,255. 0 (Default) BASIC SET to Motion sensor endpoint ignored, BASIC to root is mapped to relay endpoint, motion sensor still enabled. 1 to 100 timeout: 1 second (1) to 100 seconds (100) in 1-second resolution. @@ -115,17 +155,15 @@ 201 to 209 timeout: 1 hour (201) to 9 hours (209) in 1-hour resolution. 255 BASIC SET to Motion sensor endpoint ignored, BASIC to root is mapped to relay endpoint, motion sensor still disabled - - - - - - - - - - - - - + + + + + + + + + + + diff --git a/config/stelpro/stzw402.xml b/config/stelpro/stzw402.xml index 6048d8d8ca..bfdfb7de7f 100644 --- a/config/stelpro/stzw402.xml +++ b/config/stelpro/stzw402.xml @@ -1,4 +1,54 @@ - + + + http://www.openzwave.com/device-database/0239:0001:0001 + images/stelpro/stzw402.png + https://products.z-wavealliance.org/products/1603/ + The thermostat may be manually reset to its factory state. +When this is performed, all parameters are reset to their default values and the thermostat is removed (excluded) from the Z-Wave network. +To reset the thermostat to its default state: +- Enter the advanced settings +- Enter the °STELPRO menu (menu 6) +- Navigate to the “def” screen using the UP or DOWN buttons. +- Enter the “def” menu by pressing the UP and DOWN buttons for less than 3 seconds +- Select “yes” and confirm the selection by pressing the UP and DOWN buttons for less than 3 seconds. +If the thermostat was added (included) in a Z-wave network, it will send a ‘’device reset locally’’ notification. +The thermostat will then reset itself. + +Please use this procedure only when the network primary controller is missing or otherwise inoperable. + STZW402+ + Ki, the smart home line-voltage thermostat by Stelpro - STZW402+ +• The very first Z-Wave Plus line voltage thermostat in North America +• Supports 120Vac - 240Vac (50/60 Hz) voltages +• Controls baseboard heaters and convectors up to 4000W +• Easy to use 2 button interface +• Made in Canada +• High precision temperature control +/- 0.1 °C +• Z-Wave Plus certified, works with thousands of other Z-Wave devices +• Brings optimal comfort into your smart home +• Can be integrated into smart home automated scenes +• Local keypad lock +• Displays external temperature +• Adjustable backlight intensity +• Comfort and Eco modes +• Celsius or Fahrenheit display +• Quiet TRIAC operation +• Frost-free warning +• Sleek design to harmonize with any decor +• Backed by Stelpro’s 30 years of experience as a leader in the heating market + U.S. / Canada / Mexico + Make sure the Z-Wave hub is in the include mode (Refer to your Z-Wave hub instruction manual). + +To add (include) the thermostat to a Z-Wave network, enter the Menu 1 (Z-Wave menu) and select “On”. Then press the UP and DOWN buttons to start the inclusion process. During inclusion, “On” will be blinking and the connectivity icon will be animated in an increasing pattern. When the inclusion process has been completed, On will be displayed solid. If an error occurs, “Err” will be displayed for 3 seconds then the screen will revert to “Off” selection. + + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1603/INS_STZW402_1215_EN.pdf + Ki - Electronic Thermostat for Smart Home + Make sure the Z-Wave hub is in the exclude mode (Refer to your Z-Wave hub instruction manual). +To remove (exclude) the thermostat from a Z-Wave network, enter the Menu1 (Z-Wave menu) and select “Off”. Then press the UP and DOWN buttons to start the exclusion process. During exclusion, “Off” will be blinking and the connectivity icon will be animated in an decreasing pattern. When the exclusion process has been completed, Off will be displayed solid. If an error occurs, “Err” will be displayed for 3 seconds then the screen will revert to “On” selection. + + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1603/xml + + diff --git a/config/sunricher/srzv9001k8.xml b/config/sunricher/srzv9001k8.xml new file mode 100644 index 0000000000..83ec844ed3 --- /dev/null +++ b/config/sunricher/srzv9001k8.xml @@ -0,0 +1,53 @@ + + + http://www.openzwave.com/device-database/0330:a305:0300 + images/sunricher/srzv9001k8.png + https://products.z-wavealliance.org/products/3334 + https://www.sunricher.com/media/resources/manual/SR-ZV9001K8-DIM-G4%20Instruction%20V1.pdf + The remote control is a Z-Wave device that can both control other Z-Wave devices and activate scenes in Gateways. + Wall Controller + CEPT (Europe) + SR-ZV9001K8-DIM-G4 + Step 1. Make sure the remote control does not belong to any Z-Wave network, short press any button, if LED +indicator does not turn on, the remote control does not belong to any network, then continue step 2,if LED +indicator turns on, it means the remote control has already been included to a network, please first set the +remote control to exclusion mode (refer to the part "Exclusion" of this manual),then continue step 2. +Step 2. Set primary controller/gateway into inclusion mode (Please refer to your primary controllers manual on +how to turn your controller into inclusion). +Step 3. Press and hold down both buttons and of Group 2 over 3 seconds, LED indicator turns on, the +remote control will be set to inclusion mode, and waiting to be included, after 10s LED indicator blinks 6 times +quickly to indicate successful inclusion. The remote control is a sleepy device, after inclusion it will not enter +into sleepy mode immediately, and will continue activation status for 30s and wait data interaction from the +gateway, the LED indicator will stay solid on, please be patient to wait LED indicator to turn off. + There are two exclusion methods: +Method 1: Exclusion from the primary controller/gateway as follows: +1. Set the primary controller/gateway into exclusion mode (Please refer to your primary controllers manual on +how to set your controller into exclusion). +2. Press and hold down both buttons and of Group 2 over 3 seconds, LED indicator turns on, the remote +control will be set to exclusion mode, and waiting to be excluded, after 7s LED indicator blinks 4 times quickly to +indicate successful exclusion. +Method 2: Factory reset the remote control will force the remote control to be excluded from a network. (please +refer to the part “Factory Reset” of this manual) +Note: Factory reset is not recommended for exclusion, please use this procedure only if the primary +controller/gateway is missing or otherwise inoperable. + Press and hold down both buttons and of Group 2 for over 10 seconds, LED indicator turns on and then blinks 4 times quickly to indicate successful factory reset. + + Initial Configuration file + + + + + + + + + + + + + + + diff --git a/config/sunricher/srzv9001t4dimeu.xml b/config/sunricher/srzv9001t4dimeu.xml index 4405708fb2..37c13e8b39 100644 --- a/config/sunricher/srzv9001t4dimeu.xml +++ b/config/sunricher/srzv9001t4dimeu.xml @@ -1,18 +1,63 @@ - - - - - - - - - - - - + + + + + + + + + diff --git a/config/sunricher/srzv9003t4rgbweu.xml b/config/sunricher/srzv9003t4rgbweu.xml new file mode 100644 index 0000000000..9448957cc1 --- /dev/null +++ b/config/sunricher/srzv9003t4rgbweu.xml @@ -0,0 +1,38 @@ + + + Z-Wave Wall Controller + The Wall controller is a Security Enabled Z-Wave Plus device that can both control other Z-Wave devices and activate scenes in Gateways. + http://www.openzwave.com/device-database/0330:0300:a108 + http://www.sunricher.com/touch-panel-rgbw-z-wave-wall-controller-sr-zv9001t4-rgbw-eu.html + http://www.sunricher.com/ + images/sunricher/srzv9003t4rgbweu.png + https://products.z-wavealliance.org/ProductManual/File?folder=&filename=Manuals/2945/Z-Wave%20Wall%20Controller%20SR-ZV9003T4-RGBW-EU.pdf + Short press the “inclusion/exclusion” button, or press and hold down “ALL ON/OFF” button for over 3 seconds, the wall controller will be set to inclusion mode, and waiting to be included, then LED indicator turns on and blinks 6 times quickly to indicate successful inclusion. + Short press the “inclusion/exclusion” button, or press and hold down “ALL ON/OFF” button for over 3 seconds, the wall controller will be set to exclusion mode, and waiting to be excluded, then LED indicator turns on and shows 3 short blinks and 1 long blink to indicate successful exclusion. + Press and hold down “inclusion/exclusion” button for over 8 seconds, LED indicator blinks slowly to indicate successful factory reset, release “inclusion/exclusion” button,the wall controller will restart automatically. + https://products.z-wavealliance.org/products/2945 + CEPT (Europe) + SR-ZV9003T4-RGBW-EU + + Initial entry based on manufacturer data and test device + + + + + + + false + + + + + + + + + + + + + \ No newline at end of file diff --git a/config/sunricher/srzv9101sachpeu.xml b/config/sunricher/srzv9101sachpeu.xml index a53c2f3dc1..2d3056c0db 100644 --- a/config/sunricher/srzv9101sachpeu.xml +++ b/config/sunricher/srzv9101sachpeu.xml @@ -1,14 +1,45 @@ - - - - - + + Saving state before power failure. Default Not saved. @@ -16,42 +47,42 @@ - - Enable/disable to send the basic report to the Lifeline when the load state changed. + + Enable/disable to send the basic report to the Lifeline when the load state changed. When value set as 1, re-power on the dimmer, it will send Basic report automatically. Default Enabled. - - Fade time (units between 1-127 represent 1-127 seconds. + + Fade time (units between 1-127 represent 1-127 seconds. Units Betwen 128-244 represent minutes, 128 = 1 minute, 129 = 2 minutes. This value has the same function as Duration of Multilevel). Default 1. - - Setting minimum brightness value. + + Setting minimum brightness value. Valid value: 0 - 50, the bigger the value is, the higher the loads minimum brightness is. Note: when configure this value, the value of Multilevel will be configured as 1 automatically so that users can preview the corresponding effect of minimum brightness value - - Setting maximum brightness value. + + Setting maximum brightness value. Valid value: 0 - 100, the bigger the value is, the higher the load maximum brightness is. - - + + Choose MOSFET driving type". Default trailing edge. - - - + + + Choose external switch type. Default normal on/off switch. @@ -59,32 +90,32 @@ - - Enable/disable external switch to be added to and removed from a network. + + Enable/disable external switch to be added to and removed from a network. When enables this function, triple press the external switch within 1.5 seconds to be added to or removed from a net-work. Default Enabled. - - + + Enable/disable to detect load after re-power on (detect load type, minimum brightness, maximum brightness) - - + + Wiring type - - + + Load type @@ -92,45 +123,45 @@ - - + + Enable/disable over current protection (over 1.5A for 20 seconds continuously) - - + + Power automatic report absolute threshold, unit is W. When power changes above the absolute threshold, immediately report current power value - - + + Power automatic report percentage threshold, unit is %. When power changes above the percentage threshold, immediately report current power value - - - + + + Power metering automatic report time cycle, unit is second. Valid time cycle value: 5-2678400, when set as 0 report function is disabled - - - + + + Energy metering automatic report time cycle, unit is second. Valid time cycle value: 5-2678400, when set as 0 report function is disabled - - - + + + Voltage metering automatic report time cycle, unit is second. Valid time cycle value: 5-2678400, when set as 0 report function is disabled - - - + + + Current metering automatic report time cycle, unit is second. Valid time cycle value: 5-2678400, when set as 0 report function is disabled @@ -139,9 +170,9 @@ - - - + + + diff --git a/config/sunricher/zv9101.xml b/config/sunricher/zv9101.xml index d4ef6ebe63..d8cefc50a9 100644 --- a/config/sunricher/zv9101.xml +++ b/config/sunricher/zv9101.xml @@ -1,50 +1,75 @@ - - - - - + + Saving state before power failure. Default Not saved. - - Enable/disable to send the basic report to the Lifeline when the load state changed. + + Enable/disable to send the basic report to the Lifeline when the load state changed. When value set as 1, re-power on the dimmer, it will send Basic report automatically. Default Enabled. - - Fade time (units between 1-127 represent 1-127 seconds. + + Fade time (units between 1-127 represent 1-127 seconds. Units Between 128-244 represent minutes, 128 = 1 minute, 129 = 2 minutes. This value has the same function as Duration of Multilevel). Default 1. - - Setting minimum brightness value. + + Setting minimum brightness value. Valid value: 0 - 50, the bigger the value is, the higher the loads minimum brightness is. Note: when configure this value, the value of Multilevel will be configured as 1 automatically so that users can preview the corresponding effect of minimum brightness value - - + + Choose MOSFET driving type". Default trailing edge. - - Enable/disable external switch to be added to and removed from a network. + + Enable/disable external switch to be added to and removed from a network. When enables this function, triple press the external switch within 1.5 seconds to be added to or removed from a net-work. Default Enabled. @@ -55,9 +80,9 @@ - - - + + + diff --git a/config/telldus/tzwp100.xml b/config/telldus/tzwp100.xml index 1b27bb3e09..6910010f5c 100644 --- a/config/telldus/tzwp100.xml +++ b/config/telldus/tzwp100.xml @@ -1,32 +1,51 @@ - - - + + + http://www.openzwave.com/device-database/0176:0001:0003 + images/telldus/tzwp100.png + https://products.z-wavealliance.org/products/1536/ + Tripple click the button on the device + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1536/manual.pdf + The slim design makes this plugin switch fit almost everywhere. You can even have two switches connected into a standard 2-way wall outlet at the same time. It has a repeater function for the Z-Wave network so you can extend the range of your smart home system. Easy to install and to include in the powerful Telldus Live! system. Control lights and other electronic devices up to 2300 W (resistive load). Option to turn off indication LED. 500 chip, Z-Wave Plus. + Plug-in Switch (Schuko) + CEPT (Europe) + Tripple click the button on the device + TZWP-100 + Press and hold the button until the LED starts flashing white (approx. 6 seconds). +Press the button once more, short. + +Please note! Only use the reset procedure when the primary controller is missing or inoperable. + + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1536/xml + + + - - - + + + Number of minutes before it shutdown automatically (0 = disabled). - - - + + + Define how the plug will react after the power supply is back on. - - - - - - + + + + + + Set the intensity of the LED indicator (0-100). - - - - - - - - - + + + + + + + + + diff --git a/config/telldus/tzwp102.xml b/config/telldus/tzwp102.xml index 0a42f06d50..c96abd0054 100644 --- a/config/telldus/tzwp102.xml +++ b/config/telldus/tzwp102.xml @@ -1,76 +1,106 @@ - - + + + http://www.openzwave.com/device-database/0176:0003:0003 + images/telldus/tzwp102.png + https://products.z-wavealliance.org/products/2892/ + TZWP-102 + CEPT (Europe) + Plug-in Switch Mini + 1. Set the Z-Wave network main controller into removing mode. +2. Short press Z-button twice. +3. The LED keep blink to the end of remove exclusion, If the remove for exclusion is successful, The LED will keep slow flash, Otherwise, LED will be in power indication mode. + + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2892/TZWP-102_technical-manual.pdf + Reset Smart Plug to factory Default: +1. Make sure that the Smart Plug has been connected to the power supply. +2. Press and hold the Z-button for 5 seconds. +3. If holding time is more than one second, the LED will blink faster and faster. If holding time is more than 5 seconds, the LED will be solid for 3 seconds to indicate that the resetting is successful. Otherwise, repeat step 2. + + Use this procedure only in the event that the network primary controller missing or otherwise inoperable. + 1. Set the Z-Wave network main controller into learning mode. +2. Short press the Z-button twice +3. The LED keep blink to the end of add inclusion, If the add for inclusion is successful, LED will turn on within 2 seconds and Then will be in power indication mode, Otherwise, The LED will keep slow flash. + + Smart Plug can be included and operated in any Z-Wave network with other Z-Wave certified devices from other manufacturers and/or other applications. All non-battery operated nodes within the network will act as repeaters regardless of vendor to increase reliability of the network. +Smart Plug is also a security Z-Wave device and supports the Over The Air (OTA) feature for the product’s firmware upgrade. + + + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2892/xml + + + - - - + + + If the current exceeds 16A for more than 5 sec, the load will be switched off. Default 1. - - - - - + + + + + Define how the plug will react after the power supply is back on. Default 0. - - - - - - + + + + + + Smart Plug can send notifications to associated devices in Lifeline when the status of the plug is changed. Default 1. - - - - - - + + + + + + Configure LED mode. Default 0. - - - - - + + + + + This parameter will send a power report automatically if the power value changes of x W (Watts) compared to the last report. Default 50. - - - + + + This parameter will send a power report automatically if the power value changes of x % compared to the last report. Default 10. - - - + + + This parameter defines the period of sending power reports. Default 600. 0=Disabled, 5-2678400 seconds - - - + + + This parameter defines the period of sending energy reports. Default 3600. 0=Disabled, 5-2678400 seconds - - - + + + This parameter defines the period of sending voltage reports. Default 0. 0=Disabled, 5-2678400 seconds - - - + + + This parameter defines the period of sending current reports. Default 0. 0=Disabled, 5-2678400 seconds - - - - - - - - + + + + + + + + diff --git a/config/thermofloor/heatit056.xml b/config/thermofloor/heatit056.xml index 191430e998..bada9b193f 100644 --- a/config/thermofloor/heatit056.xml +++ b/config/thermofloor/heatit056.xml @@ -1,7 +1,42 @@ +--> + + http://www.openzwave.com/device-database/019B:0202:0003 + images/thermofloor/heatit056.png + https://products.z-wavealliance.org/products/3065/ + Adding the device: +To add the thermostat to your home automation gateway, press Center (confirm) for 10 seconds. The display will show OFF. Press Right (down) 4 times till you see Con in the display. Now start add device in your home automation software. Start adding mode by pressing Center (confirm) button for approximately 2 seconds. The icon will appear in the display. Adding Mode is indicated in the display by some “circling” LED segments in the display until the timeout occurs after 20 seconds or the module has been added in the network. Confirmation will show Inc/EcL in the display. If adding fails, Err (error) will appear. + Z-TRM2fx + Heatit Z-TRM2fx is equipped with a single pole switch and it fits most System 55 frames (Elko RS16, Schneider Exxact, Gira, Jung etc.). The thermostat can withstand a load of max 13A /2900W at 230V. At higher loads the thermostat must control a contactor. The thermostat may be connected to two wired external sensors. +The thermostat has the capacity of up to 8 associations (relays, wall plugs etc.). +The thermostat is designed for electrical heating. +FEATURES +Floor sensor +External room sensor +Temperature limiter +Weekly program/setback via gateway or pilot wire +Multilevel sensor command class +Firmware updates (OTA) +Power metering +LED-diode +Can be used in connection with different NTC-sensors +Lock mode/child lock +Calibration +8 associations +Supports encryption mode: S0, S2 Authenticated Class, S2 Unauthenticated Class + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3065/Manual_Heatit_Z-TRM2fx_ENG_3.1.pdf + Removing the device: +To remove the thermostat to your home automation gateway, press Center (confirm) for 10 seconds. The display will show OFF. Press Right (down) 4 times till you see Con in the display. Now start remove device in your home automation software. Start removing mode by pressing Center (confirm) button for approximately 2 seconds. The icon will appear in the display. Removing Mode is indicated in the display by some “circling” LED segments in the display until the timeout occurs after 20 seconds or the module has been removed in the network. Confirmation will show Inc/EcL in the display. If removing fails, Err (error) will appear. + CEPT (Europe) + By pressing buttons Right and Center (down and confirm) for 20 seconds, the thermostat will perform a complete factory reset. +NB! Please use this procedure only when the primary controller/ gateway is missing or otherwise inoperable. + Heatit Z-TRM2fx + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3065/xml + + @@ -36,20 +71,20 @@ https://products.z-wavealliance.org/products/3065 - + Set operation mode - + Set sensor mode - + Floor sensor type (10K NTC Default) diff --git a/config/vision/zd2102.xml b/config/vision/zd2102.xml index 59fd637e5c..d8b3dbe533 100644 --- a/config/vision/zd2102.xml +++ b/config/vision/zd2102.xml @@ -1,9 +1,9 @@ - + http://www.openzwave.com/device-database/0109:0101:2001 images/vision/zd2102.png https://products.z-wavealliance.org/products/111/ - Door Contact + Door Sensor http://www.visionsecurity.com.tw/ha_contact_us.html ZD 2102 http://www.visionsecurity.com.tw/ha_products_page2_154_159.html @@ -16,6 +16,8 @@ Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/779/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/848/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/988/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1705/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2823/xml https://products.z-wavealliance.org/products/779/ ZD2102IN @@ -29,9 +31,12 @@ Auto Wake Up: The wakeup interval is user settable from 10 minutes to 1 week us For “Exclusion” (removing from) a network: Put the Z-Wave™ network controller into “exclusion” mode, following its instructions. To delete the ZD2102-5 from your controller press the program switch of ZD2102-5 for at least 1 second to be excluded. Note: All user and network settings will be cleared and the device reset to factory setting defaults when the device is excluded. For “Inclusion” (adding to) a network: Put the Z-Wave™ network controller into “inclusion” mode following its instructions. To add the ZD2102-5 to your controller press the program switch of ZD2102-5 to send the Node Information Frame (NIF). After sending NIF, the network controller will send the auto inclusion request; otherwise, ZD2102-5 will go to sleep after 15 seconds. CEPT (Europe) - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/988/ZD 2102_04162014 - 500系列.pdf + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2823/ZD 2102-5_R4_20170913 (RED).pdf ZD2102EU-5 - Factory Default Reset: Trigger the rear cover switch to send the Alarm Report and trigger the reed switch (close & open) 5 times in 10 seconds, ZD2102-5 will send the “Device Reset Locally Notification” command and reset to the factory default condition. + Factory Default Reset: Trigger the rear cover switch to send the Alarm Report and trigger the reed switch (close & open) 5 times in 10 seconds, ZD2102-5 will send the “Device Reset Locally Notification” command and reset to the factory default condition. Please use this procedure only when the network primary controller is missing or otherwise inoperable! + https://products.z-wavealliance.org/products/2823/ + ZD2102JP-5 + U.S. / Canada / Mexico / Japan diff --git a/config/vision/zd2105us5.xml b/config/vision/zd2105us5.xml index 5a62456a16..55d1e76ce0 100644 --- a/config/vision/zd2105us5.xml +++ b/config/vision/zd2105us5.xml @@ -1,4 +1,25 @@ - + + + http://www.openzwave.com/device-database/0109:2201:2022 + images/vision/zd2105us5.png + https://products.z-wavealliance.org/products/1727/ + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1727/ZD 2105-5_V1-20160329.pdf + ZD2105US-5 + *If the cover of sensor is removed, the tamper switch will send signal according the Status/Signal table, and the LED will go solid and ZD2105 will send “Wake Up Notification” after 10 seconds. If ZD2105 received “Wake Up No More Information” command, the red LED will go off. If ZD2105 did not receive”Wake Up No More Information” command after 10 seconds the red LED will go off. + +*Use “Wake Up” command to set up the awaking time and send the wake up notification to controller. User can use command to change the auto wake up from 10 minutes to 1 week, Interval increment is 3 minutes. + The ZD2105US-5 Recessed Door sensor can be used in any Z-Wave network, to detect the opening or closing of a door or window. Special Design can fit most door/window frames. This sensor monitors door/window and send Z-Wave™ signal when door or window is opened and closed. Recessed Door Sensors are easily installed inside the door or window frame to keep the sensor hidden from view. When the device is securely included into Z-Wave network, above communication will be encrypted. + For “Exclusion” from (removing from) a network: Put the Z-Wave™ Interface Controller into “exclusion” mode, and following its instruction to delete the ZD2105 from your controller. Press the Program Switch of ZD2105 for 1 second at least to be excluded. Note: All user and network settings will be cleared and the device reset to factory setting defaults when the device is excluded. + U.S. / Canada / Mexico + For “Inclusion” in (adding to) a network: Put the Z-Wave™ Interface Controller into “inclusion” mode, and following its instruction to add the ZD2105 to your controller. To get in the “inclusion” mode, please press the Program Switch of ZD2105 for sending the NIF. After sending NIF, Z-Wave will send the auto inclusion; otherwise, ZD2105 will go to sleep after 20 seconds. + Door Sensor + *open the cover to send the Alarm Report and trigger the reed switch (close & open) 10 times in 10 seconds, ZD2105 will send the “Device Reset Locally Notification” command and reset to the factory default. + * Please use this procedure only in the event that the network primary controller is missing or otherwise inoperable. + + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1727/xml + + diff --git a/config/vision/zd2301.xml b/config/vision/zd2301.xml index 074c3c4cac..d53fb3bca3 100644 --- a/config/vision/zd2301.xml +++ b/config/vision/zd2301.xml @@ -1,26 +1,31 @@ - + http://www.openzwave.com/device-database/0109:1F20:201F - images/vision/zd2301.png - https://products.z-wavealliance.org/products/1334/ - Awake Mode: -Press the Program SW, the LED will flash one time and ZD2301 will send “Wake Up Notification” after 5 seconds. If ZD2301 received “Wake Up No More Information” command then the ZD2301 will go to sleep or it will wait 10 seconds then go to sleep. It will precede all the commands after sending the “Wake Up Notification” - + images/zipato/zd2301.png + https://products.z-wavealliance.org/products/2346/ + Press the Program SW, the LED will flash one time and ZD2301 will send “Wake Up Notification” after 5 seconds. If ZD2301 received “Wake Up No More Information” command then the ZD2301 will go to sleep or it will wait 10 seconds then go to sleep. It will precede all the commands after sending the “Wake Up Notification” CEPT (Europe) - Factory Default Reset: -*Open the rear cover to send the Alarm Report and then press the program switch 10 times in 10 seconds, ZD2301 will send the “Device Reset Locally” command and reset to the factory default. -*Please use this procedure only in the event that the network primary controller is missing or otherwise inoperable. - 4 in 1 Door Sensor - 5. For “Exclusion” from (removing from) a network: Put the Z-Wave™ Interface Controller into “exclusion” mode, and following its instruction to delete the ZD2301 from your controller. Press the program switch of ZD2301 for 1 second at least to be excluded. -Note: All user and network settings will be cleared and the device reset to factory defaults when the device is excluded. + All user and network settings will be cleared and the device reset to factory +defaults when the device is excluded. + +Please use this procedure only in the event if the network +controller is missing or is otherwise inoperable. + Zipato 4 in 1 Door Sensor + Put the Z-WaveTM Interface +Controller into “exclusion” mode, and following its instruction to delete the ZD2301 from your controller. Press the program switch of ZD2301 for 1 second at least to be excluded. + Door/Window, humidity, temperature and luminance sensor. +* Primarily used as dry contact door/window sensor. +* Very low power consumption +* LED indicator +* Easy installation - Vision’s wireless 4 in 1 Multi-Sensor (door window contact sensor, humidity sensor, temperature sensor, and light sensor) of the home security device. This sensor is a Z-Wave™ enabled device two-way (interoperable, RF mesh networking technology) and is fully compatible with any Z-Wave™ enabled network and its security framework. Every main powered Z-Wave enabled device acts as a signal repeater and multiple devices result in more possible transmission routes which helps eliminate “RF dead-spots” -This door sensor sends Z-Wave™ signal when door or window is opened and closed or humidity, temperature, luminous change. When the device is secure included into Z-Wave network, above communication will be encrypted. Security enabled_ Z-Wave controller must be used to fully utilize the product. - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1334/ZD 2301-5_20150603.pdf - 4. For “Inclusion” in (adding to) a network: Put the Z-Wave™ Interface Controller into “inclusion” mode, and following its instruction to add the ZD2301 to your controller. To get in the “inclusion” mode, the distance between sensor and controller is suggested to be in one meter. Press the program switch of ZD2301 for sending the NIF. After sending NIF, Z-Wave will send the auto inclusion; otherwise, ZD2301 will go to sleep after 20 seconds. - ZD2301EU-5 + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2346/zp2301.pdf + Put the Z-WaveTM Interface Controller into +“inclusion” mode, and following its instruction to add the ZD2301 to your controller. To get in the “inclusion” mode, the distance between sensor and controller is suggested to be one meter. Press the program switch of ZD2301 for sending the NIF. After sending NIF, Z-Wave will send the auto inclusion; otherwise, ZD2301 will go to sleep after 20 seconds. + vs-zd2301.eu Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1334/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2346/xml diff --git a/config/vision/zl7431.xml b/config/vision/zl7431.xml index 29b70bb95f..29778eaf46 100644 --- a/config/vision/zl7431.xml +++ b/config/vision/zl7431.xml @@ -1,18 +1,29 @@ - - - + + + http://www.openzwave.com/device-database/0109:0C02:200C + images/vision/zl7431.png + https://products.z-wavealliance.org/products/1792/ + U.S. / Canada / Mexico + Vision ZL7431US In-wall 1 relay switch + ZL7431US + ZL7431US + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1792/xml + + + - - - - - - - - - - - - - + + + + + + + + + + + + + diff --git a/config/vision/zl7432us.xml b/config/vision/zl7432us.xml new file mode 100644 index 0000000000..55ce7dc7c5 --- /dev/null +++ b/config/vision/zl7432us.xml @@ -0,0 +1,14 @@ + + + http://www.openzwave.com/device-database/0109:1717:2017 + images/vision/zl7432us.png + https://products.z-wavealliance.org/products/1807/ + Vision Security ZL7432US In-wall 2 relays switch + ZL7432US + U.S. / Canada / Mexico + ZL7432US In-wall 2 relays switch + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1807/xml + + + diff --git a/config/vision/zm1602eu5.xml b/config/vision/zm1602eu5.xml index 1140fcf3e0..389d05efbe 100644 --- a/config/vision/zm1602eu5.xml +++ b/config/vision/zm1602eu5.xml @@ -1,5 +1,32 @@ - - + + + http://www.openzwave.com/device-database/0109:0908:2009 + images/vision/zm1602eu5.png + https://products.z-wavealliance.org/products/2901/ + U.S. / Canada / Mexico + ZM1602US-5 + Put the Z-Wave™ Interface Controller into “inclusion” mode, and following its instruction to add the ZM 1602 to your controller. To get in the “inclusion” mode, the distance between siren and controller is suggested to be in one meter. Open the bracket and press the program switch of ZM 1602 for 1 second at least & release to be included. After setting, the LED Setting Lighting should go off, + Features: + +*Loud audible alarm>105dB@1 meter +*LED strobe lighting +*Low battery detection +*Siren for Battery Back-Up +*100ft line of sight +*LED Status Indicator +*Operating temp: -15oC~60oC +*Working Voltage: 6V +*Dimensions: 116*77*40mm + + Wireless Siren + removing the back cover of the ZM1602 to get into “Awake” mode, + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2901/ZM1602-5 Siren_R3_20180417 (RED).pdf + Set up the Z-Wave™ Interface Controller into “exclusion” mode, and following its instruction to delete the ZM 1602 from your controller. Press the Tamper Switch of ZM 1602 for 1 second at least & release to be excluded. + This device can’t be reset manually. It is reset to factory defaults when it is excluded. Please use this procedure only when the network primary controller is missing or otherwise inoperable. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2901/xml + + diff --git a/config/vision/zp3102.xml b/config/vision/zp3102.xml index 98a98cdcf2..984102427d 100644 --- a/config/vision/zp3102.xml +++ b/config/vision/zp3102.xml @@ -1,4 +1,4 @@ - + http://www.openzwave.com/device-database/0109:0201:2002 images/vision/zp3102.png @@ -16,6 +16,7 @@ Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/804/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/847/xml Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1070/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1702/xml ZP 3102 https://products.z-wavealliance.org/products/728/ @@ -27,15 +28,15 @@ https://products.z-wavealliance.org/products/847/ Japan ZP3102JP - https://products.z-wavealliance.org/products/1070/ - ZP3102EU-5 + https://products.z-wavealliance.org/products/1702/ + ZP3102US-5 Remove the rear cover to wake up the device, or set the wake up interval time from 10 minutes to 1 week. The battery will be drained quickly if you fail to replace the cover after using that method to wake up the device. Removing the rear cover to wake up the device. Press Program Switch 10 times within 10 seconds, ZP3102 will go back to factory default. (This is to be used only in the case of the primary controller being inoperable or otherwise unavailable.) - CEPT (Europe) + CEPT (Europe) / U.S. / Canada / Mexico Put the Z-Wave Interface Controller into 'inclusion' mode, and follow its instructions to add the ZP3102 to your Z-Wave network. For a successful inclusion, it is suggested to have the sensor and your Z-Wave controller about one meter apart. Press the Program Switch of the ZP3102 (refer to the manual for the location of the program switch) ready the ZP3102 for inclusion into the Z-Wave network. If inclusion does not take place or is unsuccessful within 20 seconds, the ZP3102 will go to sleep; if this happens, simply repeat pressing the program switch to try again. Put the Z-Wave Interface Controller into “exclusion” mode, and following its instruction to delete the ZP3102 to your Z-Wave network. Press the Program Switch of ZP3102 once to be excluded. The LED on the ZP3102 should start to flash. - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1070/20140725 - (Z-WAVE CERTIFICATION) ZP 3102-5 PIR_20140722_500 Series.pdf + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1702/ZP 3102-5 PIR_R3_500 Series_20150724.pdf - - - The LED on the TZ56D will by default, turn ON when the load attached is turned OFF. To make the LED turn ON when the load attached is turned ON instead, set parameter to a value of 1. - - - Stated in the above form,switch by default value is 1,when the value is 0,switch memory function not open; when the value is 1,open switch memory function - - - To change the top of the switch to OFF and the bottom of the switch ON , set parameter 4 to 1. - - - The TZ56-D will flicker its LED when it is transmitting to any of its 4 groups. This flickering can be set to not flicker at all (set to 0), to flicker the entire time it is transmitting (set to 1), or to flicker for only 1 second when it begins transmitting (set to 2). By default, the TZ56D is set to flicker for only 1 second. - - - Setting this parameter to the value of 1 will stop the TZ56D from transmitting to devices that are associated into Group 4. - - + + + The LED on the TZ56D will by default, turn ON when the load attached is turned OFF. To make the LED turn ON when the load attached is turned ON instead, set parameter to a value of 1. + + + Stated in the above form,switch by default value is 1,when the value is 0,switch memory function not open; when the value is 1,open switch memory function + + + To change the top of the switch to OFF and the bottom of the switch ON , set parameter 4 to 1. + + + The TZ56-D will flicker its LED when it is transmitting to any of its 4 groups. This flickering can be set to not flicker at all (set to 0), to flicker the entire time it is transmitting (set to 1), or to flicker for only 1 second when it begins transmitting (set to 2). By default, the TZ56D is set to flicker for only 1 second. + + + Setting this parameter to the value of 1 will stop the TZ56D from transmitting to devices that are associated into Group 4. + + diff --git a/config/wenzhou/tz68.xml b/config/wenzhou/tz68.xml index 6c20345ce6..bb6e680c9d 100644 --- a/config/wenzhou/tz68.xml +++ b/config/wenzhou/tz68.xml @@ -1,8 +1,8 @@ - + http://www.openzwave.com/device-database/0118:0002:0003 images/wenzhou/tz68.png - https://products.z-wavealliance.org/products/1423/ + https://products.z-wavealliance.org/products/1952/ Smart Plug in Switch 1. Have Z-Wave controller with exclusion mode @@ -10,7 +10,7 @@ 1. Have Z-Wave controller with inclusion mode 2. Press the socket on/off button three times within 1.5 seconds to be included to the controller - TZ68G + TZ68CN 1. This plug-in ON/OFF switch in a transceiver which is a Z-Wave enabled device and is fully compatible with any Z-Wave enabled network. 2. Each socket is designed to act as a repeater. Repeaters will re-transmit the RF signal to ensure the signal to ensure that the signal is received by its intended destination. 3. You can use the button in the socket to include/exclude, manually on/off or act as a indicator. You can use it to turn on/off appliance remotely via smart home or computer. @@ -18,10 +18,12 @@ 2. then within 1 second to press and hold on for 5 seconds until the socket button LED is off, reset to factory default successfully 3. Use this procedure only in the event that the network primary controller is missing or otherwise inoperable - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1423/TZ68G User Manual.pdf - CEPT (Europe) + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1952/TZ68 User Manual.pdf + CEPT (Europe) / Brazil / China Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1423/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1948/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1952/xml diff --git a/config/wenzhou/tz69.xml b/config/wenzhou/tz69.xml index 2f3c090aa8..40d40b64c6 100644 --- a/config/wenzhou/tz69.xml +++ b/config/wenzhou/tz69.xml @@ -1,41 +1,65 @@ - - - - - - Defines the behavior of the LED. - - - - - - - - - - If the setting is configured for 1 hour (value=720), the TZ69E will report its instant power consumption every 1 hour. - - - If the setting is configured for 1 hour (value=6), the TZ69E will report its accumulated power consumption (kWh) every 1 hour. - - - - - - - - - - - - - - - - + + + Defines the behavior of the LED. + + + + + + + + + + If the setting is configured for 1 hour (value=720), the TZ69E will report its instant power consumption every 1 hour. + + + If the setting is configured for 1 hour (value=6), the TZ69E will report its accumulated power consumption (kWh) every 1 hour. + + + + + + + + + + + + + + diff --git a/config/widom/DRY.xml b/config/widom/DRY.xml new file mode 100644 index 0000000000..9875ec345e --- /dev/null +++ b/config/widom/DRY.xml @@ -0,0 +1,116 @@ + + + https://www.widom.it/it/smart-dry-contact-switch/ + https://www.widom.it/wp-content/uploads/2019/03/Widom_Dry_Contact_EN.pdf + DRY + WiDOM Smart Dry Contact + WiDOM Smart Dry Contact is an ON\\OFF device based on latching relay and can be used as both a local and remote switch. + CEPT (Europe) + + Initial Metadata + + + + + + + + Defines which sequences of clicks on the external switch control the load + 0 - Local Control disabled + 1 - 1 click controls the local load + 2 - 2 clicks control the local load + 4 - 3 clicks control the local load + 7 - The load connected to the Channel 1 can be controlled using 1 click, 2 clicks or 3 clicks + Default value: 7 + Other options: + To control the load with 1 click and 2 clicks -> Parameter value must be 1 + 2 =3 + To control the load with 1 click and 3 clicks -> Parameter value must be 1 + 4 =5 + To control the load with 2 clicks and 3 clicks -> Parameter value must be 2 + 4 =6 + + + + Value used for devices belonging to Group 2 when the external switch receives 1 Click + 1-99 : Dimming purpose + 0 : OFF + -1 : ON + 100 : (Default Value) The same value of dry contact status + + + + Value used for devices belonging to Group 3 when the external switch receives 2 + 1-99 : Dimming purpose + 0 : OFF + -1 : ON + 100 : (Default Value) The same value of dry contact status + + + + Value used for devices belonging to Group 4 when external switch receives 3 Clicks + 1-99 : Dimming purpose + 0 : OFF + -1 : ON + 100 : (Default Value) The same value of dry contact status + + + + Defines the time after which the relay is switched OFF + 1 - 32000 : Number of time units (see parameter No.15) after which the dry contact is switched OFF + 0 : (Default Value) Timer disabled + + + + Defines the time after which the relay is switched ON + 1 - 32000 : Number of time units (see parameter No.15) after which the dry contact is switched ON + 0 : (Default Value) Timer disabled + + + + Defines the time unit used for parameters No.10 and No.11. (Default Value: 1 ) + + + + + + Defines the Scene Activation Set value sent to the Lifeline group with 1 Click on the external switch (Default Value: 0 ) + 1 - 255 : Value sent to the Lifeline group + 0 : (Default Value) No value is sent + + + + + Defines the Scene Activation Set value sent to the Lifeline group with 2 Clicks on the external switch (Default Value: 0 ) + 1 - 255 : Value sent to the Lifeline group + 0 : (Default Value) No value is sent + + + + + Defines the Scene Activation Set value sent to the Lifeline group with 3 Clicks on the external switch (Default Value: 0 ) + 1 - 255 : Value sent to the Lifeline group + 0 : (Default Value) No value is sent + + + + + Defines the status of the device following a restart (Default Value: 3 ) + + + + + + Defines the type of external switch connected to the device (Default Value: 1 ) + + + + + + + + + + + + + + + diff --git a/config/widom/WDS.xml b/config/widom/WDS.xml index af205cb151..0906e42165 100644 --- a/config/widom/WDS.xml +++ b/config/widom/WDS.xml @@ -1,4 +1,23 @@ - + + + http://www.openzwave.com/device-database/0149:0504:1214 + images/widom/WDS.png + https://products.z-wavealliance.org/products/1569/ + 0504 + Only a controller can remove a device from the network. WiDom Universal Double Switch is compatible with all Z-Wave certified controllers. After the exclusion procedure has been activated by the controller, the device can be removed, putting it in Exclusion Mode by three consecutive clicks on the (B) button or on the external switch, when available. + The device can be reset ot the factory reset by six consecutive clicks. This procedure shuld be used only if the primary controller is missing or inoperable. + If the device is not included into a Z-Wave network, a single click on the (B) button or on one of the external switches will launch the process of traditional inclusion. If the device inclusion procedure does not start within 2 seconds, the Network Wide Inclusion network will be launched lasting a variable amount of time between 15-30 seconds. + Universal Double Switch is the ON/OFF smallest control device in the world designed to independently control two separate loads, suited for use as both a local and remote switch. Similarly to the other WiDom “in wall” devices, it can be fully integrated into pre-existing systems and configured to associate configurable behaviours to a specific number of clicks, in full integration with the Z-Wave home automation ecosystem. +Each of its two channels features an integrated consumption measurement device. The Universal Double Switch also boasts the lowest energy consumption on the market. +At the same time, it is completely configurable so that it can adapt to the most varied needs while also being ready to be used without needing additional configurations in order to operate. +Thanks to the framework developed by WiDom, the various types of “events” on the “External Switch” can be recognised and associated to actions to be performed on the device, on any associated devices, on all devices on the network. + CEPT (Europe) + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1569/Widom Double Relay_EN.pdf + WDS + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1569/xml + + diff --git a/config/zipato/RGBBulb.xml b/config/zipato/RGBBulb.xml index 18138dcfc2..1a1aeda989 100644 --- a/config/zipato/RGBBulb.xml +++ b/config/zipato/RGBBulb.xml @@ -1,17 +1,19 @@ - + http://www.openzwave.com/device-database/0131:0002:0002 images/zipato/RGBBulb.png - https://products.z-wavealliance.org/products/1132/ + https://products.z-wavealliance.org/products/2034/ Place your Z-Wave primary controller into inclusion mode by following the controller manufacturer's instructions. Place the light bulb into inclusion mode by gently tapping the light bulb. The light bulb will shine green to indicate a successful activation of inclusion mode. - rgbwe27zw - CEPT (Europe) + rgbwe27zw.us + CEPT (Europe) / U.S. / Canada / Mexico A factory default reset is performed when the bulb is excluded -from a Z-wave network. +from a Z-Wave network. + +Please use this procedure only when the network primary controller is missing or otherwise inoperable. Zipato RGBW BULB has 5 color channels available for you to adjust: RED, GREEN, BLUE, WARM WHITE and COLD WHITE. Zipato RGBW BULB can be used to add color to your home or just to lighten it up in @@ -21,10 +23,11 @@ any white color tone you desire. Place the light bulb into exclusion mode by gently tapping the light bulb. The light bulb will shine green to indicate a successful activation of exclusion mode. - https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1132/Zipato RGBW Bulb Manual (EN) (1) (1).pdf + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2034/rgbwe27zw - Zipato RGBW Bulb User Manual v1.1.pdf Zipato RGBW light bulb Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1132/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2034/xml diff --git a/config/zipato/pan04.xml b/config/zipato/pan04.xml index 0027c1ee02..9141ecba00 100644 --- a/config/zipato/pan04.xml +++ b/config/zipato/pan04.xml @@ -1,8 +1,29 @@ - +--> + + http://www.openzwave.com/device-database/0131:0012:0001 + images/zipato/pan04.png + https://products.z-wavealliance.org/products/2421/ + This product can be operated in any Z-Wave network with other Z-Wave certified devices from other manufacturers. All non-battery operated nodes within the network will act as repeaters regardless of vendor to increase reliability of the network. Micromodule Switch Double is a transceiver which is a Z-Wave Plus enabled device and is fully compatible with any Z-Wave enabled network. Mini size design allow the module to be easily hidden into the wall box which is good for the house decoration. There are many kinds of application for using the module to switch AC power ON and OFF, one of which is the light control. The new smart relay calibration technology can reduce the inrush current caused by the load and let the module work perfectly with many kinds of light like incandescent, fluorescent and LED light. This Micromodule is able to detect Instant power wattage and overload wattage (current 7.5A) of connected light or appliances. When detecting overload state, the switch will be disabled and its ON/OFF button will be locked during which LED will flash repeatedly. Unplugging and reconnecting the Module will reset its overload condition to normal status. + Use this procedure only in the event that the network primary controller is lost or otherwise inoperable. +Pressing INCLUDE_BUTTON three times within 2 seconds will enter inclusion mode. +Within 1 second, press On/Off button again for 5 seconds until LED is off. +IDs are excluded. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2421/ph-pan04 - Zipato MM Switch Double User Manual 165x295mm v1.5.pdf + ph-pan04.eu + Micro Module Switch Double w.meter + Have Z-Wave Controller entered inclusion mode by following the instructions provided by the controller manufacturer. +Pressing INCLUDE_BUTTON threetimes within 2 seconds will enter inclusion mode. + Have Z-Wave Controller entered exclusion mode by following the instructions provided by the controller manufacturer. +Pressing INCLUDE_BUTTON three times within 2 seconds will enter exclusion mode. +Node ID has been excluded. + CEPT (Europe) + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2421/xml + + true diff --git a/config/zipato/vszd2102.xml b/config/zipato/vszd2102.xml index ff11fe1e3e..b19594cfcc 100644 --- a/config/zipato/vszd2102.xml +++ b/config/zipato/vszd2102.xml @@ -1,4 +1,22 @@ - + + + http://www.openzwave.com/device-database/0131:0106:2001 + images/zipato/vszd2102.png + https://products.z-wavealliance.org/products/1864/ + The ZD2102-5 is forced awake by opening the rear cover, the red LED will stay on and the 2102-5 will stay awake for 10 seconds. The ZD2102-5 will send “Wake Up Notification”. If ZD2102-5 receives a “Wake Up No More Information” command then the red LED will go off and it will go to sleep. +Auto Wake Up: The wakeup interval is user settable from 10 minutes to 1 week using COMMAND_CLASS_WAKE_UP, Interval increment is 3 minutes. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1864/vs-zd2102 - Zipato Door+Window Sensor User Manual v1.5.pdf + The ZD2102-5 Door and Window sensor is used in any Z-Wave network to detect the opening or closing of a door or window. Special Design can fit most of door/window frame. The primary sensing element is a magnetic reed switch, the ZD2102-5 is supplied with the sensor, sensor mounting bracket and the trigger magnet. An additional set of sensor inputs are provided through a 2 position screw terminal and can be used to expand the sensor capability to multiple inputs. The ZD2102-5 is powered by a single CR123A Lithium Battery (supplied with unit, battery life is more than 5 years) and is intended for indoor use only. The ZD2102-5 features tamper proof switch, low battery warning and can be firmware updated over the air. + For “Inclusion” (adding to) a network: Put the Z-Wave™ network controller into “inclusion” mode following its instructions. To add the ZD2102-5 to your controller press the program switch of ZD2102-5 to send the Node Information Frame (NIF). After sending NIF, the network controller will send the auto inclusion request; otherwise, ZD2102-5 will go to sleep after 15 seconds. + Door Sensor + For “Exclusion” (removing from) a network: Put the Z-Wave™ network controller into “exclusion” mode, following its instructions. To delete the ZD2102-5 from your controller press the program switch of ZD2102-5 for at least 1 second to be excluded. Note: All user and network settings will be cleared and the device reset to factory setting defaults when the device is excluded. + ZD2102US-5 + Factory Default Reset: Trigger the rear cover switch to send the Alarm Report and trigger the reed switch (close & open) 5 times in 10 seconds, ZD2102-5 will send the “Device Reset Locally Notification” command and reset to the factory default condition. (Remark: This is to be used only in the case of primary controller being inoperable or otherwise unavailable.) + U.S. / Canada / Mexico + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1864/xml + + - +--> + + http://www.openzwave.com/device-database/0131:0205:2002 + images/zipato/zp3102.png + https://products.z-wavealliance.org/products/1978/ + It will be triggered after opening the front cover. +Red LED will last 10 seconds and Multisensor Duo will send “Wake +Up Notification” after 10 seconds. + Put your Z-Wave +Controller into “inclusion” mode, and follow the instructions to add +Multisensor Duo to your controller. To get in the “inclusion” mode, +the distance between sensor and controller should be up to 1 meter. +Press the program switch of Multisensor Duo once. The LED on the +sensor should stop flashing, if not, please try again. + U.S. / Canada / Mexico / CEPT (Europe) + Zipato Multisensor Duo + Remove cover to trigged tamper +switch, LED ON & send out Alarm Report. Press Program Switch +10 times within 10 seconds. Multisensor Duo will send the “Device +Reset Locally Notification” command and reset to the factory +default settings. + +(Remark: This is to be done only in case of primary +controller being inoperable or otherwise unavailable.) + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1978/manual.pdf + Put your +Z-Wave Controller into “exclusion” mode, and follow the instructions +to remove the Multisensor Duo from you controller network. Press +the program switch of Multisensor Duo once to be excluded. The +LED on the Multisensor Duo should start to flash. + Motion and temperature sensor in one device. Zipato +Multisensor Duo offers elaborate security and ambient sensing +options. Multi-functional nature of this product allows you to detect +motion, and measure room temperature. When used with Zipato +home automation controllers it can be part of any automation +scenario created using Zipato Rule Creator. Accordingly it can be +used to automatically trigger other devices when activated. + vs-zp3102+.eu + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1969/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1978/xml + + diff --git a/config/zooz/zen06.xml b/config/zooz/zen06.xml index 0fee9a7b3e..d8ab4d8d0d 100644 --- a/config/zooz/zen06.xml +++ b/config/zooz/zen06.xml @@ -1,56 +1,116 @@ - - + + + http://www.openzwave.com/device-database/027A:000A:0101 + images/zooz/zen06.png + https://products.z-wavealliance.org/products/1901/ + Product features: +- Manual and remote on / off control +- Energy monitoring +- Scene inclusion for custom automation scenarios when included to a Z-Wave gateway controller +- LED indicator displaying Z-Wave signal strength and power usage +- Security enabled Z-Wave device with AES signal encryption (requires a security enabled gateway controller for full functionality) +- Z-Wave Plus with improved 500 chip for faster and safer wireless communication +- Built-in range extender for a stronger, more reliable network +- 2 USB charging ports for your smart phone or tablet (no Z-Wave functionality) +- Built-in overload protection in Z-Wave outlet and USB ports + +Product Specifications: +Model Number: ZEN06 +Z-Wave Signal Frequency: 908.42 MHz +Power: 110V, 60Hz +Maximum Load: 15A, 1800W +USB Charging Port Power: 1A and 2.4A +Operating Temperature: 14 – 104 F +Range: Up to 130 feet line of sight +Installation and Use: Indoor only +Dimensions: 4” x 2.5” x 1.2” +Weight: 7oz + + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1901/Zooz-Z-Wave-Smart-Plug-ZEN06 Manual.pdf + U.S. / Canada / Mexico + Zooz Z-Wave Smart Plug + Auto Z-Wave Inclusion +1. Put your Z-Wave controller in inclusion mode +2. Plug the smart plug into a grounded receptacle located within 3 feet from your Z-Wave gateway controller +3. LED indicator will flash blue +4. A new on / off device should be recognized by your Z-Wave controller + +Manual Z-Wave Inclusion +1. Plug the smart plug into a grounded receptacle located within 3 feet from your Z-Wave gateway controller +2. Put your Z-Wave controller in inclusion mode +3. Press and release the Z-Wave button 3 TIMES QUICKLY +4. LED indicator will flash blue +5. A new on / off device should be recognized by your Z-Wave controller + +Secure Z-Wave Inclusion +1. Plug the smart plug into a grounded receptacle located within 3 feet from your Z-Wave gateway controller +2. Put your Z-Wave controller in secure inclusion mode +3. Press and HOLD the Z-Wave button for at least 3 seconds +4. LED indicator will flash green +5. LED indicator will turn solid green once the inclusion is completed. Please allow 5 minutes for configuration. DO NOT press any buttons or move the device during that time +6. A new secure on / off device should be recognized by your Z-Wave controller + + ZEN06 + When your network’s primary controller is missing or otherwise inoperable, you may need to reset the device to factory settings manually. In order to complete the process, plug the smart plug into a grounded receptacle, then PRESS AND HOLD the Z-Wave button for AT LEAST 20 SECONDS. The LED indicator will stay solid yellow for 2 seconds to indicate successful reset. The plug will then automatically turn off. +NOTE: All previously recorded activity and custom settings will be erased from the device’s memory. You may only reset your smart plug once it has been included to a Z-Wave network. + 1. Plug the smart plug into a grounded receptacle located within 3 feet from your Z-Wave gateway controller +2. Put your Z-Wave controller in exclusion mode +3. Press and release the Z-Wave button 3 TIMES QUICKLY +4. LED indicator will flash orange +5. The smart plug should disappear from your controller's device list and LED indicator will remain solid orange for a few seconds to indicate exclusion + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1901/xml + + - + turns relay off once voltage exceeds 16.5A for over 5 secs if enabled - - + + - + Recovery state for power failure - - - + + + - + Send notifications to associated devices - - - + + + - + LED Indicator Control - - + + - + Minimum change in watts to report - + Minimum percentage change to report - + How often to report power consumption (W) in secs - + How often to report energy usage (KWH) in secs - + How often to report voltage (V) in secs - + How often to report electrical current (A) in secs - - + - diff --git a/config/zooz/zen15.xml b/config/zooz/zen15.xml index 17379d91df..25a0d15a88 100644 --- a/config/zooz/zen15.xml +++ b/config/zooz/zen15.xml @@ -1,55 +1,123 @@ - - - - - - - Overload protection. - - - - - Choose the recovery state for your Power Switch if power outage occurs. - - - - - - Send On/Off Status Change Notifications - - - - - - 0 - LED indicator will display power consumption whenever the device is plugged in. 1 - LED indicator will display the level of power consumption for 5 seconds only whenever the device is turned on or off - - - - - Number of Watts the appliance needs to go over for the change to be reported - - - Percentage in power usage change the appliance needs to go over for the event to be reported (Default 10) - - - Number of seconds - - - Number of seconds - - - Number of seconds - - - Number of seconds - - - - - - - - - - + + + http://www.openzwave.com/device-database/027A:000D:0101 + images/zooz/zen15.png + https://products.z-wavealliance.org/products/2517/ + 1. Plug the Power Switch into a grounded receptacle located within direct range of your Z-Wave gateway controller +2. Put your Z-Wave controller into exclusion mode +3. Press and release the Z-Wave button 3 TIMES QUICKLY +4. The LED indicator will start flashing orange, then turn blue (on) or pink (off) once excluded +5. The Power Switch will disappear from your controller's device list. The LED indicator will remain solid orange for a few seconds to indicate exclusion + +If the first attempt is unsuccessful, please repeat the process following all steps carefully. + Zooz Z-Wave Plus Power Switch + PRODUCT FEATURES: +Local and Z-Wave wireless control of your favorite home appliances like microwaves and refrigerators. + +Energy monitoring in live mode or over time (your Z-Wave gateway needs to support this feature). + +Scene inclusion for custom automation events when included to a Z-Wave gateway controller. + +On/Off status recovery after power failure. + +LED indicator to display Z-Wave signal strength and power usage for the connected device. + +Added security with AES signal encryption (requires a security enabled gateway controller for full functionality). + +Z-Wave Plus with improved 500 chip for faster and more reliable wireless communication. + +Built-in range extender. + +SPECIFICATIONS: +Model Number: ZEN15 +Z-Wave Signal Frequency: 908.42 MHz +Power: 120V, 60Hz +Maximum Load: 15A, 1800W, ½ HP +Operating Temperature: 14° – 104° F +Range: Up to 130 feet line of sight +Installation and Use: Indoor only +Dimensions: 20” (with cord) x 2.6” x 1.1” +Weight: 10oz + ZEN15 + U.S. / Canada / Mexico + When your network’s primary controller is missing or otherwise inoperable, you may need to reset the device to factory settings manually. In order to complete the process, plug the Power Switch into a grounded receptacle, then PRESS AND HOLD the Z-Wave button for AT LEAST 20 SECONDS. The LED indicator will flash orange and then stay solid orange for 2 seconds to indicate successful reset. The Power Switch will then turn off. + +NOTE: All previously recorded activity and custom settings will be erased from the device’s memory. You may only reset your Power Switch once it has been included to a Z-Wave network. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2517/zooz-z-wave-plus-power-switch-zen15-user-manual.pdf + Please include the Power Switch to your network BEFORE connecting it to the appliance you wish to control. + +Auto Z-Wave Inclusion: +1. Put your Z-Wave controller into inclusion mode +2. Plug the Power Switch into a grounded receptacle located within direct range from your Z-Wave gateway controller +3. The LED indicator will start flashing blue, then turn blue (on) or pink (off) once included +4. A new on / off device will be recognized by your Z-Wave controller + +Manual Z-Wave Inclusion: +1. Plug the Power Switch into a grounded receptacle located within direct range from your Z-Wave gateway controller +2. Put your Z-Wave controller into inclusion mode +3. Press and release the Z-Wave button 3 TIMES QUICKLY +4. The LED indicator will start flashing blue, then turn blue (on) or pink (off) once included +5. A new on / off device will be recognized by your Z-Wave controller + +Secure Z-Wave Inclusion: +1. Plug the Power Switch into a grounded receptacle located within direct range from your Z-Wave gateway controller +2. Put your Z-Wave controller in secure inclusion mode +Press and HOLD the Z-Wave button for at least 3 seconds +3. The LED indicator will start flashing green, then turn blue (on) or pink (off) once included +4. A new secure on / off device will be recognized by your Z-Wave controller + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2517/xml + + + + + + + Overload protection. + + + + + Choose the recovery state for your Power Switch if power outage occurs. + + + + + + Send On/Off Status Change Notifications + + + + + + 0 - LED indicator will display power consumption whenever the device is plugged in. 1 - LED indicator will display the level of power consumption for 5 seconds only whenever the device is turned on or off + + + + + Number of Watts the appliance needs to go over for the change to be reported + + + Percentage in power usage change the appliance needs to go over for the event to be reported (Default 10) + + + Number of seconds + + + Number of seconds + + + Number of seconds + + + Number of seconds + + + + + + + + + diff --git a/config/zooz/zen20.xml b/config/zooz/zen20.xml index 2ef1a5b9bd..acd987016b 100644 --- a/config/zooz/zen20.xml +++ b/config/zooz/zen20.xml @@ -1,13 +1,44 @@ - - - - - - - - - - - - + + + http://www.openzwave.com/device-database/015D:F51C:0651 + images/zooz/zen20.png + https://products.z-wavealliance.org/products/1646/ + U.S. / Canada / Mexico + 1. Follow the instructions for your Z-Wave certified controller to include a device to + the Z-Wave network. +2. Once the controller is ready to include your device, press up and release the toggle + to include it in the network. +3. Once your controller has confirmed that the device has been included, refresh the + Z-Wave network to optimize performance. +4. The device is associated in the same group when it included in setting process. + Now you can control your Z-Wave device according to groups, scenes, schedules and automation programmed. + + The 5 outlets power strip provides five Z-Wave outlets for remote controlled by controller through Z-Wave gateway for internet of thing service and can be configured in Z-Wave sensor network, if Z-Wave certified controller features remote access, you can now control five outlets from your mobile phone each one. Five outlets can +manual On/Off the same time by push button. The two USB ports provide 5V/2.1A charging power for MP3/ mobile phone.etc.. + + 1. Follow the instructions for your Z-Wave certified controller to exclude a device + from the Z-Wave network. +2. Once the controller is ready to Exclude your device, press up and release the toggle + to exclude it from the network. + + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1646/ZW1505-Manual0130.pdf + 1. Press and hold the top button for at least 3 seconds while you plug the smart + switch into a receptacle. +2. Use this procedure only in the event that the network primary controller is missing + or otherwise inoperable. + + 5 Outlet Power Strip with USB charger + ZW 1505 + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1646/xml + + + + + + + + + + diff --git a/config/zooz/zen20v2.xml b/config/zooz/zen20v2.xml index 523e8eba3e..248dc86679 100644 --- a/config/zooz/zen20v2.xml +++ b/config/zooz/zen20v2.xml @@ -1,124 +1,162 @@ - - - + + + http://www.openzwave.com/device-database/027A:A004:A000 + images/zooz/zen20v2.png + https://products.z-wavealliance.org/products/3158/ + FEATURES: + +- Z-Wave on/off control of up to 5 electrical devices +- On/off (charging/charged) reports from USB ports to the hub (no Z-Wave control) - turn off the charging device for best results +- Energy monitoring for each of the 5 outlets +- Built-in overload protection and ETL certification +- Z-Wave Plus signal repeater to extend network range +- S2 security protocol and the latest 500 Z-Wave chip for faster and safer wireless communication + +SPECS: +- Model Number: ZEN20 VER. 2.0 +- Z-Wave Signal Frequency: 908.42 MHz +- Power: 120 VAC +- Maximum Load: 15 A total (between 5 outlets) +- Maximum Load for USB ports: 2.1 A total (between 2 ports) +- Cord Length: 2 feet +- Range: Up to 100 feet line of sight +- Installation and Use: Indoor only + 5-Outlet Power Strip + ZEN20 VER. 2.0 + 1. Bring the strip within direct range of your Z-Wave gateway (hub). +2. Put the Z-Wave hub into exclusion mode. +3. Press and release the CH1 button 3 times quickly. +4. Your hub will confirm exclusion and all of the channels (child outlets) and the main device will disappear from your controller's device list. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3158/zooz-s2-z-wave-plus-power-strip-zen20-ver2-online-manual.pdf + If your primary controller is missing or inoperable, you may need to reset the device to factory settings. To complete the reset process manually, click-click-click’n’hold CH1 button for at least 10 seconds. All LED indicators will flash to confirm successful reset. +NOTE: All previously recorded activity and custom settings EXCEPT for the kWh record will be erased from the device’s memory. + U.S. / Canada / Mexico + 1. Plug the Power Strip into a grounded receptacle you’re planning to use it at (it doesn’t need to be close to the hub) +2. Initiate inclusion (pairing) in the app (or web interface). +3. CLICK CH1 BUTTON 3 TIMES QUICKLY. All LED indicators will start flashing +4. You will see 7 or 8 new on/off devices in your app: 5 channels or on/off control, 2 channels for on/off monitoring (USB ports reporting charging/ charged status, no control), and possibly one master node to access and adjust advanced settings in. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3158/xml + + + - + Status after Power Failure - - - + + + - + 0 = power meter disabled; 1-65535 = value in watts for report threshold - + 0 = disabled; 30-2678400 = time in seconds to send power wattage report - + 0 = disabled; 30-2678400 = time in seconds to send energy report - + 0 = disabled; 1-1800 = value in watts for overload protection - + Enable or Disable auto turn-off timer for CH1 - - + + - + Value in minutes for auto-off timer for CH1, if enabled - + Enable or Disable auto turn-off timer for CH1 - - + + - + Value in minutes for auto-on timer for CH1, if enabled - + Enable or Disable auto turn-off timer for CH2 - - + + - + Value in minutes for auto-off timer for CH2, if enabled - + Enable or Disable auto turn-off timer for CH2 - - + + - + Value in minutes for auto-on timer for CH2, if enabled - + Enable or Disable auto turn-off timer for CH3 - - + + - + Value in minutes for auto-off timer for CH3, if enabled - + Enable or Disable auto turn-off timer for CH3 - - + + - + Value in minutes for auto-on timer for CH3, if enabled - + Enable or Disable auto turn-off timer for CH4 - - + + - + Value in minutes for auto-off timer for CH4, if enabled - + Enable or Disable auto turn-off timer for CH4 - - + + - + Value in minutes for auto-on timer for CH4, if enabled - + Enable or Disable auto turn-off timer for CH5 - - + + - + Value in minutes for auto-off timer for CH5, if enabled - + Enable or Disable auto turn-off timer for CH5 - - + + - + Value in minutes for auto-on timer for CH5, if enabled - + Enable or Disable Manual Controll for out Outlets - - + + - + Normal = LED indicator is on when power is on, off when power is off. Inverse = LED indicator is off when power is on, and on when power is off. Always Off = LED indicator is always off, regardless of power status. - - - + + + - + - diff --git a/config/zooz/zen21.xml b/config/zooz/zen21.xml index 47a0b12be9..a8e0335e65 100644 --- a/config/zooz/zen21.xml +++ b/config/zooz/zen21.xml @@ -1,29 +1,56 @@ - - - + + + http://www.openzwave.com/device-database/015D:231C:0111 + images/zooz/zen21.png + https://products.z-wavealliance.org/products/1945/ + 1. Press and hold the top button for at least 3 seconds while you apply AC power to this device. +2. Use this procedure only in the event that the network primary controller is missing or otherwise inoperable. + + 1. Follow the instructions for your Z-Wave certified controller to exclude a device from the Z-Wave network. +2. Once the controller is ready to Exclude your device, press up and release the front button to exclude it from the network. + + In-wall Smart Switch + U.S. / Canada / Mexico + 1. Follow the instructions for your Z-Wave certified controller to include a device to the Z-Wave network. +2. Once the controller is ready to include your device, press up and release the toggle to include it in the network. +3. Once your controller has confirmed that the device has been included, refresh the Z-Wave network to optimize performance. +4. The device is associated in the same group when it included in setting process. +Now you can control your Z-Wave device according to groups, scenes, schedules and automation programmed. + + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2348/ZW30manual170412.pdf + ZEN21 + It is an In-wall type device controlled by Z-Wave controller and can be configured in Z-Wave sensor network, if Z-Wave certified controller features remote access, you can control lights at home from your mobile phone separately, and manual On/Off light by push button . + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1945/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2348/xml + + https://products.z-wavealliance.org/products/2348/ + U.S. / Canada / Mexico + ZW30 + + - + Controls the on/off orientation of the rocker switch - - + + - + Choose if you want the LED indicator to turn on when switch is on or off - - + + - + Enable or disable LED indicator so it stays off at all times - - + + - + - diff --git a/config/zooz/zen22.xml b/config/zooz/zen22.xml index abb4681f6a..1e1ee20970 100644 --- a/config/zooz/zen22.xml +++ b/config/zooz/zen22.xml @@ -1,11 +1,54 @@ - - - + + + http://www.openzwave.com/device-database/015D:241C:0112 + images/zooz/zen22.png + https://products.z-wavealliance.org/products/1946/ + The switch will be reset to factory defaults only by exclusion using a Z-Wave controller. You may use any certified Z-Wave controller to exclude and reset the switch. This device may not be reset manually when the network’s primary controller is missing or otherwise inoperable. NOTE: All previously recorded activity and custom settings will be erased from the device’s memory. + PRODUCT FEATURES: +- Manual or remote on/off control and dimming from your mobile device or computer (when included to a Z-Wave gateway controller) +- Z-Wave Plus with improved 500 chip for faster and safer wireless communication +- Works with most high-quality DIMMABLE LED, CFL, and incandescent bulbs +- Based on universal command classes - supported by most Z-Wave controllers +- May be associated and grouped with other Z-Wave devices for advanced home automation +- LED indicator to help locate the switch in dark space +- Simple elegant design with screwless snap-on wall plate included +- Built-in Z-Wave signal repeater for a stronger and more reliable network + +SPECIFICATIONS: +Model Number: ZEN22 +Z-Wave Signal Frequency: 908.42 MHz +Power: 120 VAC, 60 Hz +Maximum Loads: 500W Single-gang, 400W Double-gang, 300W Triple-gang Incandescent, 150W CFL or LED +Range: Up to 100 feet line of sight +Operating Temperature: 32-104° F (0-40° C) +Installation and Use: Indoor only + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1946/zooz-z-wave-plus-dimmer-switch-zen22-manual.pdf + U.S. / Canada / Mexico + 1. Bring your Z-Wave gateway hub or controller as close to the switch as possible +2. Put your Z-Wave controller in exclusion mode +3. Tap the switch on and off quickly 3 times to complete the exclusion process +4. The device should disappear from your controller's device list + ZEN22 + Zooz Z-Wave Dimmer Light Switch + 1. Bring your Z-Wave gateway hub or controller as close to the switch as possible +2. Put your Z-Wave controller in inclusion mode +3. Tap the switch on and off quickly 3 times to finalize the inclusion process +4. A new dimming device should appear on your controller's device list + +Troubleshooting Tips: +If you are unable to include the Z-Wave dimmer to your controller, please try one of the following: +- Bring the controller closer to your Z-Wave switch or use a hand-held secondary controller for inclusion +- Tap your Z-Wave switch quicker 4 or 5 times once you put the controller in the inclusion mode to ensure the command has gone through +- Put your controller in the EXCLUSION mode and tap the switch quickly 3 times, then try adding it to your network again + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1946/xml + + + - + - diff --git a/config/zooz/zen26.xml b/config/zooz/zen26.xml index 5aebd70ecd..5d1162b8c2 100644 --- a/config/zooz/zen26.xml +++ b/config/zooz/zen26.xml @@ -1,39 +1,99 @@ - - - - - - Normal mode: Upper paddle turns the light on, lower paddle turns the light off. Reverse will reverse those functions. - - - - - LED Indication light function. Normal has the LED Indication on when the switch is off, off when the switch is on. - - - - - - - Time, in seconds, for auto-off timer delay. 0 (default) disables the timer. - - - Status after power on after power failure. OFF will always turn light off. ON will always turn light on. Restore will remember the latest state and restore that state. - - - - - +--> + + http://www.openzwave.com/device-database/027A:A001:A000 + images/zooz/zen26.png + https://products.z-wavealliance.org/products/3147/ + If your primary controller is missing or inoperable, you may need to reset the device to factory settings. To complete the reset process manually, tap-tap-tap’n’hold the upper paddle for at least 10 seconds. The LED indicator will flash to confirm successful reset. +NOTE: All previously recorded activity and custom settings will be erased from the device’s memory. + 1. Bring your Z-Wave gateway (hub) close to the switch if possible +2. Put the Z-Wave hub into exclusion mode (not sure how to do that? +ask@getzooz.com) +3. Tap the lower paddle on the switch 3 times quickly + 1. Initiate inclusion (pairing) in the app (or web interface) of your hub. +2. Tap the upper paddle on the switch 3 times quickly. + U.S. / Canada / Mexico + ZEN26 + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3147/zooz-z-wave-plus-s2-on-off-switch-zen26-manual.pdf + S2 On Off Switch + FEATURES: +- Manual or Z-Wave on/off control with instant status updates +- Simple Direct 3-Way: connect with existing on/off switches in 3-way, 4-way, and 5-way set-ups, no add-on needed (neutral wire required) +- Remembers and restores on/off status after power failure +- LED indicator signals inclusion, exclusion, reset, and setting changes +- Built-in Z-Wave Plus signal repeater to extend network range +- Works with LED, CFL, and incandescent bulbs +- S2 security protocol and the latest 500 Z-Wave chip for faster and safer wireless communication +- Supported by most Z-Wave controllers - - - - - - - +SPECIFICATIONS: +- Model Number: ZEN26 +- Z-Wave Signal Frequency: 908.42 MHz +- Power: 120 VAC, 60 Hz +- Maximum Load: 8 A, 150 W LED/CFL, 600 W incandescent, 1200 W resistive +- Range: Up to 100 feet line of sight +- Operating Temperature: 32-104° F (0-40° C) +- Installation and Use: Indoor only + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3147/xml + Updated for firmware version 2.0 + + + + + + Normal mode: Upper paddle turns the light on, lower paddle turns the light off. Reverse mode: Upper paddle turns the light off, lower paddle turns the light on. Toggle mode: Either paddle toggles the light. + + + + + + LED Indication light function. Normal has the LED Indication on when the switch is off, off when the switch is on. + + + + + + + + + + + + Time, in minutes, for auto-off timer delay. + + + + + + + + Set the time (in minutes) after which you want the switch to automatically turn on once it has been turned off. + + + Status after power failure. Off: always turn light off. On: always turn light on. Restore: remember the latest state and restore that state. + + + + + + Enable or Disable scene control functionality for quick double tap triggers (Available for select hubs only). + + + + + If enabled, you'll only be able to control the connected light via Z-Wave. Scenes and other functionality will still be available through paddles. + + + + + + + + + + + diff --git a/config/zooz/zen27.xml b/config/zooz/zen27.xml index cd2fa8f117..b81b58814a 100644 --- a/config/zooz/zen27.xml +++ b/config/zooz/zen27.xml @@ -1,66 +1,125 @@ - - - - - - Normal mode: Upper paddle turns the light on, lower paddle turns the light off. Reverse will reverse those functions. - - - - - LED Indication light function. Normal has the LED Indication on when the switch is off, off when the switch is on. - - - - - - - - - - - - Time, in minutes, for auto-off timer delay. - - - - - - - - Time, in minutes, for auto-off timer delay. - - - Status after power on after power failure. OFF will always turn light off. ON will always turn light on. Restore will remember the latest state and restore that state. - - - - - - Adjust the ramp rate for your dimmer (fade-in / fade-out effect for on / off operation). Values correspond to the number of seconds it take for the dimmer to reach full brightness or turn off when operated manually. - - - Set the minimum brightness level for your dimmer. You won't be able to dim the light below the set value. - - - Set the maximum brightness level for your dimmer. You won't be able to add brightness to the light beyond the set value. Note: if Parameter 12 is set to value "Full", Parameter 11 is automatically disabled. - - - Double Tap action. When set to Full, turns light on to 100%. If set to Maximum Level, turns light on to % set in Parameter 11. - - - - + + + http://www.openzwave.com/device-database/027a:a002:a000 + images/zooz/zen27.png + https://products.z-wavealliance.org/products/3148 + Product features: +- Manual or Z-Wave on/off and brightness control +- Simple Direct 3-Way: connect with existing on/off switches in 3-way, 4-way, and 5-way set-ups, no add-on needed (neutral wire required) +- Fully adjustable ramp rate for just the right on/off speed +- Double tap to full brightness feature +- Remembers and restores on/off status after power failure +- LED indicator signals inclusion, exclusion, reset, and setting changes +- Built-in Z-Wave Plus signal repeater to extend network range +- Extended compatibility with LED bulbs, no more flickering! +- S2 security protocol and the latest 500 Z-Wave chip for faster and safer wireless communication +- Customizable LED indicator and air-gap switch for added safety - - - - - - - +SPECIFICATIONS: +- Model Number: ZEN27 +- Z-Wave Signal Frequency: 908.42 MHz +- Power: 120 VAC, 60 Hz +- Maximum Load: 100 W LED/CFL, 300 W incandescent (100 W with +both sides of heat sink tabs off) +- Range: Up to 100 feet line of sight +- Operating Temperature: 32-104° F (0-40° C) +- Installation and Use: Indoor only + + https://products.z-wavealliance.org/ProductManual/File?folder=&filename=MarketCertificationFiles/3148/zooz-z-wave-plus-s2-dimmer-switch-zen27-manual.pdf + U.S. / Canada / Mexico + S2 Dimmer + 1. Initiate inclusion (pairing) in the app (or web interface) of your hub. 2. Tap the upper paddle on the switch 3 times quickly. + + ZEN27 + If your primary controller is missing or inoperable, you may need to reset the device to factory settings. To complete the reset process manually, tap-tap-tap’n’hold the upper paddle for at least 10 seconds. The LED indicator will flash to confirm successful reset. + NOTE: All previously recorded activity and custom settings will be erased from the device’s memory. + + 1. Bring your Z-Wave gateway (hub) close to the switch if possible +2. Put the Z-Wave hub into exclusion mode (not sure how to do that? +ask@getzooz.com) +3. Tap the lower paddle on the switch 3 times quickly + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3148/xml - this requires v2.0 (or newer) firmware + + + + + + + + + Normal mode: Upper paddle turns the light on, lower paddle turns the light off. Reverse mode: Upper paddle turns the light off, lower paddle turns the light on. Toggle mode: Either paddle toggles the light. + + + + + + LED Indication light function. Normal has the LED Indication on when the switch is off, off when the switch is on. + + + + + + + + + + + + Time, in minutes, for auto-off timer delay. + + + + + + + + Set the time (in minutes) after which you want the switch to automatically turn on once it has been turned off. + + + Status after power failure. Off: always turn light off. On: always turn light on. Restore: remember the latest state and restore that state. + + + + + + Adjust the ramp rate for your dimmer (fade-in / fade-out effect for on / off operation). Values correspond to the number of seconds it take for the dimmer to reach full brightness or turn off when operated manually. + + + Set the minimum brightness level (in %) for your dimmer. You won't be able to dim the light below the set value. + + + Set the maximum brightness level (in %) for your dimmer. You won't be able to add brightness to the light beyond the set value. Note: if Parameter 12 is set to value "Full", Parameter 11 is automatically disabled. + + + Double Tap action. When set to Full, turns light on to 100%. If set to Maximum Level, turns light on to % set in Parameter 11. + + + + + Enable or Disable scene control functionality for quick double tap triggers. + + + + + Enables/Disables the double-tap fucntion and assign brightness to single tap. Last level: single tap returns to last brightness level. Full/Max level: single tap returns to full/max level + + + + + + If enabled, you'll only be able to control the connected light via Z-Wave. Scenes and other functionality will still be available through paddles. + + + + + + + + + + + + diff --git a/config/zooz/zse09.xml b/config/zooz/zse09.xml index ae2b681cfe..b250b1624f 100644 --- a/config/zooz/zse09.xml +++ b/config/zooz/zse09.xml @@ -1,54 +1,89 @@ - - - + + + http://www.openzwave.com/device-database/027A:0083:0003 + images/zooz/zse09.png + https://products.z-wavealliance.org/products/1953/ + DMMS1 + If needed, the Motion Detector can be reset locally by following these steps. Only do this when your Z-Wave controller is disconnected or otherwise unreachable. Beware that resetting your device will disconnect it from the system: +1. Remove the SENSOR COVER and confirm that your Motion Detector is powered up. +2. Press and hold the BUTTON for at least 10 seconds then release. A flashing LED INDICATOR indicates a successful factory reset. +3. The Motion Detector’s memory will be erased to factory settings. + U.S. / Canada / Mexico + Follow the instructions for your Z-Wave Certified Conto enter exclusion mode. When prompted by the controller: +1. Remove the SENSOR COVER. +2. Press the BUTTON quickly 3 times in a row. +The LED INDICATOR will flash five times indicating exclusion/disconnection. + + The Dome™ Home Automation DMMS1 Z-Wave Certified Motion Detector tracks motion in your home, helping you keep your family safe. When motion is detected, your Z-Wave hub will send an alert to your smartphone, set off an alarm or trigger a lighting scene. This detector can also measure light levels to ensure the lights are operated only when required. Convenient magnetic mount offers the ultimate flexibility for multi surface adaptable installation on either wall, ceiling or table top. The device comes with a CR123A battery and has a 3-year battery life, so you can always be confident that your detector has power. Extra-long Z-Wave wireless range (up to 150 ft) allows you to place it where it’s needed without worrying if the signal reaching your Z-Wave Hub. The Dome™ Home Automation DMMS1 Z-Wave Certified Motion Detector comes with a 1-year limited warranty. Measurements in inches: 2.5 x 3.5 x 6. This sensor requires a Dome™ Home Automation Hub or other Z-Wave Certified hub for operation. The Dome™ Home Automation system gives your family the ease and security you can count on. With Dome™, you’re always connected and always covered. +● Detects movement inside your home with extra wide 110 deg. coverage and responds to activity by sending an alert to your smarthome system. Adjustable sensitivity for optimum performance based on environment +● Capable of sensing current light conditions in the room helping create smart lighting scenes. Adjustable timeout for selecting delay when lights will turn off after motion is no longer detected +● Convenient magnetic mount offering ultimate installation flexibility +● Z-Wave Plus Certified. Requires a Z-Wave Certified Hub to operate. Up to 150-foot range and 3-year battery life (CR123A Battery Included) +● Works with SmartThings, Vera, Staples Connect, HomeSeer, Nexia, Piper, URC, Harmony. Not supported: Wink, DSC, ADT Pulse, 2gig, Napco, Interlogix, Honeywell (Dome is not associated with listed brands) + + Dome Z-Wave Plus Motion Detector + Because the Motion Detector is a battery powered device, it wakes up on regular intervals to give battery and other status updates to the controller, as well as to accept configuration settings from the controller. This helps to extend the battery life. The device can be forced to wake up to submit these reports or accept new settings immediately by simply pressing and holding the BUTTON for two seconds. The LED INDICATOR will flash once indicating successful wake up. + Follow the instructions for your Z-Wave Certified Conto enter inclusion mode. When prompted by the controller: +1. The Motion Sensor should be within 10’ of your Z-Wave controller for the inclusion process. After successful pairing, the device can be brought to the desired location. +2. Remove the SENSOR COVER by twisting it counterclockwise. +3. Remove the BATTERY TAB. +4. Press the BUTTON quickly 3 times in a row. +5. The LED INDICATOR will flash five times indicating inclusion + + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1953/Dome Motion Detector API Manual.pdf + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1938/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1953/xml + + + - - - Adjust motion detection sensitivity. Lower number is for higher sensitivity, while higher number os for lower sensitivity. Defaults to 12. - - - Set the duration you want the associated device to stay ON after being triggered by the sensor before it automatically turns OFF, in seconds. - - - Configure whether the Mini Sensor turns an associated device on or off when sending the BASIC_SET command. 0 is OFF, 255 is ON, and 1-99 is a percentage of light level. Value of 100-254 is NOT valid. - - - Enable or Disable motion detection. - - - - - Set light sensor as a secondary trigger for associated devices. If light level in a room falls beyond the set point and motion is detected, the Mini Sensor will send BASIC_SET command to associated devices to turn ON. - - - Adjust the time when motion is reported again after initial trigger, in seconds. - - - How often the Mini Sensor reports light level to the controller and associated devices, in seconds. - - - Enable/Disable the light sensor as secondary trigger. - - - - - Change required to report to the controller, in lux. - - - Enable or Disable LED Notification. - - - - - - - - - - - - - - + + + Adjust motion detection sensitivity. Lower number is for higher sensitivity, while higher number os for lower sensitivity. Defaults to 12. + + + Set the duration you want the associated device to stay ON after being triggered by the sensor before it automatically turns OFF, in seconds. + + + Configure whether the Mini Sensor turns an associated device on or off when sending the BASIC_SET command. 0 is OFF, 255 is ON, and 1-99 is a percentage of light level. Value of 100-254 is NOT valid. + + + Enable or Disable motion detection. + + + + + Set light sensor as a secondary trigger for associated devices. If light level in a room falls beyond the set point and motion is detected, the Mini Sensor will send BASIC_SET command to associated devices to turn ON. + + + Adjust the time when motion is reported again after initial trigger, in seconds. + + + How often the Mini Sensor reports light level to the controller and associated devices, in seconds. + + + Enable/Disable the light sensor as secondary trigger. + + + + + Change required to report to the controller, in lux. + + + Enable or Disable LED Notification. + + + + + + + + + + + + + diff --git a/config/zooz/zse19.xml b/config/zooz/zse19.xml index 90394590d6..cb551cd40b 100644 --- a/config/zooz/zse19.xml +++ b/config/zooz/zse19.xml @@ -1,24 +1,64 @@ - - - + + + http://www.openzwave.com/device-database/027A:0003:000C + images/zooz/zse19.png + https://products.z-wavealliance.org/products/3116/ + S2 Multisiren + If your primary controller is missing or inoperable, you may need to reset the device to factory settings. To complete the reset process manually, make sure the Multisiren is powered, then CLICK-CLICK-CLICKCLICK’N’HOLD the Z-Wave button for AT LEAST 5 SECONDS. The LED indicator will flash to confirm successful reset. +NOTE: All previously recorded activity and custom settings will be erased from the device’s memory. + 1. Bring the Multisiren within direct range of your Z-Wave gateway (hub). +2. Put the Z-Wave hub into exclusion mode (not sure how to do that? ask@getzooz.com). +3. Click the Z-Wave button on the Multisiren 3 times quickly to finalize the process. +4. Your hub will confirm exclusion and the device will disappear from your controller's device list. + FEATURES: +- Audio and visual alarm triggered by other Z-Wave devices +- Configurable siren alarm duration +- Built-in temperature and humidity sensor (if Multilevel Sensor is supported) +- Audio Speaker for custom sound playback (if Sound Switch is supported) +- S2 security protocol and the latest 500 Z-Wave chip for faster and safer wireless communication +- Tamper protection, low-battery alerts + +SPECS: +- Model Number: ZSE19 +- Z-Wave Signal Frequency: 908.42 MHz +- Power: 4 x LR14 (C Cell) battery +- Range: Up to 100 feet line of sight +- Operating Temperature: 14-104° F (-10-40° C) +- Operating Humidity: 0-80% +- Installation and Use: Indoor only + AUTO INCLUSION: +1. Initiate inclusion (pairing) in the app (or web interface). Not sure how? ask@getzooz.com +If you’re using an S2 hub, it may ask you to enter the DSK key printed on the back cover sticker to complete secure inclusion. + +2. Insert the batteries as instructed above (if you already did, take them out for at least 15 seconds before starting the inclusion process). The LED indicator will start blinking and the Multisiren will join the network automatically. + +MANUAL INCLUSION: +Put your Z-Wave hub into inclusion mode and click the Z-Wave button on the Multisiren 3 times quickly. + ZSE19 + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3116/zooz-z-wave-plus-s2-multisiren-zse19-manual.pdf + U.S. / Canada / Mexico + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3116/xml + + + - + Siren Alarm Duration, in seconds. Defaults to 600 (10 minutes). - + Reporting interval for temperature and humidity sensor, in miuntes. Defaults to 1440 (24 hours). - + Selector for custom audio files that have been manually uploaded to the alarm unit. 0 sets to no sound (default), while 1-99 selects the sound file number in the library to be used. - + - diff --git a/config/zooz/zse29.xml b/config/zooz/zse29.xml new file mode 100644 index 0000000000..532413e484 --- /dev/null +++ b/config/zooz/zse29.xml @@ -0,0 +1,60 @@ + + + http://www.openzwave.com/device-database/027A:0005:0001 + images/zooz/zse29.png + https://products.z-wavealliance.org/products/3081/ + FEATURES: +- Quick and reliable motion alerts to Z-Wave hub +- Outdoor ready housing (avoid direct sun and rain) +- Set motion time-out and lux trigger at the sensor +- Auto-inclusion for easy set-up +- The latest S2 security and Z-Wave Plus chip +- Powered by common batteries or Micro USB +- Built-in tamper switch for extra security + +SPECS: +- Model Number: ZSE29 +- Z-Wave Signal Frequency: 908.42 MHz +- Power: 3 x AA (1.5 V) batteries / Micro USB +- Motion Detection: up to 30 feet +- Operating Temperature: -4 – 104 F +- Warm-up time: 1 minute +- Range: Up to 130 feet line of sight +- Installation and Use: Indoor / Outdoor + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/3081/zooz-z-wave-plus-s2-outdoor-motion-sensor-zse29-manual.pdf + The sensor’s wake-up interval is set to 4 hours by default to save battery life. Use the Wake Up Command Class to adjust the interval (in seconds, working in 600s intervals, with 600 as min and 86400 as max values). +During wake-up, the sensor turns the Z-Wave radio on for 10 seconds to receive communication from the hub. Long wake-up interval will not affect how often the sensor reports motion to your hub. + Outdoor Motion Sensor + U.S. / Canada / Mexico + 1. Bring the sensor within direct range of your Z-Wave +gateway (hub). +2. Put the Z-Wave hub into exclusion mode (not sure +how to do that? ask@getzooz.com). +3. Press and release the tamper switch 3 times quickly. +4. Your hub will confirm exclusion and the sensor will +disappear from your controller's device list. + AUTO-INCLUSION: +1. Initiate inclusion (pairing) in the app (or web interface). Not Sure how? ask@getzooz.com. If you’re using an S2 hub, it may ask you to enter the DSK key printed on the back cover sticker to complete secure inclusion. +2. Insert the batteries or the USB adapter board. The LED indicator +will start blinking and the sensor will join the network Automatically. + +MANUAL INCLUSION: +Put your Z-Wave hub into inclusion mode and click the tamper switch 3 times quickly. + When your network’s primary controller is missing or otherwise inoperable, you may need to reset the device to factory settings manually. In order to complete the process, make sure the sensor is powered, then CLICKCLICK-CLICK-CLICK’N’HOLD the tamper switch for AT LEAST 5 SECONDS. The LED indicator will turn off to +indicate successful reset. The sensor will then enter auto-inclusion mode for 4 minutes. +NOTE: All previously recorded activity and custom settings will be erased from the device’s memory. + ZSE29 + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/3081/xml + + + + + + + + + + + + diff --git a/config/zooz/zse30.xml b/config/zooz/zse30.xml index dda4364f5e..9cdcd4dd5e 100644 --- a/config/zooz/zse30.xml +++ b/config/zooz/zse30.xml @@ -1,64 +1,116 @@ - - + + + http://www.openzwave.com/device-database/027A:0085:0003 + images/zooz/zse30.png + https://products.z-wavealliance.org/products/2204/ + ZSE30 + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2204/zooz-z-wave-plus-water-sensor-zse30-user-manual-online-v2.pdf + 1. Bring the Water Sensor within direct range of your controller +2. Carefully remove the cover from the sensor +3. Remove the plastic pull-tab from the battery slot. The LED indicator will blink slowly 5 times +4. Put your Z-Wave controller into inclusion mode +5. Press and release the Z-Wave button on the Water Sensor 3 TIMES quickly. The LED indicator + will flash quickly +6. A new water (leak) sensor will appear on your controller's device list + +Troubleshooting Tips +If you are unable to include the Z-Wave Water Sensor to your controller, try one of the following: +- Bring the sensor closer to your hub or use a hand-held secondary controller to perform inclusion +- Once in inclusion mode, press and release the Z-Wave button quickly 6-7 TIMES to ensure the command has gone through +- Put your controller in EXCLUSION mode. Press and release the Z-Wave button quickly 3 TIMES, and then try adding the sensor to your network again +- You may need to change the device type manually if the sensor is not recognized correctly (email us for more info: ask@getzooz.com) + + 1. Make sure the Water Sensor is powered on and located within direct range of your Z-Wave gateway controller +2. Put your Z-Wave controller in exclusion mode +3. Press and release the Z-Wave button 3 TIMES quickly. The LED indicator will flash quickly +4. The Water Sensor should disappear from your controller's device list +If the first attempt is unsuccessful, please repeat the process following all steps carefully. + + When your network’s primary controller is missing or otherwise inoperable, you may need to reset the device to factory settings manually. To complete the process, make sure the Water Sensor is powered on, then PRESS AND HOLD the Z-Wave button for AT LEAST 10 SECONDS until the LED indicator flashes ONCE. Release the button. NOTE: All previously recorded activity and custom settings will be erased from the device’s memory. + Product features: +- Reliable water and leak detection +- Wireless notifications and event triggers (when included to a Z-Wave gateway controller) +- Built-in audio and visual alarms +- Low battery alerts +- Z-Wave Plus with improved 500 chip for faster and safer wireless communication +- Flexible installation with 2 mounting options + +Specifications: +Model Number: ZSE30 +Z-Wave Signal Frequency: 908.42 MHz +Power: 1 CR2 battery (included) +Power Consumption: 0.13W +Operating Temperature: 32 – 104 F +Range: Up to 100 feet line of sight +Installation and Use: Indoor only +Dimensions: 2.5” x 0.9” +Weight: 2 oz + U.S. / Canada / Mexico + Zooz Z-Wave Plus Water Sensor + If you change settings and parameters for the sensor, you may need to wake it up manually for the changes to be recorded. Press and release the Z-Wave button THREE TIMES to wake the device up. The LED indicator will flash ONCE. +The sensor’s wake-up interval is set to 12 hours by default to save battery life. Though not recommended, you can change the wake-up interval using your controller’s advanced settings if available. Minimum value: 300s (5 minutes), maximum value: 16,777,200s (around 194 days). Accepted values need to match minute intervals, so 300, 360, 420, etc. + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2204/xml + + - - - + + + Use this parameter to set the total duration of audio and visual alarm each time water is detected. If the value is set to 0, the alarm will continue until water is no longer detected. - - - + + + Set the beeping frequency for the sensors audio alarm. The interval between beeps can be as low as 1 minute. - - - + + + Adjust the duration of the initial sound the alarm will produce after a leak is detected. - - - + + + Adjust the duration of the beeps the alarm will sound after a leak is detected and the first "long" beep is produced. - - + + Enable or disable the audio alarm by adjusting this parameter setting. The visual alarm will NOT be disabled and the LED indicator will always light up each time water is detected - - + + - + Enable or disable water detection for the sensor by adjusting this parameter setting.. - - + + - + You can choose if your Water Sensor turns an associated device on or off when sending the basic set command. Use value 0 to turn the associated device OFF and value 255 to turn it ON. Adjust brightness level for a Z-Wave dimmer (Multilevel switch) by putting in any value between 1 and 99. Values: 0 - OFF; 1 - 99 (% of light); 255 - ON (default). - - - - - - - - - - - - + + + + + + + + + + + diff --git a/config/zooz/zse33.xml b/config/zooz/zse33.xml index 49a33afc30..8660bfb808 100644 --- a/config/zooz/zse33.xml +++ b/config/zooz/zse33.xml @@ -1,82 +1,134 @@ - - - - - - + + + Siren volume level; low, medium, high (default). - - - - - - + + + + + + Duration of siren alarm. Default is 30 seconds. - - - - - - - - + + + + + + + + How many times the doorbell chime should repeat once triggered by a BASIC_SET alarm command from a door sensor. 0 is chime off, 1-254 is the number of cycles, 255 is chime continues until battery drains. 2 cycles is default. - - - + + + Doorbell chime volume level; low, medium, high (default). - - - - - - + + + + + + Chose one of the 10 different tones for the alarm siren. 10 is default. - - - + + + Chose one of the 10 different tones for the doorbell chime. 4 is default. - - - + + + Choose between Siren Alarm (configured by Siren Alarm parameters) or Doorbell Chime (configured by Doorbell Chime paramenters). Doorbell Chime enabled by default. - - - - - + + + + + Enable or disable visual LED alarm for Siren Mode. The LED will blink when triggered. Enabled by default. - - - - - + + + + + Enable or disable visual LED for Doorbell Chime mode. The LED will blink when triggered. Enabled by default. - - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/config/zooz/zse40.xml b/config/zooz/zse40.xml index 51a05c2d3f..691f73ded6 100644 --- a/config/zooz/zse40.xml +++ b/config/zooz/zse40.xml @@ -1,4 +1,37 @@ - + + + http://www.openzwave.com/device-database/027A:2101:2021 + images/zooz/zse40.png + https://products.z-wavealliance.org/products/1804/ + To remove theZSE40 from the Z-Wave network (exclusion), place the Z-Wave primary controller into “exclusion” mode and follow its instruction to delete the ZSE40 to the controller. Press the Program Switch of ZSE40 once to be excluded. + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1804/ZSE40-USER-MANUAL-5-13-16.pdf + ZSE40 + To add the ZSE40 to the Z-Wave network (inclusion), place the Z-Wave primary controller into inclusion mode. Press the Program Switch of ZSE40 for sending the NIF. After sending NIF, Z-Wave will send the auto inclusion, otherwise, ZSE40 will go to sleep after 20 seconds. + Use “Wake Up” command to set up the awaking time (from 10 minutes to 1 week) and send the wake up notification to controller + 4-in-1 Sensor + Enjoy 4 smart sensors in 1 compact device. Monitor motion, temperature, humidity, and light level. +This is a secure device using 128-bit signal encryption. It requires a security enabled gateway controller for full functionality. +The Zooz 4-in-1 sensor is packed with advanced features: +- 7 levels of motion sensitivity to choose from +- 3 modes for motion / temp led indicator notifications +- Built-in tamper protection +- Low battery alerts +- Z-Wave Plus with improved 500 series chip for faster and safer wireless communication + +Z-Wave Frequency: 908.42 MHz (US) +Power: 2 AAA batteries +Wireless Range: Up to 100 feet line of sight +Operating Temperature: 5° - 104°F +Installation: Indoor Use Only +1 Year Warranty + U.S. / Canada / Mexico + Remove cover to trigged tamper switch, LED flash once & send out Alarm Report. Press Program Switch 10 times within 10 seconds, ZSE40 will send the “Device Reset Locally Notification” command and reset to the factory default. (Remark: This is to be used only in the case of primary controller being inoperable or otherwise unavailable.) + + + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1804/xml + + diff --git a/config/zwave.me/ZUno.xml b/config/zwave.me/ZUno.xml index 525a0e5f71..c7cf6990b2 100644 --- a/config/zwave.me/ZUno.xml +++ b/config/zwave.me/ZUno.xml @@ -1,4 +1,34 @@ - + + + http://www.openzwave.com/device-database/0115:0001:0110 + images/zwave.me/ZUno.png + https://products.z-wavealliance.org/products/1825/ + Hold Service button for five seconds, then press Service button three times. + +Use this procedure only if your controller is missing or inoperable. + +Note that the user sketch is not erased during exclusion or reset process. + Press Service button three times + Press Service button three times + Z-Uno + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/1825/Z-Uno V3 Manual.pdf + v3 + Press Service button three times + CEPT (Europe) + Z-Uno is the first and only easy to use developer board that allows you to create your own Z-Wave device without deep knowledge of Z-Wave protocol or programming. Z-Uno is a mix of Z-Wave home automation radio protocol power and Arduino simplicity. Being inspired by Arduino project Z-Uno inherits all concepts of easy-to-use hardware and software solutions, keeping maximum flexibility. + +Z-Uno is a fully DIY product. It is made for those who are limited by existing choice of Z-Wave products and wants to extend their smart homes with more sensors and actuators: connect LEDs, buttons, switches, motors or any low voltage sensor including most of Arduino compatible sensors. + +Z-Uno programming is done by writing sketch in simplified C language and loaded into Z-Uno using Arduino IDE. Many examples and comprehensive tutorials will help you to make your own project. + +This is one of the two officially certified sketches. + +Certified 10 Channels sketch +http://z-uno.z-wave.me/examples/Certified10Channels/ + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/1825/xml + + diff --git a/config/zwp/PA-100.xml b/config/zwp/PA-100.xml index ffd85a08d5..335f9f50d1 100644 --- a/config/zwp/PA-100.xml +++ b/config/zwp/PA-100.xml @@ -1,10 +1,34 @@ - - - + + + http://www.openzwave.com/device-database/0315:3031:4447 + images/zwp/PA-100.png + https://products.z-wavealliance.org/products/2810/ + https://products.z-wavealliance.org/ProductManual/File?folder=&filename=Manuals/2810/ZL-PA-100%20UG%20v3.pdf + Z-Wave Plug-In On/Off Switch + PA-100 + Place your Z-Wave controller in "Exclusion" mode. Then tap the button to initiation Exclusion. + 1. Unplug the PA-100 from the AC outlet and also unplug the power plugs of the lighting from the module (if plugged in) +2. Press and hold the button on the PA-100 +3. Plug the PA-100 back into the AC outlet with the button pressed +After 3 seconds, release the button. If you see the button blink, that means that PA-100 has been reset successfully. +Please use this procedure only when the network primary controller is missing or otherwise inoperable. + U.S. / Canada / Mexico + Place your Z-Wave controller in "Inclusion" mode. Then tap the button once to initiation Inclusion. + ZLINK PA-100 is a Z-Wave Plus certified device with S2 security and SmartStart features. You can now add this device securely and with ease using QR code on the product with compatible gateways supporting S2 and Smart Start. PA-100 communicates with other Z-Wave certified devices and updates your home into a smart home. PA-100 can be used to turn On or Off lamps or AC operated appliances. Each Z-Wave device also serves as a node to repeat the signal in the network, thus, extending the overall Z-Wave mesh wireless network range. +Additional Features: +• Power 120 VAC, 60Hz, up to 1800 watts +• Region US: 908.4, 916 MHz +• Works with incandescent, CFL & LED lights & appliances +• Plugs into Standard AC outlet +• LED backlit On/Off button +• Control lights or appliances via schedule or remotely +• Second wall AC outlet remains free +• Works with any gateway supporting Z-Wave + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2810/xml + + @@ -16,12 +40,10 @@ OFF: the LED indicator will be always OFF regardless of the load status. - - diff --git a/config/zwp/WD-100.xml b/config/zwp/WD-100.xml index 672cd7c7d7..53c152cb8f 100644 --- a/config/zwp/WD-100.xml +++ b/config/zwp/WD-100.xml @@ -1,32 +1,58 @@ - - + + + http://www.openzwave.com/device-database/0315:3034:4447 + images/zwp/WD-100.png + https://products.z-wavealliance.org/products/2808/ + https://Products.Z-WaveAlliance.org/ProductManual/File?folder=&filename=Manuals/2808/ZL-WD-100 UG v3.pdf + Z-Wave In-Wall Dimmer + WD-100 + Place your Z-Wave controller in "Exclusion" mode. Then tap either the top or bottom paddle once to initiation Exclusion. + 1. Turn the connected light ON with the rocker +2. Quickly tap the topside of the rocker 3 times +3. Then quickly tap the bottom side of the rocker 3 times +If you see the lights turn OFF then ON it means that the module has been rest successfully. +Please use this procedure only when the network primary controller is missing or otherwise inoperable. + U.S. / Canada / Mexico + Place your Z-Wave controller in "Inclusion" mode. Then tap either the top or bottom paddle once to initiation Inclusion. + ZLINK’s WD-100 is a Z-Wave Plus certified device with S2 security and SmartStart features. You can now add this device securely and with ease using QR code on the product with compatible gateways supporting S2 and Smart Start. The elegant WD-100, with 7 LED dim level lights, communicates with other Z-Wave certified devices and updates your home into a smart home. WD-100 replaces a standard in-wall light switch turning it into a Z-Wave controlled network device with manual and remote control dimming and On/Off light control. ZLINK WD-100 supports, “Instant Feedback” of manual status to compatible gateways as well as Central Scene to allow setting multiple scene control throughout the home, with gateways supporting Central Scene. Each Z-Wave device serves as a node to repeat the signal in the network, thus, extending the overall Z-Wave mesh wireless network range. +Additional Features: +• Power 120 VAC, 60Hz, up to 600 watts +• Region US: 908.4, 916 MHz +• Works w/ most incandescent, dimmable CFL & LED lights +• 7 segment LED dim level indicator +• Remotely or manually turns ON or OFF, or DIM lights +• Fits standard wall plates (wall plate not included) +• Works with any certified gateway supporting Z-Wave + + Initial Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2299/xml + Updated Metadata Import from Z-Wave Alliance Database - https://products.z-wavealliance.org/products/2808/xml + + - + Controls the on/off orientation of the rocker switch - - + + - + Number of dim levels to change for each dim step when remotely commanded - + Interval between dimming steps when remotely commanded - + Indicates the number of levels (1-99) to change dimming each step - + The number of tens of milliseconds (1-255) to delay on each dimming step. - - + - diff --git a/cpp/build/LeakSanitizer-Suppressions.txt b/cpp/build/LeakSanitizer-Suppressions.txt new file mode 100644 index 0000000000..4c7ecc8344 --- /dev/null +++ b/cpp/build/LeakSanitizer-Suppressions.txt @@ -0,0 +1 @@ +leak:OpenZWave::Internal::Platform::DNS::DNS() diff --git a/cpp/build/Makefile b/cpp/build/Makefile index 9c1fb54189..6eed2929f1 100644 --- a/cpp/build/Makefile +++ b/cpp/build/Makefile @@ -13,10 +13,10 @@ # what flags we will use for compiling in debug mode -DEBUG_CFLAGS := -Wall -Wno-unknown-pragmas -Wno-inline -Werror -Wno-error=sequence-point -Wno-sequence-point -ggdb -DDEBUG -fPIC -DSYSCONFDIR="\"$(PREFIX)/etc/openzwave/\"" -DOPENZWAVE_ENABLE_EXCEPTIONS=1 +DEBUG_CFLAGS := -Wformat -Wall -Wno-unknown-pragmas -Wno-inline -Werror -Wno-error=sequence-point -Wno-sequence-point -ggdb -DDEBUG -fPIC -DSYSCONFDIR="\"$(PREFIX)/etc/openzwave/\"" DEBUG_CPPFLAGS := -std=c++11 # what flags we will use for compiling in release mode -RELEASE_CFLAGS := -Wall -Wno-unknown-pragmas -Werror -Wno-error=sequence-point -Wno-sequence-point -O3 -DNDEBUG -fPIC -DSYSCONFDIR="\"$(PREFIX)/etc/openzwave/\"" -DOPENZWAVE_ENABLE_EXCEPTIONS=1 +RELEASE_CFLAGS := -Wall -Wno-unknown-pragmas -Werror -Wno-error=sequence-point -Wno-sequence-point -O3 -DNDEBUG -fPIC -DSYSCONFDIR="\"$(PREFIX)/etc/openzwave/\"" RELEASE_CPPFLAGS := -std=c++11 #what flags we will use for linking in debug mode DEBUG_LDFLAGS := -g @@ -178,6 +178,10 @@ $(top_srcdir)/cpp/src/vers.cpp: -e 's|[@]VERSION@|$(VERSION).$(VERSION_REV)|g' \ < "$(top_srcdir)/dist/openzwave.spec.in" > "$(top_srcdir)/dist/openzwave.spec" +#create a vers.cpp file that contains our version and subversion revisions +updateIndexDefines: $(top_srcdir)/cpp/src/ValueIDIndexesDefines.def + @$(CXX) -E -P -o $(top_srcdir)/cpp/src/ValueIDIndexesDefines.h -x c++ $< + #$(OBJDIR)/vers.o: $(top_builddir)/vers.cpp diff --git a/cpp/build/OZW_RunTests.sh b/cpp/build/OZW_RunTests.sh index 116a2b2e33..2eb3a3fe40 100755 --- a/cpp/build/OZW_RunTests.sh +++ b/cpp/build/OZW_RunTests.sh @@ -18,7 +18,8 @@ juLog -name=CheckOptionsXML CheckXML "$topsrcdir/config/options.xsd $topsrcdi juLog -name=CheckManufactureSpecificXML CheckXML "$topsrcdir/config/manufacturer_specific.xsd $topsrcdir/config/manufacturer_specific.xml" juLog -name=CheckLocalizationXML CheckXML "$topsrcdir/config/Localization.xsd $topsrcdir/config/Localization.xml" juLog -name=CheckNotificationTypesXML CheckXML "$topsrcdir/config/NotificationCCTypes.xsd $topsrcdir/config/NotificationCCTypes.xml" -for file in $(find $topsrcdir/config/ \( -name "*.xml" ! -name "device_classes.xml" ! -name "options.xml" ! -name "manufacturer_specific.xml" ! -name "Localization.xml" ! -name "NotificationCCTypes.xml" \) ) +juLog -name=CheckSensorMultiLevelTypesXML CheckXML "$topsrcdir/config/SensorMultiLevelCCTypes.xsd $topsrcdir/config/SensorMultiLevelCCTypes.xml" +for file in $(find $topsrcdir/config/ \( -name "*.xml" ! -name "device_classes.xml" ! -name "options.xml" ! -name "manufacturer_specific.xml" ! -name "Localization.xml" ! -name "NotificationCCTypes.xml" ! -name "SensorMultiLevelCCTypes.xml" \) ) do juLog -name=$file CheckXML "$topsrcdir/config/device_configuration.xsd $file" done diff --git a/cpp/build/ozw_config.in b/cpp/build/ozw_config.in index 751798f77a..dbde404368 100755 --- a/cpp/build/ozw_config.in +++ b/cpp/build/ozw_config.in @@ -9,7 +9,7 @@ function getValue { IFS="=: " while read -r name value do - if [ "--"$name == $1 ] + if [ "--"$name = $1 ] then echo "${value//\"/}" | tr -d '\r\n' fi @@ -18,7 +18,7 @@ function getValue { pcfile=@pkgconfigfile@ key=$1 -if [ "$key" == "--with-pc" ] +if [ "$key" = "--with-pc" ] then pcfile=$2 key=$3 @@ -30,12 +30,12 @@ then fi inputfile=`cat $pcfile | grep -vE '^(\s*$|#)'` -if [ ! -z $key ] || [ "$key" == "--help" ] +if [ ! -z $key ] || [ "$key" = "--help" ] then - if [ "$key" == "--Libs" ] + if [ "$key" = "--Libs" ] then value="-L$(getValue "--libdir") -lopenzwave" - elif [ "$key" == "--Cflags" ] + elif [ "$key" = "--Cflags" ] then value="-I$(getValue "--includedir")" else diff --git a/cpp/build/sh2ju.sh b/cpp/build/sh2ju.sh index a259f0abfc..99303f7e04 100644 --- a/cpp/build/sh2ju.sh +++ b/cpp/build/sh2ju.sh @@ -51,7 +51,7 @@ juLog() { ya=""; icase="" while [ -z "$ya" ]; do case "$1" in - -name=*) name=$asserts-`echo "$1" | sed -e 's/-name=//'`; shift;; + -name=*) name=`echo "$1" | sed -e 's/-name=//'`; shift;; -ierror=*) ereg=`echo "$1" | sed -e 's/-ierror=//'`; icase="-i"; shift;; -error=*) ereg=`echo "$1" | sed -e 's/-error=//'`; shift;; *) ya=1;; diff --git a/cpp/build/support.mk b/cpp/build/support.mk index 3ffd17e48c..b026c0c3df 100644 --- a/cpp/build/support.mk +++ b/cpp/build/support.mk @@ -81,6 +81,9 @@ endif ifeq ($(UNAME),Darwin) AR := libtool -static -o RANLIB := ranlib +CC := clang +CXX := clang++ +LD := clang++ else AR := $(CROSS_COMPILE)ar rc RANLIB := $(CROSS_COMPILE)ranlib @@ -147,7 +150,7 @@ FMTCMD = fmt -1 endif $(OBJDIR)/%.o : %.cpp - @echo "Building $(notdir $@)" + @echo "Building $(<:$(top_builddir)/cpp/%=%)" @$(CXX) -MM $(CFLAGS) $(CPPFLAGS) $(INCLUDES) $< > $(DEPDIR)/$*.d @mv -f $(DEPDIR)/$*.d $(DEPDIR)/$*.d.tmp @$(SED) -e 's|.*:|$(OBJDIR)/$*.o: $(DEPDIR)/$*.d|' < $(DEPDIR)/$*.d.tmp > $(DEPDIR)/$*.d; @@ -158,7 +161,7 @@ $(OBJDIR)/%.o : %.cpp $(OBJDIR)/%.o : %.c - @echo "Building $(notdir $@)" + @echo "Building $(<:$(top_builddir)/cpp/src/%=%)" @$(CC) -MM $(CFLAGS) $(INCLUDES) $< > $(DEPDIR)/$*.d @mv -f $(DEPDIR)/$*.d $(DEPDIR)/$*.d.tmp @$(SED) -e 's|.*:|$(OBJDIR)/$*.o: $(DEPDIR)/$*.d|' < $(DEPDIR)/$*.d.tmp > $(DEPDIR)/$*.d; diff --git a/cpp/build/testconfig.pl b/cpp/build/testconfig.pl index 6c7d80a4c5..53c25ae915 100755 --- a/cpp/build/testconfig.pl +++ b/cpp/build/testconfig.pl @@ -379,10 +379,47 @@ sub CheckNotificationCCTypes { } } +sub CheckSensorMultiLevelCCTypes { + my %configfiles = map { lc $_ => 1} @{$_[0]}; + # create object + my $xml = new XML::Simple; + my $data = $xml->XMLin("config/SensorMultiLevelCCTypes.xml", KeyAttr => "", ForceArray => [ 'SensorTypes' ] ); + # do a check of MFS Revision etc + my $md5 = digest_file_hex("config/SensorMultiLevelCCTypes.xml", "SHA-512"); + if (defined($CFG::versiondb{"config/SensorMultiLevelCCTypes.xml"})) + { + if ($CFG::versiondb{"config/SensorMultiLevelCCTypes.xml"}{md5} != $md5) + { + my $dbr = $CFG::versiondb{"config/SensorMultiLevelCCTypes.xml"}->{Revision}; + my $fr = $data->{Revision}; + if ($dbr ge $fr ) + { + print "config/SensorMultiLevelCCTypes.xml"." - md5 does not match Database - Database Revision:"; + print $CFG::versiondb{"config/SensorMultiLevelCCTypes.xml"}->{Revision}." File Revision:".int $data->{Revision}; + print "\n"; + LogError("config/SensorMultiLevelCCTypes.xml", 8, "Revision Number Was Not Bumped"); + } else { + my %versions; + $versions{md5} = $md5; + $versions{Revision} = $data->{Revision}; + $CFG::versiondb{"config/SensorMultiLevelCCTypes.xml"} = \%versions; + print("config/SensorMultiLevelCCTypes.xml"." - Updating Database\n"); + } + } + } else { + my %versions; + $versions{md5} = $md5; + $versions{Revision} = $data->{Revision}; + $CFG::versiondb{"config/SensorMultiLevelCCTypes.xml"} = \%versions; + print("config/SensorMultiLevelCCTypes.xml"." - Adding new file to Database\n"); + } +} + sub PrettyPrintErrors() { - if (length(%errors) > 1) { - print "\n\nErrors: (Please Correct before Submitting to OZW)\n"; + my $number_of_errors = keys %errors; + if ($number_of_errors > 0) { + print "\n\nErrors: ", $number_of_errors, ". (Please Correct before Submitting to OZW)\n"; while ((my $key, my $value) = each %errors) { foreach my $detail (@{$value}) @@ -576,6 +613,7 @@ sub CheckSuppression CheckFileExists(\@filelist); CheckLocalization(); CheckNotificationCCTypes(); +CheckSensorMultiLevelCCTypes(); if ($doxml == 0) { PrettyPrintErrors(); @@ -597,4 +635,4 @@ sub CheckSuppression open my $FH, '>', 'cpp/build/testconfigversions.cfg'; print $FH Data::Dumper->Dump([\%CFG::versiondb], ['*versiondb']); close $FH; -} \ No newline at end of file +} diff --git a/cpp/build/testconfigversions.cfg b/cpp/build/testconfigversions.cfg index b123f30125..a8f33085c6 100644 --- a/cpp/build/testconfigversions.cfg +++ b/cpp/build/testconfigversions.cfg @@ -1,7 +1,7 @@ %versiondb = ( 'config/2gig/ct100.xml' => { - 'Revision' => '5', - 'md5' => '59d5e464fe9a3846d4950bd67df485f29817e48bd31161ba56a770aba97b1f8c5cae9a617e17b4d2eeabe0c2847281b8e17e870a0544a90749fb3e1a539553ae' + 'Revision' => '6', + 'md5' => '4fe343964064e151aac9e1b2ce76574da4b2d1ba9e9cb86b7986a27e611ab5d88a7df0005f4d04b43c39aa64e08c299ac077f9f6c85cfe5af5b46c4f3c622e77' }, 'config/2gig/ct101.xml' => { 'Revision' => '2', @@ -12,7 +12,7 @@ 'md5' => '783218e85cb8eadbb47fd3dfd1d9dc60ccd7f1bf63fd585d8fd1701cab9f3460b78afd48c30ff88bd1e6754e0f215a1f607e6a8d838b92b25fe8dad5c106ea9f' }, 'config/2gig/ct32.xml' => { - 'Revision' => 4, + 'Revision' => '4', 'md5' => '18009604655cd30d8efec4faef14f834eda15aa16f371bff700cf8876f58ddd216544a8b86af4d5a02f668ba1a9df97390017fb19b66a1d9d9851b157ab56324' }, 'config/2gig/ct50e.xml' => { @@ -32,8 +32,8 @@ 'md5' => '85a950d189684ef3797d9b043572e82f9661a29af90dff49a62a6e8e0672952442b13f113e6b9dfe69ac19141addd097e6664e8f02006f553960cc9a3add3860' }, 'config/BeNext/AlarmSound.xml' => { - 'Revision' => '3', - 'md5' => '6bbe9608c5e531c0001de1c10814afdc2ea8d4a84e618b39cea87814d8c484e4336ee1fb16721c082532b774908b00212c3984842974dcc295d6f8f5ce6d0deb' + 'Revision' => '4', + 'md5' => '8aa7047af5db54a1a47792a5a5cc63148f83a6b7dbe9e592a8a99bf5ebac4313528ec089346aea61438ff7ecb420273838f11ecd7fed7b97092b5f5eef97463b' }, 'config/BeNext/BuiltinDimmer.xml' => { 'Revision' => '2', @@ -80,8 +80,8 @@ 'md5' => '86e9af8a741a2a97cef4a2fbe8b46b558fd9903fa845cc6a09f3002b6e8d8593fbf1d89b9bd899a4cf5749411af35141ebb1fe7ddaad965eb4b8dbe49172bf42' }, 'config/BeNext/TagReader500.xml' => { - 'Revision' => '3', - 'md5' => '2aa91b0d31aabe9a9ac52582dc9afd47a0e21b4979c40bd0e036407d1d76a4d8a5b31b2d992eb06bbe7f8f2234d78ba82c3e2fc3e1e85e80ded36fa6cdf24896' + 'Revision' => '5', + 'md5' => 'e67743d1ac01fe4c07366f15806a7209a2ad458411b7a4c3dbfe0dc2e350c87b39dd72bcd7d676656d85b4fc13771aba34cf7690fc8eec0bbde116e19ca90a0e' }, 'config/BeNext/mydisplay.xml' => { 'Revision' => '1', @@ -92,13 +92,17 @@ 'md5' => 'eb39290e2085eb7493a88fba0f53782a588539d81810442fd1575d5065263e24b23e4711a2fd5df0bf7cae7ff380c605d785399e87aa658cac3f155a1d2ae667' }, 'config/Localization.xml' => { - 'Revision' => '5', - 'md5' => '4d7f5397c5dc84f6c7687dc1a3f0326f5cb4ddf62fb21edac0303bd36dccb1d75d9f044336d8357bd639f9c7ca0a4e3852a265cb2417f94af4db16e5ec37b689' + 'Revision' => '8', + 'md5' => 'cb17fb84342208b79eaa2cf41563f96e50e07362708d04eb468598c1c0567fe8d3954d15b3120a79478f9639202df168a2b11fd8424aeaa170aa9a39a923b631' }, 'config/NotificationCCTypes.xml' => { - 'Revision' => '6', - 'md5' => '3952f2a97c1b17bdcdc1a732e1a47235e4b0f0473ff0bdf9edcc0ca63d130f25270d8e25bdcaea51c772e042d757dd22195aad9e8837203eedae834def10acad' + 'Revision' => '9', + 'md5' => 'fe343cf0b94ab320774f1a8c161bc4ec5c0b3193f83067c8810cfdac36148c4c68ecad20a940514562158afdae22543fbb54f710406b070114f53606cfba4e94' }, + 'config/SensorMultiLevelCCTypes.xml' => { + 'Revision' => '3', + 'md5' => '0feafdbf1cc9dcd47c31ec4d2b380e57c6c84d8bf5819a6cc60da8cf88a80ece35a392f40cd1564e32c253be6df2e16b140cab51d1a2bf551663a01110e640f1' + }, 'config/act/lfm20.xml' => { 'Revision' => '2', 'md5' => 'f4c1366e3f7ee171137d2688de970a6e4ae2d4939c22267eda205405ce5e397c731cda516bd76225bab830e0c4cb998a4da44e249d468e88593a0151c41157eb' @@ -144,15 +148,15 @@ 'md5' => '8396a52fa0dda4e5d29b7a8a218f2fc07c8fdf734c43d916e9db558216450d435660aa7a3f0a432801108541095634dfb193720ac2fe005d895e602734dc121a' }, 'config/aeotec/dsa03202.xml' => { - 'Revision' => '4', - 'md5' => 'a6c50ebf3fe156ff4da541f542276a308b869802c4687780b967f781a6b2270012ea1b852a1a73e1696e7d4f35015f0a578d4dd140a4cf1b141b033a1e1e91bd' + 'Revision' => '5', + 'md5' => '0979e94319ead0dac6c7a9cdd7907b40202785de948535b5bb73ae2cd46c4d29ad97fd5d363dca65a6b080c0a9ede2390d015db935faaffeec84987f9e4eedfa' }, 'config/aeotec/dsa22.xml' => { 'Revision' => '1', 'md5' => '3ddb4ae3f695f1952b10592611eb98cc4c261ef4224cd681344d462283bb4732bc46bf103048708cbc43cd5fd5d9668148aa60d242dc35664973b555f14520d3' }, 'config/aeotec/dsa38.xml' => { - 'Revision' => 4, + 'Revision' => '4', 'md5' => 'f174aec88220486aa47af5d8fead4efbdf26c1ccdd8f5a6d6bc18609350d859589fdced0cfb1a07a949c3a227fbc2807ccd6328e74ee2d3368cf6d7e87ceed8d' }, 'config/aeotec/dsb04100.xml' => { @@ -168,7 +172,7 @@ 'md5' => 'fb7263fd5cfd5c64567cd8740930ae30a0f2529f24c851c2f98c851ab8f1e643f187a3ed345567300ce4dcc7f6137f9c6894ee07aa58959c0aed5401771451c6' }, 'config/aeotec/dsb28-zweu.xml' => { - 'Revision' => 3, + 'Revision' => '3', 'md5' => '378e85fb9fd12363865dc1fea1be23ea2d3699896e178c4a9ed32a0346c5aacec4ea25eda557365bd93373734bd389dc9278bbcfdceed4b1fdc0c518998c446a' }, 'config/aeotec/dsb28.xml' => { @@ -212,8 +216,8 @@ 'md5' => 'ef5dd72ffeeff633a1c3e4f800b030d15d08aee39f8d986b38b1b62dec3be5b86239d86c9bd68900b415181b3f80dcd39359719229d31e4def3025a21c61a9a4' }, 'config/aeotec/dsc14104.xml' => { - 'Revision' => '3', - 'md5' => '5f6573e5b3e1181f1cf4a3888d310251ef72fe76253392567cd00b369262be493ef5fcc0f7736dc016ca23830d68278c1688898a6f011843cbe25ebf622328d0' + 'Revision' => '4', + 'md5' => '17a2282e85a8c55c9594ebcabf655e639e05c6ff9c5fc34d735212d107cd5bb2f02de79a9d9208116a8233ee93283e5e06e56a582e225162be1745560e2ebdfd' }, 'config/aeotec/dsc18103.xml' => { 'Revision' => '4', @@ -236,23 +240,23 @@ 'md5' => '7dbc08625869c04da00c72444804e053bae36ee28f3207413fcc40591929001a69e59dfeed59eb80482c5fa5ef55d490efcf945dfd339fcf911700ec5f2a1f92' }, 'config/aeotec/dsc35103.xml' => { - 'Revision' => '1', - 'md5' => '282444661e94d42258568b07be22d05b67982b85177c03b227fcb5c9ea468a700cd1edb102df1d00ed6795d9373a579fb5c9e00d42715b67b8553d3f3f3a7c27' + 'Revision' => '2', + 'md5' => 'f5d464374a3466fc7bbf7a53858afc26224007de129cdc115171ddbf609a12282bae1fcac01f33554d9029918ba37a63b89d84f935160214e5d84b178b4715af' }, 'config/aeotec/dsd37.xml' => { 'Revision' => '5', 'md5' => '85d86525fac9158fc4fa41da95217e52dbb19eafe45a5fc02ae36f63e6ab0b7e1d7967441de798ab36f223b41f672395d6012e53ddecf25f06b7a6ff9225c256' }, 'config/aeotec/zw056.xml' => { - 'Revision' => 3, - 'md5' => 'fdaf4fcdda6c14832b6351a6acbd1ac68d67c0f02a1eedcc8a6368bfc88a2e7f12ab4f53e28067fb16cd041747281be848ad2c218be68cf952a2e5a02fd8077b' + 'Revision' => '5', + 'md5' => 'd84b9d33348e972fbc0e9d7afcccf8a9baf3ab216600a93461ba27276a16d93f2749b909640942ab4e9b9c5e6aca977df9d73a84851d25055c08973560b3b70c' }, 'config/aeotec/zw062.xml' => { - 'Revision' => 7, + 'Revision' => '7', 'md5' => '216ceb7f2224557a2c6cfd8b7e35a14c42777eaf9aa14e266c3ccdf3791c2020c3038bd4d9198bbf56d309f537004c6a9380511de115474efc371652c55193af' }, 'config/aeotec/zw074.xml' => { - 'Revision' => 5, + 'Revision' => '5', 'md5' => 'cc2f4eaea28d3c4eca92e8d354890f4dabc5f2b6bc93f92e82237a7ea243bba0e0bdfe1aa154f6b0775f846a14c0e8fe86ec9e634c1e8339c357eea80b150a60' }, 'config/aeotec/zw075.xml' => { @@ -260,128 +264,144 @@ 'md5' => '437c6d307461be670fce0b2f16f0e1634890cdbf4f5ccd43f34ff237bd68410b1bf6cf8e6a6eb029e2deb3af565a6d5c61dea6543920b20845a84dc9b8229de6' }, 'config/aeotec/zw078.xml' => { - 'Revision' => 5, + 'Revision' => '5', 'md5' => '09020a57df80e03f421bf3df6603ec5fa6e0fd50242faa53e2e8f9b3ac8e966e5735eeebad82106b458ed21a3bf8e40263cf8e6469d3c452f62a55e0a6e021f0' }, 'config/aeotec/zw080.xml' => { - 'Revision' => 6, + 'Revision' => '6', 'md5' => '78618600d24ec5b5079f23575d0559b863626162259177a93e31ff1f78540764f54ff9d4e38e84195de1709798d4a44f3efcd5c4e6cae7aff564e1c26255dfd0' }, 'config/aeotec/zw088.xml' => { - 'Revision' => 4, + 'Revision' => '4', 'md5' => '76a90cace1499ce28ec2cb7334fe3a4e1baf890732f2b272c60b5b0627c15c89ec72bf3e86ba1394aab8e0ebe6eb39e86677540af28579016430c85baeb3d311' }, 'config/aeotec/zw089.xml' => { - 'Revision' => 6, + 'Revision' => '6', 'md5' => 'e7839e6376516c3a932c2f8d32ad64d60df5a890cd5e669cacb10fb75ae0621947e3d9cb00e00de7b4bb026f8c7e4be1cc25b59336568fa1d23dd1885126b1e5' }, 'config/aeotec/zw090.xml' => { - 'Revision' => 6, + 'Revision' => '6', 'md5' => 'eda5882a0b1e3f78c95e51496307d1867a1b3dc756a0b24f705155a3a1996659e67b6af65e60bd4b800548b4b1b6bb57ff591140f2062027545612efbf2a3cfa' }, 'config/aeotec/zw095.xml' => { - 'Revision' => 3, - 'md5' => '57338297f07eb23c1ce7c2c65b18e8848224a013bbd9cf357e44d08443dd24a0c500005ee53c318f5defd0bff0710fb47134360272c42cee2ba1811bde57a23a' + 'Revision' => '5', + 'md5' => '64029aa66434ff853d0f5b54dbab6c5ab5039f9307474a6a28bd2405fe318c98f4d3fda8a718fdbc9d8765f8ce7625f6b0f9d245491f90b3559144dc9535fe0b' }, 'config/aeotec/zw096.xml' => { - 'Revision' => 5, - 'md5' => '0121752a84b04b8b56569c7c33c58a0fdd2e92bc42e8c108bd0ed0729b787f439eecd31a4122e64bb1c89e2b9e6031f3d6930d843665cdaeeca4f816777ecdb8' + 'Revision' => '8', + 'md5' => '6d1e18b9e7a418ff6eefd323b2928fc1320f034cbf93d5c10be66a2794f99f57941c67364ee5e7d0b8a15491fe5bcbc856e859be16735ec6781899f1fc1d22d7' }, 'config/aeotec/zw097.xml' => { - 'Revision' => 3, + 'Revision' => '3', 'md5' => 'f9cdfc4713dd0352b3e5069a21cf8a6a6d36014611b3ba482fe059195016111c6ec43d9ed99d1874381424970e5939e0fff6796bf8412e8c06bf9c16add43919' }, 'config/aeotec/zw098.xml' => { - 'Revision' => 6, - 'md5' => '7d6ba126654116c20ec3c50e395240536ce6b30dd5b8dc9a22370d2926fe1130d7257395f87f10fef97ce3198a3f9cd02151a3922b7336962da478c616585f94' + 'Revision' => '10', + 'md5' => 'adf310294cf46f0d5e1a833017eea6039c841b500479bc57176648e13dc27e4525591d226b60ad2ff6461483b7168229fea7885bf0d84e8c3a5169e17668dd7c' }, 'config/aeotec/zw099.xml' => { - 'Revision' => '2', - 'md5' => 'c973f5040b9353c04901b0ccb73b479eae7ca2e5c1eb49816f82946e76171b139b949148e7ea24cc0d5675f77c2f67a8cc21e883fc1623d8c34025c43d90e608' + 'Revision' => '5', + 'md5' => 'c4775cc1e44d3580cf6cadede3c1dca34dc94d9cb573888775ded7da5f224035853690d715ce8c7de0031d1e5df637d0da1ff7c1c86957755f09b65bcd4677f5' }, 'config/aeotec/zw100.xml' => { - 'Revision' => 19, - 'md5' => 'b7b7bab2aeb32f44257232c33486c563e05a73f166e604f4b9789e23bf75af57993cb7738e95613becaed1958a45aef3abc303d0cb2d3bad612ac23085c93976' + 'Revision' => '24', + 'md5' => 'd7844707b29f8fe526d94aca4b1a47a26a3639e8d4a681199bb2775024d2f273c7be634cba65062d1ba2000803491af6aa654bcf33969e7ab870ffc80ce6f673' }, 'config/aeotec/zw111.xml' => { - 'Revision' => '3', - 'md5' => '766992a483db7e72b5682bc7850e1e4187549e0328d0e91689fb36d02f1c6561c1e0354324f78582ae49871088a80744a63fced152aa13a3a6f32aca7106beaa' + 'Revision' => '6', + 'md5' => '8b12f9898911caa9368f6086a5c113b787bd6d14bf3101af07d187f8f1be8acd7b9f060e5de6355e0b1eb5d1582ca8f1fd2643a9bb3f530a04aa25077ba0d6b3' }, 'config/aeotec/zw112.xml' => { - 'Revision' => '3', - 'md5' => '722a57700fd697efe6441800c57bb3c96bd6e26a3024a33600168b67e4ad26850aa866fcda5315b7bd3ee392fcc880ef9b2dce07f2b97a997197f3a261de884c' + 'Revision' => '6', + 'md5' => '5e832838a7292144bee049fa0cff287a4de781c55c1afa5a5471d98a00a22c6a796eef7b80bcb6ad6ca15b0e72a78e90ac6d82943aeeccdd8fc78befc3b2358d' }, 'config/aeotec/zw116.xml' => { - 'Revision' => '3', - 'md5' => 'd7e7f6bf73dacd88d3738e93ace691fb2596f58b31d180e185fc1055b7a540916ca33fd4a488cc807b8644f6b7c3b979b4bb23c8b2fbd6f3dceb171eb740b630' + 'Revision' => '6', + 'md5' => 'aa24312b86df1e10ddedd71c0aa874f1e44fb49192b0481e4b973eca5a86d0e12071733ca51ad42f50d3ff09d2955952d3e0c11b2512770046795aa6ec9d7c88' }, 'config/aeotec/zw117.xml' => { - 'Revision' => '2', - 'md5' => '6096f8479b1b864e7f36f0c40bc2dacabfbb2b8c139b0deae1c0184ec7be2f308a32531101b1755df783d5fa7189069f1a77b4f841df7bb47b5a726c7beaffca' + 'Revision' => '5', + 'md5' => 'f06c4a37004d923c5131b5d81da83a3b035f8c4869cf7460e00d709cdf132ca98cda8b6d6c8efe3e123b1abae40ba2b21edb6c43e4d355c8ab0c9a893488d073' }, 'config/aeotec/zw120.xml' => { - 'Revision' => '2', - 'md5' => '796bf5c1b99463a08440905b8d6c5c638af9348cbd56f027d70d0186a8f4d11e0a79cb882e2d727c843ef74fd6c32f87acd2418b256761cb0bbc1cbe6c221805' + 'Revision' => '5', + 'md5' => 'dc9b411f14b53925f973925c79fe180d7627f605cee4f45dd53c09030b3a4e234d83b2402bf4ed348b522f69b60a02bbc318031013a489853cc2569fbc55c245' }, 'config/aeotec/zw121.xml' => { - 'Revision' => '1', - 'md5' => 'e8dd476d20ff35929896f98bcbeb93bf933966f9d8fa83cd39e6ae54338fcbab8ad5e529764685d51d1403913047a88dee7e1bc9ce3105714865aeeaf75999fd' + 'Revision' => '4', + 'md5' => '32a745da8b1a4ad35c19526739550747d4c243b93360ee64045435ad04e45e2e4148e12ed2c4f08c11efd076d39e4831395eda05651efe160fee24457b957bd5' }, 'config/aeotec/zw122.xml' => { - 'Revision' => '7', - 'md5' => 'eaae7ef0594854375ebadaa3bd78d8d058cb8260d42e9977e909d45a7f6a6ab2f94a22e34f741511b98753045a0ff59956548537433538337456dd482e99e543' + 'Revision' => '10', + 'md5' => '4c874a1d73359dd30743161b0665edfd3c7b9b16d5e4781ab13a84b5554ba2d03f9fb9480345f5192637abdde80867c4862388a10b2527c8207041999a4b4626' }, 'config/aeotec/zw129.xml' => { - 'Revision' => '2', - 'md5' => 'a62963f1b936957cda5c60663267a17f58b58935cf2538ca89a4003dddab63e120f7ffa386e8698b94face72ffaaaacc7fa44747cda5dee4da32f7c92b062509' + 'Revision' => '6', + 'md5' => '372fa89d8aacf685983efe977fdafeb25715d5397d44922ae8075b5fd2fa69e74fb4afe45ca365fd0c464aea1bd0651a93e5f0518c25a6bab98d86edf21f3861' }, 'config/aeotec/zw130.xml' => { - 'Revision' => '4', - 'md5' => 'a4fce7f4ea8924729ef6669fd16f7f4d9f92eda79842532282f2f95f83198e2e8d61a09c79477dabbd588bfd7df9dcc0f325b2154de85d539b5c2c152fe94161' + 'Revision' => '7', + 'md5' => '9e98b12590da0c343fc75ebc18b1343e4df9120f292d46700666ba53e41ee99e6a6b196a2cf4e3b5a567a844499264e015381638c418d1d9adeda9e7117e599b' }, 'config/aeotec/zw132.xml' => { - 'Revision' => '2', - 'md5' => '00871bbfdf02bdf71780953ab2b9d1f36f38b760bbe042a1a31b17ec67735ad3863fa7fa93bb94ba601c58e265a147d9d4a3cd40bb9392dcefd68bf85adb1c1b' + 'Revision' => '5', + 'md5' => 'c3a5e7f00a8b3514fb9de7b12ecfba5f2c4f85529ef5266290adcc4c01be9e5009602fa3dee17d5787715aaf57a04434b8d6f6f49d49e9279ad5b21becf549b2' }, 'config/aeotec/zw139.xml' => { - 'Revision' => '2', - 'md5' => '2f16afb6bfa8bf3bb49bdd4e9b852acc1c605c902e4569642ba8289295be27e9252882308b15b8791cdf1355dbf2ea3162594b5a91383047eecb070c3c91c3a1' + 'Revision' => '5', + 'md5' => '971cf4eb4f6323c3f983c171b744af227d2f59a13665303b1cd3b76f62111cf5cb179bb196b0fdc33d90d608716490106cc9d75946a715c35140400f628f64b6' }, 'config/aeotec/zw140.xml' => { - 'Revision' => '2', - 'md5' => '15889bcfe381910fb2f50e6eb52eb62696436badcee724e6a0c0f3f19f3dc9adcb2b0787ef162ebdafe8fe0a79ecd228bb18f547531742ad3ba7995b019335ce' + 'Revision' => '5', + 'md5' => 'b64f170b079ae1340bd4a74ef3a88f0cdf66281fa28d656b46f408b183d04c8e6a67f584f90dd6f8b2aa1fc2b2039e32b936f6f947394d28002b3d3a2a47cadb' }, 'config/aeotec/zw141.xml' => { - 'Revision' => '1', - 'md5' => '6166308cd0ab2eb96a60612e2f40952ed601ecceec92946b0dab2a81466391ffe77ed07e508508978eb6e578e384a24dc6a2cc3133b9444130f0ba38bad83eac' + 'Revision' => '5', + 'md5' => '53578d60043ed4ec1135724de795e1db8069d3a478e7caa4585ae82db0bf910f444b36cd3f10735fcc1c93e4fa307f9ed4b71a2d6ddcf6eb617b637b16adb0fc' }, 'config/aeotec/zw162.xml' => { + 'Revision' => '6', + 'md5' => '0498367a6227644ecf6dff8143c11f411f5cbaa9fa6018e234d4dbe75e5e3fdefb888d5e5032ebd1c4aec52c1842a110ea013f083d931de602dfd205b094917d' + }, + 'config/aeotec/zw164.xml' => { + 'Revision' => '1', + 'md5' => '37a2261b83bfc532e64b2aafe3b14be371f2ed9987406bc84588063bc8c0fae1b695325ad5d59bc6618db116504c4a68c74c31b231cca193a9da828ba9445c00' + }, + 'config/aeotec/zw175.xml' => { 'Revision' => '2', - 'md5' => '07e2e73a14282c74696a6c6d325e05dfb98e7b873180f7d9d2b5df57e2f3aa05380d6be9970b902fd1e1f4c44fa8b44d0dd734b99874961ec87e97cda40ca955' + 'md5' => '0c55631d8012d5c723cac19568a743397fa6dcfcdba9b30e9bd062eceec9c5eafd21690fc0fbca9b15f04c570add037f0f67c4053355fd6db994f631fbb0a04c' + }, + 'config/aeotec/zw187.xml' => { + 'Revision' => '1', + 'md5' => '146f79310f6da41585d36c8447e28fefc9686a7ad39e908f3f7dde56c22cfa00f199b647b910a1835010af94dbfafb54ad1eebc2f2789f31f64d1ed466714e68' + }, + 'config/aeotec/zw189.xml' => { + 'Revision' => '1', + 'md5' => '9fce017a9280d9419cdb71e47867fb849ae88873930e5edd6eedeadd317e6cd71953c3db3e1944c90ecd298ae1c19164e688412e7a163611375848b8625d664f' }, 'config/aeotec/zwa001.xml' => { - 'Revision' => '1', - 'md5' => '432153c03564178a012cce5eb63bfa26feaed783eb1f9497b0451f71096e607eb49c208b01793aa28061714dd709459a9de64225255c63353b1cea628f80cab9' + 'Revision' => '3', + 'md5' => 'e63fd65924332e173ce34701ba86502affcfe1e5088cac0aeaa5755a0c1e73e335727b5bdc4730784c407f8022766fc0c220e8f07e36df8e6a44ca636abf67a8' }, 'config/aeotec/zwa002.xml' => { - 'Revision' => '1', - 'md5' => 'bcfd59267c8e2236d2b629b71932cf1e549a0728c85db93a95d7aa57481d3733e36fbef91abe045f50a4eb0e0dbe39264a72b78fb0939f205fac2fa1cb326cfb' + 'Revision' => '3', + 'md5' => 'f8ae29516711f6eca7237df4095354a8ad6b69812f8032b157d875d6ec6a09cebdc03feb81e3933ddb6f7d41454b34f79b2f9b876601665c4c761f52d33da8dc' }, 'config/aeotec/zwa003.xml' => { - 'Revision' => '2', - 'md5' => 'd4b1f7829da0cb1ae40184a43e08e8641e79a6621dc9713a133ee263b84a3ea999c50c72da95f395d6b45b5074d675ba97128a53e069564665beb35de45d808a' + 'Revision' => '4', + 'md5' => 'a02624ebe5092fa4bb9514c85ceb1b0e43dbc91203ab48c0608d13f3276bd48f331fed785d8b5ef2cae1a2af2ce40fb3d258b9c1aa9d36eb808b584e2383ecb2' }, 'config/aeotec/zwa004.xml' => { - 'Revision' => '1', - 'md5' => '0df22d3e5b18377030daecdc3a834fab2c6ee1edc55ea850ccfa7092877d7797ab3bc5d192b9c9d20adb705ca0ad7b1f5423bee39cf76e0da22d637da3991586' + 'Revision' => '3', + 'md5' => '0626cc10287e159e0a8b597dc07e7f092d1ae9af4c1b8ce796ddc12370981ba4c71589d04b4549936c58f690ee8b614619208bf3268f915f32602d1e2d6aaf9b' }, 'config/aeotec/zwa005.xml' => { - 'Revision' => '3', - 'md5' => 'ba1df44adeaa27253f6ba1b3bbb1b6f55093310076d203a73d599b168c25829c059f5c5ac17d010f1685bfce06ab13d93d9b133f9219997a28d7440eff5fe985' + 'Revision' => '6', + 'md5' => '3c3441f59134243043aaefc4f01d1e8478580e03ac82a6a532f721c4d8320e5f8bf5404c93c25bcb853198b590353fb53deb364c39444fe9ca7fe36b64c218fc' }, 'config/aeotec/zwa006.xml' => { - 'Revision' => '1', - 'md5' => '485e2202979816ab6d3b97ef5abe5a3ec72040fe5a89696775187c6f4e0f60704759fe0ff9c0f483e6df8772bc1b38236a0a86ba23cb5f12e13cbd8a04a91b42' + 'Revision' => '2', + 'md5' => '08a55ab00eea7eb0fae63af644359667467bf0e31b22720bd21abb770c3b45cf0c3320039a67c8c6a33b740b8455beb1a67c9d4fa2f440cdc5056fee50f07a01' }, 'config/aeotec/zwa008.xml' => { 'Revision' => '1', @@ -391,41 +411,45 @@ 'Revision' => '1', 'md5' => '028c79db0efa85f50283cb57a22462dac7d2e7024851b5d715ddb7f715d0012b8f993829ad542639294ab266b3017fb31a62ed8fec929dde8f401dd276dde67f' }, + 'config/alfred/DB2.xml' => { + 'Revision' => '1', + 'md5' => '3277bc3318fabba8c77c47592c791a2679fb4e96a0f1e9b21c38561d2fb624452d9397b89ce9a51c3eb6d39d20444a3cc8af06cf46cbca218a52c2c7d82dc8da' + }, 'config/assa_abloy/ConexisL1.xml' => { - 'Revision' => '2', - 'md5' => 'dedfe888c9364d445fab04b9a623a7091fad7d69878b7fd23c7e400bc7f54ecd3d41c46fbf8ef474855e9325a86820860a4070d78f0d5507f0fb1576eb6a2e09' + 'Revision' => '3', + 'md5' => '87fb792063b7985b730a185e5be07e8f98d3662069b8055cd4cdd1a5f7623edd9d18f25ef5ca9c45c5489d48a91f97da914026b845ba9ed57bdd99752d985ff9' }, 'config/assa_abloy/KeyfreeConnected-plus.xml' => { - 'Revision' => '2', - 'md5' => '095078bccddb7353706e5528f896eb10438d9c1810875aa209dbdaa29a139535314ba7e51c05b43cca9ef50deb8622d192a8a8539289f126b401386bc9b12611' + 'Revision' => '4', + 'md5' => '800ecddc35ebfbd336d3bcf8880b769d4c1bf5e333085d24a38ed64fe372bd128c2bac8ad3fe6cc7929e2531c8a0d0672b2c02276e57b547c70599810ca73ef9' }, 'config/assa_abloy/KeyfreeConnected.xml' => { - 'Revision' => 2, + 'Revision' => '2', 'md5' => '4252c298eacb7e31a79c7c8fcee5e2d40b56d9bf865c8eeed53e3a29e8695508d38ffb83f558a41871e13af346c65cbdbc8a7de6caf7c5a1a67af59b5fb384b3' }, 'config/assa_abloy/PushButtonDeadbolt.xml' => { - 'Revision' => '4', - 'md5' => 'dd330883943b2675b8f7c457444d87cfc370563f840b17eee89cd9367c5aa3e0824c44a6602a800b6468e2160162644f241f0428bcaadfc7d4e45e9ce5160beb' + 'Revision' => '6', + 'md5' => 'eab93127aa1423d943e6e4bc2650b76a4a8d029d9c138011c5a713e919b4fd3e27981a73a87f35ddd2089775b925e6fb5d85976e318ccca676208bf5502570d1' }, 'config/assa_abloy/PushButtonLever.xml' => { 'Revision' => '1', 'md5' => '20533ba6551380cfb41ec7ef2e1dcec8c1b2d5e23b5ffcd87285c5a0945556989200c7bf25031cf8bdd3b39ae2c6a514565698acb3443c6bd6a3ed7ba583dbf6' }, 'config/assa_abloy/TouchDeadbolt.xml' => { - 'Revision' => 5, - 'md5' => '6e8c3059940530c557f25c34dcb8e4c643786ebd736c383122ab3e61f022db30ae8d1ec0b8722d0be0639b64f5ca6622989b4ce8d9c7e1d08e5e73d2956e0851' + 'Revision' => '12', + 'md5' => '5549c51c360f1f4c27305d6c1bda951e1a48d1072b1b1c6b3ddcbc1be8ab922fde48c3c633d58d44b64d42297da9c8093e0f475be98282745dc6d0f611d5b936' }, 'config/assa_abloy/TouchLever.xml' => { 'Revision' => '2', 'md5' => '922bb2b622dcc7c728da2fdca4d8e9bac4f3db7af115b259dcdf616addedd5a6b67dbecd5400d0a11335d8bc86b4444c25bfa755e84854988c7476c34ef986fd' }, 'config/assa_abloy/nexTouch.xml' => { - 'Revision' => '1', - 'md5' => '15a84a2a417dc14adaa9adaaba26d22ba73f9870d7e5fba72412b616dbce294b93ccde17439febe7f1c733c274f3ef0acbe295bb3672cd4a5c1228162780c34b' + 'Revision' => '5', + 'md5' => '56cacadad65e06642795966771dc7ab7058c34207ca34acd340e593156db7c10de265fbadb75c0f31574b696ebc74e4329d661f98e8e246ab16c91a55ab38e0e' }, 'config/august/asl-03.xml' => { - 'Revision' => '1', - 'md5' => '27791d04bbcdfd19f107973c5394a9454a3a6e3f1dcafe5cd33619eb4dce622c41111f785875498d60fe3a569cd74e367a00644ed1cff2db7fdc00a8dff91b1e' + 'Revision' => '2', + 'md5' => 'c20731a4c1ed5261983c163c619c36085cab448344caa87203a45f89938678cd755708bf67bb0bc997bc61120051ae0355e4465f7e50a83420f4fc12e9752ac0' }, 'config/buffalo/hw-100v15a-zw.xml' => { 'Revision' => '1', @@ -468,39 +492,39 @@ 'md5' => 'e896b83443f6776d1a9e9ad52ccbd4294c0905d2c61f1f1029c0d51316e33278efa0586fabde67562e2ed1db7dd5f98b12580b43575d8ba167041b9b80dfb605' }, 'config/danfoss/rsroom.xml' => { - 'Revision' => 9, + 'Revision' => '9', 'md5' => '8670ab88a1a580c94bd5cba9bdfe217ba8cf980ceb15ec2fe28f8def9e6bb53131e019b4029b4cf193622775a68cbe63e147c83ccd39d1da981e550870448ad3' }, 'config/danfoss/z.xml' => { - 'Revision' => 8, - 'md5' => '27ebd8afdcdfa14caf496ad17daf3d46e2d3d49373da9f5b4f6b15614ad7b98a9b15c7651b42952a6141e5e80699cf05e3b1742c847b2f8e7ed50993f80f3d75' + 'Revision' => '10', + 'md5' => '67829f0390c36d3ce36ab30b108b1c470a3e233c81bc982758f8707c0872e27cc926ed27c2587fd65656c22b551a3c0421dbe4dacca16be6bc4f8079f176572b' }, 'config/devolo/connectz.xml' => { 'Revision' => '2', 'md5' => '61e265fb8396c5b7ca94019ec7c9912fb26d975f30a8bdc286f2d2b7eb63d75be28a9f2266d06d2a7d1fc222430b74e25a330246614141ddac617145ba08af00' }, 'config/devolo/mt02648.xml' => { - 'Revision' => 4, + 'Revision' => '4', 'md5' => '90a9dd3e7ad3fba28b73ac65425ca48640ffa0962c7bcb87e3a6b56661dd5fda87a89ca9e0c3fdf09bfc96f8319b8793e9cb8089932b0c8dc65c26e7131a8c99' }, 'config/devolo/mt02755.xml' => { - 'Revision' => '2', - 'md5' => 'f02cce4cd450d120730fa6495411a89f0bf78f7f5ddfa53b695037402f142d5d01587984168567678708b5677ffe1a1367e05653c0336622cb3385028fd9ce6d' + 'Revision' => '3', + 'md5' => '8b039195599ad62f4f511f07643743f7bde06359acadbc29790328483fab0ab0d5601156735849e1542e1b2f08fa5c90a241d1a7c366d773ec86f7c9756bd711' }, 'config/devolo/mt02758.xml' => { - 'Revision' => '3', - 'md5' => '60204a49464d4619985734d3de77855725b564b84025ad5929fa5bf219b12b187901f2b9ab6de3459b0cb2a71c9e0add4feb8af5fa9e2fbe1af2f8cdbcfbe8cc' + 'Revision' => '4', + 'md5' => '14ff0b2c38401d34c8ee73b3070264d9dc5f7a8e2e0433df136b84e9590a718840b2aa4b18726eec7e40598b8f1bddb7a9f125ca17ffe1ed8f5eb3cc20661257' }, 'config/devolo/mt02792.xml' => { 'Revision' => '1', 'md5' => 'd61db8b2dd5102245fb5e73208c40af5431512b7e60e6d3cff8b98b35b4a1d1744542f5beda0eb8a4b15606e4004f111454504e6fe4dec070ac4a8ccfe07d113' }, 'config/devolo/mt2646.xml' => { - 'Revision' => 4, + 'Revision' => '4', 'md5' => 'f8715a93ad04fc6fca58e8f98d7d6d4608f62692cd825a61fbdc0bcf238e78845818fa848f33788f8d5ad3c031d969e403f96c49fa134921ed695cef73685940' }, 'config/devolo/mt2647.xml' => { - 'Revision' => 4, + 'Revision' => '4', 'md5' => 'c8591779bcb81c1861d4b1009450cd600b7c21dc11ba0660efb16ef725686dbccf2f5dda3a78abf66c0d84ed834280e99d29b0cbfd229b3741e1a5ce4f585ca2' }, 'config/devolo/mt2651.xml' => { @@ -508,7 +532,7 @@ 'md5' => 'bf1c18dbad944110d0b9cd6d4d796c77c7baaca3e51b7650f11ba84e981dc6e8de2d8a4be54e148592aeef2cb66b6751b39db4f11db5c31009de4804b51e6d05' }, 'config/devolo/mt2652.xml' => { - 'Revision' => 2, + 'Revision' => '2', 'md5' => 'a8f15a647bc553fe25af1f6dd85a43915880514e90991e3ca1dad164801b86aa2ec738f78de7e20967eac39851d34decb3e437ba083a22ca102da399bc8b6e3e' }, 'config/devolo/mt2653.xml' => { @@ -516,68 +540,68 @@ 'md5' => '54999716088a16dfb9e197b14af98c726c1f2e709cb4fb15aa29dbaf6bfd9247e236fb0e389398c25d4e74c87a488c2dbe29c0f19a8fadcf3998a7e890e9d053' }, 'config/devolo/mt2756.xml' => { - 'Revision' => '2', - 'md5' => '0215f6f8d02b910274b4217cc8f018d9c00c6075d642205524d27509312618a6c4c07db82b8bc1621da721e94e7a73f3c3e45e6f3ffd09e8d747f3b0db8e5956' + 'Revision' => '3', + 'md5' => '2907005d8044e82669ec68cedefc5b7bfa93e688221a55c8b1d3b41e387579aaf90126c60ee2fe2253a8b0ee014a8e0fb4ebe325653dce4f2a3759079570337b' }, 'config/devolo/rs014G0159.xml' => { 'Revision' => '2', 'md5' => '5a998e36359d0db43cf66cfbd59ef3b41281d12f535cb7aa57d704abd77e4e771cea236e82c8eead4ba9fb74962b536cd4431c7f6b5482f8900ba58496cfb9d9' }, 'config/diehlcontrols/766366.xml' => { - 'Revision' => 2, + 'Revision' => '2', 'md5' => '19811a36d8b2b054f026486178497b34b6c6e7819533aea8e865a57fea7bea01a39731cae1c407a7d983199ea8dae2eae7cd5ead407662ac79d35e25977c57e1' }, 'config/dlink/dch-z110.xml' => { - 'Revision' => 3, + 'Revision' => '3', 'md5' => '573c19c68df079fae58fcb4a318be9e269dfa618c38357a65ff80365a47840b9fb0f703370bd3c6d5a7409d1155472564291720169824c6e3bacfecadce05294' }, 'config/dlink/dch-z120.xml' => { - 'Revision' => 3, + 'Revision' => '3', 'md5' => '057ea9034b5751fe492a27bf4deef6c5b73fd53406649552f8817fee341be6001bb776cb5012ae6f7d8f319ada161faa29243d32c8efef9d508b18ed80cf41f8' }, 'config/dlink/dch-z510.xml' => { - 'Revision' => 3, + 'Revision' => '3', 'md5' => '0168efb962c2470418b5fb8ff1f274b5619054523605eb79341ac32e8e1e09ca817cee00c4a30fd0df2e0caa74de7740469cc32514ed0f2e3266e0dbc499789c' }, 'config/dome/0002.xml' => { - 'Revision' => '1', - 'md5' => '16aba1e00049a7b158dbff8b1be84ec6fa9933e4b0bf001d7821843c4fefd20af0e3bce86116397ed76824c9bbc7947554a86d8737bbb96dcf4947de7902d788' + 'Revision' => '2', + 'md5' => '67ed823369ab3c2446449ecd98206ac0f1c427ac66ac86b471866e3a879460f373ef33d7629a7a9bb045793894140b585c1b3079b6e8661f85ce55865151edc2' }, 'config/dome/0083.xml' => { 'Revision' => '1', 'md5' => 'df800a068d84b8f3615b232fafe6190ef9bea776c5c41f801ed127d1d76ee2decd5254b98966a2ea2b0b560a489d6279a61eafe1bfe7cc87b3e6335206fea102' }, 'config/dome/0085.xml' => { - 'Revision' => '1', - 'md5' => '8ced1de64a5cff9d47f2ae841aae223d405f956241a4866e51af28ef26edf16a61f24d171062ecb5181ceac5fc26f316852637f936374ff05e3d36baca1ffcc1' + 'Revision' => '2', + 'md5' => 'f02b0adcd4abb200640525a406f1eba3e246a5e8db82bdfd3f9f80531fa2cdec0e42d0a6ce140c3876a8e038d56f3a1e51ef9d1f5b4ae4cbec0160c958e5eaec' }, 'config/dome/0086.xml' => { - 'Revision' => '1', - 'md5' => '23480a8e87c7d0a111e88960dc3380553592a6463f949582eedf8cca9b13d6b6b9d4acfdf5d4672de410832da35224db379416fe16100e59a9672c488377e569' + 'Revision' => '3', + 'md5' => '0f86f2e63e4c1695f4cd159ada100514fcd979a5d06f3e6c9b0095ba5716a2de68d5f4dcf20bc82383d9da30050e3254251a3005fb7b14c8c1e324b329a5fb6c' }, 'config/dome/0087.xml' => { 'Revision' => '1', 'md5' => '8cbb65b02e93448094240c732e1807d0a701372d94690a90fa410f75b0b9f8eec748d7e1f190f3250d271d972de4353eb507f30221678b597141caf4134326c7' }, 'config/dome/0088.xml' => { - 'Revision' => '1', - 'md5' => '722c1908122dfdf8d7dc35b663d1bcf08317563da67b76cd3254d368d2766f370d1f1892f369bcd37b376b1b4afd15898178729586b72e14947f79c17d7d04c1' + 'Revision' => '2', + 'md5' => 'cd876175a0f5f4fad952b2bc97abdb39e82ef1b606f9f7f7303124295ee375dab7957e73535a750f9e6551479e4f48a8d55845b79a889dbed8d28e0218acd705' }, 'config/dome/0101.xml' => { 'Revision' => '1', 'md5' => '5ccce24dbb0b56cc6e5e5bbebc24e05da07750a24f64dd66a6a5cd5aec7d79a0ae59f854af5f4b40cc60806706f54cc007bb1c844346db0f91ac10c8e3b49a7e' }, 'config/dome/0201.xml' => { - 'Revision' => '1', - 'md5' => '92d4d49f683290edd96afa7b8b90424e7083c62a8ea2e0d30fd3bef40412016194b36795570a3ad06ade0e387f42232c0355126b4c2ad6ac5eba790f2be830fb' + 'Revision' => '4', + 'md5' => 'fee61cf3301b50c77758714649fa35f6d3bc3f1614124608577e3b47b897fc546fefb1a31520307f853c28726c5758cc3656d3ebe290b6ad858b43d4e99d7a64' }, 'config/domitech/zb22uk.xml' => { - 'Revision' => '1', - 'md5' => '038e46a32d237e9fe260f11463bc59bbf1a9fcff52cc0700eac534e359aa4d7e4bc54f8e56b3d8d56dba839939a847a298ab85a73909e706ca81bbf844d02a77' + 'Revision' => '2', + 'md5' => '90c85ebfbaf16201c99bd09c957a408b944034a3626a5a5c2eced093e27e6e0a8afca3d8516d7f6ace2e3889b57e5fbe585219c74ecf7c8a127d3b860970c425' }, 'config/domitech/ze27eu.xml' => { - 'Revision' => '1', - 'md5' => '797e9d169ea9a6efe3b780f755ce2dbfe321c64733b138db2c871a3f1325b168bb860d4e3b9cb02692c31aee06742f452597709e143be91d1a721a3cadbe41ce' + 'Revision' => '3', + 'md5' => 'b198727272486c632dbaf5b9c4df7dac0fb4c8c743d63f223980b764c75b747078d2754959d2a15281de83972275b0062cf6fad1ab2b83dc1a7788b2d74e0e74' }, 'config/domux/DX1CA-Z.xml' => { 'Revision' => '1', @@ -612,8 +636,8 @@ 'md5' => 'db469a75eb48481db6cc3ffcfb6590a58e531b1090cb215b3db12b8492bedd270d6068d1d716b5eec26a0fcb201694d269c106bd22095dc4190e50c8f30f016c' }, 'config/dragontech/wd-100.xml' => { - 'Revision' => 3, - 'md5' => 'ee4886d45ee6b01e41f071d75a91c46dd493ffff57f1193ec9bc50285bfafd21f3f23c3e26249a1db3410164b0fcd0daf099b56fded1514c2ebfa060802f5f9e' + 'Revision' => '5', + 'md5' => '4d7a77c213b0dea753512dcd30e3f6723f7d751d13801af9a0584a04f4182043275e3e47f268299ab44f91958356119c571a34d1022b70bf8bafc08fd717c67e' }, 'config/duwi/05458.xml' => { 'Revision' => '2', @@ -644,24 +668,28 @@ 'md5' => '29a2b8e9eadf09ee7af8441cdf46d97ab8df6271d2f1cc981acc73a9f4bd7dbf1f53449c6f71d052fa130fed9c1347a5b611b81adc46f305d704943472f54b87' }, 'config/ecolink/doorwindow.xml' => { - 'Revision' => 5, - 'md5' => '392d82d84b33148fc78c80485da6632ebe5d89ae279f0ff0826f2da92f8cce2f48836062ef63db3d8959fb00ee40903380277cb398493c58318db7725a0ec4b1' + 'Revision' => '6', + 'md5' => '8e9343a7dfd2aa2e38539833b88c9240607d168c9345686946c0d509584550130b40a40ffdeef5e8c86ea1561a138106345459ac034e7f98dcc67ea418a0a859' }, 'config/ecolink/firefighter.xml' => { - 'Revision' => '2', - 'md5' => '7b516cc68de9cf356cd5fc57a7b8568ea21f09f2b04392ac229fb099f0673c30e70e59dc85b602a9b41745dea182c9bb5111e756c239f021d94db004c4a87195' + 'Revision' => '3', + 'md5' => 'bb3c0c3231ab9eb0a0a015140702edde90edd4f0a16794efbc10a9feb286d9573642c5411ebbf5cf917ef2ecc7eda16725b95e9106032bf2ddc885e4c478ac4e' + }, + 'config/ecolink/floodfreeze.xml' => { + 'Revision' => '1', + 'md5' => 'affa47443b792317e413a8bc124477f533173a259ef9bb9e820ee9977db7cc75ec58d21332f912d65f015b46b4ed5ca0df8ea157ca03f91b483f07b6d0d4649d' }, 'config/ecolink/motion.xml' => { - 'Revision' => 3, - 'md5' => '6ddd08c356793c2f4094ed0d4372a769d1d54a3421f21739281c48589adcfb9beeea34dcc375b255caeab131b0c9e6c691cb45d1d987d2a76d232c9459cdf6d1' + 'Revision' => '4', + 'md5' => 'abde9dec922634817550f559909091b5806e1f0d42f7aa400292ed8c9e6cf6ca0aaed1bb6bab30327053643ec7883333010783b2c3e7263e45421da8dbbe31bf' }, 'config/ecolink/sensor.xml' => { 'Revision' => '3', 'md5' => 'd1897bb925a8c3c1f94ee31c3ad8cb8532be3690331fcc477444035e16c9a4b6496be1fd621f1c6c7be7575d72e55229c77234eedd956c9cb9817139ef317c51' }, 'config/ecolink/tiltsensor.xml' => { - 'Revision' => '3', - 'md5' => '0199c173800f2d015e221177808a2a5915103222b10f9b548150bdaa84959c18e56ec08590419311181e0ad258c1f3e09344e0da7049e8f9126dd3753d3b9f39' + 'Revision' => '4', + 'md5' => '59094a94ac42598b888a8a6edc2d87f08b0d47b174246fd4d22f46a71ebc1951edde9ae30a094d5502916e8381bfecb1d67d86fb9d54c9bbf91968585cf6ff3d' }, 'config/electronicsolutions/dbmz.xml' => { 'Revision' => '4', @@ -672,8 +700,8 @@ 'md5' => '461fae3791a15189acc997f64255566573dcd51612028cb8d0bb9d189a249182d86336f977b62e434bfc26e0c89f15ef839ea0786ceda7d6cb32d8b452a05071' }, 'config/enerwave/zw15rmplus.xml' => { - 'Revision' => '2', - 'md5' => 'd156554dccc9c5de29a0f5bade6ca3f91698c808121f152f7f97eaa4d0dfffda32418b23cc00b0dcd84c1e1f6e8558d757b1f20ba8b56f828054aacffbda9025' + 'Revision' => '3', + 'md5' => '0089cbf9a8c7f27a9ed4b7af8e84e594d6be66a70e1c92f0b0d85fd222355f8b8c7a03b5c584f22e99ee7c65776122a92dc74a50bd156be616327774602ae805' }, 'config/enerwave/zw15s.xml' => { 'Revision' => '2', @@ -684,36 +712,36 @@ 'md5' => '649faf0c076c9d76140c6d8e029addea7b2a82a0570b45780925d6ef435ff6478d0b86bad01078e1acb4761c71bae0ef85fbff28a8e1e1f18a587069ff7111bb' }, 'config/enerwave/zw20rm.xml' => { - 'Revision' => '1', - 'md5' => '8c70693799814bad677e06dfcc6cd1bd588141e35cdb1eeddc048fd455dd6d17052d10431ffaaa8996011e361d5b1b8dad7d4959ea02c00601929f48e49c169e' + 'Revision' => '2', + 'md5' => 'd1d8e3db4d73e61674548aaaad10ff1543cd19339b5888fe2a9885e932d3a2f09a88f9d93ff62f0ba036e8a5cc191102683af39ea665f10de43ab1f31e56f2f3' }, 'config/enerwave/zw500d.xml' => { 'Revision' => '1', 'md5' => '7d6d24d8557afcfed2d1fb8620772546730f5ec5d6dac0115f5461d3565d6890403783455e5e7d8010e326098b5cb7eb03b816df9d6557f46b6447e893c075a1' }, 'config/enerwave/zwn-bpc.xml' => { - 'Revision' => '2', - 'md5' => 'c75c70e725ed82efe3462ddf718b36a55799ce2f4b3fef558dc3e75b321a9828f239159903718c303f2250f6de06bde361da6c2d00326eca0ab4632127c6744e' + 'Revision' => '3', + 'md5' => '39b03cf30d1e29f45854d2328f661abf76754e635e4b1f6279d90ace3b4b5c57fb8d883384520617a70e499b79390bbbb3bac3d53260da19eefda686baf0bab5' }, 'config/enerwave/zwn-sc7.xml' => { 'Revision' => '1', 'md5' => '96404c642f3741b36f865b0486bf7ca0dbebdea208da28cace87d10181be77c14d69b455aa0cecdd2a3864d9b0b741c999da786f1b5daf75e2c906da568084b8' }, 'config/enerwave/zwnrsm1plus.xml' => { - 'Revision' => '1', - 'md5' => '271ba31d42afd56eb308035dd3f640be693753b584153e6db36603bc0329a9337e00f56004b87a4eb993eb35bfdd56099de4ec4fb58d9d80d0d567d1eb926f92' + 'Revision' => '3', + 'md5' => '6725ee78062fb147fca3f41f1868bb520abf637684dee1a2cf39c2257fde1d98d90eaa6a2a35f54f768e013557889552b2458e72f37b81079e39b84053b39182' }, 'config/enerwave/zwnrsm2plus.xml' => { 'Revision' => '1', 'md5' => '88a742755d7eb4a455adf6378c70430bb73ef68deeb3099cc280087eb015eac40e426c7f8667cf073009a3c9abc92e695ed4933142726c28c7a24324f25f54ce' }, 'config/eurotronic/eur_cometz.xml' => { - 'Revision' => '2', - 'md5' => 'eea6188bddc2b5902f69852d2304a118c98ff27b68fcc3560429d569f1c4ebabc9f81f6aa7549c55873351ea017a578c1dd8f6c5495ebf88aa202f4154abebe8' + 'Revision' => '6', + 'md5' => 'fecc7214a3cb7334806e38686fa9e4635caefff7a7bac8cf98af1b1a6dedefaa33a7a943f6435d5ae8d2286d39a69c08b3fab173ed29fd367de5fba6b321886b' }, 'config/eurotronic/eur_spiritz.xml' => { - 'Revision' => '3', - 'md5' => '0affe52693eea2e089ffa8a92c02b55a5aa0d2d289df4475e11a5ceb8efcf2a1f2c44cd40a0b6206b10a333374c7950033600ca5ddd80784c76a0a1994438498' + 'Revision' => '5', + 'md5' => '0aa11f27796457c03ca1de6842ffb31d7727edb6ceebc689fe7c03a71b29445807e331a6cac4f2140ae1e0cde9355bfed6a52312afe84c25c1f2b61004021776' }, 'config/eurotronic/eur_stellaz.xml' => { 'Revision' => '4', @@ -724,8 +752,8 @@ 'md5' => 'aadcf1eadebff5fa7d508e5970dbdb043632d9b9f1c106ae4d872b11127e8bbd67755114c016f52aa4961ca92069eafcb42c099ad8f919578b334015bcedb6d6' }, 'config/everspring/ad147.xml' => { - 'Revision' => '3', - 'md5' => 'e8d4dac699ee77d2955a308b9df468d5d513efb24f6a162da88e64f6d5bab66f93de1131db21092b5845b0e70c4a199ef787bb39ce2399f05c43e6b064d0cb7a' + 'Revision' => '4', + 'md5' => 'c48e9fa3f0a31c8f082ed9fb16a08787251621b3902f15a13c78c7e319ff254c8001b4883f3721ee44bd0b5584679e2a98a68d7ec005562b08623ad5c7f1630e' }, 'config/everspring/an145.xml' => { 'Revision' => '2', @@ -748,7 +776,7 @@ 'md5' => 'e39532bf66154389eb31e6f1f6da5915c40cd8dbb682152eaaf60931dd8ea4992be1a11a1b9ac58fadf40f965e3ea7de03e9deb34b7b1ba63bad9485dab53877' }, 'config/everspring/an180.xml' => { - 'Revision' => 5, + 'Revision' => '5', 'md5' => 'c1118724c848e37cb666af3cc4338314075f9013e1fb47caa2f8eef00420e80fe808c0335828154bda037891e0dc7b9769236c28dbea8e73240fd6d2daf9139e' }, 'config/everspring/an181.xml' => { @@ -772,7 +800,7 @@ 'md5' => '6579098c7dbeb3ba683016cfe27ef08805ee7dee2d9cc5e3b94e4df010d8672e0811d61fa70533061c822d766a849daf3fb66b1f18e87e90ad02862ed76ef8a0' }, 'config/everspring/lptdm1u.xml' => { - 'Revision' => 9, + 'Revision' => '9', 'md5' => '8cbffa88913207a3a149123dadfb6f9db9686886795862237723dd73cf75ca28f0e85eb57aa66ceffc21974ca40fe06f0a877605096cd5aa65e351a797af9d23' }, 'config/everspring/se812.xml' => { @@ -796,12 +824,12 @@ 'md5' => '1eb7a9708bd399b1d76a9b91b48e82367b141fdba05c99200038ecc3a425bc459c320bdce5ebbe8ac9496e1eddb5d9faac0119ff5cbe4046ae4553ac8ef397aa' }, 'config/everspring/sp815.xml' => { - 'Revision' => '2', - 'md5' => '22e9a238fd9b1ae5effb306677fd3209e266736eb8fab7d4997c1be70eb3610c36a7ad0f872e58d8c6c422e6c9b1f0f3ee612e7f2ea92cfde05085934e18e10d' + 'Revision' => '3', + 'md5' => 'e8ca9d3c02c9b238f2a8198eb349389cc8b83fe9c95639abd361672a27b32fd901690c03ebdfffa6baf3f9dbbe76d8090fc7ff6baeb955d5775211f0e84a27da' }, 'config/everspring/sp816.xml' => { - 'Revision' => '3', - 'md5' => '0b80ba58de878313ebc463865f35c08517f27b0020d8649c873325f353796850d3378e96f97c9c18ff5bd73ae3ab8996c2380742bff850f861a6dc347787b005' + 'Revision' => '5', + 'md5' => '2a6bb41379abd9b55599ad5bdc59c756c24ec41136f5fb797f8c69f35d32b04f81c1e79acae22567d58e2eb5cfd79678b13185b9762217733e41b04ba453bb09' }, 'config/everspring/st812.xml' => { 'Revision' => '5', @@ -864,68 +892,68 @@ 'md5' => 'addfa55daf406a745a852792ea34a1a6e83995d7ed3755789a7f29081833e1c12b5599b537dbf3cd36dd2d0d41d145f6174fda43fcc22b02361fd6dda7e1d425' }, 'config/fibaro/fgbs222.xml' => { - 'Revision' => '2', - 'md5' => 'f17f0793e059bde25c30ba637f2c60ca59ee74593994e19befb6c1e014ceaf9a038a66f7e29542166c23e2dbb2203198f0e47649d9a44d6df647dd572b2761f5' + 'Revision' => '4', + 'md5' => '9e7a4798a3f538dd041de9528ae8d948b6852131b8f73f7b9db0443a3eea9eba5b3fa16ad3282b23a4d817f44c470258938282c402f2c079a0853d2a18052231' }, 'config/fibaro/fgcd001.xml' => { - 'Revision' => '2', - 'md5' => '961abadfed37bfe65b2df1bbbd7a9b95e99ee1a0f6d19e06c41c19d6c444ce4840e3f95345edf9c24280388b2a050f01e1dcc17e477a85427814d99c579091f4' + 'Revision' => '5', + 'md5' => '94e7567c5a4c746afb36a90bd8f5879df6d8f95f6e2241d3fd50accd32b3c363aa2cc6454e51facfa5b17469385e9774622f7605566577692c02f40ec3eca2d5' }, 'config/fibaro/fgd211.xml' => { 'Revision' => '3', 'md5' => 'e579604d1d754bab281b4f701ca02b7f08a4b89692f4122defcd1bed87acabd1d73aa00d1f76986c6d4bd01ad2646a1369f305e793ddbcbc9e212cbe920de42a' }, 'config/fibaro/fgd212.xml' => { - 'Revision' => 8, - 'md5' => '8c05064e396b18820b82116ddcfb49432710e3eddc862e91d79e9ce82e6ee2af9d5266ecd003af5ea7c2acdfd58568acbf123197f8e11645548d54caa4fd0214' + 'Revision' => '14', + 'md5' => '21d87779df4aaf0c9619b9d3260b2e1500cda54534f89ebf272f154afdfb1fe2163107968376d9de8f43203e4a9ca45f0ffd1f5226d4690c443ca87edee630bb' }, 'config/fibaro/fgdw2.xml' => { - 'Revision' => '3', - 'md5' => '1358bc9b66bae4b234bf29dff22c2b31ee3782db8d91c8be258f0f41c785da265857d8393d71ee46e5564ed87d122d816ab5f9f412d7a3fcfdf5bb6d50426fba' + 'Revision' => '4', + 'md5' => '722542ab5ea6086a921290c5d01d7554e05fe93bc5bb467e562913ae6e1b989c807bb2eb6b172db4875e30fb8b68980395995c16626f7fb0a4f3af715fd5f687' }, 'config/fibaro/fgfs101.xml' => { 'Revision' => '3', 'md5' => '12015e24fc0e3ed9a40a9a36e372629d7a858917668b531852d52206ef0c52f438b70ae0c91310304ce004fbad8e0115fd875da1eb9ffef5c9323416f9d71cd3' }, 'config/fibaro/fgfs101zw5.xml' => { - 'Revision' => 4, - 'md5' => '06b9592c9fda1b1ab7af092bdd5a48fae46fe12c945427c9fa0302761b391af661e17a9bf914c3ff48e2999de842a085ac5487e2d920b24e434e786dea85fcc2' + 'Revision' => '8', + 'md5' => '28385ab08db45cb56171e3f9130f275fa3e68fae413150a8fe274e45988092e4316e8a727e208a9a75523719d66a187ba8387c1567ccd5e19fe7fe72a5ee7882' }, 'config/fibaro/fggc001.xml' => { - 'Revision' => '1', - 'md5' => '88882915e1065ee799f41c714fb2548cf12e2a8c75286be72b399597029067ac56bc6931fdd6f6b484fddd8a18cf17a0be7f92ab9c568f9a2acf9d1147669f33' + 'Revision' => '3', + 'md5' => '050a8006717af518041d68f2055eb5adcc759c077a0ff55ec66218b7f049151189d0e7896b66e1bd72ce6e6bd42eb7a071f300096e02a3e92feda34a7ac588d4' }, 'config/fibaro/fgk001.xml' => { 'Revision' => '6', 'md5' => '675408571e8f8fc679fa60b304c79a103c12b4dd4880d896e45829387998ceed01379216c916bddea2eb7d9d5d1d4fa4cc0315e979a8275e6fce25b179535c26' }, 'config/fibaro/fgk10x.xml' => { - 'Revision' => '3', - 'md5' => 'debfe464dabf3bf230e3dd64bba97e5c97254aa54da9b9d5e1cd325785346e9e4944cc7699ac3feea23571c76d0e9f5cc4dd0613b5f8b6869696da898d190932' + 'Revision' => '4', + 'md5' => '15b64a691b43a5c3a24753849d6721aa3241ccbcb6a6d8e5d43d2222ada1dc1fa0b08f5bdded9efc5de56391825be228435aacd6f7859b419ebfb4f317f0cf56' }, 'config/fibaro/fgkf601.xml' => { - 'Revision' => '3', - 'md5' => '6cefbd7970e1bd4cf4361ae24d185a17032d2f176a34b43879015234bb89c77435c373404297a977af0617905686a4c38164cfc572ac1cd731011d2fa8738746' + 'Revision' => '5', + 'md5' => 'b477def6a8d30e0399f8b4917b6c8317fcb2658b24f702bf8c1591b54b8a3d0ff4bbeb9e9790227d1edf2341efa9e123669644e9ee39cda91e869d42f5f14642' }, 'config/fibaro/fgms.xml' => { 'Revision' => '6', 'md5' => '76242fb913189103b1a368f5a5e4329cd443136b0b38e67286867e4170cc75527549130b1683015b93fbce90a7c9f7a95b3a22d3913c322e4730f44078b1e1f9' }, 'config/fibaro/fgmszw5.xml' => { - 'Revision' => 4, - 'md5' => '858bff191a3cd6fd77818354d303da6bf0477796c6438a08626c8e1dedd08d373008a50be49951da067619ebdbe129ece6d6f1bdd26f1549d8bcda40e8fc746a' + 'Revision' => '10', + 'md5' => '47c434a0d05848c52c3ec693f491e978086eb90d926a00ffacd7056dd645bb1bc382ee348097e26613665b08429031aa94fe5d600810815431f530791dca9214' }, 'config/fibaro/fgpb101.xml' => { - 'Revision' => '2', - 'md5' => '6a0f218e42c01aece6a20aaed6a03ec080a57afa468fafbd6a85ab431aadd2c2c9a78872b4f0f75da611db9427c5450191dd3deab783e4673bc8ae6bb4a14822' + 'Revision' => '6', + 'md5' => '4a688fdca007e02f3ae2e13e11745ab591c4dd4e58dcc9f9034c2de91e694a506cdcc99c4059d94b1f154dde6fbef84d6f800c6189a0e11e75429a3e413c9923' }, 'config/fibaro/fgr221.xml' => { 'Revision' => '2', 'md5' => 'b1ac55805cb99bfd01a6f7a553fe9893e83f4bc1a4f299c0dac1a29e931c41c119a0a81522351e8639881c92225e05170134dab379836e40c36c7f3724377622' }, 'config/fibaro/fgr223.xml' => { - 'Revision' => '2', - 'md5' => '75c1cea404a2db56e11eaa214a0e11b584a2c03a0cc9d79d6f4030a34cf67d068b671bf55d13786f14c8625dc79e2088c7ca16616e3571bfabea562da5342177' + 'Revision' => '4', + 'md5' => '10d3acdcfb6738324afa2f6c4c0547f29bf04634fbe774bedeb5c160c547168d5ffa1dbfc8740aa4c12c5b928ff2e9d8ca1ca99c5f7f2a366b6e037371a32e69' }, 'config/fibaro/fgrgbwm441.xml' => { 'Revision' => '5', @@ -944,8 +972,8 @@ 'md5' => '6b9c4b6b47544b2acdb0820ae6e914b6f25b322e88b99e48392e6968d0e57203a051870bb87c3345132385e48d18597f829c4790d21e2b270babe9b92d9faea4' }, 'config/fibaro/fgs213.xml' => { - 'Revision' => '7', - 'md5' => '7e277bcd77f7337090433d6d3da005263ae31c752b6a9cafe2b0b81d6eeb44d3be5c0bfb80ec0eee1ad860c27de807f8e4b17e0a1e7aa1c4cddc11a3a86d1e29' + 'Revision' => '11', + 'md5' => 'e41844de98b9d3c13bdce42661f3126dd742e92e834255ba4926a69a305a9d6e0f629ff16ad7018b1b299e03294b21a7b2250e68278c3f2e2f8134c46ffa3119' }, 'config/fibaro/fgs221.xml' => { 'Revision' => '4', @@ -956,33 +984,49 @@ 'md5' => '4adea0927515ef9146d48192bf09fceb0132df7a8b770ebd89d5473b92a32c12fe500e47ba31acdfc28cfb520e4d43eba5b1fbe3fa49ef5331d8a433ca83de62' }, 'config/fibaro/fgs223.xml' => { - 'Revision' => '8', - 'md5' => 'df3ce7e5214c0a7b288c59837ab25ba5b9589789739032df8b59acfa20f69083b8f1252c0eec883d276a9813df4ff22fe07bb4cd3275751037b8ae32b0fb4d2d' + 'Revision' => '14', + 'md5' => 'a20bca0d2a4fbc249391a9e21197c4481e7d650d90cf6f52a9c10f6783b576b083a7979178ecff6e64e17a6266e197f155105a8b57c5346e404e99db3de395ed' }, 'config/fibaro/fgsd002.xml' => { - 'Revision' => 5, - 'md5' => 'cbbc5aa6e68325d1b48b55e15494429387e0554908112c4f73834c23cad9ed0e61ed8c1db3705724aaea3717c6487a1fe31fc500e0d97d96ea7f7aa66a60da19' + 'Revision' => '6', + 'md5' => '1ecd3c58332deff5907969650e409a744494f69abe53cafc61c33421ec8686d6443161dfada159048f47f903df5b260ba4b1afe978c252a664d87cc13df48c1a' }, 'config/fibaro/fgss101.xml' => { 'Revision' => '4', 'md5' => 'b3ddc92e51ee5a0ac5eba30f3cdba72f8c8aa114b2b474f3d7096d0092ccf9ae8ce6042e8f6182f4a07129a891e6dc83517be0d5d67bda91893ec0bb210f0f45' }, 'config/fibaro/fgt001.xml' => { - 'Revision' => '2', - 'md5' => '94bac4c8de2593430dafdcca2ca6f830a3910d41f6e3bbeed6f3ea96d2abb80c6130ad385c347ea93aecff389f369972e51fcc81f6efe607a566ba8da454ab02' + 'Revision' => '5', + 'md5' => '64b989c2046a0c572b8e25ee2c3c595e1a5c2eb52e9c6a29d96cbe0c71b33d4a46bd640e551564e6794aeab9a5e7a9a011c0e7430ab2b52de518ba9cac81c3b4' }, + 'config/fibaro/fgwd111.xml' => { + 'Revision' => '2', + 'md5' => 'bf6d95da83aad31068f0f62fb3abf1d03481f63dcaa347f8fe6a38cc8d4a2bd9a3031722f9a4e73cd6823dc151fdf30772c4c3b5d4f06bdc6df3120389091057' + }, + 'config/fibaro/fgwds221.xml' => { + 'Revision' => '2', + 'md5' => 'cf74c8f1c18eb10c407b306c1b8d6faa536f8d9c1a7f21e1bb90c28e1502054b52a0970f820b118be2e235c34b57aeb66050b653255b48ea4aa1f811b4a20c7f' + }, + 'config/fibaro/fgwoe.xml' => { + 'Revision' => '1', + 'md5' => '117d888dee07fa6b24bf1a69a144e631921c7f06ebdb0e90632560ecf45872eabdc82e2821d734f260585c660dfd47737c5948a44c9ed21674e13b8e1533824f' + }, 'config/fibaro/fgwpe.xml' => { 'Revision' => '6', 'md5' => 'f099c34442fb3d67723c59cbec6b31d2d383686b583ac013607848e3d8dce2a9628dd96a10751a027cf8d18c4714b0272dab073dda20302b1dc5820f18273643' }, 'config/fibaro/fgwpfzw5.xml' => { - 'Revision' => '3', - 'md5' => 'af734f023eea8602278477144a62a34ba203c6bcaacb78b6e0ee6c3c92d705945be6f766cd665d60f6dbdbbce9254e6232d211ff75bcbc9263f7579e470f420c' + 'Revision' => '5', + 'md5' => '61fc9df991d5a091c0a05a92ea37c4f76d18e52d9cc9252418b5525a32f48cc8cb9815a42b05de2fa8cff62665db88094eb4b99114d5c157671337e12a8230af' }, 'config/fibaro/fgwpg111.xml' => { - 'Revision' => '2', - 'md5' => '254e9029e18484c0e100cef00435a98edd45809f10d555f88717551d78071acddd2f8f934983ed17848b6c7d88421c494804128d2e2baa23a46cb09e6031c01d' + 'Revision' => '4', + 'md5' => 'ff622cfe98037421901a2087f85d5d7272f3fc0e1c77c5b357708588cee4f4f47e61141c833c9b7af4734f2ae109dcf2e1e3d44bc6f6d4a39450ec5de8de5ab1' }, + 'config/fibaro/fgwr111.xml' => { + 'Revision' => '1', + 'md5' => '14e1efc7dd30097da9adb3b5c69ea5c114ea63806004f553c701cf7833aeea730b4fc1cc30913b1cedcf1e2e88aa2f7785cef3384663df68a879a0a3a5b184e7' + }, 'config/firstalert/zcombo.xml' => { 'Revision' => '2', 'md5' => '6550cacd482668a1c7561434bf094255cabe30b5beda26c406e2f9f5a772fb19176f2c0b28824f9015ee64b0d4f737f5f9b35ad2c133852f7286160ee337844d' @@ -992,24 +1036,24 @@ 'md5' => '3142c3cc8cd97d218a3f3a31d841d308ab0a51291fa2a57a3c13c3cc45cad79350d958463bd1667d596a99206c5759877a7423692e714437e922f9aba5bee6ee' }, 'config/forest/fs2z5232000002.xml' => { - 'Revision' => 2, - 'md5' => 'c1233ac3728fc648db0d7f000bf13147b15802e6592e2aaded7301d879ff6be8aa126fa107f0261bbe38bb5f12fd6394c710b68a0f0d52f0dcc2c0529d6fb3e1' + 'Revision' => '5', + 'md5' => '5d023a7e60f4becae275c45eca40de4772fa5650f13158727dede39a8011ba03000e5ad3941542279978f6348d3f85bfd45ad6b02a0185e612b1662f6a4bb25d' }, 'config/fortrezz/fmi.xml' => { - 'Revision' => '1', - 'md5' => '616d821cf130384c1a7da3baa5cdf0d5b8d8348ec313d9707c28fd1d31df91dd34fac107aad9b311149a88f7380a0b4681e6b5f919be1ba1c35c9a73a883a693' + 'Revision' => '2', + 'md5' => '8f7ad8fcf6fdf93c1228bde5f5ad12cdd4f6681ea96e2fba2e59da2b84b9a9ce5fbd288a1f3a859ccc640ad77c362191b3ded331a15c0cd15ba1007c4ca8d4c6' }, 'config/fortrezz/gdc1_fortrezz_1501.xml' => { 'Revision' => '1', 'md5' => '48bfe2a8c75fd3c17a87bb4405908dc9c835c131d7e8625760b93a8c8d4f3d6895cc8fd8483913bfad697d12811f42c82b9ee41168baf068ef2616d4bec65800' }, 'config/fortrezz/mimo2plus.xml' => { - 'Revision' => '1', - 'md5' => 'b4314d913bc7a2365b13b97cf3257f89b53c16658f92232ba5e287932f8ffcda09f15944fda7f3608cbe1597dc4d818f78088ac69c512434eb4eadaa8abe7762' + 'Revision' => '2', + 'md5' => '6016f3d62b2d67fc6c21749852db2bf0f158534a6aedeb5414e2e23b073ec505b86653725ee4ca69b61b0d2577b6c2cbbc09a390e00babc6d813052cd7c6ff84' }, 'config/fortrezz/mimolite.xml' => { - 'Revision' => '4', - 'md5' => 'bf52124d6608975179d737b0ff70e0f422135c67bd5d976110df7d502c15a15bef67ba572f3d26c664ae4e23288e8e1e88bcb1583e0560a7da1782396b94b17f' + 'Revision' => '5', + 'md5' => 'f8643c66c280f96588067d67f33ae3aee81243fe1ea5677ca8f8b3e0f21282cc968b98af61fe5a1772a6ac02f00ad44d9c130caf15552e49d40879419cb703fe' }, 'config/fortrezz/ssa2.xml' => { 'Revision' => '2', @@ -1040,116 +1084,136 @@ 'md5' => '2cfaf444e663bf9f6bcd25d8c08ef14163ea9c938c106556ecb6bba22641bb47b066c323bba6c7db49f4f731ee12eda16648ab9bd8e0b3f1bf949bce8fd9cfeb' }, 'config/ge/12719-plugin-switch.xml' => { - 'Revision' => 3, + 'Revision' => '3', 'md5' => '17ebbde5eba4998fad0e35f252461259606ca8e88d0eaca3437cb3ccabd36797b28671660bb7955349eaff19cf617d86f20318693d0766f7c56a14998d2c43a8' }, 'config/ge/12724-dimmer.xml' => { - 'Revision' => 6, - 'md5' => 'b0af51305e3d37fb37bffd9d33f8833dcbb915868b50efdaaaaaa8d47d37f811dca3b171c115c8e099e5a039f0971269ad911cd580c9bc1650b6197efe03e08f' + 'Revision' => 9, + 'md5' => 'cdb1e185894f7a80aa5bc4e24aa8b0bef64519c19421b27836fc93d8df2107d981fa947801fc84ec312d0bda4048afb12772b478345805a425a101525d8d6a29' }, 'config/ge/12727.xml' => { 'Revision' => '1', 'md5' => '2f1fc4587bf2caf5d982f45535996a36bdb93adb7de8f089e9ca8bc042d91e45677bc2f5997d125b3eb1e93f533c00637ef6d7106a9c456878aa8523ac52dc07' }, 'config/ge/14282-plugin-switch.xml' => { - 'Revision' => 2, - 'md5' => '3e7f44966344d995c7b09c0d70862f3f9528c9c38c8dd242bab7f474760c1521bee03adb398e17efc1407be1264a7158160b93bc097bfc22327b3c192e12186d' + 'Revision' => '4', + 'md5' => '72ec968ba6c64f65c48fc8ef9fa33f623717bda452d0685547735dea6240ef4efde6a1da95f683cd5fe1efdfaeea834a13412482a305c05423c21186c7edaa97' }, + 'config/ge/14284.xml' => { + 'Revision' => '2', + 'md5' => 'cd3edde334dc3c489b23b3148590077b6e4f3d2a50fd3530fac2e140a956ae6cc41ed1d435ea47388456d955d7fcccf0a399225d76d1e58796c36e406d42491c' + }, 'config/ge/14288-outlet.xml' => { - 'Revision' => '1', - 'md5' => '5d29381e36f1baed91732ef3e2ef091267f4eab1bf88b6a6b4b5a4e1c263c4053fb75e63eeec2e5077da9f13b47eb746b9b885a897039d80f9db88ac79d38971' + 'Revision' => '3', + 'md5' => 'd9fb1de64ede9d3da8730b73e67149d87f383aa45d878cb1fc54fe59cfc4b636577f35c58823484f3d5d830b0080aa69b4c86a934225c521e11a7f81ca07fb93' }, 'config/ge/14291-switch.xml' => { - 'Revision' => 3, - 'md5' => '82c2499a710fb65090410914e8c0b53a273ecdaeb7b05d64b7a91c882ce0ab10cefa718f9ebbe7eb1839983e50f9f777ccf514dc835200a9074146807a1578ca' + 'Revision' => '5', + 'md5' => '341219ad5f6d3fb200034d60733383e2d2499c3486b2389b11984895a8ca577b817c9b986ebf875973424771aca68d1b1800df5d710e3dd4121963ab530c2140' }, 'config/ge/14292-toggle-switch.xml' => { - 'Revision' => '1', - 'md5' => '729859e23d5dd42cb5c185267209e2017122b2d99a85b14bc28c379da765e8217dcebbd63254fcbcec11498a3941091013e265bc51c7dccee7a9ec0d20e58b57' + 'Revision' => '4', + 'md5' => '499251768ad6b8c824d1a20f49270d9ecb1bf8681067654ffe6a795aa3a5b8ac314e3a75047fade9bfaa31dd57879b16556fe5c4e04ea82db570f99c0171e177' }, 'config/ge/14294-dimmer.xml' => { - 'Revision' => 3, - 'md5' => 'a32c72065c87d004be3573a5fa9735b1c91003a0a105610af499aaaee4fc26485095c0e3ff2e5fc08f954833769caf8de4efd8bb63a904f370fcef2e8fb47a77' + 'Revision' => '5', + 'md5' => '1328e3b4a3457a0d0627f9842b6a1c47439c98995ab05cd86b1a3bb0228f8051b5839a4e69275635715de08e7c816dd32968c3b6db310b139318e71871a7a24f' }, 'config/ge/14295-dimmer-toggle.xml' => { - 'Revision' => '1', - 'md5' => '126b14bcb75732ec85e38a54267f51903c7016ac4885b81fb5a6ff670b9159953d300cc4bc225cc86970bc12b3eb18864c30ab3689d2ddc9aceff7f532708597' + 'Revision' => '2', + 'md5' => '936f319de3f6658b448d9c27ee2b6c639a5702fa2669a750ac841e13e2dc5fbfd1c686ae6805cc231b94607c36781d2bd7214ea81fdbdf10f11efd4a7f9c9848' }, 'config/ge/26931-motion-switch.xml' => { - 'Revision' => '1', - 'md5' => 'dd0a942f5699a7461986155bd926df2a6f487e7dc1e6e2fa13ac14675c8318d592003466c4ea3c7497bda60902ad94bc316db19835cf9a2d0ac6e416201c6e73' + 'Revision' => '2', + 'md5' => '80cb83a0ed9a932b0fc85f6046fefd92065741aa6d9d764417a0718edf1d528680638842f199888b8c0c2986b7cf3b7930744ca309986668d1d605ce68b59d29' }, 'config/ge/26933-motion-dimmer.xml' => { - 'Revision' => '2', - 'md5' => 'a0e33bf27c364f43c016c1717d009e063ab94d8bc10661e547553c59a8ca57702a5ad44dd7a74ac35b96eb0a672cc0cd96540af9477470daad1413fa083f1ae6' + 'Revision' => 4, + 'md5' => '0394fce7c7e8b1b3a5181ca36230cf10ccd13c4a34ebaa67f39df0af12316d58ba9bfdace934a02d6bcb4f8d12d86cba5bc113d0660b06fc833c0794c47e9d24' }, 'config/ge/28167-plugin-dimmer.xml' => { - 'Revision' => 2, - 'md5' => '509b7d178598987a1f4b72dddb8ddf0dfc89a37b024dc6539615469bd5372891810052bc52d5db8d731fd090baed3e97c5e664d7170ab74c379c8c1450d79fa9' + 'Revision' => '3', + 'md5' => '3ee59078343932afcb5732ec56eb15c259f360f3a4adcaee1f632350f057581372ba65a0c33ed51f6b239096db43231fa64a439a9307c3b9c4c9e23da0ca6995' }, 'config/ge/28169-plugin-switch.xml' => { - 'Revision' => 2, - 'md5' => '5be631bd12ee6e7d05eca2b97bddc3b4915c752dbe3c1d22452b34e417788c55e52e599315d19d6f456fafa339a46910181ec2eed8dda40f2eb6a94ec0e27ae9' + 'Revision' => '4', + 'md5' => '58980d447abb1f8c82167ba043aec5546a8ace8e6ea9f4129c521b363ae3aa3d7c723c64901af5c6bec6695d7f0aa85e4975ca318da9016deeb83cbe6aaf5e59' }, 'config/ge/45604.xml' => { 'Revision' => '2', 'md5' => '1a651b322ebaf4de9f8b5a03c9604cf55e6140cd1a64f45814e6e8818d83dc4e0988f7f8ffcd318ca3d9424f24e78250b742fa87025f682e22560e1774d18df8' }, + 'config/ge/46201-switch.xml' => { + 'Revision' => '1', + 'md5' => '3ae4ec70a396a21c7b8e72f979c343f715f133b2a53d827b31f88ed45e17fd457dfef597c64b13bf36b688d21caf42c1e488971c2128a3baa8a5d9d4b887da13' + }, 'config/ge/dimmer.xml' => { - 'Revision' => 15, + 'Revision' => '15', 'md5' => '69d688ae37c8887da28d801b24305f9bd81ee1f9b1cea214c492340ded4144263955f4325a229b33c22d5ac0a7f327b358cd0bf2100e4d096e9772822a0960a1' }, 'config/ge/dimmer_module.xml' => { - 'Revision' => 6, + 'Revision' => '6', 'md5' => 'f917273cfc180539f9dde977978e68e7ec54f30d2ef2378a2795f7c4519f93d52d9af4b860c190ef059363a562bd105899e3d5464b84b07e52af6ae417216112' }, 'config/ge/hinge-pin.xml' => { - 'Revision' => '1', - 'md5' => '4f6d9de564e89d4c3eeedd778d7aa7ae4594877b5143bfa8ba9f39d3e765617fe02ed30ffdada6fbd9bd1edad4a22a2d8a32f5ee96b32fdada58e301dbebfe00' + 'Revision' => '2', + 'md5' => '195127b7310facea584641c8c4b0de9f80c787db87f65ac10a0b0f876fd061014828d7cd32e72d2f9f2eb146deb09e3278ec5cfac299ad1a5586325611a3f52e' }, 'config/ge/receptacle.xml' => { - 'Revision' => 6, - 'md5' => '9b4b5e7822f3b52a4819470289eb58e2544f7b3a352172645eaa280b3ccb2eb9e7b5243625d5fa31336a3d2cb6649fb7964b745b93c853574116f5d40a3e3ba1' + 'Revision' => '7', + 'md5' => '3d226b9b6330953a94b786a712451067c0df84cd688feee5d156ae43ef847d490890db44629aff06771a4edad590ec0e12983de15ecdcf64400c499c8b956c8e' }, 'config/ge/relay.xml' => { - 'Revision' => 10, + 'Revision' => '10', 'md5' => '2796184b6ac7fe9f8aceb1a09221cc6a1c8c3844a039a484057dfa71f704ddca8c05b038cb6352f1df9d10972b328dcac6277749d8dc2b0197b4548760db213d' }, 'config/ge/ze26i.xml' => { - 'Revision' => '1', - 'md5' => 'd0e8da8083c42876f02ae8019639a1875e19321d76b010c386ee823c60e1a591fd8238b6879af4b748a841412beff0dc8c97744162ada449b1be9b61b193669b' + 'Revision' => '3', + 'md5' => '48668adae273d804358eb6ed626833f2576e08b25484914c8b3b5704fe2918392ff77467390677596b541f558779e9cc07b56dd1907f866ac4c1f858800b6f4e' }, 'config/ge/zw4001-switch.xml' => { 'Revision' => '1', 'md5' => '56d8b8c8c7c1450298ce238cd73f0e5782812a48a6794e2fb82a65fc32150862c5283294cd90cf9874b0085ca52dbd620710322dd50bf3e38da3d74d70ef0856' }, 'config/ge/zw6302.xml' => { - 'Revision' => '1', - 'md5' => '2feab4d33003698c5e18a35f756f3a0227d3b96d2bc1913b19d8e683313c9d45ca3af296d0fff7e7e1b98af87548988d8815cd866d823e0bac8ca320c6816242' + 'Revision' => '3', + 'md5' => '914ca5923b09d0ada05f866efdb91b060b4ac305b5a709facd1133e986c4c5399a242527e2caa0b84cc08c0cfb467e19756a5937dd8d990104c099371b0bcfd8' }, 'config/gocontrol/GC-TBZ48L.xml' => { 'Revision' => '2', 'md5' => '15d627a3d9de686ec39e3cf2cda1adcb335cb6b38ae807106007a69416c45622ccbc9fa06f2b7ea4a9fed73646497f8600cf54e27e879ef90d71fda6fa19d452' }, + 'config/gr/gr-302n.xml' => { + 'Revision' => '1', + 'md5' => 'a151aeaebddc3e1b697ea96f455aff329e374662ebb64849067dd74f50caf3a96d32750aeff1005f7df557fdb6a3f75aaf94190ace1566bae5bb25019719b0fd' + }, 'config/gr/gr105.xml' => { 'Revision' => '2', 'md5' => '54bfe047e99c0701d98c2220492a0da6c98d80abb22690916c6de4baad6a0fb473a2ec6f5ec3369e7ea31bcce54828300e43fb752ff5efc867d8e99c2f7be6dd' }, 'config/gr/gr105n.xml' => { - 'Revision' => '1', - 'md5' => '8891ce9ab24a796c14a18e6be3b2dbd8f686edbd3bbd178c0c91452fa64fa5ace1d0aeeb6596818044f9234d5ede7f40e45c181ba564d7d2547d426a28409362' + 'Revision' => '4', + 'md5' => 'ed10e4f95c410c9a6e9b539bcba6298f052c35867326105777ddd9e19d6d7677ee5ca9d2bf862a837b420fabd8b74e25483b637c7a71e35c6974dfe30e09dcc5' }, 'config/gr/grb3.xml' => { 'Revision' => '2', 'md5' => 'a03b12da4dc4cd30c564f72efa4ca00dcdac5c7a7dff878dad7ada0a87675fdc271a1408a5187a5f3349eb4809886b1064b2df6f0b4697b068308a57b337e97e' }, 'config/graber/brz1.xml' => { + 'Revision' => '2', + 'md5' => '20de3c410b7f5e4230670cc72a74a5c0aa055c452538072f17146558addcb823ac1eabe84ed5e3c5b99520a1263f3e2425a53869d1dc5ea714cf323488e88f08' + }, + 'config/graber/csz1.xml' => { 'Revision' => '1', - 'md5' => '60cf2330edcb70af53de169fcd854f6df92185904d2a053ac8667da7d42bba15fc60059db20086510264f8f8a8d3918a3729c4d1827b94302c766c4a508f40c2' + 'md5' => '536a0b35500ee8ab596c1093763c408e4b7ec61bb808f73495f0c89e25e038522fd4f35d9869fe5dcf54c51109260d35a53bc525c446040110f771a0c4cda308' }, - 'config/graber/vcz1.xml' => { + 'config/graber/rsz1.xml' => { 'Revision' => '1', - 'md5' => '8b2021d7d8a89de2754f8c6555276ae60bbee253888bcbae9c47811784b13ba7cce25782342dc474009572aaa4e30fc9fbf20058142492ef9781efef9f157336' + 'md5' => '598bdd923d527543430b89d86d2f0260c26a59017a3f44d7eeba00ce809bf01f9a0161041d1b9745a339dbab0f7f0d8f984504a74dad89921921454273e666e9' + }, + 'config/graber/vcz1.xml' => { + 'Revision' => '2', + 'md5' => '3b1ed59b630c3e890e80900dac25d798c48661a01e7cab554777f51f7bd3acb1e11d5adb0170011576b302f52611ea2489a082481bcacb00cebaf5eccb24f262' }, 'config/greenwave/gs1110-1-gr-1.xml' => { 'Revision' => '1', @@ -1163,90 +1227,98 @@ 'Revision' => '6', 'md5' => '1e575738b3a559c2de13dfc9632fceb800dc03c8ac5691ecb0d0629a57b607d1046316d8ddc3a87db9e4fe1dcae57fab20998845f1b6d699953d555af71d179a' }, + 'config/guardtec/gkw2000d.xml' => { + 'Revision' => '2', + 'md5' => '280feec2b7433f743ebbacfe437dd6b1423b38777141a11f22433e29177b9280db33d2f15a26da0a9b0940c93c47d29dd874e7ae7b12565de709dd73ab669a9a' + }, 'config/hank/hkzw-dws01.xml' => { - 'Revision' => '1', - 'md5' => 'd3a73b7c5d0c29f92d07f6bbffdf4e57d95ffdd0024712f5d34e34d891ff9fce3a49867875df5f61e9861e432ad5e09689917b260208b77ea5f0c64aad470818' + 'Revision' => '5', + 'md5' => 'b11d36a38e54d9c4f36fde7224db3847a5e0bb09e5828ff9ef8802ef1c67000846513ad3e91b2cedcf19e91b95734b4d2864a4d44a32c32bab7b16e4a5adf46e' }, 'config/hank/hkzw-fld01.xml' => { - 'Revision' => '1', - 'md5' => 'ecebc82578e3842aa30214732898f72d454bdbe79da316ce292403fcc1b7c2a362ad7d118ed50e4b97c299b1300cd4606a2b7482be6e6ec095be3b90e52ddecd' + 'Revision' => '2', + 'md5' => '02bd96bd02e95491700f0c6efd92fcd89e1c306bacd5d58d7f2f364d0df24bfd034ddd150215419537c7af5edbcf18da75eab1e77a5aff3a8140526fe527a58e' }, 'config/hank/hkzw-ms01.xml' => { - 'Revision' => '2', - 'md5' => '64f89b7ff728d98bda0a29a9e14320f11a0e1b3777a2535baf845273ca35e8fb660beed26cca226843ea99fcb872fcd3e97ef498ec760ab50b6089663f1151e9' + 'Revision' => '3', + 'md5' => '8a04fdaaa929db3866654b4b01329d13e3e32c449f711b6e23d78ab244106238ab73695e9a7002a80e203934bd1db1871dd6e5541dd944ac44ceb72b6c946d2a' }, 'config/hank/hkzw-ms02-200.xml' => { - 'Revision' => '1', - 'md5' => 'ee254cc8c2cf29a5a59911f3be721e923e395ff9a8be30c5577df4e4281061fdc9404b7e1c7ee0989f3da7ff536340e6e565867a6a96a9ce97448e1fd2bb3298' + 'Revision' => '2', + 'md5' => '412110b25652a63fd8fa53a0e8c465f8d73a1f1a8ee3af7c2e989e7446e6ff70c577af28cc953059312bac9dcfadd5801e61f2669d723c0991534084eac07344' }, 'config/hank/hkzw-ms02-300.xml' => { - 'Revision' => '1', - 'md5' => 'ee254cc8c2cf29a5a59911f3be721e923e395ff9a8be30c5577df4e4281061fdc9404b7e1c7ee0989f3da7ff536340e6e565867a6a96a9ce97448e1fd2bb3298' + 'Revision' => '2', + 'md5' => '7e4f9dcbe624e04301dd0b7363747633902930c2a1f59d832bdaade1b0c76b5f0b22287275db2d2bcd301c69993a2800f4db0c92ce52ad7cb4fa40a680687c97' }, - 'config/hank/hkzw-ms02.xml' => { - 'Revision' => '1', - 'md5' => 'ee254cc8c2cf29a5a59911f3be721e923e395ff9a8be30c5577df4e4281061fdc9404b7e1c7ee0989f3da7ff536340e6e565867a6a96a9ce97448e1fd2bb3298' - }, 'config/hank/hkzw-rgb01.xml' => { - 'Revision' => '1', - 'md5' => 'fa7e6034bc2fde37b17145e9a5cb836c63635c2cf67eb1a4410004300d976fe84f16f610a87cd8db2f87a06c5b059de461736cdaa0710e6938174d2a25ef42ab' + 'Revision' => '3', + 'md5' => '35476c9eb132e78674d3e0fea1f757dc4508e0c390362b42fac1670fc6398078983b5253de0cafe95c081daacef41896bc760a3c50dd89905f7bf070bb991e01' }, 'config/hank/hkzw-so01-smartplug.xml' => { - 'Revision' => '1', - 'md5' => '3a4762a1580cd3080d6a37105d53786d0675b6583777921447e8487393319808b7c5dc1d9e1fa2140a511d9ef17195700f43a4cba85f8f780654c3f581066044' + 'Revision' => '2', + 'md5' => '9c1ab32ee4af6cf8b1d7d3437a9d031861d48952c015fa6fbe2e8c54940c45a718fc669975691a32eb53c78f1acef8dd231faaaca643fd1b22158c5655269f8a' }, 'config/hank/hkzw-so03.xml' => { - 'Revision' => '1', - 'md5' => 'f4c999aba0419b2bce0631a3443e69b776433bbdf48ccb79e2e965ce72b2b88f1a3337828ed000df3a8b00b08e8c57331bbcd1a152e34331edec50fd43d27126' + 'Revision' => '2', + 'md5' => '3340deb59e1570b2c07fec06e4b13cf1159a9274f6b87fec2c846388ef9f47ca9a3bf3af2d306202d84e0b24adb226969f9ab6f7f0e7c3a5c916252b1583fea7' }, 'config/hank/hkzw-so05-smartplug.xml' => { - 'Revision' => '2', - 'md5' => '6818bc12fb654f87b5bee143e25a68b4bb5ad3dc428170356bf541db5ece0e860f523939250fa3936ce371893cff3e06336336c51e32a98c159596df0703bb4e' + 'Revision' => '3', + 'md5' => '6dc4cc5e720bb5c534f25510f20c134baffb3d4b1f68704d397bab9775b6b14397471dee6469f230ecb81afd79363837589a531be926a7d3e789e82b4c1c5a83' }, 'config/hank/scenecontroller1.xml' => { - 'Revision' => '2', - 'md5' => '7be78f1208706859e87a8be34907fe8a2a84d57d2a3df2f5ac76deba414df7f71a017690b84a75aeedd13b5d49fb768b3d7e09e50b45a6bd430bccfcc3d6c8d3' + 'Revision' => '3', + 'md5' => 'e748ff7ae3bb3358e80b863cdea2103275dbf536edbd538963502c7629aaa623c49b562d092cfbf4db17f7fa2f4b191223ad1e9513c86b58b937eb6504145f7c' }, 'config/hank/scenecontroller4.xml' => { - 'Revision' => '2', - 'md5' => '235f8b248ff647471fb8c3ee348b4360891d63f1455da64a24db82582975083ed4962a8808cb555eaf17d43c305ed3e8b0f819f32e8885bb85d8e7e7beda3369' + 'Revision' => '4', + 'md5' => '25e5e4f19385dc44c8d33dd0372837fd2befb1d12b5bab7dc74027a3bc12875e56afdff854c363cb0bdf186aee0f5717af03b6c62f77409bf365176c9e953aed' }, 'config/heiman/HS1CA-Z.xml' => { - 'Revision' => '1', - 'md5' => '4c80ad9405ed1ad63092c8459f4576d2c0234bea77cc0df7d44c98fce4222fb0dc39ad36a71c80b55b5a11d19d7290e897c1ca5a2eca29ca8683bfa8c2fdc11f' + 'Revision' => '3', + 'md5' => '7a20a77d2c2c7633b0a116d68c59325cf1da6cc57f83845d9927212b5864804f0e485775c317ca4728cf901764622507abed325542816aa4ec62b36cdd0db10b' }, 'config/heiman/HS1CG-Z.xml' => { - 'Revision' => '1', - 'md5' => '5af4d499b8e4ac2a6d6a202beb8bd4af02ace4683e0d81dcd5f9a7f7df19a1e8e09cd3a49493f0470da88bac19c67fec4da426655a05c95782af654fedaabd7d' + 'Revision' => '3', + 'md5' => 'dfadb2f28046d15b412034c106537d03bff4b224c0f4c4808d4af54f5fe045995cc31b1f289c215c34288ea10a82df5a7d9b26a3a20db67859d346a405a55136' }, 'config/heiman/HS1DS-Z.xml' => { - 'Revision' => '1', - 'md5' => 'ddd2229b60c2b5ac009055996154de2780b50582c9ce4307949d6a4d0369cf34e7d9e2e3e1af64a2db06210bd7b84e99c47fe5ab9a73f03a1bb3816b0f78ab72' + 'Revision' => '3', + 'md5' => '210a2d51e707e26c6619428919e5e44694c06e15bb2b111a1ef5f499a3f2ad2c4c99fd07482b824ba3dd7d95ab9e2b5219ac1805c1566a52f3ea1a88b6b7fcc2' }, 'config/heiman/HS1HT-Z.xml' => { - 'Revision' => '1', - 'md5' => '566d5acdc46072a647dba6cc05f9ea44a33c529266120011118ed599544317006474374494e8253bb18ebbb3d2983f3e48577ccd450d74fd475d3e168799bdf3' + 'Revision' => '3', + 'md5' => '1331770135d4050f99c83dee86a0e55f0dc59bf51430f083f2b7ceaad3ea32851b9a915f821fda1fd4b618041bf82c5afbe9cd7f74c0e5b73d0f5d47450008e8' }, 'config/heiman/HS1MS-Z.xml' => { - 'Revision' => '1', - 'md5' => '5e4c5ca9049ef3d12b430b4131d0567527ed359b36b38c0c4e84525fd0ed4606f04b26aa6aa7ffd9f19f05938524c37c3f154f24d0451d27f060079e9452913a' + 'Revision' => '2', + 'md5' => '0dac77cd6892ddce000c77485c595ee219aef2f83b3e7cfa641981b37e1476bea55855120e19ca80c302e566c58c328e94148ea03e734f8f4d40f862c6e6d6f4' }, 'config/heiman/HS1SA-Z.xml' => { - 'Revision' => '1', - 'md5' => '23e1ba0b091abf690b736cd2a97698c61e572d3dead692937cc3a918d95fd87624a696f16d72b262f3a3d0bfcf812165d18144124b35061d62b97920b3a71cec' + 'Revision' => '4', + 'md5' => '217ed29fff544fc5a36fc5d1b26334b84725ad6ff6181e7080731f7dd5c37ebc8d079e37e70e5cd50ac87a014066b84978ac3b0d7b080dee55d12fdaeb8db019' }, 'config/heiman/HS1WL-Z.xml' => { - 'Revision' => '1', - 'md5' => '4b98b356a19d6b3eb765511e438d1fe6936b57282b1af2479b7f750dfd43d8a8756e4aae9e4f5f22d3c1a95ee3bcb1696b3735e9bc2c2118204de7841781a01e' + 'Revision' => '4', + 'md5' => '6821d6247218a026a8832f72df5c2b3f76abd2b3b95b18302201c5bf7e0fe1fbc22659078056f5188a42981304d635088e2018c5bea98565c19a45712524cbd5' }, 'config/heiman/HS2SK-Z.xml' => { - 'Revision' => '1', - 'md5' => 'a3a58bce8baa97beaa95cf99e3a84f8fb6af72b36e6708f1561712168b408fdf4bc35863a28c20ffb9f7077cfbb967ff5b3d964da74253e8c788b607e776e944' + 'Revision' => '4', + 'md5' => '2717377bdd18d9b510f85c815d842930080a10ee319f64a43241b2cebcb8b7a2a81628ae9b4aafa95719c3d0530eb17e75acac1a444446a14bb829148d7d2bef' }, 'config/heiman/HS2WD-Z.xml' => { 'Revision' => '1', 'md5' => 'c2ce7171aec99ffae507edc6bf9aab24ccd539a25e162c93c410cb83404899bc33956bc3b50aadea0adbc75acbc0e1a655f92b4496d0d2b725b784880e7038c5' }, + 'config/heltun/he-zw-sw-5a-1.xml' => { + 'Revision' => '3', + 'md5' => 'a4f75b095ae18579fda4a9a5d857466ed83fb0d8a3679945aff2ad419c72c5b96960db4aa84168911ff0cfae551151b38e95a4156782854a9ea3a0db5576257d' + }, + 'config/heltun/he-zw-therm-fc1.xml' => { + 'Revision' => '3', + 'md5' => 'c819a5f9e0f64ab5bbde2ad1754b7e9825564f6a7b2b1e63f209c711b43dc5445021c59f36f0a06d4970ee315ad8df1899c74a7934f94a373448aa2a3cbf5bc0' + }, 'config/heltun/he-zw-therm-fl2.xml' => { 'Revision' => '2', 'md5' => '1eeee37ed56959421b124f96f69dbed1fe93ed0b230c2b6e0a133bcbb1bc34b4da975ee6f5193e793f46da217a1c0ef81d132f7ec0b8571289e284e98e42c186' @@ -1255,65 +1327,69 @@ 'Revision' => '3', 'md5' => '8d4ea274a67cfc24dd3c20205bd4e2fc8133233ed99fbb2596d7162298c0ad4ed07ab327356fb5a07e1424d6634de27227bc03b70c7a9f06754f82360d854537' }, + 'config/homeseer/hs-ds100plus.xml' => { + 'Revision' => '1', + 'md5' => 'bf724e9e2f52776c8837b1a46d465d2b20bdab25733b1775d8665e00329c82f1b9a194a5e6c2539df754abc90e3c83b6044388e1e7019b2820f9ea3c63e64aeb' + }, 'config/homeseer/hs-fc200plus.xml' => { - 'Revision' => '2', - 'md5' => '321bb4b28f0d70e0f90292bffa3e7a00b1c626edb5cc3cbc4d750c7e62d8d1deafe3b46fd3bdeecb46e0be8f281018a208a6b46b1ce35183e3d2fd4747db1221' + 'Revision' => '3', + 'md5' => '2c8076f31efdef00d014a58a4acc35db4e256175c57e2e93c3db183c66f52fe7a47feea880c2cd8723883fa860a540b81bb52cfd17c04072b7b9a5a6e06126c8' }, 'config/homeseer/hs-fls100plus.xml' => { - 'Revision' => '1', - 'md5' => '1f21e50d716953919c31b72a208b056bb431e369bff0f0fd8544f53654771acd4d32554804b7cea69ca1b76bd11a9c4257ad4d1ec24f65ed211afc4326a1a7a2' + 'Revision' => '2', + 'md5' => 'cdd48d1045234e40dc257caa0df6eff883426833bb19d55587da53b78e9362eae2699f3cddf4b25f6aefbab24d06c0fe34ded0c7bd12b03853a2c965193a754b' }, 'config/homeseer/hs-fs100plus.xml' => { 'Revision' => '1', 'md5' => 'f22c8e1b51b207c4dedf156b3bfc76e5577dfdd650eaaf96ee51952d5e42a555ab1b827f449be147bfc17fd3979f84356fd19d3ec4ed66c5dc3e639ee99afe34' }, 'config/homeseer/hs-ls100plus.xml' => { - 'Revision' => '1', - 'md5' => 'aa03be07a07a5a52d9dcc94735696895a1df134a1b8210bdc7cc4f3ff1ef19ae29896d5456bf8a8af0d3f0d5d47fb8f2af402594328a921290b064a1a6628212' + 'Revision' => '2', + 'md5' => '05e3aaee1cb368211d1e4867149f1e914bdd7d5da5e558bccfc9bbd60180d212ad0c76b1b95095bebd074e2ad64b52e15e893ef65c73e765873f0e73219d8a25' }, 'config/homeseer/hs-ms100plus.xml' => { - 'Revision' => '1', - 'md5' => '94dabe266274dd83fc72b16f6275d80b7fd35e6193fa9cebf483c491b1db37f40650bf1cd2c05bf3bc5bd0723de1df691c2968b6068a663d869e5824dee58438' + 'Revision' => '2', + 'md5' => '528e313dab27daf86c92e7ecfbf311077842bdff72f662c308d0554a308691b9a9c5830bc08dab5a4860991053c6a73b05d5c21f1cf115a8c70c873adeb27a5d' }, 'config/homeseer/hs-wd100plus.xml' => { - 'Revision' => '2', - 'md5' => '6ee3d3d33a4a2d3a86575bbce091117ed847c94f2d3870f07467399ae62f2380ef4d855dd7a697833cafe32254f8553cca0cd502fd2ebc5efa8b0939dce4d2f9' + 'Revision' => '7', + 'md5' => '58dc37e456d17f71693c819806d931e2e71fa36811e384bb225e9fac00539a80aa0df1093c5b48a0b8c58de2bfd6d1e0bf3f20ff9e8aca331d6530962fad0240' }, 'config/homeseer/hs-wd200plus.xml' => { - 'Revision' => '1', - 'md5' => '0158e3bcc2a4782b00bc918f0f29f733c29db02974a202000278d144880e75b7adb593c2fb238d8dcd4f7808aefbe4b73f9171610594fc5a26fb86710707afee' + 'Revision' => '2', + 'md5' => '25187da0fac3b2752ece5aa716e0a883577782ece97e6bfb604faee0c2155690ffd837ac0ed19afc00cffcdf2145b260797b3446620e12f4ddf3dcbc7d34d818' }, 'config/homeseer/hs-ws100plus.xml' => { - 'Revision' => '2', - 'md5' => '485ef78503bab5dbc63b3bd3464699a95e960f5dc96efff2a9bd438145247f01404cda4c0c6181d13acc8290a2b900e91e9fd20574da49ec3b45f4d71f5de4ad' + 'Revision' => '4', + 'md5' => '8dc36ef5c448b933464a3541eb156b4f9bf8c99b87f1e117ac1b881056b2cf03ddd53a7a6535a7f88210956a15c51ebce71dd5bf89daa9daac3ef2e27880e727' }, 'config/homeseer/hs-ws200plus.xml' => { - 'Revision' => '1', - 'md5' => 'ea9604645ac9a62b9547c11367554879a59212eaba8ff537c2691a0823a80afd58749ba476e9fdd09d1506cdc5e3c945054cb1eeb2466b2875790481a7c77d93' + 'Revision' => '2', + 'md5' => 'a34e0e874f7b7cf55801068535eea231f80ffcb6564c1a6e3ef4fe41c7da677c00340d456f4b79a413e657bce7b8847b6d7f5b293c7a8a0309713f1cd3872214' }, 'config/homeseer/hsm100.xml' => { 'Revision' => '3', 'md5' => 'd3078946530995d9f5cf1fc432617617466d8d100a3a368f619bf4762c62ba852d20a4c0b9c19321805995f4f3b15d4bdf98efe3e4c1fa7addad3aa6cfbcbdb2' }, 'config/homeseer/hsm200.xml' => { - 'Revision' => 4, - 'md5' => 'dd10f8050495a3d05810292b9dda60cca88f4a569cc34705c44de141055d5ac42bbea3539caf3b2a5af7f53ee196b3577b93b366a2d9c935f8c04da8b0d11824' + 'Revision' => '5', + 'md5' => '05846519da65becb8e4d36ef93040bb190fc7e599e11dd1a82619a7abde98fc3393d80f08160d74911b0090925c4fe04d419628cb278feab92c586262bcd7be0' }, 'config/homeseer/ztroller.xml' => { 'Revision' => '1', 'md5' => '46f0c29d16537254242bd4458489767cd57709b2d0c5faf5ea6ba92778d35362c72e998352a92964c67c81b9b819d66cdac55131154028d5928f0842c96f920e' }, 'config/honeywell/39351-ZW3005.xml' => { - 'Revision' => '1', - 'md5' => 'd21ae692c37548ac5243f6110e8167841179a72671fcaaaffe8eb62e278f1c8bfda52c1c85805f0a750f28da50ca591f210e813a3a469fd67b8919218a6781df' + 'Revision' => '2', + 'md5' => '9bcbbda3dbd837836905a4d6601aff515eae4bd452f5cde4676c490e04d92eabb04abcde02f5157a3f41fcdc3279ac87ca87b7d73c2b422e5e3432a51f140cf4' }, 'config/honeywell/lynx-touch-l5100.xml' => { 'Revision' => '2', 'md5' => '530fd1b4c43248f55ab6bcc788e80bda83eeeafa515f8b812e07b1f507399f163145ab3337d8f26d6bd7313de6028ad13502c7ae2d07f9b4ea8b4ca730cab0c0' }, 'config/honeywell/th6320zw2003.xml' => { - 'Revision' => '1', - 'md5' => 'e4ef4d230f25dc28736ecbb36e18b2b029ea7485cb43ff4a9872eb75468246c9d1a5c283836620b8dc94a7c6f6357d7434f69a72438ffb5cee937fec3f45dbca' + 'Revision' => '3', + 'md5' => '8a0acbe77f563e0aae7ff5ad345c82d385af65bfa46d4b846209cfc03c49bf6c2895163092c1be788cdd17013cc7cf0dc74d8bb3c8e750546ffe9da63120e2ca' }, 'config/honeywell/th8320zw1000.xml' => { 'Revision' => '3', @@ -1328,19 +1404,19 @@ 'md5' => 'd9f875c619feaf1136bc76eada1cd63a3c7396d6fb8d4b50c2515264eca723c0420d7afb58290a8a0e2c4f7b780c154ffddefc411e64cafeeda941494b3702f2' }, 'config/horstmann/scsc17.xml' => { - 'Revision' => '5', - 'md5' => 'ab4488e3e1ad13da3a997ae315225676ef2b622a557c0f349e01f2b7c65ac3e019b511d1cfb34f164e17bbf639a5300a27b01527f8fe6f224438f9854efc0df6' + 'Revision' => '6', + 'md5' => '689b01ced1d29a5cb443a11c222de099c2ea19ab4d355d3274c5610f0c8356940bb3d97df684bbde76186483ffc7e25af3b5c3df173ce9bebd207a9c3509fe1c' }, 'config/horstmann/ses301.xml' => { 'Revision' => '1', 'md5' => '36f2fdaff9dbb847944983cdd4d542db17602846822d67541265a3bf5d913cbb82b05c7e9c964948a5298e145223820ba029936d990eaf66fe3c2a124ee854eb' }, 'config/horstmann/ses302.xml' => { - 'Revision' => 2, + 'Revision' => '2', 'md5' => '7b929c04ea087fee4dd1c2ec08385d8587f3c5bc7371c684f1f8cdb5bc42c9140a0fa496cd2742a611301f7231e39780f9f3aa2848d52da5f730eb778926769e' }, 'config/horstmann/ses303.xml' => { - 'Revision' => 2, + 'Revision' => '2', 'md5' => 'e8ba07277647d361613657702f2c181c3092499e561aafb2c612ad106151609487a39763f477a996952daaf8e5ffb3db810280dac73eb77d2f1cc239d7af6bce' }, 'config/horstmann/sir321.xml' => { @@ -1348,11 +1424,11 @@ 'md5' => 'a3f4c5fe213ca7ceafee96eae84b01c8146f72e3e5715e8a0d9added2bfb6640a868f91c7e743172df177ac6c61d237112c82768419a8ceaee2305efad80776c' }, 'config/horstmann/srt321.xml' => { - 'Revision' => '2', - 'md5' => 'a26ec2d1896f93408c31c279150826616e4e0509b03c58a6025ede158fd25de90bcbf77d676d1a15a84cbac213f2d8d1b5013156679ce216dc1dcf5078defd06' + 'Revision' => '3', + 'md5' => '322c5d1195a2aa4de8a792befc4103f048280c914a6bc0d237a7dbec8d14a4ec26cdea4274082011a041d88ec22fc288b0f856719cf59fe343b9b7094861c386' }, 'config/horstmann/srt323.xml' => { - 'Revision' => 4, + 'Revision' => '4', 'md5' => '8585cef3b015848b99920976e699e68bd519bca47fcbd11c6059d04a3629ca99428119965cb060848f1b2eaec49052bd8a4c7a537c083769dd30c132baffdcc4' }, 'config/horstmann/ssr302.xml' => { @@ -1360,25 +1436,33 @@ 'md5' => 'b244edf548e853864c9698958e440fa7e4436c63806296e39b2f70ddebeb1dc591e7f13456edd002911ccc5f945a8fd14b2ef9f18f4663816371a17a424b5027' }, 'config/horstmann/ssr303.xml' => { - 'Revision' => '2', - 'md5' => 'b9e320c377566126f183bf2097b4f4f3bf11e5c23f654051b7887661d0abc0f60100b5caf57dc1a83488fc8415eb9dc81162e4eb1d955043306271e54bd65ad0' + 'Revision' => '3', + 'md5' => '9375b06248963dddbb3bc64fbff19537cc4ef6e4c4e7fe946ebc8a40280ea32217104d2ce4eacc12449e9ea3f943aa9e38447d18215bf2dd1cfd40c242dc73af' }, 'config/icare/zw-66.xml' => { 'Revision' => '1', 'md5' => 'c35e93e83039a1eb91d700668764769e8117761b626b894f4fe18435db4c12e95934af23cc5983282c49f1cfd55edb397b84ee5ec05fbdbae7805e0df4b42ffb' }, 'config/idlock/idlock101.xml' => { - 'Revision' => '1', - 'md5' => '69ba8044d261dc9d097dcd45274344b8f01e22f5ee806f644113bdd8ffbed02075851b1ea17deca4f8e4517ef5b1dcd015caa85c8f5835abf0901eeabadc3999' + 'Revision' => '2', + 'md5' => 'f9fbf4ae903cdd0ee79fd4e11621453ea66777e729e85d437bbe76892984eea29514b93574f11dde87c478c05122c4f125639e44753dca567cc597b0c79d38e0' }, 'config/idlock/idlock150.xml' => { - 'Revision' => '1', - 'md5' => 'b59456fd3fcb42b552cc142b758045070e96c81fefd91140a8b57afa1f0a9dbf0a98e8dfa452e1780277d96c2c0147d5614686386808bc74b6d304332700281a' + 'Revision' => 3, + 'md5' => 'fb0f3c54e2ebb95fa12f98ab7390151b803b89f239dba61fe2cf64a14c8c97de916127408348298e85d5868e981da2919864d6a8d06be23463187d808814ff75' }, 'config/ingersoll/dwzwave1.xml' => { 'Revision' => '2', 'md5' => '7fe244aa57c478f25638817f015d2d5d9f83a6f971014de80242a25fd94a35c1e98d3bcc0ad26b69a0677df64993614ee58ae7fe60e6c8af1afe713d4a152f71' }, + 'config/inovelli/lzw30-sn.xml' => { + 'Revision' => '6', + 'md5' => '7c5190dbe0d7f2b8afe3830b1d58d0ff9a784b877e2927fd1e6716a6faf092895fcf3b77c1c4942f53e62f815391cd967d9b1d772951ad1c0f5d77a224382715' + }, + 'config/inovelli/lzw30.xml' => { + 'Revision' => '5', + 'md5' => '8208176e7ccc83f4d3844e46f9779deee793a2be79c9b4d67e0106eed0a92c6034165bd008f6df4b6a5c8a0dc2d06e751b2de2904bf603ba70ba6ec7b928de0b' + }, 'config/inovelli/nzw1201.xml' => { 'Revision' => '1', 'md5' => 'f5789891f9adf7716e6dec82b5764c2869b48fc626b54b9d7bc8eb894368b980c6831073858d82a6155297b4349fb415d39fe4e8a9680cf163802d78fa9e6eaa' @@ -1412,8 +1496,8 @@ 'md5' => 'c175f8a9765bd1411d594988c61846d9f77fbd54518f714f94db99ad9214dd4478003dde586a139b59e54011a60a0313967efa0a7bf0736eb5d2dae565a71264' }, 'config/inovelli/simple_module.xml' => { - 'Revision' => '1', - 'md5' => 'a0c920e6f1109725a540d72513da75b3f0f67f59a618cffb32407998d852cfb0e254c016f6b2578089e2e2f85d9f070a2b5d0cd1e4fe8bc0db090e1f8d3e261b' + 'Revision' => '7', + 'md5' => '2fb8a975ffe9bacac544ef535b9842f50aee91b1228bd18826b864e6f9d585bf7032c2990714b392d20b3013a04c470edb7922e5f4bedea1756603be824b3650' }, 'config/intermatic/ca8900.xml' => { 'Revision' => '2', @@ -1436,28 +1520,28 @@ 'md5' => '1f93ef3a4b052f0280b54d95d2f91b8845be7e683d32cb5410cd6cf8c9928642c66450fd0f1d10a42523b21a2e114f8be667775c52418108d717b369adce0d08' }, 'config/kaipule/im20.xml' => { - 'Revision' => '2', - 'md5' => '08ec2f1ea70db856ebe724c29d368dce185f9412b452618437a121346214188f338c2c94c6d34eadf4988a9682315e76880cad9f49aa92fca3af89b58ef40879' + 'Revision' => '3', + 'md5' => 'a9b5df85ca3414019c366a874650c0dfc9c1f70f85d5ee75be43b07e6d13204239a0be9872be4cefb12cae00b3a209bbe4361cfaa47355f48be4405c1756014d' }, 'config/kaipule/ix32.xml' => { 'Revision' => '1', 'md5' => '6c73035dfad876c339cd6433337ec8b822da99ec5e4cee641f7c0bea712b18118e58243764df11200aa7745e1ef4fbe38b77f3df17b8a81ec7bc1350d379d57b' }, 'config/kwikset/smartcode.xml' => { - 'Revision' => '9', - 'md5' => '3effb314dc33969e2093be890e2044789d52983df17dbe161ba45afc1f37187c26d75b25e17898470baa72d7483f2ba12761efd7e9262534f32f8572709cb200' + 'Revision' => '14', + 'md5' => 'ebdc34b0bbc28dfe0fba9a646885a4f1311664b85e267dddf02cdcd3f7012ce915f2c4ee8a88fe460e804c8faadfb6e03bbd691fe767547de0be4ce8fc8126a7' }, 'config/leviton/dz15s.xml' => { - 'Revision' => '2', - 'md5' => '52980085975272918bf77ba7141738f4bb12986fd93806cf5b835231b80555499dfee2dd986a5324c431996a516be742ef66033f4906add6a644cf554ac911df' + 'Revision' => '4', + 'md5' => '732a89135dc8ae080edff82c4662d60b69b1e94980c01e6a3201dd91ace0ffc58fd61bf621317410476325f304be2d78688a020a0f89a1d0736893232a6679e7' }, 'config/leviton/dz6hd.xml' => { - 'Revision' => '2', - 'md5' => 'bfbc9f51fb67c68ce4ed1abc375108b58eeabbee5f61a597ad987c3d89765ec331c17d43ab2df63bcae1cf817544126ef16f7be175e415dd47f5a66ae1921c50' + 'Revision' => '4', + 'md5' => '48977e685e55b815ff14870d049d84b7046fb76e55afff21055e6374a612971eb43f9ce51aee02f763b17cb77893b33d37abfe838af55b518d045ac2635ff2f0' }, 'config/leviton/dzpd3.xml' => { - 'Revision' => '2', - 'md5' => 'f95d579f71179c9505c1a17c04458d88b7dbc1857cd03be07d9b652e0f59f39c50e47b8468045dd0adc97185891b354edccab13280914c656503b48b262d6709' + 'Revision' => '3', + 'md5' => '56d3f1600de0802f82cc66f25306024d84aab6539f74cc12062304bb9975d5b5d605ce6c88e3b4112a68f2673c76a5a525e91f83a8ae0d6ecc487b7bd16f86c3' }, 'config/leviton/rzi10.xml' => { 'Revision' => '2', @@ -1500,7 +1584,7 @@ 'md5' => 'bae62218e942cd6e768c236ca9d90864f53afba4f142fb30d2d399dbc5ac864a6b2ec94f371d4a845774db0463d00d45d6faea7c272b593bd04c706ff578a69a' }, 'config/linear/LB60Z-1.xml' => { - 'Revision' => 5, + 'Revision' => '5', 'md5' => '7af77dcbc2dfec7eda52a38d8cd7042444141b0ad8f48cf29ad69903e4b0f609e6ccdcf042e14651c7485211aea9c07898a09ec9601f68df64f1ebf91fdd9d95' }, 'config/linear/PD300Z-2.xml' => { @@ -1528,16 +1612,20 @@ 'md5' => 'd2af4d164e011dd302616cdc29244b66d17d94fc75b2c582af63d39dcbf73cb3e288e8e01e87e09eb67c385ae12e3b90ad0e153effa957a9ce3f774e3b2e87d1' }, 'config/linear/WD500Z5-1.xml' => { - 'Revision' => '1', - 'md5' => '018e905b7d4c8b004cbd8f60ba026f40b0eefd65c4f91200bcce3b43351b448d08b8d7e415816bf506fc254419167e0a0aaaefba4fb675a57509fa1e0d6b3cbc' + 'Revision' => '2', + 'md5' => 'e11f2016a1ea920b46f0f727b6c3a4205a0b752db14cbfe27f15abfc4a10ba84762dea5d1aa8b1905afd2ae7f71eae7d74ea06bd989f7c778099e2f0cd090333' }, 'config/linear/WS15Z-1.xml' => { - 'Revision' => '2', - 'md5' => 'b7a783ed2012fa3b08cf54262bb78f730ddbd7720e55d78d2a31e761f8a322ac065d2d334b3700d63ef9f8a5c47beedcfb6d4156bb89e3c8d39163737df839db' + 'Revision' => '3', + 'md5' => 'e3a8734089a4cd8a592ce7ac844198abe8503f803219ba6c0af1a94fad0fae4264c1bd5114d8d1c7ac5c194ac3e69205d29cf22d2d305dbe7a3b6bd01cd6a6a6' }, 'config/linear/WT00Z-1.xml' => { - 'Revision' => '1', - 'md5' => '93a71f8b113829df98a08f0a063e431a97f0f85d53f19822f6824fd41e9ab4410db621285c3bdcc1b405bc472fffd602bbedc98290f904771de9d7597ac659f2' + 'Revision' => '2', + 'md5' => '4431cdf404d513158d1f7b9f62644ef45818a5cbce27b27a18ab0bfc631c11884996556a41b82c6242dd5c574f005a80e68b8bafe144659d10bde6304aea0a5c' + }, + 'config/linear/gd00z-7.xml' => { + 'Revision' => '2', + 'md5' => '48a5f7d3b0d0cafd025fc035680a298e8afce80831940ff003b46cfbd3a8056e781474e5a6d247bcbbd6cd74ce9d4c04475b7445dee870401ee912c3e6056c9e' }, 'config/linear/ngd00z.xml' => { 'Revision' => '2', @@ -1548,20 +1636,20 @@ 'md5' => 'cbd53fd7d938a6086861d26e8214c1c56916b0fa2337366c59b4ea5bb35af9727b1fa1d3b447a733ca269c708f5f5385f7ed3661821e9ec29929828459d35a77' }, 'config/logicsoft/ZHC5010.xml' => { - 'Revision' => '5', - 'md5' => 'c9cde91871b13c49810405501bcc459e6676f72458a353ce4d75413f81629acd98ac6cec27a8d7ffc6e87aeb6674a43944a0c3d5f83032bf94eecc028dd992f0' + 'Revision' => '6', + 'md5' => '4d34aeaaea917c229bedbb737e4de1550b2d7db5f9e61566a1c0a39966b6442d381d01f93714e12aae1404797d36854274cc4063dd7424b00d27da238b17a36a' }, 'config/manufacturer_specific.xml' => { - 'Revision' => '21', - 'md5' => '92cd0db922ce7b1c599658b9162ea24a32cadcc7882252f72b7af29a50df67d0b1962aaaecb8827570b9aa6332db23c8c6511c65404efafcd8f323fe17f8fd3c' + 'Revision' => '59', + 'md5' => 'd9be6f84bc171bd9c11c6ec811e6938a337aea4086bec8f3a034cec5951832fca1ec2f44e578abd8251191719d2b8d4d7aa0369dffa6551dc2f433a18a8dfceb' }, 'config/mcohome/a8-9.xml' => { 'Revision' => '1', 'md5' => 'd1809616fec114edc52eab80314654c8644550fecaec881193460099bface47dc976da727f2d2b0ed6b06fdea1560a942ba2bf230752722ec64c210ed8ce95db' }, 'config/mcohome/mh7h.xml' => { - 'Revision' => '2', - 'md5' => 'b5be73a8fc5e109ee68ff8a3d7a0063fd798bfc0d330ba6fb4d946835b7f37f7b12a8e0f733093a5d57cfaa88b920f0b89ea5e305a0c0c2877b7b1c70d903ac7' + 'Revision' => '3', + 'md5' => '03ca338b59a9e520891497741c0c25dd562734b3f6367a4eac65aaa739351a409004c95faab888ae84c523ce1721d9b5842a9f365554dedf6faf6ed9fb6c7cb9' }, 'config/mcohome/mh8fceu.xml' => { 'Revision' => '2', @@ -1575,6 +1663,14 @@ 'Revision' => '1', 'md5' => 'ef4a59bae64c999292ce1f3307af32bec1203cd74c1bf69a990d036e670c9e02fe75b441e4e58cc52a7f563a6c5aa854c36479c06da46db4a6962d1f8c8648c6' }, + 'config/mcohome/mhp220.xml' => { + 'Revision' => '1', + 'md5' => 'cdd157b8cf327dfa5f4b86e94708b2b4fbc6f749906c4b50908155b7ed54e0f1276e82aedf256772ddfe6c4f0d976ada08e4bd0f60e330ce4d089075132983e6' + }, + 'config/mcohome/mhp511.xml' => { + 'Revision' => '1', + 'md5' => '3cb80a2f92e58623f3c390ceb6dac6a4195a12bfce6726ea417ac28d2c80b337da8b79047436b1a34bee629b34e5cec6df3193e8acaab4c0866dd0e3ba5471dd' + }, 'config/mcohome/mhs311.xml' => { 'Revision' => '2', 'md5' => '4ce93d5bcf48f3a80f31d8293f4b2501f5541c2d74f1d09b35f1a6db7fee94bb14a375c3b443ab0582c325bddc0e0ad343eda1dce9948e16d356a51688980ba0' @@ -1628,7 +1724,7 @@ 'md5' => '702416a0165005b37d576d5fb029a5cf057406bcac8cd0e26092aebdb728a4ffb98da456fae6e06794275b0421444ec20415292300f988d0c19a808f29b41bcc' }, 'config/nexia/db100z.xml' => { - 'Revision' => 2, + 'Revision' => '2', 'md5' => 'a85e3b5dd39faff1bd76dc1f73f3b3527eacea0e1e1c70aa6d6e879533219b9e8034fc872b2553a12c7144152781389f3d055927a62565814695db853b87bf8e' }, 'config/nodon/asp3100SmartPlug.xml' => { @@ -1636,20 +1732,20 @@ 'md5' => '7c24be4705939a05a678db1c9d8a569abd97f9d074abff0cac479f92fd7235bc95439f0371d0767e72220ca1281cb1beb526eb4e0f68184d7ca29fc3fe620259' }, 'config/nodon/crc3100OctanRemote.xml' => { - 'Revision' => 2, - 'md5' => '8ed3592d59f00dbb56192df72567987ddce31f8d7ee21b2e6a96d1dab209b30d9e00f2dd78d3b8309245fd487510f80190628fc8faa045f4833d6055982f659e' + 'Revision' => '3', + 'md5' => '4c2e1bf3aa0abdda59164b964887b9662a637a852d859baf197f480d9b3959cc796b38fcad3208a63e8592ac533b588cc82943707c1f81acdbf73d8cf08f8cfa' }, 'config/nodon/crc360xSofremote.xml' => { - 'Revision' => 3, - 'md5' => '9673f7bb15d3d7ba08d641ec4678147a4b0043329157eda770773c1925318cbd6052d7c43da876e02191f9b1b335a97c228738231e34649cc8c2e36bc7e3e032' + 'Revision' => '4', + 'md5' => 'c9224c55596b27daf81dc38f5f8f99797a2002bfa7c513161a94c818fdd1d411ec2beeb48209f531c87eb1c8fbb5ed7d71f14d03076cc403c63adea718e720f9' }, 'config/nodon/cws3101wallswitch.xml' => { - 'Revision' => 2, + 'Revision' => '2', 'md5' => '3488db5887b2336d0a1bf35b8c81692fb6f899d620598b09de648a3c192780d343ba6edd5444fadd750aa426391037cf1074b503387e8d32c7a6749ec3d2b1e1' }, 'config/nodon/msp31xxMicroSmartPlug.xml' => { - 'Revision' => '1', - 'md5' => '63f7bd5dcc034107dc320a7708586033ce8fcc5c0c68399f190f315aff42c9100f424d232bf01ff81ef8e810c06424d9c519eb1cb37497cb0e4bbd8dfa2805e2' + 'Revision' => '2', + 'md5' => '12f715e8f79d0351ded0d6fba4094bd58d0fcbd3ece3eb325ff7ea7e7bf0e47c322e42cb8af4dc89bfc16b657a799768ed21184f2371c2f121cc0febd5fdefaf' }, 'config/northq/nq9021.xml' => { 'Revision' => '4', @@ -1664,28 +1760,36 @@ 'md5' => 'c1145f7d6cd67f960109fdf04b12952fe4b6255bf703f3826e62512c54c8f4e4f58ef33554f5cb03eedb1b2fd969e5ebe48b03e296dde88b89b9218fc3a6a2e9' }, 'config/oomi/ft100.xml' => { - 'Revision' => '2', - 'md5' => '5f674deeae430f45e22823fd8d5cbc0096d4a9964b45f30200c278a187504121298a31606e81fff9f34d1023e6cbbe40d09f3810fc75379ef9da63d1a8115855' + 'Revision' => '4', + 'md5' => '8398a78120575f099e915e4544755bb035a8f9d8dea8caa536d9341baf8140ae82bae017b0556a22f8617dbe5d567422a29c2b8667d6b8a7807fb097ab86dfc6' }, 'config/oomi/ft111.xml' => { - 'Revision' => '1', - 'md5' => 'd92a731adbdbf6b87d1496af4fb7219c4de747a1b1f44b31a730859cdf306f5a1d3932b7e7405c078ad7ccf72f7c3d03ade4881a2ee055a276aa139604a07578' + 'Revision' => '4', + 'md5' => '1495bc054f8821256e12b70cc4aadd76e55b1d5a15ce26912e2df6a9b7246bab73968e723ae994c7e0ef923a293b46f8f72760e8c3ebb8fb32ffed7fa73e8caf' }, + 'config/permundo/psc132zw.xml' => { + 'Revision' => '1', + 'md5' => 'fdfb1fdc33cbe4dcb02dee460b52941dbf751641a35d80814e50df85a4235f182323a55203948213c7d99d083beb95174ba6acc860f38b41bea65608f227decd' + }, + 'config/permundo/psc234zw.xml' => { + 'Revision' => '1', + 'md5' => '32cf262b674384dea494dd38e5cde1393f2f0996c1ea42715ec82597af90f59898bbd75e6d37ff4a1d0b491e914a5f28c9b2946713e432f5b598907dcb052cfc' + }, 'config/philio/pad02.xml' => { - 'Revision' => '1', - 'md5' => '2c1279de793be1c3c6fe0b849d241fad1f11c88afc2feb5e694f2cca0975f8fdf9cd5799707b03cfdacc5ee8db8f7d514a95eaee7f45447920f844471c4c064c' + 'Revision' => '2', + 'md5' => '8e1fe2169622ea923aff37663ee762a922dd90d2600fecf6f95808917cd414187d2dcbae6d33a97508b09d5cbfbf91413d3ef0284d875905f2e611e34069e393' }, 'config/philio/pan03.xml' => { 'Revision' => '5', 'md5' => '69ac125e867e1523ba7cd4e7ed1e7e8a4fbce0d48dca53080db404a833c1bd6446ae1014871a60f4756f5fd789dc0f314a2c23ea3467464665e61766778124ff' }, 'config/philio/pan04.xml' => { - 'Revision' => 7, + 'Revision' => '7', 'md5' => 'c9a658764da83f06371d5ddbc57f0ffaf025d6f5f566ce0edea4b0cc003e930d98b7ebcd5b5fe061b2e0db481e96d6c37300c1ce7a264109d04aea72dd750a69' }, 'config/philio/pan05.xml' => { - 'Revision' => 3, - 'md5' => '21ceabe6d8a71261fb6891b942181304b691f3a3daa9e8e98960db3b7ef8c2375d027061eb8913a4c79d52136fc5a5f9a99982a0b8a161d9707d110d644150af' + 'Revision' => '5', + 'md5' => 'e57f208a8b5d5037bf9a1d1a8991a8936e3302944b6572dab297f15f086654e4a24b059171ca9bbc1f7cf835afadd568000cc6b8cc20a0c7e8de452118817193' }, 'config/philio/pan06.xml' => { 'Revision' => '4', @@ -1696,72 +1800,72 @@ 'md5' => 'd38c538a03cd694dc2c5b55488d947b7e3541c99fb852ca3fd0c2f422aed746626ce34d8387244aaeb353bcbcdfda5087815b8d823839756cfee45c324d7abc0' }, 'config/philio/pan08.xml' => { - 'Revision' => 5, - 'md5' => '74a69d841896a06a4a89fd31bc338566a1d8a5ec6c46ed9213ecbf88973e3f7ec9c7115bf3300dd5012b785bb40378659de73439b4545593400f20f80f914cfe' + 'Revision' => '7', + 'md5' => '6f40cd915cbf21b17d229218e374e06931c17679066d5a9b66a3be20fb7f1f126034828484ea0b34493a6bd2f690e0ce79886b563dfe73b7d2d92477cdb96f56' }, 'config/philio/pan11-1.xml' => { 'Revision' => '4', 'md5' => 'aa358cc989d2e2d476bc0229750ad7f963fc07edc0ad9acd9b14f0e08fba41a1ed858d5db360195dd77b34799a610a774c2a5210eff0ae29c5de570ce3e560ae' }, 'config/philio/pan11.xml' => { - 'Revision' => '3', - 'md5' => 'f23b64fc23522b029ea0fe3b7ba24b740f88f21b1264b095a78ccee1ecfc85a7b6fa32407b66fbac5368e07264ffdc30abc15052769fbb468a159fe47695ea76' + 'Revision' => '4', + 'md5' => 'bcb431b0960b2c0731437a8c6f88a43a32586c45dea68c43245bd51f1895d5a8b7ee875d77ee07f2ab510a88487f4f910c38aada574cb27396b70617ff1f8757' }, 'config/philio/pan16.xml' => { - 'Revision' => '1', - 'md5' => 'fcc4c678e5513b299cbf52446ab382f7eee75d160e842758d92a9b800586fdd182e271f7285a1cf2db68709cb30d50039ff63e67bc40eb02dbbe0bcab28f318f' + 'Revision' => '5', + 'md5' => 'a7fefd71f6bc5ede497d62d300ecfb3e5700c0cce1c55068349881fd6ad31ce08c19a0760a935033d42ec6407853b65d1d39f49d5047eeb69a6a0d05cd57094a' }, 'config/philio/phpab01.xml' => { - 'Revision' => '3', - 'md5' => '855b223990f45d6490bab31972afddf2412a284ac61835c096a0ec5286332021363f3aa3c550d0790cd60dfdada4e48731cc9e310a1ab37a136e244e33342405' + 'Revision' => '5', + 'md5' => 'ee5564aa200257d255d4a630e4a329e33fbc0a202f0e0ed64f3e8933f760f8fdb5d248a94bf21ebcf20affd30fa5fadaa652cb01b1470496cd1b18a1d196740e' }, 'config/philio/phpat02.xml' => { - 'Revision' => 5, - 'md5' => '353aa8f9eb8a1ef9ceeea03d59b832ddce5e44d2a3b9e6fee4400a151e488d1cfd71a4a8af8af322b9a67e25ea170f8343e320fa091e5287866060b5bba12fdc' + 'Revision' => '7', + 'md5' => '2934c2c8f14d96e31c6b978a4f0d6514eb40fcbf6bf4cf88b0298661f7aa58a3f552d8d7071bc096f61d2f2d81d7af8e4e3e2a281306c12bfe1957ef210173c0' }, 'config/philio/phpsg01.xml' => { - 'Revision' => 3, - 'md5' => 'c90d9ad11c0b51a5b7d837408b0a94dd16c884a217cc30c6eab7c9e2bdd73a2475ba9f39348b4932bb8fe1d1b33338ad64728a920b66e285712767861eee24a3' + 'Revision' => '5', + 'md5' => '2fc5c66f6abdfec254f00814927a5de34ac80a32d433781cdcce2f3756726bbd22c5c52e38af2128c0c5d478ae767256c3e257010170d39fae8cf6e8f17a692b' }, 'config/philio/pse02.xml' => { - 'Revision' => '3', - 'md5' => 'd64f99039f574c4432d53c4efba9a6b51a2fc1e14064b86812455af375cea5087b834af6705a16fa2ef227badc23a7f40b7e195ef7093018c6eeab6c2eb469b3' + 'Revision' => '5', + 'md5' => '2660f6fafc0f5d1929d6fc4896fe7da6da4d1bc420d8f98d1ced1ce5c492819239c1296d18965314b6119e840cadb226677add587e1cc6eab01d7fa4ec312578' }, 'config/philio/psm02.xml' => { - 'Revision' => '7', - 'md5' => '82a7c6a7609ccbf2b3687f33888f644c775ee48cf982838ff42389c443bff6ee8d05a38f1475c2a84508803f3a39d08970685d12549584bc9f657fec152b2f24' + 'Revision' => '8', + 'md5' => '61de4f16428eb7b039dc52080318783485c5ef1281f6e8b9b966ba668fa9a34c5155fc94e1a32def1cca869f832c750232608be17c007305386e491177411aaf' }, 'config/philio/psp05.xml' => { - 'Revision' => '1', - 'md5' => '5b2c12a400a4aa23255a3dbba5ce11171ffcf47979789f2523b4e1de486dfaf1678a270b913aa21895bbd42f27b5675923574a52d45bca48afd92c927c88e8af' + 'Revision' => '4', + 'md5' => 'c11ff9ff5577b4b78cf5c9501053be6b23c53ccdcdde42b06b5e042001cbb5f898e855e3d8769bb5af6f5aeff7738f2d955d638d3609caa988b28c8beefcec1e' }, 'config/philio/psr03-1b.xml' => { - 'Revision' => 2, + 'Revision' => '2', 'md5' => '47648ede1096a03001221a87b148e05f226dfdc160ab84731c299694b64f5a982503a25c1c5cf2905f0654df08024d05c44010133648ebf5ab4358cbe7e34736' }, 'config/philio/psr04.xml' => { - 'Revision' => 4, - 'md5' => '342539f5bd02acbef8fe07ba656312b4ad38c481c13208a87be2d7709c99b7a5b31a9c8293dfc9894bd65e8d8b005d6044a54a29f333cc9bfe431c3442174300' + 'Revision' => '5', + 'md5' => '02d630345e20cc163797e73a0299c2f1f678854e1bbec6475c694167ba95e38b9dae3933e151a56a0457d7548757bd7ac45b3f4acadde7b671f396f04079f454' }, 'config/philio/pst02-1c.xml' => { - 'Revision' => '4', - 'md5' => '8b2f659b0eebeef6bb1345e09811fc2477ab16b64a373e0882114d1c6ab7469e38f8d1d8560fc726d3beac58fa26f95cadf49de4af4a9fb075b766aa49e89dfa' + 'Revision' => '6', + 'md5' => '464c0b4b141a2574032381b026c8e1a188c7f39f196449a3470de246591c0b75b842f1db09261e7ea8fe78d13718d38614ef2c04b311dfafb4f896772833eb5f' }, 'config/philio/pst02-b.xml' => { - 'Revision' => '4', - 'md5' => 'a3ef7e2153f0303d2dc3d3d14d70241d8912d3ea25eec2b66a590b8d89f9295d41759b5b620d55f7636be57846eba7d8fdf19b1e8cbc6b857d5ce2ff3418d697' + 'Revision' => '6', + 'md5' => '4231162c58f286ebb12b0a6fd65fcfe1cee8d5a41f1a7565648dac2f50f03b327c88bf7932369c76ff17b7b2cabbc3f87e082e2978ee0012b47ba60c0361443a' }, 'config/philio/pst02.xml' => { - 'Revision' => 7, - 'md5' => '75f639bf393510327a2103dfaef3a80483100afb2fee4deebc95093d7e9cb739261770f503e75814bf82101abb2d89561335d0ce34dfa923fec5bf603818153d' + 'Revision' => '11', + 'md5' => '03450ce5dd6f64055d0ade348357cfae39a7bfde49c15fb94298489f56e303faf669dfc19bf51dd4da2e95d72dc7bbe1fe691848074c339d20377f1de337532b' }, 'config/polycontrol/doorlock.xml' => { - 'Revision' => 5, - 'md5' => '86c8c24c7776de44781993516e045d0a6b859a2caf8f21171766f01feb5ce9827cc62f6e047a61024205331650ffb00a5fc4dd32f20306c8b71075225c540fed' + 'Revision' => '9', + 'md5' => '41699e435d7d757d17c930c7b6a255218ce13c9c0ffd7c813eb8d1ad9872fd5e10e08497833a96b1d5c8d6d5e6ac7cb4983e62f179930c2fd4963014748ae50c' }, 'config/polycontrol/doorlockv3.xml' => { - 'Revision' => '2', - 'md5' => 'b48685e242619eeb483e4357d0b99a4057d2dc26faa4fe43fd238043ca36ce640b79a73e02d2e800b2768d205c1a0fe3491eb3eb384f5b03babc11d5b3d41467' + 'Revision' => '15', + 'md5' => '470dffd2518ef1de4af71fdd29ead1afef79913651964dd328c2068e8e8d3539e61b5ed5c5ef3bbacd47590a6a800e182a0115f1dff6fb29be6b6bf47e302eeb' }, 'config/polycontrol/keypad.xml' => { 'Revision' => '2', @@ -1772,28 +1876,28 @@ 'md5' => 'd568bb68a43925c93fa91ae1e90be02a7bd122a96e45976024451d554e30bbbcd4b1c379eb7b929ca09086d6e2a2c3a50235193627b115358f104bb3f78a5861' }, 'config/popp/004407.xml' => { - 'Revision' => '1', - 'md5' => 'd73c3482e9e3924f7d7469791ce4d359b2a514b4df554dee7defce3281839bc4cbf8cc1268d9ed002665a2c048b304055492994c5d87a7857f94d143e13cd53b' + 'Revision' => '2', + 'md5' => '9aef97d5a39d568f37918b440777fd2cd95cb0f094dc1463fc846d3ccfd6a9834b0890409e6ee7c3baf18a058ba90540c03eb04e86b54f30d8ad3183db88daa5' }, 'config/popp/009105.xml' => { 'Revision' => '1', 'md5' => 'f342fff90c90bb58c7b2982fc2ac1c1dbc81a62de8ba5e955714efbacfa2a90950df81bbd5a255771bb43820a5b3e65fa6abf83863ef19787590cb540dba0a99' }, 'config/popp/009303.xml' => { - 'Revision' => '1', - 'md5' => 'fcac16531f3d726e4b147f692f9b236a40545b84e183278ae8f2fd7246371aa3b048d3449bb42e51e97826751afd50e49083595b73d303f0f1a05457a9c70050' + 'Revision' => '2', + 'md5' => 'a5d8cc2a490a870b0c4e8bcdaae57d2efc4e2c3cf632da50950a7e16a23cdea02389fe078aab9441eaf29d9312f808d00d6173c78aacaca000693cb88d1a3f28' }, 'config/popp/009402.xml' => { - 'Revision' => '3', - 'md5' => '697cc2474dceecb72210f815ce12a57ce435182181588b539babe5df9b2a01b40e3a18d32e4af18e670797470d40ce29a11faadfd5d43c0533dde111f5632881' + 'Revision' => '4', + 'md5' => '76fb11bdec34c53312c01e694e798cfd05516215f82a6756628b47628a832f9f29852adb0d33f6783e3706bc35b132c44b9be7631049d91077a434ae148d5f41' }, 'config/popp/009501.xml' => { 'Revision' => '1', 'md5' => '749c31c6f0a959da709f13b331f01abe31bdd5c9f93a584cdff75ba40ede6051b777056d01bd42fb4e34e4728ec2f5454fcd8d634ded05209afc66450412e013' }, 'config/popp/012501.xml' => { - 'Revision' => '1', - 'md5' => '54f58f4e1bca94ddb993602b6f8a8986c85093bdbb29dcde78b87ddaff73fe957d6fdbbd1ad00162a5e716c63ef56d5fbfa2f6ef556998fbe8d9ab42aa9fbdad' + 'Revision' => '2', + 'md5' => '44af7415b92881839701d05860bbd9b1a4f3d1e1a249c2bd0dbceaa4f1e4f704009adf51b33242e8b81ab41a7766c2a0fe3c2b27e71a592c21a659d0c74d24ed' }, 'config/popp/123580.xml' => { 'Revision' => '2', @@ -1808,32 +1912,36 @@ 'md5' => '7a156ae6ee0a11a5a22edd0b0be003173c37f8abfa4e93558c0d78c0c15a48be962a83a797423bd75e2fccf1b6133020ec5886da5cf81721a726fdb525ddd11f' }, 'config/popp/700045.xml' => { - 'Revision' => '1', - 'md5' => 'c37e1e4bd5dabdd68839be58481eca4b1d6374d3e0f45f44c8176c0cdcdb296f7cc063ee2a68e534726dce8e301ba7a2ebf270fed5400c01d83378f67e81f696' + 'Revision' => '2', + 'md5' => '9f5b536c1f6716e9171b9cb6f6778f0f609ef33321bb8b3ecbd890a66d428048fe05d7cc39b4fcce7a1c2e16273ec76fda322af74e87cb7bb02ec951f342b6be' }, 'config/popp/700168.xml' => { - 'Revision' => '1', - 'md5' => '80606a61b9833255058c20223e7c1bbd04922c218c9e880efb34a735a207f9acb4fea433461779cae74b7a0fb365eabfa9d11a5e5c21be4ccdfa7d17a0147a4e' + 'Revision' => '2', + 'md5' => '1edd75ada9a0c8be1e77b48629a4e07f724a5755f32fa80b0471709043dbdac923a028f3698eeadee2ee948b039560c0e99dc500165e26f1bbb67bf5a4788729' }, 'config/popp/700397.xml' => { - 'Revision' => '1', - 'md5' => '584ce82baaefe7b8aed076b923f03c55bdca7d91367111b4503af9ba3d8f363eff19c326407e0223fbb8201838c68d8b7ab2960128010265c9d5db9c34c56228' + 'Revision' => '2', + 'md5' => '89784ba95b9219c52c8f63826514c480fbbd9fe84910789b0e3c5bd5a10038621fc68c392a8b759ad89a2c43aa34e823af029ff354651b86f65fcc71c098a848' }, 'config/popp/700793.xml' => { 'Revision' => '1', 'md5' => 'caceab22bf95c5e0e3e030befb73d612d94620cb3f11011509a7ac8d85a0b7771d24521385275918054334d7046ab98902f576d8c9d5ea98009e735d0413a331' }, + 'config/popp/dwt.xml' => { + 'Revision' => '1', + 'md5' => '68638128d2fefdf799548463d04769bf7d911ad2b2d6240ddd4d7a6df7e03875808773e819839c84deb29a5a2fc3474c326e13a9335653f389a5ab211f57f644' + }, 'config/popp/smoke-detector.xml' => { - 'Revision' => '1', - 'md5' => '19f74dfec627ef52f1b2d220d4534256e3d23486418a8a26c3b53279d7c12de94055e6a289337ca1ed1663d699a419a2d1e1b676a658e35e2a97d2762238d22a' + 'Revision' => '2', + 'md5' => '5a0047adbd73b8bac7bb78d1a01c4e04a8674b2c6afff325d14b2e83710fa1e9008af3c6650368dd7e9c2694dd601b885cc8a64c1127fd1019ad401d12b35996' }, 'config/popp/solar-siren.xml' => { - 'Revision' => '1', - 'md5' => '318b090f0cf86094564ca69e1c06b9da98f5185da4124b439d980d155a97e292a86e08c5eb0ea3ef9a205a7f651bc31682e1a72ad547ffa6d2ccc04286a2c1b8' + 'Revision' => '2', + 'md5' => '010d56d45a25cf13b51b1953554f0ae4dddbf52f18dc03a3c1f85a264ebac8d065d7f226c12e2cffcca5b42d0fbda10208ee3156df78c7930b7c8ba023722be8' }, 'config/popp/zweather.xml' => { - 'Revision' => '1', - 'md5' => 'b1099304d7baeded87570a9e93a033313fd88e9b802343e7ad7922964801b22b20da3e6f8bb33e7b4c8fae7637c09f87edc75725bb1071b66cf264c9b855fec0' + 'Revision' => '2', + 'md5' => '89c31bb70e56b887ec4559b2d4bc450bdf40490fb9b496f37e337265539e638c0bcdcc128f6914c3940f2d58cf51655deb1ea7876c38d74ccc2e89af7e1240df' }, 'config/prowell/zw-702.xml' => { 'Revision' => '5', @@ -1852,32 +1960,36 @@ 'md5' => '080174f8dbebe8e5e80bb84601cd153946b7a014450bd04eb52cac0351dcf326b6b5c139385a42c055e1f01a09a41e1baf19586b66fe20e975ab6e7ab5b87e8d' }, 'config/qubino/ZMNHADx.xml' => { - 'Revision' => '5', - 'md5' => '318d1abc88eb2857463e576619fe0719c2ce353a249e72167b3cafc9c998c71042d543d9976396bdabfda18d3d0550ca062b330b03013c13a6604d1071ce8057' + 'Revision' => '9', + 'md5' => '510f98884bd31bfb09f356abcdefcdcb4456fb1edb54c6d20e673878983744d98a06a0b643880e842678bbe76d9272ddae4469606dfa57ab7546f26531f5d64b' }, 'config/qubino/ZMNHBA2.xml' => { 'Revision' => '2', 'md5' => '35bde84eae9bf56aae8a8ec8710cd96c066d9caf087ec1356c3fda124e82bed5406af2e72b627a45bc45e1e6c91f8f0d9af9368e80fcf5973d9be2ffb5e191cd' }, 'config/qubino/ZMNHBDx.xml' => { - 'Revision' => '4', - 'md5' => 'ca90af71d93774743c2edbbf25624e6eaff2e84a7831bced3dc4cd97455d2aeecaab4bb17db69bd1ef249d36ac96f44bcedaeadcdac54791b7985a579e84c848' + 'Revision' => '5', + 'md5' => 'e7997e9c51a66d078d37e5501191a2a36bd7faa8b98dc8967043b68e9e97621c5dc5f797640ee4c50a3ae4389d38ed87e6e3a94540911549298f366aa8ac5cd9' }, 'config/qubino/ZMNHCA2.xml' => { 'Revision' => '2', 'md5' => '94f11e408312da4a3104d120112bb697bf53a9c5877f3eb73128e480f23e217aa72bac2bc0752f2595a68d26dceb22573beb7f4a98938149e73facd854e21114' }, 'config/qubino/ZMNHCDx.xml' => { - 'Revision' => '4', - 'md5' => '72a42927158f1f27f68522538b719fcfc1c08c6858efffba624c1f4debd53b91f0ff4c2adfe5ca5fefa793613b0878d97f78be220181b070ed87039b6c6d2748' + 'Revision' => '7', + 'md5' => '7133bddad00285e714e0469b6ebb11bdf1bae84de2393fc512520ffcbb93c1d204646327ed6b2e50da1c23fd423361a4550af9ecde4aa587890d8261f09dbf9e' }, 'config/qubino/ZMNHDA2.xml' => { - 'Revision' => 4, + 'Revision' => '4', 'md5' => '7883b97dc7151ac7c550f56adbafb086a548613a14617da51232bb1e199a97144f89205622555efdac851e2fde437e2e00e65066c591ac1f1d622e7b57a1c59b' }, 'config/qubino/ZMNHDDx.xml' => { - 'Revision' => '5', - 'md5' => '81bea011036c1c4f4aab335d479d8b195754da493ac52f0833ee7d3d8e1ac341620dbb71b0d8ffe3313c17816906d32f90ebff4d7f9b65fd6eee0053619fad6e' + 'Revision' => 9, + 'md5' => 'de18029a1539e10dd15fc85ede084182e1cfcbc78325602ca6e5b428884f6db6ce1bebdbea331a8ca0f4ba133828c09f13ce6c1f8486871a5ca9c17258358ba1' + }, + 'config/qubino/ZMNHHDx.xml' => { + 'Revision' => '1', + 'md5' => 'd47f8f39a5bdd5d5f5881708761769ccd517dae796e7580f77f8441715a957ed29de74221bff41746b306b461f243dbeaa6ec9d09451b8ba0d97eb2696b465a5' }, 'config/qubino/ZMNHIA2.xml' => { 'Revision' => '2', @@ -1888,8 +2000,8 @@ 'md5' => '061416a33033dc5cd68fceb1b06a690fa02c5f6c7804453a8d28173d3869b54b7067f87e30eca380330514ad1c078931c338563cf7af6f3da98916134d97d3af' }, 'config/qubino/ZMNHIDxS2.xml' => { - 'Revision' => '2', - 'md5' => '260ac0da7df02b29bb62fb4c7a8e3fa345406e1099e9b7af6fb4deb3a5302084fc9763412ff271e1c57d82749dcaa2dc44602c940c09a87bca8819a824766702' + 'Revision' => '3', + 'md5' => '39e39c091d03726768865e889d20390d30af0cf5da390e49adff1928cc79030a2d59d9c1436942140c2ddceab49c70505f2963e2f54397e3cdb751a174cc3122' }, 'config/qubino/ZMNHJA2.xml' => { 'Revision' => '2', @@ -1912,44 +2024,48 @@ 'md5' => '5024808b8551691103b25c05fe37ae3b49499a38fe0491bcd492accab0eb346b7e810c3132cd67e1920ed0d971f07dd9303a3b774276aab38ac04610fe5dbd50' }, 'config/qubino/ZMNHNDx.xml' => { - 'Revision' => 4, - 'md5' => 'bb1ce24d7b82ccab1dffb094cfcabab8aed89e0e6fe509a375b01f977ea5824d162da71c2a0626b6e2feaadb5c7a4191ec168edca08c41d77966607335b8978d' + 'Revision' => '6', + 'md5' => 'a10317520ca58616369d1d7782640ffeb84fb778c781f3bb39e7d6a0f22cfdad7aedb65b781f632e36c2c9837188019d00bb8b6509bc022719a64a77ea2c6277' }, 'config/qubino/ZMNHODx.xml' => { + 'Revision' => '2', + 'md5' => '9e267442a84763403fc4c9ba6088fa59a067e1a5a362300efdcae287697426a53b5b705fde59ae5c106091923fbe51b2856e9c9bdc7bbe9f9601d7dde7878e8c' + }, + 'config/qubino/ZMNHQDx.xml' => { 'Revision' => '1', - 'md5' => 'b86e96f68e8b2d9e1722ba7730f8cd31978869d25b6f530f6433dc5525f12bcf69d1939141196fb578d0720f2873d0bb2787c198b8c639607482a318b7323a1a' + 'md5' => '0b359cc2fad436b06e51bbe02e625e12a1bb81854732b062d664634e8059d2e162c6ba3c870723ab32d6f0bb395afc0edd1b0e9459ae302a080d3cd55d9f70dd' }, 'config/qubino/ZMNHSDx.xml' => { - 'Revision' => '4', - 'md5' => 'd0d0d318fb5d265f02c15eb9c825a2139638af1074ecd9f91f564728ce5b56df14cbb3492b91fe2afbf01279f732c0dc6e52bee9282974fccee7a0a4eaa4d433' + 'Revision' => '5', + 'md5' => 'a65c7430dcd17dbe5f1932ffece29cec38b684636c2db1931222c7c042e3e6808a049b149db78b9e3a3b12145da078416b8331d72052cfd0a149b8499242d10c' }, 'config/qubino/ZMNHTDx.xml' => { - 'Revision' => '3', - 'md5' => 'd54d8ca136f575e142d021dae8b01a0bc02f705d4461ad031e0a57d501d3691050f97316be34722931d0c0d358506fb938871f3e1f06d397c0f66fdc2edec713' + 'Revision' => '6', + 'md5' => '75568a1a5e7119daf2d493b4ea6e7ceb59e065fa9325f933cd61db7334dfc792343946e0dae62b6bc84f8f598d55890aa9e2392419dce0cfd4eb58b6d23e7801' }, 'config/qubino/ZMNHTDxS3.xml' => { 'Revision' => '2', 'md5' => 'df04a24a50282278c6deb7e885702d97ec98a2b4ac2998212caa7c16ddf961b590168214bee1c4ca76512a4386cf9b3199fe129757e4af5a725cc1a2a3d79090' }, 'config/qubino/ZMNHUD1.xml' => { - 'Revision' => '2', - 'md5' => 'a9b34a8da785da8b3150b3860a944a9c93fe36187d94bc07623d48cacc8065ac5c51ef22c6bf2fdd5e85f6e18610e1c555544421d026e5192c18f8d4496f5b69' + 'Revision' => '3', + 'md5' => 'e1b8ae48d7388aefa2464f7e0e51eb23a68f65e8d7d4b35a4c3af29524fb2d53d40e1d861f1d4d798282bd1c916e854f55da894e27dd6ef43ec40c13b3a56610' }, 'config/qubino/ZMNHVDx.xml' => { - 'Revision' => '2', - 'md5' => '7315db240b4261127af88ba0c96d5077734bbfeafeb9f75cf1f743249edbe7750724f3ac9b20a949697cbc5a5a90dc8b551aedfeea48d64261550bafa2ba7c8f' + 'Revision' => '5', + 'md5' => '84d8b8e248e7494d1b5ef403cc55c84a9c7e32c484b878c7d1103b89ba58fcff3a7dde495bbeb9d85c41dd2a029cd56da45502a4297f5c7897a9b9b2f5ca2af1' }, 'config/qubino/ZMNHWD1.xml' => { - 'Revision' => '2', - 'md5' => '8c1dd388fd7e71689b450bda2700a00a40e436ddc3281a886af8f675d3edce076035037916291020acff34d56b395ee02d03265fc0ca90b73d4d72aaffe73301' + 'Revision' => '5', + 'md5' => 'f5833225b7eacbb94d422c08baf8b5b490425a09b15efedcbb08a92700c9918f926b1ecc1b68fdbc0cf1cd460a26f57806f9ed5a625f3147dd2859091ccf99ed' }, 'config/qubino/ZMNHXDx.xml' => { - 'Revision' => '2', - 'md5' => 'd291496c65278a821f626a105f55b3ce81086d75a6eeb3e43681947ccb5ed43d4a9e3b79db57ef6c96664dd71b7fa2d44a123ba26f4abc62f00a1602065558ba' + 'Revision' => '4', + 'md5' => '318e982feee6e6df7c03da246678861e51eedf93463e134476af6fe5a0905624db9807b0b961147baf98982fdb4942a7ddf987dfeabb27241a39cf0e61d5d6ab' }, 'config/qubino/ZMNHYDx.xml' => { - 'Revision' => '1', - 'md5' => '0bf07845f7c498e919ebeb09d84240d71dc90035aa04adf7355a00e7cf818d5a1b5fc0975c41abb48c49599b2bb16671c5d15f8b46837b5411bba8a69d1eab53' + 'Revision' => '2', + 'md5' => '1b5e30e6eddc0ffd67764eb7fcb8a22f86d6d124cfe822b1b7d98c372e268dae78c5b6332ab7fab85bbf8fbbf71c3b98532c8f02dfb95a065992df2dc4e10f60' }, 'config/qubino/ZMNHZDx.xml' => { 'Revision' => '4', @@ -1991,45 +2107,53 @@ 'Revision' => '3', 'md5' => 'e3b6afb43fa679b8575f94b04caa71d8942ee15ddaf3fc70b15ae194af4d1b38ee710b3f7a0aa2ca9df19f2eebf4611a8927018a98639d3113399614c0704fec' }, + 'config/remotec/zrc-100eu.xml' => { + 'Revision' => '1', + 'md5' => '5b840b10226c7f8e158623b9939ed2c8eee3aa1516de6a78c3f19ffd89fac6fade7acdd6da5a7aedd6394c019ead43902a586351f233740dfaca13f0e2a291cc' + }, 'config/remotec/zrc-90.xml' => { - 'Revision' => '1', - 'md5' => '5fab5318674e38c7ea352814122b6ff75be83bb5cd02893a849fa819ae5a7efdc8a1ac04aef052415e206f1b48a8358eb99bca104ecd743a5e0599b1208eb6cd' + 'Revision' => '2', + 'md5' => '98ec165810b4b80a4d1e22957432046b7d61dcd6f4ceed69059d81ef1924124ac0f146a17192564b82011a37943aab7852ca97a512ef2dc8bbd1ce8a06f831dc' }, 'config/remotec/zts-110.xml' => { 'Revision' => '4', 'md5' => 'fbac42632e85ac10571db822206b25d8c793e3a1c5e16783f822b094c68411f3742eea8d7b3657a2937f6c406e8184f624b80967acf3c1e31b8bc881dedc359c' }, 'config/remotec/zts-500.xml' => { - 'Revision' => '3', - 'md5' => 'efd8445e2b859716d417fcf1b99ecc455bfca9a3f3ba75c5c37b94e8363d2eab1c6226bdfd3833366ed7acf656135483f51f8f4599ea26e6f0abf82f4e5a4785' + 'Revision' => '4', + 'md5' => '9897b20e553a4979e362a639021215c4377d8212c46de5f6929b37ec4ee810f82c9e4ed6958f3d4ceedee249966e623a21ef84059803e8fb5a68fe73c2df7348' }, 'config/remotec/zurc.xml' => { 'Revision' => '4', 'md5' => '3ffabe2c9da2cd2f4f625682584003c5cdb4302e09a074783c718526b796eb394ed7dd020594167751f46a18894dd54b39d9c4e3b06c5cf64fcca738b4aaad4b' }, 'config/remotec/zxt-120.xml' => { - 'Revision' => '4', - 'md5' => '9bf8c68c46bbb073b33f11be97e1f496b98c92272ebfe845946d06270bf366a8cfeabf4f5ec0d0f94869316674b358ec54ae572ba14341eef57bd1ec86ff1583' + 'Revision' => '7', + 'md5' => 'e7545d88ab5223f20078134b437c5e4f5c4e85a8201d92537cb159cc829b8b3fa17b84856cbe68a90e10793c155c4c711cf1675136ef82cc524240c44b4711c6' }, 'config/remotec/zxt-310.xml' => { - 'Revision' => '1', - 'md5' => 'afa8d83b4c319afd8c0b4bba33fb94263da75982ee6a7436d029342735a74220b1a39c11f1f8439f10a0296f7279f88dbd7fb16c4d75b75f22e158630e7ffc81' + 'Revision' => '2', + 'md5' => '5de09bb88d9c21d33dca3ba693a7ae886e9a4476e50966861b581d22902636df68981a069debbec830380576f14a6676d7fd302f165553c9ba558a3803b8c991' }, 'config/remotec/zxt-600.xml' => { - 'Revision' => '2', - 'md5' => 'e7269cc340103049cba68ea1151c2363b9a904737469e9881aab232f0dba9583b616f9456b51426798497facb47c6858863bad4644da337ca76c40efbd335a92' + 'Revision' => '4', + 'md5' => '55a6ccde16e43ecdeb440406354d761ae34cc7743d6cae4946e928e82826f8d4aafbfedfa5428cbde8a5eaa216c24b6c4417bb04edc28d118763b3c7defb8c1e' }, 'config/schlage/BE468.xml' => { 'Revision' => '1', 'md5' => 'b5394f171f4ac0441a01efa1b79945eb4d6a04aff4a7b91a5b25f6214c0d9615a5a88b30e13b523d5cfd252e4b8dd45fa30478cc1fbf78138a1b6ada34594aa2' }, + 'config/schlage/BE468ZP.xml' => { + 'Revision' => '2', + 'md5' => 'cf44b4f428c8013422e2acc14b08bff8c2920e01bcaaef16ab7f655f14d38b6aa678d041bcf0910a44a90aea88b700634d6715df434e3870d70cc8226d0d4fa4' + }, 'config/schlage/BE469.xml' => { 'Revision' => '4', 'md5' => 'f073cb3e764245fc7678d3b28426fc87008746c7a8e0ec85fdaaf735fa60d32109ca83883fdae89deef484729734faed302ef9ac6b6b506b62822581088f937e' }, 'config/schlage/BE469ZP.xml' => { - 'Revision' => '1', - 'md5' => 'd860234e29e059721fcd7b757d39e76e78d565067006f893380840383bcf5a733478676f984cd20662c68a5b95b728efd6227db3eb8b5cb7e8dfe07968b89335' + 'Revision' => '2', + 'md5' => '3cef5311c3333e70360024e65d3d654051062df8493670fc10f81f0a30c5bea705a455ef87c8e606c6e6734bc024b672de22f96ee726472794e194d3263bf509' }, 'config/schlage/fe599.xml' => { 'Revision' => '1', @@ -2044,16 +2168,16 @@ 'md5' => '4f3be313a7ae86c458518f7269cc51cc1df19d5900ae319c160c060dda74d57439c1d7f4b1ac881caaad1b726c3349a9c03a6c9d88103d864c31512c434908ab' }, 'config/schlagelink/minikeypad.xml' => { - 'Revision' => '2', - 'md5' => '809c258219c7c9a49fb7afdfdd3512533c6b4dc133647b6bfb7f29fd2b0a7ce1b64aadf56ba2b93bc2cd5354a613e2c44d5b6164fd0495560aedcb9043310fd0' + 'Revision' => '3', + 'md5' => '8d4411fdc3a3e9b9f943be980cead9e614c02953c82b6066466db7838da7079c5ffbf000fef4a28d8a52a6286bf9811a9c2dab8c79f3670feeda80cc398df4e7' }, 'config/sensative/strips.xml' => { - 'Revision' => '1', - 'md5' => '5ff1a4aac04bc81b3550981b5fa63f277e1cfaf0a0e330b09f8071a9a9beec9d5f7e1f8a82b78fe64120b88547d08a4865a4cf2ab18d921247b41a08924c91af' + 'Revision' => '15', + 'md5' => 'b9d3afd0be617a7a5d87ca36b07dc07ab3fd8dd2e31ffa99a519d4b94ea3ffd87b83e900c97e46a1fdb0dbfbd7b19a388354c1b8734fab5f96b64bad2e222fca' }, 'config/sensative/stripscomfort.xml' => { - 'Revision' => '1', - 'md5' => 'b1628d429b3074b1e060881476c187dfcb36698d40275d506cb5014c60b8c61b3cbf7f938f68ac403a3b98602409942a01915902dd083693c0b57bb6febcef64' + 'Revision' => '14', + 'md5' => 'e76c9730441ff8cd2eba5b52bdbee17109157076813bc628b873abfedc23a62d2a44b27e5f2b3919f82cabe4df44f75f1abfd30494edf2198ffb88a23bb55b63' }, 'config/sercomm/sw-clp01-eu.xml' => { 'Revision' => '1', @@ -2068,40 +2192,40 @@ 'md5' => '54536587d5b748daabf86c94f72a62e6558c67a244f4da46e4c9dd63ba369b8c240a7f5f678ff58ea23dacf11913bfa1a23a11db265e715a089dc2f5e3fd3d7b' }, 'config/shenzen_neo/nas-ab01z.xml' => { - 'Revision' => '2', - 'md5' => '40abd28e22d93640a08506b18229cded19e4b73f1abfcdf245b68a3ee1eca58d7e59d09f2afdfc84e94c66cc13d88976cda0dd13e7c04cc4416719d4c25893d4' + 'Revision' => '4', + 'md5' => '11df6cacff870c04677b5fc3a3828281d6e59506d09c1696ded074a4a607b87f8f96a42277dd409f64d3f8a91ced972f4ada74a32bfd304e07c19a1bef427a2c' }, 'config/shenzen_neo/nas-ds01z.xml' => { - 'Revision' => '2', - 'md5' => '6110128ca2f14fe921a961598c8c01ab13cbb103321b506bdd6ac6c57822a4a1538e157eb0798510a82552b7884100a6075b96a411ab7b2b6b3e68b86773364d' + 'Revision' => '4', + 'md5' => 'dfd1992f3edf1e2b0c8e4f4afb6d99575ccfe2ea7c0042668fedccf540993fa39743f9bf969a5038d57dca3e1ab0749d28e1cb0be35272c71248b82625f99c09' }, 'config/shenzen_neo/nas-pd01z.xml' => { - 'Revision' => '3', - 'md5' => '981254222e07f2ef4cba573306206635b69b4f94376fe61097ea2ee4d8907e5aa482efc92f39d3be5664cdc4a07b8fd8fa682b5c75e00e1b11b8b408ab046c23' + 'Revision' => '5', + 'md5' => 'cbfd1220724bf3a460a69f6f278903ed790a8bf2dfd704e7a3d1e4c6467d1898a636ecd08bff6f8c1b855706268073648e8fb96f015bec3eec2b035c243089ed' }, 'config/shenzen_neo/nas-pd02z.xml' => { - 'Revision' => '1', - 'md5' => '35a0ebabfb716f932f0dd1b5a6e48d713df5c6ddee97a7b5ba13d8b6bef55e9d04574ea9730761083189d0250f8de77d1c71402ab82db5426880663e50eb8d32' + 'Revision' => '2', + 'md5' => '506ecedfdee089d52ff07117b0208dfaa2aca5a72d71d07ee4ce417a7760a1c8bde3139a5cb82c950b240de0528a3382eb59ec30ed3a4e530f71a7b69f765ba1' }, 'config/shenzen_neo/nas-rc01z.xml' => { 'Revision' => '1', 'md5' => 'd11ecf14ca8722b1e59f5cb5b20303be9bf66786e9a1d18038f2f0c760f8aeca673b31b993bda0369ed662cc96dfd3b314e8aff94e6fd8b1f2e981f51d90dbef' }, 'config/shenzen_neo/nas-wr01z.xml' => { - 'Revision' => '3', - 'md5' => '5783f4a716337413815ffb1ec6b2dcccac619629345e4c8d303ba7fc49e90b148303092bdc246a63d91b8a6903257ccdc9e309aafbaad900ca7375497854a116' + 'Revision' => '5', + 'md5' => 'b98d36d9c20d3d44f588519b788ee9b58a51361b8185561810bd2e62691955316c46467c1d27ea75b458ea91491bd4c789f05ae4e2cbdf8a24bd03359bf04f11' }, 'config/shenzen_neo/nas-wr01ze.xml' => { 'Revision' => '1', 'md5' => 'c17eb0cfba1f1b8f72da898a978fb0dcc0f2293f36c5d06e0967211f8f8d938707a94b1381bbfa9e6b5d6db9ca24240854d0a75e94994ca3a9708ff89643a524' }, 'config/shenzen_neo/nas-ws02z.xml' => { - 'Revision' => '1', - 'md5' => '09559580aaba9293ecc9a207cd1c003260372cdec4e71013e2564e6b925d1fd0e751b5a2ae6894a61df0eadd04472ce24ea775fbd20576d64ede37fe76260c04' + 'Revision' => '2', + 'md5' => '7eccf1cbebc601996e0d6a552217c0b1dc8883cc78fdddb088303888d15832f7734d08f43c0991e8c9535a9dccc1e4b6f509802ed972477b4e45d499f45bbd5c' }, 'config/simon/10002034-13X.xml' => { - 'Revision' => '2', - 'md5' => '5e38291d25df52c689d7228ddd5cf8285b03b4a7dcb4ad8d37574b86497278f5a01d08454d9df69e73153692470a02f19042ce72f5ce474be6f39f656083bd1e' + 'Revision' => '3', + 'md5' => '8bb9641949c548b619a32d4169dd3f3b14367fd98bcc0168ffb6402fab467d0821f1a011e5be2987eab93ccad87692aaea9a63ee568722dc05e69c4a22359485' }, 'config/simon/10002041-13X.xml' => { 'Revision' => '2', @@ -2120,36 +2244,44 @@ 'md5' => '7def694a6414e50226cf75191573d1fbe6a277cefa3170461e7f35301b968e28494cbd9217871ea6808206b9b417c696facf068f7a40892cb790d8b47d916fd8' }, 'config/steinel/is140-2.xml' => { - 'Revision' => '1', - 'md5' => '518130d83952b92f3ed0ace586a4dac4749d9cb59d387bea65110c1b87d4fe14bed9bce1c0a84a50c1faa05c3a21095ca57661b1390e5fbc4d637fc18c51ea62' + 'Revision' => '2', + 'md5' => 'f5538ee6fa326e3f433ba8ad930b38dd8468db94991e8697555ff64c5546f47bd8fd086347e4c80e7f921206bc11b35238a4c78e73d6ea1e751b2f4c4849a884' }, 'config/steinel/l810-led-ihf.xml' => { - 'Revision' => '2', - 'md5' => 'ea923e77ed8fde513534e3caf2747237de41784f5603fe00e04a8ec310031d720b39e8848153b5e4d92b2507b37e44cb6592faaaeeab8e3afa42125864ad62c0' + 'Revision' => '3', + 'md5' => '87ec6dd62e0f09a1c81645fdf0d54272791232633a2824f7571e2c44817cd418c4a5cd34b32141f36b8faee28eb93c63b22f514eb9d073d6d6055e24b99fa7c4' }, 'config/steinel/rs-led-d2.xml' => { - 'Revision' => '1', - 'md5' => '919c8d4110aa53995a8efc82fa39988280285e00a39275758a892dc4f4d51acb0024503177cec0ffc0da132de36158233896b9b606d32d8de13a02ab73e886fc' + 'Revision' => '2', + 'md5' => '9f3767724904d6ce85e7880dfdfec9c1f851638e0e35045790cc35589d0c9cd653fa176c48a7b818b5b8218c861e2903eb8adeb313a6d4e8bb9a33a61dc90976' }, 'config/steinel/xled-home-2.xml' => { - 'Revision' => '1', - 'md5' => 'b9ecff0786b4ae6d44d2459d283708f227c4970555087c5594bf9ae6459c1da1398a3dae1201b73e83ce874eaeb302bd4de5d3e2f446aa25d56f47b1be46bf43' + 'Revision' => '2', + 'md5' => 'abc03eeac10da39b8eb39afb7709ad9b44c819e6e0d43364599702a2d03f31bda2cfa395d72dbb5c4ece0e456370a1d39be41c5f99edc6fe3951fe512fe4162b' }, 'config/stelpro/stzw402.xml' => { - 'Revision' => '2', - 'md5' => '50b9b93834bbb64a3d66c48652f9d56e986be914227c96f47234930e4a352c0c806c6afcfd5e6c2bb92144ff4116b2905d6dd6e8bc05f16c4d40d4d3049fdf31' + 'Revision' => '3', + 'md5' => 'd50042a91f9b2fa3e64d618b8caa2f64ea8ec9c74e7fa82840556dc4d5a8ce1b8d8de840c008ff36619d0cb31393f066dd8a7c286af328ae66ffe0d6b5816221' }, + 'config/sunricher/srzv9001k8.xml' => { + 'Revision' => '1', + 'md5' => '3bac22970afda1d7629827057b92df49076f16258e76ee02674f0aaf0046a847642edb2c794740f2b8b1e9f38d0c2ec3932259b2803ff416f461757214bd0686' + }, 'config/sunricher/srzv9001t4dimeu.xml' => { - 'Revision' => '1', - 'md5' => 'de22a403943d201b5c5b5c3cc85ba716cebf67c2e9b1e47dd314769858fef155095bdc3425f2075b667e86c5003ec0df48d84c0492a7fe32b46055db77843e79' + 'Revision' => '2', + 'md5' => '211998372694c7f418d774c3dab739339f07167bb37faa972ce076e4de2391dcfe369ea1ea335d35a9db66f9dce34ea0ac3dad054f2f734c864e1462cb0f5d1d' }, + 'config/sunricher/srzv9003t4rgbweu.xml' => { + 'Revision' => '1', + 'md5' => 'a8754c4d9762da7d89d509475ce8f495f3e6d8a857c0dd38b10c0afbef1838ef96e417426edafb67403a011bc388c0dc80454fd64de935d9de38f642dc7bb9f6' + }, 'config/sunricher/srzv9101sachpeu.xml' => { - 'Revision' => '1', - 'md5' => '7d92e236fc3988db8405af72a5a8e3910fe4e831fd60de86e094baa75938bbe77f178e348316d121f3bfe160e032dbf63ebec790ceccc0372a1ad01ed2c84015' + 'Revision' => '2', + 'md5' => 'cfa47e28a8463496354a30d2998b5b11dab834b2ffa1b8e91a687d2ec4e9e41ef73d38d058dd60911aa69cb1164808da94b88d627744250e5abd576ea5f8d1fa' }, 'config/sunricher/zv9101.xml' => { - 'Revision' => '1', - 'md5' => '4e0c8599f9b3f0affa7ca6d111c7d42a475aa2bc42d463f7d1b881b54d8ba8dd19003d976bbc04e82395bac299334671ab01590bc0431f3a76d11ff36d1b6043' + 'Revision' => '2', + 'md5' => 'adb7779262cbea1eb2832f78e67b253cade102bcf7fd24aa14db965dbde11a8ff073ee654c7bf1af0c2c4f44507b97feffdf142ed8261ff163ada4d766b0d906' }, 'config/swiid/swiidinter.xml' => { 'Revision' => '3', @@ -2160,28 +2292,28 @@ 'md5' => '1de9d7c988ff7753ddf936270a4a2abe3e1de1d5e7e546da3f7c02619dec1f875029af669c9607f398f2634833d0b1f40a34e72cf3c8b2898a644e46f980930c' }, 'config/telldus/tzdw100.xml' => { - 'Revision' => 2, + 'Revision' => '2', 'md5' => '00dafcf5a0bb13180d8cae532067dbd8833c65374d800fe02134732413c02ea4361a2597bfe4bb0466d0bdde93216cdea5474b8aecc3a9d644212f989401bbdd' }, 'config/telldus/tzwp100.xml' => { - 'Revision' => '1', - 'md5' => '418e7897d568a49c61fc94f12c71b82fef1b51fad1fb9544aee9efeba72cbac6ec5e1903fbafd9c051c7bdd83721aa1e87eb1b428a180d8777d3208823bd0939' + 'Revision' => '2', + 'md5' => '632f66e9679859f3709bb56fd682d027b4076069e0ffde81fd5c90b01e5d1de5eaa4626a9dcba71257aae8abdc4454b50f4540802a273f4a1fdcd7fb53834d77' }, 'config/telldus/tzwp102.xml' => { - 'Revision' => '1', - 'md5' => '79820fea15abdb1eb8ba67a8556378e2ac5bc7d20b3add74af87c347480d71295556849072d54bd54eb330042d91b5934bb71fe2f35631758d29570ad6bb4939' + 'Revision' => '2', + 'md5' => 'f68f1a70eccd43240a3f87b647237abb39a5e66e33be3ad413dab356be16c6a4b6391cdfe3cd62d0bf02a0b4c10ea53d8724981040d7911d29fe3db560418cf7' }, 'config/there/800z.xml' => { 'Revision' => '1', 'md5' => 'b065d0460c3da5e6bab88657b36d0c840db877c3c0c89c26313d7fd4bd12f7f57af2045cf89bcd689449989f0902f3ae3c6487fa9842dc45ca4538931e4a134e' }, 'config/thermofloor/heatit021.xml' => { - 'Revision' => 8, + 'Revision' => '8', 'md5' => 'f95dd11de5275bd29d3ba1f459bb463ab3d1280d82a23a428486abdd6be9244bb79ee66e2c0c1218512402f7acc8aebca81d9acf2ae674173e20b100002c276e' }, 'config/thermofloor/heatit056.xml' => { - 'Revision' => '2', - 'md5' => 'f7cb533a4899b27fd5c985d180be04e67443f5af31fed4be0b7120e124278a30ad54b9470e966aad01063b7ecd9a8c4aa222557f2f2a1d63cd63e3c55cf0e577' + 'Revision' => '3', + 'md5' => 'd248ea9d79f6da656599bd9237cedde63af5d5789075d9dce1e355980053d8c25d7439a9de79778280f6086588b595f1bb91313e2ca0e42b9bf850c84c78a925' }, 'config/trane/TZEMT400AB32MAA.xml' => { 'Revision' => '3', @@ -2195,18 +2327,6 @@ 'Revision' => '3', 'md5' => '46e5a829940d1de88207f121808a62c7526871d0740875ef2976f43eebaad9e629651c266bb458c8843da0b0e880532b59d707f93b3e57f2eec4dfbfd04b5853' }, - 'config/tronika/zsc01d.xml' => { - 'Revision' => '1', - 'md5' => '8e08c87f78152bd6811b81eec125c20f23cf2ab5d035735e82242f9d39904373e198582e9aad5dfe080e49d0c8405a156def488ef1a3d2202a160e2e7e54e160' - }, - 'config/tronika/zv9040.xml' => { - 'Revision' => '1', - 'md5' => 'a81c673de1af340838322d9b08054fd4e8e072ec0eaafe1a6e1d1a1a2d42ce4cca381b5532a69d2a7d01bed0e6f6e0c52a58fa3574fe52643db81a4f76ac2f1a' - }, - 'config/tronika/zv9101.xml' => { - 'Revision' => '1', - 'md5' => '4e0c8599f9b3f0affa7ca6d111c7d42a475aa2bc42d463f7d1b881b54d8ba8dd19003d976bbc04e82395bac299334671ab01590bc0431f3a76d11ff36d1b6043' - }, 'config/vera/vera2.xml' => { 'Revision' => '3', 'md5' => 'c50512474aef869c8f849d9ea2d42bd28dd89de9198c3bb6bc95eff66e67ac50567580ac5a3cc9bdfbdb49e9c1fe036d4e6e9a4987a1135dc5d2b3d0d537dbe7' @@ -2220,20 +2340,20 @@ 'md5' => '7f9cdf21fd4ffcc3b7827c024564774932878b74faf99090321c4c9ee4f33c3326a66fc07a233e35ca058198af676a588f6f41e31506bbd1fdf14c59c2459a22' }, 'config/vision/zd2102.xml' => { - 'Revision' => '9', - 'md5' => '47a7efc5802a289e8fdaf6b219c2695ed5d77e5c7ec4d05adb5fbe13aac77d753cfe11115c9d97319a5680f4a2978bb20a343b4a09bfbeaaf4b7fb25df8f1aa8' + 'Revision' => '11', + 'md5' => 'd7308c12bd68905b955e4c729d96e0b3279e35a6fde798c6650f077a61391fcac0514c2ee54933c30c5bb1c73cdb85b00ae79c93fe7be775702070d2c84eefac' }, 'config/vision/zd2105us5.xml' => { - 'Revision' => '2', - 'md5' => 'b633caae889183f64dadff5e23786dddb0f103aec11824e6378fffc271ef10bba1fa31a0fbfc9d7cb7627cb1dc60721f0729988e5ae983add38874596eb22823' + 'Revision' => '3', + 'md5' => 'f520919cd7c02a48643a747d677ae891a96960ba84a4eaf90402a7d8a71f801fc924115f82190901eb658e49ad22d84ce5e7d407240b69be011b19373d10ab1d' }, 'config/vision/zd2201.xml' => { - 'Revision' => '3', - 'md5' => 'b8c9a6a236eb2474292ecb6b15a25aa5cb9ac10286d56614068116dac7fe475f149239e26af01a230c84578d0f75964f8b490fb83649c9cf03683bb24aad5d7b' + 'Revision' => '5', + 'md5' => '3186992dc8f959af67ab8dceeedfd6831649dbddd1d15350a854467d6f0219bb4b6187a7a7995a21133f6d58abc6d77129dfd2a34301d17e8a7ef57b04ac1429' }, 'config/vision/zd2301.xml' => { - 'Revision' => 3, - 'md5' => '036f5e6d664de09a3aab7cedadf5361be795514814dd0b5542abce3f0b606917bb6cfedb9661471ca8a1f6e8d5ae2d827f6a2a44f030ec8555cc6c17cd9aa94f' + 'Revision' => '4', + 'md5' => '5dbdf01ac0aff9cfc9de47fd4bff6d26642b39a0f5b9a98f9590250f637510370ee3e00963cb04b3d1303bcb74228f3b7d2f307105f69cf6233c4fd9cfd4809e' }, 'config/vision/zf5201.xml' => { 'Revision' => '2', @@ -2256,15 +2376,19 @@ 'md5' => '6765ebbdad546c3073673446a63a7b2bda080ec606ea6fccfedd4a49d76d54c1e48fc3c030eb2e44060751012dfde67b564d6c68d9faf40673d846e45b914e47' }, 'config/vision/zl7431.xml' => { - 'Revision' => '1', - 'md5' => 'e2a30515c1093744edfaa1117aadf5c3f3ce1b2838748d95a1ecdc3b1fa29d039a306504d89d45dc09e34f76fd7e62c8f2905187f5c0c7b1823a7a1e7148167f' + 'Revision' => '2', + 'md5' => 'd8437300f7533463a987685da39e0412fb06ab2615532125d51530c0aedff578164ec5cba8593b3bacdb7f15623ed11981f5a87169cf6d6068dfaac45810382e' }, + 'config/vision/zl7432us.xml' => { + 'Revision' => '1', + 'md5' => 'b4f4a7ffb44d5d9f74a9c3003b7cacaf1f28162555ac8134b187804369cdd23923e20e67f0a58141a79ac920a52294bc1ab560dd498530c3944507e144777054' + }, 'config/vision/zm1601eu.xml' => { 'Revision' => '4', 'md5' => '607da3bf3b0504dcefd2d6fb9312b6c3d21c1cabe6d1acd77b595aa112b0545fc3ebbfece0089796e9ab0c0b41f254ff28ba2e9f63d4f94615c8251064305dc0' }, 'config/vision/zm1601eu5.xml' => { - 'Revision' => 3, + 'Revision' => '3', 'md5' => '0f55aead2c32ce164f7b85ce9a7ea7d718d152fd8840ed48446d662f32144f6f706e17411f6fb5048577bc98c4e6fbb3f4974f6924ed0370f08f8cd44681cfba' }, 'config/vision/zm1602eu.xml' => { @@ -2272,16 +2396,16 @@ 'md5' => '298b94cc8f598b57409cf5db86304998053639cd0d74a44dae05f5eb69ac4c91ce7e034a1295242fb2784b52271c2d885675b72e8693650b79cd19c437387113' }, 'config/vision/zm1602eu5.xml' => { - 'Revision' => '2', - 'md5' => '77b3ad52f2eaad2e7bc43b105e9e4e450fe3581b3ba7b30ea1fdabf9d4c15f65a338ecc7e60c634f42e92197be111731e00632793355249fb9c69930f014e45e' + 'Revision' => '3', + 'md5' => '3e86f5e2fd0bd4a9e2ce3c433e017909efbf006ef6c542328907584531bda2f060264e2fa8c30a9b9d9ae644b772d67bff969a7067f8ca5669c789d360ed75a0' }, 'config/vision/zp3102.xml' => { - 'Revision' => '9', - 'md5' => 'a8ca862ecce2282d38ea82080dfa98884a6fe097db5671de6a514c92a757bcdaaea7702d491539da698ec7c85951ea40da0f02fc7257d267925cccbe7944d9e8' + 'Revision' => '10', + 'md5' => '5ab5e86cad871f1ec4153281ad321e3f387f7e49c41f684c1c9503fe29644ae7b91493bc13a4be07c8325bca365aeb05eef22322d9acdf9dae5c84888b4a0833' }, 'config/vision/zp3111.xml' => { - 'Revision' => '3', - 'md5' => '67276ee16f0d8ad5ae37bac8613d7118532bf52e6d60dcab6809310403bce7f558e3c3ddc25d123bcc4e16c4de3e0b78a55844139526eed5eaa45a9ac1ea5728' + 'Revision' => '6', + 'md5' => '54c3b06afbd284c83a935d5c18ccf21340d81e82188e5d88d1d52ffb655e0e5713aaadb28d9fbea214898dec7e2213816f3ef26dbae8aeafd923029b0ad8c46d' }, 'config/vision/zr1202us.xml' => { 'Revision' => '1', @@ -2299,10 +2423,6 @@ 'Revision' => '1', 'md5' => '6c3a3747736a8dbc94d55649dfac4757ed1e7f178e17dcb88b0515ec105b97fd51322047d36540fddf38a8a8663f4c95bc2518dc022e4c6eb4a1aac940206b04' }, - 'config/vitrum/vitrumBS.xml' => { - 'Revision' => '2', - 'md5' => '76f9677eade9e7eef265a6f907b4caf36fac9b6cd076a4ec92622f154416d224cd3e7747925edd95401d95cf1871a20d3d227a8f46fd7c6e090e757d1bbab080' - }, 'config/vitrum/vitrumI-Dimmer.xml' => { 'Revision' => '3', 'md5' => '238254ee2cc5feb7effc709529fd6b4811416284cc61215fda1384b72ccba66314b152af7684712044f1008a6b7c063ebcce7bed8872c1e657b6d1f8c048c18c' @@ -2311,14 +2431,14 @@ 'Revision' => '3', 'md5' => 'd417c83e11e28dfed63f1b1d685ed8c662c1d9733ec7d1bd1a3d42d648ed70361ee4312f1408cdeedeb5ce8d984e3e7b38f4a11f194dc35eacf359f6121c6040' }, - 'config/vitrum/vitrumII-Blind.xml' => { - 'Revision' => '3', - 'md5' => 'd75c8a6739a61a0aa1c1ff6c18a95c06688322ccd131aace8610270d31fa676c4c29d48107643a7ac735d39e1d5a77ad8465c31c47dbb2a7886eba551e8a7c9b' - }, 'config/vitrum/vitrumII-Dimmer.xml' => { 'Revision' => '4', 'md5' => '94048824ccffd27bf338bec81a6ac3f4d1b8c0d1c7af307ad1059986f99daac77522976762d51c13fc51e4710c2f6ddde1194d0502364600afc396c3f22d4104' }, + 'config/vitrum/vitrumII-RollerBlind.xml' => { + 'Revision' => '3', + 'md5' => 'd75c8a6739a61a0aa1c1ff6c18a95c06688322ccd131aace8610270d31fa676c4c29d48107643a7ac735d39e1d5a77ad8465c31c47dbb2a7886eba551e8a7c9b' + }, 'config/vitrum/vitrumII-Switch.xml' => { 'Revision' => '3', 'md5' => '1809b19960cae19a6a0216b9b63c30fac4fe14ec6f0a5a8f7b6346dff0461f6102d6ecb5e2ff069163e2b58b15b9b1ed9980623905a735273ca59b18f1915ed7' @@ -2352,12 +2472,12 @@ 'md5' => 'c724909421d7301bb7597c4360b536965ab40649a7db2a054fb19cfd2c29efa18ccd104217510de5814c1e75b387873a042ce6e0650a8a6f23219656ce29cc69' }, 'config/wenzhou/tz55.xml' => { - 'Revision' => 3, + 'Revision' => '3', 'md5' => 'e0e3de23861dc7ff105f07dbaf1d24524364357fceaa2bf4b55f531b28e25f34ccb3f2af802cb1befe5bf41a6c0182f0865bb165c1d16482a68e6c046349b9fd' }, 'config/wenzhou/tz56.xml' => { - 'Revision' => '2', - 'md5' => 'd0d0c4c23c88563efb078765748ba2ca9ee36d4d8e35635a218f6deba86ca8874eb841420467984daf7b08cad4ccc6dc546de8282a188f8429a9764be00e02bb' + 'Revision' => '3', + 'md5' => '731e37f2f19957d94f40921c7eaf52c9a304676ea91684e3e59c09289b560f17c0ad9079fd9b1dff5054f40382d28cbfed1666bfb7f98b8d958928018c91a016' }, 'config/wenzhou/tz56s.xml' => { 'Revision' => '1', @@ -2368,7 +2488,7 @@ 'md5' => 'f5010718afca7611e7c7318942c0d01211706a79c746ba0c7e2f3df5102d79b9edf2181e071f8134bc1f56b44020f87815b4e0a7b01dcd6b0f8af11ec92aac2c' }, 'config/wenzhou/tz65d.xml' => { - 'Revision' => 6, + 'Revision' => '6', 'md5' => 'c142e5b7ca34ce4a6f4cbe242ea63587711cbcc454dae6ed28c923a894e11c97f06442523ffac17120c14376674d8eef286115960aac716383ae96afa0b15e4a' }, 'config/wenzhou/tz66d.xml' => { @@ -2380,12 +2500,12 @@ 'md5' => 'b62b4bf4d4b4634460529385eb1427e7f396dfa29cf510a34e1cdb614cfff959ccf8bb5c5604b20bc012955581884efb8808e4c9d0d777976974ffa4f2bdbde2' }, 'config/wenzhou/tz68.xml' => { - 'Revision' => 3, - 'md5' => '5dd9727b4f8a3d37383b731f7d8489b7083fa52e4c88e406c00916abaf012e943feeedc55a9cfb2a1dfe18b27962e291256d68f77c8a4d25badc7d06a9cb0db3' + 'Revision' => '5', + 'md5' => '1692f252e441eaddb2efb274f9b6e9b43a60496f074c8e911c0b088699db1833164278bcffc2de8cdd2a0377f63ecd2c8ffb46655042350cd0db86731619a9ae' }, 'config/wenzhou/tz69.xml' => { - 'Revision' => '1', - 'md5' => 'a8a1406c7c23358e2ed50b7bae79e0d7e6bcbab1bc2480c76deb228616c32e6b77c90910caba06c29bf2249c2fa2bb506da27295c72914abec1232f86d25ecc6' + 'Revision' => '7', + 'md5' => '6cab1b3be95dd92fca2e77e4c6320cb6783519302b711502fb5ba9012d8bd0c958c4759b7e3bfd613714f08d0b96c634aed3485a1217bb9277d4e2024666c05c' }, 'config/wenzhou/tz74.xml' => { 'Revision' => '1', @@ -2396,76 +2516,80 @@ 'md5' => '2bf67e52c7ea08ed1669c002b5d80ca5101bf88c0c0565c1798d177f7b70a21981770fe89a36d07588c2e562a7728b543ae7e64167ad431a6028a6897dff0f3c' }, 'config/wenzhou/tz88.xml' => { - 'Revision' => 7, + 'Revision' => '7', 'md5' => '571fe7897815e47fd1b640f2bdd741b9daee276510e8348bd6e9002e018a8e16c67b00c94ca6f3d0ce15c847c61ae2eaa0146772b7a8c330aab89f31935ed3b3' }, + 'config/widom/DRY.xml' => { + 'Revision' => '1', + 'md5' => '8f3fb96319999fadb2a0ec7f3f80266588c465a022ef2e51b51a8d2bdd431fdaafd705e412a087e71eca17b9bf8282dee4b66975832fc95619280e1f31708179' + }, 'config/widom/UBS104.xml' => { 'Revision' => '2', 'md5' => '6843a6c3d929b4e54a1751853942e8cea1651c35f39722138cd21ef47746103881cf18242518f9c459087950fdf29f051ec90b56f844b1290a47db87d8a2c47b' }, 'config/widom/UME304C_S.xml' => { - 'Revision' => 3, + 'Revision' => '3', 'md5' => 'cedd8b8d8c43c00c9213bb2aec31fca162f048abe3543a7da214bf4ae65eab07429ad6ed9f4c973aa0da220d9243e348b8b4351367fc856b759cd275fb2fb1b7' }, 'config/widom/WDS.xml' => { - 'Revision' => '3', - 'md5' => 'dd79aea6b8cc4c72681db7e38622fc7378d6468404794b070c089604b225a0e8e23cadc05525ea1657283044dd877f2e8bc3bf356100840fa343db8ed05fd19b' + 'Revision' => '4', + 'md5' => 'd990ef6c9e1876d3980827d7e4c084eaab69193252d3bfe118a87b5307e0583eee1f5454ba2e46e89b805802274f857fecf3e9bd5797b3d59745292729f1d6d8' }, 'config/zipato/MiniKeypad.xml' => { 'Revision' => '3', 'md5' => '1137446900ed79f792ef14c677ae4e99aeca62b977ef3acfcacf114784f6ea82f09471d7c498c977cdc92228cd3e2903afc445f0782186766c7ae21f2dfdf5cd' }, 'config/zipato/RGBBulb.xml' => { - 'Revision' => 2, - 'md5' => '7eddb4e176900e1fe347af8eb984c9f248a453e8730f77f125479913bed567d0a6f71e8db14bc688bd16074aba28ac92e9192f4817d97f0387f8000568924276' + 'Revision' => '3', + 'md5' => 'f0e8b19dbd8492ebd4751bba9855b96592b66bfe06e6a8788831e35e89a46f14f5376651995f26c0f966e742ca880cfabb26af0696d632195711f554949cde7c' }, 'config/zipato/RGBBulb2.xml' => { 'Revision' => '3', 'md5' => '3ab581bd5b844da008afc3e601f8486bfd9b4e89f627d018b815955a4cee2a537eaa0ef2714ad4ec2e1b9ce69064e4942a29f1f8703f19181333e13b9ebc4c58' }, 'config/zipato/pan04.xml' => { - 'Revision' => '2', - 'md5' => 'e791e6d0acd0ecd78c05ab927db3aa9ff51e716bbc565984e8f3dac4ccaf7687414aeebb7d1565370a3a05e4ea56b71ad088c9659149bf54874b8d5498c7c4a0' + 'Revision' => '3', + 'md5' => '73a6ceb8dfa58662bf133853184b7786947c388d9764cb4cc7a0d1ff9f02c1f6faff90ba930d6a96da589abb4c779003e1eeccedf9a663c3aa76408cd3e65d8d' }, 'config/zipato/vszd2102.xml' => { - 'Revision' => '2', - 'md5' => '371a23139744f1990f34782de7d06b3a0114f7e04abb80f725aa0d8adfe4b3508f3ae4850a1d9fc312bbb4f804913a9e165a4ebda0958ff610a5fa0414708de8' + 'Revision' => '3', + 'md5' => '3a083cdd5300ea8233f80836cf92de77f94789d3621a23911c103d8789ee0fbe46ee50f233e2f6109e0407e9b304072008cfb1efe7a7108194921cfd4e905511' }, 'config/zipato/zp3102.xml' => { - 'Revision' => '2', - 'md5' => '421da3f20a8b13eeba7ee43175b0c0d41aa2cb176215c7ac28baaabe169258b390e518b336d7eacf14273dc106953957e7ff3ce37eaca3c38aeb77b2f34eaef8' + 'Revision' => '4', + 'md5' => '9b6e2104c590a66f620ce51e77f1318cb413f690600c932ded4d650e2cf822a085eb2ebb4f3293f6a48cb3c408d15b56e8496923143a5500921fc37b76bbe18d' }, 'config/zooz/zen06.xml' => { - 'Revision' => '1', - 'md5' => 'f4c999aba0419b2bce0631a3443e69b776433bbdf48ccb79e2e965ce72b2b88f1a3337828ed000df3a8b00b08e8c57331bbcd1a152e34331edec50fd43d27126' + 'Revision' => '2', + 'md5' => '3272685c18a9649d5b938ec972f5d4fc8732fe16a5f2d5e44c42a8023f2051e1844316320a0bb11bf5521dd0a854c8899384ca629725ddcbfec89432382d8ea1' }, 'config/zooz/zen07.xml' => { 'Revision' => '2', 'md5' => 'c96f925786747bb098e22f5ecb671dc52d51736dd1e8c9a83ab84a77bcb9abe6bae0da1f86af32970da18b2f2f3e987bd2ce4bd1cfa5444f702b5ea32e2dca72' }, 'config/zooz/zen15.xml' => { - 'Revision' => '1', - 'md5' => 'faf24d5d25cd5051bc46a131431ac1bc0882f5955d214df836f2d09bd78f928226a530e47bc4034e9af9bbed678deb50a2b319ce46cbe5a3891c3df9d1437ed1' + 'Revision' => '2', + 'md5' => 'fc33bd7bbe32980ecf49082d92401742b4c19a8906a736a99feb4ad5208cecda504f443aa3fcdb21fcea2de6702db39d876215fb3a2e827dfa7c05ce15568ddd' }, 'config/zooz/zen20.xml' => { - 'Revision' => '1', - 'md5' => '2ce68705ce568c26d09150263a989afc6eef4175dbd8e8a45ade1208eae3ae44f3bc1a8f7eb544967fc983ff0d831bd76d20e9a76a40471e93851dba4b6c472a' + 'Revision' => '2', + 'md5' => 'ac2c564441a145b501c401ca5fbb62806ae9d69a354bf2abebce04f50e6017c10d3f5d3465975ac771cb047b31d4bca8e1fde9f5c910a36d0bb958c3c1b57826' }, 'config/zooz/zen20v2.xml' => { - 'Revision' => '1', - 'md5' => '20250445291e762729e124618023081b5cbfc1f25f0b3868e4453368f90ed9d67cbe8750e64da7bfccd19f8acdffba2fb22f686a8f8edecbfe016dd7399d2707' + 'Revision' => '2', + 'md5' => 'fe4cd67071d47c622e7cb9ac99b34c43865d8387df219347649fc2ff2b73b11c8763450abee39fbf884be7297ca5b286276dd3b69b5bc93f38b068ef12911821' }, 'config/zooz/zen21.xml' => { - 'Revision' => '1', - 'md5' => '0b9fff4c7762982a8827127dab9b51b84dc2efbc07b55a1a6298d136dfd140e6ede363a1f3b4a9bf8828ff4cc68e591f2ac9d6aaf989746ac95c3bc32a6d23fb' + 'Revision' => '3', + 'md5' => '047323e2ed1a3e5340c052d40737fbdb2d2790e225e002f7d58fa3ad32f592da3e2a8cc0f3dd6cc6f06f7b6b505378482be7125db0a335e56abfd478c1cb398b' }, 'config/zooz/zen21v2.xml' => { 'Revision' => '1', 'md5' => '3891b1d08aac36a6c37ac96fc3015947bd5119305c066600a3a16231f7c171dbc3893dbb1cf654d9fec1f2c01fd62e3d6cc635f2afd186e21f87ac8fe1529293' }, 'config/zooz/zen22.xml' => { - 'Revision' => '1', - 'md5' => '3fc436977c83df58ffa6c470cce584f1f80ad30c7aba73e38b58c8a40585bc7fb8505c000f77fe507940d8d50bed06e1b105b08b30c8b25de8dd9c7d8f472153' + 'Revision' => '2', + 'md5' => '5516b28dbfb21fa8057cf83e04100d7e27a74d6bffa5c8203924fbd139ffee8536552307cab4c29dc92f4d762c99e357eb5f86641bae733fb226d67fab9b09a5' }, 'config/zooz/zen22v2.xml' => { 'Revision' => '2', @@ -2484,40 +2608,44 @@ 'md5' => 'a1518c737c0eb0b63610dca95ebece7df7be426b8b435fb309314f110c77ddb90146d0b03888d2ac03959b2bfd6d181edb7b71cc59c798aeb7f5fa341c4f0d4d' }, 'config/zooz/zen26.xml' => { - 'Revision' => '1', - 'md5' => 'a167a3ac9dfeb417ee90a9dba947d483632859adb1c8e98b4efab19b1e3ca1e2da7a4eb9063f67e53568ce61ff556eab3a0107c7d6bb168a891dedaf40446ecb' + 'Revision' => 3, + 'md5' => 'a29881e72eda6f6f3e7f649efa58c8ee1ac1728985c37885a7fd987d9685bcb7d50306a6a72b42f3fad06935fa56f4cc3a50bbd13852d5d56ded7468897f2584' }, 'config/zooz/zen27.xml' => { - 'Revision' => '1', - 'md5' => 'f5b7f1dee5d98246915ea79190e907b6a9b0020a7c872f7ed14db4c2acfac8400d30db46e48f3a9aae5fa1063f71844f32f26db909cf4ab7b3aecb01d200d58a' + 'Revision' => 2, + 'md5' => '5ab98630896730c87473681c02bb78e6774818f447d47abbc4da4b2c2560ed23b5e2b1ace378c942eb65ad8cb9794ebe038fc2bb68e62c3f6e1ece9df2fb05ef' }, 'config/zooz/zse08.xml' => { 'Revision' => '1', 'md5' => '78ecc6bdf19ce151d87a328949b4ce16e59bf6fd20212d4a7fd23da700e177259b8903bba5150f87c71f7d6ec4b140855c5337b5053cc358b0e2e8c5c41885dc' }, 'config/zooz/zse09.xml' => { - 'Revision' => '3', - 'md5' => '60b8e5f34b6328e1b7797ba4fdf54b227a06f5eebc94e6f5b7103bc817c8e2c424454915dfab0504020a57edd02c5a6ef5e8b21a6d6797f477b7ba20ad15c377' + 'Revision' => '5', + 'md5' => 'b50183e6c2dc5b4b9678ad3cdd96198e14eaabecf9fcb02783b5027d6cfcc34761eb1ffcf7667e5775b989e624138bfedda4dd5f43caf95d33c5a3d85653fe63' }, 'config/zooz/zse18.xml' => { 'Revision' => '1', 'md5' => '463b089a041215ad5c2f2576648a86d2720477f4d1be2e9f3c8914a9c97e8bd31f1b9cd7300019ffc99224d8da0b9fcac78f2f134fbd6f1b68f3027f2392b753' }, 'config/zooz/zse19.xml' => { - 'Revision' => '1', - 'md5' => '2c871b75b9f2b3e6fbba6db71716216191e3f66bcb54a5d3103dc3849ff889b814e3a88dad231fcfdf03c358419e4772c9c331ec60044d781cf57ee17c3e6bd0' + 'Revision' => '2', + 'md5' => 'b7115353998366bdeebc3f5bd1182429f1c20e0e229ca5e22eb7c6d5fb0e617f5af16faac078ed29c17db01c6e1338628a34d3434e8adfcd1cc08b8a59dcdd2c' + }, + 'config/zooz/zse29.xml' => { + 'Revision' => '2', + 'md5' => '8bbe07b8c1158ae2673a0f30be191749dd5b3f40a2043d056615c28fc4d7b9b3e69545ab0925da167080b52279a032d93e8112d3db132fb3a0fd5199c9037832' }, 'config/zooz/zse30.xml' => { - 'Revision' => '1', - 'md5' => '162910f06e630312751a36131cabfbeeb64515071b7d0b0e0c3f794d7be0b0e0d898fe4cbdce3c6c86c18daeab12c0af0630e504651f8fd84131040d32d7af55' + 'Revision' => '2', + 'md5' => '16731dc5b294943714a42063058ccbbcaa230b5fc3afd675b9ce340dbfd6466f22ffea32b6d055d8ef5bac341bd86123b490e62509c71f97e0cd3a35a8e23203' }, 'config/zooz/zse33.xml' => { - 'Revision' => '1', - 'md5' => '614c29e13e41e018c199752a9293e482076bff5af4194fc682cb4204ba3251ac2a87cc3553e958afdbf8627a9792fc5c33c6aa57e170ea42d010ea876c4adbc7' + 'Revision' => '2', + 'md5' => '0484e37ea12b75ce8b33c7501a01c8fd45c2176e0c696ceedc3699a94f71e8bc08ffd425336f58e202c8adba41799a4af0c39d6ca109ba501b5f2fdcffb301a4' }, 'config/zooz/zse40.xml' => { - 'Revision' => '3', - 'md5' => '3f8fc81dca577fd6c964972ed6bd39b152dc8feac887060590a9786a6e4fd8b14de661859b1dcedec4d855b3e5af1714916dbf9b4f18eee33815c5db91d39834' + 'Revision' => '4', + 'md5' => '1e0ed06e4dd0df87cd985a28f0f1d89c32da3f4568334aae4ed0cf8c525910d43b63a8f4a426d5ee1c71328dc75f58fe0d900d24594f19c7b6ef337a77452d4e' }, 'config/zwave.me/004001.xml' => { 'Revision' => '1', @@ -2564,8 +2692,8 @@ 'md5' => '90b00f6c25ecfabd71029590bb0d5a20bd2265297d01ba15ab11e4f9f2dd60d63bdb0cc1988bd03c1b1e3420622848bdc80c7b039a7b31c2a50627dd3c8d1e39' }, 'config/zwave.me/ZUno.xml' => { - 'Revision' => '3', - 'md5' => '7d9e78d71ca2f7f898c4699c530a82a055d98ccaf1324ff65c2cab402d2e5896a6931e9a0214cd08d783edd6a5da564cb499fa1a7e05ac22844ecad583265652' + 'Revision' => '4', + 'md5' => '74246cca8439213f22c8000f53c8f7599bbed8ce05fb24f8a28ed5179e1625d66584e5c0511a9ce2d464173816aad3dc9563f72042960ca2f129b36d4e48f6ef' }, 'config/zwave.me/iTemp.xml' => { 'Revision' => '3', @@ -2576,7 +2704,7 @@ 'md5' => 'c071ad553d96f6e79fa728e477dd6a12c9ddb0a029f69657ee65a2438bf9fdf9c9ee3d57084e6ddfb35a346a54bb51a8c4708642b40968041df0a336a2cba0c4' }, 'config/zwave.me/popp_kfob-c.xml' => { - 'Revision' => 4, + 'Revision' => '4', 'md5' => '91374eeabd5950ae498de528ee67309d78f87bc3f2d18b1cb73e06f4d16f660eb0099e583397e7003a0a5796d7261f5f5ec029ba67ef683319d35c20da4cd3a3' }, 'config/zwave.me/zme_raz5.xml' => { @@ -2584,15 +2712,15 @@ 'md5' => 'cdfd903cab9349c17a53d25ff8210d42a5f9197ebbe8fd3e654dc5caedc12c40e96bcb3fadfdf72ce3e05d59c99de58fd21858be5ca8c2c820c8d315e3415149' }, 'config/zwave.me/zweather.xml' => { - 'Revision' => 2, + 'Revision' => '2', 'md5' => 'f40e1e4cc7ff539af041862b90ccf3dc74b602fab35a6e74a406694ee29283077d3b1cd418b52fcdee30269e75e9b07155024cb5f62cb1bebc5fef8012492ba6' }, 'config/zwp/PA-100.xml' => { - 'Revision' => '1', - 'md5' => 'd56c0e81121ac1a31d631c3d99f2cd27617e30ace00d6924f407e7f580988836bd876711ae5927579bc7bb030cfa0898ca7ef5f5a6e1ff781e80f0a5802e8dd7' + 'Revision' => '2', + 'md5' => '93335c6b61d2f82b5bdc62d2c48cb3e10bf2bad3ea39c9e0e7a82d191e3b74b23937f6c12f473fd5243983382337b23b652dc64f663c74fcd3f1a99be4e58ec4' }, 'config/zwp/WD-100.xml' => { - 'Revision' => '1', - 'md5' => 'eaa6ac2bcfd0f8fab022efd6ddd6c80febba232ed232cb5ada3a45066c3be85ad03fa87af36e7c3ee67c9a200bc6d21eb41d22c2f0c65b4a937f46f59c847f24' + 'Revision' => '3', + 'md5' => 'a5bceb54540c63bdc1f03a6f26ff79f1bba74af878895b8f70cdfe67fdd6165c366b1cea29f44a5773549655012aafd4c8cd35fa78180ad30cd1b39de36357e6' } ); diff --git a/cpp/build/winRT/vs2015/OpenZWave.vcxproj b/cpp/build/winRT/vs2015/OpenZWave.vcxproj index cbe8ea4986..f511f189b5 100644 --- a/cpp/build/winRT/vs2015/OpenZWave.vcxproj +++ b/cpp/build/winRT/vs2015/OpenZWave.vcxproj @@ -386,6 +386,7 @@ exit 0 + @@ -517,6 +518,7 @@ exit 0 + @@ -531,6 +533,7 @@ exit 0 + diff --git a/cpp/build/windows/vs2008/OpenZWave.sln b/cpp/build/windows/vs2008/OpenZWave.sln deleted file mode 100644 index 83f41cf299..0000000000 --- a/cpp/build/windows/vs2008/OpenZWave.sln +++ /dev/null @@ -1,26 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenZWave", "OpenZWave.vcproj", "{497F9828-DEC2-4C80-B9E0-AD066CCB587C}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - DLL_Debug|Win32 = DLL_Debug|Win32 - DLL_Release|Win32 = DLL_Release|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Debug|Win32.ActiveCfg = Debug|Win32 - {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Debug|Win32.Build.0 = Debug|Win32 - {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.DLL_Debug|Win32.ActiveCfg = DLL_Debug|Win32 - {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.DLL_Debug|Win32.Build.0 = DLL_Debug|Win32 - {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.DLL_Release|Win32.ActiveCfg = DLL_Release|Win32 - {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.DLL_Release|Win32.Build.0 = DLL_Release|Win32 - {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Release|Win32.ActiveCfg = Release|Win32 - {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/cpp/build/windows/vs2008/OpenZWave.vcproj b/cpp/build/windows/vs2008/OpenZWave.vcproj deleted file mode 100644 index 9a09ad83df..0000000000 --- a/cpp/build/windows/vs2008/OpenZWave.vcproj +++ /dev/null @@ -1,1223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cpp/build/windows/vs2010/OpenZWave.vcxproj b/cpp/build/windows/vs2010/OpenZWave.vcxproj index c7fb8e4637..a9e680d28d 100644 --- a/cpp/build/windows/vs2010/OpenZWave.vcxproj +++ b/cpp/build/windows/vs2010/OpenZWave.vcxproj @@ -1,4 +1,4 @@ - + @@ -230,11 +230,13 @@ exit 0 + + @@ -359,6 +361,7 @@ exit 0 + @@ -403,6 +406,7 @@ exit 0 + diff --git a/cpp/examples/MinOZW/Main.cpp b/cpp/examples/MinOZW/Main.cpp index 97b6e969e2..15613e1a6d 100644 --- a/cpp/examples/MinOZW/Main.cpp +++ b/cpp/examples/MinOZW/Main.cpp @@ -136,7 +136,7 @@ void OnNotification // One of the node values has changed if( NodeInfo* nodeInfo = GetNodeInfo( _notification ) ) { - nodeInfo = nodeInfo; // placeholder for real action + (void)nodeInfo; // placeholder for real action } break; } @@ -146,7 +146,7 @@ void OnNotification // One of the node's association groups has changed if( NodeInfo* nodeInfo = GetNodeInfo( _notification ) ) { - nodeInfo = nodeInfo; // placeholder for real action + (void)nodeInfo; // placeholder for real action } break; } @@ -186,7 +186,7 @@ void OnNotification // basic_set or hail message. if( NodeInfo* nodeInfo = GetNodeInfo( _notification ) ) { - nodeInfo = nodeInfo; // placeholder for real action + (void)nodeInfo; // placeholder for real action } break; } @@ -366,11 +366,12 @@ int main( int argc, char* argv[] ) { ValueID v = *it2; printf("\t ValueLabel: %s \n", Manager::Get()->GetValueLabel(v).c_str()); - printf("\t\t ValueType: %d \n", v.GetType()); + printf("\t\t ValueType: %s (%d) \n", v.GetTypeAsString().c_str(), v.GetType()); printf("\t\t ValueHelp: %s \n", Manager::Get()->GetValueHelp(v).c_str()); printf("\t\t ValueUnits: %s \n", Manager::Get()->GetValueUnits(v).c_str()); printf("\t\t ValueMin: %d \n", Manager::Get()->GetValueMin(v)); printf("\t\t ValueMax: %d \n", Manager::Get()->GetValueMax(v)); + printf("\t\t ValueGenre: %s (%d)\n", v.GetGenreAsString().c_str(), v.GetGenre()); if( v.GetCommandClassId() == COMMAND_CLASS_BASIC ) { @@ -389,13 +390,13 @@ int main( int argc, char* argv[] ) // stalling the OpenZWave drivers. // At this point, the program just waits for 3 minutes (to demonstrate polling), // then exits - for( int i = 0; i < 60*3; i++ ) - { - pthread_mutex_lock( &g_criticalSection ); + //for( int i = 0; i < 60*3; i++ ) + //{ + // pthread_mutex_lock( &g_criticalSection ); // but NodeInfo list and similar data should be inside critical section - pthread_mutex_unlock( &g_criticalSection ); - sleep(1); - } + // pthread_mutex_unlock( &g_criticalSection ); + // sleep(1); + //} Driver::DriverData data; Manager::Get()->GetDriverStatistics( g_homeId, &data ); @@ -417,5 +418,12 @@ int main( int argc, char* argv[] ) Manager::Destroy(); Options::Destroy(); pthread_mutex_destroy( &g_criticalSection ); + for( list::iterator it = g_nodes.begin(); it != g_nodes.end(); ++it ) + { + NodeInfo* nodeInfo = *it; + nodeInfo->m_values.clear(); + delete nodeInfo; + } + g_nodes.clear(); return 0; } diff --git a/cpp/examples/MinOZW/Makefile b/cpp/examples/MinOZW/Makefile index fe37cf5514..ec613e55e7 100644 --- a/cpp/examples/MinOZW/Makefile +++ b/cpp/examples/MinOZW/Makefile @@ -10,8 +10,8 @@ .PHONY: default clean -DEBUG_CFLAGS := -Wall -Wno-format -ggdb -DDEBUG $(CPPFLAGS) -RELEASE_CFLAGS := -Wall -Wno-unknown-pragmas -Wno-format -O3 $(CPPFLAGS) +DEBUG_CFLAGS := -Wall -Wno-format -ggdb -DDEBUG $(CPPFLAGS) -std=c++11 +RELEASE_CFLAGS := -Wall -Wno-unknown-pragmas -Wno-format -O3 $(CPPFLAGS) -std=c++11 DEBUG_LDFLAGS := -g @@ -66,8 +66,8 @@ LDFLAGS+= -lusb-1.0 endif $(OBJDIR)/MinOZW: $(patsubst %.cpp,$(OBJDIR)/%.o,$(minozwsrc)) - @echo "Linking $(OBJDIR)/MinOZW" - $(LD) $(LDFLAGS) $(TARCH) -o $@ $< $(LIBS) -pthread + @echo "Linking MinOZW" + @$(LD) $(LDFLAGS) $(TARCH) -o $@ $< $(LIBS) -pthread $(top_builddir)/MinOZW: $(top_srcdir)/cpp/examples/MinOZW/MinOZW.in $(OBJDIR)/MinOZW @echo "Creating Temporary Shell Launch Script" diff --git a/cpp/examples/windows/MinOZW/vs2008/MinOZW.sln b/cpp/examples/windows/MinOZW/vs2008/MinOZW.sln deleted file mode 100644 index 2a94b33e16..0000000000 --- a/cpp/examples/windows/MinOZW/vs2008/MinOZW.sln +++ /dev/null @@ -1,39 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MinOZW", "MinOZW.vcproj", "{22847D76-B1CF-4921-8B7A-61E248412C4A}" - ProjectSection(ProjectDependencies) = postProject - {497F9828-DEC2-4C80-B9E0-AD066CCB587C} = {497F9828-DEC2-4C80-B9E0-AD066CCB587C} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenZWave", "..\..\..\..\build\windows\vs2008\OpenZWave.vcproj", "{497F9828-DEC2-4C80-B9E0-AD066CCB587C}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - DLL_Debug|Win32 = DLL_Debug|Win32 - DLL_Release|Win32 = DLL_Release|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {22847D76-B1CF-4921-8B7A-61E248412C4A}.Debug|Win32.ActiveCfg = Debug|Win32 - {22847D76-B1CF-4921-8B7A-61E248412C4A}.Debug|Win32.Build.0 = Debug|Win32 - {22847D76-B1CF-4921-8B7A-61E248412C4A}.DLL_Debug|Win32.ActiveCfg = DLL_Debug|Win32 - {22847D76-B1CF-4921-8B7A-61E248412C4A}.DLL_Debug|Win32.Build.0 = DLL_Debug|Win32 - {22847D76-B1CF-4921-8B7A-61E248412C4A}.DLL_Release|Win32.ActiveCfg = DLL_Release|Win32 - {22847D76-B1CF-4921-8B7A-61E248412C4A}.DLL_Release|Win32.Build.0 = DLL_Release|Win32 - {22847D76-B1CF-4921-8B7A-61E248412C4A}.Release|Win32.ActiveCfg = Release|Win32 - {22847D76-B1CF-4921-8B7A-61E248412C4A}.Release|Win32.Build.0 = Release|Win32 - {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Debug|Win32.ActiveCfg = Debug|Win32 - {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Debug|Win32.Build.0 = Debug|Win32 - {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.DLL_Debug|Win32.ActiveCfg = DLL_Debug|Win32 - {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.DLL_Debug|Win32.Build.0 = DLL_Debug|Win32 - {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.DLL_Release|Win32.ActiveCfg = DLL_Release|Win32 - {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.DLL_Release|Win32.Build.0 = DLL_Release|Win32 - {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Release|Win32.ActiveCfg = Release|Win32 - {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/cpp/examples/windows/MinOZW/vs2008/MinOZW.vcproj b/cpp/examples/windows/MinOZW/vs2008/MinOZW.vcproj deleted file mode 100644 index 67416387b4..0000000000 --- a/cpp/examples/windows/MinOZW/vs2008/MinOZW.vcproj +++ /dev/null @@ -1,336 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cpp/src/Bitfield.cpp b/cpp/src/Bitfield.cpp index a0dedacfd1..71af08c755 100644 --- a/cpp/src/Bitfield.cpp +++ b/cpp/src/Bitfield.cpp @@ -27,178 +27,187 @@ #include "Bitfield.h" -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + /* Note: we have our own "BitSet" class rather than using the Std Library version + * as the Std Library version can not be resized at runtime. This version can. Its the basis + * of the BitSet ValueID class + */ -/* Note: we have our own "BitSet" class rather than using the Std Library version - * as the Std Library version can not be resized at runtime. This version can. Its the basis - * of the BitSet ValueID class - */ + Bitfield::Bitfield() : + m_numSetBits(0), m_value(0) + { + } + Bitfield::Bitfield(uint32 value) : + m_numSetBits(0), m_value(value) + { + for (unsigned int i = 0; i < 8 * sizeof(uint32); i++) + { + if (m_value & (1 << i)) + { + Set(i); + } + } + } + Bitfield::~Bitfield() + { -Bitfield::Bitfield() : - m_numSetBits(0), - m_value(0) -{ -} + } -Bitfield::Bitfield(uint32 value) : - m_numSetBits(0), - m_value(value) -{ - for (unsigned int i = 0; i < 8 * sizeof(uint32); i++) { - if (m_value & (1 << i)) { - Set(i); + bool Bitfield::SetValue(uint32 val) + { + for (unsigned int i = 0; i < 8 * sizeof(uint32); i++) + { + if (val & (1 << i)) + { + Set(i); + } + else + { + Clear(i); + } + } + return true; } - } -} -Bitfield::~Bitfield() -{ -} + bool Bitfield::Set(uint8 _idx) + { + if (_idx > 0x1F) + { + return false; + } -bool Bitfield::SetValue(uint32 val) { - for (unsigned int i = 0; i < 8 * sizeof(uint32); i++) { - if (val & (1 << i)) { - Set(i); - } else { - Clear(i); + if (!IsSet(_idx)) + { + uint32 newSize = (_idx >> 5) + 1; + if (newSize > m_bits.size()) + { + m_bits.resize(newSize, 0); + } + m_bits[_idx >> 5] |= (1 << (_idx & 0x1f)); + ++m_numSetBits; + } + return true; } - } - return true; -} + bool Bitfield::Clear(uint8 _idx) + { + if (_idx > 0x1F) + { + return false; + } + if (IsSet(_idx)) + { + m_bits[_idx >> 5] &= ~(1 << (_idx & 0x1f)); + --m_numSetBits; + } + return true; + } -bool Bitfield::Set( uint8 _idx ) -{ - if (_idx > 0x1F) { - return false; - } + bool Bitfield::IsSet(uint8 _idx) const + { + if (_idx > 0x1F) + { + return false; + } + if ((unsigned int) (_idx >> 5) < (unsigned int) m_bits.size()) + { + return ((m_bits[_idx >> 5] & (1 << (_idx & 0x1f))) != 0); + } + return false; + } - if( !IsSet(_idx) ) - { - uint32 newSize = (_idx>>5)+1; - if( newSize > m_bits.size() ) + uint32 Bitfield::GetNumSetBits() const { - m_bits.resize( newSize, 0 ); + return m_numSetBits; } - m_bits[_idx>>5] |= (1<<(_idx&0x1f)); - ++m_numSetBits; - } - return true; -} -bool Bitfield::Clear( uint8 _idx ) -{ - if (_idx > 0x1F) { - return false; - } - if( IsSet(_idx) ) - { - m_bits[_idx>>5] &= ~(1<<(_idx&0x1f)); - --m_numSetBits; - } - return true; -} + uint32 Bitfield::GetValue() const + { + uint32 value = 0; + for (unsigned int i = 0; i < m_bits.size(); i++) + { + value += (m_bits[i] << (8 * i)); + } + return value; + } -bool Bitfield::IsSet( uint8 _idx )const -{ - if (_idx > 0x1F) { - return false; - } - if( (unsigned int)(_idx>>5) < (unsigned int)m_bits.size() ) - { - return( ( m_bits[_idx>>5] & (1<<(_idx&0x1f)) ) !=0 ); - } - return false; -} + uint32 Bitfield::GetSize() const + { + return m_bits.size() * sizeof(uint32) * 8; + } -uint32 Bitfield::GetNumSetBits() const -{ - return m_numSetBits; -} + Bitfield::Iterator Bitfield::Begin() const + { + return Iterator(this, 0); + } + Bitfield::Iterator Bitfield::End() const + { + return Iterator(this, (uint32) m_bits.size() << 5); + } -uint32 Bitfield::GetValue() const -{ - uint32 value = 0; - for (unsigned int i = 0; i < m_bits.size(); i++) { - value += ( m_bits[i] << (8*i) ); - } - return value; -} - -uint32 Bitfield::GetSize() const -{ - return m_bits.size() * sizeof(uint32) * 8; -} + uint32 Bitfield::Iterator::operator *() const + { + return m_idx; + } -Bitfield::Iterator Bitfield::Begin() const -{ - return Iterator( this, 0 ); -} -Bitfield::Iterator Bitfield::End() const -{ - return Iterator( this, (uint32) m_bits.size()<<5 ); -} + Bitfield::Iterator& Bitfield::Iterator::operator++() + { + // Search forward to next set bit + NextSetBit(); + return *this; + } + Bitfield::Iterator Bitfield::Iterator::operator++(int a) + { + Iterator tmp = *this; + ++tmp; + return tmp; + } -uint32 Bitfield::Iterator::operator *() const -{ - return m_idx; -} + bool Bitfield::Iterator::operator ==(const Iterator &rhs) + { + return m_idx == rhs.m_idx; + } -Bitfield::Iterator& Bitfield::Iterator::operator++() - { - // Search forward to next set bit - NextSetBit(); - return *this; - } + bool Bitfield::Iterator::operator !=(const Iterator &rhs) + { + return m_idx != rhs.m_idx; + } -Bitfield::Iterator Bitfield::Iterator::operator++(int a) - { - Iterator tmp = *this; - ++tmp; - return tmp; - } + Bitfield::Iterator::Iterator(Bitfield const* _bitfield, uint32 _idx) : + m_idx(_idx), m_bitfield(_bitfield) + { + // If this is a begin iterator, move it to the first set bit + if ((_idx == 0) && (!m_bitfield->IsSet(0))) + { + NextSetBit(); + } + } -bool Bitfield::Iterator::operator ==(const Iterator &rhs) + void Bitfield::Iterator::NextSetBit() + { + while (((++m_idx) >> 5) < m_bitfield->m_bits.size()) + { + // See if there are any bits left to find in the current uint32 + if ((m_bitfield->m_bits[m_idx >> 5] & ~((1 << (m_idx & 0x1f)) - 1)) == 0) { - return m_idx == rhs.m_idx; + // No more bits - move on to next uint32 (or rather one less than + // the next uint32 because of the preincrement in the while statement) + m_idx = (m_idx & 0xffffffe0) + 31; } - -bool Bitfield::Iterator::operator !=(const Iterator &rhs) + else { - return m_idx != rhs.m_idx; + if ((m_bitfield->m_bits[m_idx >> 5] & (1 << (m_idx & 0x1f))) != 0) + { + // This bit is set + return; + } } - -Bitfield::Iterator::Iterator( Bitfield const* _bitfield, uint32 _idx ) : - m_idx( _idx ), - m_bitfield( _bitfield ) -{ - // If this is a begin iterator, move it to the first set bit - if( ( _idx == 0 ) && ( !m_bitfield->IsSet(0) ) ) - { - NextSetBit(); - } -} - -void Bitfield::Iterator::NextSetBit() -{ - while( ((++m_idx)>>5)m_bits.size() ) - { - // See if there are any bits left to find in the current uint32 - if( ( m_bitfield->m_bits[m_idx>>5] & ~((1<<(m_idx&0x1f))-1) ) == 0 ) - { - // No more bits - move on to next uint32 (or rather one less than - // the next uint32 because of the preincrement in the while statement) - m_idx = (m_idx&0xffffffe0)+31; - } - else - { - if( (m_bitfield->m_bits[m_idx>>5] & (1<<(m_idx&0x1f))) !=0 ) - { - // This bit is set - return; } } - } -} + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/Bitfield.h b/cpp/src/Bitfield.h index 4cb1ad123f..0cf0e38a20 100644 --- a/cpp/src/Bitfield.h +++ b/cpp/src/Bitfield.h @@ -33,54 +33,54 @@ namespace OpenZWave { -class OPENZWAVE_EXPORT Bitfield -{ - friend class Iterator; - -public: - Bitfield(); - Bitfield(uint32 value); - ~Bitfield(); - bool Set( uint8 _idx ); - bool Clear( uint8 _idx ); - bool IsSet( uint8 _idx ) const; - uint32 GetNumSetBits() const; - uint32 GetValue() const; - bool SetValue(uint32 val); - uint32 GetSize() const; - class Iterator + namespace Internal { - friend class Bitfield; - public: - uint32 operator *() const; - Iterator& operator++(); - Iterator operator++(int); + class OPENZWAVE_EXPORT Bitfield + { + friend class Iterator; - bool operator ==(const Iterator &rhs); - bool operator !=(const Iterator &rhs); - private: - Iterator( Bitfield const* _bitfield, uint32 _idx ); + public: + Bitfield(); + Bitfield(uint32 value); + ~Bitfield(); + bool Set(uint8 _idx); + bool Clear(uint8 _idx); + bool IsSet(uint8 _idx) const; + uint32 GetNumSetBits() const; + uint32 GetValue() const; + bool SetValue(uint32 val); + uint32 GetSize() const; + class Iterator + { + friend class Bitfield; - void NextSetBit(); + public: + uint32 operator *() const; + Iterator& operator++(); + Iterator operator++(int); - uint32 m_idx; - Bitfield const* m_bitfield; - }; + bool operator ==(const Iterator &rhs); + bool operator !=(const Iterator &rhs); + private: + Iterator(Bitfield const* _bitfield, uint32 _idx); - Iterator Begin() const; - Iterator End() const; + void NextSetBit(); -private: - OPENZWAVE_EXPORT_WARNINGS_OFF - vector m_bits; - OPENZWAVE_EXPORT_WARNINGS_ON - uint32 m_numSetBits; - uint32 m_value; -}; -} // namespace OpenZWave + uint32 m_idx; + Bitfield const* m_bitfield; + }; -#endif + Iterator Begin() const; + Iterator End() const; + private: + vector m_bits; + uint32 m_numSetBits; + uint32 m_value; + }; + } // namespace OpenZWave +} // namespace OpenZWave +#endif diff --git a/cpp/src/CompatOptionManager.cpp b/cpp/src/CompatOptionManager.cpp index 099634bbe9..569663017d 100644 --- a/cpp/src/CompatOptionManager.cpp +++ b/cpp/src/CompatOptionManager.cpp @@ -29,415 +29,674 @@ #include "CompatOptionManager.h" #include "platform/Log.h" -namespace OpenZWave { - -CompatOptionFlagDefintions availableCompatFlags[] = -{ - { "GetSupported", COMPAT_FLAG_GETSUPPORTED, COMPAT_FLAG_TYPE_BOOL }, - { "OverridePrecision", COMPAT_FLAG_OVERRIDEPRECISION, COMPAT_FLAG_TYPE_BYTE }, - { "ForceVersion", COMPAT_FLAG_FORCEVERSION, COMPAT_FLAG_TYPE_BYTE }, - { "CreateVars", COMPAT_FLAG_CREATEVARS, COMPAT_FLAG_TYPE_BOOL }, - { "RefreshOnWakeup", COMPAT_FLAG_REFRESHONWAKEUP, COMPAT_FLAG_TYPE_BOOL }, - { "IgnoreMapping", COMPAT_FLAG_BASIC_IGNOREREMAPPING, COMPAT_FLAG_TYPE_BOOL }, - { "SetAsReport", COMPAT_FLAG_BASIC_SETASREPORT, COMPAT_FLAG_TYPE_BOOL }, - { "Mapping", COMPAT_FLAG_BASIC_MAPPING, COMPAT_FLAG_TYPE_BYTE }, - { "ColorIndexBug", COMPAT_FLAG_COLOR_IDXBUG, COMPAT_FLAG_TYPE_BOOL }, // Fibaro RGBW before version 25.25 always reported the coloridx as 3 in the Report Message. Work around it - { "ForceInstances", COMPAT_FLAG_MCA_FORCEINSTANCES, COMPAT_FLAG_TYPE_BOOL }, - { "MapRootToEndpoint", COMPAT_FLAG_MI_MAPROOTTOENDPOINT, COMPAT_FLAG_TYPE_BOOL }, // was mapping in old version. was 0 or false in old version. when mapping=endpoints, thats = true - { "ForceUniqueEndpoints", COMPAT_FLAG_MI_FORCEUNIQUEENDPOINTS, COMPAT_FLAG_TYPE_BOOL }, - { "IgnoreMCCapReports", COMPAT_FLAG_MI_IGNMCCAPREPORTS, COMPAT_FLAG_TYPE_BOOL }, // was ignoreUnsolicitedMultiChnCapReport - { "EndpointHint", COMPAT_FLAG_MI_ENDPOINTHINT, COMPAT_FLAG_TYPE_BYTE }, - { "Base", COMPAT_FLAG_TSSP_BASE, COMPAT_FLAG_TYPE_BYTE }, - { "AltTypeInterpretation", COMPAT_FLAG_TSSP_ALTTYPEINTERPRETATION, COMPAT_FLAG_TYPE_BOOL }, - { "ExposeRawUserCodes", COMPAT_FLAG_UC_EXPOSERAWVALUE, COMPAT_FLAG_TYPE_BOOL }, - { "ClassGetVersionSupported", COMPAT_FLAG_VERSION_GETCLASSVERSION, COMPAT_FLAG_TYPE_BOOL }, - { "DelayNoMoreInfo", COMPAT_FLAG_WAKEUP_DELAYNMI, COMPAT_FLAG_TYPE_INT }, -}; - -uint16_t availableCompatFlagsCount = sizeof(availableCompatFlags) / sizeof(availableCompatFlags[0]); - -CompatOptionFlagDefintions availableDiscoveryFlags [] = -{ - { "CCVersion", STATE_FLAG_CCVERSION, COMPAT_FLAG_TYPE_BYTE }, - { "StaticRequests", STATE_FLAG_STATIC_REQUESTS, COMPAT_FLAG_TYPE_BYTE }, - { "AfterMark", STATE_FLAG_AFTERMARK, COMPAT_FLAG_TYPE_BOOL }, - { "Encrypted", STATE_FLAG_ENCRYPTED, COMPAT_FLAG_TYPE_BOOL }, - { "InNif", STATE_FLAG_INNIF, COMPAT_FLAG_TYPE_BOOL }, - { "SceneCount", STATE_FLAG_CS_SCENECOUNT, COMPAT_FLAG_TYPE_BYTE }, - { "ClearTimeout", STATE_FLAG_CS_CLEARTIMEOUT, COMPAT_FLAG_TYPE_INT }, - { "ChangeCounter", STATE_FLAG_CCS_CHANGECOUNTER, COMPAT_FLAG_TYPE_BYTE }, - { "Channels", STATE_FLAG_COLOR_CHANNELS, COMPAT_FLAG_TYPE_SHORT}, - { "TimeOut", STATE_FLAG_DOORLOCK_TIMEOUT, COMPAT_FLAG_TYPE_BYTE }, - { "InsideMode", STATE_FLAG_DOORLOCK_INSIDEMODE, COMPAT_FLAG_TYPE_BYTE }, - { "OutsideMode", STATE_FLAG_DOORLOCK_OUTSIDEMODE, COMPAT_FLAG_TYPE_BYTE }, - { "TimeOutMins", STATE_FLAG_DOORLOCK_TIMEOUTMINS, COMPAT_FLAG_TYPE_BYTE }, - { "TImeOutSecs", STATE_FLAG_DOORLOCK_TIMEOUTSECS, COMPAT_FLAG_TYPE_BYTE }, - { "MaxRecords", STATE_FLAG_DOORLOCKLOG_MAXRECORDS, COMPAT_FLAG_TYPE_BYTE }, - { "Count", STATE_FLAG_USERCODE_COUNT, COMPAT_FLAG_TYPE_BYTE } -}; - -uint16_t availableDiscoveryFlagsCount = sizeof(availableDiscoveryFlags) / sizeof(availableDiscoveryFlags[0]); - -CompatOptionManager::CompatOptionManager -( - CompatOptionType type, - CommandClass *owner -): -m_owner(owner), -m_comtype(type) +namespace OpenZWave { - switch (m_comtype) { - case CompatOptionType_Compatibility: - m_availableFlags = availableCompatFlags; - m_availableFlagsCount = availableCompatFlagsCount; - break; - case CompatOptionType_Discovery: - m_availableFlags = availableDiscoveryFlags; - m_availableFlagsCount = availableDiscoveryFlagsCount; - break; - } -} - -CompatOptionManager::~CompatOptionManager -( -) -{ -} + namespace Internal + { + + CompatOptionFlagDefintions availableCompatFlags[] = + { + { "GetSupported", COMPAT_FLAG_GETSUPPORTED, COMPAT_FLAG_TYPE_BOOL }, + { "OverridePrecision", COMPAT_FLAG_OVERRIDEPRECISION, COMPAT_FLAG_TYPE_BYTE }, + { "ForceVersion", COMPAT_FLAG_FORCEVERSION, COMPAT_FLAG_TYPE_BYTE }, + { "CreateVars", COMPAT_FLAG_CREATEVARS, COMPAT_FLAG_TYPE_BOOL }, + { "RefreshOnWakeup", COMPAT_FLAG_REFRESHONWAKEUP, COMPAT_FLAG_TYPE_BOOL }, + { "IgnoreMapping", COMPAT_FLAG_BASIC_IGNOREREMAPPING, COMPAT_FLAG_TYPE_BOOL }, + { "SetAsReport", COMPAT_FLAG_BASIC_SETASREPORT, COMPAT_FLAG_TYPE_BOOL }, + { "Mapping", COMPAT_FLAG_BASIC_MAPPING, COMPAT_FLAG_TYPE_BYTE }, + { "ColorIndexBug", COMPAT_FLAG_COLOR_IDXBUG, COMPAT_FLAG_TYPE_BOOL }, // Fibaro RGBW before version 25.25 always reported the coloridx as 3 in the Report Message. Work around it + { "ForceInstances", COMPAT_FLAG_MCA_FORCEINSTANCES, COMPAT_FLAG_TYPE_BOOL }, + { "MapRootToEndpoint", COMPAT_FLAG_MI_MAPROOTTOENDPOINT, COMPAT_FLAG_TYPE_BOOL }, // was mapping in old version. was 0 or false in old version. when mapping=endpoints, thats = true + { "ForceUniqueEndpoints", COMPAT_FLAG_MI_FORCEUNIQUEENDPOINTS, COMPAT_FLAG_TYPE_BOOL }, + { "IgnoreMCCapReports", COMPAT_FLAG_MI_IGNMCCAPREPORTS, COMPAT_FLAG_TYPE_BOOL }, // was ignoreUnsolicitedMultiChnCapReport + { "EndpointHint", COMPAT_FLAG_MI_ENDPOINTHINT, COMPAT_FLAG_TYPE_BYTE }, + { "Base", COMPAT_FLAG_TSSP_BASE, COMPAT_FLAG_TYPE_BYTE }, + { "AltTypeInterpretation", COMPAT_FLAG_TSSP_ALTTYPEINTERPRETATION, COMPAT_FLAG_TYPE_BOOL }, + { "ExposeRawUserCodes", COMPAT_FLAG_UC_EXPOSERAWVALUE, COMPAT_FLAG_TYPE_BOOL }, + { "ClassGetVersionSupported", COMPAT_FLAG_VERSION_GETCLASSVERSION, COMPAT_FLAG_TYPE_BOOL }, + { "DelayNoMoreInfo", COMPAT_FLAG_WAKEUP_DELAYNMI, COMPAT_FLAG_TYPE_INT }, + { "RemoveCC", COMPAT_FLAG_MI_REMOVECC, COMPAT_FLAG_TYPE_BOOL_ARRAY }, + { "VerifyChanged", COMPAT_FLAG_VERIFYCHANGED, COMPAT_FLAG_TYPE_BOOL_ARRAY }, + { "EnableNotificationClear", COMPAT_FLAG_NOT_ENABLECLEAR, COMPAT_FLAG_TYPE_BOOL }, + { "EnableV1AlarmTypes", COMPAT_FLAG_NOT_V1ALARMTYPES_ENABLED, COMPAT_FLAG_TYPE_BOOL }, + }; + uint16_t availableCompatFlagsCount = sizeof(availableCompatFlags) / sizeof(availableCompatFlags[0]); -void CompatOptionManager::EnableFlag -( - CompatOptionFlags flag, - uint32_t defaultval -) -{ - for (uint32_t i = 0; i < m_availableFlagsCount; i++) { - if (m_availableFlags[i].flag == flag) { - m_enabledCompatFlags[m_availableFlags[i].name] = flag; - m_CompatVals[flag].type = m_availableFlags[i].type; - m_CompatVals[flag].changed = false; - switch (m_availableFlags[i].type) + CompatOptionFlagDefintions availableDiscoveryFlags[] = + { + { "CCVersion", STATE_FLAG_CCVERSION, COMPAT_FLAG_TYPE_BYTE }, + { "StaticRequests", STATE_FLAG_STATIC_REQUESTS, COMPAT_FLAG_TYPE_BYTE }, + { "AfterMark", STATE_FLAG_AFTERMARK, COMPAT_FLAG_TYPE_BOOL }, + { "Encrypted", STATE_FLAG_ENCRYPTED, COMPAT_FLAG_TYPE_BOOL }, + { "InNif", STATE_FLAG_INNIF, COMPAT_FLAG_TYPE_BOOL }, + { "SceneCount", STATE_FLAG_CS_SCENECOUNT, COMPAT_FLAG_TYPE_BYTE }, + { "ClearTimeout", STATE_FLAG_CS_CLEARTIMEOUT, COMPAT_FLAG_TYPE_INT }, + { "ChangeCounter", STATE_FLAG_CCS_CHANGECOUNTER, COMPAT_FLAG_TYPE_BYTE }, + { "Channels", STATE_FLAG_COLOR_CHANNELS, COMPAT_FLAG_TYPE_SHORT }, + { "TimeOut", STATE_FLAG_DOORLOCK_TIMEOUT, COMPAT_FLAG_TYPE_BYTE }, + { "InsideMode", STATE_FLAG_DOORLOCK_INSIDEMODE, COMPAT_FLAG_TYPE_BYTE }, + { "OutsideMode", STATE_FLAG_DOORLOCK_OUTSIDEMODE, COMPAT_FLAG_TYPE_BYTE }, + { "TimeOutMins", STATE_FLAG_DOORLOCK_TIMEOUTMINS, COMPAT_FLAG_TYPE_BYTE }, + { "TImeOutSecs", STATE_FLAG_DOORLOCK_TIMEOUTSECS, COMPAT_FLAG_TYPE_BYTE }, + { "MaxRecords", STATE_FLAG_DOORLOCKLOG_MAXRECORDS, COMPAT_FLAG_TYPE_BYTE }, + { "Count", STATE_FLAG_USERCODE_COUNT, COMPAT_FLAG_TYPE_BYTE } }; + + uint16_t availableDiscoveryFlagsCount = sizeof(availableDiscoveryFlags) / sizeof(availableDiscoveryFlags[0]); + + CompatOptionManager::CompatOptionManager(CompatOptionType type, Internal::CC::CommandClass *owner) : + m_owner(owner), m_comtype(type) + { + switch (m_comtype) { - case COMPAT_FLAG_TYPE_BOOL: - if (defaultval > 2) { - Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "EnableFlag: Default Value for %s is not a Bool", m_availableFlags[i].name.c_str()); - defaultval = 0; - } - m_CompatVals[flag].valBool = defaultval == 0 ? false : true; - break; - case COMPAT_FLAG_TYPE_BYTE: - if (defaultval > UINT8_MAX) { - Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "EnableFlag: Default Value for %s is larger than a byte", m_availableFlags[i].name.c_str()); - defaultval = 0; - } - m_CompatVals[flag].valByte = defaultval; + case CompatOptionType_Compatibility: + m_availableFlags = availableCompatFlags; + m_availableFlagsCount = availableCompatFlagsCount; break; - case COMPAT_FLAG_TYPE_SHORT: - if (defaultval > UINT16_MAX) { - Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "EnableFlag: Default Value for %s is larger than a short", m_availableFlags[i].name.c_str()); - defaultval = 0; - } - m_CompatVals[flag].valShort = defaultval; + case CompatOptionType_Discovery: + m_availableFlags = availableDiscoveryFlags; + m_availableFlagsCount = availableDiscoveryFlagsCount; break; - case COMPAT_FLAG_TYPE_INT: - if (defaultval > UINT32_MAX) { - Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "EnableFlag: Default Value for %s is larger than a int", m_availableFlags[i].name.c_str()); - defaultval = 0; + } + } + + CompatOptionManager::~CompatOptionManager() + { + } + + void CompatOptionManager::EnableFlag(CompatOptionFlags flag, uint32_t defaultval) + { + for (uint32_t i = 0; i < m_availableFlagsCount; i++) + { + if (m_availableFlags[i].flag == flag) + { + m_enabledCompatFlags[m_availableFlags[i].name] = flag; + m_CompatVals[flag].type = m_availableFlags[i].type; + m_CompatVals[flag].changed = false; + switch (m_availableFlags[i].type) + { + case COMPAT_FLAG_TYPE_BOOL: + case COMPAT_FLAG_TYPE_BOOL_ARRAY: + if (defaultval > 2) + { + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "EnableFlag: Default Value for %s is not a Bool", m_availableFlags[i].name.c_str()); + defaultval = 0; + } + m_CompatVals[flag].valBool = (defaultval == 0 ? false : true); + break; + case COMPAT_FLAG_TYPE_BYTE: + case COMPAT_FLAG_TYPE_BYTE_ARRAY: + if (defaultval > UINT8_MAX) + { + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "EnableFlag: Default Value for %s is larger than a byte", m_availableFlags[i].name.c_str()); + defaultval = 0; + } + m_CompatVals[flag].valByte = defaultval; + break; + case COMPAT_FLAG_TYPE_SHORT: + case COMPAT_FLAG_TYPE_SHORT_ARRAY: + if (defaultval > UINT16_MAX) + { + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "EnableFlag: Default Value for %s is larger than a short", m_availableFlags[i].name.c_str()); + defaultval = 0; + } + m_CompatVals[flag].valShort = defaultval; + break; + case COMPAT_FLAG_TYPE_INT: + case COMPAT_FLAG_TYPE_INT_ARRAY: + if (defaultval > UINT32_MAX) + { + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "EnableFlag: Default Value for %s is larger than a int", m_availableFlags[i].name.c_str()); + defaultval = 0; + } + m_CompatVals[flag].valInt = defaultval; + break; } - m_CompatVals[flag].valInt = defaultval; - break; + } } } - } -} -void CompatOptionManager::ReadXML -( - TiXmlElement const* _ccElement -) -{ - TiXmlElement const *compatElement = _ccElement->FirstChildElement(GetXMLTagName().c_str()); + void CompatOptionManager::ReadXML(TiXmlElement const* _ccElement) + { + TiXmlElement const *compatElement = _ccElement->FirstChildElement(GetXMLTagName().c_str()); + + if (compatElement) + { + map::iterator it; + string value; + for (it = m_enabledCompatFlags.begin(); it != m_enabledCompatFlags.end(); it++) + { + TiXmlElement const *valElement = compatElement->FirstChildElement(it->first.c_str()); + if (valElement) + { + value = valElement->GetText(); + char* pStopChar; + uint32_t val = strtol(value.c_str(), &pStopChar, 10); + switch (m_CompatVals[it->second].type) + { + case COMPAT_FLAG_TYPE_BOOL: + if (m_CompatVals[it->second].valBool != !strcmp(value.c_str(), "true")) + { + m_CompatVals[it->second].valBool = !strcmp(value.c_str(), "true"); + m_CompatVals[it->second].changed = true; + } + break; + case COMPAT_FLAG_TYPE_BOOL_ARRAY: + { + if (m_CompatVals[it->second].valBool != !strcmp(value.c_str(), "true")) + { + string indexVal = valElement->Attribute("index"); + uint32 index = strtol(indexVal.c_str(), &pStopChar, 10); + m_CompatVals[it->second].valBoolArray.insert(std::pair(index, !strcmp(value.c_str(), "true"))); + m_CompatVals[it->second].changed = true; + } + break; + } + case COMPAT_FLAG_TYPE_BYTE: + if (val > UINT8_MAX) + { + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "ReadXML: (%s) - Value for %s is larger than a byte", m_owner->GetCommandClassName().c_str(), it->first.c_str()); + val = 0; + } + if (m_CompatVals[it->second].valByte != val) + { + m_CompatVals[it->second].valByte = val; + m_CompatVals[it->second].changed = true; + } + break; + case COMPAT_FLAG_TYPE_BYTE_ARRAY: + if (val > UINT8_MAX) + { + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "ReadXML: (%s) - Value for %s is larger than a byte", m_owner->GetCommandClassName().c_str(), it->first.c_str()); + val = 0; + } + if (m_CompatVals[it->second].valByte != val) + { + string indexVal = valElement->Attribute("index"); + uint32 index = strtol(indexVal.c_str(), &pStopChar, 10); + m_CompatVals[it->second].valByteArray.insert(std::pair(index, val)); + m_CompatVals[it->second].changed = true; + } + break; + + case COMPAT_FLAG_TYPE_SHORT: + if (val > UINT16_MAX) + { + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "ReadXML: (%s) - Value for %s is larger than a short", m_owner->GetCommandClassName().c_str(), it->first.c_str()); + val = 0; + } + if (m_CompatVals[it->second].valShort != val) + { + m_CompatVals[it->second].valShort = val; + m_CompatVals[it->second].changed = true; + } + break; + case COMPAT_FLAG_TYPE_SHORT_ARRAY: + if (val > UINT16_MAX) + { + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "ReadXML: (%s) - Value for %s is larger than a short", m_owner->GetCommandClassName().c_str(), it->first.c_str()); + val = 0; + } + if (m_CompatVals[it->second].valShort != val) + { + string indexVal = valElement->Attribute("index"); + uint32 index = strtol(indexVal.c_str(), &pStopChar, 10); + m_CompatVals[it->second].valShortArray.insert(std::pair(index, val)); + m_CompatVals[it->second].changed = true; + } + break; + case COMPAT_FLAG_TYPE_INT: + if (val > UINT32_MAX) + { + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "ReadXML: (%s) - Value for %s is larger than a int", m_owner->GetCommandClassName().c_str(), it->first.c_str()); + val = 0; + } + if (m_CompatVals[it->second].valInt != val) + { + m_CompatVals[it->second].valInt = val; + m_CompatVals[it->second].changed = true; + } + break; + case COMPAT_FLAG_TYPE_INT_ARRAY: + if (val > UINT32_MAX) + { + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "ReadXML: (%s) - Value for %s is larger than a int", m_owner->GetCommandClassName().c_str(), it->first.c_str()); + val = 0; + } + if (m_CompatVals[it->second].valInt != val) + { + string indexVal = valElement->Attribute("index"); + uint32 index = strtol(indexVal.c_str(), &pStopChar, 10); + m_CompatVals[it->second].valIntArray.insert(std::pair(index, val)); + m_CompatVals[it->second].changed = true; + } + break; - if (compatElement) { - map::iterator it; - string value; - for ( it = m_enabledCompatFlags.begin(); it != m_enabledCompatFlags.end(); it++) + } + } + } + } + { + map::iterator it; + Log::Write(LogLevel_Info, m_owner->GetNodeId(), "(%d - %s) - %s Flags:", m_owner->GetCommandClassId(), m_owner->GetCommandClassName().c_str(), GetXMLTagName().c_str()); + for (it = m_enabledCompatFlags.begin(); it != m_enabledCompatFlags.end(); it++) + { + if (m_CompatVals[it->second].changed) + { + switch (m_CompatVals[it->second].type) + { + case COMPAT_FLAG_TYPE_BOOL: + Log::Write(LogLevel_Info, m_owner->GetNodeId(), "\t %s: %s", it->first.c_str(), m_CompatVals[it->second].valBool ? "true" : "false"); + break; + case COMPAT_FLAG_TYPE_BOOL_ARRAY: + Log::Write(LogLevel_Info, m_owner->GetNodeId(), "\t %s (Default): %s", it->first.c_str(), m_CompatVals[it->second].valBool ? "true" : "false"); + for (std::map::iterator it2 = m_CompatVals[it->second].valBoolArray.begin(); it2 != m_CompatVals[it->second].valBoolArray.end(); it2++) + Log::Write(LogLevel_Info, m_owner->GetNodeId(), "\t\t %s - %d: %s", it->first.c_str(), it2->first, it2->second ? "true" : "false"); + break; + case COMPAT_FLAG_TYPE_BYTE: + Log::Write(LogLevel_Info, m_owner->GetNodeId(), "\t %s: %d", it->first.c_str(), m_CompatVals[it->second].valByte); + break; + case COMPAT_FLAG_TYPE_BYTE_ARRAY: + Log::Write(LogLevel_Info, m_owner->GetNodeId(), "\t %s (Default): %d", it->first.c_str(), m_CompatVals[it->second].valByte); + for (std::map::iterator it2 = m_CompatVals[it->second].valByteArray.begin(); it2 != m_CompatVals[it->second].valByteArray.end(); it2++) + Log::Write(LogLevel_Info, m_owner->GetNodeId(), "\t\t %s - %d: %d", it->first.c_str(), it2->first, it2->second ); + break; + case COMPAT_FLAG_TYPE_SHORT: + Log::Write(LogLevel_Info, m_owner->GetNodeId(), "\t %s: %d", it->first.c_str(), m_CompatVals[it->second].valShort); + break; + case COMPAT_FLAG_TYPE_SHORT_ARRAY: + Log::Write(LogLevel_Info, m_owner->GetNodeId(), "\t %s (Default): %d", it->first.c_str(), m_CompatVals[it->second].valShort); + for (std::map::iterator it2 = m_CompatVals[it->second].valShortArray.begin(); it2 != m_CompatVals[it->second].valShortArray.end(); it2++) + Log::Write(LogLevel_Info, m_owner->GetNodeId(), "\t\t %s - %d: %d", it->first.c_str(), it2->first, it2->second ); + break; + case COMPAT_FLAG_TYPE_INT: + Log::Write(LogLevel_Info, m_owner->GetNodeId(), "\t %s: %d", it->first.c_str(), m_CompatVals[it->second].valInt); + break; + case COMPAT_FLAG_TYPE_INT_ARRAY: + Log::Write(LogLevel_Info, m_owner->GetNodeId(), "\t %s (Default): %d", it->first.c_str(), m_CompatVals[it->second].valShort); + for (std::map::iterator it2 = m_CompatVals[it->second].valIntArray.begin(); it2 != m_CompatVals[it->second].valIntArray.end(); it2++) + Log::Write(LogLevel_Info, m_owner->GetNodeId(), "\t\t %s - %d: %d", it->first.c_str(), it2->first, it2->second ); + break; + + } + } + } + } + + } + + void CompatOptionManager::WriteXML(TiXmlElement * _ccElement) { - TiXmlElement const *valElement = compatElement->FirstChildElement(it->first.c_str()); - if (valElement) { - value = valElement->GetText(); - char* pStopChar; - uint32_t val = strtol( value.c_str(), &pStopChar, 10 );; - std::cout << "Flags: " << it->first.c_str() << value.c_str() << std::endl;; - switch (m_CompatVals[it->second].type) { + TiXmlElement* compatElement = new TiXmlElement(GetXMLTagName().c_str()); + + map::iterator it; + string value; + for (it = m_enabledCompatFlags.begin(); it != m_enabledCompatFlags.end(); it++) + { + if (m_CompatVals[it->second].changed == false) + { + /* skip writing out default values */ + continue; + } + char str[32]; + switch (m_CompatVals[it->second].type) + { case COMPAT_FLAG_TYPE_BOOL: - m_CompatVals[it->second].valBool = !strcmp(value.c_str(), "true"); - m_CompatVals[it->second].changed = true; + { + TiXmlElement* valElement = new TiXmlElement(it->first.c_str()); + TiXmlText *text = new TiXmlText(m_CompatVals[it->second].valBool == true ? "true" : "false"); + valElement->LinkEndChild(text); + compatElement->LinkEndChild(valElement); + break; + } + case COMPAT_FLAG_TYPE_BOOL_ARRAY: + { + for (std::map::iterator it2 = m_CompatVals[it->second].valBoolArray.begin(); it2 != m_CompatVals[it->second].valBoolArray.end(); it2++) { + if (it2->second != m_CompatVals[it->second].valBool) { + TiXmlElement* valElement = new TiXmlElement(it->first.c_str()); + valElement->SetAttribute("index", it2->first); + TiXmlText *text = new TiXmlText(it2->second == true ? "true" : "false"); + valElement->LinkEndChild(text); + compatElement->LinkEndChild(valElement); + } + } break; + } case COMPAT_FLAG_TYPE_BYTE: - if (val > UINT8_MAX) { - Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "ReadXML: (%s) - Value for %s is larger than a byte", m_owner->GetCommandClassName().c_str(), it->first.c_str()); - val = 0; + { + snprintf(str, sizeof(str), "%d", m_CompatVals[it->second].valByte); + TiXmlElement* valElement = new TiXmlElement(it->first.c_str()); + TiXmlText *text = new TiXmlText(str); + valElement->LinkEndChild(text); + compatElement->LinkEndChild(valElement); + break; + } + case COMPAT_FLAG_TYPE_BYTE_ARRAY: + { + for (std::map::iterator it2 = m_CompatVals[it->second].valByteArray.begin(); it2 != m_CompatVals[it->second].valByteArray.end(); it2++) { + if (it2->second != m_CompatVals[it->second].valByte) { + snprintf(str, sizeof(str), "%d", it2->second); + TiXmlElement* valElement = new TiXmlElement(it->first.c_str()); + valElement->SetAttribute("index", it2->first); + TiXmlText *text = new TiXmlText(str); + valElement->LinkEndChild(text); + compatElement->LinkEndChild(valElement); + } } - m_CompatVals[it->second].valByte = val; - m_CompatVals[it->second].changed = true; break; + } case COMPAT_FLAG_TYPE_SHORT: - if (val > UINT16_MAX) { - Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "ReadXML: (%s) - Value for %s is larger than a short", m_owner->GetCommandClassName().c_str(), it->first.c_str()); - val = 0; + { + snprintf(str, sizeof(str), "%d", m_CompatVals[it->second].valShort); + TiXmlElement* valElement = new TiXmlElement(it->first.c_str()); + TiXmlText *text = new TiXmlText(str); + valElement->LinkEndChild(text); + compatElement->LinkEndChild(valElement); + break; + } + case COMPAT_FLAG_TYPE_SHORT_ARRAY: + { + for (std::map::iterator it2 = m_CompatVals[it->second].valShortArray.begin(); it2 != m_CompatVals[it->second].valShortArray.end(); it2++) { + if (it2->second != m_CompatVals[it->second].valShort) { + snprintf(str, sizeof(str), "%d", it2->second); + TiXmlElement* valElement = new TiXmlElement(it->first.c_str()); + valElement->SetAttribute("index", it2->first); + TiXmlText *text = new TiXmlText(str); + valElement->LinkEndChild(text); + compatElement->LinkEndChild(valElement); + } } - m_CompatVals[it->second].valShort = val; - m_CompatVals[it->second].changed = true; break; + } case COMPAT_FLAG_TYPE_INT: - if (val > UINT32_MAX) { - Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "ReadXML: (%s) - Value for %s is larger than a int", m_owner->GetCommandClassName().c_str(), it->first.c_str()); - val = 0; + { + snprintf(str, sizeof(str), "%d", m_CompatVals[it->second].valInt); + TiXmlElement* valElement = new TiXmlElement(it->first.c_str()); + TiXmlText *text = new TiXmlText(str); + valElement->LinkEndChild(text); + compatElement->LinkEndChild(valElement); + break; + } + case COMPAT_FLAG_TYPE_INT_ARRAY: + { + for (std::map::iterator it2 = m_CompatVals[it->second].valIntArray.begin(); it2 != m_CompatVals[it->second].valIntArray.end(); it2++) { + if (it2->second != m_CompatVals[it->second].valInt) { + snprintf(str, sizeof(str), "%d", it2->second); + TiXmlElement* valElement = new TiXmlElement(it->first.c_str()); + valElement->SetAttribute("index", it2->first); + TiXmlText *text = new TiXmlText(str); + valElement->LinkEndChild(text); + compatElement->LinkEndChild(valElement); + } } - m_CompatVals[it->second].valInt = val; - m_CompatVals[it->second].changed = true; break; + } } } + _ccElement->LinkEndChild(compatElement); } - } - { - map::iterator it; - Log::Write(LogLevel_Info, m_owner->GetNodeId(), "(%d - %s) - %s Flags:", m_owner->GetCommandClassId(), m_owner->GetCommandClassName().c_str(), GetXMLTagName().c_str()); - for ( it = m_enabledCompatFlags.begin(); it != m_enabledCompatFlags.end(); it++) + + bool CompatOptionManager::GetFlagBool(CompatOptionFlags const flag, uint32_t index) const { - if (m_CompatVals[it->second].changed) { - switch (m_CompatVals[it->second].type) { - case COMPAT_FLAG_TYPE_BOOL: - Log::Write(LogLevel_Info, m_owner->GetNodeId(), "\t %s: %s", it->first.c_str(), m_CompatVals[it->second].valBool ? "true": "false"); - break; - case COMPAT_FLAG_TYPE_BYTE: - Log::Write(LogLevel_Info, m_owner->GetNodeId(), "\t %s: %d", it->first.c_str(), m_CompatVals[it->second].valByte); - break; - case COMPAT_FLAG_TYPE_SHORT: - Log::Write(LogLevel_Info, m_owner->GetNodeId(), "\t %s: %d", it->first.c_str(), m_CompatVals[it->second].valShort); - break; - case COMPAT_FLAG_TYPE_INT: - Log::Write(LogLevel_Info, m_owner->GetNodeId(), "\t %s: %d", it->first.c_str(), m_CompatVals[it->second].valInt); - break; + if (m_CompatVals.count(flag) == 0) + { + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "GetFlagBool: (%s) - Flag %s Not Enabled!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); + return false; + } + if (m_CompatVals.at(flag).type == COMPAT_FLAG_TYPE_BOOL) + { + return m_CompatVals.at(flag).valBool; + } + if (m_CompatVals.at(flag).type == COMPAT_FLAG_TYPE_BOOL_ARRAY) + { + if (index == (uint32_t)-1) { + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "GetFlagBool: (%s) - Flag %s had Invalid Index", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); + return m_CompatVals.at(flag).valBool; } + if (m_CompatVals.at(flag).valBoolArray.count(index)) + return m_CompatVals.at(flag).valBoolArray.at(index); + /* Return our Default */ + return m_CompatVals.at(flag).valBool; } + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "GetFlagBool: (%s) - Flag %s Not a Boolean Value!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); + return false; + } - } -} + uint8_t CompatOptionManager::GetFlagByte(CompatOptionFlags flag, uint32_t index) const + { + if (m_CompatVals.count(flag) == 0) + { + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "GetFlagByte: (%s) - Flag %s Not Enabled!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); + return 0; + } + if (m_CompatVals.at(flag).type == COMPAT_FLAG_TYPE_BYTE) + { + return m_CompatVals.at(flag).valByte; + } + if (m_CompatVals.at(flag).type == COMPAT_FLAG_TYPE_BYTE_ARRAY) + { + if (index == (uint32_t)-1) { + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "GetFlagByte: (%s) - Flag %s had Invalid Index", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); + return m_CompatVals.at(flag).valByte; + } + if (m_CompatVals.at(flag).valByteArray.count(index)) + return m_CompatVals.at(flag).valByteArray.at(index); + /* Return our Default */ + return m_CompatVals.at(flag).valByte; -void CompatOptionManager::WriteXML -( - TiXmlElement * _ccElement -) -{ - TiXmlElement* compatElement = new TiXmlElement( GetXMLTagName().c_str() ); + } + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "GetFlagByte: (%s) - Flag %s Not a Byte Value!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); + return 0; - map::iterator it; - string value; - for ( it = m_enabledCompatFlags.begin(); it != m_enabledCompatFlags.end(); it++) - { - TiXmlElement* valElement = new TiXmlElement( it->first.c_str() ); - char str[32]; - TiXmlText * text = NULL; -// std::cout << "Name " << it->first << " Type: " << m_CompatVals[it->second].type << std::endl; - switch (m_CompatVals[it->second].type) { - case COMPAT_FLAG_TYPE_BOOL: - text = new TiXmlText(m_CompatVals[it->second].valBool == true ? "true" : "false"); - break; - case COMPAT_FLAG_TYPE_BYTE: - snprintf(str, sizeof(str), "%d", m_CompatVals[it->second].valByte); - text = new TiXmlText(str); - break; - case COMPAT_FLAG_TYPE_SHORT: - snprintf(str, sizeof(str), "%d", m_CompatVals[it->second].valShort); - text = new TiXmlText(str); - break; - case COMPAT_FLAG_TYPE_INT: - snprintf(str, sizeof(str), "%d", m_CompatVals[it->second].valInt); - text = new TiXmlText(str); - break; } - valElement->LinkEndChild(text); - compatElement->LinkEndChild( valElement ); - } - _ccElement->LinkEndChild(compatElement); -} - -bool CompatOptionManager::GetFlagBool -( - CompatOptionFlags const flag -) const -{ - if (m_CompatVals.count(flag) == 0) - { - Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "GetFlagBool: (%s) - Flag %s Not Enabled!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); - return false; - } - if (m_CompatVals.at(flag).type != COMPAT_FLAG_TYPE_BOOL) - { - Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "GetFlagBool: (%s) - Flag %s Not a Boolean Value!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); - return false; - } - return m_CompatVals.at(flag).valBool; -} - -uint8_t CompatOptionManager::GetFlagByte -( - CompatOptionFlags flag -) const -{ - if (m_CompatVals.count(flag) == 0) { - Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "GetFlagByte: (%s) - Flag %s Not Enabled!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); - return 0; - } - if (m_CompatVals.at(flag).type != COMPAT_FLAG_TYPE_BYTE) - { - Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "GetFlagByte: (%s) - Flag %s Not a Byte Value!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); - return 0; - } - return m_CompatVals.at(flag).valByte; -} - -uint16_t CompatOptionManager::GetFlagShort -( - CompatOptionFlags flag -) const -{ - if (m_CompatVals.count(flag) == 0) { - Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "GetFlagShort: (%s) - Flag %s Not Enabled!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); - return 0; - } - if (m_CompatVals.at(flag).type != COMPAT_FLAG_TYPE_SHORT) - { - Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "GetFlagShort: (%s) - Flag %s Not a Short Value!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); - return 0; - } - return m_CompatVals.at(flag).valShort; -} - -uint32_t CompatOptionManager::GetFlagInt -( - CompatOptionFlags flag -) const -{ - if (m_CompatVals.count(flag) == 0) { - Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "GetFlagInt: (%s) - Flag %s Not Enabled!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); - return 0; - } - if (m_CompatVals.at(flag).type != COMPAT_FLAG_TYPE_INT) - { - Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "GetFlagInt: (%s) - Flag %s Not a Int Value!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); - return 0; - } - return m_CompatVals.at(flag).valInt; -} - -bool CompatOptionManager::SetFlagBool -( - CompatOptionFlags flag, - bool value -) -{ - if (m_CompatVals.count(flag) == 0) { - Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "SetFlagBool: (%s) - Flag %s Not Enabled!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); - return false; - } - if (m_CompatVals.at(flag).type != COMPAT_FLAG_TYPE_BOOL) - { - Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "SetFlagBool: (%s) - Flag %s Not a Bool Value!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); - return false; - } - m_CompatVals.at(flag).valBool = value; - m_CompatVals.at(flag).changed = true; - return true; -} - -bool CompatOptionManager::SetFlagByte -( - CompatOptionFlags flag, - uint8_t value -) -{ - if (m_CompatVals.count(flag) == 0) { - Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "SetFlagByte: (%s) - Flag %s Not Enabled!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); - return false; - } - if (m_CompatVals.at(flag).type != COMPAT_FLAG_TYPE_BYTE) - { - Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "SetFlagByte: (%s) - Flag %s Not a Byte Value!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); - return false; - } - m_CompatVals.at(flag).valByte = value; - m_CompatVals.at(flag).changed = true; - return true; -} - -bool CompatOptionManager::SetFlagShort -( - CompatOptionFlags flag, - uint16_t value -) -{ - if (m_CompatVals.count(flag) == 0) { - Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "SetFlagShort: (%s) - Flag %s Not Enabled!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); - return false; - } - if (m_CompatVals.at(flag).type != COMPAT_FLAG_TYPE_SHORT) - { - Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "SetFlagShort: (%s) - Flag %s Not a Short Value!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); - return false; - } - m_CompatVals.at(flag).valShort = value; - m_CompatVals.at(flag).changed = true; - return true; -} - -bool CompatOptionManager::SetFlagInt -( - CompatOptionFlags flag, - uint32_t value -) -{ - if (m_CompatVals.count(flag) == 0) { - Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "SetFlagInt: (%s) - Flag %s Not Enabled!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); - return false; - } - if (m_CompatVals.at(flag).type != COMPAT_FLAG_TYPE_INT) - { - Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "SetFlagInt: (%s) - Flag %s Not a Int Value!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); - return false; - } - m_CompatVals.at(flag).valInt = value; - m_CompatVals.at(flag).changed = true; - return true; -} - -string CompatOptionManager::GetFlagName -( - CompatOptionFlags flag -) const -{ - for (uint32_t i = 0; i < m_availableFlagsCount; i++) { - if (m_availableFlags[i].flag == flag) { - return m_availableFlags[i].name; + + uint16_t CompatOptionManager::GetFlagShort(CompatOptionFlags flag, uint32_t index) const + { + if (m_CompatVals.count(flag) == 0) + { + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "GetFlagShort: (%s) - Flag %s Not Enabled!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); + return 0; + } + if (m_CompatVals.at(flag).type == COMPAT_FLAG_TYPE_SHORT) + { + return m_CompatVals.at(flag).valShort; + } + if (m_CompatVals.at(flag).type == COMPAT_FLAG_TYPE_SHORT_ARRAY) + { + if (index == (uint32_t)-1) { + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "GetFlagShort: (%s) - Flag %s had Invalid Index", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); + return m_CompatVals.at(flag).valShort; + } + if (m_CompatVals.at(flag).valShortArray.count(index)) + return m_CompatVals.at(flag).valShortArray.at(index); + /* Return our Default */ + return m_CompatVals.at(flag).valShort; + } + + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "GetFlagShort: (%s) - Flag %s Not a Short Value!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); + return 0; + } - } - return "Unknown"; -} -string CompatOptionManager::GetXMLTagName -( -) -{ - switch (m_comtype) { - case CompatOptionType_Compatibility: - return "Compatibility"; - case CompatOptionType_Discovery: - return "State"; - } - assert(0); - return "Unknown"; -} -} /* namespace OpenZWave */ + + uint32_t CompatOptionManager::GetFlagInt(CompatOptionFlags flag, uint32_t index) const + { + if (m_CompatVals.count(flag) == 0) + { + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "GetFlagInt: (%s) - Flag %s Not Enabled!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); + return 0; + } + if (m_CompatVals.at(flag).type == COMPAT_FLAG_TYPE_INT) + { + return m_CompatVals.at(flag).valInt; + } + if (m_CompatVals.at(flag).type == COMPAT_FLAG_TYPE_INT_ARRAY) + { + if (index == (uint32_t)-1) { + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "GetFlagInt: (%s) - Flag %s had Invalid Index", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); + return m_CompatVals.at(flag).valInt; + } + if (m_CompatVals.at(flag).valIntArray.count(index)) + return m_CompatVals.at(flag).valIntArray.at(index); + /* Return our Default */ + return m_CompatVals.at(flag).valInt; + } + + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "GetFlagInt: (%s) - Flag %s Not a Int Value!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); + return 0; + + } + + bool CompatOptionManager::SetFlagBool(CompatOptionFlags flag, bool value, uint32_t index) + { + if (m_CompatVals.count(flag) == 0) + { + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "SetFlagBool: (%s) - Flag %s Not Enabled!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); + return false; + } + if (m_CompatVals.at(flag).type == COMPAT_FLAG_TYPE_BOOL) + { + m_CompatVals.at(flag).valBool = value; + m_CompatVals.at(flag).changed = true; + return true; + } + if (m_CompatVals.at(flag).type == COMPAT_FLAG_TYPE_BOOL_ARRAY) + { + if (index == (uint32_t)-1) { + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "SetFlagBool: (%s) - Flag %s had Invalid Index", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); + return false; + } + m_CompatVals.at(flag).changed = true; + if (m_CompatVals.at(flag).valBoolArray.count(index)) { + m_CompatVals.at(flag).valBoolArray.at(index) = value; + return true; + } else { + m_CompatVals.at(flag).valBoolArray.insert(std::pair(index, value)); + return true; + } + } + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "SetFlagBool: (%s) - Flag %s Not a Bool Value!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); + return false; + } + + bool CompatOptionManager::SetFlagByte(CompatOptionFlags flag, uint8_t value, uint32_t index) + { + if (m_CompatVals.count(flag) == 0) + { + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "SetFlagByte: (%s) - Flag %s Not Enabled!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); + return false; + } + if (m_CompatVals.at(flag).type == COMPAT_FLAG_TYPE_BYTE) + { + m_CompatVals.at(flag).valByte = value; + m_CompatVals.at(flag).changed = true; + return true; + } + if (m_CompatVals.at(flag).type == COMPAT_FLAG_TYPE_BYTE_ARRAY) + { + if (index == (uint32_t)-1) { + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "SetFlagByte: (%s) - Flag %s had Invalid Index", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); + return false; + } + m_CompatVals.at(flag).changed = true; + if (m_CompatVals.at(flag).valByteArray.count(index)) { + m_CompatVals.at(flag).valByteArray.at(index) = value; + return true; + } else { + m_CompatVals.at(flag).valByteArray.insert(std::pair(index, value)); + return true; + } + } + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "SetFlagByte: (%s) - Flag %s Not a Byte Value!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); + return false; + } + + bool CompatOptionManager::SetFlagShort(CompatOptionFlags flag, uint16_t value, uint32_t index) + { + if (m_CompatVals.count(flag) == 0) + { + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "SetFlagShort: (%s) - Flag %s Not Enabled!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); + return false; + } + if (m_CompatVals.at(flag).type == COMPAT_FLAG_TYPE_SHORT) + { + m_CompatVals.at(flag).valShort = value; + m_CompatVals.at(flag).changed = true; + return true; + } + if (m_CompatVals.at(flag).type == COMPAT_FLAG_TYPE_SHORT_ARRAY) + { + if (index == (uint32_t)-1) { + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "SetFlagShort: (%s) - Flag %s had Invalid Index", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); + return false; + } + m_CompatVals.at(flag).changed = true; + if (m_CompatVals.at(flag).valShortArray.count(index)) { + m_CompatVals.at(flag).valShortArray.at(index) = value; + return true; + } else { + m_CompatVals.at(flag).valShortArray.insert(std::pair(index, value)); + return true; + } + } + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "SetFlagShort: (%s) - Flag %s Not a Short Value!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); + return false; + } + + bool CompatOptionManager::SetFlagInt(CompatOptionFlags flag, uint32_t value, uint32_t index) + { + if (m_CompatVals.count(flag) == 0) + { + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "SetFlagInt: (%s) - Flag %s Not Enabled!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); + return false; + } + if (m_CompatVals.at(flag).type == COMPAT_FLAG_TYPE_INT) + { + m_CompatVals.at(flag).valInt = value; + m_CompatVals.at(flag).changed = true; + return true; + } + if (m_CompatVals.at(flag).type == COMPAT_FLAG_TYPE_INT_ARRAY) + { + if (index == (uint32_t)-1) { + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "SetFlagInt: (%s) - Flag %s had Invalid Index", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); + return false; + } + m_CompatVals.at(flag).changed = true; + if (m_CompatVals.at(flag).valIntArray.count(index)) { + m_CompatVals.at(flag).valIntArray.at(index) = value; + return true; + } else { + m_CompatVals.at(flag).valIntArray.insert(std::pair(index, value)); + return true; + } + } + Log::Write(LogLevel_Warning, m_owner->GetNodeId(), "SetFlagInt: (%s) - Flag %s Not a Int Value!", m_owner->GetCommandClassName().c_str(), GetFlagName(flag).c_str()); + return false; + } + + string CompatOptionManager::GetFlagName(CompatOptionFlags flag) const + { + for (uint32_t i = 0; i < m_availableFlagsCount; i++) + { + if (m_availableFlags[i].flag == flag) + { + return m_availableFlags[i].name; + } + } + return "Unknown"; + } + string CompatOptionManager::GetXMLTagName() + { + switch (m_comtype) + { + case CompatOptionType_Compatibility: + return "Compatibility"; + case CompatOptionType_Discovery: + return "State"; + } + assert(0); + return "Unknown"; + } + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/CompatOptionManager.h b/cpp/src/CompatOptionManager.h index c94a1e3eae..e54ef00e73 100644 --- a/cpp/src/CompatOptionManager.h +++ b/cpp/src/CompatOptionManager.h @@ -33,109 +33,140 @@ #include -namespace OpenZWave { - -enum CompatOptionFlags +namespace OpenZWave { - COMPAT_FLAG_GETSUPPORTED, - COMPAT_FLAG_OVERRIDEPRECISION, - COMPAT_FLAG_FORCEVERSION, - COMPAT_FLAG_CREATEVARS, - COMPAT_FLAG_REFRESHONWAKEUP, - COMPAT_FLAG_BASIC_IGNOREREMAPPING, - COMPAT_FLAG_BASIC_SETASREPORT, - COMPAT_FLAG_BASIC_MAPPING, - COMPAT_FLAG_COLOR_IDXBUG, - COMPAT_FLAG_MCA_FORCEINSTANCES, - COMPAT_FLAG_MI_MAPROOTTOENDPOINT, - COMPAT_FLAG_MI_FORCEUNIQUEENDPOINTS, - COMPAT_FLAG_MI_IGNMCCAPREPORTS, - COMPAT_FLAG_MI_ENDPOINTHINT, - COMPAT_FLAG_TSSP_BASE, - COMPAT_FLAG_TSSP_ALTTYPEINTERPRETATION, - COMPAT_FLAG_UC_EXPOSERAWVALUE, - COMPAT_FLAG_VERSION_GETCLASSVERSION, - COMPAT_FLAG_WAKEUP_DELAYNMI, - STATE_FLAG_CCVERSION, - STATE_FLAG_STATIC_REQUESTS, - STATE_FLAG_AFTERMARK, - STATE_FLAG_ENCRYPTED, - STATE_FLAG_INNIF, - STATE_FLAG_CS_SCENECOUNT, - STATE_FLAG_CS_CLEARTIMEOUT, - STATE_FLAG_CCS_CHANGECOUNTER, - STATE_FLAG_COLOR_CHANNELS, - STATE_FLAG_DOORLOCK_TIMEOUT, - STATE_FLAG_DOORLOCK_INSIDEMODE, - STATE_FLAG_DOORLOCK_OUTSIDEMODE, - STATE_FLAG_DOORLOCK_TIMEOUTMINS, - STATE_FLAG_DOORLOCK_TIMEOUTSECS, - STATE_FLAG_DOORLOCKLOG_MAXRECORDS, - STATE_FLAG_USERCODE_COUNT, -}; -enum CompatOptionFlagType -{ - COMPAT_FLAG_TYPE_BOOL, - COMPAT_FLAG_TYPE_BYTE, - COMPAT_FLAG_TYPE_SHORT, - COMPAT_FLAG_TYPE_INT -}; + namespace Internal + { + namespace CC + { + class CommandClass; + } -enum CompatOptionType -{ - CompatOptionType_Compatibility, - CompatOptionType_Discovery -}; + enum CompatOptionFlags + { + COMPAT_FLAG_GETSUPPORTED, + COMPAT_FLAG_OVERRIDEPRECISION, + COMPAT_FLAG_FORCEVERSION, + COMPAT_FLAG_CREATEVARS, + COMPAT_FLAG_REFRESHONWAKEUP, + COMPAT_FLAG_BASIC_IGNOREREMAPPING, + COMPAT_FLAG_BASIC_SETASREPORT, + COMPAT_FLAG_BASIC_MAPPING, + COMPAT_FLAG_COLOR_IDXBUG, + COMPAT_FLAG_MCA_FORCEINSTANCES, + COMPAT_FLAG_MI_MAPROOTTOENDPOINT, + COMPAT_FLAG_MI_FORCEUNIQUEENDPOINTS, + COMPAT_FLAG_MI_IGNMCCAPREPORTS, + COMPAT_FLAG_MI_ENDPOINTHINT, + COMPAT_FLAG_TSSP_BASE, + COMPAT_FLAG_TSSP_ALTTYPEINTERPRETATION, + COMPAT_FLAG_UC_EXPOSERAWVALUE, + COMPAT_FLAG_VERSION_GETCLASSVERSION, + COMPAT_FLAG_WAKEUP_DELAYNMI, + COMPAT_FLAG_MI_REMOVECC, + COMPAT_FLAG_VERIFYCHANGED, + COMPAT_FLAG_NOT_ENABLECLEAR, + COMPAT_FLAG_NOT_V1ALARMTYPES_ENABLED, + STATE_FLAG_CCVERSION, + STATE_FLAG_STATIC_REQUESTS, + STATE_FLAG_AFTERMARK, + STATE_FLAG_ENCRYPTED, + STATE_FLAG_INNIF, + STATE_FLAG_CS_SCENECOUNT, + STATE_FLAG_CS_CLEARTIMEOUT, + STATE_FLAG_CCS_CHANGECOUNTER, + STATE_FLAG_COLOR_CHANNELS, + STATE_FLAG_DOORLOCK_TIMEOUT, + STATE_FLAG_DOORLOCK_INSIDEMODE, + STATE_FLAG_DOORLOCK_OUTSIDEMODE, + STATE_FLAG_DOORLOCK_TIMEOUTMINS, + STATE_FLAG_DOORLOCK_TIMEOUTSECS, + STATE_FLAG_DOORLOCKLOG_MAXRECORDS, + STATE_FLAG_USERCODE_COUNT, + }; + + enum CompatOptionFlagType + { + COMPAT_FLAG_TYPE_BOOL, + COMPAT_FLAG_TYPE_BYTE, + COMPAT_FLAG_TYPE_SHORT, + COMPAT_FLAG_TYPE_INT, + COMPAT_FLAG_TYPE_BOOL_ARRAY, + COMPAT_FLAG_TYPE_BYTE_ARRAY, + COMPAT_FLAG_TYPE_SHORT_ARRAY, + COMPAT_FLAG_TYPE_INT_ARRAY + }; -struct CompatOptionFlagStorage { - CompatOptionFlags flag; - CompatOptionFlagType type; - bool changed; - union { - bool valBool; - uint8_t valByte; - uint16_t valShort; - uint32_t valInt; - }; -}; + enum CompatOptionType + { + CompatOptionType_Compatibility, + CompatOptionType_Discovery + }; -struct CompatOptionFlagDefintions { - string name; - CompatOptionFlags flag; - CompatOptionFlagType type; -}; + struct CompatOptionFlagStorage + { + CompatOptionFlags flag; + CompatOptionFlagType type; + bool changed; + /* when a single Value (not a FLAG_TYPE_*_ARRAY) this union holds the actual value + * but when its a FLAG_*_ARRAY, this union holds the default value + */ + union + { + bool valBool; + uint8_t valByte; + uint16_t valShort; + uint32_t valInt; + }; + /* Only when FLAG_TYPE_*_ARRAY is this union used, and holds + * individual values for each key. Default Value is taken from + * the above Union + */ + /* oh - And we can't use a Union here with a non-POD type */ + std::map valBoolArray; + std::map valByteArray; + std::map valShortArray; + std::map valIntArray; + }; -class CommandClass; -class CompatOptionManager { -public: - CompatOptionManager(CompatOptionType type, CommandClass *cc); - virtual ~CompatOptionManager(); + struct CompatOptionFlagDefintions + { + string name; + CompatOptionFlags flag; + CompatOptionFlagType type; + }; - void SetNodeAndCC(uint8_t node, uint8_t cc); - void EnableFlag(CompatOptionFlags flag, uint32_t defaultval); + class CompatOptionManager + { + public: + CompatOptionManager(CompatOptionType type, Internal::CC::CommandClass *cc); + virtual ~CompatOptionManager(); - void ReadXML( TiXmlElement const* _ccElement ); - void WriteXML( TiXmlElement* _ccElement ); - bool GetFlagBool(CompatOptionFlags flag) const; - uint8_t GetFlagByte(CompatOptionFlags flag) const; - uint16_t GetFlagShort(CompatOptionFlags flag) const; - uint32_t GetFlagInt(CompatOptionFlags flag) const; - bool SetFlagBool(CompatOptionFlags flag, bool value); - bool SetFlagByte(CompatOptionFlags flag, uint8_t value); - bool SetFlagShort(CompatOptionFlags flag, uint16_t value); - bool SetFlagInt(CompatOptionFlags flag, uint32_t value); -private: - string GetFlagName(CompatOptionFlags flag) const; - string GetXMLTagName(); - map m_CompatVals; - map m_enabledCompatFlags; - CommandClass *m_owner; - CompatOptionType m_comtype; - CompatOptionFlagDefintions *m_availableFlags; - uint32_t m_availableFlagsCount; -}; + void SetNodeAndCC(uint8_t node, uint8_t cc); + void EnableFlag(CompatOptionFlags flag, uint32_t defaultval); + void ReadXML(TiXmlElement const* _ccElement); + void WriteXML(TiXmlElement* _ccElement); + bool GetFlagBool(CompatOptionFlags flag, uint32_t index = -1) const; + uint8_t GetFlagByte(CompatOptionFlags flag, uint32_t index = -1) const; + uint16_t GetFlagShort(CompatOptionFlags flag, uint32_t index = -1) const; + uint32_t GetFlagInt(CompatOptionFlags flag, uint32_t index = -1) const; + bool SetFlagBool(CompatOptionFlags flag, bool value, uint32_t index = -1); + bool SetFlagByte(CompatOptionFlags flag, uint8_t value, uint32_t index = -1); + bool SetFlagShort(CompatOptionFlags flag, uint16_t value, uint32_t index = -1); + bool SetFlagInt(CompatOptionFlags flag, uint32_t value, uint32_t index = -1); + private: + string GetFlagName(CompatOptionFlags flag) const; + string GetXMLTagName(); + map m_CompatVals; + map m_enabledCompatFlags; + Internal::CC::CommandClass *m_owner; + CompatOptionType m_comtype; + CompatOptionFlagDefintions *m_availableFlags; + uint32_t m_availableFlagsCount; + }; + } // namespace Internal } /* namespace OpenZWave */ #endif /* CPP_SRC_COMPATOPTIONMANAGER_H_ */ diff --git a/cpp/src/DNSThread.cpp b/cpp/src/DNSThread.cpp index 15d56796a4..b7ba72df84 100644 --- a/cpp/src/DNSThread.cpp +++ b/cpp/src/DNSThread.cpp @@ -29,116 +29,102 @@ #include "Utils.h" #include "Driver.h" -using namespace OpenZWave; - - -DNSThread::DNSThread -( -Driver *driver -): -m_driver (driver), -m_dnsMutex ( new Mutex() ), -m_dnsRequestEvent ( new Event() ) -{ -} - -DNSThread::~DNSThread -( -) -{ - -} - -void DNSThread::DNSThreadEntryPoint -( - Event* _exitEvent, - void* _context -) -{ - DNSThread* dns = (DNSThread*)_context; - if( dns ) - { - dns->DNSThreadProc( _exitEvent ); - } -} - -void DNSThread::DNSThreadProc -( -Event* _exitEvent -) +namespace OpenZWave { - Log::Write(LogLevel_Info, "Starting DNSThread"); - while( true ) + namespace Internal { - // DNSThread has been initialized - const uint32 count = 2; - - Wait* waitObjects[count]; - int32 timeout = Wait::Timeout_Infinite; -// timeout = 5000; - - - waitObjects[0] = _exitEvent; // Thread must exit. - waitObjects[1] = m_dnsRequestEvent; // DNS Request - // Wait for something to do + DNSThread::DNSThread(Driver *driver) : + m_driver(driver), m_dnsMutex(new Internal::Platform::Mutex()), m_dnsRequestEvent(new Internal::Platform::Event()) + { + } - int32 res = Wait::Multiple( waitObjects, count, timeout ); + DNSThread::~DNSThread() + { + m_dnsMutex->Release(); + m_dnsRequestEvent->Release(); + } - switch (res) { - case -1: /* timeout */ - Log::Write(LogLevel_Warning, "DNSThread Timeout..."); - break; - case 0: /* exitEvent */ - Log::Write(LogLevel_Info, "Stopping DNSThread"); - return; - case 1: /* dnsEvent */ - processResult(); - break; + void DNSThread::DNSThreadEntryPoint(Internal::Platform::Event* _exitEvent, void* _context) + { + DNSThread* dns = (DNSThread*) _context; + if (dns) + { + dns->DNSThreadProc(_exitEvent); + } } - } -} -bool DNSThread::sendRequest -( -DNSLookup *lookup -) -{ - Log::Write(LogLevel_Info, lookup->NodeID, "Queuing Lookup on %s for Node %d", lookup->lookup.c_str(), lookup->NodeID); - LockGuard LG(m_dnsMutex); - m_dnslist.push_back(lookup); - m_dnsRequestEvent->Set(); - return true; -} + void DNSThread::DNSThreadProc(Internal::Platform::Event* _exitEvent) + { + Log::Write(LogLevel_Info, "Starting DNSThread"); + while (true) + { + // DNSThread has been initialized + const uint32 count = 2; -void DNSThread::processResult -( -) -{ - string result; - DNSLookup *lookup; - { - LockGuard LG(m_dnsMutex); - lookup = m_dnslist.front(); - m_dnslist.pop_front(); - if (m_dnslist.empty()) - m_dnsRequestEvent->Reset(); - } - Log::Write(LogLevel_Info, "LookupTxT Checking %s", lookup->lookup.c_str()); - if (!m_dnsresolver.LookupTxT(lookup->lookup, lookup->result)) { - Log::Write(LogLevel_Warning, "Lookup on %s Failed", lookup->lookup.c_str()); - } else { - Log::Write(LogLevel_Info, "Lookup for %s returned %s", lookup->lookup.c_str(), lookup->result.c_str()); - } - lookup->status = m_dnsresolver.status; + Internal::Platform::Wait* waitObjects[count]; - /* send the response back to the Driver for processing */ - Driver::EventMsg *event = new Driver::EventMsg(); - event->type = Driver::EventMsg::Event_DNS; - event->event.lookup = lookup; - this->m_driver->SubmitEventMsg(event); + int32 timeout = Internal::Platform::Wait::Timeout_Infinite; +// timeout = 5000; + waitObjects[0] = _exitEvent; // Thread must exit. + waitObjects[1] = m_dnsRequestEvent; // DNS Request + // Wait for something to do + + int32 res = Internal::Platform::Wait::Multiple(waitObjects, count, timeout); + + switch (res) + { + case -1: /* timeout */ + Log::Write(LogLevel_Warning, "DNSThread Timeout..."); + break; + case 0: /* exitEvent */ + Log::Write(LogLevel_Info, "Stopping DNSThread"); + return; + case 1: /* dnsEvent */ + processResult(); + break; + } + } + } -} + bool DNSThread::sendRequest(DNSLookup *lookup) + { + Log::Write(LogLevel_Info, lookup->NodeID, "Queuing Lookup on %s for Node %d", lookup->lookup.c_str(), lookup->NodeID); + LockGuard LG(m_dnsMutex); + m_dnslist.push_back(lookup); + m_dnsRequestEvent->Set(); + return true; + } + void DNSThread::processResult() + { + string result; + Internal::DNSLookup *lookup; + { + LockGuard LG(m_dnsMutex); + lookup = m_dnslist.front(); + m_dnslist.pop_front(); + if (m_dnslist.empty()) + m_dnsRequestEvent->Reset(); + } + Log::Write(LogLevel_Info, "LookupTxT Checking %s", lookup->lookup.c_str()); + if (!m_dnsresolver.LookupTxT(lookup->lookup, lookup->result)) + { + Log::Write(LogLevel_Warning, "Lookup on %s Failed", lookup->lookup.c_str()); + } + else + { + Log::Write(LogLevel_Info, "Lookup for %s returned %s", lookup->lookup.c_str(), lookup->result.c_str()); + } + lookup->status = m_dnsresolver.status; + + /* send the response back to the Driver for processing */ + Driver::EventMsg *event = new Driver::EventMsg(); + event->type = Driver::EventMsg::Event_DNS; + event->event.lookup = lookup; + this->m_driver->SubmitEventMsg(event); + } + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/DNSThread.h b/cpp/src/DNSThread.h index 1de524af62..3a0267a503 100644 --- a/cpp/src/DNSThread.h +++ b/cpp/src/DNSThread.h @@ -41,61 +41,65 @@ namespace OpenZWave { - class Event; - class Mutex; - class Controller; - class Thread; - - - enum LookupType { - DNS_Lookup_ConfigRevision = 1 - }; - - struct DNSLookup { - uint8 NodeID; - string lookup; - string result; - DNSError status; - LookupType type; - - }; - - - /** \brief the DNSThread provides Async DNS lookups for checking revision numbers of - * Config Files against the official database - */ - class OPENZWAVE_EXPORT DNSThread + namespace Internal { - friend class Driver; - private: - DNSThread(Driver *); - virtual ~DNSThread(); - - /** - * Entry point for DNSThread - */ - static void DNSThreadEntryPoint( Event* _exitEvent, void* _context ); - /** - * DNSThreadProc for DNSThread. This is where all the "action" takes place. - */ - void DNSThreadProc( Event* _exitEvent ); - - /* submit a Request to the DNS List */ - bool sendRequest(DNSLookup *); - - /* process the most recent request recieved */ - void processResult(); - - Driver* m_driver; - Mutex* m_dnsMutex; - list m_dnslist; - list m_dnslistinprogress; - Event* m_dnsRequestEvent; - DNS m_dnsresolver; - - - }; /* class DNSThread */ + namespace Platform + { + class Event; + class Mutex; + class Thread; + } + + enum LookupType + { + DNS_Lookup_ConfigRevision = 1 + }; + + struct DNSLookup + { + uint8 NodeID; + string lookup; + string result; + Internal::Platform::DNSError status; + LookupType type; + + }; + + /** \brief the DNSThread provides Async DNS lookups for checking revision numbers of + * Config Files against the official database + */ + class OPENZWAVE_EXPORT DNSThread + { + friend class OpenZWave::Driver; + private: + DNSThread(Driver *); + virtual ~DNSThread(); + + /** + * Entry point for DNSThread + */ + static void DNSThreadEntryPoint(Internal::Platform::Event* _exitEvent, void* _context); + /** + * DNSThreadProc for DNSThread. This is where all the "action" takes place. + */ + void DNSThreadProc(Internal::Platform::Event* _exitEvent); + + /* submit a Request to the DNS List */ + bool sendRequest(DNSLookup *); + + /* process the most recent request recieved */ + void processResult(); + + Driver* m_driver; + Internal::Platform::Mutex* m_dnsMutex; + list m_dnslist; + list m_dnslistinprogress; + Internal::Platform::Event* m_dnsRequestEvent; + Internal::Platform::DNS m_dnsresolver; + + }; + /* class DNSThread */ + } // namespace Internal } /* namespace OpenZWave */ - #endif diff --git a/cpp/src/Defs.h b/cpp/src/Defs.h index 386573b0fa..2789311d88 100644 --- a/cpp/src/Defs.h +++ b/cpp/src/Defs.h @@ -31,26 +31,25 @@ #include #include #include - +#include // Compilation export flags #if (defined _WINDOWS || defined WIN32 || defined _MSC_VER) && (!defined MINGW && !defined __MINGW32__ && !defined __MINGW64__) +// As discussd here https://github.com/OpenZWave/open-zwave/pull/1835 +// Disable certain MSVC warnings here (instead of applying the pragma throughout the code as was done in the past). +// Application and DLL should be built with same compiler and settings anyway. +// See https://stackoverflow.com/questions/5661738/how-can-i-use-standard-library-stl-classes-in-my-dll-interface-or-abi # if defined OPENZWAVE_MAKEDLL // Create the dynamic library. # define OPENZWAVE_EXPORT __declspec(dllexport) + __pragma(warning(disable: 4251)) __pragma(warning(disable: 4275)) # elif defined OPENZWAVE_USEDLL // Use the dynamic library # define OPENZWAVE_EXPORT __declspec(dllimport) + __pragma(warning(disable: 4251)) __pragma(warning(disable: 4275)) # else // Create/Use the static library # define OPENZWAVE_EXPORT # endif -// Disable export warnings -# define OPENZWAVE_EXPORT_WARNINGS_OFF __pragma( warning(push) )\ - __pragma( warning(disable: 4251) ) \ - __pragma( warning(disable: 4275) ) -# define OPENZWAVE_EXPORT_WARNINGS_ON __pragma( warning(pop) ) #else # define OPENZWAVE_EXPORT -# define OPENZWAVE_EXPORT_WARNINGS_OFF -# define OPENZWAVE_EXPORT_WARNINGS_ON #endif #ifdef __GNUC__ @@ -62,7 +61,6 @@ #define DEPRECATED #endif - #ifdef _MSC_VER #define OPENZWAVE_DEPRECATED_WARNINGS_OFF __pragma( warning(push) )\ __pragma( warning(disable: 4996) ) @@ -77,38 +75,37 @@ #define OPENZWAVE_DEPRECATED_WARNINGS_ON _Pragma ( "GCC diagnostic pop" ) #endif - - #ifdef NULL #undef NULL #endif #define NULL 0 // Basic types -typedef signed char int8; -typedef unsigned char uint8; +typedef signed char int8; +typedef unsigned char uint8; -typedef signed short int16; -typedef unsigned short uint16; +typedef signed short int16; +typedef unsigned short uint16; -typedef signed int int32; -typedef unsigned int uint32; +typedef signed int int32; +typedef unsigned int uint32; #ifdef _MSC_VER -typedef signed __int64 int64; -typedef unsigned __int64 uint64; +typedef signed __int64 int64; +typedef unsigned __int64 uint64; #endif #ifdef __GNUC__ -typedef signed long long int64; -typedef unsigned long long uint64; +typedef signed long long int64; +typedef unsigned long long uint64; #endif -typedef float float32; -typedef double float64; +typedef float float32; +typedef double float64; -typedef struct ozwversion { - uint32_t _v; /* major << 16 | minor */ +typedef struct ozwversion +{ + uint32_t _v; /* major << 16 | minor */ } ozwversion; /** @@ -116,7 +113,8 @@ typedef struct ozwversion { * \param v: the version number to obtain the major number from * \return the Major Version Number */ -static inline uint16_t version_major(struct ozwversion v) { +static inline uint16_t version_major(struct ozwversion v) +{ return (v._v & 0xFFFF0000) >> 16; } @@ -125,7 +123,8 @@ static inline uint16_t version_major(struct ozwversion v) { * \param v: the version number to obtain the minor number from * \return the Minor Version Number */ -static inline uint16_t version_minor(const struct ozwversion &v) { +static inline uint16_t version_minor(const struct ozwversion &v) +{ return v._v & 0xFFFF; } @@ -138,7 +137,7 @@ static inline uint16_t version_minor(const struct ozwversion &v) { static inline struct ozwversion version(uint16_t major, uint16_t minor) { struct ozwversion v; - v._v = (uint32_t)(major << 16) | (uint32_t)minor; + v._v = (uint32_t) (major << 16) | (uint32_t) minor; return v; } @@ -157,7 +156,7 @@ static inline struct ozwversion version(uint16_t major, uint16_t minor) */ static inline int version_cmp(struct ozwversion a, struct ozwversion b) { - return (a._v == b._v) ? 0 : (a._v > b._v) ? 1 : - 1; + return (a._v == b._v) ? 0 : (a._v > b._v) ? 1 : -1; } #include "OZWException.h" @@ -166,28 +165,27 @@ static inline int version_cmp(struct ozwversion a, struct ozwversion b) #else # define __MYFUNCTION__ __FILE__ #endif -// Exceptions : define OPENZWAVE_ENABLE_EXCEPTIONS in compiler flags to enable exceptions instead of exit function -#ifdef OPENZWAVE_ENABLE_EXCEPTIONS # define OZW_FATAL_ERROR(exitCode, msg) Log::Write( LogLevel_Error,"Exception: %s:%d - %d - %s", std::string(__MYFUNCTION__).substr(std::string(__MYFUNCTION__).find_last_of("/\\") + 1).c_str(), __LINE__, exitCode, msg); \ throw OZWException(__MYFUNCTION__, __LINE__, exitCode, msg) # define OZW_ERROR(exitCode, msg) Log::Write( LogLevel_Warning,"Exception: %s:%d - %d - %s", std::string(__MYFUNCTION__).substr(std::string(__MYFUNCTION__).find_last_of("/\\") + 1).c_str(), __LINE__, exitCode, msg); \ throw OZWException(__MYFUNCTION__, __LINE__, exitCode, msg) -#else - -# define OZW_FATAL_ERROR(exitCode, msg) Log::Write( LogLevel_Error,"Exception: %s:%d - %d - %s", std::string(__MYFUNCTION__).substr(std::string(__MYFUNCTION__).find_last_of("/\\") + 1).c_str(), __LINE__, exitCode, msg); \ - std::cerr << "Error: "<< std::string(__MYFUNCTION__).substr(std::string(__MYFUNCTION__).find_last_of("/\\") + 1) << ":" << __LINE__ << " - " << msg << std::endl; exit(exitCode) -# define OZW_ERROR(exitCode, msg) Log::Write( LogLevel_Warning,"Exception: %s:%d - %d - %s", std::string(__MYFUNCTION__).substr(std::string(__MYFUNCTION__).find_last_of("/\\") + 1).c_str(), __LINE__, exitCode, msg); - -#endif - // Declare the OpenZWave namespace -namespace std {} +namespace std +{ +} namespace OpenZWave { // Include the STL namespace using namespace std; + namespace Internal + { + namespace CC + { + + } + } } // Modifications for Microsoft compilers @@ -202,11 +200,9 @@ namespace OpenZWave #define snprintf sprintf_s #define strcasecmp _stricmp #define sscanf sscanf_s -#define strncpy strncpy_s +#define strncpy(x, y, z) strncpy_s(x, sizeof(x), y, sizeof(x)-1) #define strncat strncat_s - - #endif // Modifications for MiNGW32 compiler @@ -222,7 +218,6 @@ namespace OpenZWave #define fopen_s fopen - #endif //#define MAX_TRIES 3 // Retry sends up to 3 times @@ -334,7 +329,6 @@ namespace OpenZWave #define FUNC_ID_PROPRIETARY_D 0xFD #define FUNC_ID_PROPRIETARY_E 0xFE - #define ADD_NODE_ANY 0x01 #define ADD_NODE_CONTROLLER 0x02 #define ADD_NODE_SLAVE 0x03 @@ -453,14 +447,14 @@ namespace OpenZWave /* RouteScheme Definitions */ typedef enum TXSTATUS_ROUTING_SCHEME { - ROUTINGSCHEME_IDLE = 0, - ROUTINGSCHEME_DIRECT = 1, - ROUTINGSCHEME_CACHED_ROUTE_SR = 2, - ROUTINGSCHEME_CACHED_ROUTE = 3, - ROUTINGSCHEME_CACHED_ROUTE_NLWR = 4, - ROUTINGSCHEME_ROUTE = 5, - ROUTINGSCHEME_RESORT_DIRECT = 6, - ROUTINGSCHEME_RESORT_EXPLORE = 7 + ROUTINGSCHEME_IDLE = 0, + ROUTINGSCHEME_DIRECT = 1, + ROUTINGSCHEME_CACHED_ROUTE_SR = 2, + ROUTINGSCHEME_CACHED_ROUTE = 3, + ROUTINGSCHEME_CACHED_ROUTE_NLWR = 4, + ROUTINGSCHEME_ROUTE = 5, + ROUTINGSCHEME_RESORT_DIRECT = 6, + ROUTINGSCHEME_RESORT_EXPLORE = 7 } TXSTATUS_ROUTING_SCHEME; /* RouteSpeed Definitions */ @@ -472,5 +466,4 @@ typedef enum TXSTATUS_ROUTE_SPEED ROUTE_SPEED_100K = 3, } TXSTATUS_ROUTE_SPEED; - #endif // _Defs_H diff --git a/cpp/src/DoxygenMain.h b/cpp/src/DoxygenMain.h index ad6119686e..98602a3a91 100644 --- a/cpp/src/DoxygenMain.h +++ b/cpp/src/DoxygenMain.h @@ -1,4 +1,3 @@ - /** * \mainpage OpenZWave * \section Introduction Introduction to OpenZWave @@ -7,29 +6,12 @@ * applications, without requiring any in depth knowledge of the Z-Wave * protocol. *

- * The Majority of the Z-Wave Protocol has been released into the public domain - * on Sept, 2016. Prior to Sept, 2016, OpenZWave had reverse engineered the - * protocol to allow applications to be created to interact with Z-Wave devices. - * There is now ongoing work to update OpenZWave to be compliant with the Z-Wave - * Specifications that are now released at http://zwavepublic.com - *

- * There is one part of the protocol that has not been released into the Public - * Domain, namely, the "SerialAPI" protocol that specifies how to talk to - * a USB Stick via a Serial COM Port. This portion of OpenZWave will continue to - * be reverse engineered if needed in the future. - *

- * The goal of the project is to make a positive contribution to the Z-Wave - * community by creating a library that supports as much of the Z-Wave - * specification as possible, and that can be used as a "black-box" - * solution by anyone wanting to add Z-Wave to their application. - *

- * @image html zwalliance_250x100.jpg - *

OpenZWave is a affiliate member of the Z-Wave Alliance (http://zwavealliance.org/)
- + * For more information about the OpenZWave project: see README.md in the + * root of the OpenZWave repository. * \section ZWave Z-Wave Concepts * Z-Wave is a proprietary wireless communications protocol employing mesh * networking technology. A mesh network allows low power devices to - * communicate over long ranges, and around radio blackspots by passing + * communicate over long ranges, and around radio black spots by passing * messages from one node to another. It is important to note that not all * Z-Wave devices are active all the time, especially those that are battery * powered. These nodes cannot take part in the forwarding of messages @@ -37,10 +19,10 @@ *

* Each Z-Wave device is known as "Node" in the network. A Z-Wave network * can contain up to 232 nodes. If more devices are required, then - * multiple networks need to be set up using separate Z-Wave controller. + * multiple networks need to be set up using separate Z-Wave controllers. * OpenZWave supports multiple controllers, but on its own does not bridge - * the networks allowing a device on one to directly control a device on - * another. This functionality would have to be supplied by the application. + * the networks, allowing a device on one to directly control a device on + * another. This functionality would have to be supplied by the application. *

* Z-Wave nodes can be divided into two types: Controllers and Slaves. The * controllers are usually in the form of hand-held remote controls, or PC @@ -49,7 +31,6 @@ * Replication * Command Classes * Values - *


* \section Library The OpenZWave Library * \subsection Overview Overview @@ -93,7 +74,7 @@ * to be reliable. Do not rely on receiving a response to any request. * * - A Z-Wave network may change at any time. The application's notification - * callback handler must deal woth all notifications, and any representation + * callback handler must deal with all notifications, and any representation * of the state of the Z-Wave network held by the application must be * modified to match. User interfaces should be built dynamically from the * information reported in the notification callbacks, and must be able to cope @@ -112,23 +93,11 @@ *
* \section Licensing Licensing - * OpenZWave is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, either version 3 of the License, - * or (at your option) any later version. - *

- * OpenZWave is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - *

- * You should have received a copy of the GNU Lesser General Public License - * along with OpenZWave. If not, see . + * See README.md in the root of the OpenZWave project. *


* \section Support Support - * Assistance with all OpenZWave issues can be obtained by posting a message - * to the OpenZWave Google Group (http://groups.google.com/group/openzwave) + * See README.md in the root of the OpenZWave project. *

*/ diff --git a/cpp/src/Driver.cpp b/cpp/src/Driver.cpp index 5b001f4e5b..cf720813d4 100644 --- a/cpp/src/Driver.cpp +++ b/cpp/src/Driver.cpp @@ -67,7 +67,6 @@ #include "tinyxml.h" - #include "Utils.h" #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) # include @@ -89,12 +88,11 @@ using namespace OpenZWave; // 01: 12-31-2010 - Introduced config version numbering due to ValueID format change. // 02: 01-12-2011 - Command class m_afterMark sense corrected, and attribute named to match. // 03: 08-04-2011 - Changed command class instance handling for non-sequential MultiChannel endpoints. -// -uint32 const c_configVersion = 3; +// 04: 12-07-2019 - Changed Interview Order +uint32 const c_configVersion = 4; static char const* c_libraryTypeNames[] = -{ - "Unknown", // library type 0 +{ "Unknown", // library type 0 "Static Controller", // library type 1 "Controller", // library type 2 "Enhanced Slave", // library type 3 @@ -103,161 +101,63 @@ static char const* c_libraryTypeNames[] = "Routing Slave", // library type 6 "Bridge Controller", // library type 7 "Device Under Test" // library type 8 -}; + }; static char const* c_controllerCommandNames[] = -{ - "None", - "Add Device", - "Create New Primary", - "Receive Configuration", - "Remove Device", - "Remove Failed Node", - "Has Node Failed", - "Replace Failed Node", - "Transfer Primary Role", - "Request Network Update", - "Request Node Neighbor Update", - "Assign Return Route", - "Delete All Return Routes", - "Send Node Information", - "Replication Send", - "Create Button", - "Delete Button" -}; +{ "None", "Add Device", "Create New Primary", "Receive Configuration", "Remove Device", "Remove Failed Node", "Has Node Failed", "Replace Failed Node", "Transfer Primary Role", "Request Network Update", "Request Node Neighbor Update", "Assign Return Route", "Delete All Return Routes", "Send Node Information", "Replication Send", "Create Button", "Delete Button" }; static char const* c_sendQueueNames[] = -{ - "Command", - "NoOp", - "Controller", - "WakeUp", - "Send", - "Query", - "Poll" -}; - +{ "Command", "NoOp", "Controller", "WakeUp", "Send", "Query", "Poll" }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -Driver::Driver -( - string const& _controllerPath, - ControllerInterface const& _interface -): -m_driverThread( new Thread( "driver" ) ), -m_dns ( new DNSThread(this) ), -m_dnsThread ( new Thread( "dns" ) ), -m_initMutex(new Mutex()), -m_exit( false ), -m_init( false ), -m_awakeNodesQueried( false ), -m_allNodesQueried( false ), -m_notifytransactions( false ), -m_timer ( new TimerThread( this ) ), -m_timerThread ( new Thread( "timer" ) ), -m_controllerInterfaceType( _interface ), -m_controllerPath( _controllerPath ), -m_controller( NULL ), -m_homeId( 0 ), -m_libraryVersion( "" ), -m_libraryTypeName( "" ), -m_libraryType( 0 ), -m_manufacturerId( 0 ), -m_productType( 0 ), -m_productId ( 0 ), -m_initVersion( 0 ), -m_initCaps( 0 ), -m_controllerCaps( 0 ), -m_Controller_nodeId ( 0 ), -m_nodeMutex( new Mutex() ), -m_controllerReplication( NULL ), -m_transmitOptions( TRANSMIT_OPTION_ACK | TRANSMIT_OPTION_AUTO_ROUTE | TRANSMIT_OPTION_EXPLORE ), -m_waitingForAck( false ), -m_expectedCallbackId( 0 ), -m_expectedReply( 0 ), -m_expectedCommandClassId( 0 ), -m_expectedNodeId( 0 ), -m_pollThread( new Thread( "poll" ) ), -m_pollMutex( new Mutex() ), -m_pollInterval( 0 ), -m_bIntervalBetweenPolls( false ), // if set to true (via SetPollInterval), the pollInterval will be interspersed between each poll (so a much smaller m_pollInterval like 100, 500, or 1,000 may be appropriate) -m_currentControllerCommand( NULL ), -m_SUCNodeId( 0 ), -m_controllerResetEvent( NULL ), -m_sendMutex( new Mutex() ), -m_currentMsg( NULL ), -m_virtualNeighborsReceived( false ), -m_notificationsEvent( new Event() ), -m_SOFCnt( 0 ), -m_ACKWaiting( 0 ), -m_readAborts( 0 ), -m_badChecksum( 0 ), -m_readCnt( 0 ), -m_writeCnt( 0 ), -m_CANCnt( 0 ), -m_NAKCnt( 0 ), -m_ACKCnt( 0 ), -m_OOFCnt( 0 ), -m_dropped( 0 ), -m_retries( 0 ), -m_callbacks( 0 ), -m_badroutes( 0 ), -m_noack( 0 ), -m_netbusy( 0 ), -m_notidle( 0 ), -m_txverified( 0 ), -m_nondelivery( 0 ), -m_routedbusy( 0 ), -m_broadcastReadCnt( 0 ), -m_broadcastWriteCnt( 0 ), -AuthKey( 0 ), -EncryptKey( 0 ), -m_nonceReportSent( 0 ), -m_nonceReportSentAttempt( 0 ), -m_queueMsgEvent (new Event() ), -m_eventMutex (new Mutex() ) +Driver::Driver(string const& _controllerPath, ControllerInterface const& _interface) : + m_driverThread(new Internal::Platform::Thread("driver")), m_dns(new Internal::DNSThread(this)), m_dnsThread(new Internal::Platform::Thread("dns")), m_initMutex(new Internal::Platform::Mutex()), m_exit(false), m_init(false), m_awakeNodesQueried(false), m_allNodesQueried(false), m_notifytransactions(false), m_timer(new Internal::TimerThread(this)), m_timerThread(new Internal::Platform::Thread("timer")), m_controllerInterfaceType(_interface), m_controllerPath(_controllerPath), m_controller( + NULL), m_homeId(0), m_libraryVersion(""), m_libraryTypeName(""), m_libraryType(0), m_manufacturerId(0), m_productType(0), m_productId(0), m_initVersion(0), m_initCaps(0), m_controllerCaps(0), m_Controller_nodeId(0), m_nodeMutex(new Internal::Platform::Mutex()), m_controllerReplication( NULL), m_transmitOptions( TRANSMIT_OPTION_ACK | TRANSMIT_OPTION_AUTO_ROUTE | TRANSMIT_OPTION_EXPLORE), m_waitingForAck(false), m_expectedCallbackId(0), m_expectedReply(0), m_expectedCommandClassId( + 0), m_expectedNodeId(0), m_pollThread(new Internal::Platform::Thread("poll")), m_pollMutex(new Internal::Platform::Mutex()), m_pollInterval(0), m_bIntervalBetweenPolls(false), // if set to true (via SetPollInterval), the pollInterval will be interspersed between each poll (so a much smaller m_pollInterval like 100, 500, or 1,000 may be appropriate) + m_currentControllerCommand( NULL), m_SUCNodeId(0), m_controllerResetEvent( NULL), m_sendMutex(new Internal::Platform::Mutex()), m_currentMsg( NULL), m_virtualNeighborsReceived(false), m_notificationsEvent(new Internal::Platform::Event()), m_SOFCnt(0), m_ACKWaiting(0), m_readAborts(0), m_badChecksum(0), m_readCnt(0), m_writeCnt(0), m_CANCnt(0), m_NAKCnt(0), m_ACKCnt(0), m_OOFCnt(0), m_dropped(0), m_retries(0), m_callbacks(0), m_badroutes(0), m_noack(0), m_netbusy(0), m_notidle(0), m_txverified( + 0), m_nondelivery(0), m_routedbusy(0), m_broadcastReadCnt(0), m_broadcastWriteCnt(0), AuthKey(0), EncryptKey(0), m_nonceReportSent(0), m_nonceReportSentAttempt(0), m_queueMsgEvent(new Internal::Platform::Event()), m_eventMutex(new Internal::Platform::Mutex()) { // set a timestamp to indicate when this driver started - TimeStamp m_startTime; + Internal::Platform::TimeStamp m_startTime; // Create the message queue events - for( int32 i=0; iSetSignalThreshold( 1 ); + m_controller->SetSignalThreshold(1); - Options::Get()->GetOptionAsBool( "NotifyTransactions", &m_notifytransactions ); - Options::Get()->GetOptionAsInt( "PollInterval", &m_pollInterval ); - Options::Get()->GetOptionAsBool( "IntervalBetweenPolls", &m_bIntervalBetweenPolls ); + Options::Get()->GetOptionAsBool("NotifyTransactions", &m_notifytransactions); + Options::Get()->GetOptionAsInt("PollInterval", &m_pollInterval); + Options::Get()->GetOptionAsBool("IntervalBetweenPolls", &m_bIntervalBetweenPolls); - m_httpClient = new HttpClient(this); + m_httpClient = new Internal::HttpClient(this); - m_mfs = ManufacturerSpecificDB::Create(); + m_mfs = Internal::ManufacturerSpecificDB::Create(); CheckMFSConfigRevision(); @@ -267,29 +167,26 @@ m_eventMutex (new Mutex() ) // // Destructor //----------------------------------------------------------------------------- -Driver::~Driver -( -) +Driver::~Driver() { /* Signal that we are going away... so at least Apps know... */ - Notification* notification = new Notification( Notification::Type_DriverRemoved ); - notification->SetHomeAndNodeIds( m_homeId, 0 ); - QueueNotification( notification ); + Notification* notification = new Notification(Notification::Type_DriverRemoved); + notification->SetHomeAndNodeIds(m_homeId, 0); + QueueNotification(notification); NotifyWatchers(); - // append final driver stats output to the log file LogDriverStatistics(); // Save the driver config before deleting anything else bool save; - if( Options::Get()->GetOptionAsBool( "SaveConfiguration", &save) ) + if (Options::Get()->GetOptionAsBool("SaveConfiguration", &save)) { - if( save ) + if (save) { WriteCache(); - Scene::WriteXML( "zwscene.xml" ); + Internal::Scene::WriteXML("zwscene.xml"); } } @@ -310,9 +207,9 @@ Driver::~Driver m_driverThread->Stop(); m_driverThread->Release(); - m_timerThread->Stop(); - m_timerThread->Release(); - delete m_timer; + m_timerThread->Stop(); + m_timerThread->Release(); + delete m_timer; m_sendMutex->Release(); @@ -321,23 +218,23 @@ Driver::~Driver m_initMutex->Release(); - if( m_currentMsg != NULL ) + if (m_currentMsg != NULL) { RemoveCurrentMsg(); } // Clear the node data { - LockGuard LG(m_nodeMutex); - for( int i=0; i<256; ++i ) + Internal::LockGuard LG(m_nodeMutex); + for (int i = 0; i < 256; ++i) { - if( GetNodeUnsafe( i ) ) + if (GetNodeUnsafe(i)) { delete m_nodes[i]; m_nodes[i] = NULL; - Notification* notification = new Notification( Notification::Type_NodeRemoved ); - notification->SetHomeAndNodeIds( m_homeId, i ); - QueueNotification( notification ); + Notification* notification = new Notification(Notification::Type_NodeRemoved); + notification->SetHomeAndNodeIds(m_homeId, i); + QueueNotification(notification); } } } @@ -345,16 +242,16 @@ Driver::~Driver m_pollMutex->Release(); // Clear the send Queue - for( int32 i=0; iGetOptionAsBool( "NotifyOnDriverUnload", ¬ify) ) + if (Options::Get()->GetOptionAsBool("NotifyOnDriverUnload", ¬ify)) { - if( notify ) + if (notify) { NotifyWatchers(); } } + list::iterator nit = m_notifications.begin(); + while (nit != m_notifications.end()) + { + Notification* notification = m_notifications.front(); + m_notifications.pop_front(); + delete notification; + nit = m_notifications.begin(); + } + if (m_controllerReplication) delete m_controllerReplication; m_notificationsEvent->Release(); m_nodeMutex->Release(); + m_queueMsgEvent->Release(); + m_eventMutex->Release(); delete this->AuthKey; delete this->EncryptKey; delete this->m_httpClient; @@ -394,30 +302,24 @@ Driver::~Driver // // Start the driver thread //----------------------------------------------------------------------------- -void Driver::Start -( -) +void Driver::Start() { // Start the thread that will handle communications with the Z-Wave network - m_driverThread->Start( Driver::DriverThreadEntryPoint, this ); - m_dnsThread->Start ( DNSThread::DNSThreadEntryPoint, m_dns); - m_timerThread->Start( TimerThread::TimerThreadEntryPoint, m_timer ); + m_driverThread->Start(Driver::DriverThreadEntryPoint, this); + m_dnsThread->Start(Internal::DNSThread::DNSThreadEntryPoint, m_dns); + m_timerThread->Start(Internal::TimerThread::TimerThreadEntryPoint, m_timer); } //----------------------------------------------------------------------------- // // Entry point of the thread for creating and managing the worker threads //----------------------------------------------------------------------------- -void Driver::DriverThreadEntryPoint -( - Event* _exitEvent, - void* _context -) +void Driver::DriverThreadEntryPoint(Internal::Platform::Event* _exitEvent, void* _context) { - Driver* driver = (Driver*)_context; - if( driver ) + Driver* driver = (Driver*) _context; + if (driver) { - driver->DriverThreadProc( _exitEvent ); + driver->DriverThreadProc(_exitEvent); } } @@ -425,24 +327,22 @@ void Driver::DriverThreadEntryPoint // // Create and manage the worker threads //----------------------------------------------------------------------------- -void Driver::DriverThreadProc -( - Event* _exitEvent -) +void Driver::DriverThreadProc(Internal::Platform::Event* _exitEvent) { #define WAITOBJECTCOUNT 11 uint32 attempts = 0; bool mfsisReady = false; - while( true ) + while (true) { - if( Init( attempts ) ) + if (Init(attempts)) { // Driver has been initialised - Wait* waitObjects[WAITOBJECTCOUNT]; + Internal::Platform::Wait* waitObjects[WAITOBJECTCOUNT]; waitObjects[0] = _exitEvent; // Thread must exit. waitObjects[1] = m_notificationsEvent; // Notifications waiting to be sent. - waitObjects[2] = m_queueMsgEvent; ; // a DNS and HTTP Event + waitObjects[2] = m_queueMsgEvent; + ; // a DNS and HTTP Event waitObjects[3] = m_controller; // Controller has received data. waitObjects[4] = m_queueEvent[MsgQueue_Command]; // A controller command is in progress. waitObjects[5] = m_queueEvent[MsgQueue_NoOp]; // Send device probes and diagnostics messages @@ -452,32 +352,34 @@ void Driver::DriverThreadProc waitObjects[9] = m_queueEvent[MsgQueue_Query]; // Node queries are pending. waitObjects[10] = m_queueEvent[MsgQueue_Poll]; // Poll request is waiting. - TimeStamp retryTimeStamp; + Internal::Platform::TimeStamp retryTimeStamp; int retryTimeout = RETRY_TIMEOUT; - Options::Get()->GetOptionAsInt( "RetryTimeout", &retryTimeout ); + Options::Get()->GetOptionAsInt("RetryTimeout", &retryTimeout); //retryTimeout = RETRY_TIMEOUT * 10; - while( true ) + while (true) { - Log::Write( LogLevel_StreamDetail, " Top of DriverThreadProc loop." ); + Log::Write(LogLevel_StreamDetail, " Top of DriverThreadProc loop."); uint32 count = WAITOBJECTCOUNT; - int32 timeout = Wait::Timeout_Infinite; + int32 timeout = Internal::Platform::Wait::Timeout_Infinite; // if the ManufacturerDB class is setting up, we can't do anything yet - if (mfsisReady == false) { - count=3; + if (mfsisReady == false) + { + count = 3; // If we're waiting for a message to complete, we can only // handle incoming data, notifications, DNS/HTTP and exit events. - } else if( m_waitingForAck || m_expectedCallbackId || m_expectedReply ) + } + else if (m_waitingForAck || m_expectedCallbackId || m_expectedReply) { count = 4; timeout = m_waitingForAck ? ACK_TIMEOUT : retryTimeStamp.TimeRemaining(); - if( timeout < 0 ) + if (timeout < 0) { timeout = 0; } } - else if( m_currentControllerCommand != NULL ) + else if (m_currentControllerCommand != NULL) { count = 7; } @@ -487,63 +389,64 @@ void Driver::DriverThreadProc } // Wait for something to do - int32 res = Wait::Multiple( waitObjects, count, timeout ); + int32 res = Internal::Platform::Wait::Multiple(waitObjects, count, timeout); - switch( res ) - { - case -1: + switch (res) { - // Wait has timed out - time to resend - if( m_currentMsg != NULL ) + case -1: { - Notification* notification = new Notification( Notification::Type_Notification ); - notification->SetHomeAndNodeIds( m_homeId, m_currentMsg->GetTargetNodeId() ); - notification->SetNotification( Notification::Code_Timeout ); - QueueNotification( notification ); + // Wait has timed out - time to resend + if (m_currentMsg != NULL) + { + Notification* notification = new Notification(Notification::Type_Notification); + notification->SetHomeAndNodeIds(m_homeId, m_currentMsg->GetTargetNodeId()); + notification->SetNotification(Notification::Code_Timeout); + QueueNotification(notification); + } + if (WriteMsg("Wait Timeout")) + { + retryTimeStamp.SetTime(retryTimeout); + } + break; } - if( WriteMsg( "Wait Timeout" ) ) + case 0: { - retryTimeStamp.SetTime( retryTimeout ); + // Exit has been signalled + return; } - break; - } - case 0: - { - // Exit has been signalled - return; - } - case 1: - { - // Notifications are waiting to be sent - NotifyWatchers(); - break; - } - case 2: - { - // a DNS or HTTP Event has occurred - ProcessEventMsg(); - if (mfsisReady == false && m_mfs->isReady()) { - Notification* notification = new Notification( Notification::Type_ManufacturerSpecificDBReady ); - QueueNotification( notification ); - mfsisReady = true; + case 1: + { + // Notifications are waiting to be sent + NotifyWatchers(); + break; } - break; - } - case 3: - { - // Data has been received - ReadMsg(); - break; - } - default: - { - // All the other events are sending message queue items - if( WriteNextMsg( (MsgQueue)(res-4) ) ) + case 2: { - retryTimeStamp.SetTime( retryTimeout ); + // a DNS or HTTP Event has occurred + ProcessEventMsg(); + if (mfsisReady == false && m_mfs->isReady()) + { + Notification* notification = new Notification(Notification::Type_ManufacturerSpecificDBReady); + QueueNotification(notification); + mfsisReady = true; + } + break; + } + case 3: + { + // Data has been received + ReadMsg(); + break; + } + default: + { + // All the other events are sending message queue items + if (WriteNextMsg((MsgQueue) (res - 4))) + { + retryTimeStamp.SetTime(retryTimeout); + } + break; } - break; - } } } } @@ -551,18 +454,18 @@ void Driver::DriverThreadProc ++attempts; uint32 maxAttempts = 0; - Options::Get()->GetOptionAsInt("DriverMaxAttempts", (int32 *)&maxAttempts); - if( maxAttempts && (attempts >= maxAttempts) ) + Options::Get()->GetOptionAsInt("DriverMaxAttempts", (int32 *) &maxAttempts); + if (maxAttempts && (attempts >= maxAttempts)) { Manager::Get()->Manager::SetDriverReady(this, false); NotifyWatchers(); break; } - if( attempts < 25 ) + if (attempts < 25) { // Retry every 5 seconds for the first two minutes - if( Wait::Single( _exitEvent, 5000 ) == 0 ) + if (Internal::Platform::Wait::Single(_exitEvent, 5000) == 0) { // Exit signalled. return; @@ -571,7 +474,7 @@ void Driver::DriverThreadProc else { // Retry every 30 seconds after that - if( Wait::Single( _exitEvent, 30000 ) == 0 ) + if (Internal::Platform::Wait::Single(_exitEvent, 30000) == 0) { // Exit signalled. return; @@ -580,15 +483,11 @@ void Driver::DriverThreadProc } } - //----------------------------------------------------------------------------- // // Initialize the controller //----------------------------------------------------------------------------- -bool Driver::Init -( - uint32 _attempts -) +bool Driver::Init(uint32 _attempts) { m_initMutex->Lock(); @@ -602,24 +501,24 @@ bool Driver::Init m_waitingForAck = false; // Open the controller - Log::Write( LogLevel_Info, " Opening controller %s", m_controllerPath.c_str() ); + Log::Write(LogLevel_Info, " Opening controller %s", m_controllerPath.c_str()); - if( !m_controller->Open( m_controllerPath ) ) + if (!m_controller->Open(m_controllerPath)) { - Log::Write( LogLevel_Warning, "WARNING: Failed to init the controller (attempt %d)", _attempts ); + Log::Write(LogLevel_Warning, "WARNING: Failed to init the controller (attempt %d)", _attempts); m_initMutex->Unlock(); return false; } // Controller opened successfully, so we need to start all the worker threads - m_pollThread->Start( Driver::PollThreadEntryPoint, this ); + m_pollThread->Start(Driver::PollThreadEntryPoint, this); // Send a NAK to the ZWave device uint8 nak = NAK; - m_controller->Write( &nak, 1 ); + m_controller->Write(&nak, 1); // Get/set ZWave controller information in its preferred initialization order - m_controller->PlayInitSequence( this ); + m_controller->PlayInitSequence(this); //If we ever want promiscuous mode uncomment this code. //Msg* msg = new Msg( "FUNC_ID_ZW_SET_PROMISCUOUS_MODE", 0xff, REQUEST, FUNC_ID_ZW_SET_PROMISCUOUS_MODE, false, false ); @@ -636,34 +535,31 @@ bool Driver::Init // // Clean up any messages to a node //----------------------------------------------------------------------------- -void Driver::RemoveQueues -( - uint8 const _nodeId -) +void Driver::RemoveQueues(uint8 const _nodeId) { - if( m_currentMsg != NULL && m_currentMsg->GetTargetNodeId() == _nodeId ) + if (m_currentMsg != NULL && m_currentMsg->GetTargetNodeId() == _nodeId) { RemoveCurrentMsg(); } // Clear the send Queue - for( int32 i=0; i::iterator it = m_msgQueue[i].begin(); - while( it != m_msgQueue[i].end() ) + while (it != m_msgQueue[i].end()) { bool remove = false; MsgQueueItem const& item = *it; - if( MsgQueueCmd_SendMsg == item.m_command && _nodeId == item.m_msg->GetTargetNodeId() ) + if (MsgQueueCmd_SendMsg == item.m_command && _nodeId == item.m_msg->GetTargetNodeId()) { delete item.m_msg; remove = true; } - else if( MsgQueueCmd_QueryStageComplete == item.m_command && _nodeId == item.m_nodeId ) + else if (MsgQueueCmd_QueryStageComplete == item.m_command && _nodeId == item.m_nodeId) { remove = true; } - else if( MsgQueueCmd_Controller == item.m_command && _nodeId == item.m_cci->m_controllerCommandNode && m_currentControllerCommand != item.m_cci ) + else if (MsgQueueCmd_Controller == item.m_command && _nodeId == item.m_cci->m_controllerCommandNode && m_currentControllerCommand != item.m_cci) { delete item.m_cci; remove = true; @@ -672,16 +568,16 @@ void Driver::RemoveQueues { remove = true; } - if( remove ) + if (remove) { - it = m_msgQueue[i].erase( it ); + it = m_msgQueue[i].erase(it); } else { ++it; } } - if( m_msgQueue[i].empty() ) + if (m_msgQueue[i].empty()) { m_queueEvent[i]->Reset(); } @@ -696,121 +592,125 @@ void Driver::RemoveQueues // // Read our configuration from an XML document //----------------------------------------------------------------------------- -bool Driver::ReadCache -( -) +bool Driver::ReadCache() { char str[32]; int32 intVal; // Load the XML document that contains the driver configuration string userPath; - Options::Get()->GetOptionAsString( "UserPath", &userPath ); + Options::Get()->GetOptionAsString("UserPath", &userPath); - snprintf( str, sizeof(str), "ozwcache_0x%08x.xml", m_homeId ); - string filename = userPath + string(str); + snprintf(str, sizeof(str), "ozwcache_0x%08x.xml", m_homeId); + string filename = userPath + string(str); TiXmlDocument doc; - if( !doc.LoadFile( filename.c_str(), TIXML_ENCODING_UTF8 ) ) + if (!doc.LoadFile(filename.c_str(), TIXML_ENCODING_UTF8)) { return false; } - doc.SetUserData((void *)filename.c_str()); + doc.SetUserData((void *) filename.c_str()); TiXmlElement const* driverElement = doc.RootElement(); + char const *xmlns = driverElement->Attribute("xmlns"); + if (strcmp(xmlns, "https://github.com/OpenZWave/open-zwave")) + { + Log::Write(LogLevel_Warning, "Invalid XML Namespace. Ignoring %s", filename.c_str()); + return false; + } + // Version - if( TIXML_SUCCESS != driverElement->QueryIntAttribute( "version", &intVal ) || (uint32)intVal != c_configVersion ) + if (TIXML_SUCCESS != driverElement->QueryIntAttribute("version", &intVal) || (uint32) intVal != c_configVersion) { - Log::Write( LogLevel_Warning, "WARNING: Driver::ReadCache - %s is from an older version of OpenZWave and cannot be loaded.", filename.c_str() ); + Log::Write(LogLevel_Warning, "WARNING: Driver::ReadCache - %s is from an older version of OpenZWave and cannot be loaded.", filename.c_str()); return false; } // Capabilities - if( TIXML_SUCCESS == driverElement->QueryIntAttribute( "revision", &intVal ) ) + if (TIXML_SUCCESS == driverElement->QueryIntAttribute("revision", &intVal)) { m_mfs->setLatestRevision(intVal); } - // Home ID - char const* homeIdStr = driverElement->Attribute( "home_id" ); - if( homeIdStr ) + char const* homeIdStr = driverElement->Attribute("home_id"); + if (homeIdStr) { char* p; - uint32 homeId = (uint32)strtoul( homeIdStr, &p, 0 ); + uint32 homeId = (uint32) strtoul(homeIdStr, &p, 0); - if( homeId != m_homeId ) + if (homeId != m_homeId) { - Log::Write( LogLevel_Warning, "WARNING: Driver::ReadCache - Home ID in file %s is incorrect", filename.c_str() ); + Log::Write(LogLevel_Warning, "WARNING: Driver::ReadCache - Home ID in file %s is incorrect", filename.c_str()); return false; } } else { - Log::Write( LogLevel_Warning, "WARNING: Driver::ReadCache - Home ID is missing from file %s", filename.c_str() ); + Log::Write(LogLevel_Warning, "WARNING: Driver::ReadCache - Home ID is missing from file %s", filename.c_str()); return false; } // Node ID - if( TIXML_SUCCESS == driverElement->QueryIntAttribute( "node_id", &intVal ) ) + if (TIXML_SUCCESS == driverElement->QueryIntAttribute("node_id", &intVal)) { - if( (uint8)intVal != m_Controller_nodeId ) + if ((uint8) intVal != m_Controller_nodeId) { - Log::Write( LogLevel_Warning, "WARNING: Driver::ReadCache - Controller Node ID in file %s is incorrect", filename.c_str() ); + Log::Write(LogLevel_Warning, "WARNING: Driver::ReadCache - Controller Node ID in file %s is incorrect", filename.c_str()); return false; } } else { - Log::Write( LogLevel_Warning, "WARNING: Driver::ReadCache - Node ID is missing from file %s", filename.c_str() ); + Log::Write(LogLevel_Warning, "WARNING: Driver::ReadCache - Node ID is missing from file %s", filename.c_str()); return false; } // Capabilities - if( TIXML_SUCCESS == driverElement->QueryIntAttribute( "api_capabilities", &intVal ) ) + if (TIXML_SUCCESS == driverElement->QueryIntAttribute("api_capabilities", &intVal)) { - m_initCaps = (uint8)intVal; + m_initCaps = (uint8) intVal; } - if( TIXML_SUCCESS == driverElement->QueryIntAttribute( "controller_capabilities", &intVal ) ) + if (TIXML_SUCCESS == driverElement->QueryIntAttribute("controller_capabilities", &intVal)) { - m_controllerCaps = (uint8)intVal; + m_controllerCaps = (uint8) intVal; } // Poll Interval - if( TIXML_SUCCESS == driverElement->QueryIntAttribute( "poll_interval", &intVal ) ) + if (TIXML_SUCCESS == driverElement->QueryIntAttribute("poll_interval", &intVal)) { m_pollInterval = intVal; } // Poll Interval--between polls or period for polling the entire pollList? - char const* cstr = driverElement->Attribute( "poll_interval_between" ); - if( cstr ) + char const* cstr = driverElement->Attribute("poll_interval_between"); + if (cstr) { - m_bIntervalBetweenPolls = !strcmp( cstr, "true" ); + m_bIntervalBetweenPolls = !strcmp(cstr, "true"); } // Read the nodes - LockGuard LG(m_nodeMutex); + Internal::LockGuard LG(m_nodeMutex); TiXmlElement const* nodeElement = driverElement->FirstChildElement(); - while( nodeElement ) + while (nodeElement) { char const* str = nodeElement->Value(); - if( str && !strcmp( str, "Node" ) ) + if (str && !strcmp(str, "Node")) { // Get the node Id from the XML - if( TIXML_SUCCESS == nodeElement->QueryIntAttribute( "id", &intVal ) ) + if (TIXML_SUCCESS == nodeElement->QueryIntAttribute("id", &intVal)) { - uint8 nodeId = (uint8)intVal; - Node* node = new Node( m_homeId, nodeId ); + uint8 nodeId = (uint8) intVal; + Node* node = new Node(m_homeId, nodeId); m_nodes[nodeId] = node; - Notification* notification = new Notification( Notification::Type_NodeAdded ); - notification->SetHomeAndNodeIds( m_homeId, nodeId ); - QueueNotification( notification ); + Notification* notification = new Notification(Notification::Type_NodeAdded); + notification->SetHomeAndNodeIds(m_homeId, nodeId); + QueueNotification(notification); // Read the rest of the node configuration from the XML - node->ReadXML( nodeElement ); + node->ReadXML(nodeElement); } } @@ -820,16 +720,16 @@ bool Driver::ReadCache LG.Unlock(); // restore the previous state (for now, polling) for the nodes/values just retrieved - for( int i=0; i<256; i++ ) + for (int i = 0; i < 256; i++) { - if( m_nodes[i] != NULL ) + if (m_nodes[i] != NULL) { - ValueStore* vs = m_nodes[i]->m_values; - for( ValueStore::Iterator it = vs->Begin(); it != vs->End(); ++it ) + Internal::VC::ValueStore* vs = m_nodes[i]->m_values; + for (Internal::VC::ValueStore::Iterator it = vs->Begin(); it != vs->End(); ++it) { - Value* value = it->second; - if( value->m_pollIntensity != 0 ) - EnablePoll( value->GetID(), value->m_pollIntensity ); + Internal::VC::Value* value = it->second; + if (value->m_pollIntensity != 0) + EnablePoll(value->GetID(), value->m_pollIntensity); } } } @@ -841,73 +741,75 @@ bool Driver::ReadCache // // Write ourselves to an XML document //----------------------------------------------------------------------------- -void Driver::WriteCache -( -) +void Driver::WriteCache() { char str[32]; - if (!m_homeId) { - Log::Write( LogLevel_Warning, "WARNING: Tried to write driver config with no home ID set"); + if (!m_homeId) + { + Log::Write(LogLevel_Warning, "WARNING: Tried to write driver config with no home ID set"); return; } Log::Write(LogLevel_Info, "Saving Cache"); // Create a new XML document to contain the driver configuration TiXmlDocument doc; - TiXmlDeclaration* decl = new TiXmlDeclaration( "1.0", "utf-8", "" ); - TiXmlElement* driverElement = new TiXmlElement( "Driver" ); - doc.LinkEndChild( decl ); - doc.LinkEndChild( driverElement ); + TiXmlDeclaration* decl = new TiXmlDeclaration("1.0", "utf-8", ""); + TiXmlElement* driverElement = new TiXmlElement("Driver"); + doc.LinkEndChild(decl); + doc.LinkEndChild(driverElement); - driverElement->SetAttribute( "xmlns", "https://github.com/OpenZWave/open-zwave" ); + driverElement->SetAttribute("xmlns", "https://github.com/OpenZWave/open-zwave"); - snprintf( str, sizeof(str), "%d", c_configVersion ); - driverElement->SetAttribute( "version", str ); + snprintf(str, sizeof(str), "%d", c_configVersion); + driverElement->SetAttribute("version", str); - snprintf( str, sizeof(str), "%d", GetManufacturerSpecificDB()->getRevision()); - driverElement->SetAttribute( "revision", str); + snprintf(str, sizeof(str), "%d", GetManufacturerSpecificDB()->getRevision()); + driverElement->SetAttribute("revision", str); - snprintf( str, sizeof(str), "0x%.8x", m_homeId ); - driverElement->SetAttribute( "home_id", str ); + snprintf(str, sizeof(str), "0x%.8x", m_homeId); + driverElement->SetAttribute("home_id", str); - snprintf( str, sizeof(str), "%d", m_Controller_nodeId ); - driverElement->SetAttribute( "node_id", str ); + snprintf(str, sizeof(str), "%d", m_Controller_nodeId); + driverElement->SetAttribute("node_id", str); - snprintf( str, sizeof(str), "%d", m_initCaps ); - driverElement->SetAttribute( "api_capabilities", str ); + snprintf(str, sizeof(str), "%d", m_initCaps); + driverElement->SetAttribute("api_capabilities", str); - snprintf( str, sizeof(str), "%d", m_controllerCaps ); - driverElement->SetAttribute( "controller_capabilities", str ); + snprintf(str, sizeof(str), "%d", m_controllerCaps); + driverElement->SetAttribute("controller_capabilities", str); - snprintf( str, sizeof(str), "%d", m_pollInterval ); - driverElement->SetAttribute( "poll_interval", str ); + snprintf(str, sizeof(str), "%d", m_pollInterval); + driverElement->SetAttribute("poll_interval", str); - snprintf( str, sizeof(str), "%s", m_bIntervalBetweenPolls ? "true" : "false" ); - driverElement->SetAttribute( "poll_interval_between", str ); + snprintf(str, sizeof(str), "%s", m_bIntervalBetweenPolls ? "true" : "false"); + driverElement->SetAttribute("poll_interval_between", str); { - LockGuard LG(m_nodeMutex); + Internal::LockGuard LG(m_nodeMutex); - for( int i=0; i<256; ++i ) + for (int i = 0; i < 256; ++i) { - if( m_nodes[i] ) + if (m_nodes[i]) { - if (m_nodes[i]->GetCurrentQueryStage() == Node::QueryStage_Complete) { - m_nodes[i]->WriteXML( driverElement ); - Log::Write(LogLevel_Info, i, "Cache Save for Node %d as its QueryStage_Complete", i); - } else { - Log::Write(LogLevel_Info, i, "Skipping Cache Save for Node %d as its not QueryStage_Complete", i); + if (m_nodes[i]->GetCurrentQueryStage() >= Node::QueryStage_CacheLoad) + { + m_nodes[i]->WriteXML(driverElement); + Log::Write(LogLevel_Info, i, "Cache Save for Node %d as its QueryStage_CacheLoad", i); + } + else + { + Log::Write(LogLevel_Info, i, "Skipping Cache Save for Node %d as its not past QueryStage_CacheLoad", i); } } } } string userPath; - Options::Get()->GetOptionAsString( "UserPath", &userPath ); + Options::Get()->GetOptionAsString("UserPath", &userPath); - snprintf( str, sizeof(str), "ozwcache_0x%08x.xml", m_homeId ); - string filename = userPath + string(str); + snprintf(str, sizeof(str), "ozwcache_0x%08x.xml", m_homeId); + string filename = userPath + string(str); - doc.SaveFile( filename.c_str() ); + doc.SaveFile(filename.c_str()); } //----------------------------------------------------------------------------- @@ -919,12 +821,9 @@ void Driver::WriteCache // Returns a pointer to the requested node without locking. // Only to be used by main thread code. //----------------------------------------------------------------------------- -Node* Driver::GetNodeUnsafe -( - uint8 _nodeId -) +Node* Driver::GetNodeUnsafe(uint8 _nodeId) { - if( Node* node = m_nodes[_nodeId] ) + if (Node* node = m_nodes[_nodeId]) { return node; } @@ -935,16 +834,14 @@ Node* Driver::GetNodeUnsafe // // Locks the nodes and returns a pointer to the requested one //----------------------------------------------------------------------------- -Node* Driver::GetNode -( - uint8 _nodeId -) +Node* Driver::GetNode(uint8 _nodeId) { - if (m_nodeMutex->IsSignalled()) { + if (m_nodeMutex->IsSignalled()) + { Log::Write(LogLevel_Error, _nodeId, "Driver Thread is Not Locked during Call to GetNode"); return NULL; } - if( Node* node = m_nodes[_nodeId] ) + if (Node* node = m_nodes[_nodeId]) { return node; } @@ -960,11 +857,7 @@ Node* Driver::GetNode // // Queue an item on the query queue that indicates a stage is complete //----------------------------------------------------------------------------- -void Driver::SendQueryStageComplete -( - uint8 const _nodeId, - Node::QueryStage const _stage -) +void Driver::SendQueryStageComplete(uint8 const _nodeId, Node::QueryStage const _stage) { MsgQueueItem item; item.m_command = MsgQueueCmd_QueryStageComplete; @@ -972,28 +865,28 @@ void Driver::SendQueryStageComplete item.m_queryStage = _stage; item.m_retry = false; - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { - if( !node->IsListeningDevice() ) + if (!node->IsListeningDevice()) { - if( WakeUp* wakeUp = static_cast( node->GetCommandClass( WakeUp::StaticGetCommandClassId() ) ) ) + if (Internal::CC::WakeUp* wakeUp = static_cast(node->GetCommandClass(Internal::CC::WakeUp::StaticGetCommandClassId()))) { - if( !wakeUp->IsAwake() ) + if (!wakeUp->IsAwake()) { // If the message is for a sleeping node, we queue it in the node itself. - Log::Write( LogLevel_Info, "" ); - Log::Write( LogLevel_Detail, node->GetNodeId(), "Queuing (%s) Query Stage Complete (%s)", c_sendQueueNames[MsgQueue_WakeUp], node->GetQueryStageName( _stage ).c_str() ); - wakeUp->QueueMsg( item ); + Log::Write(LogLevel_Info, ""); + Log::Write(LogLevel_Detail, node->GetNodeId(), "Queuing (%s) Query Stage Complete (%s)", c_sendQueueNames[MsgQueue_WakeUp], node->GetQueryStageName(_stage).c_str()); + wakeUp->QueueMsg(item); return; } } } // Non-sleeping node - Log::Write( LogLevel_Detail, node->GetNodeId(), "Queuing (%s) Query Stage Complete (%s)", c_sendQueueNames[MsgQueue_Query], node->GetQueryStageName( _stage ).c_str() ); + Log::Write(LogLevel_Detail, node->GetNodeId(), "Queuing (%s) Query Stage Complete (%s)", c_sendQueueNames[MsgQueue_Query], node->GetQueryStageName(_stage).c_str()); m_sendMutex->Lock(); - m_msgQueue[MsgQueue_Query].push_back( item ); + m_msgQueue[MsgQueue_Query].push_back(item); m_queueEvent[MsgQueue_Query]->Set(); m_sendMutex->Unlock(); @@ -1004,11 +897,7 @@ void Driver::SendQueryStageComplete // // Request the current stage will be repeated //----------------------------------------------------------------------------- -void Driver::RetryQueryStageComplete -( - uint8 const _nodeId, - Node::QueryStage const _stage -) +void Driver::RetryQueryStageComplete(uint8 const _nodeId, Node::QueryStage const _stage) { MsgQueueItem item; item.m_command = MsgQueueCmd_QueryStageComplete; @@ -1017,9 +906,9 @@ void Driver::RetryQueryStageComplete m_sendMutex->Lock(); - for( list::iterator it = m_msgQueue[MsgQueue_Query].begin(); it != m_msgQueue[MsgQueue_Query].end(); ++it ) + for (list::iterator it = m_msgQueue[MsgQueue_Query].begin(); it != m_msgQueue[MsgQueue_Query].end(); ++it) { - if( *it == item ) + if (*it == item) { (*it).m_retry = true; break; @@ -1032,11 +921,7 @@ void Driver::RetryQueryStageComplete // // Queue a message to be sent to the Z-Wave PC Interface //----------------------------------------------------------------------------- -void Driver::SendMsg -( - Msg* _msg, - MsgQueue const _queue -) +void Driver::SendMsg(Internal::Msg* _msg, MsgQueue const _queue) { MsgQueueItem item; @@ -1046,52 +931,52 @@ void Driver::SendMsg _msg->SetHomeId(m_homeId); _msg->Finalize(); { - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode(_msg->GetTargetNodeId()) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_msg->GetTargetNodeId())) { /* if the node Supports the Security Class - check if this message is meant to be encapsulated */ - if ( node->GetCommandClass(Security::StaticGetCommandClassId()) ) + if (node->GetCommandClass(Internal::CC::Security::StaticGetCommandClassId())) { - CommandClass *cc = node->GetCommandClass(_msg->GetSendingCommandClass()); - if ( (cc) && (cc->IsSecured()) ) + Internal::CC::CommandClass *cc = node->GetCommandClass(_msg->GetSendingCommandClass()); + if ((cc) && (cc->IsSecured())) { - Log::Write( LogLevel_Detail, GetNodeNumber( _msg ), "Setting Encryption Flag on Message For Command Class %s", cc->GetCommandClassName().c_str()); + Log::Write(LogLevel_Detail, GetNodeNumber(_msg), "Setting Encryption Flag on Message For Command Class %s", cc->GetCommandClassName().c_str()); item.m_msg->setEncrypted(); } } // If the message is for a sleeping node, we queue it in the node itself. - if( !node->IsListeningDevice() ) + if (!node->IsListeningDevice()) { - if( WakeUp* wakeUp = static_cast( node->GetCommandClass( WakeUp::StaticGetCommandClassId() ) ) ) + if (Internal::CC::WakeUp* wakeUp = static_cast(node->GetCommandClass(Internal::CC::WakeUp::StaticGetCommandClassId()))) { - if( !wakeUp->IsAwake() ) + if (!wakeUp->IsAwake()) { - Log::Write( LogLevel_Detail, "" ); + Log::Write(LogLevel_Detail, ""); // Handle saving multi-step controller commands - if( m_currentControllerCommand != NULL ) + if (m_currentControllerCommand != NULL) { - Log::Write( LogLevel_Detail, GetNodeNumber( _msg ), "Queuing (%s) %s", c_sendQueueNames[MsgQueue_Controller], c_controllerCommandNames[m_currentControllerCommand->m_controllerCommand] ); + Log::Write(LogLevel_Detail, GetNodeNumber(_msg), "Queuing (%s) %s", c_sendQueueNames[MsgQueue_Controller], c_controllerCommandNames[m_currentControllerCommand->m_controllerCommand]); delete _msg; item.m_command = MsgQueueCmd_Controller; - item.m_cci = new ControllerCommandItem( *m_currentControllerCommand ); + item.m_cci = new ControllerCommandItem(*m_currentControllerCommand); item.m_msg = NULL; - UpdateControllerState( ControllerState_Sleeping ); + UpdateControllerState(ControllerState_Sleeping); } else { - Log::Write( LogLevel_Detail, GetNodeNumber( _msg ), "Queuing (%s) %s", c_sendQueueNames[MsgQueue_WakeUp], _msg->GetAsString().c_str() ); + Log::Write(LogLevel_Detail, GetNodeNumber(_msg), "Queuing (%s) %s", c_sendQueueNames[MsgQueue_WakeUp], _msg->GetAsString().c_str()); } - wakeUp->QueueMsg( item ); + wakeUp->QueueMsg(item); return; } } } } } - Log::Write( LogLevel_Detail, GetNodeNumber( _msg ), "Queuing (%s) %s", c_sendQueueNames[_queue], _msg->GetAsString().c_str() ); + Log::Write(LogLevel_Detail, GetNodeNumber(_msg), "Queuing (%s) %s", c_sendQueueNames[_queue], _msg->GetAsString().c_str()); m_sendMutex->Lock(); - m_msgQueue[_queue].push_back( item ); + m_msgQueue[_queue].push_back(item); m_queueEvent[_queue]->Set(); m_sendMutex->Unlock(); } @@ -1100,101 +985,99 @@ void Driver::SendMsg // // Transmit a queued message to the Z-Wave controller //----------------------------------------------------------------------------- -bool Driver::WriteNextMsg -( - MsgQueue const _queue -) +bool Driver::WriteNextMsg(MsgQueue const _queue) { // There are messages to send, so get the one at the front of the queue m_sendMutex->Lock(); MsgQueueItem item = m_msgQueue[_queue].front(); - if( MsgQueueCmd_SendMsg == item.m_command ) + if (MsgQueueCmd_SendMsg == item.m_command) { // Send a message m_currentMsg = item.m_msg; m_currentMsgQueueSource = _queue; m_msgQueue[_queue].pop_front(); - if( m_msgQueue[_queue].empty() ) + if (m_msgQueue[_queue].empty()) { m_queueEvent[_queue]->Reset(); } - if (m_nonceReportSent > 0) { + if (m_nonceReportSent > 0) + { MsgQueueItem item_new; item_new.m_command = MsgQueueCmd_SendMsg; item_new.m_nodeId = item.m_msg->GetTargetNodeId(); item_new.m_retry = item.m_retry; - item_new.m_msg = new Msg(*item.m_msg); + item_new.m_msg = new Internal::Msg(*item.m_msg); m_msgQueue[_queue].push_front(item_new); m_queueEvent[_queue]->Set(); } m_sendMutex->Unlock(); - return WriteMsg( "WriteNextMsg" ); + return WriteMsg("WriteNextMsg"); } - else if( MsgQueueCmd_QueryStageComplete == item.m_command ) + else if (MsgQueueCmd_QueryStageComplete == item.m_command) { // Move to the next query stage m_currentMsg = NULL; Node::QueryStage stage = item.m_queryStage; m_msgQueue[_queue].pop_front(); - if( m_msgQueue[_queue].empty() ) + if (m_msgQueue[_queue].empty()) { m_queueEvent[_queue]->Reset(); } m_sendMutex->Unlock(); - Node* node = GetNodeUnsafe( item.m_nodeId ); - if( node != NULL ) + Node* node = GetNodeUnsafe(item.m_nodeId); + if (node != NULL) { - Log::Write( LogLevel_Detail, node->GetNodeId(), "Query Stage Complete (%s)", node->GetQueryStageName( stage ).c_str() ); - if( !item.m_retry ) + Log::Write(LogLevel_Detail, node->GetNodeId(), "Query Stage Complete (%s)", node->GetQueryStageName(stage).c_str()); + if (!item.m_retry) { - node->QueryStageComplete( stage ); + node->QueryStageComplete(stage); } node->AdvanceQueries(); return true; } } - else if( MsgQueueCmd_Controller == item.m_command ) + else if (MsgQueueCmd_Controller == item.m_command) { // Run a multi-step controller command m_currentControllerCommand = item.m_cci; m_sendMutex->Unlock(); // Figure out if done with command - if ( m_currentControllerCommand->m_controllerCommandDone ) + if (m_currentControllerCommand->m_controllerCommandDone) { m_sendMutex->Lock(); m_msgQueue[_queue].pop_front(); - if( m_msgQueue[_queue].empty() ) + if (m_msgQueue[_queue].empty()) { m_queueEvent[_queue]->Reset(); } m_sendMutex->Unlock(); - if( m_currentControllerCommand->m_controllerCallback ) + if (m_currentControllerCommand->m_controllerCallback) { - m_currentControllerCommand->m_controllerCallback( m_currentControllerCommand->m_controllerState, m_currentControllerCommand->m_controllerReturnError, m_currentControllerCommand->m_controllerCallbackContext ); + m_currentControllerCommand->m_controllerCallback(m_currentControllerCommand->m_controllerState, m_currentControllerCommand->m_controllerReturnError, m_currentControllerCommand->m_controllerCallbackContext); } m_sendMutex->Lock(); delete m_currentControllerCommand; m_currentControllerCommand = NULL; m_sendMutex->Unlock(); } - else if( m_currentControllerCommand->m_controllerState == ControllerState_Normal ) + else if (m_currentControllerCommand->m_controllerState == ControllerState_Normal) { DoControllerCommand(); } - else if( m_currentControllerCommand->m_controllerStateChanged ) + else if (m_currentControllerCommand->m_controllerStateChanged) { - if( m_currentControllerCommand->m_controllerCallback ) + if (m_currentControllerCommand->m_controllerCallback) { - m_currentControllerCommand->m_controllerCallback( m_currentControllerCommand->m_controllerState, m_currentControllerCommand->m_controllerReturnError, m_currentControllerCommand->m_controllerCallbackContext ); + m_currentControllerCommand->m_controllerCallback(m_currentControllerCommand->m_controllerState, m_currentControllerCommand->m_controllerReturnError, m_currentControllerCommand->m_controllerCallbackContext); } m_currentControllerCommand->m_controllerStateChanged = false; } else { - Log::Write( LogLevel_Info, "WriteNextMsg Controller nothing to do" ); + Log::Write(LogLevel_Info, "WriteNextMsg Controller nothing to do"); m_sendMutex->Lock(); m_queueEvent[_queue]->Reset(); m_sendMutex->Unlock(); @@ -1204,7 +1087,7 @@ bool Driver::WriteNextMsg else if (MsgQueueCmd_ReloadNode == item.m_command) { m_msgQueue[_queue].pop_front(); - if( m_msgQueue[_queue].empty() ) + if (m_msgQueue[_queue].empty()) { m_queueEvent[_queue]->Reset(); } @@ -1214,8 +1097,7 @@ bool Driver::WriteNextMsg /* this will reload the Node, ignoring any cache that exists etc */ ReloadNode(item.m_nodeId); return true; -} - + } return false; } @@ -1224,14 +1106,11 @@ bool Driver::WriteNextMsg // // Transmit the current message to the Z-Wave controller //----------------------------------------------------------------------------- -bool Driver::WriteMsg -( - string const &msg -) +bool Driver::WriteMsg(string const &msg) { - if( !m_currentMsg ) + if (!m_currentMsg) { - Log::Write( LogLevel_Detail, GetNodeNumber( m_currentMsg ), "WriteMsg %s m_currentMsg=%08x", msg.c_str(), m_currentMsg ); + Log::Write(LogLevel_Detail, GetNodeNumber(m_currentMsg), "WriteMsg %s m_currentMsg=%08x", msg.c_str(), m_currentMsg); // We try not to hang when this happenes m_expectedCallbackId = 0; m_expectedCommandClassId = 0; @@ -1246,31 +1125,35 @@ bool Driver::WriteMsg */ uint8 attempts; uint8 nodeId; - if (m_nonceReportSent > 0) { + if (m_nonceReportSent > 0) + { attempts = m_nonceReportSentAttempt++; nodeId = m_nonceReportSent; - } else { + } + else + { attempts = m_currentMsg->GetSendAttempts(); nodeId = m_currentMsg->GetTargetNodeId(); } - LockGuard LG(m_nodeMutex); - Node* node = GetNode( nodeId ); - if( attempts >= m_currentMsg->GetMaxSendAttempts() || - (node != NULL && !node->IsNodeAlive() && !m_currentMsg->IsNoOperation() ) ) + Internal::LockGuard LG(m_nodeMutex); + Node* node = GetNode(nodeId); + if (attempts >= m_currentMsg->GetMaxSendAttempts() || (node != NULL && !node->IsNodeAlive() && !m_currentMsg->IsNoOperation())) { - if( node != NULL && !node->IsNodeAlive() ) + if (node != NULL && !node->IsNodeAlive()) { - Log::Write( LogLevel_Error, nodeId, "ERROR: Dropping command because node is presumed dead" ); + Log::Write(LogLevel_Error, nodeId, "ERROR: Dropping command because node is presumed dead"); } else { // That's it - already tried to send GetMaxSendAttempt() times. - Log::Write( LogLevel_Error, nodeId, "ERROR: Dropping command, expected response not received after %d attempt(s)", m_currentMsg->GetMaxSendAttempts() ); + Log::Write(LogLevel_Error, nodeId, "ERROR: Dropping command, expected response not received after %d attempt(s). Command: \"%s\"", + m_currentMsg->GetMaxSendAttempts(), + m_currentMsg->GetAsString().c_str()); } - if( m_currentControllerCommand != NULL ) + if (m_currentControllerCommand != NULL) { /* its a ControllerCommand that is failed */ - UpdateControllerState( ControllerState_Error, ControllerError_Failed); + UpdateControllerState(ControllerState_Error, ControllerError_Failed); } @@ -1279,7 +1162,7 @@ bool Driver::WriteMsg return false; } - if (( attempts != 0) && (m_nonceReportSent == 0)) + if ((attempts != 0) && (m_nonceReportSent == 0)) { // this is not the first attempt, so increment the callback id before sending m_currentMsg->UpdateCallbackId(); @@ -1290,11 +1173,15 @@ bool Driver::WriteMsg * */ - if (m_nonceReportSent == 0) { - if (m_currentMsg->isEncrypted() && !m_currentMsg->isNonceRecieved()) { - m_currentMsg->SetSendAttempts( ++attempts ); - } else if (!m_currentMsg->isEncrypted() ) { - m_currentMsg->SetSendAttempts( ++attempts ); + if (m_nonceReportSent == 0) + { + if (m_currentMsg->isEncrypted() && !m_currentMsg->isNonceRecieved()) + { + m_currentMsg->SetSendAttempts(++attempts); + } + else if (!m_currentMsg->isEncrypted()) + { + m_currentMsg->SetSendAttempts(++attempts); } m_expectedCallbackId = m_currentMsg->GetCallbackId(); m_expectedCommandClassId = m_currentMsg->GetExpectedCommandClassId(); @@ -1303,33 +1190,41 @@ bool Driver::WriteMsg m_waitingForAck = true; } string attemptsstr = ""; - if( attempts > 1 ) + if (attempts > 1) { char buf[15]; - snprintf( buf, sizeof(buf), "Attempt %d, ", attempts ); + snprintf(buf, sizeof(buf), "Attempt %d, ", attempts); attemptsstr = buf; m_retries++; - if( node != NULL ) + if (node != NULL) { node->m_retries++; } } - Log::Write( LogLevel_Detail, "" ); + Log::Write(LogLevel_Detail, ""); - if (m_nonceReportSent > 0) { + if (m_nonceReportSent > 0 && node != NULL) + { /* send a new NONCE report */ SendNonceKey(m_nonceReportSent, node->GenerateNonceKey()); - } else if (m_currentMsg->isEncrypted()) { - if (m_currentMsg->isNonceRecieved()) { - Log::Write( LogLevel_Info, nodeId, "Processing (%s) Encrypted message (%sCallback ID=0x%.2x, Expected Reply=0x%.2x) - %s", c_sendQueueNames[m_currentMsgQueueSource], attemptsstr.c_str(), m_expectedCallbackId, m_expectedReply, m_currentMsg->GetAsString().c_str() ); + } + else if (m_currentMsg->isEncrypted()) + { + if (m_currentMsg->isNonceRecieved()) + { + Log::Write(LogLevel_Info, nodeId, "Processing (%s) Encrypted message (%sCallback ID=0x%.2x, Expected Reply=0x%.2x) - %s", c_sendQueueNames[m_currentMsgQueueSource], attemptsstr.c_str(), m_expectedCallbackId, m_expectedReply, m_currentMsg->GetAsString().c_str()); SendEncryptedMessage(); - } else { - Log::Write( LogLevel_Info, nodeId, "Processing (%s) Nonce Request message (%sCallback ID=0x%.2x, Expected Reply=0x%.2x)", c_sendQueueNames[m_currentMsgQueueSource], attemptsstr.c_str(), m_expectedCallbackId, m_expectedReply); + } + else + { + Log::Write(LogLevel_Info, nodeId, "Processing (%s) Nonce Request message (%sCallback ID=0x%.2x, Expected Reply=0x%.2x)", c_sendQueueNames[m_currentMsgQueueSource], attemptsstr.c_str(), m_expectedCallbackId, m_expectedReply); SendNonceRequest(m_currentMsg->GetLogText()); } - } else { - Log::Write( LogLevel_Info, nodeId, "Sending (%s) message (%sCallback ID=0x%.2x, Expected Reply=0x%.2x) - %s", c_sendQueueNames[m_currentMsgQueueSource], attemptsstr.c_str(), m_expectedCallbackId, m_expectedReply, m_currentMsg->GetAsString().c_str() ); + } + else + { + Log::Write(LogLevel_Info, nodeId, "Sending (%s) message (%sCallback ID=0x%.2x, Expected Reply=0x%.2x) - %s", c_sendQueueNames[m_currentMsgQueueSource], attemptsstr.c_str(), m_expectedCallbackId, m_expectedReply, m_currentMsg->GetAsString().c_str()); uint32 bytesWritten = m_controller->Write(m_currentMsg->GetBuffer(), m_currentMsg->GetLength()); if (bytesWritten == 0) @@ -1348,20 +1243,20 @@ bool Driver::WriteMsg } m_writeCnt++; - if( nodeId == 0xff ) + if (nodeId == 0xff) { m_broadcastWriteCnt++; // not accurate since library uses 0xff for the controller too } else { - if( node != NULL ) + if (node != NULL) { node->m_sentCnt++; node->m_sentTS.SetTime(); - if( m_expectedReply == FUNC_ID_APPLICATION_COMMAND_HANDLER ) + if (m_expectedReply == FUNC_ID_APPLICATION_COMMAND_HANDLER) { - CommandClass *cc = node->GetCommandClass(m_expectedCommandClassId); - if( cc != NULL ) + Internal::CC::CommandClass *cc = node->GetCommandClass(m_expectedCommandClassId); + if (cc != NULL) { cc->SentCntIncr(); } @@ -1375,12 +1270,10 @@ bool Driver::WriteMsg // // Delete the current message //----------------------------------------------------------------------------- -void Driver::RemoveCurrentMsg -( -) +void Driver::RemoveCurrentMsg() { - Log::Write( LogLevel_Detail, GetNodeNumber( m_currentMsg ), "Removing current message" ); - if( m_currentMsg != NULL) + Log::Write(LogLevel_Detail, GetNodeNumber(m_currentMsg), "Removing current message"); + if (m_currentMsg != NULL) { delete m_currentMsg; m_currentMsg = NULL; @@ -1399,54 +1292,50 @@ void Driver::RemoveCurrentMsg // // Move messages for a sleeping device to its wake-up queue //----------------------------------------------------------------------------- -bool Driver::MoveMessagesToWakeUpQueue -( - uint8 const _targetNodeId, - bool const _move -) +bool Driver::MoveMessagesToWakeUpQueue(uint8 const _targetNodeId, bool const _move) { // If the target node is one that goes to sleep, transfer // all messages for it to its Wake-Up queue. - if( Node* node = GetNodeUnsafe(_targetNodeId) ) + if (Node* node = GetNodeUnsafe(_targetNodeId)) { - if( !node->IsListeningDevice() && !node->IsFrequentListeningDevice() && _targetNodeId != m_Controller_nodeId ) + if (!node->IsListeningDevice() && !node->IsFrequentListeningDevice() && _targetNodeId != m_Controller_nodeId) { - if( WakeUp* wakeUp = static_cast( node->GetCommandClass( WakeUp::StaticGetCommandClassId() ) ) ) + if (Internal::CC::WakeUp* wakeUp = static_cast(node->GetCommandClass(Internal::CC::WakeUp::StaticGetCommandClassId()))) { // Mark the node as asleep - wakeUp->SetAwake( false ); + wakeUp->SetAwake(false); // If we need to save the messages - if( _move ) + if (_move) { // Move all messages for this node to the wake-up queue m_sendMutex->Lock(); // See if we are working on a controller command - if( m_currentControllerCommand ) + if (m_currentControllerCommand) { // Don't save controller message as it will be recreated RemoveCurrentMsg(); } // Then try the current message first - if( m_currentMsg ) + if (m_currentMsg) { - if( _targetNodeId == m_currentMsg->GetTargetNodeId() ) + if (_targetNodeId == m_currentMsg->GetTargetNodeId()) { // This message is for the unresponsive node // We do not move any "Wake Up No More Information" // commands or NoOperations to the pending queue. - if( !m_currentMsg->IsWakeUpNoMoreInformationCommand() && !m_currentMsg->IsNoOperation() ) + if (!m_currentMsg->IsWakeUpNoMoreInformationCommand() && !m_currentMsg->IsNoOperation()) { - Log::Write( LogLevel_Info, _targetNodeId, "Node not responding - moving message to Wake-Up queue: %s", m_currentMsg->GetAsString().c_str() ); + Log::Write(LogLevel_Info, _targetNodeId, "Node not responding - moving message to Wake-Up queue: %s", m_currentMsg->GetAsString().c_str()); /* reset the sendAttempts */ m_currentMsg->SetSendAttempts(0); MsgQueueItem item; item.m_command = MsgQueueCmd_SendMsg; item.m_msg = m_currentMsg; - wakeUp->QueueMsg( item ); + wakeUp->QueueMsg(item); } else { @@ -1463,26 +1352,26 @@ bool Driver::MoveMessagesToWakeUpQueue } // Now the message queues - for( int i=0; i::iterator it = m_msgQueue[i].begin(); - while( it != m_msgQueue[i].end() ) + while (it != m_msgQueue[i].end()) { bool remove = false; MsgQueueItem const& item = *it; - if( MsgQueueCmd_SendMsg == item.m_command ) + if (MsgQueueCmd_SendMsg == item.m_command) { - if( _targetNodeId == item.m_msg->GetTargetNodeId() ) + if (_targetNodeId == item.m_msg->GetTargetNodeId()) { // This message is for the unresponsive node // We do not move any "Wake Up No More Information" // commands or NoOperations to the pending queue. - if( !item.m_msg->IsWakeUpNoMoreInformationCommand() && !item.m_msg->IsNoOperation() ) + if (!item.m_msg->IsWakeUpNoMoreInformationCommand() && !item.m_msg->IsNoOperation()) { - Log::Write( LogLevel_Info, item.m_msg->GetTargetNodeId(), "Node not responding - moving message to Wake-Up queue: %s", item.m_msg->GetAsString().c_str() ); + Log::Write(LogLevel_Info, item.m_msg->GetTargetNodeId(), "Node not responding - moving message to Wake-Up queue: %s", item.m_msg->GetAsString().c_str()); /* reset any SendAttempts */ item.m_msg->SetSendAttempts(0); - wakeUp->QueueMsg( item ); + wakeUp->QueueMsg(item); } else { @@ -1491,30 +1380,30 @@ bool Driver::MoveMessagesToWakeUpQueue remove = true; } } - if( MsgQueueCmd_QueryStageComplete == item.m_command ) + if (MsgQueueCmd_QueryStageComplete == item.m_command) { - if( _targetNodeId == item.m_nodeId ) + if (_targetNodeId == item.m_nodeId) { - Log::Write( LogLevel_Info, _targetNodeId, "Node not responding - moving QueryStageComplete command to Wake-Up queue" ); + Log::Write(LogLevel_Info, _targetNodeId, "Node not responding - moving QueryStageComplete command to Wake-Up queue"); - wakeUp->QueueMsg( item ); + wakeUp->QueueMsg(item); remove = true; } } - if( MsgQueueCmd_Controller == item.m_command ) + if (MsgQueueCmd_Controller == item.m_command) { - if( _targetNodeId == item.m_cci->m_controllerCommandNode ) + if (_targetNodeId == item.m_cci->m_controllerCommandNode) { - Log::Write( LogLevel_Info, _targetNodeId, "Node not responding - moving controller command to Wake-Up queue: %s", c_controllerCommandNames[item.m_cci->m_controllerCommand] ); + Log::Write(LogLevel_Info, _targetNodeId, "Node not responding - moving controller command to Wake-Up queue: %s", c_controllerCommandNames[item.m_cci->m_controllerCommand]); - wakeUp->QueueMsg( item ); + wakeUp->QueueMsg(item); remove = true; } } - if( remove ) + if (remove) { - it = m_msgQueue[i].erase( it ); + it = m_msgQueue[i].erase(it); } else { @@ -1523,21 +1412,21 @@ bool Driver::MoveMessagesToWakeUpQueue } // If the queue is now empty, we need to clear its event - if( m_msgQueue[i].empty() ) + if (m_msgQueue[i].empty()) { m_queueEvent[i]->Reset(); } } - if( m_currentControllerCommand ) + if (m_currentControllerCommand) { // Put command back on queue so it will be cleaned up - UpdateControllerState( ControllerState_Sleeping ); + UpdateControllerState(ControllerState_Sleeping); MsgQueueItem item; item.m_command = MsgQueueCmd_Controller; - item.m_cci = new ControllerCommandItem( *m_currentControllerCommand ); + item.m_cci = new ControllerCommandItem(*m_currentControllerCommand); m_currentControllerCommand = item.m_cci; - m_msgQueue[MsgQueue_Controller].push_back( item ); + m_msgQueue[MsgQueue_Controller].push_back(item); m_queueEvent[MsgQueue_Controller]->Set(); } @@ -1559,55 +1448,50 @@ bool Driver::MoveMessagesToWakeUpQueue // For messages that return a ZW_SEND_DATA response, process the results here // If it is a non-listeing (sleeping) node return true. //----------------------------------------------------------------------------- -bool Driver::HandleErrorResponse -( - uint8 const _error, - uint8 const _nodeId, - char const* _funcStr, - bool _sleepCheck // = 0 -) +bool Driver::HandleErrorResponse(uint8 const _error, uint8 const _nodeId, char const* _funcStr, bool _sleepCheck // = 0 + ) { // Only called with a ZW_SEND_DATA error response. We count and output the message here. - if( _error == TRANSMIT_COMPLETE_NOROUTE ) + if (_error == TRANSMIT_COMPLETE_NOROUTE) { m_badroutes++; - Log::Write( LogLevel_Info, _nodeId, "ERROR: %s failed. No route available.", _funcStr ); + Log::Write(LogLevel_Info, _nodeId, "ERROR: %s failed. No route available.", _funcStr); } - else if( _error == TRANSMIT_COMPLETE_NO_ACK ) + else if (_error == TRANSMIT_COMPLETE_NO_ACK) { m_noack++; - Log::Write( LogLevel_Info, _nodeId, "WARNING: %s failed. No ACK received - device may be asleep.", _funcStr ); - if( m_currentMsg ) + Log::Write(LogLevel_Info, _nodeId, "WARNING: %s failed. No ACK received - device may be asleep.", _funcStr); + if (m_currentMsg) { // In case the failure is due to the target being a sleeping node, we // first try to move its pending messages to its wake-up queue. - if( MoveMessagesToWakeUpQueue( m_currentMsg->GetTargetNodeId(), _sleepCheck ) ) + if (MoveMessagesToWakeUpQueue(m_currentMsg->GetTargetNodeId(), _sleepCheck)) { return true; } - Log::Write( LogLevel_Warning, _nodeId, "WARNING: Device is not a sleeping node." ); + Log::Write(LogLevel_Warning, _nodeId, "WARNING: Device is not a sleeping node."); } } - else if( _error == TRANSMIT_COMPLETE_FAIL ) + else if (_error == TRANSMIT_COMPLETE_FAIL) { m_netbusy++; - Log::Write( LogLevel_Info, _nodeId, "ERROR: %s failed. Network is busy.", _funcStr ); + Log::Write(LogLevel_Info, _nodeId, "ERROR: %s failed. Network is busy.", _funcStr); } - else if( _error == TRANSMIT_COMPLETE_NOT_IDLE ) + else if (_error == TRANSMIT_COMPLETE_NOT_IDLE) { m_notidle++; - Log::Write( LogLevel_Info, _nodeId, "ERROR: %s failed. Network is busy.", _funcStr ); + Log::Write(LogLevel_Info, _nodeId, "ERROR: %s failed. Network is busy.", _funcStr); } - else if ( _error == TRANSMIT_COMPLETE_VERIFIED ) + else if (_error == TRANSMIT_COMPLETE_VERIFIED) { m_txverified++; - Log::Write( LogLevel_Info, _nodeId, "ERROR: %s failed. Transmit Verified.", _funcStr ); + Log::Write(LogLevel_Info, _nodeId, "ERROR: %s failed. Transmit Verified.", _funcStr); } - if( Node* node = GetNodeUnsafe( _nodeId ) ) + if (Node* node = GetNodeUnsafe(_nodeId)) { - if( ++node->m_errors >= 3 ) + if (++node->m_errors >= 3) { - node->SetNodeAlive( false ); + node->SetNodeAlive(false); } } return false; @@ -1617,32 +1501,30 @@ bool Driver::HandleErrorResponse // // Identify controller (as opposed to node) commands...especially blocking ones //----------------------------------------------------------------------------- -void Driver::CheckCompletedNodeQueries -( -) +void Driver::CheckCompletedNodeQueries() { - Log::Write( LogLevel_Warning, "CheckCompletedNodeQueries m_allNodesQueried=%d m_awakeNodesQueried=%d", m_allNodesQueried, m_awakeNodesQueried ); - if( !m_allNodesQueried ) + Log::Write(LogLevel_Warning, "CheckCompletedNodeQueries m_allNodesQueried=%d m_awakeNodesQueried=%d", m_allNodesQueried, m_awakeNodesQueried); + if (!m_allNodesQueried) { bool all = true; bool sleepingOnly = true; bool deadFound = false; { - LockGuard LG(m_nodeMutex); - for( int i=0; i<256; ++i ) + Internal::LockGuard LG(m_nodeMutex); + for (int i = 0; i < 256; ++i) { - if( m_nodes[i] ) + if (m_nodes[i]) { - if ( m_nodes[i]->GetCurrentQueryStage() != Node::QueryStage_Complete ) + if (m_nodes[i]->GetCurrentQueryStage() != Node::QueryStage_Complete) { - if( !m_nodes[i]->IsNodeAlive() ) + if (!m_nodes[i]->IsNodeAlive()) { deadFound = true; continue; } all = false; - if( m_nodes[i]->IsListeningDevice() ) + if (m_nodes[i]->IsListeningDevice()) { sleepingOnly = false; } @@ -1651,37 +1533,37 @@ void Driver::CheckCompletedNodeQueries } } - Log::Write( LogLevel_Warning, "CheckCompletedNodeQueries all=%d, deadFound=%d sleepingOnly=%d", all, deadFound, sleepingOnly ); - if( all ) + Log::Write(LogLevel_Warning, "CheckCompletedNodeQueries all=%d, deadFound=%d sleepingOnly=%d", all, deadFound, sleepingOnly); + if (all) { - if( deadFound ) + if (deadFound) { // only dead nodes left to query - Log::Write( LogLevel_Info, " Node query processing complete except for dead nodes." ); - Notification* notification = new Notification( Notification::Type_AllNodesQueriedSomeDead ); - notification->SetHomeAndNodeIds( m_homeId, 0xff ); - QueueNotification( notification ); + Log::Write(LogLevel_Info, " Node query processing complete except for dead nodes."); + Notification* notification = new Notification(Notification::Type_AllNodesQueriedSomeDead); + notification->SetHomeAndNodeIds(m_homeId, 0xff); + QueueNotification(notification); } else { // no sleeping nodes, no dead nodes and no more nodes in the queue, so...All done - Log::Write( LogLevel_Info, " Node query processing complete." ); - Notification* notification = new Notification( Notification::Type_AllNodesQueried ); - notification->SetHomeAndNodeIds( m_homeId, 0xff ); - QueueNotification( notification ); + Log::Write(LogLevel_Info, " Node query processing complete."); + Notification* notification = new Notification(Notification::Type_AllNodesQueried); + notification->SetHomeAndNodeIds(m_homeId, 0xff); + QueueNotification(notification); } m_awakeNodesQueried = true; m_allNodesQueried = true; } - else if( sleepingOnly ) + else if (sleepingOnly) { - if (!m_awakeNodesQueried ) + if (!m_awakeNodesQueried) { // only sleeping nodes remain, so signal awake nodes queried complete - Log::Write( LogLevel_Info, " Node query processing complete except for sleeping nodes." ); - Notification* notification = new Notification( Notification::Type_AwakeNodesQueried ); - notification->SetHomeAndNodeIds( m_homeId, 0xff ); - QueueNotification( notification ); + Log::Write(LogLevel_Info, " Node query processing complete except for sleeping nodes."); + Notification* notification = new Notification(Notification::Type_AwakeNodesQueried); + notification->SetHomeAndNodeIds(m_homeId, 0xff); + QueueNotification(notification); m_awakeNodesQueried = true; } } @@ -1693,37 +1575,25 @@ void Driver::CheckCompletedNodeQueries // // Determine if the reply is from the node we are expecting. //----------------------------------------------------------------------------- -bool Driver::IsExpectedReply -( - const uint8 _nodeId -) +bool Driver::IsExpectedReply(const uint8 _nodeId) { // Accept all controller commands or where the protocol doesn't identify the actual node - if( m_expectedNodeId == 255 || _nodeId == 0 ) + if (m_expectedNodeId == 255 || _nodeId == 0) { return true; } // Accept all messages that do not convey source node identification. - if( m_expectedReply == FUNC_ID_ZW_GET_NODE_PROTOCOL_INFO || - m_expectedReply == FUNC_ID_ZW_REQUEST_NODE_INFO || - m_expectedReply == FUNC_ID_ZW_GET_ROUTING_INFO || - m_expectedReply == FUNC_ID_ZW_ASSIGN_RETURN_ROUTE || - m_expectedReply == FUNC_ID_ZW_DELETE_RETURN_ROUTE || - m_expectedReply == FUNC_ID_ZW_SEND_DATA || - m_expectedReply == FUNC_ID_ZW_SEND_NODE_INFORMATION || - m_expectedReply == FUNC_ID_ZW_REQUEST_NODE_NEIGHBOR_UPDATE || - m_expectedReply == FUNC_ID_ZW_ENABLE_SUC || - m_expectedReply == FUNC_ID_ZW_SET_SUC_NODE_ID || - m_expectedReply == FUNC_ID_ZW_REQUEST_NODE_NEIGHBOR_UPDATE_OPTIONS ) + if (m_expectedReply == FUNC_ID_ZW_GET_NODE_PROTOCOL_INFO || m_expectedReply == FUNC_ID_ZW_REQUEST_NODE_INFO || m_expectedReply == FUNC_ID_ZW_GET_ROUTING_INFO || m_expectedReply == FUNC_ID_ZW_ASSIGN_RETURN_ROUTE || m_expectedReply == FUNC_ID_ZW_DELETE_RETURN_ROUTE || m_expectedReply == FUNC_ID_ZW_SEND_DATA || m_expectedReply == FUNC_ID_ZW_SEND_NODE_INFORMATION || m_expectedReply == FUNC_ID_ZW_REQUEST_NODE_NEIGHBOR_UPDATE || m_expectedReply == FUNC_ID_ZW_ENABLE_SUC + || m_expectedReply == FUNC_ID_ZW_SET_SUC_NODE_ID || m_expectedReply == FUNC_ID_ZW_REQUEST_NODE_NEIGHBOR_UPDATE_OPTIONS) { return true; } // Accept if source message contains node info and it is from the one we are expecting - if( m_expectedNodeId == _nodeId ) + if (m_expectedNodeId == _nodeId) { return true; } - Log::Write( LogLevel_Detail, "IsExpectedReply: m_expectedNodeId = %d m_expectedReply = %02x", m_expectedNodeId, m_expectedReply ); + Log::Write(LogLevel_Detail, "IsExpectedReply: m_expectedNodeId = %d m_expectedReply = %02x", m_expectedNodeId, m_expectedReply); return false; } //----------------------------------------------------------------------------- @@ -1734,166 +1604,164 @@ bool Driver::IsExpectedReply // // Read data from the serial port //----------------------------------------------------------------------------- -bool Driver::ReadMsg -( -) +bool Driver::ReadMsg() { uint8 buffer[1024]; - memset(buffer, 0, sizeof(uint8)* 1024); + memset(buffer, 0, sizeof(uint8) * 1024); - if( !m_controller->Read( buffer, 1 ) ) + if (!m_controller->Read(buffer, 1)) { // Nothing to read return false; } - switch( buffer[0] ) + switch (buffer[0]) { - case SOF: - { - m_SOFCnt++; - if( m_waitingForAck ) + case SOF: { - // This can happen on any normal network when a transmission overlaps an unexpected - // reception and the data in the buffer doesn't contain the ACK. The controller will - // notice and send us a CAN to retransmit. - Log::Write( LogLevel_Detail, "Unsolicited message received while waiting for ACK." ); - m_ACKWaiting++; - } + m_SOFCnt++; + if (m_waitingForAck) + { + // This can happen on any normal network when a transmission overlaps an unexpected + // reception and the data in the buffer doesn't contain the ACK. The controller will + // notice and send us a CAN to retransmit. + Log::Write(LogLevel_Detail, "Unsolicited message received while waiting for ACK."); + m_ACKWaiting++; + } - // Read the length byte. Keep trying until we get it. - m_controller->SetSignalThreshold( 1 ); - int32 response = Wait::Single( m_controller, 50 ); - if( response < 0 ) - { - Log::Write( LogLevel_Warning, "WARNING: 50ms passed without finding the length byte...aborting frame read"); - m_readAborts++; - break; - } + // Read the length byte. Keep trying until we get it. + m_controller->SetSignalThreshold(1); + int32 response = Internal::Platform::Wait::Single(m_controller, 50); + if (response < 0) + { + Log::Write(LogLevel_Warning, "WARNING: 50ms passed without finding the length byte...aborting frame read"); + m_readAborts++; + break; + } - m_controller->Read( &buffer[1], 1 ); - m_controller->SetSignalThreshold( buffer[1] ); - if( Wait::Single( m_controller, 500 ) < 0 ) - { - Log::Write( LogLevel_Warning, "WARNING: 500ms passed without reading the rest of the frame...aborting frame read" ); - m_readAborts++; - m_controller->SetSignalThreshold( 1 ); - break; - } + m_controller->Read(&buffer[1], 1); + m_controller->SetSignalThreshold(buffer[1]); + if (Internal::Platform::Wait::Single(m_controller, 500) < 0) + { + Log::Write(LogLevel_Warning, "WARNING: 500ms passed without reading the rest of the frame...aborting frame read"); + m_readAborts++; + m_controller->SetSignalThreshold(1); + break; + } - m_controller->Read( &buffer[2], buffer[1] ); - m_controller->SetSignalThreshold( 1 ); + m_controller->Read(&buffer[2], buffer[1]); + m_controller->SetSignalThreshold(1); - uint32 length = buffer[1] + 2; + uint32 length = buffer[1] + 2; - // Log the data - string str = ""; - for( uint32 i=0; iWrite( &ack, 1 ); - m_readCnt++; + if (buffer[length - 1] == checksum) + { + // Checksum correct - send ACK + uint8 ack = ACK; + m_controller->Write(&ack, 1); + m_readCnt++; - // Process the received message - ProcessMsg( &buffer[2], length-2 ); - } - else - { - Log::Write( LogLevel_Warning, nodeId, "WARNING: Checksum incorrect - sending NAK" ); - m_badChecksum++; - uint8 nak = NAK; - m_controller->Write( &nak, 1 ); - m_controller->Purge(); + // Process the received message + ProcessMsg(&buffer[2], length - 2); + } + else + { + Log::Write(LogLevel_Warning, nodeId, "WARNING: Checksum incorrect - sending NAK"); + m_badChecksum++; + uint8 nak = NAK; + m_controller->Write(&nak, 1); + m_controller->Purge(); + } + break; } - break; - } - case CAN: - { - // This is the other side of an unsolicited ACK. As mentioned there if we receive a message - // just after we transmitted one, the controller will notice and tell us to retransmit here. - // Don't increment the transmission counter as it is possible the message will never get out - // on very busy networks with lots of unsolicited messages being received. Increase the amount - // of retries but only up to a limit so we don't stay here forever. - Log::Write( LogLevel_Detail, GetNodeNumber( m_currentMsg ), "CAN received...triggering resend" ); - m_CANCnt++; - if( m_currentMsg != NULL ) - { - m_currentMsg->SetMaxSendAttempts( m_currentMsg->GetMaxSendAttempts() + 1 ); - } - else + case CAN: { - Log::Write( LogLevel_Warning, "m_currentMsg was NULL when trying to set MaxSendAttempts" ); - Log::QueueDump(); + // This is the other side of an unsolicited ACK. As mentioned there if we receive a message + // just after we transmitted one, the controller will notice and tell us to retransmit here. + // Don't increment the transmission counter as it is possible the message will never get out + // on very busy networks with lots of unsolicited messages being received. Increase the amount + // of retries but only up to a limit so we don't stay here forever. + Log::Write(LogLevel_Detail, GetNodeNumber(m_currentMsg), "CAN received...triggering resend"); + m_CANCnt++; + if (m_currentMsg != NULL) + { + m_currentMsg->SetMaxSendAttempts(m_currentMsg->GetMaxSendAttempts() + 1); + } + else + { + Log::Write(LogLevel_Warning, "m_currentMsg was NULL when trying to set MaxSendAttempts"); + Log::QueueDump(); + } + WriteMsg("CAN"); + break; } - WriteMsg( "CAN" ); - break; - } - case NAK: - { - Log::Write( LogLevel_Warning, GetNodeNumber( m_currentMsg ), "WARNING: NAK received...triggering resend" ); - m_NAKCnt++; - WriteMsg( "NAK" ); - break; - } - - case ACK: - { - m_ACKCnt++; - m_waitingForAck = false; - if( m_currentMsg == NULL ) + case NAK: { - Log::Write( LogLevel_StreamDetail, 255, " ACK received" ); + Log::Write(LogLevel_Warning, GetNodeNumber(m_currentMsg), "WARNING: NAK received...triggering resend"); + m_NAKCnt++; + WriteMsg("NAK"); + break; } - else + + case ACK: { - Log::Write( LogLevel_StreamDetail, GetNodeNumber( m_currentMsg ), " ACK received CallbackId 0x%.2x Reply 0x%.2x", m_expectedCallbackId, m_expectedReply ); - if( ( 0 == m_expectedCallbackId ) && ( 0 == m_expectedReply ) ) + m_ACKCnt++; + m_waitingForAck = false; + if (m_currentMsg == NULL) { - // Remove the message from the queue, now that it has been acknowledged. - RemoveCurrentMsg(); + Log::Write(LogLevel_StreamDetail, 255, " ACK received"); + } + else + { + Log::Write(LogLevel_StreamDetail, GetNodeNumber(m_currentMsg), " ACK received CallbackId 0x%.2x Reply 0x%.2x", m_expectedCallbackId, m_expectedReply); + if ((0 == m_expectedCallbackId) && (0 == m_expectedReply)) + { + // Remove the message from the queue, now that it has been acknowledged. + RemoveCurrentMsg(); + } } + break; } - break; - } - default: - { - Log::Write( LogLevel_Warning, "WARNING: Out of frame flow! (0x%.2x). Sending NAK.", buffer[0] ); - m_OOFCnt++; - uint8 nak = NAK; - m_controller->Write( &nak, 1 ); - m_controller->Purge(); - break; - } + default: + { + Log::Write(LogLevel_Warning, "WARNING: Out of frame flow! (0x%.2x). Sending NAK.", buffer[0]); + m_OOFCnt++; + uint8 nak = NAK; + m_controller->Write(&nak, 1); + m_controller->Purge(); + break; + } } return true; @@ -1903,24 +1771,22 @@ bool Driver::ReadMsg // // Process data received from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::ProcessMsg -( - uint8* _data, - uint8 _length -) +void Driver::ProcessMsg(uint8* _data, uint8 _length) { bool handleCallback = true; bool wasencrypted = false; //uint8 nodeId = GetNodeNumber( m_currentMsg ); - if ((REQUEST == _data[0]) && - (Security::StaticGetCommandClassId() == _data[5])) { + if ((REQUEST == _data[0]) && FUNC_ID_APPLICATION_COMMAND_HANDLER == _data[1] && (Internal::CC::Security::StaticGetCommandClassId() == _data[5])) + { /* if this message is a NONCE Report - Then just Trigger the Encrypted Send */ - if (SecurityCmd_NonceReport == _data[6]) { - Log::Write(LogLevel_Info, _data[3], "Received SecurityCmd_NonceReport from node %d", _data[3] ); + if (Internal::CC::SecurityCmd_NonceReport == _data[6]) + { + Log::Write(LogLevel_Info, _data[3], "Received SecurityCmd_NonceReport from node %d", _data[3]); /* handle possible resends of NONCE_REPORT messages.... See Issue #931 */ - if (!m_currentMsg) { + if (!m_currentMsg) + { Log::Write(LogLevel_Warning, _data[3], "Received a NonceReport from node, but no pending messages. Dropping.."); return; } @@ -1931,15 +1797,20 @@ void Driver::ProcessMsg return; /* if this is a NONCE Get - Then call to the CC directly, process it, and then bail out. */ - } else if (SecurityCmd_NonceGet == _data[6]) { - Log::Write(LogLevel_Info, _data[3], "Received SecurityCmd_NonceGet from node %d", _data[3] ); + } + else if (Internal::CC::SecurityCmd_NonceGet == _data[6]) + { + Log::Write(LogLevel_Info, _data[3], "Received SecurityCmd_NonceGet from node %d", _data[3]); { uint8 *nonce = NULL; - LockGuard LG(m_nodeMutex); - Node* node = GetNode( _data[3] ); - if( node ) { + Internal::LockGuard LG(m_nodeMutex); + Node* node = GetNode(_data[3]); + if (node) + { nonce = node->GenerateNonceKey(); - } else { + } + else + { Log::Write(LogLevel_Warning, _data[3], "Couldn't Generate Nonce Key for Node %d", _data[3]); return; } @@ -1951,7 +1822,9 @@ void Driver::ProcessMsg return; /* if this message is encrypted, decrypt it first */ - } else if ((SecurityCmd_MessageEncap == _data[6]) || (SecurityCmd_MessageEncapNonceGet == _data[6])) { + } + else if ((Internal::CC::SecurityCmd_MessageEncap == _data[6]) || (Internal::CC::SecurityCmd_MessageEncapNonceGet == _data[6])) + { uint8 _newdata[256]; uint8 SecurityCmd = _data[6]; uint8 *_nonce; @@ -1962,20 +1835,25 @@ void Driver::ProcessMsg /* make sure the Node Exists, and it has the Security CC */ { - LockGuard LG(m_nodeMutex); - Node* node = GetNode( _data[3] ); - if( node ) { - _nonce = node->GetNonceKey(_data[_data[4]-4]); - if (!_nonce) { + Internal::LockGuard LG(m_nodeMutex); + Node* node = GetNode(_data[3]); + if (node) + { + _nonce = node->GetNonceKey(_data[_data[4] - 4]); + if (!_nonce) + { Log::Write(LogLevel_Warning, _data[3], "Could Not Retrieve Nonce for Node %d", _data[3]); return; } - } else { + } + else + { Log::Write(LogLevel_Warning, _data[3], "Can't Find Node %d for Encrypted Message", _data[3]); return; } } - if (DecryptBuffer(&_data[5], _data[4]+1, this, _data[3], this->GetControllerNodeId(), _nonce, &_newdata[0])) { + if (Internal::DecryptBuffer(&_data[5], _data[4] + 1, this, _data[3], this->GetControllerNodeId(), _nonce, &_newdata[0])) + { /* Ok - _newdata now contains the decrypted packet */ /* copy it back to the _data packet for processing */ /* New Length - See Decrypt Packet for why these numbers*/ @@ -1986,14 +1864,17 @@ void Driver::ProcessMsg //PrintHex("Decrypted Packet", _data, _data[4]+5); /* if the Node has something else to send, it will encrypt a message and send it as a MessageEncapNonceGet */ - if (SecurityCmd_MessageEncapNonceGet == SecurityCmd ) + if (Internal::CC::SecurityCmd_MessageEncapNonceGet == SecurityCmd) { - Log::Write(LogLevel_Info, _data[3], "Received SecurityCmd_MessageEncapNonceGet from node %d - Sending New Nonce", _data[3] ); - LockGuard LG(m_nodeMutex); - Node* node = GetNode( _data[3] ); - if( node ) { + Log::Write(LogLevel_Info, _data[3], "Received SecurityCmd_MessageEncapNonceGet from node %d - Sending New Nonce", _data[3]); + Internal::LockGuard LG(m_nodeMutex); + Node* node = GetNode(_data[3]); + if (node) + { _nonce = node->GenerateNonceKey(); - } else { + } + else + { Log::Write(LogLevel_Warning, _data[3], "Couldn't Generate Nonce Key for Node %d", _data[3]); return; } @@ -2002,16 +1883,21 @@ void Driver::ProcessMsg wasencrypted = true; - } else { + } + else + { /* if the Node has something else to send, it will encrypt a message and send it as a MessageEncapNonceGet */ - if (SecurityCmd_MessageEncapNonceGet == SecurityCmd ) + if (Internal::CC::SecurityCmd_MessageEncapNonceGet == SecurityCmd) { - Log::Write(LogLevel_Info, _data[3], "Received SecurityCmd_MessageEncapNonceGet from node %d - Sending New Nonce", _data[3] ); - LockGuard LG(m_nodeMutex); - Node* node = GetNode( _data[3] ); - if( node ) { + Log::Write(LogLevel_Info, _data[3], "Received SecurityCmd_MessageEncapNonceGet from node %d - Sending New Nonce", _data[3]); + Internal::LockGuard LG(m_nodeMutex); + Node* node = GetNode(_data[3]); + if (node) + { _nonce = node->GenerateNonceKey(); - } else { + } + else + { Log::Write(LogLevel_Warning, _data[3], "Couldn't Generate Nonce Key for Node %d", _data[3]); return; } @@ -2026,452 +1912,458 @@ void Driver::ProcessMsg } } - - if( RESPONSE == _data[0] ) + if ( RESPONSE == _data[0]) { - switch( _data[1] ) - { - case FUNC_ID_SERIAL_API_GET_INIT_DATA: - { - Log::Write( LogLevel_Detail, "" ); - HandleSerialAPIGetInitDataResponse( _data ); - break; - } - case FUNC_ID_ZW_GET_CONTROLLER_CAPABILITIES: - { - Log::Write( LogLevel_Detail, "" ); - HandleGetControllerCapabilitiesResponse( _data ); - break; - } - case FUNC_ID_SERIAL_API_GET_CAPABILITIES: - { - Log::Write( LogLevel_Detail, "" ); - HandleGetSerialAPICapabilitiesResponse( _data ); - break; - } - case FUNC_ID_SERIAL_API_SOFT_RESET: - { - Log::Write( LogLevel_Detail, "" ); - HandleSerialAPISoftResetResponse( _data ); - break; - } - case FUNC_ID_ZW_SEND_DATA: - { - HandleSendDataResponse( _data, false ); - handleCallback = false; // Skip the callback handling - a subsequent FUNC_ID_ZW_SEND_DATA request will deal with that - break; - } - case FUNC_ID_ZW_GET_VERSION: - { - Log::Write( LogLevel_Detail, "" ); - HandleGetVersionResponse( _data ); - break; - } - case FUNC_ID_ZW_GET_RANDOM: - { - Log::Write( LogLevel_Detail, "" ); - HandleGetRandomResponse( _data ); - break; - } - case FUNC_ID_SERIAL_API_SETUP: - { - Log::Write( LogLevel_Detail, "" ); - HandleSerialAPISetupResponse( _data ); - break; - } - case FUNC_ID_ZW_MEMORY_GET_ID: - { - Log::Write( LogLevel_Detail, "" ); - HandleMemoryGetIdResponse( _data ); - break; - } - case FUNC_ID_ZW_GET_NODE_PROTOCOL_INFO: - { - Log::Write( LogLevel_Detail, "" ); - HandleGetNodeProtocolInfoResponse( _data ); - break; - } - case FUNC_ID_ZW_REPLICATION_SEND_DATA: + switch (_data[1]) { - HandleSendDataResponse( _data, true ); - handleCallback = false; // Skip the callback handling - a subsequent FUNC_ID_ZW_REPLICATION_SEND_DATA request will deal with that - break; - } - case FUNC_ID_ZW_ASSIGN_RETURN_ROUTE: - { - Log::Write( LogLevel_Detail, "" ); - if( !HandleAssignReturnRouteResponse( _data ) ) + case FUNC_ID_SERIAL_API_GET_INIT_DATA: { - m_expectedCallbackId = _data[2]; // The callback message won't be coming, so we force the transaction to complete - m_expectedReply = 0; - m_expectedCommandClassId = 0; - m_expectedNodeId = 0; + Log::Write(LogLevel_Detail, ""); + HandleSerialAPIGetInitDataResponse(_data); + break; } - break; - } - case FUNC_ID_ZW_DELETE_RETURN_ROUTE: - { - Log::Write( LogLevel_Detail, "" ); - if( !HandleDeleteReturnRouteResponse( _data ) ) + case FUNC_ID_ZW_GET_CONTROLLER_CAPABILITIES: { - m_expectedCallbackId = _data[2]; // The callback message won't be coming, so we force the transaction to complete - m_expectedReply = 0; - m_expectedCommandClassId = 0; - m_expectedNodeId = 0; + Log::Write(LogLevel_Detail, ""); + HandleGetControllerCapabilitiesResponse(_data); + break; } - break; - } - case FUNC_ID_ZW_ENABLE_SUC: - { - Log::Write( LogLevel_Detail, "" ); - HandleEnableSUCResponse( _data ); - break; - } - case FUNC_ID_ZW_REQUEST_NETWORK_UPDATE: - { - Log::Write( LogLevel_Detail, "" ); - if( !HandleNetworkUpdateResponse( _data ) ) + case FUNC_ID_SERIAL_API_GET_CAPABILITIES: { - m_expectedCallbackId = _data[2]; // The callback message won't be coming, so we force the transaction to complete - m_expectedReply = 0; - m_expectedCommandClassId = 0; - m_expectedNodeId = 0; + Log::Write(LogLevel_Detail, ""); + HandleGetSerialAPICapabilitiesResponse(_data); + break; } - break; - } - case FUNC_ID_ZW_SET_SUC_NODE_ID: - { - Log::Write( LogLevel_Detail, "" ); - HandleSetSUCNodeIdResponse( _data ); - break; - } - case FUNC_ID_ZW_GET_SUC_NODE_ID: - { - Log::Write( LogLevel_Detail, "" ); - HandleGetSUCNodeIdResponse( _data ); - break; - } - case FUNC_ID_ZW_REQUEST_NODE_INFO: - { - Log::Write( LogLevel_Detail, "" ); - if( _data[2] ) + case FUNC_ID_SERIAL_API_SOFT_RESET: { - Log::Write( LogLevel_Info, _data[3], "FUNC_ID_ZW_REQUEST_NODE_INFO Request successful." ); + Log::Write(LogLevel_Detail, ""); + HandleSerialAPISoftResetResponse(_data); + break; } - else + case FUNC_ID_ZW_SEND_DATA: { - Log::Write( LogLevel_Info, _data[3], "FUNC_ID_ZW_REQUEST_NODE_INFO Request failed." ); + HandleSendDataResponse(_data, false); + handleCallback = false; // Skip the callback handling - a subsequent FUNC_ID_ZW_SEND_DATA request will deal with that + break; } - break; - } - case FUNC_ID_ZW_REMOVE_FAILED_NODE_ID: - { - Log::Write( LogLevel_Detail, "" ); - if( !HandleRemoveFailedNodeResponse( _data ) ) + case FUNC_ID_ZW_GET_VERSION: { - m_expectedCallbackId = _data[2]; // The callback message won't be coming, so we force the transaction to complete - m_expectedReply = 0; - m_expectedCommandClassId = 0; - m_expectedNodeId = 0; + Log::Write(LogLevel_Detail, ""); + HandleGetVersionResponse(_data); + break; } - break; - } - case FUNC_ID_ZW_IS_FAILED_NODE_ID: - { - Log::Write( LogLevel_Detail, "" ); - HandleIsFailedNodeResponse( _data ); - break; - } - case FUNC_ID_ZW_REPLACE_FAILED_NODE: - { - Log::Write( LogLevel_Detail, "" ); - if( !HandleReplaceFailedNodeResponse( _data ) ) + case FUNC_ID_ZW_GET_RANDOM: { - m_expectedCallbackId = _data[2]; // The callback message won't be coming, so we force the transaction to complete - m_expectedReply = 0; - m_expectedCommandClassId = 0; - m_expectedNodeId = 0; + Log::Write(LogLevel_Detail, ""); + HandleGetRandomResponse(_data); + break; } - break; - } - case FUNC_ID_ZW_GET_ROUTING_INFO: - { - Log::Write( LogLevel_Detail, "" ); - HandleGetRoutingInfoResponse( _data ); - break; - } - case FUNC_ID_ZW_R_F_POWER_LEVEL_SET: - { - Log::Write( LogLevel_Detail, "" ); - HandleRfPowerLevelSetResponse( _data ); - break; - } - case FUNC_ID_ZW_READ_MEMORY: - { - Log::Write( LogLevel_Detail, "" ); - HandleReadMemoryResponse( _data ); - break; - } - case FUNC_ID_SERIAL_API_SET_TIMEOUTS: - { - Log::Write( LogLevel_Detail, "" ); - HandleSerialApiSetTimeoutsResponse( _data ); - break; - } - case FUNC_ID_MEMORY_GET_BYTE: - { - Log::Write( LogLevel_Detail, "" ); - HandleMemoryGetByteResponse( _data ); - break; - } - case FUNC_ID_ZW_GET_VIRTUAL_NODES: - { - Log::Write( LogLevel_Detail, "" ); - HandleGetVirtualNodesResponse( _data ); - break; - } - case FUNC_ID_ZW_SET_SLAVE_LEARN_MODE: - { - Log::Write( LogLevel_Detail, "" ); - if( !HandleSetSlaveLearnModeResponse( _data ) ) + case FUNC_ID_SERIAL_API_SETUP: { - m_expectedCallbackId = _data[2]; // The callback message won't be coming, so we force the transaction to complete - m_expectedReply = 0; - m_expectedCommandClassId = 0; - m_expectedNodeId = 0; + Log::Write(LogLevel_Detail, ""); + HandleSerialAPISetupResponse(_data); + break; } - break; - } - case FUNC_ID_ZW_SEND_SLAVE_NODE_INFO: - { - Log::Write( LogLevel_Detail, "" ); - if( !HandleSendSlaveNodeInfoResponse( _data ) ) + case FUNC_ID_ZW_MEMORY_GET_ID: { - m_expectedCallbackId = _data[2]; // The callback message won't be coming, so we force the transaction to complete - m_expectedReply = 0; - m_expectedCommandClassId = 0; - m_expectedNodeId = 0; + Log::Write(LogLevel_Detail, ""); + HandleMemoryGetIdResponse(_data); + break; + } + case FUNC_ID_ZW_GET_NODE_PROTOCOL_INFO: + { + Log::Write(LogLevel_Detail, ""); + HandleGetNodeProtocolInfoResponse(_data); + break; + } + case FUNC_ID_ZW_REPLICATION_SEND_DATA: + { + HandleSendDataResponse(_data, true); + handleCallback = false; // Skip the callback handling - a subsequent FUNC_ID_ZW_REPLICATION_SEND_DATA request will deal with that + break; + } + case FUNC_ID_ZW_ASSIGN_RETURN_ROUTE: + { + Log::Write(LogLevel_Detail, ""); + if (!HandleAssignReturnRouteResponse(_data)) + { + m_expectedCallbackId = _data[2]; // The callback message won't be coming, so we force the transaction to complete + m_expectedReply = 0; + m_expectedCommandClassId = 0; + m_expectedNodeId = 0; + } + break; + } + case FUNC_ID_ZW_DELETE_RETURN_ROUTE: + { + Log::Write(LogLevel_Detail, ""); + if (!HandleDeleteReturnRouteResponse(_data)) + { + m_expectedCallbackId = _data[2]; // The callback message won't be coming, so we force the transaction to complete + m_expectedReply = 0; + m_expectedCommandClassId = 0; + m_expectedNodeId = 0; + } + break; + } + case FUNC_ID_ZW_ENABLE_SUC: + { + Log::Write(LogLevel_Detail, ""); + HandleEnableSUCResponse(_data); + break; + } + case FUNC_ID_ZW_REQUEST_NETWORK_UPDATE: + { + Log::Write(LogLevel_Detail, ""); + if (!HandleNetworkUpdateResponse(_data)) + { + m_expectedCallbackId = _data[2]; // The callback message won't be coming, so we force the transaction to complete + m_expectedReply = 0; + m_expectedCommandClassId = 0; + m_expectedNodeId = 0; + } + break; + } + case FUNC_ID_ZW_SET_SUC_NODE_ID: + { + Log::Write(LogLevel_Detail, ""); + HandleSetSUCNodeIdResponse(_data); + break; + } + case FUNC_ID_ZW_GET_SUC_NODE_ID: + { + Log::Write(LogLevel_Detail, ""); + HandleGetSUCNodeIdResponse(_data); + break; + } + case FUNC_ID_ZW_REQUEST_NODE_INFO: + { + // This code used _data[3] to log Node ID + // but FUNC_ID_ZW_REQUEST_NODE_INFO reply does not report back node number. + Log::Write(LogLevel_Detail, ""); + if (_data[2]) + { + + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), "FUNC_ID_ZW_REQUEST_NODE_INFO Request successful."); + } + else + { + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), "FUNC_ID_ZW_REQUEST_NODE_INFO Request failed."); + } + break; + } + case FUNC_ID_ZW_REMOVE_FAILED_NODE_ID: + { + Log::Write(LogLevel_Detail, ""); + if (!HandleRemoveFailedNodeResponse(_data)) + { + m_expectedCallbackId = _data[2]; // The callback message won't be coming, so we force the transaction to complete + m_expectedReply = 0; + m_expectedCommandClassId = 0; + m_expectedNodeId = 0; + } + break; + } + case FUNC_ID_ZW_IS_FAILED_NODE_ID: + { + Log::Write(LogLevel_Detail, ""); + HandleIsFailedNodeResponse(_data); + break; + } + case FUNC_ID_ZW_REPLACE_FAILED_NODE: + { + Log::Write(LogLevel_Detail, ""); + if (!HandleReplaceFailedNodeResponse(_data)) + { + m_expectedCallbackId = _data[2]; // The callback message won't be coming, so we force the transaction to complete + m_expectedReply = 0; + m_expectedCommandClassId = 0; + m_expectedNodeId = 0; + } + break; + } + case FUNC_ID_ZW_GET_ROUTING_INFO: + { + Log::Write(LogLevel_Detail, ""); + HandleGetRoutingInfoResponse(_data); + break; + } + case FUNC_ID_ZW_R_F_POWER_LEVEL_SET: + { + Log::Write(LogLevel_Detail, ""); + HandleRfPowerLevelSetResponse(_data); + break; + } + case FUNC_ID_ZW_READ_MEMORY: + { + Log::Write(LogLevel_Detail, ""); + HandleReadMemoryResponse(_data); + break; + } + case FUNC_ID_SERIAL_API_SET_TIMEOUTS: + { + Log::Write(LogLevel_Detail, ""); + HandleSerialApiSetTimeoutsResponse(_data); + break; + } + case FUNC_ID_MEMORY_GET_BYTE: + { + Log::Write(LogLevel_Detail, ""); + HandleMemoryGetByteResponse(_data); + break; + } + case FUNC_ID_ZW_GET_VIRTUAL_NODES: + { + Log::Write(LogLevel_Detail, ""); + HandleGetVirtualNodesResponse(_data); + break; + } + case FUNC_ID_ZW_SET_SLAVE_LEARN_MODE: + { + Log::Write(LogLevel_Detail, ""); + if (!HandleSetSlaveLearnModeResponse(_data)) + { + m_expectedCallbackId = _data[2]; // The callback message won't be coming, so we force the transaction to complete + m_expectedReply = 0; + m_expectedCommandClassId = 0; + m_expectedNodeId = 0; + } + break; + } + case FUNC_ID_ZW_SEND_SLAVE_NODE_INFO: + { + Log::Write(LogLevel_Detail, ""); + if (!HandleSendSlaveNodeInfoResponse(_data)) + { + m_expectedCallbackId = _data[2]; // The callback message won't be coming, so we force the transaction to complete + m_expectedReply = 0; + m_expectedCommandClassId = 0; + m_expectedNodeId = 0; + } + break; + } + /* Ignore these. They are manufacturer proprietary */ + case FUNC_ID_PROPRIETARY_0: + case FUNC_ID_PROPRIETARY_1: + case FUNC_ID_PROPRIETARY_2: + case FUNC_ID_PROPRIETARY_3: + case FUNC_ID_PROPRIETARY_4: + case FUNC_ID_PROPRIETARY_5: + case FUNC_ID_PROPRIETARY_6: + case FUNC_ID_PROPRIETARY_7: + case FUNC_ID_PROPRIETARY_8: + case FUNC_ID_PROPRIETARY_9: + case FUNC_ID_PROPRIETARY_A: + case FUNC_ID_PROPRIETARY_B: + case FUNC_ID_PROPRIETARY_C: + case FUNC_ID_PROPRIETARY_D: + case FUNC_ID_PROPRIETARY_E: + { + break; + } + default: + { + Log::Write(LogLevel_Detail, ""); + Log::Write(LogLevel_Info, "**TODO: handle response for 0x%.2x** Please report this message.", _data[1]); + break; } - break; - } - /* Ignore these. They are manufacturer proprietary */ - case FUNC_ID_PROPRIETARY_0: - case FUNC_ID_PROPRIETARY_1: - case FUNC_ID_PROPRIETARY_2: - case FUNC_ID_PROPRIETARY_3: - case FUNC_ID_PROPRIETARY_4: - case FUNC_ID_PROPRIETARY_5: - case FUNC_ID_PROPRIETARY_6: - case FUNC_ID_PROPRIETARY_7: - case FUNC_ID_PROPRIETARY_8: - case FUNC_ID_PROPRIETARY_9: - case FUNC_ID_PROPRIETARY_A: - case FUNC_ID_PROPRIETARY_B: - case FUNC_ID_PROPRIETARY_C: - case FUNC_ID_PROPRIETARY_D: - case FUNC_ID_PROPRIETARY_E: - { - break; - } - default: - { - Log::Write( LogLevel_Detail, "" ); - Log::Write( LogLevel_Info, "**TODO: handle response for 0x%.2x** Please report this message.", _data[1] ); - break; - } } } - else if( REQUEST == _data[0] ) + else if ( REQUEST == _data[0]) { - switch( _data[1] ) - { - case FUNC_ID_APPLICATION_COMMAND_HANDLER: - { - Log::Write( LogLevel_Detail, "" ); - HandleApplicationCommandHandlerRequest( _data, wasencrypted ); - break; - } - case FUNC_ID_ZW_SEND_DATA: - { - HandleSendDataRequest( _data, _length, false ); - break; - } - case FUNC_ID_ZW_REPLICATION_COMMAND_COMPLETE: + switch (_data[1]) { - if( m_controllerReplication ) + case FUNC_ID_APPLICATION_COMMAND_HANDLER: { - Log::Write( LogLevel_Detail, "" ); - m_controllerReplication->SendNextData(); + Log::Write(LogLevel_Detail, ""); + HandleApplicationCommandHandlerRequest(_data, wasencrypted); + break; + } + case FUNC_ID_ZW_SEND_DATA: + { + HandleSendDataRequest(_data, _length, false); + break; + } + case FUNC_ID_ZW_REPLICATION_COMMAND_COMPLETE: + { + if (m_controllerReplication) + { + Log::Write(LogLevel_Detail, ""); + m_controllerReplication->SendNextData(); + } + break; + } + case FUNC_ID_ZW_REPLICATION_SEND_DATA: + { + HandleSendDataRequest(_data, _length, true); + break; + } + case FUNC_ID_ZW_ASSIGN_RETURN_ROUTE: + { + Log::Write(LogLevel_Detail, ""); + HandleAssignReturnRouteRequest(_data); + break; + } + case FUNC_ID_ZW_DELETE_RETURN_ROUTE: + { + Log::Write(LogLevel_Detail, ""); + HandleDeleteReturnRouteRequest(_data); + break; + } + case FUNC_ID_ZW_SEND_NODE_INFORMATION: + { + Log::Write(LogLevel_Detail, ""); + HandleSendNodeInformationRequest(_data); + break; + } + case FUNC_ID_ZW_REQUEST_NODE_NEIGHBOR_UPDATE: + case FUNC_ID_ZW_REQUEST_NODE_NEIGHBOR_UPDATE_OPTIONS: + { + Log::Write(LogLevel_Detail, ""); + HandleNodeNeighborUpdateRequest(_data); + break; + } + case FUNC_ID_ZW_APPLICATION_UPDATE: + { + Log::Write(LogLevel_Detail, ""); + handleCallback = !HandleApplicationUpdateRequest(_data); + break; + } + case FUNC_ID_ZW_ADD_NODE_TO_NETWORK: + { + Log::Write(LogLevel_Detail, ""); + HandleAddNodeToNetworkRequest(_data); + break; + } + case FUNC_ID_ZW_REMOVE_NODE_FROM_NETWORK: + { + Log::Write(LogLevel_Detail, ""); + HandleRemoveNodeFromNetworkRequest(_data); + break; + } + case FUNC_ID_ZW_CREATE_NEW_PRIMARY: + { + Log::Write(LogLevel_Detail, ""); + HandleCreateNewPrimaryRequest(_data); + break; + } + case FUNC_ID_ZW_CONTROLLER_CHANGE: + { + Log::Write(LogLevel_Detail, ""); + HandleControllerChangeRequest(_data); + break; + } + case FUNC_ID_ZW_SET_LEARN_MODE: + { + Log::Write(LogLevel_Detail, ""); + HandleSetLearnModeRequest(_data); + break; + } + case FUNC_ID_ZW_REQUEST_NETWORK_UPDATE: + { + Log::Write(LogLevel_Detail, ""); + HandleNetworkUpdateRequest(_data); + break; + } + case FUNC_ID_ZW_REMOVE_FAILED_NODE_ID: + { + Log::Write(LogLevel_Detail, ""); + HandleRemoveFailedNodeRequest(_data); + break; + } + case FUNC_ID_ZW_REPLACE_FAILED_NODE: + { + Log::Write(LogLevel_Detail, ""); + HandleReplaceFailedNodeRequest(_data); + break; + } + case FUNC_ID_ZW_SET_SLAVE_LEARN_MODE: + { + Log::Write(LogLevel_Detail, ""); + HandleSetSlaveLearnModeRequest(_data); + break; + } + case FUNC_ID_ZW_SEND_SLAVE_NODE_INFO: + { + Log::Write(LogLevel_Detail, ""); + HandleSendSlaveNodeInfoRequest(_data); + break; + } + case FUNC_ID_APPLICATION_SLAVE_COMMAND_HANDLER: + { + Log::Write(LogLevel_Detail, ""); + HandleApplicationSlaveCommandRequest(_data); + break; + } + case FUNC_ID_PROMISCUOUS_APPLICATION_COMMAND_HANDLER: + { + Log::Write(LogLevel_Detail, ""); + HandlePromiscuousApplicationCommandHandlerRequest(_data); + break; + } + case FUNC_ID_ZW_SET_DEFAULT: + { + Log::Write(LogLevel_Detail, ""); + HandleSerialAPIResetRequest(_data); + break; + } + /* Ignore these. They are manufacturer proprietary */ + case FUNC_ID_PROPRIETARY_0: + case FUNC_ID_PROPRIETARY_1: + case FUNC_ID_PROPRIETARY_2: + case FUNC_ID_PROPRIETARY_3: + case FUNC_ID_PROPRIETARY_4: + case FUNC_ID_PROPRIETARY_5: + case FUNC_ID_PROPRIETARY_6: + case FUNC_ID_PROPRIETARY_7: + case FUNC_ID_PROPRIETARY_8: + case FUNC_ID_PROPRIETARY_9: + case FUNC_ID_PROPRIETARY_A: + case FUNC_ID_PROPRIETARY_B: + case FUNC_ID_PROPRIETARY_C: + case FUNC_ID_PROPRIETARY_D: + case FUNC_ID_PROPRIETARY_E: + { + break; + } + default: + { + Log::Write(LogLevel_Detail, ""); + Log::Write(LogLevel_Info, "**TODO: handle request for 0x%.2x** Please report this message.", _data[1]); + break; } - break; - } - case FUNC_ID_ZW_REPLICATION_SEND_DATA: - { - HandleSendDataRequest( _data, _length, true ); - break; - } - case FUNC_ID_ZW_ASSIGN_RETURN_ROUTE: - { - Log::Write( LogLevel_Detail, "" ); - HandleAssignReturnRouteRequest( _data ); - break; - } - case FUNC_ID_ZW_DELETE_RETURN_ROUTE: - { - Log::Write( LogLevel_Detail, "" ); - HandleDeleteReturnRouteRequest( _data ); - break; - } - case FUNC_ID_ZW_SEND_NODE_INFORMATION: - { - Log::Write( LogLevel_Detail, "" ); - HandleSendNodeInformationRequest( _data ); - break; - } - case FUNC_ID_ZW_REQUEST_NODE_NEIGHBOR_UPDATE: - case FUNC_ID_ZW_REQUEST_NODE_NEIGHBOR_UPDATE_OPTIONS: - { - Log::Write( LogLevel_Detail, "" ); - HandleNodeNeighborUpdateRequest( _data ); - break; - } - case FUNC_ID_ZW_APPLICATION_UPDATE: - { - Log::Write( LogLevel_Detail, "" ); - handleCallback = !HandleApplicationUpdateRequest( _data ); - break; - } - case FUNC_ID_ZW_ADD_NODE_TO_NETWORK: - { - Log::Write( LogLevel_Detail, "" ); - HandleAddNodeToNetworkRequest( _data ); - break; - } - case FUNC_ID_ZW_REMOVE_NODE_FROM_NETWORK: - { - Log::Write( LogLevel_Detail, "" ); - HandleRemoveNodeFromNetworkRequest( _data ); - break; - } - case FUNC_ID_ZW_CREATE_NEW_PRIMARY: - { - Log::Write( LogLevel_Detail, "" ); - HandleCreateNewPrimaryRequest( _data ); - break; - } - case FUNC_ID_ZW_CONTROLLER_CHANGE: - { - Log::Write( LogLevel_Detail, "" ); - HandleControllerChangeRequest( _data ); - break; - } - case FUNC_ID_ZW_SET_LEARN_MODE: - { - Log::Write( LogLevel_Detail, "" ); - HandleSetLearnModeRequest( _data ); - break; - } - case FUNC_ID_ZW_REQUEST_NETWORK_UPDATE: - { - Log::Write( LogLevel_Detail, "" ); - HandleNetworkUpdateRequest( _data ); - break; - } - case FUNC_ID_ZW_REMOVE_FAILED_NODE_ID: - { - Log::Write( LogLevel_Detail, "" ); - HandleRemoveFailedNodeRequest( _data ); - break; - } - case FUNC_ID_ZW_REPLACE_FAILED_NODE: - { - Log::Write( LogLevel_Detail, "" ); - HandleReplaceFailedNodeRequest( _data ); - break; - } - case FUNC_ID_ZW_SET_SLAVE_LEARN_MODE: - { - Log::Write( LogLevel_Detail, "" ); - HandleSetSlaveLearnModeRequest( _data ); - break; - } - case FUNC_ID_ZW_SEND_SLAVE_NODE_INFO: - { - Log::Write( LogLevel_Detail, "" ); - HandleSendSlaveNodeInfoRequest( _data ); - break; - } - case FUNC_ID_APPLICATION_SLAVE_COMMAND_HANDLER: - { - Log::Write( LogLevel_Detail, "" ); - HandleApplicationSlaveCommandRequest( _data ); - break; - } - case FUNC_ID_PROMISCUOUS_APPLICATION_COMMAND_HANDLER: - { - Log::Write( LogLevel_Detail, "" ); - HandlePromiscuousApplicationCommandHandlerRequest( _data ); - break; - } - case FUNC_ID_ZW_SET_DEFAULT: - { - Log::Write( LogLevel_Detail, "" ); - HandleSerialAPIResetRequest( _data ); - break; - } - /* Ignore these. They are manufacturer proprietary */ - case FUNC_ID_PROPRIETARY_0: - case FUNC_ID_PROPRIETARY_1: - case FUNC_ID_PROPRIETARY_2: - case FUNC_ID_PROPRIETARY_3: - case FUNC_ID_PROPRIETARY_4: - case FUNC_ID_PROPRIETARY_5: - case FUNC_ID_PROPRIETARY_6: - case FUNC_ID_PROPRIETARY_7: - case FUNC_ID_PROPRIETARY_8: - case FUNC_ID_PROPRIETARY_9: - case FUNC_ID_PROPRIETARY_A: - case FUNC_ID_PROPRIETARY_B: - case FUNC_ID_PROPRIETARY_C: - case FUNC_ID_PROPRIETARY_D: - case FUNC_ID_PROPRIETARY_E: - { - break; - } - default: - { - Log::Write( LogLevel_Detail, "" ); - Log::Write( LogLevel_Info, "**TODO: handle request for 0x%.2x** Please report this message.", _data[1] ); - break; - } } } // Generic callback handling - if( handleCallback ) + // This code used _data[3] in some parts to log Node ID, + // but not all serial data frames report back node number. + if (handleCallback) { - if( ( m_expectedCallbackId || m_expectedReply ) ) + if ((m_expectedCallbackId || m_expectedReply)) { - if( m_expectedCallbackId ) + if (m_expectedCallbackId) { - if( m_expectedCallbackId == _data[2] ) + if (m_expectedCallbackId == _data[2]) { - Log::Write( LogLevel_Detail, _data[3], " Expected callbackId was received" ); + Log::Write(LogLevel_Detail, GetNodeNumber(m_currentMsg), " Expected callbackId was received"); m_expectedCallbackId = 0; - } else if (_data[2] == 0x02 || _data[2] == 0x01) { + } + else if (_data[2] == 0x02 || _data[2] == 0x01) + { /* it was a NONCE request/reply. Drop it */ return; } } - if( m_expectedReply ) + if (m_expectedReply) { - if( m_expectedReply == _data[1] ) + if (m_expectedReply == _data[1]) { - if( m_expectedCommandClassId && ( m_expectedReply == FUNC_ID_APPLICATION_COMMAND_HANDLER ) ) + if (m_expectedCommandClassId && (m_expectedReply == FUNC_ID_APPLICATION_COMMAND_HANDLER)) { - if( m_expectedCallbackId == 0 && m_expectedCommandClassId == _data[5] && m_expectedNodeId == _data[3] ) + if (m_expectedCallbackId == 0 && m_expectedCommandClassId == _data[5] && m_expectedNodeId == _data[3]) { - Log::Write( LogLevel_Detail, _data[3], " Expected reply and command class was received" ); + Log::Write(LogLevel_Detail, _data[3], " Expected reply and command class was received"); m_waitingForAck = false; m_expectedReply = 0; m_expectedCommandClassId = 0; @@ -2480,27 +2372,27 @@ void Driver::ProcessMsg } else { - if( IsExpectedReply( _data[3] ) ) + if (IsExpectedReply(_data[3])) { - Log::Write( LogLevel_Detail, _data[3], " Expected reply was received" ); + Log::Write(LogLevel_Detail, GetNodeNumber(m_currentMsg), " Expected reply was received"); m_expectedReply = 0; m_expectedNodeId = 0; } } } } - if( !( m_expectedCallbackId || m_expectedReply ) ) + if (!(m_expectedCallbackId || m_expectedReply)) { - Log::Write( LogLevel_Detail, _data[3], " Message transaction complete" ); - Log::Write( LogLevel_Detail, "" ); + Log::Write(LogLevel_Detail, GetNodeNumber(m_currentMsg), " Message transaction complete"); + Log::Write(LogLevel_Detail, ""); - if( m_notifytransactions ) + if (m_notifytransactions) { - Notification* notification = new Notification( Notification::Type_Notification ); - notification->SetHomeAndNodeIds( m_homeId, _data[3] ); - notification->SetNotification( Notification::Code_MsgComplete ); - QueueNotification( notification ); + Notification* notification = new Notification(Notification::Type_Notification); + notification->SetHomeAndNodeIds(m_homeId, GetNodeNumber(m_currentMsg)); + notification->SetNotification(Notification::Code_MsgComplete); + QueueNotification(notification); } RemoveCurrentMsg(); } @@ -2512,28 +2404,26 @@ void Driver::ProcessMsg // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleGetVersionResponse -( - uint8* _data -) +void Driver::HandleGetVersionResponse(uint8* _data) { - m_libraryVersion = (char*)&_data[2]; + m_libraryVersion = (char*) &_data[2]; - m_libraryType = _data[m_libraryVersion.size()+3]; - if( m_libraryType < 9 ) + m_libraryType = _data[m_libraryVersion.size() + 3]; + if (m_libraryType < 9) { m_libraryTypeName = c_libraryTypeNames[m_libraryType]; } - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), "Received reply to FUNC_ID_ZW_GET_VERSION:" ); - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), " %s library, version %s", m_libraryTypeName.c_str(), m_libraryVersion.c_str() ); - if ( !((m_libraryType == ZW_LIB_CONTROLLER_STATIC ) || (m_libraryType == ZW_LIB_CONTROLLER)) ) { - Log::Write( LogLevel_Fatal, GetNodeNumber( m_currentMsg), "Z-Wave Interface is not a Supported Library Type: %s", m_libraryTypeName.c_str()); - Log::Write( LogLevel_Fatal, GetNodeNumber( m_currentMsg), "Z-Wave Interface should be a Static Controller Library Type"); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), "Received reply to FUNC_ID_ZW_GET_VERSION:"); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), " %s library, version %s", m_libraryTypeName.c_str(), m_libraryVersion.c_str()); + if (!((m_libraryType == ZW_LIB_CONTROLLER_STATIC) || (m_libraryType == ZW_LIB_CONTROLLER))) + { + Log::Write(LogLevel_Fatal, GetNodeNumber(m_currentMsg), "Z-Wave Interface is not a Supported Library Type: %s", m_libraryTypeName.c_str()); + Log::Write(LogLevel_Fatal, GetNodeNumber(m_currentMsg), "Z-Wave Interface should be a Static Controller Library Type"); { - Notification* notification = new Notification( Notification::Type_UserAlerts ); - notification->SetUserAlertNotification( Notification::Alert_UnsupportedController ); - QueueNotification( notification ); + Notification* notification = new Notification(Notification::Type_UserAlerts); + notification->SetUserAlertNotification(Notification::Alert_UnsupportedController); + QueueNotification(notification); } { Notification* notification = new Notification(Notification::Type_DriverFailed); @@ -2552,41 +2442,35 @@ void Driver::HandleGetVersionResponse // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleGetRandomResponse -( - uint8* _data -) +void Driver::HandleGetRandomResponse(uint8* _data) { - Log::Write( LogLevel_Info, "Received reply to FUNC_ID_ZW_GET_RANDOM: %s", _data[2] ? "true" : "false" ); + Log::Write(LogLevel_Info, "Received reply to FUNC_ID_ZW_GET_RANDOM: %s", _data[2] ? "true" : "false"); } -void Driver::HandleSerialAPISetupResponse -( - uint8* _data -) +void Driver::HandleSerialAPISetupResponse(uint8* _data) { // See INS13954 for description of FUNC_ID_SERIAL_API_SETUP with command // SERIAL_API_SETUP_CMD_TX_STATUS_REPORT // Note: SERIAL_API_SETUP can do more things than enable this report... - Log::Write( LogLevel_Info, "Received reply to FUNC_ID_SERIAL_API_SETUP"); + Log::Write(LogLevel_Info, "Received reply to FUNC_ID_SERIAL_API_SETUP"); switch (_data[0]) { - case 1: - Log::Write(LogLevel_Info, "Successfully enabled extended txStatusReport."); - m_hasExtendedTxStatus = true; - break; + case 1: + Log::Write(LogLevel_Info, "Successfully enabled extended txStatusReport."); + m_hasExtendedTxStatus = true; + break; - case 0: - Log::Write(LogLevel_Info, "Failed to enable extended txStatusReport. Controller might not support it."); - m_hasExtendedTxStatus = false; - break; + case 0: + Log::Write(LogLevel_Info, "Failed to enable extended txStatusReport. Controller might not support it."); + m_hasExtendedTxStatus = false; + break; - default: - Log::Write(LogLevel_Info, "FUNC_ID_SERIAL_API_SETUP returned unknown status: %u", _data[0]); - m_hasExtendedTxStatus = false; - break; + default: + Log::Write(LogLevel_Info, "FUNC_ID_SERIAL_API_SETUP returned unknown status: %u", _data[0]); + m_hasExtendedTxStatus = false; + break; } } @@ -2594,34 +2478,25 @@ void Driver::HandleSerialAPISetupResponse // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleGetControllerCapabilitiesResponse -( - uint8* _data -) +void Driver::HandleGetControllerCapabilitiesResponse(uint8* _data) { m_controllerCaps = _data[2]; - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), "Received reply to FUNC_ID_ZW_GET_CONTROLLER_CAPABILITIES:" ); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), "Received reply to FUNC_ID_ZW_GET_CONTROLLER_CAPABILITIES:"); char str[256]; - if( m_controllerCaps & ControllerCaps_SIS ) + if (m_controllerCaps & ControllerCaps_SIS) { - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), " There is a SUC ID Server (SIS) in this network." ); - snprintf( str, sizeof(str), " The PC controller is an inclusion %s%s%s", - ( m_controllerCaps & ControllerCaps_SUC ) ? "static update controller (SUC)" : "controller", - ( m_controllerCaps & ControllerCaps_OnOtherNetwork ) ? " which is using a Home ID from another network" : "", - ( m_controllerCaps & ControllerCaps_RealPrimary ) ? " and was the original primary before the SIS was added." : "." ); - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), str ); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), " There is a SUC ID Server (SIS) in this network."); + snprintf(str, sizeof(str), " The PC controller is an inclusion %s%s%s", (m_controllerCaps & ControllerCaps_SUC) ? "static update controller (SUC)" : "controller", (m_controllerCaps & ControllerCaps_OnOtherNetwork) ? " which is using a Home ID from another network" : "", (m_controllerCaps & ControllerCaps_RealPrimary) ? " and was the original primary before the SIS was added." : "."); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), str); } else { - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), " There is no SUC ID Server (SIS) in this network." ); - snprintf( str, sizeof(str), " The PC controller is a %s%s%s", - ( m_controllerCaps & ControllerCaps_Secondary ) ? "secondary" : "primary", - ( m_controllerCaps & ControllerCaps_SUC ) ? " static update controller (SUC)" : " controller", - ( m_controllerCaps & ControllerCaps_OnOtherNetwork ) ? " which is using a Home ID from another network." : "." ); - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), str ); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), " There is no SUC ID Server (SIS) in this network."); + snprintf(str, sizeof(str), " The PC controller is a %s%s%s", (m_controllerCaps & ControllerCaps_Secondary) ? "secondary" : "primary", (m_controllerCaps & ControllerCaps_SUC) ? " static update controller (SUC)" : " controller", (m_controllerCaps & ControllerCaps_OnOtherNetwork) ? " which is using a Home ID from another network." : "."); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), str); } } @@ -2629,94 +2504,84 @@ void Driver::HandleGetControllerCapabilitiesResponse // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleGetSerialAPICapabilitiesResponse -( - uint8* _data -) +void Driver::HandleGetSerialAPICapabilitiesResponse(uint8* _data) { - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), " Received reply to FUNC_ID_SERIAL_API_GET_CAPABILITIES" ); - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), " Serial API Version: %d.%d", _data[2], _data[3] ); - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), " Manufacturer ID: 0x%.2x%.2x", _data[4], _data[5] ); - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), " Product Type: 0x%.2x%.2x", _data[6], _data[7] ); - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), " Product ID: 0x%.2x%.2x", _data[8], _data[9] ); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), " Received reply to FUNC_ID_SERIAL_API_GET_CAPABILITIES"); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), " Serial API Version: %d.%d", _data[2], _data[3]); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), " Manufacturer ID: 0x%.2x%.2x", _data[4], _data[5]); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), " Product Type: 0x%.2x%.2x", _data[6], _data[7]); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), " Product ID: 0x%.2x%.2x", _data[8], _data[9]); // _data[10] to _data[41] are a 256-bit bitmask with one bit set for // each FUNC_ID_ method supported by the controller. // Bit 0 is FUNC_ID_ 1. So FUNC_ID_SERIAL_API_GET_CAPABILITIES (0x07) will be bit 6 of the first byte. m_serialAPIVersion[0] = _data[2]; m_serialAPIVersion[1] = _data[3]; - m_manufacturerId = ( ( (uint16)_data[4] )<<8) | (uint16)_data[5]; - m_productType = ( ( (uint16)_data[6] )<<8 ) | (uint16)_data[7]; - m_productId = ( ( (uint16)_data[8] )<<8 ) | (uint16)_data[9]; - memcpy( m_apiMask, &_data[10], sizeof( m_apiMask ) ); + m_manufacturerId = (((uint16) _data[4]) << 8) | (uint16) _data[5]; + m_productType = (((uint16) _data[6]) << 8) | (uint16) _data[7]; + m_productId = (((uint16) _data[8]) << 8) | (uint16) _data[9]; + memcpy(m_apiMask, &_data[10], sizeof(m_apiMask)); - if( IsBridgeController() ) + if (IsBridgeController()) { - SendMsg( new Msg( "FUNC_ID_ZW_GET_VIRTUAL_NODES", 0xff, REQUEST, FUNC_ID_ZW_GET_VIRTUAL_NODES, false ), MsgQueue_Command); + SendMsg(new Internal::Msg("FUNC_ID_ZW_GET_VIRTUAL_NODES", 0xff, REQUEST, FUNC_ID_ZW_GET_VIRTUAL_NODES, false), MsgQueue_Command); } - if( IsAPICallSupported( FUNC_ID_ZW_GET_RANDOM ) ) + if (IsAPICallSupported( FUNC_ID_ZW_GET_RANDOM)) { - Msg *msg = new Msg( "FUNC_ID_ZW_GET_RANDOM", 0xff, REQUEST, FUNC_ID_ZW_GET_RANDOM, false ); - msg->Append( 32 ); // 32 bytes - SendMsg( msg, MsgQueue_Command ); + Internal::Msg *msg = new Internal::Msg("FUNC_ID_ZW_GET_RANDOM", 0xff, REQUEST, FUNC_ID_ZW_GET_RANDOM, false); + msg->Append(32); // 32 bytes + SendMsg(msg, MsgQueue_Command); } - if( IsAPICallSupported( FUNC_ID_SERIAL_API_SETUP ) ) + if (IsAPICallSupported( FUNC_ID_SERIAL_API_SETUP)) { - Msg *msg = new Msg( "FUNC_ID_SERIAL_API_SETUP", 0xff, REQUEST, FUNC_ID_SERIAL_API_SETUP, false ); - msg->Append( SERIAL_API_SETUP_CMD_TX_STATUS_REPORT ); - msg->Append( 1 ); - SendMsg( msg, MsgQueue_Command ); + Internal::Msg *msg = new Internal::Msg("FUNC_ID_SERIAL_API_SETUP", 0xff, REQUEST, FUNC_ID_SERIAL_API_SETUP, false); + msg->Append( SERIAL_API_SETUP_CMD_TX_STATUS_REPORT); + msg->Append(1); + SendMsg(msg, MsgQueue_Command); } - - SendMsg( new Msg( "FUNC_ID_SERIAL_API_GET_INIT_DATA", 0xff, REQUEST, FUNC_ID_SERIAL_API_GET_INIT_DATA, false ), MsgQueue_Command); - if( !IsBridgeController() ) + SendMsg(new Internal::Msg("FUNC_ID_SERIAL_API_GET_INIT_DATA", 0xff, REQUEST, FUNC_ID_SERIAL_API_GET_INIT_DATA, false), MsgQueue_Command); + if (!IsBridgeController()) { - Msg* msg = new Msg( "FUNC_ID_SERIAL_API_SET_TIMEOUTS", 0xff, REQUEST, FUNC_ID_SERIAL_API_SET_TIMEOUTS, false ); - msg->Append( ACK_TIMEOUT / 10 ); - msg->Append( BYTE_TIMEOUT / 10 ); - SendMsg( msg, MsgQueue_Command ); + Internal::Msg* msg = new Internal::Msg("FUNC_ID_SERIAL_API_SET_TIMEOUTS", 0xff, REQUEST, FUNC_ID_SERIAL_API_SET_TIMEOUTS, false); + msg->Append( ACK_TIMEOUT / 10); + msg->Append( BYTE_TIMEOUT / 10); + SendMsg(msg, MsgQueue_Command); } - Msg* msg = new Msg( "FUNC_ID_SERIAL_API_APPL_NODE_INFORMATION", 0xff, REQUEST, FUNC_ID_SERIAL_API_APPL_NODE_INFORMATION, false, false ); - msg->Append( APPLICATION_NODEINFO_LISTENING ); - msg->Append( 0x02 ); // Generic Static Controller - msg->Append( 0x01 ); // Specific Static PC Controller + Internal::Msg* msg = new Internal::Msg("FUNC_ID_SERIAL_API_APPL_NODE_INFORMATION", 0xff, REQUEST, FUNC_ID_SERIAL_API_APPL_NODE_INFORMATION, false, false); + msg->Append( APPLICATION_NODEINFO_LISTENING); + msg->Append(0x02); // Generic Static Controller + msg->Append(0x01); // Specific Static PC Controller /* get a list of Advertised Command Classes */ - list advertisedCommandClasses = CommandClasses::GetAdvertisedCommandClasses(); - msg->Append( (uint8)advertisedCommandClasses.size() ); // Length + list advertisedCommandClasses = Internal::CC::CommandClasses::GetAdvertisedCommandClasses(); + msg->Append((uint8) advertisedCommandClasses.size()); // Length for (list::iterator it = advertisedCommandClasses.begin(); it != advertisedCommandClasses.end(); ++it) msg->Append(*it); - SendMsg( msg, MsgQueue_Command ); + SendMsg(msg, MsgQueue_Command); } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleSerialAPISoftResetResponse -( - uint8* _data -) +void Driver::HandleSerialAPISoftResetResponse(uint8* _data) { - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), "Received reply to Soft Reset." ); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), "Received reply to Soft Reset."); } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleSerialAPIResetRequest -( - uint8* _data -) +void Driver::HandleSerialAPIResetRequest(uint8* _data) { - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), "Received reply to complete Controller Reset." ); - if( m_controllerResetEvent != NULL ) + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), "Received reply to complete Controller Reset."); + if (m_controllerResetEvent != NULL) { m_controllerResetEvent->Set(); m_controllerResetEvent = NULL; @@ -2727,38 +2592,32 @@ void Driver::HandleSerialAPIResetRequest // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleEnableSUCResponse -( - uint8* _data -) +void Driver::HandleEnableSUCResponse(uint8* _data) { - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), "Received reply to Enable SUC." ); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), "Received reply to Enable SUC."); } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- -bool Driver::HandleNetworkUpdateResponse -( - uint8* _data -) +bool Driver::HandleNetworkUpdateResponse(uint8* _data) { bool res = true; ControllerState state = ControllerState_InProgress; - if( _data[2] ) + if (_data[2]) { - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), "Received reply to FUNC_ID_ZW_REQUEST_NETWORK_UPDATE - command in progress" ); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), "Received reply to FUNC_ID_ZW_REQUEST_NETWORK_UPDATE - command in progress"); } else { // Failed - Log::Write( LogLevel_Warning, GetNodeNumber( m_currentMsg ), "WARNING: Received reply to FUNC_ID_ZW_REQUEST_NETWORK_UPDATE - command failed" ); + Log::Write(LogLevel_Warning, GetNodeNumber(m_currentMsg), "WARNING: Received reply to FUNC_ID_ZW_REQUEST_NETWORK_UPDATE - command failed"); state = ControllerState_Failed; res = false; } - UpdateControllerState( state ); + UpdateControllerState(state); return res; } @@ -2766,50 +2625,50 @@ bool Driver::HandleNetworkUpdateResponse // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleSetSUCNodeIdResponse -( - uint8* _data -) +void Driver::HandleSetSUCNodeIdResponse(uint8* _data) { - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), "Received reply to SET_SUC_NODE_ID." ); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), "Received reply to SET_SUC_NODE_ID."); } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleGetSUCNodeIdResponse -( - uint8* _data -) +void Driver::HandleGetSUCNodeIdResponse(uint8* _data) { - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), "Received reply to GET_SUC_NODE_ID. Node ID = %d", _data[2] ); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), "Received reply to GET_SUC_NODE_ID. Node ID = %d", _data[2]); m_SUCNodeId = _data[2]; - if( _data[2] == 0) + if (_data[2] == 0) { bool enableSIS = true; Options::Get()->GetOptionAsBool("EnableSIS", &enableSIS); - if (enableSIS) { - if (IsAPICallSupported(FUNC_ID_ZW_ENABLE_SUC) && IsAPICallSupported(FUNC_ID_ZW_SET_SUC_NODE_ID)) { - Log::Write( LogLevel_Info, " No SUC, so we become SIS" ); - - Msg* msg; - msg = new Msg( "Enable SUC", m_Controller_nodeId, REQUEST, FUNC_ID_ZW_ENABLE_SUC, false ); - msg->Append( 1 ); - msg->Append( SUC_FUNC_NODEID_SERVER ); // SIS; SUC would be ZW_SUC_FUNC_BASIC_SUC - SendMsg( msg, MsgQueue_Send ); - - msg = new Msg( "Set SUC node ID", m_Controller_nodeId, REQUEST, FUNC_ID_ZW_SET_SUC_NODE_ID, false ); - msg->Append( m_Controller_nodeId ); - msg->Append( 1 ); // TRUE, we want to be SUC/SIS - msg->Append( 0 ); // no low power - msg->Append( SUC_FUNC_NODEID_SERVER ); - SendMsg( msg, MsgQueue_Send ); - } else { - Log::Write (LogLevel_Info, "Controller Does not Support SUC - Cannot Setup Controller as SUC Node"); + if (enableSIS) + { + if (IsAPICallSupported(FUNC_ID_ZW_ENABLE_SUC) && IsAPICallSupported(FUNC_ID_ZW_SET_SUC_NODE_ID)) + { + Log::Write(LogLevel_Info, " No SUC, so we become SIS"); + + Internal::Msg* msg; + msg = new Internal::Msg("Enable SUC", m_Controller_nodeId, REQUEST, FUNC_ID_ZW_ENABLE_SUC, false); + msg->Append(1); + msg->Append( SUC_FUNC_NODEID_SERVER); // SIS; SUC would be ZW_SUC_FUNC_BASIC_SUC + SendMsg(msg, MsgQueue_Send); + + msg = new Internal::Msg("Set SUC node ID", m_Controller_nodeId, REQUEST, FUNC_ID_ZW_SET_SUC_NODE_ID, false); + msg->Append(m_Controller_nodeId); + msg->Append(1); // TRUE, we want to be SUC/SIS + msg->Append(0); // no low power + msg->Append( SUC_FUNC_NODEID_SERVER); + SendMsg(msg, MsgQueue_Send); } - } else { - Log::Write( LogLevel_Info, " No SUC, not becoming SUC as option is disabled" ); + else + { + Log::Write(LogLevel_Info, "Controller Does not Support SUC - Cannot Setup Controller as SUC Node"); + } + } + else + { + Log::Write(LogLevel_Info, " No SUC, not becoming SUC as option is disabled"); } } } @@ -2818,33 +2677,27 @@ void Driver::HandleGetSUCNodeIdResponse // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleMemoryGetIdResponse -( - uint8* _data -) +void Driver::HandleMemoryGetIdResponse(uint8* _data) { - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), "Received reply to FUNC_ID_ZW_MEMORY_GET_ID. Home ID = 0x%02x%02x%02x%02x. Our node ID = %d", _data[2], _data[3], _data[4], _data[5], _data[6] ); - m_homeId = ( ( (uint32)_data[2] )<<24 ) | ( ( (uint32)_data[3] )<<16 ) | ( ( (uint32)_data[4] )<<8 ) | ( (uint32)_data[5] ); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), "Received reply to FUNC_ID_ZW_MEMORY_GET_ID. Home ID = 0x%02x%02x%02x%02x. Our node ID = %d", _data[2], _data[3], _data[4], _data[5], _data[6]); + m_homeId = (((uint32) _data[2]) << 24) | (((uint32) _data[3]) << 16) | (((uint32) _data[4]) << 8) | ((uint32) _data[5]); m_Controller_nodeId = _data[6]; - m_controllerReplication = static_cast(ControllerReplication::Create( m_homeId, m_Controller_nodeId )); + m_controllerReplication = static_cast(Internal::CC::ControllerReplication::Create(m_homeId, m_Controller_nodeId)); } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleSerialAPIGetInitDataResponse -( - uint8* _data -) +void Driver::HandleSerialAPIGetInitDataResponse(uint8* _data) { int32 i; - if( !m_init ) + if (!m_init) { // Mark the driver as ready (we have to do this first or // all the code handling notifications will go awry). - Manager::Get()->SetDriverReady( this, true ); + Manager::Get()->SetDriverReady(this, true); // Read the config file first, to get the last known state ReadCache(); @@ -2853,68 +2706,68 @@ void Driver::HandleSerialAPIGetInitDataResponse { // Notify the user that all node and value information has been deleted // We need to wait to do this here so we have new information to report. - Notification* notification = new Notification( Notification::Type_DriverReset ); - notification->SetHomeAndNodeIds( m_homeId, 0 ); - QueueNotification( notification ); + Notification* notification = new Notification(Notification::Type_DriverReset); + notification->SetHomeAndNodeIds(m_homeId, 0); + QueueNotification(notification); } - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), "Received reply to FUNC_ID_SERIAL_API_GET_INIT_DATA:" ); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), "Received reply to FUNC_ID_SERIAL_API_GET_INIT_DATA:"); m_initVersion = _data[2]; m_initCaps = _data[3]; - if( _data[4] == NUM_NODE_BITFIELD_BYTES ) + if (_data[4] == NUM_NODE_BITFIELD_BYTES) { - for( i=0; iSetQueryStage( Node::QueryStage_CacheLoad ); + node->SetQueryStage(Node::QueryStage_CacheLoad); } } else { // This node is new - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), " Node %.3d - New", nodeId ); - Notification* notification = new Notification( Notification::Type_NodeNew ); - notification->SetHomeAndNodeIds( m_homeId, nodeId ); - QueueNotification( notification ); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), " Node %.3d - New", nodeId); + Notification* notification = new Notification(Notification::Type_NodeNew); + notification->SetHomeAndNodeIds(m_homeId, nodeId); + QueueNotification(notification); // Create the node and request its info - InitNode( nodeId ); + InitNode(nodeId); } } } else { - LockGuard LG(m_nodeMutex); - if( GetNode(nodeId) ) + Internal::LockGuard LG(m_nodeMutex); + if (GetNode(nodeId)) { // This node no longer exists in the Z-Wave network - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), " Node %.3d - Removed", nodeId ); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), " Node %.3d - Removed", nodeId); delete m_nodes[nodeId]; m_nodes[nodeId] = NULL; - Notification* notification = new Notification( Notification::Type_NodeRemoved ); - notification->SetHomeAndNodeIds( m_homeId, nodeId ); - QueueNotification( notification ); + Notification* notification = new Notification(Notification::Type_NodeRemoved); + notification->SetHomeAndNodeIds(m_homeId, nodeId); + QueueNotification(notification); } } @@ -2929,26 +2782,23 @@ void Driver::HandleSerialAPIGetInitDataResponse // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleGetNodeProtocolInfoResponse -( - uint8* _data -) +void Driver::HandleGetNodeProtocolInfoResponse(uint8* _data) { // The node that the protocol info response is for is not included in the message. // We have to assume that the node is the same one as in the most recent request. - if( !m_currentMsg ) + if (!m_currentMsg) { - Log::Write( LogLevel_Warning, "WARNING: Received unexpected FUNC_ID_ZW_GET_NODE_PROTOCOL_INFO message - ignoring."); + Log::Write(LogLevel_Warning, "WARNING: Received unexpected FUNC_ID_ZW_GET_NODE_PROTOCOL_INFO message - ignoring."); return; } uint8 nodeId = m_currentMsg->GetTargetNodeId(); - Log::Write( LogLevel_Info, nodeId, "Received reply to FUNC_ID_ZW_GET_NODE_PROTOCOL_INFO" ); + Log::Write(LogLevel_Info, nodeId, "Received reply to FUNC_ID_ZW_GET_NODE_PROTOCOL_INFO"); // Update the node with the protocol info - if( Node* node = GetNodeUnsafe( nodeId ) ) + if (Node* node = GetNodeUnsafe(nodeId)) { - node->UpdateProtocolInfo( &_data[2] ); + node->UpdateProtocolInfo(&_data[2]); } } @@ -2956,26 +2806,23 @@ void Driver::HandleGetNodeProtocolInfoResponse // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- -bool Driver::HandleAssignReturnRouteResponse -( - uint8* _data -) +bool Driver::HandleAssignReturnRouteResponse(uint8* _data) { bool res = true; ControllerState state = ControllerState_InProgress; - if( _data[2] ) + if (_data[2]) { - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), "Received reply to FUNC_ID_ZW_ASSIGN_RETURN_ROUTE - command in progress" ); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), "Received reply to FUNC_ID_ZW_ASSIGN_RETURN_ROUTE - command in progress"); } else { // Failed - Log::Write( LogLevel_Warning, GetNodeNumber( m_currentMsg ), "WARNING: Received reply to FUNC_ID_ZW_ASSIGN_RETURN_ROUTE - command failed" ); + Log::Write(LogLevel_Warning, GetNodeNumber(m_currentMsg), "WARNING: Received reply to FUNC_ID_ZW_ASSIGN_RETURN_ROUTE - command failed"); state = ControllerState_Failed; res = false; } - UpdateControllerState( state ); + UpdateControllerState(state); return res; } @@ -2983,26 +2830,23 @@ bool Driver::HandleAssignReturnRouteResponse // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- -bool Driver::HandleDeleteReturnRouteResponse -( - uint8* _data -) +bool Driver::HandleDeleteReturnRouteResponse(uint8* _data) { bool res = true; ControllerState state = ControllerState_InProgress; - if( _data[2] ) + if (_data[2]) { - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), "Received reply to FUNC_ID_ZW_DELETE_RETURN_ROUTE - command in progress" ); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), "Received reply to FUNC_ID_ZW_DELETE_RETURN_ROUTE - command in progress"); } else { // Failed - Log::Write( LogLevel_Warning, GetNodeNumber( m_currentMsg ), "WARNING: Received reply to FUNC_ID_ZW_DELETE_RETURN_ROUTE - command failed" ); + Log::Write(LogLevel_Warning, GetNodeNumber(m_currentMsg), "WARNING: Received reply to FUNC_ID_ZW_DELETE_RETURN_ROUTE - command failed"); state = ControllerState_Failed; res = false; } - UpdateControllerState( state ); + UpdateControllerState(state); return res; } @@ -3010,60 +2854,57 @@ bool Driver::HandleDeleteReturnRouteResponse // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- -bool Driver::HandleRemoveFailedNodeResponse -( - uint8* _data -) +bool Driver::HandleRemoveFailedNodeResponse(uint8* _data) { bool res = true; ControllerState state = ControllerState_InProgress; ControllerError error = ControllerError_None; - if( _data[2] ) + if (_data[2]) { string reason; - switch( _data[2] ) - { - case FAILED_NODE_NOT_FOUND: - { - reason = "Node not found"; - error = ControllerError_NotFound; - break; - } - case FAILED_NODE_REMOVE_PROCESS_BUSY: - { - reason = "Remove process busy"; - error = ControllerError_Busy; - break; - } - case FAILED_NODE_REMOVE_FAIL: - { - reason = "Remove failed"; - error = ControllerError_Failed; - break; - } - case FAILED_NODE_NOT_PRIMARY_CONTROLLER: - { - reason = "Not Primary Controller"; - error = ControllerError_NotPrimary; - break; - } - default: + switch (_data[2]) { - reason = "Command failed"; - break; - } + case FAILED_NODE_NOT_FOUND: + { + reason = "Node not found"; + error = ControllerError_NotFound; + break; + } + case FAILED_NODE_REMOVE_PROCESS_BUSY: + { + reason = "Remove process busy"; + error = ControllerError_Busy; + break; + } + case FAILED_NODE_REMOVE_FAIL: + { + reason = "Remove failed"; + error = ControllerError_Failed; + break; + } + case FAILED_NODE_NOT_PRIMARY_CONTROLLER: + { + reason = "Not Primary Controller"; + error = ControllerError_NotPrimary; + break; + } + default: + { + reason = "Command failed"; + break; + } } - Log::Write( LogLevel_Warning, GetNodeNumber( m_currentMsg ), "WARNING: Received reply to FUNC_ID_ZW_REMOVE_FAILED_NODE_ID - %s", reason.c_str() ); + Log::Write(LogLevel_Warning, GetNodeNumber(m_currentMsg), "WARNING: Received reply to FUNC_ID_ZW_REMOVE_FAILED_NODE_ID - %s", reason.c_str()); state = ControllerState_Failed; res = false; } else { - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), "Received reply to FUNC_ID_ZW_REMOVE_FAILED_NODE_ID - Command in progress" ); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), "Received reply to FUNC_ID_ZW_REMOVE_FAILED_NODE_ID - Command in progress"); } - UpdateControllerState( state, error ); + UpdateControllerState(state, error); return res; } @@ -3071,69 +2912,66 @@ bool Driver::HandleRemoveFailedNodeResponse // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleIsFailedNodeResponse -( - uint8* _data -) +void Driver::HandleIsFailedNodeResponse(uint8* _data) { ControllerState state; - uint8 nodeId = m_currentControllerCommand ? m_currentControllerCommand->m_controllerCommandNode : GetNodeNumber( m_currentMsg ); - if( _data[2] ) + uint8 nodeId = m_currentControllerCommand ? m_currentControllerCommand->m_controllerCommandNode : GetNodeNumber(m_currentMsg); + if (_data[2]) { - Log::Write( LogLevel_Warning, nodeId, "WARNING: Received reply to FUNC_ID_ZW_IS_FAILED_NODE_ID - node %d failed", nodeId ); + Log::Write(LogLevel_Warning, nodeId, "WARNING: Received reply to FUNC_ID_ZW_IS_FAILED_NODE_ID - node %d failed", nodeId); state = ControllerState_NodeFailed; - if( Node* node = GetNodeUnsafe( nodeId ) ) + if (Node* node = GetNodeUnsafe(nodeId)) { - if (node->IsNodeReset()) { + if (node->IsNodeReset()) + { /* a DeviceReset has Occured. Remove the Node */ if (!BeginControllerCommand(Driver::ControllerCommand_RemoveFailedNode, NULL, NULL, true, nodeId, 0)) Log::Write(LogLevel_Warning, nodeId, "RemoveFailedNode for DeviceResetLocally Command Failed"); - Notification* notification = new Notification( Notification::Type_NodeReset ); - notification->SetHomeAndNodeIds( m_homeId, nodeId ); - QueueNotification( notification ); + Notification* notification = new Notification(Notification::Type_NodeReset); + notification->SetHomeAndNodeIds(m_homeId, nodeId); + QueueNotification(notification); state = ControllerState_Completed; - } else { - node->SetNodeAlive( false ); + } + else + { + node->SetNodeAlive(false); } } } else { - Log::Write( LogLevel_Warning, nodeId, "Received reply to FUNC_ID_ZW_IS_FAILED_NODE_ID - node %d has not failed", nodeId ); - if( Node* node = GetNodeUnsafe( nodeId ) ) + Log::Write(LogLevel_Warning, nodeId, "Received reply to FUNC_ID_ZW_IS_FAILED_NODE_ID - node %d has not failed", nodeId); + if (Node* node = GetNodeUnsafe(nodeId)) { - node->SetNodeAlive( true ); + node->SetNodeAlive(true); } state = ControllerState_NodeOK; } - UpdateControllerState( state ); + UpdateControllerState(state); } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- -bool Driver::HandleReplaceFailedNodeResponse -( - uint8* _data -) +bool Driver::HandleReplaceFailedNodeResponse(uint8* _data) { bool res = true; ControllerState state = ControllerState_InProgress; - if( _data[2] ) + if (_data[2]) { // Command failed - Log::Write( LogLevel_Warning, GetNodeNumber( m_currentMsg ), "WARNING: Received reply to FUNC_ID_ZW_REPLACE_FAILED_NODE - command failed" ); + Log::Write(LogLevel_Warning, GetNodeNumber(m_currentMsg), "WARNING: Received reply to FUNC_ID_ZW_REPLACE_FAILED_NODE - command failed"); state = ControllerState_Failed; res = false; } else { - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), "Received reply to FUNC_ID_ZW_REPLACE_FAILED_NODE - command in progress" ); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), "Received reply to FUNC_ID_ZW_REPLACE_FAILED_NODE - command in progress"); } - UpdateControllerState( state ); + UpdateControllerState(state); return res; } @@ -3141,21 +2979,17 @@ bool Driver::HandleReplaceFailedNodeResponse // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleSendDataResponse -( - uint8* _data, - bool _replication -) +void Driver::HandleSendDataResponse(uint8* _data, bool _replication) { - if( _data[2] ) + if (_data[2]) { - Log::Write( LogLevel_Detail, GetNodeNumber( m_currentMsg ), " %s delivered to Z-Wave stack", _replication ? "ZW_REPLICATION_SEND_DATA" : "ZW_SEND_DATA" ); + Log::Write(LogLevel_Detail, GetNodeNumber(m_currentMsg), " %s delivered to Z-Wave stack", _replication ? "ZW_REPLICATION_SEND_DATA" : "ZW_SEND_DATA"); } else { - Log::Write( LogLevel_Error, GetNodeNumber( m_currentMsg ), "ERROR: %s could not be delivered to Z-Wave stack", _replication ? "ZW_REPLICATION_SEND_DATA" : "ZW_SEND_DATA" ); + Log::Write(LogLevel_Error, GetNodeNumber(m_currentMsg), "ERROR: %s could not be delivered to Z-Wave stack", _replication ? "ZW_REPLICATION_SEND_DATA" : "ZW_SEND_DATA"); m_nondelivery++; - if( Node* node = GetNodeUnsafe( GetNodeNumber( m_currentMsg ) ) ) + if (Node* node = GetNodeUnsafe(GetNodeNumber(m_currentMsg))) { node->m_sentFailed++; } @@ -3166,35 +3000,32 @@ void Driver::HandleSendDataResponse // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleGetRoutingInfoResponse -( - uint8* _data -) +void Driver::HandleGetRoutingInfoResponse(uint8* _data) { - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), "Received reply to FUNC_ID_ZW_GET_ROUTING_INFO" ); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), "Received reply to FUNC_ID_ZW_GET_ROUTING_INFO"); - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( GetNodeNumber( m_currentMsg ) ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(GetNodeNumber(m_currentMsg))) { // copy the 29-byte bitmap received (29*8=232 possible nodes) into this node's neighbors member variable - memcpy( node->m_neighbors, &_data[2], 29 ); - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), " Neighbors of this node are:" ); + memcpy(node->m_neighbors, &_data[2], 29); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), " Neighbors of this node are:"); bool bNeighbors = false; - for( int by=0; by<29; by++ ) + for (int by = 0; by < 29; by++) { - for( int bi=0; bi<8; bi++ ) + for (int bi = 0; bi < 8; bi++) { - if( (_data[2+by] & (0x01< // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleSendDataRequest -( - uint8* _data, - uint8 _length, - bool _replication -) +void Driver::HandleSendDataRequest(uint8* _data, uint8 _length, bool _replication) { - uint8 nodeId = GetNodeNumber( m_currentMsg ); - Log::Write( LogLevel_Detail, nodeId, " %s Request with callback ID 0x%.2x received (expected 0x%.2x)", _replication ? "ZW_REPLICATION_SEND_DATA" : "ZW_SEND_DATA", _data[2], _data[2] < 10 ? _data[2] : m_expectedCallbackId ); + uint8 nodeId = GetNodeNumber(m_currentMsg); + Log::Write(LogLevel_Detail, nodeId, " %s Request with callback ID 0x%.2x received (expected 0x%.2x)", _replication ? "ZW_REPLICATION_SEND_DATA" : "ZW_SEND_DATA", _data[2], _data[2] < 10 ? _data[2] : m_expectedCallbackId); /* Callback ID's below 10 are reserved for NONCE messages */ - if ((_data[2] > 10 ) && ( _data[2] != m_expectedCallbackId )) { + if ((_data[2] > 10) && (_data[2] != m_expectedCallbackId)) + { // Wrong callback ID m_callbacks++; - Log::Write( LogLevel_Warning, nodeId, "WARNING: Unexpected Callback ID received" ); - } else { - Node* node = GetNodeUnsafe( nodeId ); - if( node != NULL ) + Log::Write(LogLevel_Warning, nodeId, "WARNING: Unexpected Callback ID received"); + } + else + { + Node* node = GetNodeUnsafe(nodeId); + if (node != NULL) { - if( _data[3] != TRANSMIT_COMPLETE_OK ) + if (_data[3] != TRANSMIT_COMPLETE_OK) { node->m_sentFailed++; } @@ -3229,21 +3058,22 @@ void Driver::HandleSendDataRequest { node->m_lastRequestRTT = -node->m_sentTS.TimeRemaining(); - if( node->m_averageRequestRTT ) + if (node->m_averageRequestRTT) { // if the average has been established, update by averaging the average and the last RTT - node->m_averageRequestRTT = ( node->m_averageRequestRTT + node->m_lastRequestRTT ) >> 1; + node->m_averageRequestRTT = (node->m_averageRequestRTT + node->m_lastRequestRTT) >> 1; } else { // if this is the first observed RTT, set the average to this value node->m_averageRequestRTT = node->m_lastRequestRTT; } - Log::Write(LogLevel_Info, nodeId, "Request RTT %d Average Request RTT %d", node->m_lastRequestRTT, node->m_averageRequestRTT ); + Log::Write(LogLevel_Info, nodeId, "Request RTT %d Average Request RTT %d", node->m_lastRequestRTT, node->m_averageRequestRTT); } /* if the frame has txStatus message, then extract it */ // petergebruers, changed test (_length > 7) to >= 23 to avoid extracting non-existent data, highest is _data[22] - if (_length >= 23) { + if (_length >= 23) + { node->m_txStatusReportSupported = true; // petergebruers: // because OpenZWave uses "ms" everywhere, and wTransmitTicks @@ -3253,71 +3083,66 @@ void Driver::HandleSendDataRequest node->m_hops = _data[6]; // petergebruers: there are 5 rssi values because there are // 4 repeaters + 1 sending node - strncpy(node->m_rssi_1, rssi_to_string(_data[7]), sizeof(node->m_rssi_1) - 1); - strncpy(node->m_rssi_2, rssi_to_string(_data[8]), sizeof(node->m_rssi_2) - 1); - strncpy(node->m_rssi_3, rssi_to_string(_data[9]), sizeof(node->m_rssi_3) - 1); - strncpy(node->m_rssi_4, rssi_to_string(_data[10]), sizeof(node->m_rssi_4) - 1); - strncpy(node->m_rssi_5, rssi_to_string(_data[11]), sizeof(node->m_rssi_5) - 1); + strncpy(node->m_rssi_1, Internal::rssi_to_string(_data[7]), sizeof(node->m_rssi_1) - 1); + strncpy(node->m_rssi_2, Internal::rssi_to_string(_data[8]), sizeof(node->m_rssi_2) - 1); + strncpy(node->m_rssi_3, Internal::rssi_to_string(_data[9]), sizeof(node->m_rssi_3) - 1); + strncpy(node->m_rssi_4, Internal::rssi_to_string(_data[10]), sizeof(node->m_rssi_4) - 1); + strncpy(node->m_rssi_5, Internal::rssi_to_string(_data[11]), sizeof(node->m_rssi_5) - 1); node->m_ackChannel = _data[12]; node->m_lastTxChannel = _data[13]; - node->m_routeScheme = (TXSTATUS_ROUTING_SCHEME)_data[14]; + node->m_routeScheme = (TXSTATUS_ROUTING_SCHEME) _data[14]; node->m_routeUsed[0] = _data[15]; node->m_routeUsed[1] = _data[16]; node->m_routeUsed[2] = _data[17]; node->m_routeUsed[3] = _data[18]; - node->m_routeSpeed = (TXSTATUS_ROUTE_SPEED)_data[19]; + node->m_routeSpeed = (TXSTATUS_ROUTE_SPEED) _data[19]; node->m_routeTries = _data[20]; node->m_lastFailedLinkFrom = _data[21]; node->m_lastFailedLinkTo = _data[22]; Node::NodeData nd; node->GetNodeStatistics(&nd); // petergebruers: changed "ChannelAck" to "AckChannel", to be consistent with docs and "TxChannel" - Log::Write( LogLevel_Detail, nodeId, "Extended TxStatus: Time: %d, Hops: %d, Rssi: %s %s %s %s %s, AckChannel: %d, TxChannel: %d, RouteScheme: %s, Route: %d %d %d %d, RouteSpeed: %s, RouteTries: %d, FailedLinkFrom: %d, FailedLinkTo: %d", - nd.m_txTime, nd.m_hops, nd.m_rssi_1, nd.m_rssi_2, nd.m_rssi_3, nd.m_rssi_4, nd.m_rssi_4, - nd.m_ackChannel, nd.m_lastTxChannel, Manager::GetNodeRouteScheme(&nd).c_str(), nd.m_routeUsed[0], - nd.m_routeUsed[1], nd.m_routeUsed[2], nd.m_routeUsed[3], Manager::GetNodeRouteSpeed(&nd).c_str(), - nd.m_routeTries, nd.m_lastFailedLinkFrom, nd.m_lastFailedLinkTo); + Log::Write(LogLevel_Detail, nodeId, "Extended TxStatus: Time: %d, Hops: %d, Rssi: %s %s %s %s %s, AckChannel: %d, TxChannel: %d, RouteScheme: %s, Route: %d %d %d %d, RouteSpeed: %s, RouteTries: %d, FailedLinkFrom: %d, FailedLinkTo: %d", nd.m_txTime, nd.m_hops, nd.m_rssi_1, nd.m_rssi_2, nd.m_rssi_3, nd.m_rssi_4, nd.m_rssi_4, nd.m_ackChannel, nd.m_lastTxChannel, Manager::GetNodeRouteScheme(&nd).c_str(), nd.m_routeUsed[0], nd.m_routeUsed[1], nd.m_routeUsed[2], nd.m_routeUsed[3], + Manager::GetNodeRouteSpeed(&nd).c_str(), nd.m_routeTries, nd.m_lastFailedLinkFrom, nd.m_lastFailedLinkTo); } } // We do this here since HandleErrorResponse/MoveMessagesToWakeUpQueue can delete m_currentMsg - if( m_currentMsg && m_currentMsg->IsNoOperation() ) + if (m_currentMsg && m_currentMsg->IsNoOperation()) { - Notification* notification = new Notification( Notification::Type_Notification ); - notification->SetHomeAndNodeIds( m_homeId, GetNodeNumber( m_currentMsg) ); - notification->SetNotification( Notification::Code_NoOperation ); - QueueNotification( notification ); + Notification* notification = new Notification(Notification::Type_Notification); + notification->SetHomeAndNodeIds(m_homeId, GetNodeNumber(m_currentMsg)); + notification->SetNotification(Notification::Code_NoOperation); + QueueNotification(notification); } // Callback ID matches our expectation - if( _data[3] != TRANSMIT_COMPLETE_OK ) + if (_data[3] != TRANSMIT_COMPLETE_OK) { - if( !HandleErrorResponse( _data[3], nodeId, _replication ? "ZW_REPLICATION_END_DATA" : "ZW_SEND_DATA", !_replication ) ) + if (!HandleErrorResponse(_data[3], nodeId, _replication ? "ZW_REPLICATION_END_DATA" : "ZW_SEND_DATA", !_replication)) { - if( m_currentMsg && m_currentMsg->IsNoOperation() && node != NULL && - ( node->GetCurrentQueryStage() == Node::QueryStage_Probe || - node->GetCurrentQueryStage() == Node::QueryStage_CacheLoad ) ) + if (m_currentMsg && m_currentMsg->IsNoOperation() && node != NULL && (node->GetCurrentQueryStage() == Node::QueryStage_Probe || node->GetCurrentQueryStage() == Node::QueryStage_CacheLoad)) { - node->QueryStageRetry( node->GetCurrentQueryStage(), 3 ); + node->QueryStageRetry(node->GetCurrentQueryStage(), 3); } } } - else if( node != NULL ) + else if (node != NULL) { // If WakeUpNoMoreInformation request succeeds, update our status - if( m_currentMsg && m_currentMsg->IsWakeUpNoMoreInformationCommand() ) + if (m_currentMsg && m_currentMsg->IsWakeUpNoMoreInformationCommand()) { - if( WakeUp* wakeUp = static_cast( node->GetCommandClass( WakeUp::StaticGetCommandClassId() ) ) ) + if (Internal::CC::WakeUp* wakeUp = static_cast(node->GetCommandClass(Internal::CC::WakeUp::StaticGetCommandClassId()))) { // Mark the node as asleep - wakeUp->SetAwake( false ); + wakeUp->SetAwake(false); } } // If node is not alive, mark it alive now - if( !node->IsNodeAlive() ) + if (!node->IsNodeAlive()) { - node->SetNodeAlive( true ); + node->SetNodeAlive(true); } } // Command reception acknowledged by node, error or not, but ignore any NONCE messages @@ -3330,486 +3155,460 @@ void Driver::HandleSendDataRequest // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleNetworkUpdateRequest -( - uint8* _data -) +void Driver::HandleNetworkUpdateRequest(uint8* _data) { ControllerState state = ControllerState_Failed; ControllerError error = ControllerError_None; - uint8 nodeId = GetNodeNumber( m_currentMsg ); - switch( _data[3] ) - { - case SUC_UPDATE_DONE: + uint8 nodeId = GetNodeNumber(m_currentMsg); + switch (_data[3]) { - Log::Write( LogLevel_Info, nodeId, "Received reply to FUNC_ID_ZW_REQUEST_NETWORK_UPDATE: Success" ); - state = ControllerState_Completed; - break; - } - case SUC_UPDATE_ABORT: - { - Log::Write( LogLevel_Warning, nodeId, "WARNING: Received reply to FUNC_ID_ZW_REQUEST_NETWORK_UPDATE: Failed - Error. Process aborted." ); - error = ControllerError_Failed; - break; - } - case SUC_UPDATE_WAIT: - { - Log::Write( LogLevel_Warning, nodeId, "WARNING: Received reply to FUNC_ID_ZW_REQUEST_NETWORK_UPDATE: Failed - SUC is busy." ); - error = ControllerError_Busy; - break; - } - case SUC_UPDATE_DISABLED: - { - Log::Write( LogLevel_Warning, nodeId, "WARNING: Received reply to FUNC_ID_ZW_REQUEST_NETWORK_UPDATE: Failed - SUC is disabled." ); - error = ControllerError_Disabled; - break; - } - case SUC_UPDATE_OVERFLOW: - { - Log::Write( LogLevel_Warning, nodeId, "WARNING: Received reply to FUNC_ID_ZW_REQUEST_NETWORK_UPDATE: Failed - Overflow. Full replication required." ); - error = ControllerError_Overflow; - break; - } - default: - { - } + case SUC_UPDATE_DONE: + { + Log::Write(LogLevel_Info, nodeId, "Received reply to FUNC_ID_ZW_REQUEST_NETWORK_UPDATE: Success"); + state = ControllerState_Completed; + break; + } + case SUC_UPDATE_ABORT: + { + Log::Write(LogLevel_Warning, nodeId, "WARNING: Received reply to FUNC_ID_ZW_REQUEST_NETWORK_UPDATE: Failed - Error. Process aborted."); + error = ControllerError_Failed; + break; + } + case SUC_UPDATE_WAIT: + { + Log::Write(LogLevel_Warning, nodeId, "WARNING: Received reply to FUNC_ID_ZW_REQUEST_NETWORK_UPDATE: Failed - SUC is busy."); + error = ControllerError_Busy; + break; + } + case SUC_UPDATE_DISABLED: + { + Log::Write(LogLevel_Warning, nodeId, "WARNING: Received reply to FUNC_ID_ZW_REQUEST_NETWORK_UPDATE: Failed - SUC is disabled."); + error = ControllerError_Disabled; + break; + } + case SUC_UPDATE_OVERFLOW: + { + Log::Write(LogLevel_Warning, nodeId, "WARNING: Received reply to FUNC_ID_ZW_REQUEST_NETWORK_UPDATE: Failed - Overflow. Full replication required."); + error = ControllerError_Overflow; + break; + } + default: + { + } } - UpdateControllerState( state, error ); + UpdateControllerState(state, error); } //----------------------------------------------------------------------------- // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleAddNodeToNetworkRequest -( - uint8* _data -) +void Driver::HandleAddNodeToNetworkRequest(uint8* _data) { - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), "FUNC_ID_ZW_ADD_NODE_TO_NETWORK:" ); - CommonAddNodeStatusRequestHandler( FUNC_ID_ZW_ADD_NODE_TO_NETWORK, _data ); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), "FUNC_ID_ZW_ADD_NODE_TO_NETWORK:"); + CommonAddNodeStatusRequestHandler( FUNC_ID_ZW_ADD_NODE_TO_NETWORK, _data); } //----------------------------------------------------------------------------- // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleRemoveNodeFromNetworkRequest -( - uint8* _data -) +void Driver::HandleRemoveNodeFromNetworkRequest(uint8* _data) { //uint8 nodeId = GetNodeNumber( m_currentMsg ); - if( m_currentControllerCommand == NULL ) + if (m_currentControllerCommand == NULL) { return; } ControllerState state = m_currentControllerCommand->m_controllerState; - Log::Write( LogLevel_Info, "FUNC_ID_ZW_REMOVE_NODE_FROM_NETWORK:" ); + Log::Write(LogLevel_Info, "FUNC_ID_ZW_REMOVE_NODE_FROM_NETWORK:"); - switch( _data[3] ) - { - case REMOVE_NODE_STATUS_LEARN_READY: - { - Log::Write( LogLevel_Info, "REMOVE_NODE_STATUS_LEARN_READY" ); - state = ControllerState_Waiting; - m_currentControllerCommand->m_controllerCommandNode = 0; - break; - } - case REMOVE_NODE_STATUS_NODE_FOUND: + switch (_data[3]) { - Log::Write( LogLevel_Info, "REMOVE_NODE_STATUS_NODE_FOUND" ); - state = ControllerState_InProgress; - break; - } - case REMOVE_NODE_STATUS_REMOVING_SLAVE: - { - Log::Write( LogLevel_Info, "REMOVE_NODE_STATUS_REMOVING_SLAVE" ); - if (_data[4] != 0) + case REMOVE_NODE_STATUS_LEARN_READY: { - Log::Write( LogLevel_Info, "Removing node ID %d", _data[4] ); - m_currentControllerCommand->m_controllerCommandNode = _data[4]; + Log::Write(LogLevel_Info, "REMOVE_NODE_STATUS_LEARN_READY"); + state = ControllerState_Waiting; + m_currentControllerCommand->m_controllerCommandNode = 0; + break; } - else + case REMOVE_NODE_STATUS_NODE_FOUND: { - Log::Write( LogLevel_Warning, "Remove Node Failed - NodeID 0 Returned"); - state = ControllerState_Failed; + Log::Write(LogLevel_Info, "REMOVE_NODE_STATUS_NODE_FOUND"); + state = ControllerState_InProgress; + break; } - break; - } - case REMOVE_NODE_STATUS_REMOVING_CONTROLLER: - { - Log::Write( LogLevel_Info, "REMOVE_NODE_STATUS_REMOVING_CONTROLLER" ); - m_currentControllerCommand->m_controllerCommandNode = _data[4]; - if( m_currentControllerCommand->m_controllerCommandNode == 0 ) // Some controllers don't return node number + case REMOVE_NODE_STATUS_REMOVING_SLAVE: + { + Log::Write(LogLevel_Info, "REMOVE_NODE_STATUS_REMOVING_SLAVE"); + if (_data[4] != 0) + { + Log::Write(LogLevel_Info, "Removing node ID %d", _data[4]); + m_currentControllerCommand->m_controllerCommandNode = _data[4]; + } + else + { + Log::Write(LogLevel_Warning, "Remove Node Failed - NodeID 0 Returned"); + state = ControllerState_Failed; + } + break; + } + case REMOVE_NODE_STATUS_REMOVING_CONTROLLER: { - if( _data[5] >= 3 ) + Log::Write(LogLevel_Info, "REMOVE_NODE_STATUS_REMOVING_CONTROLLER"); + m_currentControllerCommand->m_controllerCommandNode = _data[4]; + if (m_currentControllerCommand->m_controllerCommandNode == 0) // Some controllers don't return node number { - LockGuard LG(m_nodeMutex); - for( int i=0; i<256; i++ ) + if (_data[5] >= 3) { - if( m_nodes[i] == NULL ) - { - continue; - } - // Ignore primary controller - if( m_nodes[i]->m_nodeId == m_Controller_nodeId ) + Internal::LockGuard LG(m_nodeMutex); + for (int i = 0; i < 256; i++) { - continue; - } - // See if we can match another way - if( m_nodes[i]->m_basic == _data[6] && - m_nodes[i]->m_generic == _data[7] && - m_nodes[i]->m_specific == _data[8] ) - { - if( m_currentControllerCommand->m_controllerCommandNode != 0 ) + if (m_nodes[i] == NULL) { - Log::Write( LogLevel_Info, "Alternative controller lookup found more then one match. Using the first one found." ); + continue; } - else + // Ignore primary controller + if (m_nodes[i]->m_nodeId == m_Controller_nodeId) { - m_currentControllerCommand->m_controllerCommandNode = m_nodes[i]->m_nodeId; + continue; + } + // See if we can match another way + if (m_nodes[i]->m_basic == _data[6] && m_nodes[i]->m_generic == _data[7] && m_nodes[i]->m_specific == _data[8]) + { + if (m_currentControllerCommand->m_controllerCommandNode != 0) + { + Log::Write(LogLevel_Info, "Alternative controller lookup found more then one match. Using the first one found."); + } + else + { + m_currentControllerCommand->m_controllerCommandNode = m_nodes[i]->m_nodeId; + } } } + LG.Unlock(); + } + else + { + Log::Write(LogLevel_Warning, "WARNING: Node is 0 but not enough data to perform alternative match."); } - LG.Unlock(); } else { - Log::Write( LogLevel_Warning, "WARNING: Node is 0 but not enough data to perform alternative match." ); + m_currentControllerCommand->m_controllerCommandNode = _data[4]; } + WriteCache(); + Log::Write(LogLevel_Info, "Removing controller ID %d", m_currentControllerCommand->m_controllerCommandNode); + break; } - else - { - m_currentControllerCommand->m_controllerCommandNode = _data[4]; - } - Log::Write( LogLevel_Info, "Removing controller ID %d", m_currentControllerCommand->m_controllerCommandNode ); - break; - } - case REMOVE_NODE_STATUS_DONE: - { - Log::Write( LogLevel_Info, "REMOVE_NODE_STATUS_DONE" ); - if( !m_currentControllerCommand->m_controllerCommandDone ) + case REMOVE_NODE_STATUS_DONE: { - - // Remove Node Stop calls back through here so make sure - // we do't do it again. - UpdateControllerState( ControllerState_Completed ); - //AddNodeStop( FUNC_ID_ZW_REMOVE_NODE_FROM_NETWORK ); - if ( m_currentControllerCommand->m_controllerCommandNode == 0 ) // never received "removing" update + Log::Write(LogLevel_Info, "REMOVE_NODE_STATUS_DONE"); + if (!m_currentControllerCommand->m_controllerCommandDone) { - if ( _data[4] != 0 ) // but message has the clue + + // Remove Node Stop calls back through here so make sure + // we do't do it again. + UpdateControllerState(ControllerState_Completed); + //AddNodeStop( FUNC_ID_ZW_REMOVE_NODE_FROM_NETWORK ); + if (m_currentControllerCommand->m_controllerCommandNode == 0) // never received "removing" update { - m_currentControllerCommand->m_controllerCommandNode = _data[4]; + if (_data[4] != 0) // but message has the clue + { + m_currentControllerCommand->m_controllerCommandNode = _data[4]; + } } - } - if ( m_currentControllerCommand->m_controllerCommandNode != 0 && m_currentControllerCommand->m_controllerCommandNode != 0xff ) - { + if (m_currentControllerCommand->m_controllerCommandNode != 0 && m_currentControllerCommand->m_controllerCommandNode != 0xff) { - LockGuard LG(m_nodeMutex); - delete m_nodes[m_currentControllerCommand->m_controllerCommandNode]; - m_nodes[m_currentControllerCommand->m_controllerCommandNode] = NULL; + { + Internal::LockGuard LG(m_nodeMutex); + delete m_nodes[m_currentControllerCommand->m_controllerCommandNode]; + m_nodes[m_currentControllerCommand->m_controllerCommandNode] = NULL; + } + WriteCache(); + Notification* notification = new Notification(Notification::Type_NodeRemoved); + notification->SetHomeAndNodeIds(m_homeId, m_currentControllerCommand->m_controllerCommandNode); + QueueNotification(notification); } - Notification* notification = new Notification( Notification::Type_NodeRemoved ); - notification->SetHomeAndNodeIds( m_homeId, m_currentControllerCommand->m_controllerCommandNode ); - QueueNotification( notification ); } + return; + } + case REMOVE_NODE_STATUS_FAILED: + { + //AddNodeStop( FUNC_ID_ZW_REMOVE_NODE_FROM_NETWORK ); + Log::Write(LogLevel_Warning, "WARNING: REMOVE_NODE_STATUS_FAILED"); + state = ControllerState_Failed; + break; + } + default: + { + break; } - return; - } - case REMOVE_NODE_STATUS_FAILED: - { - //AddNodeStop( FUNC_ID_ZW_REMOVE_NODE_FROM_NETWORK ); - Log::Write( LogLevel_Warning, "WARNING: REMOVE_NODE_STATUS_FAILED" ); - state = ControllerState_Failed; - break; - } - default: - { - break; - } } - UpdateControllerState( state ); + UpdateControllerState(state); } //----------------------------------------------------------------------------- // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleControllerChangeRequest -( - uint8* _data -) +void Driver::HandleControllerChangeRequest(uint8* _data) { - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), "FUNC_ID_ZW_CONTROLLER_CHANGE:" ); - CommonAddNodeStatusRequestHandler( FUNC_ID_ZW_CONTROLLER_CHANGE, _data ); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), "FUNC_ID_ZW_CONTROLLER_CHANGE:"); + CommonAddNodeStatusRequestHandler( FUNC_ID_ZW_CONTROLLER_CHANGE, _data); } //----------------------------------------------------------------------------- // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleCreateNewPrimaryRequest -( - uint8* _data -) +void Driver::HandleCreateNewPrimaryRequest(uint8* _data) { - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), "FUNC_ID_ZW_CREATE_NEW_PRIMARY:" ); - CommonAddNodeStatusRequestHandler( FUNC_ID_ZW_CREATE_NEW_PRIMARY, _data ); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), "FUNC_ID_ZW_CREATE_NEW_PRIMARY:"); + CommonAddNodeStatusRequestHandler( FUNC_ID_ZW_CREATE_NEW_PRIMARY, _data); } //----------------------------------------------------------------------------- // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleSetLearnModeRequest -( - uint8* _data -) +void Driver::HandleSetLearnModeRequest(uint8* _data) { - uint8 nodeId = GetNodeNumber( m_currentMsg ); - if( m_currentControllerCommand == NULL ) + uint8 nodeId = GetNodeNumber(m_currentMsg); + if (m_currentControllerCommand == NULL) { return; } ControllerState state = m_currentControllerCommand->m_controllerState; - Log::Write( LogLevel_Info, nodeId, "FUNC_ID_ZW_SET_LEARN_MODE:" ); + Log::Write(LogLevel_Info, nodeId, "FUNC_ID_ZW_SET_LEARN_MODE:"); - switch( _data[3] ) - { - case LEARN_MODE_STARTED: - { - Log::Write( LogLevel_Info, nodeId, "LEARN_MODE_STARTED" ); - state = ControllerState_Waiting; - break; - } - case LEARN_MODE_DONE: + switch (_data[3]) { - Log::Write( LogLevel_Info, nodeId, "LEARN_MODE_DONE" ); - state = ControllerState_Completed; + case LEARN_MODE_STARTED: + { + Log::Write(LogLevel_Info, nodeId, "LEARN_MODE_STARTED"); + state = ControllerState_Waiting; + break; + } + case LEARN_MODE_DONE: + { + Log::Write(LogLevel_Info, nodeId, "LEARN_MODE_DONE"); + state = ControllerState_Completed; - // Stop learn mode - Msg* msg = new Msg( "End Learn Mode", 0xff, REQUEST, FUNC_ID_ZW_SET_LEARN_MODE, false, false ); - msg->Append( 0 ); - SendMsg( msg, MsgQueue_Command ); + // Stop learn mode + Internal::Msg* msg = new Internal::Msg("End Learn Mode", 0xff, REQUEST, FUNC_ID_ZW_SET_LEARN_MODE, false, false); + msg->Append(0); + SendMsg(msg, MsgQueue_Command); - // Rebuild all the node info. Group and scene data that we stored - // during replication will be applied as we discover each node. - InitAllNodes(); - break; - } - case LEARN_MODE_FAILED: - { - Log::Write( LogLevel_Warning, nodeId, "WARNING: LEARN_MODE_FAILED" ); - state = ControllerState_Failed; + // Rebuild all the node info. Group and scene data that we stored + // during replication will be applied as we discover each node. + InitAllNodes(); + break; + } + case LEARN_MODE_FAILED: + { + Log::Write(LogLevel_Warning, nodeId, "WARNING: LEARN_MODE_FAILED"); + state = ControllerState_Failed; - // Stop learn mode - Msg* msg = new Msg( "End Learn Mode", 0xff, REQUEST, FUNC_ID_ZW_SET_LEARN_MODE, false, false ); - msg->Append( 0 ); - SendMsg( msg, MsgQueue_Command ); + // Stop learn mode + Internal::Msg* msg = new Internal::Msg("End Learn Mode", 0xff, REQUEST, FUNC_ID_ZW_SET_LEARN_MODE, false, false); + msg->Append(0); + SendMsg(msg, MsgQueue_Command); - // Rebuild all the node info, since it may have been partially - // updated by the failed command. Group and scene data that we - // stored during replication will be applied as we discover each node. - InitAllNodes(); - break; - } - case LEARN_MODE_DELETED: - { - Log::Write( LogLevel_Info, nodeId, "LEARN_MODE_DELETED" ); - state = ControllerState_Failed; - // Stop learn mode - Msg* msg = new Msg( "End Learn Mode", 0xff, REQUEST, FUNC_ID_ZW_SET_LEARN_MODE, false, false ); - msg->Append( 0 ); - SendMsg( msg, MsgQueue_Command ); - break; - } + // Rebuild all the node info, since it may have been partially + // updated by the failed command. Group and scene data that we + // stored during replication will be applied as we discover each node. + InitAllNodes(); + break; + } + case LEARN_MODE_DELETED: + { + Log::Write(LogLevel_Info, nodeId, "LEARN_MODE_DELETED"); + state = ControllerState_Failed; + // Stop learn mode + Internal::Msg* msg = new Internal::Msg("End Learn Mode", 0xff, REQUEST, FUNC_ID_ZW_SET_LEARN_MODE, false, false); + msg->Append(0); + SendMsg(msg, MsgQueue_Command); + break; + } } - UpdateControllerState( state ); + UpdateControllerState(state); } //----------------------------------------------------------------------------- // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleRemoveFailedNodeRequest -( - uint8* _data -) +void Driver::HandleRemoveFailedNodeRequest(uint8* _data) { ControllerState state = ControllerState_Completed; - uint8 nodeId = GetNodeNumber( m_currentMsg ); - switch( _data[3] ) - { - case FAILED_NODE_OK: + uint8 nodeId = GetNodeNumber(m_currentMsg); + switch (_data[3]) { - Log::Write( LogLevel_Warning, nodeId, "WARNING: Received reply to FUNC_ID_ZW_REMOVE_FAILED_NODE_ID - Node %d is OK, so command failed", m_currentControllerCommand->m_controllerCommandNode ); - state = ControllerState_NodeOK; - break; - } - case FAILED_NODE_REMOVED: - { - Log::Write( LogLevel_Info, nodeId, "Received reply to FUNC_ID_ZW_REMOVE_FAILED_NODE_ID - node %d successfully moved to failed nodes list", m_currentControllerCommand->m_controllerCommandNode ); - state = ControllerState_Completed; + case FAILED_NODE_OK: { - LockGuard LG(m_nodeMutex); - delete m_nodes[m_currentControllerCommand->m_controllerCommandNode]; - m_nodes[m_currentControllerCommand->m_controllerCommandNode] = NULL; + Log::Write(LogLevel_Warning, nodeId, "WARNING: Received reply to FUNC_ID_ZW_REMOVE_FAILED_NODE_ID - Node %d is OK, so command failed", m_currentControllerCommand->m_controllerCommandNode); + state = ControllerState_NodeOK; + break; } - Notification* notification = new Notification( Notification::Type_NodeRemoved ); - notification->SetHomeAndNodeIds( m_homeId, m_currentControllerCommand->m_controllerCommandNode ); - QueueNotification( notification ); + case FAILED_NODE_REMOVED: + { + Log::Write(LogLevel_Info, nodeId, "Received reply to FUNC_ID_ZW_REMOVE_FAILED_NODE_ID - node %d successfully moved to failed nodes list", m_currentControllerCommand->m_controllerCommandNode); + state = ControllerState_Completed; + { + Internal::LockGuard LG(m_nodeMutex); + delete m_nodes[m_currentControllerCommand->m_controllerCommandNode]; + m_nodes[m_currentControllerCommand->m_controllerCommandNode] = NULL; + } + WriteCache(); + Notification* notification = new Notification(Notification::Type_NodeRemoved); + notification->SetHomeAndNodeIds(m_homeId, m_currentControllerCommand->m_controllerCommandNode); + QueueNotification(notification); - break; - } - case FAILED_NODE_NOT_REMOVED: - { - Log::Write( LogLevel_Warning, nodeId, "WARNING: Received reply to FUNC_ID_ZW_REMOVE_FAILED_NODE_ID - unable to move node %d to failed nodes list", m_currentControllerCommand->m_controllerCommandNode ); - state = ControllerState_Failed; - break; - } + break; + } + case FAILED_NODE_NOT_REMOVED: + { + Log::Write(LogLevel_Warning, nodeId, "WARNING: Received reply to FUNC_ID_ZW_REMOVE_FAILED_NODE_ID - unable to move node %d to failed nodes list", m_currentControllerCommand->m_controllerCommandNode); + state = ControllerState_Failed; + break; + } } - UpdateControllerState( state ); + UpdateControllerState(state); } //----------------------------------------------------------------------------- // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleReplaceFailedNodeRequest -( - uint8* _data -) +void Driver::HandleReplaceFailedNodeRequest(uint8* _data) { ControllerState state = ControllerState_Completed; - uint8 nodeId = GetNodeNumber( m_currentMsg ); - switch( _data[3] ) - { - case FAILED_NODE_OK: - { - Log::Write( LogLevel_Info, nodeId, "Received reply to FUNC_ID_ZW_REPLACE_FAILED_NODE - Node is OK, so command failed" ); - state = ControllerState_NodeOK; - break; - } - case FAILED_NODE_REPLACE_WAITING: - { - Log::Write( LogLevel_Info, nodeId, "Received reply to FUNC_ID_ZW_REPLACE_FAILED_NODE - Waiting for new node" ); - state = ControllerState_Waiting; - break; - } - case FAILED_NODE_REPLACE_DONE: + uint8 nodeId = GetNodeNumber(m_currentMsg); + switch (_data[3]) { - Log::Write( LogLevel_Info, nodeId, "Received reply to FUNC_ID_ZW_REPLACE_FAILED_NODE - Node successfully replaced" ); - state = ControllerState_Completed; + case FAILED_NODE_OK: + { + Log::Write(LogLevel_Info, nodeId, "Received reply to FUNC_ID_ZW_REPLACE_FAILED_NODE - Node is OK, so command failed"); + state = ControllerState_NodeOK; + break; + } + case FAILED_NODE_REPLACE_WAITING: + { + Log::Write(LogLevel_Info, nodeId, "Received reply to FUNC_ID_ZW_REPLACE_FAILED_NODE - Waiting for new node"); + state = ControllerState_Waiting; + break; + } + case FAILED_NODE_REPLACE_DONE: + { + Log::Write(LogLevel_Info, nodeId, "Received reply to FUNC_ID_ZW_REPLACE_FAILED_NODE - Node successfully replaced"); + state = ControllerState_Completed; - // Request new node info for this device - if( m_currentControllerCommand != NULL ) + // Request new node info for this device + if (m_currentControllerCommand != NULL) + { + InitNode(m_currentControllerCommand->m_controllerCommandNode, true); + } + WriteCache(); + break; + } + case FAILED_NODE_REPLACE_FAILED: { - InitNode( m_currentControllerCommand->m_controllerCommandNode, true ); + Log::Write(LogLevel_Info, nodeId, "Received reply to FUNC_ID_ZW_REPLACE_FAILED_NODE - Node replacement failed"); + state = ControllerState_Failed; + break; } - break; - } - case FAILED_NODE_REPLACE_FAILED: - { - Log::Write( LogLevel_Info, nodeId, "Received reply to FUNC_ID_ZW_REPLACE_FAILED_NODE - Node replacement failed" ); - state = ControllerState_Failed; - break; - } } - UpdateControllerState( state ); + UpdateControllerState(state); } //----------------------------------------------------------------------------- // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleApplicationCommandHandlerRequest -( - uint8* _data, - bool encrypted -) +void Driver::HandleApplicationCommandHandlerRequest(uint8* _data, bool encrypted) { uint8 status = _data[2]; uint8 nodeId = _data[3]; uint8 classId = _data[5]; - Node* node = GetNodeUnsafe( nodeId ); + Node* node = GetNodeUnsafe(nodeId); - if( ( status & RECEIVE_STATUS_ROUTED_BUSY ) != 0 ) + if ((status & RECEIVE_STATUS_ROUTED_BUSY) != 0) { m_routedbusy++; } - if( ( status & RECEIVE_STATUS_TYPE_BROAD ) != 0 ) + if ((status & RECEIVE_STATUS_TYPE_BROAD) != 0) { m_broadcastReadCnt++; } - if( node != NULL ) + if (node != NULL) { node->m_receivedCnt++; node->m_errors = 0; - int cmp = memcmp( _data, node->m_lastReceivedMessage, sizeof(node->m_lastReceivedMessage)); - if( cmp == 0 && node->m_receivedTS.TimeRemaining() > -500 ) + int cmp = memcmp(_data, node->m_lastReceivedMessage, sizeof(node->m_lastReceivedMessage)); + if (cmp == 0 && node->m_receivedTS.TimeRemaining() > -500) { // if the exact same sequence of bytes are received within 500ms node->m_receivedDups++; } else { - memcpy( node->m_lastReceivedMessage, _data, sizeof(node->m_lastReceivedMessage) ); + memcpy(node->m_lastReceivedMessage, _data, sizeof(node->m_lastReceivedMessage)); } node->m_receivedTS.SetTime(); - if( m_expectedReply == FUNC_ID_APPLICATION_COMMAND_HANDLER && m_expectedNodeId == nodeId ) + if (m_expectedReply == FUNC_ID_APPLICATION_COMMAND_HANDLER && m_expectedNodeId == nodeId) { // Need to confirm this is the correct response to the last sent request. // At least ignore any received messages prior to the send data request. node->m_lastResponseRTT = -node->m_sentTS.TimeRemaining(); - if( node->m_averageResponseRTT ) + if (node->m_averageResponseRTT) { // if the average has been established, update by averaging the average and the last RTT - node->m_averageResponseRTT = ( node->m_averageResponseRTT + node->m_lastResponseRTT ) >> 1; + node->m_averageResponseRTT = (node->m_averageResponseRTT + node->m_lastResponseRTT) >> 1; } else { // if this is the first observed RTT, set the average to this value node->m_averageResponseRTT = node->m_lastResponseRTT; } - Log::Write(LogLevel_Info, nodeId, "Response RTT %d Average Response RTT %d", node->m_lastResponseRTT, node->m_averageResponseRTT ); + Log::Write(LogLevel_Info, nodeId, "Response RTT %d Average Response RTT %d", node->m_lastResponseRTT, node->m_averageResponseRTT); } else { node->m_receivedUnsolicited++; } - if ( !node->IsNodeAlive() ) + if (!node->IsNodeAlive()) { - node->SetNodeAlive( true ); + node->SetNodeAlive(true); } } - if( ApplicationStatus::StaticGetCommandClassId() == classId ) + if (Internal::CC::ApplicationStatus::StaticGetCommandClassId() == classId) { //TODO: Test this class function or implement } - else if( ControllerReplication::StaticGetCommandClassId() == classId ) + else if (Internal::CC::ControllerReplication::StaticGetCommandClassId() == classId) { - if( m_controllerReplication && m_currentControllerCommand && ( ControllerCommand_ReceiveConfiguration == m_currentControllerCommand->m_controllerCommand ) ) + if (m_controllerReplication && m_currentControllerCommand && (ControllerCommand_ReceiveConfiguration == m_currentControllerCommand->m_controllerCommand)) { - m_controllerReplication->HandleMsg( &_data[6], _data[4] ); + m_controllerReplication->HandleMsg(&_data[6], _data[4]); - UpdateControllerState( ControllerState_InProgress ); + UpdateControllerState(ControllerState_InProgress); } } else { // Allow the node to handle the message itself - if( node != NULL ) + if (node != NULL) { - node->ApplicationCommandHandler( _data, encrypted ); + node->ApplicationCommandHandler(_data, encrypted); } } } @@ -3818,10 +3617,7 @@ void Driver::HandleApplicationCommandHandlerRequest // // Process a request from the Z-Wave PC interface when in promiscuous mode. //----------------------------------------------------------------------------- -void Driver::HandlePromiscuousApplicationCommandHandlerRequest -( - uint8* _data -) +void Driver::HandlePromiscuousApplicationCommandHandlerRequest(uint8* _data) { //uint8 nodeId = _data[3]; //uint8 len = _data[4]; @@ -3833,245 +3629,230 @@ void Driver::HandlePromiscuousApplicationCommandHandlerRequest // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleAssignReturnRouteRequest -( - uint8* _data -) +void Driver::HandleAssignReturnRouteRequest(uint8* _data) { ControllerState state; - uint8 nodeId = GetNodeNumber( m_currentMsg ); - if( m_currentControllerCommand == NULL ) + uint8 nodeId = GetNodeNumber(m_currentMsg); + if (m_currentControllerCommand == NULL) { return; } - if( _data[3] ) + if (_data[3]) { // Failed - HandleErrorResponse( _data[3], m_currentControllerCommand->m_controllerCommandNode, "ZW_ASSIGN_RETURN_ROUTE", true ); + HandleErrorResponse(_data[3], m_currentControllerCommand->m_controllerCommandNode, "ZW_ASSIGN_RETURN_ROUTE", true); state = ControllerState_Failed; } else { // Success - Log::Write( LogLevel_Info, nodeId, "Received reply to FUNC_ID_ZW_ASSIGN_RETURN_ROUTE for node %d - SUCCESS", m_currentControllerCommand->m_controllerCommandNode ); + Log::Write(LogLevel_Info, nodeId, "Received reply to FUNC_ID_ZW_ASSIGN_RETURN_ROUTE for node %d - SUCCESS", m_currentControllerCommand->m_controllerCommandNode); state = ControllerState_Completed; } - UpdateControllerState( state ); + UpdateControllerState(state); } //----------------------------------------------------------------------------- // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleDeleteReturnRouteRequest -( - uint8* _data -) +void Driver::HandleDeleteReturnRouteRequest(uint8* _data) { ControllerState state; - uint8 nodeId = GetNodeNumber( m_currentMsg ); - if( m_currentControllerCommand == NULL ) + uint8 nodeId = GetNodeNumber(m_currentMsg); + if (m_currentControllerCommand == NULL) { return; } - if( _data[3] != TRANSMIT_COMPLETE_OK) + if (_data[3] != TRANSMIT_COMPLETE_OK) { // Failed - HandleErrorResponse( _data[3], m_currentControllerCommand->m_controllerCommandNode, "ZW_DELETE_RETURN_ROUTE", true ); + HandleErrorResponse(_data[3], m_currentControllerCommand->m_controllerCommandNode, "ZW_DELETE_RETURN_ROUTE", true); state = ControllerState_Failed; } else { // Success - Log::Write( LogLevel_Info, nodeId, "Received reply to FUNC_ID_ZW_DELETE_RETURN_ROUTE for node %d - SUCCESS", m_currentControllerCommand->m_controllerCommandNode ); + Log::Write(LogLevel_Info, nodeId, "Received reply to FUNC_ID_ZW_DELETE_RETURN_ROUTE for node %d - SUCCESS", m_currentControllerCommand->m_controllerCommandNode); state = ControllerState_Completed; } - UpdateControllerState( state ); + UpdateControllerState(state); } //----------------------------------------------------------------------------- // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleSendNodeInformationRequest -( - uint8* _data -) +void Driver::HandleSendNodeInformationRequest(uint8* _data) { ControllerState state; - uint8 nodeId = GetNodeNumber( m_currentMsg ); - if( m_currentControllerCommand == NULL ) + uint8 nodeId = GetNodeNumber(m_currentMsg); + if (m_currentControllerCommand == NULL) { return; } - if( _data[3] != TRANSMIT_COMPLETE_OK ) + if (_data[3] != TRANSMIT_COMPLETE_OK) { // Failed - HandleErrorResponse( _data[3], m_currentControllerCommand->m_controllerCommandNode, "ZW_SEND_NODE_INFORMATION" ); + HandleErrorResponse(_data[3], m_currentControllerCommand->m_controllerCommandNode, "ZW_SEND_NODE_INFORMATION"); state = ControllerState_Failed; } else { // Success - Log::Write( LogLevel_Info, nodeId, "Received reply to FUNC_ID_ZW_SEND_NODE_INFORMATION - SUCCESS" ); + Log::Write(LogLevel_Info, nodeId, "Received reply to FUNC_ID_ZW_SEND_NODE_INFORMATION - SUCCESS"); state = ControllerState_Completed; } - UpdateControllerState( state ); + UpdateControllerState(state); } //----------------------------------------------------------------------------- // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleNodeNeighborUpdateRequest -( - uint8* _data -) +void Driver::HandleNodeNeighborUpdateRequest(uint8* _data) { - uint8 nodeId = GetNodeNumber( m_currentMsg ); + uint8 nodeId = GetNodeNumber(m_currentMsg); ControllerState state = ControllerState_Normal; - switch( _data[3] ) - { - case REQUEST_NEIGHBOR_UPDATE_STARTED: + switch (_data[3]) { - Log::Write( LogLevel_Info, nodeId, "REQUEST_NEIGHBOR_UPDATE_STARTED" ); - state = ControllerState_InProgress; - break; - } - case REQUEST_NEIGHBOR_UPDATE_DONE: - { - Log::Write( LogLevel_Info, nodeId, "REQUEST_NEIGHBOR_UPDATE_DONE" ); - state = ControllerState_Completed; + case REQUEST_NEIGHBOR_UPDATE_STARTED: + { + Log::Write(LogLevel_Info, nodeId, "REQUEST_NEIGHBOR_UPDATE_STARTED"); + state = ControllerState_InProgress; + break; + } + case REQUEST_NEIGHBOR_UPDATE_DONE: + { + Log::Write(LogLevel_Info, nodeId, "REQUEST_NEIGHBOR_UPDATE_DONE"); + state = ControllerState_Completed; - // We now request the neighbour information from the - // controller and store it in our node object. - if( m_currentControllerCommand != NULL ) + // We now request the neighbour information from the + // controller and store it in our node object. + if (m_currentControllerCommand != NULL) + { + RequestNodeNeighbors(m_currentControllerCommand->m_controllerCommandNode, 0); + } + break; + } + case REQUEST_NEIGHBOR_UPDATE_FAILED: { - RequestNodeNeighbors( m_currentControllerCommand->m_controllerCommandNode, 0 ); + Log::Write(LogLevel_Warning, nodeId, "WARNING: REQUEST_NEIGHBOR_UPDATE_FAILED"); + state = ControllerState_Failed; + break; + } + default: + { + break; } - break; - } - case REQUEST_NEIGHBOR_UPDATE_FAILED: - { - Log::Write( LogLevel_Warning, nodeId, "WARNING: REQUEST_NEIGHBOR_UPDATE_FAILED" ); - state = ControllerState_Failed; - break; - } - default: - { - break; - } } - UpdateControllerState( state ); + UpdateControllerState(state); } //----------------------------------------------------------------------------- // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- -bool Driver::HandleApplicationUpdateRequest -( - uint8* _data -) +bool Driver::HandleApplicationUpdateRequest(uint8* _data) { bool messageRemoved = false; uint8 nodeId = _data[3]; - Node* node = GetNodeUnsafe( nodeId ); + Node* node = GetNodeUnsafe(nodeId); // If node is not alive, mark it alive now - if( node != NULL && !node->IsNodeAlive() ) + if (node != NULL && !node->IsNodeAlive()) { - node->SetNodeAlive( true ); + node->SetNodeAlive(true); } - switch( _data[2] ) + switch (_data[2]) { - case UPDATE_STATE_SUC_ID: + case UPDATE_STATE_SUC_ID: { - Log::Write( LogLevel_Info, nodeId, "UPDATE_STATE_SUC_ID from node %d", nodeId ); + Log::Write(LogLevel_Info, nodeId, "UPDATE_STATE_SUC_ID from node %d", nodeId); m_SUCNodeId = nodeId; // need to confirm real data here break; } - case UPDATE_STATE_DELETE_DONE: + case UPDATE_STATE_DELETE_DONE: { - Log::Write( LogLevel_Info, nodeId, "** Network change **: Z-Wave node %d was removed", nodeId ); + Log::Write(LogLevel_Info, nodeId, "** Network change **: Z-Wave node %d was removed", nodeId); { - LockGuard LG(m_nodeMutex); + Internal::LockGuard LG(m_nodeMutex); delete m_nodes[nodeId]; m_nodes[nodeId] = NULL; } - Notification* notification = new Notification( Notification::Type_NodeRemoved ); - notification->SetHomeAndNodeIds( m_homeId, nodeId ); - QueueNotification( notification ); - break; + Notification* notification = new Notification(Notification::Type_NodeRemoved); + notification->SetHomeAndNodeIds(m_homeId, nodeId); + QueueNotification(notification); + break; } - case UPDATE_STATE_NEW_ID_ASSIGNED: - { - Log::Write( LogLevel_Info, nodeId, "** Network change **: ID %d was assigned to a new Z-Wave node", nodeId ); - // Check if the new node id is equal to the current one.... if so no operation is needed, thus no remove and add is necessary - if ( _data[3] != _data[6] ) + case UPDATE_STATE_NEW_ID_ASSIGNED: { - // Request the node protocol info (also removes any existing node and creates a new one) - InitNode( nodeId ); + Log::Write(LogLevel_Info, nodeId, "** Network change **: ID %d was assigned to a new Z-Wave node", nodeId); + // Check if the new node id is equal to the current one.... if so no operation is needed, thus no remove and add is necessary + if (_data[3] != _data[6]) + { + // Request the node protocol info (also removes any existing node and creates a new one) + InitNode(nodeId); + } + else + { + Log::Write(LogLevel_Info, nodeId, "Not Re-assigning NodeID as old and new NodeID match"); + } + + break; } - else + case UPDATE_STATE_ROUTING_PENDING: { - Log::Write(LogLevel_Info, nodeId, "Not Re-assigning NodeID as old and new NodeID match"); + Log::Write(LogLevel_Info, nodeId, "UPDATE_STATE_ROUTING_PENDING from node %d", nodeId); + break; } - - break; - } - case UPDATE_STATE_ROUTING_PENDING: - { - Log::Write( LogLevel_Info, nodeId, "UPDATE_STATE_ROUTING_PENDING from node %d", nodeId ); - break; - } - case UPDATE_STATE_NODE_INFO_REQ_FAILED: - { - Log::Write( LogLevel_Warning, nodeId, "WARNING: FUNC_ID_ZW_APPLICATION_UPDATE: UPDATE_STATE_NODE_INFO_REQ_FAILED received" ); - - // Note: Unhelpfully, the nodeId is always zero in this message. We have to - // assume the message came from the last node to which we sent a request. - if( m_currentMsg ) + case UPDATE_STATE_NODE_INFO_REQ_FAILED: { - Node* tnode = GetNodeUnsafe( m_currentMsg->GetTargetNodeId() ); - if( tnode ) - { - // Retry the query twice - tnode->QueryStageRetry( Node::QueryStage_NodeInfo, 2 ); + Log::Write(LogLevel_Warning, nodeId, "WARNING: FUNC_ID_ZW_APPLICATION_UPDATE: UPDATE_STATE_NODE_INFO_REQ_FAILED received"); - // Just in case the failure was due to the node being asleep, we try - // to move its pending messages to its wakeup queue. If it is not - // a sleeping device, this will have no effect. - if( MoveMessagesToWakeUpQueue( tnode->GetNodeId(), true ) ) + // Note: Unhelpfully, the nodeId is always zero in this message. We have to + // assume the message came from the last node to which we sent a request. + if (m_currentMsg) + { + Node* tnode = GetNodeUnsafe(m_currentMsg->GetTargetNodeId()); + if (tnode) { - messageRemoved = true; + // Retry the query twice + tnode->QueryStageRetry(Node::QueryStage_NodeInfo, 2); + + // Just in case the failure was due to the node being asleep, we try + // to move its pending messages to its wakeup queue. If it is not + // a sleeping device, this will have no effect. + if (MoveMessagesToWakeUpQueue(tnode->GetNodeId(), true)) + { + messageRemoved = true; + } } } + break; } - break; - } - case UPDATE_STATE_NODE_INFO_REQ_DONE: - { - Log::Write( LogLevel_Info, nodeId, "UPDATE_STATE_NODE_INFO_REQ_DONE from node %d", nodeId ); - break; - } - case UPDATE_STATE_NODE_INFO_RECEIVED: - { - Log::Write( LogLevel_Info, nodeId, "UPDATE_STATE_NODE_INFO_RECEIVED from node %d", nodeId ); - if( node ) + case UPDATE_STATE_NODE_INFO_REQ_DONE: { - node->UpdateNodeInfo( &_data[8], _data[4] - 3 ); + Log::Write(LogLevel_Info, nodeId, "UPDATE_STATE_NODE_INFO_REQ_DONE from node %d", nodeId); + break; + } + case UPDATE_STATE_NODE_INFO_RECEIVED: + { + Log::Write(LogLevel_Info, nodeId, "UPDATE_STATE_NODE_INFO_RECEIVED from node %d", nodeId); + if (node) + { + node->UpdateNodeInfo(&_data[8], _data[4] - 3); + } + break; } - break; - } } - if( messageRemoved ) + if (messageRemoved) { m_waitingForAck = false; m_expectedCallbackId = 0; @@ -4087,136 +3868,134 @@ bool Driver::HandleApplicationUpdateRequest // // Handle common AddNode processing for many similar commands //----------------------------------------------------------------------------- -void Driver::CommonAddNodeStatusRequestHandler -( - uint8 _funcId, - uint8* _data -) +void Driver::CommonAddNodeStatusRequestHandler(uint8 _funcId, uint8* _data) { - uint8 nodeId = GetNodeNumber( m_currentMsg ); + uint8 nodeId = GetNodeNumber(m_currentMsg); ControllerState state = ControllerState_Normal; - if( m_currentControllerCommand != NULL ) + if (m_currentControllerCommand != NULL) { state = m_currentControllerCommand->m_controllerState; } - switch( _data[3] ) - { - case ADD_NODE_STATUS_LEARN_READY: - { - Log::Write( LogLevel_Info, nodeId, "ADD_NODE_STATUS_LEARN_READY" ); - m_currentControllerCommand->m_controllerAdded = false; - state = ControllerState_Waiting; - break; - } - case ADD_NODE_STATUS_NODE_FOUND: - { - Log::Write( LogLevel_Info, nodeId, "ADD_NODE_STATUS_NODE_FOUND" ); - state = ControllerState_InProgress; - break; - } - case ADD_NODE_STATUS_ADDING_SLAVE: + switch (_data[3]) { - Log::Write( LogLevel_Info, nodeId, "ADD_NODE_STATUS_ADDING_SLAVE" ); - Log::Write( LogLevel_Info, nodeId, "Adding node ID %d - %s", _data[4], m_currentControllerCommand->m_controllerCommandArg ? "Secure" : "Non-Secure"); - /* Discovered all the CC's are sent in this packet as well: - * position description - * 4 - Node ID - * 5 - Length - * 6 - Basic Device Class - * 7 - Generic Device Class - * 8 - Specific Device Class - * 9 to Length - Command Classes - * Last pck - CRC - */ - if( m_currentControllerCommand != NULL ) + case ADD_NODE_STATUS_LEARN_READY: { + Log::Write(LogLevel_Info, nodeId, "ADD_NODE_STATUS_LEARN_READY"); m_currentControllerCommand->m_controllerAdded = false; - m_currentControllerCommand->m_controllerCommandNode = _data[4]; - /* make sure we dont overrun our buffer. Its ok to truncate */ - uint8 length = _data[5]; - if (length > 254) length = 254; - memcpy(&m_currentControllerCommand->m_controllerDeviceProtocolInfo, &_data[6], length); - m_currentControllerCommand->m_controllerDeviceProtocolInfoLength = length; - } - // AddNodeStop( _funcId ); - // sleep(1); - break; - } - case ADD_NODE_STATUS_ADDING_CONTROLLER: - { - Log::Write( LogLevel_Info, nodeId, "ADD_NODE_STATUS_ADDING_CONTROLLER"); - Log::Write( LogLevel_Info, nodeId, "Adding controller ID %d", _data[4] ); - /* Discovered all the CC's are sent in this packet as well: - * position description - * 4 - Node ID - * 5 - Length - * 6 - Basic Device Class - * 7 - Generic Device Class - * 8 - Specific Device Class - * 9 to Length - Command Classes - * Last pck - CRC - */ - - if( m_currentControllerCommand != NULL ) - { - m_currentControllerCommand->m_controllerAdded = true; - m_currentControllerCommand->m_controllerCommandNode = _data[4]; + state = ControllerState_Waiting; + break; } - // AddNodeStop( _funcId ); - break; - } - case ADD_NODE_STATUS_PROTOCOL_DONE: - { - Log::Write( LogLevel_Info, nodeId, "ADD_NODE_STATUS_PROTOCOL_DONE" ); - // We added a device. - // Get the controller out of add mode to avoid accidentally adding other devices. - // We used to call replication here. - AddNodeStop( _funcId ); - break; - } - case ADD_NODE_STATUS_DONE: - { - if (state == ControllerState_Failed) { - /* if it was a failed add, we just move on */ - state = ControllerState_Completed; + case ADD_NODE_STATUS_NODE_FOUND: + { + Log::Write(LogLevel_Info, nodeId, "ADD_NODE_STATUS_NODE_FOUND"); + state = ControllerState_InProgress; break; } - - Log::Write( LogLevel_Info, nodeId, "ADD_NODE_STATUS_DONE" ); - state = ControllerState_Completed; - if( m_currentControllerCommand != NULL && m_currentControllerCommand->m_controllerCommandNode != 0xff ) + case ADD_NODE_STATUS_ADDING_SLAVE: + { + Log::Write(LogLevel_Info, nodeId, "ADD_NODE_STATUS_ADDING_SLAVE"); + Log::Write(LogLevel_Info, nodeId, "Adding node ID %d - %s", _data[4], m_currentControllerCommand->m_controllerCommandArg ? "Secure" : "Non-Secure"); + /* Discovered all the CC's are sent in this packet as well: + * position description + * 4 - Node ID + * 5 - Length + * 6 - Basic Device Class + * 7 - Generic Device Class + * 8 - Specific Device Class + * 9 to Length - Command Classes + * Last pck - CRC + */ + if (m_currentControllerCommand != NULL) + { + m_currentControllerCommand->m_controllerAdded = false; + m_currentControllerCommand->m_controllerCommandNode = _data[4]; + /* make sure we dont overrun our buffer. Its ok to truncate */ + uint8 length = _data[5]; + if (length > 254) + length = 254; + memcpy(&m_currentControllerCommand->m_controllerDeviceProtocolInfo, &_data[6], length); + m_currentControllerCommand->m_controllerDeviceProtocolInfoLength = length; + } + // AddNodeStop( _funcId ); + // sleep(1); + break; + } + case ADD_NODE_STATUS_ADDING_CONTROLLER: + { + Log::Write(LogLevel_Info, nodeId, "ADD_NODE_STATUS_ADDING_CONTROLLER"); + Log::Write(LogLevel_Info, nodeId, "Adding controller ID %d", _data[4]); + /* Discovered all the CC's are sent in this packet as well: + * position description + * 4 - Node ID + * 5 - Length + * 6 - Basic Device Class + * 7 - Generic Device Class + * 8 - Specific Device Class + * 9 to Length - Command Classes + * Last pck - CRC + */ + + if (m_currentControllerCommand != NULL) + { + m_currentControllerCommand->m_controllerAdded = true; + m_currentControllerCommand->m_controllerCommandNode = _data[4]; + } + // AddNodeStop( _funcId ); + break; + } + case ADD_NODE_STATUS_PROTOCOL_DONE: { - InitNode( m_currentControllerCommand->m_controllerCommandNode, true, m_currentControllerCommand->m_controllerCommandArg != 0, m_currentControllerCommand->m_controllerDeviceProtocolInfo, m_currentControllerCommand->m_controllerDeviceProtocolInfoLength ); + Log::Write(LogLevel_Info, nodeId, "ADD_NODE_STATUS_PROTOCOL_DONE"); + // We added a device. + // Get the controller out of add mode to avoid accidentally adding other devices. + // We used to call replication here. + AddNodeStop(_funcId); + break; } - - // Not sure about the new controller function here. - if( _funcId != FUNC_ID_ZW_ADD_NODE_TO_NETWORK && m_currentControllerCommand != NULL && m_currentControllerCommand->m_controllerAdded ) + case ADD_NODE_STATUS_DONE: { - // Rebuild all the node info. Group and scene data that we stored - // during replication will be applied as we discover each node. - InitAllNodes(); + if (state == ControllerState_Failed) + { + /* if it was a failed add, we just move on */ + state = ControllerState_Completed; + break; + } + + Log::Write(LogLevel_Info, nodeId, "ADD_NODE_STATUS_DONE"); + state = ControllerState_Completed; + if (m_currentControllerCommand != NULL && m_currentControllerCommand->m_controllerCommandNode != 0xff) + { + InitNode(m_currentControllerCommand->m_controllerCommandNode, true, m_currentControllerCommand->m_controllerCommandArg != 0, m_currentControllerCommand->m_controllerDeviceProtocolInfo, m_currentControllerCommand->m_controllerDeviceProtocolInfoLength); + } + + // Not sure about the new controller function here. + if (_funcId != FUNC_ID_ZW_ADD_NODE_TO_NETWORK && m_currentControllerCommand != NULL && m_currentControllerCommand->m_controllerAdded) + { + // Rebuild all the node info. Group and scene data that we stored + // during replication will be applied as we discover each node. + InitAllNodes(); + } + break; } - break; - } - case ADD_NODE_STATUS_FAILED: - { - Log::Write( LogLevel_Info, nodeId, "ADD_NODE_STATUS_FAILED" ); - state = ControllerState_Failed; + case ADD_NODE_STATUS_FAILED: + { + Log::Write(LogLevel_Info, nodeId, "ADD_NODE_STATUS_FAILED"); + state = ControllerState_Failed; - // Remove the AddNode command from the queue - RemoveCurrentMsg(); + // Remove the AddNode command from the queue + RemoveCurrentMsg(); - // Get the controller out of add mode to avoid accidentally adding other devices. - AddNodeStop( _funcId ); - break; - } - default: - { - break; - } + // Get the controller out of add mode to avoid accidentally adding other devices. + AddNodeStop(_funcId); + break; + } + default: + { + break; + } } - UpdateControllerState( state ); + UpdateControllerState(state); } //----------------------------------------------------------------------------- @@ -4227,35 +4006,31 @@ void Driver::CommonAddNodeStatusRequestHandler // // Enable polling of a value //----------------------------------------------------------------------------- -bool Driver::EnablePoll -( - ValueID const &_valueId, - uint8 const _intensity -) +bool Driver::EnablePoll(ValueID const &_valueId, uint8 const _intensity) { // make sure the polling thread doesn't lock the node while we're in this function m_pollMutex->Lock(); // confirm that this node exists uint8 nodeId = _valueId.GetNodeId(); - LockGuard LG(m_nodeMutex); - Node* node = GetNode( nodeId ); - if( node != NULL ) + Internal::LockGuard LG(m_nodeMutex); + Node* node = GetNode(nodeId); + if (node != NULL) { // confirm that this value is in the node's value store - if( Value* value = node->GetValue( _valueId ) ) + if (Internal::VC::Value* value = node->GetValue(_valueId)) { // update the value's pollIntensity - value->SetPollIntensity( _intensity ); + value->SetPollIntensity(_intensity); // Add the valueid to the polling list // See if the node is already in the poll list. - for( list::iterator it = m_pollList.begin(); it != m_pollList.end(); ++it ) + for (list::iterator it = m_pollList.begin(); it != m_pollList.end(); ++it) { - if( (*it).m_id == _valueId ) + if ((*it).m_id == _valueId) { // It is already in the poll list, so we have nothing to do. - Log::Write( LogLevel_Detail, "EnablePoll not required to do anything (value is already in the poll list)" ); + Log::Write(LogLevel_Detail, "EnablePoll not required to do anything (value is already in the poll list)"); value->Release(); m_pollMutex->Unlock(); return true; @@ -4266,30 +4041,30 @@ bool Driver::EnablePoll PollEntry pe; pe.m_id = _valueId; pe.m_pollCounter = value->GetPollIntensity(); - m_pollList.push_back( pe ); + m_pollList.push_back(pe); value->Release(); m_pollMutex->Unlock(); // send notification to indicate polling is enabled - Notification* notification = new Notification( Notification::Type_PollingEnabled ); - notification->SetHomeAndNodeIds( m_homeId, _valueId.GetNodeId() ); - QueueNotification( notification ); - Log::Write( LogLevel_Info, nodeId, "EnablePoll for HomeID 0x%.8x, value(cc=0x%02x,in=0x%02x,id=0x%02x)--poll list has %d items", - _valueId.GetHomeId(), _valueId.GetCommandClassId(), _valueId.GetIndex(), _valueId.GetInstance(), m_pollList.size() ); + Notification* notification = new Notification(Notification::Type_PollingEnabled); + notification->SetHomeAndNodeIds(m_homeId, _valueId.GetNodeId()); + notification->SetValueId(_valueId); + QueueNotification(notification); + Log::Write(LogLevel_Info, nodeId, "EnablePoll for HomeID 0x%.8x, value(cc=0x%02x,in=0x%02x,id=0x%02x)--poll list has %d items", _valueId.GetHomeId(), _valueId.GetCommandClassId(), _valueId.GetIndex(), _valueId.GetInstance(), m_pollList.size()); return true; } // allow the poll thread to continue m_pollMutex->Unlock(); - Log::Write( LogLevel_Info, nodeId, "EnablePoll failed - value not found for node %d", nodeId ); + Log::Write(LogLevel_Info, nodeId, "EnablePoll failed - value not found for node %d", nodeId); return false; } // allow the poll thread to continue m_pollMutex->Unlock(); - Log::Write( LogLevel_Info, "EnablePoll failed - node %d not found", nodeId ); + Log::Write(LogLevel_Info, "EnablePoll failed - node %d not found", nodeId); return false; } @@ -4297,57 +4072,54 @@ bool Driver::EnablePoll // // Disable polling of a node //----------------------------------------------------------------------------- -bool Driver::DisablePoll -( - ValueID const &_valueId -) +bool Driver::DisablePoll(ValueID const &_valueId) { // make sure the polling thread doesn't lock the node while we're in this function m_pollMutex->Lock(); // confirm that this node exists uint8 nodeId = _valueId.GetNodeId(); - LockGuard LG(m_nodeMutex); - Node* node = GetNode( nodeId ); - if( node != NULL) + Internal::LockGuard LG(m_nodeMutex); + Node* node = GetNode(nodeId); + if (node != NULL) { // See if the value is already in the poll list. - for( list::iterator it = m_pollList.begin(); it != m_pollList.end(); ++it ) + for (list::iterator it = m_pollList.begin(); it != m_pollList.end(); ++it) { - if( (*it).m_id == _valueId ) + if ((*it).m_id == _valueId) { // Found it // remove it from the poll list - m_pollList.erase( it ); + m_pollList.erase(it); // get the value object and reset pollIntensity to zero (indicating no polling) - Value* value = GetValue( _valueId ); + Internal::VC::Value* value = GetValue(_valueId); if (!value) continue; - value->SetPollIntensity( 0 ); + value->SetPollIntensity(0); value->Release(); m_pollMutex->Unlock(); // send notification to indicate polling is disabled - Notification* notification = new Notification( Notification::Type_PollingDisabled ); - notification->SetHomeAndNodeIds( m_homeId, _valueId.GetNodeId() ); - QueueNotification( notification ); - Log::Write( LogLevel_Info, nodeId, "DisablePoll for HomeID 0x%.8x, value(cc=0x%02x,in=0x%02x,id=0x%02x)--poll list has %d items", - _valueId.GetHomeId(), _valueId.GetCommandClassId(), _valueId.GetIndex(), _valueId.GetInstance(), m_pollList.size() ); + Notification* notification = new Notification(Notification::Type_PollingDisabled); + notification->SetHomeAndNodeIds(m_homeId, _valueId.GetNodeId()); + notification->SetValueId(_valueId); + QueueNotification(notification); + Log::Write(LogLevel_Info, nodeId, "DisablePoll for HomeID 0x%.8x, value(cc=0x%02x,in=0x%02x,id=0x%02x)--poll list has %d items", _valueId.GetHomeId(), _valueId.GetCommandClassId(), _valueId.GetIndex(), _valueId.GetInstance(), m_pollList.size()); return true; } } // Not in the list m_pollMutex->Unlock(); - Log::Write( LogLevel_Info, nodeId, "DisablePoll failed - value not on list"); + Log::Write(LogLevel_Info, nodeId, "DisablePoll failed - value not on list"); return false; } // allow the poll thread to continue m_pollMutex->Unlock(); - Log::Write( LogLevel_Info, "DisablePoll failed - node %d not found", nodeId ); + Log::Write(LogLevel_Info, "DisablePoll failed - node %d not found", nodeId); return false; } @@ -4355,18 +4127,15 @@ bool Driver::DisablePoll // // Check polling status of a value //----------------------------------------------------------------------------- -bool Driver::isPolled -( - ValueID const &_valueId -) +bool Driver::isPolled(ValueID const &_valueId) { bool bPolled; // make sure the polling thread doesn't lock the node while we're in this function m_pollMutex->Lock(); - Value* value = GetValue( _valueId ); - if( value && value->GetPollIntensity() != 0 ) + Internal::VC::Value* value = GetValue(_valueId); + if (value && value->GetPollIntensity() != 0) { bPolled = true; } @@ -4375,7 +4144,8 @@ bool Driver::isPolled bPolled = false; } - if (value) value->Release(); + if (value) + value->Release(); /* * This code is retained for the moment as a belt-and-suspenders test to confirm that @@ -4384,46 +4154,46 @@ bool Driver::isPolled */ // confirm that this node exists uint8 nodeId = _valueId.GetNodeId(); - LockGuard LG(m_nodeMutex); - Node* node = GetNode( nodeId ); - if( node != NULL) + Internal::LockGuard LG(m_nodeMutex); + Node* node = GetNode(nodeId); + if (node != NULL) { // See if the value is already in the poll list. - for( list::iterator it = m_pollList.begin(); it != m_pollList.end(); ++it ) + for (list::iterator it = m_pollList.begin(); it != m_pollList.end(); ++it) { - if( (*it).m_id == _valueId ) + if ((*it).m_id == _valueId) { // Found it - if( bPolled ) + if (bPolled) { m_pollMutex->Unlock(); return true; } else { - Log::Write( LogLevel_Error, nodeId, "IsPolled setting for valueId 0x%016x is not consistent with the poll list", _valueId.GetId() ); + Log::Write(LogLevel_Error, nodeId, "IsPolled setting for valueId 0x%016x is not consistent with the poll list", _valueId.GetId()); } } } // Not in the list - if( !bPolled ) + if (!bPolled) { m_pollMutex->Unlock(); return false; } else { - Log::Write( LogLevel_Error, nodeId, "IsPolled setting for valueId 0x%016x is not consistent with the poll list", _valueId.GetId() ); + Log::Write(LogLevel_Error, nodeId, "IsPolled setting for valueId 0x%016x is not consistent with the poll list", _valueId.GetId()); } } // allow the poll thread to continue m_pollMutex->Unlock(); - Log::Write( LogLevel_Info, "isPolled failed - node %d not found (the value reported that it is%s polled)", nodeId, bPolled?"":" not" ); + Log::Write(LogLevel_Info, "isPolled failed - node %d not found (the value reported that it is%s polled)", nodeId, bPolled ? "" : " not"); return false; } @@ -4431,19 +4201,15 @@ bool Driver::isPolled // // Set the intensity with which this value is polled //----------------------------------------------------------------------------- -void Driver::SetPollIntensity -( - ValueID const &_valueId, - uint8 const _intensity -) +void Driver::SetPollIntensity(ValueID const &_valueId, uint8 const _intensity) { // make sure the polling thread doesn't lock the value while we're in this function m_pollMutex->Lock(); - Value* value = GetValue( _valueId ); + Internal::VC::Value* value = GetValue(_valueId); if (!value) return; - value->SetPollIntensity( _intensity ); + value->SetPollIntensity(_intensity); value->Release(); m_pollMutex->Unlock(); @@ -4453,16 +4219,12 @@ void Driver::SetPollIntensity // // Entry point of the thread for poll Z-Wave devices //----------------------------------------------------------------------------- -void Driver::PollThreadEntryPoint -( - Event* _exitEvent, - void* _context -) +void Driver::PollThreadEntryPoint(Internal::Platform::Event* _exitEvent, void* _context) { - Driver* driver = (Driver*)_context; - if( driver ) + Driver* driver = (Driver*) _context; + if (driver) { - driver->PollThreadProc( _exitEvent ); + driver->PollThreadProc(_exitEvent); } } @@ -4470,16 +4232,13 @@ void Driver::PollThreadEntryPoint // // Thread for poll Z-Wave devices //----------------------------------------------------------------------------- -void Driver::PollThreadProc -( - Event* _exitEvent -) +void Driver::PollThreadProc(Internal::Platform::Event* _exitEvent) { - while( 1 ) + while (1) { int32 pollInterval = m_pollInterval; - if( m_awakeNodesQueried && !m_pollList.empty() ) + if (m_awakeNodesQueried && !m_pollList.empty()) { // We only bother getting the lock if the pollList is not empty m_pollMutex->Lock(); @@ -4487,13 +4246,13 @@ void Driver::PollThreadProc // Get the next value to be polled PollEntry pe = m_pollList.front(); m_pollList.pop_front(); - ValueID valueId = pe.m_id; + ValueID valueId = pe.m_id; // only execute this poll if pe.m_pollCounter == 1; otherwise decrement the counter and process the next polled value - if( pe.m_pollCounter != 1) + if (pe.m_pollCounter != 1) { pe.m_pollCounter--; - m_pollList.push_back( pe ); + m_pollList.push_back(pe); m_pollMutex->Unlock(); continue; } @@ -4501,40 +4260,40 @@ void Driver::PollThreadProc // reset the poll counter to the full pollIntensity value and push it at the end of the list // release the value object referenced; call GetNode to ensure the node objects are locked during this period { - LockGuard LG(m_nodeMutex); - (void)GetNode( valueId.GetNodeId() ); - Value* value = GetValue( valueId ); + Internal::LockGuard LG(m_nodeMutex); + (void) GetNode(valueId.GetNodeId()); + Internal::VC::Value* value = GetValue(valueId); if (!value) continue; pe.m_pollCounter = value->GetPollIntensity(); - m_pollList.push_back( pe ); + m_pollList.push_back(pe); value->Release(); } // If the polling interval is for the whole poll list, calculate the time before the next poll, // so that all polls can take place within the user-specified interval. - if( !m_bIntervalBetweenPolls ) + if (!m_bIntervalBetweenPolls) { - if( pollInterval < 100 ) + if (pollInterval < 100) { - Log::Write( LogLevel_Info, "The pollInterval setting is only %d, which appears to be a legacy setting. Multiplying by 1000 to convert to ms.", pollInterval ); + Log::Write(LogLevel_Info, "The pollInterval setting is only %d, which appears to be a legacy setting. Multiplying by 1000 to convert to ms.", pollInterval); pollInterval *= 1000; } pollInterval /= (int32) m_pollList.size(); } { - LockGuard LG(m_nodeMutex); + Internal::LockGuard LG(m_nodeMutex); // Request the state of the value from the node to which it belongs - if( Node* node = GetNode( valueId.GetNodeId() ) ) + if (Node* node = GetNode(valueId.GetNodeId())) { bool requestState = true; - if( !node->IsListeningDevice() ) + if (!node->IsListeningDevice()) { // The device is not awake all the time. If it is not awake, we mark it // as requiring a poll. The poll will be done next time the node wakes up. - if( WakeUp* wakeUp = static_cast( node->GetCommandClass( WakeUp::StaticGetCommandClassId() ) ) ) + if (Internal::CC::WakeUp* wakeUp = static_cast(node->GetCommandClass(Internal::CC::WakeUp::StaticGetCommandClassId()))) { - if( !wakeUp->IsAwake() ) + if (!wakeUp->IsAwake()) { wakeUp->SetPollRequired(); requestState = false; @@ -4542,15 +4301,16 @@ void Driver::PollThreadProc } } - if( requestState ) + if (requestState) { // Request an update of the value - CommandClass* cc = node->GetCommandClass( valueId.GetCommandClassId() ); - if (cc) { + Internal::CC::CommandClass* cc = node->GetCommandClass(valueId.GetCommandClassId()); + if (cc) + { uint16_t index = valueId.GetIndex(); uint8_t instance = valueId.GetInstance(); - Log::Write( LogLevel_Detail, node->m_nodeId, "Polling: %s index = %d instance = %d (poll queue has %d messages)", cc->GetCommandClassName().c_str(), index, instance, m_msgQueue[MsgQueue_Poll].size() ); - cc->RequestValue( 0, index, instance, MsgQueue_Poll ); + Log::Write(LogLevel_Detail, node->m_nodeId, "Polling: %s index = %d instance = %d (poll queue has %d messages)", cc->GetCommandClassName().c_str(), index, instance, m_msgQueue[MsgQueue_Poll].size()); + cc->RequestValue(0, index, instance, MsgQueue_Poll); } } @@ -4566,30 +4326,26 @@ void Driver::PollThreadProc // Wait until the library isn't actively sending messages (or in the midst of a transaction) int i32; int loopCount = 0; - while( !m_msgQueue[MsgQueue_Poll].empty() - || !m_msgQueue[MsgQueue_Send].empty() - || !m_msgQueue[MsgQueue_Command].empty() - || !m_msgQueue[MsgQueue_Query].empty() - || m_currentMsg != NULL ) - { - i32 = Wait::Single( _exitEvent, 10); // test conditions every 10ms - if( i32 == 0 ) + while (!m_msgQueue[MsgQueue_Poll].empty() || !m_msgQueue[MsgQueue_Send].empty() || !m_msgQueue[MsgQueue_Command].empty() || !m_msgQueue[MsgQueue_Query].empty() || m_currentMsg != NULL) + { + i32 = Internal::Platform::Wait::Single(_exitEvent, 10); // test conditions every 10ms + if (i32 == 0) { // Exit has been called return; } loopCount++; - if( loopCount == 3000*10 ) // 300 seconds worth of delay? Something unusual is going on + if (loopCount == 3000 * 10) // 300 seconds worth of delay? Something unusual is going on { - Log::Write( LogLevel_Warning, "Poll queue hasn't been able to execute for 300 secs or more" ); + Log::Write(LogLevel_Warning, "Poll queue hasn't been able to execute for 300 secs or more"); Log::QueueDump(); // assert( 0 ); } } // ready for next poll...insert the pollInterval delay - i32 = Wait::Single( _exitEvent, pollInterval ); - if( i32 == 0 ) + i32 = Internal::Platform::Wait::Single(_exitEvent, pollInterval); + if (i32 == 0) { // Exit has been called return; @@ -4598,8 +4354,8 @@ void Driver::PollThreadProc else // poll list is empty or awake nodes haven't been fully queried yet { // don't poll just yet, wait for the pollInterval or exit before re-checking to see if the pollList has elements - int32 i32 = Wait::Single( _exitEvent, 500 ); - if( i32 == 0 ) + int32 i32 = Internal::Platform::Wait::Single(_exitEvent, 500); + if (i32 == 0) { // Exit has been called return; @@ -4616,16 +4372,14 @@ void Driver::PollThreadProc // // Delete all nodes and fetch new node data from the Z-Wave network //----------------------------------------------------------------------------- -void Driver::InitAllNodes -( -) +void Driver::InitAllNodes() { // Delete all the node data { - LockGuard LG(m_nodeMutex); - for( int i=0; i<256; ++i ) + Internal::LockGuard LG(m_nodeMutex); + for (int i = 0; i < 256; ++i) { - if( m_nodes[i] ) + if (m_nodes[i]) { delete m_nodes[i]; m_nodes[i] = NULL; @@ -4633,47 +4387,46 @@ void Driver::InitAllNodes } } // Fetch new node data from the Z-Wave network - m_controller->PlayInitSequence( this ); + m_controller->PlayInitSequence(this); } //----------------------------------------------------------------------------- // // Queue a node to be interrogated for its setup details //----------------------------------------------------------------------------- -void Driver::InitNode -( - uint8 const _nodeId, - bool newNode, - bool secure, - uint8 const *_protocolInfo, - uint8 const _length -) +void Driver::InitNode(uint8 const _nodeId, bool newNode, bool secure, uint8 const *_protocolInfo, uint8 const _length) { // Delete any existing node and replace it with a new one { - LockGuard LG(m_nodeMutex); - if( m_nodes[_nodeId] ) + Internal::LockGuard LG(m_nodeMutex); + if (m_nodes[_nodeId]) { // Remove the original node delete m_nodes[_nodeId]; - Notification* notification = new Notification( Notification::Type_NodeRemoved ); - notification->SetHomeAndNodeIds( m_homeId, _nodeId ); - QueueNotification( notification ); + m_nodes[_nodeId] = NULL; + WriteCache(); + Notification* notification = new Notification(Notification::Type_NodeRemoved); + notification->SetHomeAndNodeIds(m_homeId, _nodeId); + QueueNotification(notification); } // Add the new node - m_nodes[_nodeId] = new Node( m_homeId, _nodeId ); - if (newNode == true) static_cast(m_nodes[_nodeId])->SetAddingNode(); + m_nodes[_nodeId] = new Node(m_homeId, _nodeId); + if (newNode == true) + static_cast(m_nodes[_nodeId])->SetAddingNode(); } - Notification* notification = new Notification( Notification::Type_NodeAdded ); - notification->SetHomeAndNodeIds( m_homeId, _nodeId ); - QueueNotification( notification ); + Notification* notification = new Notification(Notification::Type_NodeAdded); + notification->SetHomeAndNodeIds(m_homeId, _nodeId); + QueueNotification(notification); - if (_length == 0) { + if (_length == 0) + { // Request the node info - m_nodes[_nodeId]->SetQueryStage( Node::QueryStage_ProtocolInfo ); - } else { + m_nodes[_nodeId]->SetQueryStage(Node::QueryStage_ProtocolInfo); + } + else + { if (isNetworkKeySet()) m_nodes[_nodeId]->SetSecured(secure); else @@ -4687,14 +4440,11 @@ void Driver::InitNode // // Get whether the node is a listening device that does not go to sleep //----------------------------------------------------------------------------- -bool Driver::IsNodeListeningDevice -( - uint8 const _nodeId -) +bool Driver::IsNodeListeningDevice(uint8 const _nodeId) { bool res = false; - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { res = node->IsListeningDevice(); } @@ -4706,14 +4456,11 @@ bool Driver::IsNodeListeningDevice // // Get whether the node is a listening device that does not go to sleep //----------------------------------------------------------------------------- -bool Driver::IsNodeFrequentListeningDevice -( - uint8 const _nodeId -) +bool Driver::IsNodeFrequentListeningDevice(uint8 const _nodeId) { bool res = false; - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { res = node->IsFrequentListeningDevice(); } @@ -4725,14 +4472,11 @@ bool Driver::IsNodeFrequentListeningDevice // // Get whether the node is a beam capable device. //----------------------------------------------------------------------------- -bool Driver::IsNodeBeamingDevice -( - uint8 const _nodeId -) +bool Driver::IsNodeBeamingDevice(uint8 const _nodeId) { bool res = false; - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { res = node->IsBeamingDevice(); } @@ -4744,14 +4488,11 @@ bool Driver::IsNodeBeamingDevice // // Get whether the node is a routing device that passes messages to other nodes //----------------------------------------------------------------------------- -bool Driver::IsNodeRoutingDevice -( - uint8 const _nodeId -) +bool Driver::IsNodeRoutingDevice(uint8 const _nodeId) { bool res = false; - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { res = node->IsRoutingDevice(); } @@ -4763,14 +4504,11 @@ bool Driver::IsNodeRoutingDevice // // Get the security attribute for a node //----------------------------------------------------------------------------- -bool Driver::IsNodeSecurityDevice -( - uint8 const _nodeId -) +bool Driver::IsNodeSecurityDevice(uint8 const _nodeId) { bool security = false; - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { security = node->IsSecurityDevice(); } @@ -4782,14 +4520,11 @@ bool Driver::IsNodeSecurityDevice // // Get the maximum baud rate of a node's communications //----------------------------------------------------------------------------- -uint32 Driver::GetNodeMaxBaudRate -( - uint8 const _nodeId -) +uint32 Driver::GetNodeMaxBaudRate(uint8 const _nodeId) { uint32 baud = 0; - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { baud = node->GetMaxBaudRate(); } @@ -4801,14 +4536,11 @@ uint32 Driver::GetNodeMaxBaudRate // // Get the version number of a node //----------------------------------------------------------------------------- -uint8 Driver::GetNodeVersion -( - uint8 const _nodeId -) +uint8 Driver::GetNodeVersion(uint8 const _nodeId) { uint8 version = 0; - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { version = node->GetVersion(); } @@ -4820,14 +4552,11 @@ uint8 Driver::GetNodeVersion // // Get the security byte of a node //----------------------------------------------------------------------------- -uint8 Driver::GetNodeSecurity -( - uint8 const _nodeId -) +uint8 Driver::GetNodeSecurity(uint8 const _nodeId) { uint8 security = 0; - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { security = node->GetSecurity(); } @@ -4839,14 +4568,11 @@ uint8 Driver::GetNodeSecurity // // Get the basic type of a node //----------------------------------------------------------------------------- -uint8 Driver::GetNodeBasic -( - uint8 const _nodeId -) +uint8 Driver::GetNodeBasic(uint8 const _nodeId) { uint8 basic = 0; - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { basic = node->GetBasic(); } @@ -4854,56 +4580,96 @@ uint8 Driver::GetNodeBasic return basic; } +//----------------------------------------------------------------------------- +// +// Get the basic type of a node +//----------------------------------------------------------------------------- +string Driver::GetNodeBasicString(uint8 const _nodeId) +{ + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) + { + return node->GetBasicString(); + } + + return "Unknown"; +} + + + + //----------------------------------------------------------------------------- // // Get the generic type of a node //----------------------------------------------------------------------------- -uint8 Driver::GetNodeGeneric -( - uint8 const _nodeId -) +uint8 Driver::GetNodeGeneric(uint8 const _nodeId, uint8 const _instance) { uint8 genericType = 0; - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { - genericType = node->GetGeneric(); + genericType = node->GetGeneric(_instance); } return genericType; } +//----------------------------------------------------------------------------- +// +// Get the generic type of a node +//----------------------------------------------------------------------------- +string Driver::GetNodeGenericString(uint8 const _nodeId, uint8 const _instance) +{ + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) + { + return node->GetGenericString(_instance); + } + + return "Unknown"; +} + + //----------------------------------------------------------------------------- // // Get the specific type of a node //----------------------------------------------------------------------------- -uint8 Driver::GetNodeSpecific -( - uint8 const _nodeId -) +uint8 Driver::GetNodeSpecific(uint8 const _nodeId, uint8 const _instance) { uint8 specific = 0; - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { - specific = node->GetSpecific(); + specific = node->GetSpecific(_instance); } return specific; } +//----------------------------------------------------------------------------- +// +// Get the specific type of a node +//----------------------------------------------------------------------------- +string Driver::GetNodeSpecificString(uint8 const _nodeId, uint8 const _instance) +{ + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) + { + return node->GetSpecificString(_instance); + } + + return "Unknown"; +} + //----------------------------------------------------------------------------- // // Get the basic/generic/specific type of the specified node // Returns a copy of the string rather than a const ref for thread safety //----------------------------------------------------------------------------- -string Driver::GetNodeType -( - uint8 const _nodeId -) +string Driver::GetNodeType(uint8 const _nodeId) { - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { return node->GetType(); } @@ -4911,36 +4677,27 @@ string Driver::GetNodeType return "Unknown"; } - -bool Driver::IsNodeZWavePlus -( - uint8 const _nodeId -) +bool Driver::IsNodeZWavePlus(uint8 const _nodeId) { - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { return node->IsNodeZWavePlus(); } return false; } - //----------------------------------------------------------------------------- // // Gets the neighbors for a node //----------------------------------------------------------------------------- -uint32 Driver::GetNodeNeighbors -( - uint8 const _nodeId, - uint8** o_neighbors -) +uint32 Driver::GetNodeNeighbors(uint8 const _nodeId, uint8** o_neighbors) { uint32 numNeighbors = 0; - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { - numNeighbors = node->GetNeighbors( o_neighbors ); + numNeighbors = node->GetNeighbors(o_neighbors); } return numNeighbors; @@ -4951,13 +4708,10 @@ uint32 Driver::GetNodeNeighbors // Get the manufacturer name for the node with the specified ID // Returns a copy of the string rather than a const ref for thread safety //----------------------------------------------------------------------------- -string Driver::GetNodeManufacturerName -( - uint8 const _nodeId -) +string Driver::GetNodeManufacturerName(uint8 const _nodeId) { - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { return node->GetManufacturerName(); } @@ -4970,13 +4724,10 @@ string Driver::GetNodeManufacturerName // Get the product name for the node with the specified ID // Returns a copy of the string rather than a const ref for thread safety //----------------------------------------------------------------------------- -string Driver::GetNodeProductName -( - uint8 const _nodeId -) +string Driver::GetNodeProductName(uint8 const _nodeId) { - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { return node->GetProductName(); } @@ -4989,13 +4740,10 @@ string Driver::GetNodeProductName // Get the user-editable name for the node with the specified ID // Returns a copy of the string rather than a const ref for thread safety //----------------------------------------------------------------------------- -string Driver::GetNodeName -( - uint8 const _nodeId -) +string Driver::GetNodeName(uint8 const _nodeId) { - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { return node->GetNodeName(); } @@ -5008,13 +4756,10 @@ string Driver::GetNodeName // Get the user-editable string for location of the specified node // Returns a copy of the string rather than a const ref for thread safety //----------------------------------------------------------------------------- -string Driver::GetNodeLocation -( - uint8 const _nodeId -) +string Driver::GetNodeLocation(uint8 const _nodeId) { - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { return node->GetLocation(); } @@ -5027,13 +4772,10 @@ string Driver::GetNodeLocation // Get the manufacturer Id string value with the specified ID // Returns a copy of the string rather than a const ref for thread safety //----------------------------------------------------------------------------- -uint16 Driver::GetNodeManufacturerId -( - uint8 const _nodeId -) +uint16 Driver::GetNodeManufacturerId(uint8 const _nodeId) { - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { return node->GetManufacturerId(); } @@ -5046,13 +4788,10 @@ uint16 Driver::GetNodeManufacturerId // Get the product type string value with the specified ID // Returns a copy of the string rather than a const ref for thread safety //----------------------------------------------------------------------------- -uint16 Driver::GetNodeProductType -( - uint8 const _nodeId -) +uint16 Driver::GetNodeProductType(uint8 const _nodeId) { - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { return node->GetProductType(); } @@ -5065,13 +4804,10 @@ uint16 Driver::GetNodeProductType // Get the product Id string value with the specified ID // Returns a copy of the string rather than a const ref for thread safety //----------------------------------------------------------------------------- -uint16 Driver::GetNodeProductId -( - uint8 const _nodeId -) +uint16 Driver::GetNodeProductId(uint8 const _nodeId) { - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { return node->GetProductId(); } @@ -5083,13 +4819,10 @@ uint16 Driver::GetNodeProductId // // Get the node device type as reported in the Z-Wave+ Info report. //----------------------------------------------------------------------------- -uint16 Driver::GetNodeDeviceType -( - uint8 const _nodeId -) +uint16 Driver::GetNodeDeviceType(uint8 const _nodeId) { - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { return node->GetDeviceType(); } @@ -5102,14 +4835,11 @@ uint16 Driver::GetNodeDeviceType // Get the node DeviceType as a string as reported in the Z-Wave+ Info report. //----------------------------------------------------------------------------- -string Driver::GetNodeDeviceTypeString -( - uint8 const _nodeId -) +string Driver::GetNodeDeviceTypeString(uint8 const _nodeId) { - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { return node->GetDeviceTypeString(); } @@ -5117,19 +4847,14 @@ string Driver::GetNodeDeviceTypeString return ""; // unknown } - - //----------------------------------------------------------------------------- // // Get the node role as reported in the Z-Wave+ Info report. //----------------------------------------------------------------------------- -uint8 Driver::GetNodeRole -( - uint8 const _nodeId -) +uint8 Driver::GetNodeRole(uint8 const _nodeId) { - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { return node->GetRoleType(); } @@ -5141,13 +4866,10 @@ uint8 Driver::GetNodeRole // // Get the node role as a string as reported in the Z-Wave+ Info report. //----------------------------------------------------------------------------- -string Driver::GetNodeRoleString -( - uint8 const _nodeId -) +string Driver::GetNodeRoleString(uint8 const _nodeId) { - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { return node->GetRoleTypeString(); } @@ -5159,13 +4881,10 @@ string Driver::GetNodeRoleString // // Get the node role as a string as reported in the Z-Wave+ Info report. //----------------------------------------------------------------------------- -uint8 Driver::GetNodePlusType -( - uint8 const _nodeId -) +uint8 Driver::GetNodePlusType(uint8 const _nodeId) { - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { return node->GetNodeType(); } @@ -5176,37 +4895,26 @@ uint8 Driver::GetNodePlusType // // Get the node role as a string as reported in the Z-Wave+ Info report. //----------------------------------------------------------------------------- -string Driver::GetNodePlusTypeString -( - uint8 const _nodeId -) +string Driver::GetNodePlusTypeString(uint8 const _nodeId) { - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { return node->GetNodeTypeString(); } return ""; // unknown } - - - - //----------------------------------------------------------------------------- // // Set the manufacturer name for the node with the specified ID //----------------------------------------------------------------------------- -void Driver::SetNodeManufacturerName -( - uint8 const _nodeId, - string const& _manufacturerName -) +void Driver::SetNodeManufacturerName(uint8 const _nodeId, string const& _manufacturerName) { - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { - node->SetManufacturerName( _manufacturerName ); + node->SetManufacturerName(_manufacturerName); } } @@ -5214,16 +4922,12 @@ void Driver::SetNodeManufacturerName // // Set the product name string value with the specified ID //----------------------------------------------------------------------------- -void Driver::SetNodeProductName -( - uint8 const _nodeId, - string const& _productName -) +void Driver::SetNodeProductName(uint8 const _nodeId, string const& _productName) { - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { - node->SetProductName( _productName ); + node->SetProductName(_productName); } } @@ -5231,16 +4935,12 @@ void Driver::SetNodeProductName // // Set the node name string value with the specified ID //----------------------------------------------------------------------------- -void Driver::SetNodeName -( - uint8 const _nodeId, - string const& _nodeName -) +void Driver::SetNodeName(uint8 const _nodeId, string const& _nodeName) { - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { - node->SetNodeName( _nodeName ); + node->SetNodeName(_nodeName); } } @@ -5248,16 +4948,12 @@ void Driver::SetNodeName // // Set the location string value with the specified ID //----------------------------------------------------------------------------- -void Driver::SetNodeLocation -( - uint8 const _nodeId, - string const& _location -) +void Driver::SetNodeLocation(uint8 const _nodeId, string const& _location) { - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { - node->SetLocation( _location ); + node->SetLocation(_location); } } @@ -5265,16 +4961,12 @@ void Driver::SetNodeLocation // // Helper to set the node level through the basic command class //----------------------------------------------------------------------------- -void Driver::SetNodeLevel -( - uint8 const _nodeId, - uint8 const _level -) +void Driver::SetNodeLevel(uint8 const _nodeId, uint8 const _level) { - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { - node->SetLevel( _level ); + node->SetLevel(_level); } } @@ -5282,13 +4974,10 @@ void Driver::SetNodeLevel // // Helper to set the node on through the basic command class //----------------------------------------------------------------------------- -void Driver::SetNodeOn -( - uint8 const _nodeId -) +void Driver::SetNodeOn(uint8 const _nodeId) { - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { node->SetNodeOn(); } @@ -5298,13 +4987,10 @@ void Driver::SetNodeOn // // Helper to set the node off through the basic command class //----------------------------------------------------------------------------- -void Driver::SetNodeOff -( - uint8 const _nodeId -) +void Driver::SetNodeOff(uint8 const _nodeId) { - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { node->SetNodeOff(); } @@ -5314,16 +5000,13 @@ void Driver::SetNodeOff // // Get a pointer to a Value object for the specified ValueID //----------------------------------------------------------------------------- -Value* Driver::GetValue -( - ValueID const& _id -) +Internal::VC::Value* Driver::GetValue(ValueID const& _id) { // This method is only called by code that has already locked the node - if( Node* node = m_nodes[_id.GetNodeId()] ) + if (Node* node = m_nodes[_id.GetNodeId()]) { - return node->GetValue( _id ); + return node->GetValue(_id); } return NULL; @@ -5337,52 +5020,43 @@ Value* Driver::GetValue // // Reset controller and erase all node information //----------------------------------------------------------------------------- -void Driver::ResetController -( - Event* _evt -) +void Driver::ResetController(Internal::Platform::Event* _evt) { m_controllerResetEvent = _evt; - Log::Write( LogLevel_Info, "Reset controller and erase all node information"); - Msg* msg = new Msg( "Reset controller and erase all node information", 0xff, REQUEST, FUNC_ID_ZW_SET_DEFAULT, true ); - SendMsg( msg, MsgQueue_Command ); + Log::Write(LogLevel_Info, "Reset controller and erase all node information"); + Internal::Msg* msg = new Internal::Msg("Reset controller and erase all node information", 0xff, REQUEST, FUNC_ID_ZW_SET_DEFAULT, true); + SendMsg(msg, MsgQueue_Command); } //----------------------------------------------------------------------------- // // Soft-reset the Z-Wave controller chip //----------------------------------------------------------------------------- -void Driver::SoftReset -( -) +void Driver::SoftReset() { - Log::Write( LogLevel_Info, "Soft-resetting the Z-Wave controller chip"); - Msg* msg = new Msg( "Soft-resetting the Z-Wave controller chip", 0xff, REQUEST, FUNC_ID_SERIAL_API_SOFT_RESET, false, false ); - SendMsg( msg, MsgQueue_Command ); + Log::Write(LogLevel_Info, "Soft-resetting the Z-Wave controller chip"); + Internal::Msg* msg = new Internal::Msg("Soft-resetting the Z-Wave controller chip", 0xff, REQUEST, FUNC_ID_SERIAL_API_SOFT_RESET, false, false); + SendMsg(msg, MsgQueue_Command); } //----------------------------------------------------------------------------- // // Get the neighbour information for a node from the controller //----------------------------------------------------------------------------- -void Driver::RequestNodeNeighbors -( - uint8 const _nodeId, - uint32 const _requestFlags -) +void Driver::RequestNodeNeighbors(uint8 const _nodeId, uint32 const _requestFlags) { - if( IsAPICallSupported( FUNC_ID_ZW_GET_ROUTING_INFO ) ) + if (IsAPICallSupported( FUNC_ID_ZW_GET_ROUTING_INFO)) { // Note: This is not the same as RequestNodeNeighbourUpdate. This method // merely requests the controller's current neighbour information and // the reply will be copied into the relevant Node object for later use. - Log::Write( LogLevel_Detail, GetNodeNumber( m_currentMsg ), "Requesting routing info (neighbor list) for Node %d", _nodeId ); - Msg* msg = new Msg( "Get Routing Info", _nodeId, REQUEST, FUNC_ID_ZW_GET_ROUTING_INFO, false ); - msg->Append( _nodeId ); - msg->Append( 0 ); // don't remove bad links - msg->Append( 0 ); // don't remove non-repeaters - msg->Append( 3 ); // funcid - SendMsg( msg, MsgQueue_Command ); + Log::Write(LogLevel_Detail, GetNodeNumber(m_currentMsg), "Requesting routing info (neighbor list) for Node %d", _nodeId); + Internal::Msg* msg = new Internal::Msg("Get Routing Info", _nodeId, REQUEST, FUNC_ID_ZW_GET_ROUTING_INFO, false); + msg->Append(_nodeId); + msg->Append(0); // don't remove bad links + msg->Append(0); // don't remove non-repeaters + msg->Append(3); // funcid + SendMsg(msg, MsgQueue_Command); } } @@ -5391,25 +5065,17 @@ void Driver::RequestNodeNeighbors // Start the controller performing one of its network management functions // Create a ControllerCommand request. //----------------------------------------------------------------------------- -bool Driver::BeginControllerCommand -( - ControllerCommand _command, - pfnControllerCallback_t _callback, - void* _context, - bool _highPower, - uint8 _nodeId, - uint8 _arg -) +bool Driver::BeginControllerCommand(ControllerCommand _command, pfnControllerCallback_t _callback, void* _context, bool _highPower, uint8 _nodeId, uint8 _arg) { ControllerCommandItem* cci; MsgQueueItem item; - if( _command == ControllerCommand_None ) + if (_command == ControllerCommand_None) { return false; } - Log::Write( LogLevel_Detail, _nodeId, "Queuing (%s) %s", c_sendQueueNames[MsgQueue_Controller], c_controllerCommandNames[_command] ); + Log::Write(LogLevel_Detail, _nodeId, "Queuing (%s) %s", c_sendQueueNames[MsgQueue_Controller], c_controllerCommandNames[_command]); cci = new ControllerCommandItem(); cci->m_controllerCommand = _command; cci->m_controllerCallback = _callback; @@ -5425,7 +5091,7 @@ bool Driver::BeginControllerCommand item.m_cci = cci; m_sendMutex->Lock(); - m_msgQueue[MsgQueue_Controller].push_back( item ); + m_msgQueue[MsgQueue_Controller].push_back(item); m_queueEvent[MsgQueue_Controller]->Set(); m_sendMutex->Unlock(); @@ -5436,314 +5102,315 @@ bool Driver::BeginControllerCommand // // Start the controller performing one of its network management functions //----------------------------------------------------------------------------- -void Driver::DoControllerCommand -( -) +void Driver::DoControllerCommand() { - UpdateControllerState( ControllerState_Starting ); - switch( m_currentControllerCommand->m_controllerCommand ) - { - case ControllerCommand_AddDevice: + UpdateControllerState(ControllerState_Starting); + switch (m_currentControllerCommand->m_controllerCommand) { - if( !IsPrimaryController() ) + case ControllerCommand_AddDevice: { - UpdateControllerState( ControllerState_Error, ControllerError_NotPrimary ); + if (!IsPrimaryController()) + { + UpdateControllerState(ControllerState_Error, ControllerError_NotPrimary); + } + else + { + Log::Write(LogLevel_Info, 0, "Add Device"); + Internal::Msg* msg = new Internal::Msg("ControllerCommand_AddDevice", 0xff, REQUEST, FUNC_ID_ZW_ADD_NODE_TO_NETWORK, true); + uint8 options = ADD_NODE_ANY; + if (m_currentControllerCommand->m_highPower) + options |= OPTION_HIGH_POWER; + if (IsAPICallSupported(FUNC_ID_ZW_EXPLORE_REQUEST_INCLUSION)) + options |= OPTION_NWI; + msg->Append(options); + SendMsg(msg, MsgQueue_Command); + } + break; } - else + case ControllerCommand_CreateNewPrimary: + { + if (IsPrimaryController()) + { + UpdateControllerState(ControllerState_Error, ControllerError_NotSecondary); + } + else if (!IsStaticUpdateController()) + { + UpdateControllerState(ControllerState_Error, ControllerError_NotSUC); + } + else + { + Log::Write(LogLevel_Info, 0, "Create New Primary"); + Internal::Msg* msg = new Internal::Msg("ControllerCommand_CreateNewPrimary", 0xff, REQUEST, FUNC_ID_ZW_CREATE_NEW_PRIMARY, true); + msg->Append( CREATE_PRIMARY_START); + SendMsg(msg, MsgQueue_Command); + } + break; + } + case ControllerCommand_ReceiveConfiguration: { - Log::Write( LogLevel_Info, 0, "Add Device" ); - Msg* msg = new Msg( "ControllerCommand_AddDevice", 0xff, REQUEST, FUNC_ID_ZW_ADD_NODE_TO_NETWORK, true ); - uint8 options = ADD_NODE_ANY; - if (m_currentControllerCommand->m_highPower) options |= OPTION_HIGH_POWER; - if (IsAPICallSupported(FUNC_ID_ZW_EXPLORE_REQUEST_INCLUSION)) options |= OPTION_NWI; - msg->Append( options); - SendMsg( msg, MsgQueue_Command ); + Log::Write(LogLevel_Info, 0, "Receive Configuration"); + Internal::Msg* msg = new Internal::Msg("ControllerCommand_ReceiveConfiguration", 0xff, REQUEST, FUNC_ID_ZW_SET_LEARN_MODE, true); + msg->Append(0xff); + SendMsg(msg, MsgQueue_Command); + break; } - break; - } - case ControllerCommand_CreateNewPrimary: - { - if( IsPrimaryController() ) + case ControllerCommand_RemoveDevice: { - UpdateControllerState( ControllerState_Error, ControllerError_NotSecondary ); + if (!IsPrimaryController()) + { + UpdateControllerState(ControllerState_Error, ControllerError_NotPrimary); + } + else + { + Log::Write(LogLevel_Info, 0, "Remove Device"); + Internal::Msg* msg = new Internal::Msg("ControllerCommand_RemoveDevice", 0xff, REQUEST, FUNC_ID_ZW_REMOVE_NODE_FROM_NETWORK, true); + msg->Append(m_currentControllerCommand->m_highPower ? REMOVE_NODE_ANY | OPTION_HIGH_POWER : REMOVE_NODE_ANY); + SendMsg(msg, MsgQueue_Command); + } + break; } - else if( !IsStaticUpdateController() ) + case ControllerCommand_HasNodeFailed: { - UpdateControllerState( ControllerState_Error, ControllerError_NotSUC ); + Log::Write(LogLevel_Info, 0, "Requesting whether node %d has failed", m_currentControllerCommand->m_controllerCommandNode); + Internal::Msg* msg = new Internal::Msg("ControllerCommand_HasNodeFailed", 0xff, REQUEST, FUNC_ID_ZW_IS_FAILED_NODE_ID, false); + msg->Append(m_currentControllerCommand->m_controllerCommandNode); + SendMsg(msg, MsgQueue_Command); + break; } - else + case ControllerCommand_RemoveFailedNode: { - Log::Write( LogLevel_Info, 0, "Create New Primary" ); - Msg* msg = new Msg( "ControllerCommand_CreateNewPrimary", 0xff, REQUEST, FUNC_ID_ZW_CREATE_NEW_PRIMARY, true ); - msg->Append( CREATE_PRIMARY_START ); - SendMsg( msg, MsgQueue_Command ); + Log::Write(LogLevel_Info, 0, "ControllerCommand_RemoveFailedNode", m_currentControllerCommand->m_controllerCommandNode); + Internal::Msg* msg = new Internal::Msg("ControllerCommand_RemoveFailedNode", 0xff, REQUEST, FUNC_ID_ZW_REMOVE_FAILED_NODE_ID, true); + msg->Append(m_currentControllerCommand->m_controllerCommandNode); + SendMsg(msg, MsgQueue_Command); + break; } - break; - } - case ControllerCommand_ReceiveConfiguration: - { - Log::Write( LogLevel_Info, 0, "Receive Configuration" ); - Msg* msg = new Msg( "ControllerCommand_ReceiveConfiguration", 0xff, REQUEST, FUNC_ID_ZW_SET_LEARN_MODE, true ); - msg->Append( 0xff ); - SendMsg( msg, MsgQueue_Command ); - break; - } - case ControllerCommand_RemoveDevice: - { - if( !IsPrimaryController() ) + case ControllerCommand_ReplaceFailedNode: { - UpdateControllerState( ControllerState_Error, ControllerError_NotPrimary ); + Log::Write(LogLevel_Info, 0, "Replace Failed Node %d", m_currentControllerCommand->m_controllerCommandNode); + Internal::Msg* msg = new Internal::Msg("ControllerCommand_ReplaceFailedNode", 0xff, REQUEST, FUNC_ID_ZW_REPLACE_FAILED_NODE, true); + msg->Append(m_currentControllerCommand->m_controllerCommandNode); + SendMsg(msg, MsgQueue_Command); + break; } - else + case ControllerCommand_TransferPrimaryRole: { - Log::Write( LogLevel_Info, 0, "Remove Device" ); - Msg* msg = new Msg( "ControllerCommand_RemoveDevice", 0xff, REQUEST, FUNC_ID_ZW_REMOVE_NODE_FROM_NETWORK, true ); - msg->Append( m_currentControllerCommand->m_highPower ? REMOVE_NODE_ANY | OPTION_HIGH_POWER : REMOVE_NODE_ANY ); - SendMsg( msg, MsgQueue_Command ); + if (!IsPrimaryController()) + { + UpdateControllerState(ControllerState_Error, ControllerError_NotPrimary); + } + else + { + Log::Write(LogLevel_Info, 0, "Transfer Primary Role"); + Internal::Msg* msg = new Internal::Msg("ControllerCommand_TransferPrimaryRole", 0xff, REQUEST, FUNC_ID_ZW_CONTROLLER_CHANGE, true); + msg->Append(m_currentControllerCommand->m_highPower ? CONTROLLER_CHANGE_START | OPTION_HIGH_POWER : CONTROLLER_CHANGE_START); + SendMsg(msg, MsgQueue_Command); + } + break; } - break; - } - case ControllerCommand_HasNodeFailed: - { - Log::Write( LogLevel_Info, 0, "Requesting whether node %d has failed", m_currentControllerCommand->m_controllerCommandNode ); - Msg* msg = new Msg( "ControllerCommand_HasNodeFailed", 0xff, REQUEST, FUNC_ID_ZW_IS_FAILED_NODE_ID, false ); - msg->Append( m_currentControllerCommand->m_controllerCommandNode ); - SendMsg( msg, MsgQueue_Command ); - break; - } - case ControllerCommand_RemoveFailedNode: - { - Log::Write( LogLevel_Info, 0, "ControllerCommand_RemoveFailedNode", m_currentControllerCommand->m_controllerCommandNode ); - Msg* msg = new Msg( "ControllerCommand_RemoveFailedNode", 0xff, REQUEST, FUNC_ID_ZW_REMOVE_FAILED_NODE_ID, true ); - msg->Append( m_currentControllerCommand->m_controllerCommandNode ); - SendMsg( msg, MsgQueue_Command ); - break; - } - case ControllerCommand_ReplaceFailedNode: - { - Log::Write( LogLevel_Info, 0, "Replace Failed Node %d", m_currentControllerCommand->m_controllerCommandNode ); - Msg* msg = new Msg( "ControllerCommand_ReplaceFailedNode", 0xff, REQUEST, FUNC_ID_ZW_REPLACE_FAILED_NODE, true ); - msg->Append( m_currentControllerCommand->m_controllerCommandNode ); - SendMsg( msg, MsgQueue_Command ); - break; - } - case ControllerCommand_TransferPrimaryRole: - { - if( !IsPrimaryController() ) + case ControllerCommand_RequestNetworkUpdate: { - UpdateControllerState( ControllerState_Error, ControllerError_NotPrimary ); + if (!IsStaticUpdateController()) + { + UpdateControllerState(ControllerState_Error, ControllerError_NotSUC); + } + else + { + Log::Write(LogLevel_Info, 0, "Request Network Update"); + Internal::Msg* msg = new Internal::Msg("ControllerCommand_RequestNetworkUpdate", 0xff, REQUEST, FUNC_ID_ZW_REQUEST_NETWORK_UPDATE, true); + SendMsg(msg, MsgQueue_Command); + } + break; } - else + case ControllerCommand_RequestNodeNeighborUpdate: { - Log::Write( LogLevel_Info, 0, "Transfer Primary Role" ); - Msg* msg = new Msg( "ControllerCommand_TransferPrimaryRole", 0xff, REQUEST, FUNC_ID_ZW_CONTROLLER_CHANGE, true ); - msg->Append( m_currentControllerCommand->m_highPower ? CONTROLLER_CHANGE_START | OPTION_HIGH_POWER : CONTROLLER_CHANGE_START ); - SendMsg( msg, MsgQueue_Command ); + if (!IsPrimaryController()) + { + UpdateControllerState(ControllerState_Error, ControllerError_NotPrimary); + } + else + { + Log::Write(LogLevel_Info, 0, "Requesting Neighbor Update for node %d", m_currentControllerCommand->m_controllerCommandNode); + bool opts = IsAPICallSupported( FUNC_ID_ZW_REQUEST_NODE_NEIGHBOR_UPDATE_OPTIONS); + Internal::Msg* msg; + if (opts) + { + msg = new Internal::Msg("ControllerCommand_RequestNodeNeighborUpdate", m_currentControllerCommand->m_controllerCommandNode, REQUEST, FUNC_ID_ZW_REQUEST_NODE_NEIGHBOR_UPDATE_OPTIONS, true); + } + else + { + msg = new Internal::Msg("ControllerCommand_RequestNodeNeighborUpdate", m_currentControllerCommand->m_controllerCommandNode, REQUEST, FUNC_ID_ZW_REQUEST_NODE_NEIGHBOR_UPDATE, true); + } + msg->Append(m_currentControllerCommand->m_controllerCommandNode); + if (opts) + { + msg->Append(GetTransmitOptions()); + } + SendMsg(msg, MsgQueue_Command); + } + break; } - break; - } - case ControllerCommand_RequestNetworkUpdate: - { - if( !IsStaticUpdateController() ) + case ControllerCommand_AssignReturnRoute: { - UpdateControllerState( ControllerState_Error, ControllerError_NotSUC ); + Log::Write(LogLevel_Info, 0, "Assigning return route from node %d to node %d", m_currentControllerCommand->m_controllerCommandNode, m_currentControllerCommand->m_controllerCommandArg); + Internal::Msg* msg = new Internal::Msg("ControllerCommand_AssignReturnRoute", m_currentControllerCommand->m_controllerCommandNode, REQUEST, FUNC_ID_ZW_ASSIGN_RETURN_ROUTE, true); + msg->Append(m_currentControllerCommand->m_controllerCommandNode); // from the node + msg->Append(m_currentControllerCommand->m_controllerCommandArg); // to the specific destination + SendMsg(msg, MsgQueue_Command); + break; } - else + case ControllerCommand_DeleteAllReturnRoutes: { - Log::Write( LogLevel_Info, 0, "Request Network Update" ); - Msg* msg = new Msg( "ControllerCommand_RequestNetworkUpdate", 0xff, REQUEST, FUNC_ID_ZW_REQUEST_NETWORK_UPDATE, true ); - SendMsg( msg, MsgQueue_Command ); + Log::Write(LogLevel_Info, 0, "Deleting all return routes from node %d", m_currentControllerCommand->m_controllerCommandNode); + Internal::Msg* msg = new Internal::Msg("ControllerCommand_DeleteAllReturnRoutess", m_currentControllerCommand->m_controllerCommandNode, REQUEST, FUNC_ID_ZW_DELETE_RETURN_ROUTE, true); + msg->Append(m_currentControllerCommand->m_controllerCommandNode); // from the node + SendMsg(msg, MsgQueue_Command); + break; } - break; - } - case ControllerCommand_RequestNodeNeighborUpdate: - { - if( !IsPrimaryController() ) + case ControllerCommand_SendNodeInformation: { - UpdateControllerState( ControllerState_Error, ControllerError_NotPrimary ); + Log::Write(LogLevel_Info, 0, "Sending a node information frame"); + Internal::Msg* msg = new Internal::Msg("ControllerCommand_SendNodeInformation", m_currentControllerCommand->m_controllerCommandNode, REQUEST, FUNC_ID_ZW_SEND_NODE_INFORMATION, true); + msg->Append(m_currentControllerCommand->m_controllerCommandNode); // to the node + msg->Append(GetTransmitOptions()); + SendMsg(msg, MsgQueue_Command); + break; } - else + case ControllerCommand_ReplicationSend: { - Log::Write( LogLevel_Info, 0, "Requesting Neighbor Update for node %d", m_currentControllerCommand->m_controllerCommandNode ); - bool opts = IsAPICallSupported( FUNC_ID_ZW_REQUEST_NODE_NEIGHBOR_UPDATE_OPTIONS ); - Msg* msg; - if( opts ) + if (!IsPrimaryController()) { - msg = new Msg( "ControllerCommand_RequestNodeNeighborUpdate", m_currentControllerCommand->m_controllerCommandNode, REQUEST, FUNC_ID_ZW_REQUEST_NODE_NEIGHBOR_UPDATE_OPTIONS, true ); + UpdateControllerState(ControllerState_Error, ControllerError_NotPrimary); } else { - msg = new Msg( "ControllerCommand_RequestNodeNeighborUpdate", m_currentControllerCommand->m_controllerCommandNode, REQUEST, FUNC_ID_ZW_REQUEST_NODE_NEIGHBOR_UPDATE, true ); + Log::Write(LogLevel_Info, 0, "Replication Send"); + Internal::Msg* msg = new Internal::Msg("ControllerCommand_ReplicationSend", 0xff, REQUEST, FUNC_ID_ZW_ADD_NODE_TO_NETWORK, true); + msg->Append(m_currentControllerCommand->m_highPower ? ADD_NODE_CONTROLLER | OPTION_HIGH_POWER : ADD_NODE_CONTROLLER); + SendMsg(msg, MsgQueue_Command); } - msg->Append( m_currentControllerCommand->m_controllerCommandNode ); - if( opts ) - { - msg->Append( GetTransmitOptions() ); - } - SendMsg( msg, MsgQueue_Command ); - } - break; - } - case ControllerCommand_AssignReturnRoute: - { - Log::Write( LogLevel_Info, 0, "Assigning return route from node %d to node %d", m_currentControllerCommand->m_controllerCommandNode, m_currentControllerCommand->m_controllerCommandArg ); - Msg* msg = new Msg( "ControllerCommand_AssignReturnRoute", m_currentControllerCommand->m_controllerCommandNode, REQUEST, FUNC_ID_ZW_ASSIGN_RETURN_ROUTE, true ); - msg->Append( m_currentControllerCommand->m_controllerCommandNode ); // from the node - msg->Append( m_currentControllerCommand->m_controllerCommandArg ); // to the specific destination - SendMsg( msg, MsgQueue_Command ); - break; - } - case ControllerCommand_DeleteAllReturnRoutes: - { - Log::Write( LogLevel_Info, 0, "Deleting all return routes from node %d", m_currentControllerCommand->m_controllerCommandNode ); - Msg* msg = new Msg( "ControllerCommand_DeleteAllReturnRoutess", m_currentControllerCommand->m_controllerCommandNode, REQUEST, FUNC_ID_ZW_DELETE_RETURN_ROUTE, true ); - msg->Append( m_currentControllerCommand->m_controllerCommandNode ); // from the node - SendMsg( msg, MsgQueue_Command ); - break; - } - case ControllerCommand_SendNodeInformation: - { - Log::Write( LogLevel_Info, 0, "Sending a node information frame" ); - Msg* msg = new Msg( "ControllerCommand_SendNodeInformation", m_currentControllerCommand->m_controllerCommandNode, REQUEST, FUNC_ID_ZW_SEND_NODE_INFORMATION, true ); - msg->Append( m_currentControllerCommand->m_controllerCommandNode ); // to the node - msg->Append( GetTransmitOptions() ); - SendMsg( msg, MsgQueue_Command ); - break; - } - case ControllerCommand_ReplicationSend: - { - if( !IsPrimaryController() ) - { - UpdateControllerState( ControllerState_Error, ControllerError_NotPrimary ); - } - else - { - Log::Write( LogLevel_Info, 0, "Replication Send" ); - Msg* msg = new Msg( "ControllerCommand_ReplicationSend", 0xff, REQUEST, FUNC_ID_ZW_ADD_NODE_TO_NETWORK, true ); - msg->Append( m_currentControllerCommand->m_highPower ? ADD_NODE_CONTROLLER | OPTION_HIGH_POWER : ADD_NODE_CONTROLLER ); - SendMsg( msg, MsgQueue_Command ); + break; } - break; - } - case ControllerCommand_CreateButton: - { - if( IsBridgeController() ) + case ControllerCommand_CreateButton: { - Node* node = GetNodeUnsafe( m_currentControllerCommand->m_controllerCommandNode ); - if( node != NULL ) + if (IsBridgeController()) { - if( node->m_buttonMap.find( m_currentControllerCommand->m_controllerCommandArg ) == node->m_buttonMap.end() && m_virtualNeighborsReceived ) + Node* node = GetNodeUnsafe(m_currentControllerCommand->m_controllerCommandNode); + if (node != NULL) { - bool found = false; - for( uint8 n = 1; n <= 232 && !found; n++ ) + if (node->m_buttonMap.find(m_currentControllerCommand->m_controllerCommandArg) == node->m_buttonMap.end() && m_virtualNeighborsReceived) { - if( !IsVirtualNode( n )) - continue; - - map::iterator it = node->m_buttonMap.begin(); - for( ; it != node->m_buttonMap.end(); ++it ) + bool found = false; + for (uint8 n = 1; n <= 232 && !found; n++) { - // is virtual node already in map? - if( it->second == n ) - break; + if (!IsVirtualNode(n)) + continue; + + map::iterator it = node->m_buttonMap.begin(); + for (; it != node->m_buttonMap.end(); ++it) + { + // is virtual node already in map? + if (it->second == n) + break; + } + if (it == node->m_buttonMap.end()) // found unused virtual node + { + node->m_buttonMap[m_currentControllerCommand->m_controllerCommandArg] = n; + SendVirtualNodeInfo(n, m_currentControllerCommand->m_controllerCommandNode); + found = true; + } } - if( it == node->m_buttonMap.end() ) // found unused virtual node + if (!found) // create a new virtual node { - node->m_buttonMap[m_currentControllerCommand->m_controllerCommandArg] = n; - SendVirtualNodeInfo( n, m_currentControllerCommand->m_controllerCommandNode ); - found = true; + Log::Write(LogLevel_Info, 0, "AddVirtualNode"); + Internal::Msg* msg = new Internal::Msg("FUNC_ID_SERIAL_API_SLAVE_NODE_INFO", 0xff, REQUEST, FUNC_ID_SERIAL_API_SLAVE_NODE_INFO, false, false); + msg->Append(0); // node 0 + msg->Append(1); // listening + msg->Append(0x09); // genericType window covering + msg->Append(0x00); // specificType undefined + msg->Append(0); // length + SendMsg(msg, MsgQueue_Command); + + msg = new Internal::Msg("FUNC_ID_ZW_SET_SLAVE_LEARN_MODE", 0xff, REQUEST, FUNC_ID_ZW_SET_SLAVE_LEARN_MODE, true); + msg->Append(0); // node 0 to add + if (IsPrimaryController() || IsInclusionController()) + { + msg->Append( SLAVE_LEARN_MODE_ADD); + } + else + { + msg->Append( SLAVE_LEARN_MODE_ENABLE); + } + SendMsg(msg, MsgQueue_Command); } } - if( !found ) // create a new virtual node + else { - Log::Write( LogLevel_Info, 0, "AddVirtualNode" ); - Msg* msg = new Msg( "FUNC_ID_SERIAL_API_SLAVE_NODE_INFO", 0xff, REQUEST, FUNC_ID_SERIAL_API_SLAVE_NODE_INFO, false, false ); - msg->Append( 0 ); // node 0 - msg->Append( 1 ); // listening - msg->Append( 0x09 ); // genericType window covering - msg->Append( 0x00 ); // specificType undefined - msg->Append( 0 ); // length - SendMsg( msg, MsgQueue_Command ); - - msg = new Msg( "FUNC_ID_ZW_SET_SLAVE_LEARN_MODE", 0xff, REQUEST, FUNC_ID_ZW_SET_SLAVE_LEARN_MODE, true ); - msg->Append( 0 ); // node 0 to add - if( IsPrimaryController() || IsInclusionController() ) - { - msg->Append( SLAVE_LEARN_MODE_ADD ); - } - else - { - msg->Append( SLAVE_LEARN_MODE_ENABLE ); - } - SendMsg( msg, MsgQueue_Command ); + UpdateControllerState(ControllerState_Error, ControllerError_ButtonNotFound); } } else { - UpdateControllerState( ControllerState_Error, ControllerError_ButtonNotFound ); + UpdateControllerState(ControllerState_Error, ControllerError_NodeNotFound); } } else { - UpdateControllerState( ControllerState_Error, ControllerError_NodeNotFound ); + UpdateControllerState(ControllerState_Error, ControllerError_NotBridge); } - } else - { - UpdateControllerState( ControllerState_Error, ControllerError_NotBridge ); + break; } - break; - } - case ControllerCommand_DeleteButton: - { - if( IsBridgeController() ) + case ControllerCommand_DeleteButton: { - Node* node = GetNodeUnsafe( m_currentControllerCommand->m_controllerCommandNode ); - if( node != NULL ) + if (IsBridgeController()) { - // Make sure button is allocated to a virtual node. - if( node->m_buttonMap.find( m_currentControllerCommand->m_controllerCommandArg ) != node->m_buttonMap.end() ) + Node* node = GetNodeUnsafe(m_currentControllerCommand->m_controllerCommandNode); + if (node != NULL) { + // Make sure button is allocated to a virtual node. + if (node->m_buttonMap.find(m_currentControllerCommand->m_controllerCommandArg) != node->m_buttonMap.end()) + { #ifdef notdef - // We would need a reference count to decide when to free virtual nodes - // We could do this by making the bitmap of virtual nodes into a map that also holds a reference count. - Log::Write( LogLevel_Info, 0, "RemoveVirtualNode %d", m_currentControllerCommand->m_controllerCommandNode ); - Msg* msg = new Msg( "Remove Virtual Node", 0xff, REQUEST, FUNC_ID_ZW_SET_SLAVE_LEARN_MODE, true ); - msg->Append( m_currentControllerCommand->m_controllerCommandNode ); // from the node - if( IsPrimaryController() || IsInclusionController() ) + // We would need a reference count to decide when to free virtual nodes + // We could do this by making the bitmap of virtual nodes into a map that also holds a reference count. + Log::Write( LogLevel_Info, 0, "RemoveVirtualNode %d", m_currentControllerCommand->m_controllerCommandNode ); + Msg* msg = new Msg( "Remove Virtual Node", 0xff, REQUEST, FUNC_ID_ZW_SET_SLAVE_LEARN_MODE, true ); + msg->Append( m_currentControllerCommand->m_controllerCommandNode );// from the node + if( IsPrimaryController() || IsInclusionController() ) msg->Append( SLAVE_LEARN_MODE_REMOVE ); - else + else msg->Append( SLAVE_LEARN_MODE_ENABLE ); - SendMsg( msg ); + SendMsg( msg ); #endif - node->m_buttonMap.erase( m_currentControllerCommand->m_controllerCommandArg ); - SaveButtons(); + node->m_buttonMap.erase(m_currentControllerCommand->m_controllerCommandArg); + SaveButtons(); - Notification* notification = new Notification( Notification::Type_DeleteButton ); - notification->SetHomeAndNodeIds( m_homeId, m_currentControllerCommand->m_controllerCommandNode ); - notification->SetButtonId( m_currentControllerCommand->m_controllerCommandArg ); - QueueNotification( notification ); + Notification* notification = new Notification(Notification::Type_DeleteButton); + notification->SetHomeAndNodeIds(m_homeId, m_currentControllerCommand->m_controllerCommandNode); + notification->SetButtonId(m_currentControllerCommand->m_controllerCommandArg); + QueueNotification(notification); + } + else + { + UpdateControllerState(ControllerState_Error, ControllerError_ButtonNotFound); + } } else { - UpdateControllerState( ControllerState_Error, ControllerError_ButtonNotFound ); + UpdateControllerState(ControllerState_Error, ControllerError_NodeNotFound); } } else { - UpdateControllerState( ControllerState_Error, ControllerError_NodeNotFound ); + UpdateControllerState(ControllerState_Error, ControllerError_NotBridge); } + break; } - else + case ControllerCommand_None: { - UpdateControllerState( ControllerState_Error, ControllerError_NotBridge ); + // To keep gcc quiet + break; } - break; - } - case ControllerCommand_None: - { - // To keep gcc quiet - break; - } } } @@ -5751,141 +5418,160 @@ void Driver::DoControllerCommand // // Stop the current controller function //----------------------------------------------------------------------------- -void Driver::UpdateControllerState( ControllerState const _state, ControllerError const _error ) +void Driver::UpdateControllerState(ControllerState const _state, ControllerError const _error) { - if( m_currentControllerCommand != NULL ) + if (m_currentControllerCommand != NULL) { - if( _state != m_currentControllerCommand->m_controllerState ) + if (_state != m_currentControllerCommand->m_controllerState) { m_currentControllerCommand->m_controllerStateChanged = true; m_currentControllerCommand->m_controllerState = _state; - switch( _state ) - { - case ControllerState_Error: - case ControllerState_Cancel: - case ControllerState_Failed: - case ControllerState_Sleeping: - case ControllerState_NodeFailed: - case ControllerState_NodeOK: - case ControllerState_Completed: - { - m_currentControllerCommand->m_controllerCommandDone = true; - m_sendMutex->Lock(); - m_queueEvent[MsgQueue_Controller]->Set(); - m_sendMutex->Unlock(); - break; - } - default: + switch (_state) { - break; - } + case ControllerState_Error: + case ControllerState_Cancel: + case ControllerState_Failed: + case ControllerState_Sleeping: + case ControllerState_NodeFailed: + case ControllerState_NodeOK: + case ControllerState_Completed: + { + m_currentControllerCommand->m_controllerCommandDone = true; + m_sendMutex->Lock(); + m_queueEvent[MsgQueue_Controller]->Set(); + m_sendMutex->Unlock(); + break; + } + default: + { + break; + } } } - Notification* notification = new Notification( Notification::Type_ControllerCommand ); - notification->SetHomeAndNodeIds(m_homeId, 0); + Notification* notification = new Notification(Notification::Type_ControllerCommand); + + // PR #1879 + // The change below sets the nodeId in the notifications for controller state changes. These state changes are + // caused by controller commands. Below is a list of controller commands with what the nodeId gets set to, + // along with the Manager method(s) that use the controller command. + + // Driver::ControllerCommand_RequestNodeNeighborUpdate: supplied nodeId (Manager::HealNetworkNode, Manager::HealNetwork) + // Driver::ControllerCommand_AddDevice: nodeId of an added node (Manager::AddNode) + // Driver::ControllerCommand_RemoveDevice: nodeId of a removed node (Manager::RemoveNode) + // Driver::ControllerCommand_RemoveFailedNode: supplied nodeId (Manager::RemoveFailedNode) + // Driver::ControllerCommand_HasNodeFailed supplied nodeId (Manager::HasNodeFailed) + // Driver::ControllerCommand_AssignReturnRoute: supplied nodeId (Manager::AssignReturnRoute) + // Driver::ControllerCommand_RequestNodeNeighborUpdate: supplied nodeId (Manager::RequestNodeNeighborUpdate) + // Driver::ControllerCommand_DeleteAllReturnRoutes supplied nodeId (Manager::DeleteAllReturnRoutes) + // Driver::ControllerCommand_SendNodeInformation: supplied nodeId (Manager::SendNodeInformation) + // Driver::ControllerCommand_CreateNewPrimary: unknown (Manager::CreateNewPrimary) + // Driver::ControllerCommand_ReceiveConfiguration: unknown (Manager::ReceiveConfiguration) + // Driver::ControllerCommand_ReplaceFailedNode: could be the supplied nodeId or the nodeId of the node that was added (Manager::ReplaceFailedNode) + // Driver::ControllerCommand_TransferPrimaryRole: unknown (Manager::TransferPrimaryRole) + // Driver::ControllerCommand_RequestNetworkUpdate: supplied nodeId (Manager::RequestNetworkUpdate) + // Driver::ControllerCommand_ReplicationSend: supplied nodeId (Manager::ReplicationSend) + // Driver::ControllerCommand_CreateButton: supplied nodeId (Manager::CreateButton) + // Driver::ControllerCommand_DeleteButton: supplied nodeId (Manager::DeleteButton) + notification->SetHomeAndNodeIds(m_homeId, m_currentControllerCommand->m_controllerCommandNode); + notification->SetCommand(m_currentControllerCommand->m_controllerCommand); notification->SetEvent(_state); - if( _error != ControllerError_None ) + if (_error != ControllerError_None) { m_currentControllerCommand->m_controllerReturnError = _error; /* Create a new Notification Callback */ notification->SetNotification(_error); } - QueueNotification( notification ); + QueueNotification(notification); } } - - - //----------------------------------------------------------------------------- // // Stop the current controller function //----------------------------------------------------------------------------- -bool Driver::CancelControllerCommand -( -) +bool Driver::CancelControllerCommand() { - if( m_currentControllerCommand == NULL ) + if (m_currentControllerCommand == NULL) { // Controller is not doing anything return false; } - switch( m_currentControllerCommand->m_controllerCommand ) - { - case ControllerCommand_AddDevice: - { - Log::Write( LogLevel_Info, 0, "Cancel Add Node" ); - m_currentControllerCommand->m_controllerCommandNode = 0xff; // identify the fact that there is no new node to initialize - AddNodeStop( FUNC_ID_ZW_ADD_NODE_TO_NETWORK ); - break; - } - case ControllerCommand_CreateNewPrimary: - { - Log::Write( LogLevel_Info, 0, "Cancel Create New Primary" ); - Msg* msg = new Msg( "CreateNewPrimary Stop", 0xff, REQUEST, FUNC_ID_ZW_CREATE_NEW_PRIMARY, true ); - msg->Append( CREATE_PRIMARY_STOP ); - SendMsg( msg, MsgQueue_Command ); - break; - } - case ControllerCommand_ReceiveConfiguration: - { - Log::Write( LogLevel_Info, 0, "Cancel Receive Configuration" ); - Msg* msg = new Msg( "ReceiveConfiguration Stop", 0xff, REQUEST, FUNC_ID_ZW_SET_LEARN_MODE, false, false ); - msg->Append( 0 ); - SendMsg( msg, MsgQueue_Command ); - break; - } - case ControllerCommand_RemoveDevice: - { - Log::Write( LogLevel_Info, 0, "Cancel Remove Device" ); - m_currentControllerCommand->m_controllerCommandNode = 0xff; // identify the fact that there is no node to remove - AddNodeStop( FUNC_ID_ZW_REMOVE_NODE_FROM_NETWORK ); - break; - } - case ControllerCommand_TransferPrimaryRole: - { - Log::Write( LogLevel_Info, 0, "Cancel Transfer Primary Role" ); - Msg* msg = new Msg( "Transfer Primary Role Stop", 0xff, REQUEST, FUNC_ID_ZW_CONTROLLER_CHANGE, true ); - msg->Append( CONTROLLER_CHANGE_STOP ); - SendMsg( msg, MsgQueue_Command ); - break; - } - case ControllerCommand_ReplicationSend: - { - Log::Write( LogLevel_Info, 0, "Cancel Replication Send" ); - m_currentControllerCommand->m_controllerCommandNode = 0xff; // identify the fact that there is no new node to initialize - AddNodeStop( FUNC_ID_ZW_ADD_NODE_TO_NETWORK ); - break; - } - case ControllerCommand_CreateButton: - case ControllerCommand_DeleteButton: + switch (m_currentControllerCommand->m_controllerCommand) { - if( m_currentControllerCommand->m_controllerCommandNode != 0 ) + case ControllerCommand_AddDevice: + { + Log::Write(LogLevel_Info, 0, "Cancel Add Node"); + m_currentControllerCommand->m_controllerCommandNode = 0xff; // identify the fact that there is no new node to initialize + AddNodeStop( FUNC_ID_ZW_ADD_NODE_TO_NETWORK); + break; + } + case ControllerCommand_CreateNewPrimary: { - SendSlaveLearnModeOff(); + Log::Write(LogLevel_Info, 0, "Cancel Create New Primary"); + Internal::Msg* msg = new Internal::Msg("CreateNewPrimary Stop", 0xff, REQUEST, FUNC_ID_ZW_CREATE_NEW_PRIMARY, true); + msg->Append( CREATE_PRIMARY_STOP); + SendMsg(msg, MsgQueue_Command); + break; + } + case ControllerCommand_ReceiveConfiguration: + { + Log::Write(LogLevel_Info, 0, "Cancel Receive Configuration"); + Internal::Msg* msg = new Internal::Msg("ReceiveConfiguration Stop", 0xff, REQUEST, FUNC_ID_ZW_SET_LEARN_MODE, false, false); + msg->Append(0); + SendMsg(msg, MsgQueue_Command); + break; + } + case ControllerCommand_RemoveDevice: + { + Log::Write(LogLevel_Info, 0, "Cancel Remove Device"); + m_currentControllerCommand->m_controllerCommandNode = 0xff; // identify the fact that there is no node to remove + AddNodeStop( FUNC_ID_ZW_REMOVE_NODE_FROM_NETWORK); + break; + } + case ControllerCommand_TransferPrimaryRole: + { + Log::Write(LogLevel_Info, 0, "Cancel Transfer Primary Role"); + Internal::Msg* msg = new Internal::Msg("Transfer Primary Role Stop", 0xff, REQUEST, FUNC_ID_ZW_CONTROLLER_CHANGE, true); + msg->Append( CONTROLLER_CHANGE_STOP); + SendMsg(msg, MsgQueue_Command); + break; + } + case ControllerCommand_ReplicationSend: + { + Log::Write(LogLevel_Info, 0, "Cancel Replication Send"); + m_currentControllerCommand->m_controllerCommandNode = 0xff; // identify the fact that there is no new node to initialize + AddNodeStop( FUNC_ID_ZW_ADD_NODE_TO_NETWORK); + break; + } + case ControllerCommand_CreateButton: + case ControllerCommand_DeleteButton: + { + if (m_currentControllerCommand->m_controllerCommandNode != 0) + { + SendSlaveLearnModeOff(); + } + break; + } + case ControllerCommand_None: + case ControllerCommand_RequestNetworkUpdate: + case ControllerCommand_RequestNodeNeighborUpdate: + case ControllerCommand_AssignReturnRoute: + case ControllerCommand_DeleteAllReturnRoutes: + case ControllerCommand_RemoveFailedNode: + case ControllerCommand_HasNodeFailed: + case ControllerCommand_ReplaceFailedNode: + case ControllerCommand_SendNodeInformation: + { + // Cannot cancel + return false; } - break; - } - case ControllerCommand_None: - case ControllerCommand_RequestNetworkUpdate: - case ControllerCommand_RequestNodeNeighborUpdate: - case ControllerCommand_AssignReturnRoute: - case ControllerCommand_DeleteAllReturnRoutes: - case ControllerCommand_RemoveFailedNode: - case ControllerCommand_HasNodeFailed: - case ControllerCommand_ReplaceFailedNode: - case ControllerCommand_SendNodeInformation: - { - // Cannot cancel - return false; - } } - UpdateControllerState( ControllerState_Cancel ); + UpdateControllerState(ControllerState_Cancel); return true; } @@ -5893,28 +5579,25 @@ bool Driver::CancelControllerCommand // // Stop the Add Node mode based on API of controller //----------------------------------------------------------------------------- -void Driver::AddNodeStop -( - uint8 const _funcId -) +void Driver::AddNodeStop(uint8 const _funcId) { - if( m_currentControllerCommand == NULL ) + if (m_currentControllerCommand == NULL) { // Controller is not doing anything return; } - if( m_serialAPIVersion[0] == 2 && m_serialAPIVersion[1] == 76 ) + if (m_serialAPIVersion[0] == 2 && m_serialAPIVersion[1] == 76) { - Msg* msg = new Msg( "Add Node Stop", 0xff, REQUEST, _funcId, false, false ); - msg->Append( ADD_NODE_STOP ); - SendMsg( msg, Driver::MsgQueue_Command ); + Internal::Msg* msg = new Internal::Msg("Add Node Stop", 0xff, REQUEST, _funcId, false, false); + msg->Append( ADD_NODE_STOP); + SendMsg(msg, Driver::MsgQueue_Command); } else { - Msg* msg = new Msg( "Add Node Stop", 0xff, REQUEST, _funcId, false, true ); - msg->Append( ADD_NODE_STOP ); - SendMsg( msg, Driver::MsgQueue_Command ); + Internal::Msg* msg = new Internal::Msg("Add Node Stop", 0xff, REQUEST, _funcId, false, true); + msg->Append( ADD_NODE_STOP); + SendMsg(msg, Driver::MsgQueue_Command); } } @@ -5922,37 +5605,33 @@ void Driver::AddNodeStop // // Run a series of messages to a single node or every node on the network. //----------------------------------------------------------------------------- -void Driver::TestNetwork -( - uint8 const _nodeId, - uint32 const _count -) +void Driver::TestNetwork(uint8 const _nodeId, uint32 const _count) { - LockGuard LG(m_nodeMutex); - if( _nodeId == 0 ) // send _count messages to every node + Internal::LockGuard LG(m_nodeMutex); + if (_nodeId == 0) // send _count messages to every node { - for( int i=0; i<256; ++i ) + for (int i = 0; i < 256; ++i) { - if( i == m_Controller_nodeId ) // ignore sending to ourself + if (i == m_Controller_nodeId) // ignore sending to ourself { continue; } - if( m_nodes[i] != NULL ) + if (m_nodes[i] != NULL) { - NoOperation *noop = static_cast( m_nodes[i]->GetCommandClass( NoOperation::StaticGetCommandClassId() ) ); - for( int j=0; j < (int)_count; j++ ) + Internal::CC::NoOperation *noop = static_cast(m_nodes[i]->GetCommandClass(Internal::CC::NoOperation::StaticGetCommandClassId())); + for (int j = 0; j < (int) _count; j++) { - noop->Set( true ); + noop->Set(true); } } } } - else if( _nodeId != m_Controller_nodeId && m_nodes[_nodeId] != NULL ) + else if (_nodeId != m_Controller_nodeId && m_nodes[_nodeId] != NULL) { - NoOperation *noop = static_cast( m_nodes[_nodeId]->GetCommandClass( NoOperation::StaticGetCommandClassId() ) ); - for( int i=0; i < (int)_count; i++ ) + Internal::CC::NoOperation *noop = static_cast(m_nodes[_nodeId]->GetCommandClass(Internal::CC::NoOperation::StaticGetCommandClassId())); + for (int i = 0; i < (int) _count; i++) { - noop->Set( true ); + noop->Set(true); } } } @@ -5965,20 +5644,18 @@ void Driver::TestNetwork // // All devices that support the SwitchAll command class will be turned on //----------------------------------------------------------------------------- -void Driver::SwitchAllOn -( -) +void Driver::SwitchAllOn() { - SwitchAll::On( this, 0xff ); + Internal::CC::SwitchAll::On(this, 0xff); - LockGuard LG(m_nodeMutex); - for( int i=0; i<256; ++i ) + Internal::LockGuard LG(m_nodeMutex); + for (int i = 0; i < 256; ++i) { - if( GetNodeUnsafe( i ) ) + if (GetNodeUnsafe(i)) { - if( m_nodes[i]->GetCommandClass( SwitchAll::StaticGetCommandClassId() ) ) + if (m_nodes[i]->GetCommandClass(Internal::CC::SwitchAll::StaticGetCommandClassId())) { - SwitchAll::On( this, (uint8)i ); + Internal::CC::SwitchAll::On(this, (uint8) i); } } } @@ -5988,20 +5665,18 @@ void Driver::SwitchAllOn // // All devices that support the SwitchAll command class will be turned off //----------------------------------------------------------------------------- -void Driver::SwitchAllOff -( -) +void Driver::SwitchAllOff() { - SwitchAll::Off( this, 0xff ); + Internal::CC::SwitchAll::Off(this, 0xff); - LockGuard LG(m_nodeMutex); - for( int i=0; i<256; ++i ) + Internal::LockGuard LG(m_nodeMutex); + for (int i = 0; i < 256; ++i) { - if( GetNodeUnsafe( i ) ) + if (GetNodeUnsafe(i)) { - if( m_nodes[i]->GetCommandClass( SwitchAll::StaticGetCommandClassId() ) ) + if (m_nodes[i]->GetCommandClass(Internal::CC::SwitchAll::StaticGetCommandClassId())) { - SwitchAll::Off( this, (uint8)i ); + Internal::CC::SwitchAll::Off(this, (uint8) i); } } } @@ -6011,18 +5686,12 @@ void Driver::SwitchAllOff // // Set the value of one of the configuration parameters of a device //----------------------------------------------------------------------------- -bool Driver::SetConfigParam -( - uint8 const _nodeId, - uint8 const _param, - int32 _value, - uint8 _size -) +bool Driver::SetConfigParam(uint8 const _nodeId, uint8 const _param, int32 _value, uint8 _size) { - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { - return node->SetConfigParam( _param, _value, _size ); + return node->SetConfigParam(_param, _value, _size); } return false; @@ -6032,16 +5701,12 @@ bool Driver::SetConfigParam // // Request the value of one of the configuration parameters of a device //----------------------------------------------------------------------------- -void Driver::RequestConfigParam -( - uint8 const _nodeId, - uint8 const _param -) +void Driver::RequestConfigParam(uint8 const _nodeId, uint8 const _param) { - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { - node->RequestConfigParam( _param ); + node->RequestConfigParam(_param); } } @@ -6049,14 +5714,11 @@ void Driver::RequestConfigParam // // Gets the number of association groups reported by this node //----------------------------------------------------------------------------- -uint8 Driver::GetNumGroups -( - uint8 const _nodeId -) +uint8 Driver::GetNumGroups(uint8 const _nodeId) { uint8 numGroups = 0; - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { numGroups = node->GetNumGroups(); } @@ -6068,18 +5730,13 @@ uint8 Driver::GetNumGroups // // Gets the associations for a group //----------------------------------------------------------------------------- -uint32 Driver::GetAssociations -( - uint8 const _nodeId, - uint8 const _groupIdx, - uint8** o_associations -) +uint32 Driver::GetAssociations(uint8 const _nodeId, uint8 const _groupIdx, uint8** o_associations) { uint32 numAssociations = 0; - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { - numAssociations = node->GetAssociations( _groupIdx, o_associations ); + numAssociations = node->GetAssociations(_groupIdx, o_associations); } return numAssociations; @@ -6089,18 +5746,13 @@ uint32 Driver::GetAssociations // // Gets the associations for a group //----------------------------------------------------------------------------- -uint32 Driver::GetAssociations -( - uint8 const _nodeId, - uint8 const _groupIdx, - InstanceAssociation** o_associations -) +uint32 Driver::GetAssociations(uint8 const _nodeId, uint8 const _groupIdx, InstanceAssociation** o_associations) { uint32 numAssociations = 0; - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { - numAssociations = node->GetAssociations( _groupIdx, o_associations ); + numAssociations = node->GetAssociations(_groupIdx, o_associations); } return numAssociations; @@ -6110,17 +5762,13 @@ uint32 Driver::GetAssociations // // Gets the maximum number of associations for a group //----------------------------------------------------------------------------- -uint8 Driver::GetMaxAssociations -( - uint8 const _nodeId, - uint8 const _groupIdx -) +uint8 Driver::GetMaxAssociations(uint8 const _nodeId, uint8 const _groupIdx) { uint8 maxAssociations = 0; - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { - maxAssociations = node->GetMaxAssociations( _groupIdx ); + maxAssociations = node->GetMaxAssociations(_groupIdx); } return maxAssociations; @@ -6130,17 +5778,13 @@ uint8 Driver::GetMaxAssociations // // Returns true if group supports multi instance //----------------------------------------------------------------------------- -bool Driver::IsMultiInstance -( - uint8 const _nodeId, - uint8 const _groupIdx -) +bool Driver::IsMultiInstance(uint8 const _nodeId, uint8 const _groupIdx) { bool multiInstance = false; - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { - multiInstance = node->IsMultiInstance( _groupIdx ); + multiInstance = node->IsMultiInstance(_groupIdx); } return multiInstance; } @@ -6149,17 +5793,13 @@ bool Driver::IsMultiInstance // // Gets the label for a particular group //----------------------------------------------------------------------------- -string Driver::GetGroupLabel -( - uint8 const _nodeId, - uint8 const _groupIdx -) +string Driver::GetGroupLabel(uint8 const _nodeId, uint8 const _groupIdx) { string label = ""; - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { - label = node->GetGroupLabel( _groupIdx ); + label = node->GetGroupLabel(_groupIdx); } return label; @@ -6169,18 +5809,12 @@ string Driver::GetGroupLabel // // Adds a node to an association group //----------------------------------------------------------------------------- -void Driver::AddAssociation -( - uint8 const _nodeId, - uint8 const _groupIdx, - uint8 const _targetNodeId, - uint8 const _instance -) +void Driver::AddAssociation(uint8 const _nodeId, uint8 const _groupIdx, uint8 const _targetNodeId, uint8 const _instance) { - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { - node->AddAssociation( _groupIdx, _targetNodeId, _instance ); + node->AddAssociation(_groupIdx, _targetNodeId, _instance); } } @@ -6188,18 +5822,12 @@ void Driver::AddAssociation // // Removes a node from an association group //----------------------------------------------------------------------------- -void Driver::RemoveAssociation -( - uint8 const _nodeId, - uint8 const _groupIdx, - uint8 const _targetNodeId, - uint8 const _instance -) +void Driver::RemoveAssociation(uint8 const _nodeId, uint8 const _groupIdx, uint8 const _targetNodeId, uint8 const _instance) { - LockGuard LG(m_nodeMutex); - if( Node* node = GetNode( _nodeId ) ) + Internal::LockGuard LG(m_nodeMutex); + if (Node* node = GetNode(_nodeId)) { - node->RemoveAssociation( _groupIdx, _targetNodeId, _instance ); + node->RemoveAssociation(_groupIdx, _targetNodeId, _instance); } } @@ -6207,12 +5835,9 @@ void Driver::RemoveAssociation // // Add a notification to the queue to be sent at a later, safe time. //----------------------------------------------------------------------------- -void Driver::QueueNotification -( - Notification* _notification -) +void Driver::QueueNotification(Notification* _notification) { - m_notifications.push_back( _notification ); + m_notifications.push_back(_notification); m_notificationsEvent->Set(); } @@ -6220,37 +5845,39 @@ void Driver::QueueNotification // // Notify any watching objects of a value change //----------------------------------------------------------------------------- -void Driver::NotifyWatchers -( -) +void Driver::NotifyWatchers() { list::iterator nit = m_notifications.begin(); - while( nit != m_notifications.end() ) + while (nit != m_notifications.end()) { Notification* notification = m_notifications.front(); m_notifications.pop_front(); /* check the any ValueID's sent as part of the Notification are still valid */ - switch (notification->GetType()) { - case Notification::Type_ValueChanged: - case Notification::Type_ValueRefreshed: { - Value *val = GetValue(notification->GetValueID()); - if (!val) { - Log::Write(LogLevel_Info, notification->GetNodeId(), "Dropping Notification as ValueID does not exist"); - nit = m_notifications.begin(); - delete notification; + switch (notification->GetType()) + { + case Notification::Type_ValueAdded: + case Notification::Type_ValueChanged: + case Notification::Type_ValueRefreshed: + { + Internal::VC::Value *val = GetValue(notification->GetValueID()); + if (!val) + { + Log::Write(LogLevel_Info, notification->GetNodeId(), "Dropping Notification as ValueID does not exist"); + nit = m_notifications.begin(); + delete notification; + continue; + } val->Release(); - continue; + break; } - break; - } - default: - break; + default: + break; } Log::Write(LogLevel_Detail, notification->GetNodeId(), "Notification: %s", notification->GetAsString().c_str()); - Manager::Get()->NotifyWatchers( notification ); + Manager::Get()->NotifyWatchers(notification); delete notification; nit = m_notifications.begin(); @@ -6262,15 +5889,12 @@ void Driver::NotifyWatchers // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- -bool Driver::HandleRfPowerLevelSetResponse -( - uint8* _data -) +bool Driver::HandleRfPowerLevelSetResponse(uint8* _data) { bool res = true; // the meaning of this command is currently unclear, and there // isn't any returned response data, so just log the function call - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), "Received reply to FUNC_ID_ZW_R_F_POWER_LEVEL_SET" ); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), "Received reply to FUNC_ID_ZW_R_F_POWER_LEVEL_SET"); return res; } @@ -6279,14 +5903,11 @@ bool Driver::HandleRfPowerLevelSetResponse // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- -bool Driver::HandleSerialApiSetTimeoutsResponse -( - uint8* _data -) +bool Driver::HandleSerialApiSetTimeoutsResponse(uint8* _data) { // the meaning of this command and its response is currently unclear bool res = true; - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), "Received reply to FUNC_ID_SERIAL_API_SET_TIMEOUTS" ); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), "Received reply to FUNC_ID_SERIAL_API_SET_TIMEOUTS"); return res; } @@ -6294,15 +5915,12 @@ bool Driver::HandleSerialApiSetTimeoutsResponse // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- -bool Driver::HandleMemoryGetByteResponse -( - uint8* _data -) +bool Driver::HandleMemoryGetByteResponse(uint8* _data) { bool res = true; // the meaning of this command and its response is currently unclear // it seems to return three bytes of data, so print them out - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), "Received reply to FUNC_ID_ZW_MEMORY_GET_BYTE, returned data: 0x%02hx 0x%02hx 0x%02hx", _data[0], _data[1], _data[2] ); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), "Received reply to FUNC_ID_ZW_MEMORY_GET_BYTE, returned data: 0x%02hx 0x%02hx 0x%02hx", _data[0], _data[1], _data[2]); return res; } @@ -6311,14 +5929,11 @@ bool Driver::HandleMemoryGetByteResponse // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- -bool Driver::HandleReadMemoryResponse -( - uint8* _data -) +bool Driver::HandleReadMemoryResponse(uint8* _data) { // the meaning of this command and its response is currently unclear bool res = true; - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), "Received reply to FUNC_ID_MEMORY_GET_BYTE" ); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), "Received reply to FUNC_ID_MEMORY_GET_BYTE"); return res; } @@ -6326,56 +5941,50 @@ bool Driver::HandleReadMemoryResponse // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleGetVirtualNodesResponse -( - uint8* _data -) +void Driver::HandleGetVirtualNodesResponse(uint8* _data) { - uint8 nodeId = GetNodeNumber( m_currentMsg ); - Log::Write( LogLevel_Info, nodeId, "Received reply to FUNC_ID_ZW_GET_VIRTUAL_NODES" ); - memcpy( m_virtualNeighbors, &_data[2], 29 ); + uint8 nodeId = GetNodeNumber(m_currentMsg); + Log::Write(LogLevel_Info, nodeId, "Received reply to FUNC_ID_ZW_GET_VIRTUAL_NODES"); + memcpy(m_virtualNeighbors, &_data[2], 29); m_virtualNeighborsReceived = true; bool bNeighbors = false; - for( int by=0; by<29; by++ ) + for (int by = 0; by < 29; by++) { - for( int bi=0; bi<8; bi++ ) + for (int bi = 0; bi < 8; bi++) { - if( (_data[2+by] & (0x01< // Gets the virtual neighbors for a network //----------------------------------------------------------------------------- -uint32 Driver::GetVirtualNeighbors -( - uint8** o_neighbors -) +uint32 Driver::GetVirtualNeighbors(uint8** o_neighbors) { int i; uint32 numNeighbors = 0; - if( !m_virtualNeighborsReceived ) + if (!m_virtualNeighborsReceived) { *o_neighbors = NULL; return 0; } - for( i = 0; i < 29; i++ ) + for (i = 0; i < 29; i++) { - for( unsigned char mask = 0x80; mask != 0; mask >>= 1 ) - if( m_virtualNeighbors[i] & mask ) + for (unsigned char mask = 0x80; mask != 0; mask >>= 1) + if (m_virtualNeighbors[i] & mask) numNeighbors++; } // handle the possibility that no neighbors are reported - if( !numNeighbors ) + if (!numNeighbors) { *o_neighbors = NULL; return 0; @@ -6384,12 +5993,12 @@ uint32 Driver::GetVirtualNeighbors // create and populate an array with neighbor node ids uint8* neighbors = new uint8[numNeighbors]; uint32 index = 0; - for( int by=0; by<29; by++ ) + for (int by = 0; by < 29; by++) { - for( int bi=0; bi<8; bi++ ) + for (int bi = 0; bi < 8; bi++) { - if( (m_virtualNeighbors[by] & (0x01< // Get the virtual neighbour information from the controller //----------------------------------------------------------------------------- -void Driver::RequestVirtualNeighbors -( - MsgQueue const _queue -) +void Driver::RequestVirtualNeighbors(MsgQueue const _queue) { - Msg* msg = new Msg( "Get Virtual Neighbor List", 0xff, REQUEST, FUNC_ID_ZW_GET_VIRTUAL_NODES, false ); - SendMsg( msg, _queue ); + Internal::Msg* msg = new Internal::Msg("Get Virtual Neighbor List", 0xff, REQUEST, FUNC_ID_ZW_GET_VIRTUAL_NODES, false); + SendMsg(msg, _queue); } //----------------------------------------------------------------------------- // // Send node info frame on behalf of a virtual node. //----------------------------------------------------------------------------- -void Driver::SendVirtualNodeInfo -( - uint8 const _FromNodeId, - uint8 const _ToNodeId -) +void Driver::SendVirtualNodeInfo(uint8 const _FromNodeId, uint8 const _ToNodeId) { char str[80]; - snprintf( str, sizeof(str), "Send Virtual Node Info from %d to %d", _FromNodeId, _ToNodeId ); - Msg* msg = new Msg( str, 0xff, REQUEST, FUNC_ID_ZW_SEND_SLAVE_NODE_INFO, true ); - msg->Append( _FromNodeId ); // from the virtual node - msg->Append( _ToNodeId ); // to the handheld controller - msg->Append( TRANSMIT_OPTION_ACK ); - SendMsg( msg, MsgQueue_Command ); + snprintf(str, sizeof(str), "Send Virtual Node Info from %d to %d", _FromNodeId, _ToNodeId); + Internal::Msg* msg = new Internal::Msg(str, 0xff, REQUEST, FUNC_ID_ZW_SEND_SLAVE_NODE_INFO, true); + msg->Append(_FromNodeId); // from the virtual node + msg->Append(_ToNodeId); // to the handheld controller + msg->Append( TRANSMIT_OPTION_ACK); + SendMsg(msg, MsgQueue_Command); } //----------------------------------------------------------------------------- // // Disable Slave Learn Mode. //----------------------------------------------------------------------------- -void Driver::SendSlaveLearnModeOff -( -) +void Driver::SendSlaveLearnModeOff() { - if( !( IsPrimaryController() || IsInclusionController() ) ) + if (!(IsPrimaryController() || IsInclusionController())) { - Msg* msg = new Msg( "Set Slave Learn Mode Off ", 0xff, REQUEST, FUNC_ID_ZW_SET_SLAVE_LEARN_MODE, true ); - msg->Append( 0 ); // filler node id - msg->Append( SLAVE_LEARN_MODE_DISABLE ); - SendMsg( msg, MsgQueue_Command ); + Internal::Msg* msg = new Internal::Msg("Set Slave Learn Mode Off ", 0xff, REQUEST, FUNC_ID_ZW_SET_SLAVE_LEARN_MODE, true); + msg->Append(0); // filler node id + msg->Append( SLAVE_LEARN_MODE_DISABLE); + SendMsg(msg, MsgQueue_Command); } } @@ -6451,68 +6051,63 @@ void Driver::SendSlaveLearnModeOff // // Save button info into file. //----------------------------------------------------------------------------- -void Driver::SaveButtons -( -) +void Driver::SaveButtons() { char str[16]; // Create a new XML document to contain the driver configuration TiXmlDocument doc; - TiXmlDeclaration* decl = new TiXmlDeclaration( "1.0", "utf-8", "" ); - TiXmlElement* nodesElement = new TiXmlElement( "Nodes" ); - doc.LinkEndChild( decl ); - doc.LinkEndChild( nodesElement ); + TiXmlDeclaration* decl = new TiXmlDeclaration("1.0", "utf-8", ""); + TiXmlElement* nodesElement = new TiXmlElement("Nodes"); + doc.LinkEndChild(decl); + doc.LinkEndChild(nodesElement); - nodesElement->SetAttribute( "xmlns", "http://code.google.com/p/open-zwave/" ); + nodesElement->SetAttribute("xmlns", "http://code.google.com/p/open-zwave/"); - snprintf( str, sizeof(str), "%d", 1 ); - nodesElement->SetAttribute( "version", str); - LockGuard LG(m_nodeMutex); - for( int i = 1; i < 256; i++ ) + snprintf(str, sizeof(str), "%d", 1); + nodesElement->SetAttribute("version", str); + Internal::LockGuard LG(m_nodeMutex); + for (int i = 1; i < 256; i++) { - if( m_nodes[i] == NULL || m_nodes[i]->m_buttonMap.empty() ) + if (m_nodes[i] == NULL || m_nodes[i]->m_buttonMap.empty()) { continue; } - TiXmlElement* nodeElement = new TiXmlElement( "Node" ); + TiXmlElement* nodeElement = new TiXmlElement("Node"); - snprintf( str, sizeof(str), "%d", i ); - nodeElement->SetAttribute( "id", str ); + snprintf(str, sizeof(str), "%d", i); + nodeElement->SetAttribute("id", str); - for( map::iterator it = m_nodes[i]->m_buttonMap.begin(); it != m_nodes[i]->m_buttonMap.end(); ++it ) + for (map::iterator it = m_nodes[i]->m_buttonMap.begin(); it != m_nodes[i]->m_buttonMap.end(); ++it) { - TiXmlElement* valueElement = new TiXmlElement( "Button" ); + TiXmlElement* valueElement = new TiXmlElement("Button"); - snprintf( str, sizeof(str), "%d", it->first ); - valueElement->SetAttribute( "id", str ); + snprintf(str, sizeof(str), "%d", it->first); + valueElement->SetAttribute("id", str); - snprintf( str, sizeof(str), "%d", it->second ); - TiXmlText* textElement = new TiXmlText( str ); - valueElement->LinkEndChild( textElement ); + snprintf(str, sizeof(str), "%d", it->second); + TiXmlText* textElement = new TiXmlText(str); + valueElement->LinkEndChild(textElement); - nodeElement->LinkEndChild( valueElement ); + nodeElement->LinkEndChild(valueElement); } - nodesElement->LinkEndChild( nodeElement ); + nodesElement->LinkEndChild(nodeElement); } string userPath; - Options::Get()->GetOptionAsString( "UserPath", &userPath ); + Options::Get()->GetOptionAsString("UserPath", &userPath); - string filename = userPath + "zwbutton.xml"; + string filename = userPath + "zwbutton.xml"; - doc.SaveFile( filename.c_str() ); + doc.SaveFile(filename.c_str()); } //----------------------------------------------------------------------------- // // Read button info per node from file. //----------------------------------------------------------------------------- -void Driver::ReadButtons -( - uint8 const _nodeId -) +void Driver::ReadButtons(uint8 const _nodeId) { int32 intVal; int32 nodeId; @@ -6521,83 +6116,83 @@ void Driver::ReadButtons // Load the XML document that contains the driver configuration string userPath; - Options::Get()->GetOptionAsString( "UserPath", &userPath ); + Options::Get()->GetOptionAsString("UserPath", &userPath); - string filename = userPath + "zwbutton.xml"; + string filename = userPath + "zwbutton.xml"; TiXmlDocument doc; - if( !doc.LoadFile( filename.c_str(), TIXML_ENCODING_UTF8 ) ) + if (!doc.LoadFile(filename.c_str(), TIXML_ENCODING_UTF8)) { - Log::Write( LogLevel_Debug, "Driver::ReadButtons - zwbutton.xml file not found."); + Log::Write(LogLevel_Debug, "Driver::ReadButtons - zwbutton.xml file not found."); return; } - doc.SetUserData((void *)filename.c_str()); + doc.SetUserData((void *) filename.c_str()); TiXmlElement const* nodesElement = doc.RootElement(); str = nodesElement->Value(); - if( str && strcmp( str, "Nodes" )) + if (str && strcmp(str, "Nodes")) { - Log::Write( LogLevel_Warning, "WARNING: Driver::ReadButtons - zwbutton.xml is malformed"); + Log::Write(LogLevel_Warning, "WARNING: Driver::ReadButtons - zwbutton.xml is malformed"); return; } // Version - if( TIXML_SUCCESS == nodesElement->QueryIntAttribute( "version", &intVal ) ) + if (TIXML_SUCCESS == nodesElement->QueryIntAttribute("version", &intVal)) { - if( (uint32)intVal != 1 ) + if ((uint32) intVal != 1) { - Log::Write( LogLevel_Info, "Driver::ReadButtons - %s is from an older version of OpenZWave and cannot be loaded.", "zwbutton.xml" ); + Log::Write(LogLevel_Info, "Driver::ReadButtons - %s is from an older version of OpenZWave and cannot be loaded.", "zwbutton.xml"); return; } } else { - Log::Write( LogLevel_Warning, "WARNING: Driver::ReadButtons - zwbutton.xml is from an older version of OpenZWave and cannot be loaded." ); + Log::Write(LogLevel_Warning, "WARNING: Driver::ReadButtons - zwbutton.xml is from an older version of OpenZWave and cannot be loaded."); return; } TiXmlElement const* nodeElement = nodesElement->FirstChildElement(); - while( nodeElement ) + while (nodeElement) { str = nodeElement->Value(); - if( str && !strcmp( str, "Node" )) + if (str && !strcmp(str, "Node")) { Node* node = NULL; - if( TIXML_SUCCESS == nodeElement->QueryIntAttribute( "id", &intVal ) ) + if (TIXML_SUCCESS == nodeElement->QueryIntAttribute("id", &intVal)) { - if( _nodeId == intVal ) + if (_nodeId == intVal) { - node = GetNodeUnsafe( intVal ); + node = GetNodeUnsafe(intVal); } } - if( node != NULL ) + if (node != NULL) { TiXmlElement const* buttonElement = nodeElement->FirstChildElement(); - while( buttonElement ) + while (buttonElement) { str = buttonElement->Value(); - if( str && !strcmp( str, "Button")) + if (str && !strcmp(str, "Button")) { - if (TIXML_SUCCESS != buttonElement->QueryIntAttribute( "id", &buttonId ) ) + if (TIXML_SUCCESS != buttonElement->QueryIntAttribute("id", &buttonId)) { - Log::Write( LogLevel_Warning, "WARNING: Driver::ReadButtons - cannot find Button Id for node %d", _nodeId ); + Log::Write(LogLevel_Warning, "WARNING: Driver::ReadButtons - cannot find Button Id for node %d", _nodeId); return; } str = buttonElement->GetText(); - if( str ) + if (str) { char *p; - nodeId = (int32)strtol( str, &p, 0 ); + nodeId = (int32) strtol(str, &p, 0); } else { - Log::Write( LogLevel_Info, "Driver::ReadButtons - missing virtual node value for node %d button id %d", _nodeId, buttonId ); + Log::Write(LogLevel_Info, "Driver::ReadButtons - missing virtual node value for node %d button id %d", _nodeId, buttonId); return; } node->m_buttonMap[buttonId] = nodeId; - Notification* notification = new Notification( Notification::Type_CreateButton ); - notification->SetHomeAndNodeIds( m_homeId, nodeId ); - notification->SetButtonId( buttonId ); - QueueNotification( notification ); + Notification* notification = new Notification(Notification::Type_CreateButton); + notification->SetHomeAndNodeIds(m_homeId, nodeId); + notification->SetButtonId(buttonId); + QueueNotification(notification); } buttonElement = buttonElement->NextSiblingElement(); } @@ -6610,28 +6205,25 @@ void Driver::ReadButtons // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- -bool Driver::HandleSetSlaveLearnModeResponse -( - uint8* _data -) +bool Driver::HandleSetSlaveLearnModeResponse(uint8* _data) { bool res = true; ControllerState state = ControllerState_InProgress; - uint8 nodeId = GetNodeNumber( m_currentMsg ); - if( _data[2] ) + uint8 nodeId = GetNodeNumber(m_currentMsg); + if (_data[2]) { - Log::Write( LogLevel_Info, nodeId, "Received reply to FUNC_ID_ZW_SET_SLAVE_LEARN_MODE - command in progress" ); + Log::Write(LogLevel_Info, nodeId, "Received reply to FUNC_ID_ZW_SET_SLAVE_LEARN_MODE - command in progress"); } else { // Failed - Log::Write( LogLevel_Warning, nodeId, "WARNING: Received reply to FUNC_ID_ZW_SET_SLAVE_LEARN_MODE - command failed" ); + Log::Write(LogLevel_Warning, nodeId, "WARNING: Received reply to FUNC_ID_ZW_SET_SLAVE_LEARN_MODE - command failed"); state = ControllerState_Failed; res = false; SendSlaveLearnModeOff(); } - UpdateControllerState( state ); + UpdateControllerState(state); return res; } @@ -6639,108 +6231,100 @@ bool Driver::HandleSetSlaveLearnModeResponse // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleSetSlaveLearnModeRequest -( - uint8* _data -) +void Driver::HandleSetSlaveLearnModeRequest(uint8* _data) { ControllerState state = ControllerState_Waiting; - uint8 nodeId = GetNodeNumber( m_currentMsg ); + uint8 nodeId = GetNodeNumber(m_currentMsg); - if( m_currentControllerCommand == NULL ) + if (m_currentControllerCommand == NULL) { return; } SendSlaveLearnModeOff(); - switch( _data[3] ) + switch (_data[3]) { - case SLAVE_ASSIGN_COMPLETE: - { - Log::Write( LogLevel_Info, nodeId, "SLAVE_ASSIGN_COMPLETE" ); - if( _data[4] == 0 ) // original node is 0 so adding + case SLAVE_ASSIGN_COMPLETE: { - Log::Write( LogLevel_Info, nodeId, "Adding virtual node ID %d", _data[5] ); - Node* node = GetNodeUnsafe( m_currentControllerCommand->m_controllerCommandNode ); - if( node != NULL ) + Log::Write(LogLevel_Info, nodeId, "SLAVE_ASSIGN_COMPLETE"); + if (_data[4] == 0) // original node is 0 so adding { - node->m_buttonMap[m_currentControllerCommand->m_controllerCommandArg] = _data[5]; - SendVirtualNodeInfo( _data[5], m_currentControllerCommand->m_controllerCommandNode ); + Log::Write(LogLevel_Info, nodeId, "Adding virtual node ID %d", _data[5]); + Node* node = GetNodeUnsafe(m_currentControllerCommand->m_controllerCommandNode); + if (node != NULL) + { + node->m_buttonMap[m_currentControllerCommand->m_controllerCommandArg] = _data[5]; + SendVirtualNodeInfo(_data[5], m_currentControllerCommand->m_controllerCommandNode); + } } - } - else - if( _data[5] == 0 ) + else if (_data[5] == 0) { - Log::Write( LogLevel_Info, nodeId, "Removing virtual node ID %d", _data[4] ); + Log::Write(LogLevel_Info, nodeId, "Removing virtual node ID %d", _data[4]); } - break; - } - case SLAVE_ASSIGN_NODEID_DONE: - { - Log::Write( LogLevel_Info, nodeId, "SLAVE_ASSIGN_NODEID_DONE" ); - if( _data[4] == 0 ) // original node is 0 so adding + break; + } + case SLAVE_ASSIGN_NODEID_DONE: { - Log::Write( LogLevel_Info, nodeId, "Adding virtual node ID %d", _data[5] ); - Node* node = GetNodeUnsafe( m_currentControllerCommand->m_controllerCommandNode ); - if( node != NULL ) + Log::Write(LogLevel_Info, nodeId, "SLAVE_ASSIGN_NODEID_DONE"); + if (_data[4] == 0) // original node is 0 so adding { - node->m_buttonMap[m_currentControllerCommand->m_controllerCommandArg] = _data[5]; - SendVirtualNodeInfo( _data[5], m_currentControllerCommand->m_controllerCommandNode ); + Log::Write(LogLevel_Info, nodeId, "Adding virtual node ID %d", _data[5]); + Node* node = GetNodeUnsafe(m_currentControllerCommand->m_controllerCommandNode); + if (node != NULL) + { + node->m_buttonMap[m_currentControllerCommand->m_controllerCommandArg] = _data[5]; + SendVirtualNodeInfo(_data[5], m_currentControllerCommand->m_controllerCommandNode); + } } - } - else - if( _data[5] == 0 ) + else if (_data[5] == 0) { - Log::Write( LogLevel_Info, nodeId, "Removing virtual node ID %d", _data[4] ); + Log::Write(LogLevel_Info, nodeId, "Removing virtual node ID %d", _data[4]); } - break; - } - case SLAVE_ASSIGN_RANGE_INFO_UPDATE: - { - Log::Write( LogLevel_Info, nodeId, "SLAVE_ASSIGN_RANGE_INFO_UPDATE" ); - break; - } + break; + } + case SLAVE_ASSIGN_RANGE_INFO_UPDATE: + { + Log::Write(LogLevel_Info, nodeId, "SLAVE_ASSIGN_RANGE_INFO_UPDATE"); + break; + } } m_currentControllerCommand->m_controllerAdded = false; - UpdateControllerState( state ); + UpdateControllerState(state); } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- -bool Driver::HandleSendSlaveNodeInfoResponse -( - uint8* _data -) +bool Driver::HandleSendSlaveNodeInfoResponse(uint8* _data) { bool res = true; ControllerState state = ControllerState_InProgress; - uint8 nodeId = GetNodeNumber( m_currentMsg ); - if( m_currentControllerCommand == NULL ) + uint8 nodeId = GetNodeNumber(m_currentMsg); + if (m_currentControllerCommand == NULL) { return false; } - if( _data[2] ) + if (_data[2]) { - Log::Write( LogLevel_Info, nodeId, "Received reply to FUNC_ID_ZW_SEND_SLAVE_NODE_INFO - command in progress" ); + Log::Write(LogLevel_Info, nodeId, "Received reply to FUNC_ID_ZW_SEND_SLAVE_NODE_INFO - command in progress"); } else { // Failed - Log::Write( LogLevel_Info, nodeId, "Received reply to FUNC_ID_ZW_SEND_SLAVE_NODE_INFO - command failed" ); + Log::Write(LogLevel_Info, nodeId, "Received reply to FUNC_ID_ZW_SEND_SLAVE_NODE_INFO - command failed"); state = ControllerState_Failed; // Undo button map settings - Node* node = GetNodeUnsafe( m_currentControllerCommand->m_controllerCommandNode ); - if( node != NULL ) + Node* node = GetNodeUnsafe(m_currentControllerCommand->m_controllerCommandNode); + if (node != NULL) { - node->m_buttonMap.erase( m_currentControllerCommand->m_controllerCommandArg ); + node->m_buttonMap.erase(m_currentControllerCommand->m_controllerCommandArg); } res = false; } - UpdateControllerState( state ); + UpdateControllerState(state); return res; } @@ -6748,34 +6332,31 @@ bool Driver::HandleSendSlaveNodeInfoResponse // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleSendSlaveNodeInfoRequest -( - uint8* _data -) +void Driver::HandleSendSlaveNodeInfoRequest(uint8* _data) { - if( m_currentControllerCommand == NULL ) + if (m_currentControllerCommand == NULL) { return; } - if( _data[3] == TRANSMIT_COMPLETE_OK ) // finish up + if (_data[3] == TRANSMIT_COMPLETE_OK) // finish up { - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), "SEND_SLAVE_NODE_INFO_COMPLETE OK" ); + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), "SEND_SLAVE_NODE_INFO_COMPLETE OK"); SaveButtons(); - Notification* notification = new Notification( Notification::Type_CreateButton ); - notification->SetHomeAndNodeIds( m_homeId, m_currentControllerCommand->m_controllerCommandNode ); - notification->SetButtonId( m_currentControllerCommand->m_controllerCommandArg ); - QueueNotification( notification ); + Notification* notification = new Notification(Notification::Type_CreateButton); + notification->SetHomeAndNodeIds(m_homeId, m_currentControllerCommand->m_controllerCommandNode); + notification->SetButtonId(m_currentControllerCommand->m_controllerCommandArg); + QueueNotification(notification); - UpdateControllerState( ControllerState_Completed ); - RequestVirtualNeighbors( MsgQueue_Send ); + UpdateControllerState(ControllerState_Completed); + RequestVirtualNeighbors(MsgQueue_Send); } else // error. try again { - HandleErrorResponse( _data[3], m_currentControllerCommand->m_controllerCommandNode, "SLAVE_NODE_INFO_COMPLETE" ); - Node* node = GetNodeUnsafe( m_currentControllerCommand->m_controllerCommandNode ); - if( node != NULL) + HandleErrorResponse(_data[3], m_currentControllerCommand->m_controllerCommandNode, "SLAVE_NODE_INFO_COMPLETE"); + Node* node = GetNodeUnsafe(m_currentControllerCommand->m_controllerCommandNode); + if (node != NULL) { - SendVirtualNodeInfo( node->m_buttonMap[m_currentControllerCommand->m_controllerCommandArg], m_currentControllerCommand->m_controllerCommandNode ); + SendVirtualNodeInfo(node->m_buttonMap[m_currentControllerCommand->m_controllerCommandArg], m_currentControllerCommand->m_controllerCommandNode); } } } @@ -6784,35 +6365,32 @@ void Driver::HandleSendSlaveNodeInfoRequest // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- -void Driver::HandleApplicationSlaveCommandRequest -( - uint8* _data -) +void Driver::HandleApplicationSlaveCommandRequest(uint8* _data) { - Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), "APPLICATION_SLAVE_COMMAND_HANDLER rxStatus %x dest %d source %d len %d", _data[2], _data[3], _data[4], _data[5] ); - Node* node = GetNodeUnsafe( _data[4] ); - if( node != NULL && _data[5] == 3 && _data[6] == 0x20 && _data[7] == 0x01 ) // only support Basic Set for now + Log::Write(LogLevel_Info, GetNodeNumber(m_currentMsg), "APPLICATION_SLAVE_COMMAND_HANDLER rxStatus %x dest %d source %d len %d", _data[2], _data[3], _data[4], _data[5]); + Node* node = GetNodeUnsafe(_data[4]); + if (node != NULL && _data[5] == 3 && _data[6] == 0x20 && _data[7] == 0x01) // only support Basic Set for now { - map::iterator it = node->m_buttonMap.begin(); - for( ; it != node->m_buttonMap.end(); ++it ) + map::iterator it = node->m_buttonMap.begin(); + for (; it != node->m_buttonMap.end(); ++it) { - if( it->second == _data[3] ) + if (it->second == _data[3]) break; } - if( it != node->m_buttonMap.end() ) + if (it != node->m_buttonMap.end()) { Notification *notification; - if( _data[8] == 0 ) + if (_data[8] == 0) { - notification = new Notification( Notification::Type_ButtonOff ); + notification = new Notification(Notification::Type_ButtonOff); } else { - notification = new Notification( Notification::Type_ButtonOn ); + notification = new Notification(Notification::Type_ButtonOn); } - notification->SetHomeAndNodeIds( m_homeId, _data[4] ); - notification->SetButtonId( it->first ); - QueueNotification( notification ); + notification->SetHomeAndNodeIds(m_homeId, _data[4]); + notification->SetButtonId(it->first); + QueueNotification(notification); } } } @@ -6821,19 +6399,20 @@ void Driver::HandleApplicationSlaveCommandRequest // // See if we can get node from incoming message data //----------------------------------------------------------------------------- -uint8 Driver::NodeFromMessage -( - uint8 const* buffer -) +uint8 Driver::NodeFromMessage(uint8 const* buffer) { uint8 nodeId = 0; - if( buffer[1] >= 5 ) + if (buffer[1] >= 5) { - switch( buffer[3] ) + switch (buffer[3]) { - case FUNC_ID_APPLICATION_COMMAND_HANDLER: nodeId = buffer[5]; break; - case FUNC_ID_ZW_APPLICATION_UPDATE: nodeId = buffer[5]; break; + case FUNC_ID_APPLICATION_COMMAND_HANDLER: + nodeId = buffer[5]; + break; + case FUNC_ID_ZW_APPLICATION_UPDATE: + nodeId = buffer[5]; + break; } } return nodeId; @@ -6842,17 +6421,14 @@ uint8 Driver::NodeFromMessage // // Update a node's routing information //----------------------------------------------------------------------------- -void Driver::UpdateNodeRoutes -( - uint8 const _nodeId, - bool _doUpdate // = false -) +void Driver::UpdateNodeRoutes(uint8 const _nodeId, bool _doUpdate // = false + ) { // Only for routing slaves - Node* node = GetNodeUnsafe( _nodeId ); - if( node != NULL && node->GetBasic() == 0x04 ) + Node* node = GetNodeUnsafe(_nodeId); + if (node != NULL && node->GetBasic() == 0x04) { - uint8 numGroups = GetNumGroups( _nodeId ); + uint8 numGroups = GetNumGroups(_nodeId); uint8 numNodes = 0; uint8 nodes[5]; InstanceAssociation* associations; @@ -6860,44 +6436,44 @@ void Driver::UpdateNodeRoutes // Determine up to 5 destinations - memset( nodes, 0, sizeof(nodes) ); - for( i = 1; i <= numGroups && numNodes < sizeof(nodes) ; i++ ) + memset(nodes, 0, sizeof(nodes)); + for (i = 1; i <= numGroups && numNodes < sizeof(nodes); i++) { associations = NULL; - uint32 len = GetAssociations( _nodeId, i, &associations ); - for( uint8 j = 0; j < len; j++ ) + uint32 len = GetAssociations(_nodeId, i, &associations); + for (uint8 j = 0; j < len; j++) { uint8 k; /* there is a gcc bug that triggers here: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124 * see also https://github.com/OpenZWave/open-zwave/issues/586 */ - for( k = 0; k < numNodes && k < sizeof(nodes); k++ ) + for (k = 0; k < numNodes && k < sizeof(nodes); k++) { - if( nodes[k] == associations[j].m_nodeId ) + if (nodes[k] == associations[j].m_nodeId) { break; } } - if( k >= numNodes && numNodes < sizeof(nodes) ) // not in list so add it + if (k >= numNodes && numNodes < sizeof(nodes)) // not in list so add it { nodes[numNodes++] = associations[j].m_nodeId; } } - if( associations != NULL ) + if (associations != NULL) { - delete [] associations; + delete[] associations; } } - if( _doUpdate || numNodes != node->m_numRouteNodes || memcmp( nodes, node->m_routeNodes, sizeof(node->m_routeNodes) ) != 0 ) + if (_doUpdate || numNodes != node->m_numRouteNodes || memcmp(nodes, node->m_routeNodes, sizeof(node->m_routeNodes)) != 0) { // Figure out what to do if one of these fail. - BeginControllerCommand( ControllerCommand_DeleteAllReturnRoutes, NULL, NULL, true, _nodeId, 0 ); - for( i = 0; i < numNodes; i++ ) + BeginControllerCommand(ControllerCommand_DeleteAllReturnRoutes, NULL, NULL, true, _nodeId, 0); + for (i = 0; i < numNodes; i++) { - BeginControllerCommand( ControllerCommand_AssignReturnRoute, NULL, NULL, true, _nodeId, nodes[i] ); + BeginControllerCommand(ControllerCommand_AssignReturnRoute, NULL, NULL, true, _nodeId, nodes[i]); } node->m_numRouteNodes = numNodes; - memcpy( node->m_routeNodes, nodes, sizeof(nodes) ); + memcpy(node->m_routeNodes, nodes, sizeof(nodes)); } } } @@ -6906,10 +6482,7 @@ void Driver::UpdateNodeRoutes // // Return driver statistics //----------------------------------------------------------------------------- -void Driver::GetDriverStatistics -( - DriverData* _data -) +void Driver::GetDriverStatistics(DriverData* _data) { _data->m_SOFCnt = m_SOFCnt; _data->m_ACKWaiting = m_ACKWaiting; @@ -6939,17 +6512,13 @@ void Driver::GetDriverStatistics // // Return per node statistics //----------------------------------------------------------------------------- -void Driver::GetNodeStatistics -( - uint8 const _nodeId, - Node::NodeData* _data -) +void Driver::GetNodeStatistics(uint8 const _nodeId, Node::NodeData* _data) { - LockGuard LG(m_nodeMutex); - Node* node = GetNode( _nodeId ); - if( node != NULL ) + Internal::LockGuard LG(m_nodeMutex); + Node* node = GetNode(_nodeId); + if (node != NULL) { - node->GetNodeStatistics( _data ); + node->GetNodeStatistics(_data); } } @@ -6957,62 +6526,64 @@ void Driver::GetNodeStatistics // // Report driver statistics to the driver's log //----------------------------------------------------------------------------- -void Driver::LogDriverStatistics -( -) +void Driver::LogDriverStatistics() { DriverData data; GetDriverStatistics(&data); int32 totalElapsed = -m_startTime.TimeRemaining(); - int32 days = totalElapsed / (1000*60*60*24); - - totalElapsed -= days*1000*60*60*24; - int32 hours = totalElapsed/(1000*60*60); - - totalElapsed -= hours*1000*60*60; - int32 minutes = totalElapsed/(1000*60); - - Log::Write( LogLevel_Always, "***************************************************************************" ); - Log::Write( LogLevel_Always, "********************* Cumulative Network Statistics *********************" ); - Log::Write( LogLevel_Always, "*** General" ); - Log::Write( LogLevel_Always, "Driver run time: . . . %ld days, %ld hours, %ld minutes", days, hours, minutes); - Log::Write( LogLevel_Always, "Frames processed: . . . . . . . . . . . . . . . . . . . . %ld", data.m_SOFCnt ); - Log::Write( LogLevel_Always, "Total messages successfully received: . . . . . . . . . . %ld", data.m_readCnt ); - Log::Write( LogLevel_Always, "Total Messages successfully sent: . . . . . . . . . . . . %ld", data.m_writeCnt ); - Log::Write( LogLevel_Always, "ACKs received from controller: . . . . . . . . . . . . . %ld", data.m_ACKCnt ); + int32 days = totalElapsed / (1000 * 60 * 60 * 24); + + totalElapsed -= days * 1000 * 60 * 60 * 24; + int32 hours = totalElapsed / (1000 * 60 * 60); + + totalElapsed -= hours * 1000 * 60 * 60; + int32 minutes = totalElapsed / (1000 * 60); + + Log::Write(LogLevel_Always, "***************************************************************************"); + Log::Write(LogLevel_Always, "********************* Cumulative Network Statistics *********************"); + Log::Write(LogLevel_Always, "*** General"); + Log::Write(LogLevel_Always, "Driver run time: . . . %ld days, %ld hours, %ld minutes", days, hours, minutes); + Log::Write(LogLevel_Always, "Frames processed: . . . . . . . . . . . . . . . . . . . . %ld", data.m_SOFCnt); + Log::Write(LogLevel_Always, "Total messages successfully received: . . . . . . . . . . %ld", data.m_readCnt); + Log::Write(LogLevel_Always, "Total Messages successfully sent: . . . . . . . . . . . . %ld", data.m_writeCnt); + Log::Write(LogLevel_Always, "ACKs received from controller: . . . . . . . . . . . . . %ld", data.m_ACKCnt); // Consider tracking and adding: // Initialization messages // Ad-hoc command messages // Polling messages // Messages inititated by network // Others? - Log::Write( LogLevel_Always, "*** Errors" ); - Log::Write( LogLevel_Always, "Unsolicited messages received while waiting for ACK: . . %ld", data.m_ACKWaiting ); - Log::Write( LogLevel_Always, "Reads aborted due to timeouts: . . . . . . . . . . . . . %ld", data.m_readAborts ); - Log::Write( LogLevel_Always, "Bad checksum errors: . . . . . . . . . . . . . . . . . . %ld", data.m_badChecksum ); - Log::Write( LogLevel_Always, "CANs received from controller: . . . . . . . . . . . . . %ld", data.m_CANCnt ); - Log::Write( LogLevel_Always, "NAKs received from controller: . . . . . . . . . . . . . %ld", data.m_NAKCnt ); - Log::Write( LogLevel_Always, "Out of frame data flow errors: . . . . . . . . . . . . . %ld", data.m_OOFCnt ); - Log::Write( LogLevel_Always, "Messages retransmitted: . . . . . . . . . . . . . . . . . %ld", data.m_retries ); - Log::Write( LogLevel_Always, "Messages dropped and not delivered: . . . . . . . . . . . %ld", data.m_dropped ); - Log::Write( LogLevel_Always, "***************************************************************************" ); + Log::Write(LogLevel_Always, "*** Errors"); + Log::Write(LogLevel_Always, "Unsolicited messages received while waiting for ACK: . . %ld", data.m_ACKWaiting); + Log::Write(LogLevel_Always, "Reads aborted due to timeouts: . . . . . . . . . . . . . %ld", data.m_readAborts); + Log::Write(LogLevel_Always, "Bad checksum errors: . . . . . . . . . . . . . . . . . . %ld", data.m_badChecksum); + Log::Write(LogLevel_Always, "CANs received from controller: . . . . . . . . . . . . . %ld", data.m_CANCnt); + Log::Write(LogLevel_Always, "NAKs received from controller: . . . . . . . . . . . . . %ld", data.m_NAKCnt); + Log::Write(LogLevel_Always, "Out of frame data flow errors: . . . . . . . . . . . . . %ld", data.m_OOFCnt); + Log::Write(LogLevel_Always, "Messages retransmitted: . . . . . . . . . . . . . . . . . %ld", data.m_retries); + Log::Write(LogLevel_Always, "Messages dropped and not delivered: . . . . . . . . . . . %ld", data.m_dropped); + Log::Write(LogLevel_Always, "***************************************************************************"); } //----------------------------------------------------------------------------- // // Get the Network Key we will use for Security Command Class //----------------------------------------------------------------------------- -uint8 *Driver::GetNetworkKey() { +uint8 *Driver::GetNetworkKey() +{ std::string networkKey; std::vector elems; unsigned int tempkey[16]; - static uint8 keybytes[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + static uint8 keybytes[16] = + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static bool keySet = false; - if (keySet == false) { - Options::Get()->GetOptionAsString("NetworkKey", &networkKey ); - OpenZWave::split(elems, networkKey, ",", true); - if (elems.size() != 16) { + if (keySet == false) + { + Options::Get()->GetOptionAsString("NetworkKey", &networkKey); + Internal::split(elems, networkKey, ",", true); + if (elems.size() != 16) + { Log::Write(LogLevel_Warning, "Invalid Network Key. Does not contain 16 Bytes - Contains %d", elems.size()); Log::Write(LogLevel_Warning, "Raw Key: %s", networkKey.c_str()); Log::Write(LogLevel_Warning, "Parsed Key:"); @@ -7022,11 +6593,15 @@ uint8 *Driver::GetNetworkKey() { OZW_FATAL_ERROR(OZWException::OZWEXCEPTION_SECURITY_FAILED, "Failed to Read Network Key"); } int i = 0; - for (std::vector::iterator it = elems.begin(); it != elems.end(); it++) { - if (0 == sscanf(OpenZWave::trim(*it).c_str(), "%x", &tempkey[i])) { + for (std::vector::iterator it = elems.begin(); it != elems.end(); it++) + { + if (0 == sscanf(Internal::trim(*it).c_str(), "%x", &tempkey[i])) + { Log::Write(LogLevel_Warning, "Cannot Convert Network Key Byte %s to Key", (*it).c_str()); OZW_FATAL_ERROR(OZWException::OZWEXCEPTION_SECURITY_FAILED, "Failed to Convert Network Key"); - } else { + } + else + { keybytes[i] = (tempkey[i] & 0xFF); } i++; @@ -7040,21 +6615,22 @@ uint8 *Driver::GetNetworkKey() { // // Send either a NONCE request, or the actual encrypted message, depending what state the Message Currently is in. //----------------------------------------------------------------------------- -bool Driver::SendEncryptedMessage() { +bool Driver::SendEncryptedMessage() +{ uint8 *buffer = m_currentMsg->GetBuffer(); uint8 length = m_currentMsg->GetLength(); m_expectedCallbackId = m_currentMsg->GetCallbackId(); Log::Write(LogLevel_Info, m_currentMsg->GetTargetNodeId(), "Sending (%s) message (Callback ID=0x%.2x, Expected Reply=0x%.2x) - %s", c_sendQueueNames[m_currentMsgQueueSource], m_expectedCallbackId, m_expectedReply, m_currentMsg->GetAsString().c_str()); - m_controller->Write( buffer, length ); + m_controller->Write(buffer, length); m_currentMsg->clearNonce(); return true; } - -bool Driver::SendNonceRequest(string logmsg) { +bool Driver::SendNonceRequest(string logmsg) +{ uint8 m_buffer[11]; @@ -7065,8 +6641,8 @@ bool Driver::SendNonceRequest(string logmsg) { m_buffer[3] = FUNC_ID_ZW_SEND_DATA; m_buffer[4] = m_currentMsg->GetTargetNodeId(); m_buffer[5] = 2; // Length of the payload - m_buffer[6] = Security::StaticGetCommandClassId(); - m_buffer[7] = SecurityCmd_NonceGet; + m_buffer[6] = Internal::CC::Security::StaticGetCommandClassId(); + m_buffer[7] = Internal::CC::SecurityCmd_NonceGet; //m_buffer[8] = TRANSMIT_OPTION_ACK | TRANSMIT_OPTION_AUTO_ROUTE; m_buffer[8] = TRANSMIT_OPTION_ACK | TRANSMIT_OPTION_AUTO_ROUTE; /* this is the same as the Actual Message */ @@ -7074,47 +6650,54 @@ bool Driver::SendNonceRequest(string logmsg) { m_buffer[9] = 2; // Calculate the checksum m_buffer[10] = 0xff; - for( uint32 i=1; i<10; ++i ) + for (uint32 i = 1; i < 10; ++i) { m_buffer[10] ^= m_buffer[i]; } - Log::Write(LogLevel_Info, m_currentMsg->GetTargetNodeId(), "Sending (%s) message (Callback ID=0x%.2x, Expected Reply=0x%.2x) - Nonce_Get(%s) - %s:", c_sendQueueNames[m_currentMsgQueueSource], 2, m_expectedReply, logmsg.c_str(), PktToString(m_buffer, 10).c_str()); + Log::Write(LogLevel_Info, m_currentMsg->GetTargetNodeId(), "Sending (%s) message (Callback ID=0x%.2x, Expected Reply=0x%.2x) - Nonce_Get(%s) - %s:", c_sendQueueNames[m_currentMsgQueueSource], 2, m_expectedReply, logmsg.c_str(), Internal::PktToString(m_buffer, 10).c_str()); m_controller->Write(m_buffer, 11); return true; } -bool Driver::initNetworkKeys(bool newnode) { +bool Driver::initNetworkKeys(bool newnode) +{ - uint8_t EncryptPassword[16] = {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}; - uint8_t AuthPassword[16] = {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55}; + uint8_t EncryptPassword[16] = + { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA }; + uint8_t AuthPassword[16] = + { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }; - uint8_t SecuritySchemes[1][16] = { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } - }; + uint8_t SecuritySchemes[1][16] = + { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; this->m_inclusionkeySet = newnode; this->AuthKey = new aes_encrypt_ctx; this->EncryptKey = new aes_encrypt_ctx; Log::Write(LogLevel_Info, GetControllerNodeId(), "Setting Up %s Network Key for Secure Communications", newnode == true ? "Inclusion" : "Provided"); - if (!isNetworkKeySet()) { + if (!isNetworkKeySet()) + { Log::Write(LogLevel_Warning, GetControllerNodeId(), "Failed - Network Key Not Set"); return false; } - if (aes_init() == EXIT_FAILURE) { + if (aes_init() == EXIT_FAILURE) + { Log::Write(LogLevel_Warning, GetControllerNodeId(), "Failed to Init AES Engine"); return false; } - if (aes_encrypt_key128(newnode == false ? this->GetNetworkKey() : SecuritySchemes[0], this->EncryptKey) == EXIT_FAILURE) { + if (aes_encrypt_key128(newnode == false ? this->GetNetworkKey() : SecuritySchemes[0], this->EncryptKey) == EXIT_FAILURE) + { Log::Write(LogLevel_Warning, GetControllerNodeId(), "Failed to Set Initial Network Key for Encryption"); return false; } - if (aes_encrypt_key128(newnode == false ? this->GetNetworkKey() : SecuritySchemes[0], this->AuthKey) == EXIT_FAILURE) { + if (aes_encrypt_key128(newnode == false ? this->GetNetworkKey() : SecuritySchemes[0], this->AuthKey) == EXIT_FAILURE) + { Log::Write(LogLevel_Warning, GetControllerNodeId(), "Failed to Set Initial Network Key for Authentication"); return false; } @@ -7124,23 +6707,26 @@ bool Driver::initNetworkKeys(bool newnode) { aes_mode_reset(this->EncryptKey); aes_mode_reset(this->AuthKey); - if (aes_ecb_encrypt(EncryptPassword, tmpEncKey, 16, this->EncryptKey) == EXIT_FAILURE) { + if (aes_ecb_encrypt(EncryptPassword, tmpEncKey, 16, this->EncryptKey) == EXIT_FAILURE) + { Log::Write(LogLevel_Warning, GetControllerNodeId(), "Failed to Generate Encrypted Network Key for Encryption"); return false; } - if (aes_ecb_encrypt(AuthPassword, tmpAuthKey, 16, this->AuthKey) == EXIT_FAILURE) { + if (aes_ecb_encrypt(AuthPassword, tmpAuthKey, 16, this->AuthKey) == EXIT_FAILURE) + { Log::Write(LogLevel_Warning, GetControllerNodeId(), "Failed to Generate Encrypted Network Key for Authentication"); return false; } - aes_mode_reset(this->EncryptKey); aes_mode_reset(this->AuthKey); - if (aes_encrypt_key128(tmpEncKey, this->EncryptKey) == EXIT_FAILURE) { + if (aes_encrypt_key128(tmpEncKey, this->EncryptKey) == EXIT_FAILURE) + { Log::Write(LogLevel_Warning, GetControllerNodeId(), "Failed to set Encrypted Network Key for Encryption"); return false; } - if (aes_encrypt_key128(tmpAuthKey, this->AuthKey) == EXIT_FAILURE) { + if (aes_encrypt_key128(tmpAuthKey, this->AuthKey) == EXIT_FAILURE) + { Log::Write(LogLevel_Warning, GetControllerNodeId(), "Failed to set Encrypted Network Key for Authentication"); return false; } @@ -7149,8 +6735,8 @@ bool Driver::initNetworkKeys(bool newnode) { return true; } -void Driver::SendNonceKey(uint8 nodeId, uint8 *nonce) { - +void Driver::SendNonceKey(uint8 nodeId, uint8 *nonce) +{ uint8 m_buffer[19]; /* construct a standard NONCE_GET message */ @@ -7160,72 +6746,74 @@ void Driver::SendNonceKey(uint8 nodeId, uint8 *nonce) { m_buffer[3] = FUNC_ID_ZW_SEND_DATA; m_buffer[4] = nodeId; m_buffer[5] = 10; // Length of the payload - m_buffer[6] = Security::StaticGetCommandClassId(); - m_buffer[7] = SecurityCmd_NonceReport; - for (int i = 0; i < 8; ++i) { - m_buffer[8+i] = nonce[i]; + m_buffer[6] = Internal::CC::Security::StaticGetCommandClassId(); + m_buffer[7] = Internal::CC::SecurityCmd_NonceReport; + for (int i = 0; i < 8; ++i) + { + m_buffer[8 + i] = nonce[i]; } m_buffer[16] = TRANSMIT_OPTION_ACK | TRANSMIT_OPTION_AUTO_ROUTE; /* this is the same as the Actual Message */ m_buffer[17] = 1; // Calculate the checksum m_buffer[18] = 0xff; - for( uint32 i=1; i<18; ++i ) + for (uint32 i = 1; i < 18; ++i) { m_buffer[18] ^= m_buffer[i]; } - Log::Write(LogLevel_Info, nodeId, "Sending (%s) message (Callback ID=0x%.2x, Expected Reply=0x%.2x) - Nonce_Report - %s:", c_sendQueueNames[m_currentMsgQueueSource], m_buffer[17], m_expectedReply, PktToString(m_buffer, 19).c_str()); + Log::Write(LogLevel_Info, nodeId, "Sending (%s) message (Callback ID=0x%.2x, Expected Reply=0x%.2x) - Nonce_Report - %s:", c_sendQueueNames[m_currentMsgQueueSource], m_buffer[17], m_expectedReply, Internal::PktToString(m_buffer, 19).c_str()); m_controller->Write(m_buffer, 19); m_nonceReportSent = nodeId; } -aes_encrypt_ctx *Driver::GetAuthKey -( -) +aes_encrypt_ctx *Driver::GetAuthKey() { - if( m_currentControllerCommand != NULL && - m_currentControllerCommand->m_controllerCommand == ControllerCommand_AddDevice && - m_currentControllerCommand->m_controllerState == ControllerState_Completed ) { + if (m_currentControllerCommand != NULL && m_currentControllerCommand->m_controllerCommand == ControllerCommand_AddDevice && m_currentControllerCommand->m_controllerState == ControllerState_Completed) + { /* we are adding a Node, so our AuthKey is different from normal comms */ initNetworkKeys(true); - } else if (m_inclusionkeySet) { + } + else if (m_inclusionkeySet) + { initNetworkKeys(false); } return this->AuthKey; -}; -aes_encrypt_ctx *Driver::GetEncKey -( -) -{ - if( m_currentControllerCommand != NULL && - m_currentControllerCommand->m_controllerCommand == ControllerCommand_AddDevice && - m_currentControllerCommand->m_controllerState == ControllerState_Completed ) { +} +; +aes_encrypt_ctx *Driver::GetEncKey() +{ + if (m_currentControllerCommand != NULL && m_currentControllerCommand->m_controllerCommand == ControllerCommand_AddDevice && m_currentControllerCommand->m_controllerState == ControllerState_Completed) + { /* we are adding a Node, so our EncryptKey is different from normal comms */ initNetworkKeys(true); - } else if (m_inclusionkeySet) { + } + else if (m_inclusionkeySet) + { initNetworkKeys(false); } return this->EncryptKey; -}; +} +; -bool Driver::isNetworkKeySet() { +bool Driver::isNetworkKeySet() +{ std::string networkKey; - if (!Options::Get()->GetOptionAsString("NetworkKey", &networkKey )) { + if (!Options::Get()->GetOptionAsString("NetworkKey", &networkKey)) + { return false; - } else { + } + else + { return networkKey.length() <= 0 ? false : true; } } -bool Driver::CheckNodeConfigRevision -( - Node *node -) +bool Driver::CheckNodeConfigRevision(Node *node) { - DNSLookup *lu = new DNSLookup; + Internal::DNSLookup *lu = new Internal::DNSLookup; lu->NodeID = node->GetNodeId(); /* make up a string of what we want to look up */ std::stringstream ss; @@ -7234,43 +6822,42 @@ bool Driver::CheckNodeConfigRevision ss << std::hex << std::setw(4) << std::setfill('0') << node->GetManufacturerId() << ".db.openzwave.com"; lu->lookup = ss.str(); - lu->type = DNS_Lookup_ConfigRevision; + lu->type = Internal::DNS_Lookup_ConfigRevision; return m_dns->sendRequest(lu); } -bool Driver::CheckMFSConfigRevision -( -) +bool Driver::CheckMFSConfigRevision() { - DNSLookup *lu = new DNSLookup; + Internal::DNSLookup *lu = new Internal::DNSLookup; lu->NodeID = 0; lu->lookup = "mfs.db.openzwave.com"; - lu->type = DNS_Lookup_ConfigRevision; + lu->type = Internal::DNS_Lookup_ConfigRevision; return m_dns->sendRequest(lu); } - -void Driver::processConfigRevision -( - DNSLookup *result -) +void Driver::processConfigRevision(Internal::DNSLookup *result) { - if (result->status == DNSError_None) { - if (result->type == DNS_Lookup_ConfigRevision) { - if (result->NodeID > 0) { - LockGuard LG(m_nodeMutex); + if (result->status == Internal::Platform::DNSError_None) + { + if (result->type == Internal::DNS_Lookup_ConfigRevision) + { + if (result->NodeID > 0) + { + Internal::LockGuard LG(m_nodeMutex); Node *node = this->GetNode(result->NodeID); - if (!node) { + if (!node) + { Log::Write(LogLevel_Warning, result->NodeID, "Node disappeared when processing Config Revision"); return; } - node->setLatestConfigRevision((unsigned long)atol(result->result.c_str())); - if (node->getFileConfigRevision() < node->getLatestConfigRevision()) { + node->setLatestConfigRevision((unsigned long) atol(result->result.c_str())); + if (node->getFileConfigRevision() < node->getLatestConfigRevision()) + { Log::Write(LogLevel_Warning, node->GetNodeId(), "Config File for Device \"%s\" is out of date", node->GetProductName().c_str()); - Notification* notification = new Notification( Notification::Type_UserAlerts ); - notification->SetHomeAndNodeIds( m_homeId, node->GetNodeId() ); + Notification* notification = new Notification(Notification::Type_UserAlerts); + notification->SetHomeAndNodeIds(m_homeId, node->GetNodeId()); notification->SetUserAlertNotification(Notification::Alert_ConfigOutOfDate); - QueueNotification( notification ); + QueueNotification(notification); bool update = false; Options::Get()->GetOptionAsBool("AutoUpdateConfigFile", &update); @@ -7279,54 +6866,64 @@ void Driver::processConfigRevision m_mfs->updateConfigFile(this, node); } - } else if (result->NodeID == 0) { + } + else if (result->NodeID == 0) + { /* manufacturer_specific */ - m_mfs->setLatestRevision((unsigned long)atol(result->result.c_str())); - if (m_mfs->getRevision() < (unsigned long)atol(result->result.c_str())) { + m_mfs->setLatestRevision((unsigned long) atol(result->result.c_str())); + if (m_mfs->getRevision() < (unsigned long) atol(result->result.c_str())) + { Log::Write(LogLevel_Warning, "Config Revision of ManufacturerSpecific Database is out of date"); - Notification* notification = new Notification( Notification::Type_UserAlerts ); + Notification* notification = new Notification(Notification::Type_UserAlerts); notification->SetUserAlertNotification(Notification::Alert_MFSOutOfDate); - QueueNotification( notification ); + QueueNotification(notification); bool update = false; Options::Get()->GetOptionAsBool("AutoUpdateConfigFile", &update); - if (update) { + if (update) + { m_mfs->updateMFSConfigFile(this); - } else { + } + else + { m_mfs->checkInitialized(); } - } else { + } + else + { /* its upto date - Check to make sure we have all the config files */ m_mfs->checkConfigFiles(this); } } return; } - } else if (result->status == DNSError_NotFound) { + } + else if (result->status == Internal::Platform::DNSError_NotFound) + { Log::Write(LogLevel_Info, "Not Found for Device record %s", result->lookup.c_str()); - Notification* notification = new Notification( Notification::Type_UserAlerts ); + Notification* notification = new Notification(Notification::Type_UserAlerts); notification->SetUserAlertNotification(Notification::Alert_DNSError); - QueueNotification( notification ); - } else if (result->status == DNSError_DomainError) { + QueueNotification(notification); + } + else if (result->status == Internal::Platform::DNSError_DomainError) + { Log::Write(LogLevel_Warning, "Domain Error Looking up record %s", result->lookup.c_str()); - Notification* notification = new Notification( Notification::Type_UserAlerts ); + Notification* notification = new Notification(Notification::Type_UserAlerts); notification->SetUserAlertNotification(Notification::Alert_DNSError); - QueueNotification( notification ); - } else if (result->status == DNSError_InternalError) { + QueueNotification(notification); + } + else if (result->status == Internal::Platform::DNSError_InternalError) + { Log::Write(LogLevel_Warning, "Internal DNS Error looking up record %s", result->lookup.c_str()); - Notification* notification = new Notification( Notification::Type_UserAlerts ); + Notification* notification = new Notification(Notification::Type_UserAlerts); notification->SetUserAlertNotification(Notification::Alert_DNSError); - QueueNotification( notification ); + QueueNotification(notification); } m_mfs->checkInitialized(); } - -bool Driver::setHttpClient -( - i_HttpClient *client -) +bool Driver::setHttpClient(Internal::i_HttpClient *client) { if (m_httpClient) delete m_httpClient; @@ -7334,85 +6931,80 @@ bool Driver::setHttpClient return true; } - -bool Driver::startConfigDownload -( - uint16 _manufacturerId, - uint16 _productType, - uint16 _productId, - string configfile, - uint8 node -) +bool Driver::startConfigDownload(uint16 _manufacturerId, uint16 _productType, uint16 _productId, string configfile, uint8 node) { - HttpDownload *download = new HttpDownload(); + Internal::HttpDownload *download = new Internal::HttpDownload(); std::stringstream ss; ss << std::hex << std::setw(4) << std::setfill('0') << _productId << "."; ss << std::hex << std::setw(4) << std::setfill('0') << _productType << "."; ss << std::hex << std::setw(4) << std::setfill('0') << _manufacturerId << ".xml"; download->url = "http://download.db.openzwave.com/" + ss.str(); download->filename = configfile; - download->operation = HttpDownload::Config; + download->operation = Internal::HttpDownload::Config; download->node = node; Log::Write(LogLevel_Info, "Queuing download for %s (Node %d)", download->url.c_str(), download->node); return m_httpClient->StartDownload(download); } -bool Driver::startMFSDownload -( - string configfile -) +bool Driver::startMFSDownload(string configfile) { - HttpDownload *download = new HttpDownload(); + Internal::HttpDownload *download = new Internal::HttpDownload(); download->url = "http://download.db.openzwave.com/mfs.xml"; download->filename = configfile; - download->operation = HttpDownload::MFSConfig; + download->operation = Internal::HttpDownload::MFSConfig; download->node = 0; Log::Write(LogLevel_Info, "Queuing download for %s", download->url.c_str()); return m_httpClient->StartDownload(download); } -bool Driver::refreshNodeConfig -( - uint8 _nodeId -) +bool Driver::refreshNodeConfig(uint8 _nodeId) { - LockGuard LG(m_nodeMutex); + Internal::LockGuard LG(m_nodeMutex); string action; - Options::Get()->GetOptionAsString("ReloadAfterUpdate",&action); - if (ToUpper(action) == "NEVER") { - Notification* notification = new Notification( Notification::Type_UserAlerts ); - notification->SetUserAlertNotification(Notification::Alert_NodeReloadReqired); - QueueNotification( notification ); + Options::Get()->GetOptionAsString("ReloadAfterUpdate", &action); + if (Internal::ToUpper(action) == "NEVER") + { + Notification* notification = new Notification(Notification::Type_UserAlerts); + notification->SetUserAlertNotification(Notification::Alert_NodeReloadRequired); + QueueNotification(notification); return true; - } else if (ToUpper(action) == "IMMEDIATE") { + } + else if (Internal::ToUpper(action) == "IMMEDIATE") + { Log::Write(LogLevel_Info, _nodeId, "Reloading Node after new Config File loaded"); /* this will reload the Node, ignoring any cache that exists etc */ ReloadNode(_nodeId); return true; - } else if (ToUpper(action) == "AWAKE") { + } + else if (Internal::ToUpper(action) == "AWAKE") + { Node *node = GetNode(_nodeId); - if( !node->IsListeningDevice() ) + if (!node->IsListeningDevice()) { - if( WakeUp* wakeUp = static_cast( node->GetCommandClass( WakeUp::StaticGetCommandClassId() ) ) ) + if (Internal::CC::WakeUp* wakeUp = static_cast(node->GetCommandClass(Internal::CC::WakeUp::StaticGetCommandClassId()))) { - if( !wakeUp->IsAwake() ) + if (!wakeUp->IsAwake()) { /* Node is Asleep. Queue it for WakeUp */ Log::Write(LogLevel_Info, _nodeId, "Queuing Sleeping Node Reload after New Config File Loaded"); MsgQueueItem item; item.m_command = MsgQueueCmd_ReloadNode; item.m_nodeId = _nodeId; - wakeUp->QueueMsg( item ); - } else { + wakeUp->QueueMsg(item); + } + else + { /* Node is Awake. Reload it */ Log::Write(LogLevel_Info, _nodeId, "Reloading Awake Node after new Config File loaded"); ReloadNode(_nodeId); return true; } } - } else { + } + else + { Log::Write(LogLevel_Info, _nodeId, "Reloading Node after new Config File Loaded"); ReloadNode(_nodeId); } @@ -7421,43 +7013,42 @@ bool Driver::refreshNodeConfig } //----------------------------------------------------------------------------- -// -// Queue an item on the query queue that indicates a stage is complete +// +// Reload a Node - Remove it from ozwcache, and re-initilize the node from scratch (doing a full interview) //----------------------------------------------------------------------------- -void Driver::ReloadNode -( - uint8 const _nodeId -) +void Driver::ReloadNode(uint8 const _nodeId) { - LockGuard LG(m_nodeMutex); - Log::Write( LogLevel_Detail, _nodeId, "Reloading Node"); + Internal::LockGuard LG(m_nodeMutex); + Log::Write(LogLevel_Detail, _nodeId, "Reloading Node"); /* delete any cached information about this node so we start from fresh */ char str[32]; int32 intVal; string userPath; - Options::Get()->GetOptionAsString( "UserPath", &userPath ); + Options::Get()->GetOptionAsString("UserPath", &userPath); - snprintf( str, sizeof(str), "ozwcache_0x%08x.xml", m_homeId ); - string filename = userPath + string(str); + snprintf(str, sizeof(str), "ozwcache_0x%08x.xml", m_homeId); + string filename = userPath + string(str); TiXmlDocument doc; - if( doc.LoadFile( filename.c_str(), TIXML_ENCODING_UTF8 ) ) + if (doc.LoadFile(filename.c_str(), TIXML_ENCODING_UTF8)) { - doc.SetUserData((void *)filename.c_str()); + doc.SetUserData((void *) filename.c_str()); TiXmlElement * driverElement = doc.RootElement(); TiXmlNode * nodeElement = driverElement->FirstChild(); - while( nodeElement ) + while (nodeElement) { - if (nodeElement->ToElement()) { + if (nodeElement->ToElement()) + { char const* str2 = nodeElement->ToElement()->Value(); - if( str2 && !strcmp( str2, "Node" ) ) + if (str2 && !strcmp(str2, "Node")) { // Get the node Id from the XML - if( TIXML_SUCCESS == nodeElement->ToElement()->QueryIntAttribute( "id", &intVal ) ) + if (TIXML_SUCCESS == nodeElement->ToElement()->QueryIntAttribute("id", &intVal)) { - if (intVal == _nodeId) { + if (intVal == _nodeId) + { driverElement->RemoveChild(nodeElement); break; } @@ -7473,108 +7064,112 @@ void Driver::ReloadNode InitNode(_nodeId); } - - -void Driver::processDownload -( - HttpDownload *download -) +void Driver::processDownload(Internal::HttpDownload *download) { - if (download->transferStatus == HttpDownload::Ok) { + if (download->transferStatus == Internal::HttpDownload::Ok) + { Log::Write(LogLevel_Info, "Download Finished: %s (Node: %d)", download->filename.c_str(), download->node); - if (download->operation == HttpDownload::Config) { + if (download->operation == Internal::HttpDownload::Config) + { m_mfs->configDownloaded(this, download->filename, download->node); - } else if (download->operation == HttpDownload::MFSConfig) { + } + else if (download->operation == Internal::HttpDownload::MFSConfig) + { m_mfs->mfsConfigDownloaded(this, download->filename); } - } else { + } + else + { Log::Write(LogLevel_Warning, "Download of %s Failed (Node: %d)", download->url.c_str(), download->node); - if (download->operation == HttpDownload::Config) { + if (download->operation == Internal::HttpDownload::Config) + { m_mfs->configDownloaded(this, download->filename, download->node, false); - } else if (download->operation == HttpDownload::MFSConfig) { + } + else if (download->operation == Internal::HttpDownload::MFSConfig) + { m_mfs->mfsConfigDownloaded(this, download->filename, false); } - Notification* notification = new Notification( Notification::Type_UserAlerts ); + Notification* notification = new Notification(Notification::Type_UserAlerts); notification->SetUserAlertNotification(Notification::Alert_ConfigFileDownloadFailed); - QueueNotification( notification ); + QueueNotification(notification); } } -bool Driver::downloadConfigRevision -( - Node *node -) +bool Driver::downloadConfigRevision(Node *node) { /* only download if the revision is 1 or higher. Revision 0's are for local testing only */ - if (node->getFileConfigRevision() <= 0) { + if (node->getFileConfigRevision() <= 0) + { Log::Write(LogLevel_Warning, node->GetNodeId(), "Config File Revision is 0. Not Updating"); - Notification* notification = new Notification( Notification::Type_UserAlerts ); + Notification* notification = new Notification(Notification::Type_UserAlerts); notification->SetUserAlertNotification(Notification::Alert_ConfigFileDownloadFailed); - QueueNotification( notification ); + QueueNotification(notification); return false; } - if (node->getFileConfigRevision() >= node->getLatestConfigRevision()) { + if (node->getFileConfigRevision() >= node->getLatestConfigRevision()) + { Log::Write(LogLevel_Warning, node->GetNodeId(), "Config File Revision %d is equal to or greater than current revision %d", node->getFileConfigRevision(), node->getLatestConfigRevision()); - Notification* notification = new Notification( Notification::Type_UserAlerts ); + Notification* notification = new Notification(Notification::Type_UserAlerts); notification->SetUserAlertNotification(Notification::Alert_ConfigFileDownloadFailed); - QueueNotification( notification ); + QueueNotification(notification); return false; - } else { + } + else + { m_mfs->updateConfigFile(this, node); return true; } } -bool Driver::downloadMFSRevision -( -) +bool Driver::downloadMFSRevision() { - if (m_mfs->getRevision() <= 0) { + if (m_mfs->getRevision() <= 0) + { Log::Write(LogLevel_Warning, "ManufacturerSpecific Revision is 0. Not Updating"); - Notification* notification = new Notification( Notification::Type_UserAlerts ); + Notification* notification = new Notification(Notification::Type_UserAlerts); notification->SetUserAlertNotification(Notification::Alert_ConfigFileDownloadFailed); - QueueNotification( notification ); + QueueNotification(notification); return false; } - if (m_mfs->getRevision() >= m_mfs->getLatestRevision()) { + if (m_mfs->getRevision() >= m_mfs->getLatestRevision()) + { Log::Write(LogLevel_Warning, "ManufacturerSpecific Revision %d is equal to or greater than current revision %d", m_mfs->getRevision(), m_mfs->getLatestRevision()); - Notification* notification = new Notification( Notification::Type_UserAlerts ); + Notification* notification = new Notification(Notification::Type_UserAlerts); notification->SetUserAlertNotification(Notification::Alert_ConfigFileDownloadFailed); - QueueNotification( notification ); + QueueNotification(notification); return false; } m_mfs->updateMFSConfigFile(this); return true; } -void Driver::SubmitEventMsg(EventMsg *event) { - LockGuard LG(m_eventMutex); +void Driver::SubmitEventMsg(EventMsg *event) +{ + Internal::LockGuard LG(m_eventMutex); m_eventQueueMsg.push_back(event); m_queueMsgEvent->Set(); } - -void Driver::ProcessEventMsg -( -) +void Driver::ProcessEventMsg() { EventMsg *event; { - LockGuard LG(m_eventMutex); + Internal::LockGuard LG(m_eventMutex); event = m_eventQueueMsg.front(); m_eventQueueMsg.pop_front(); if (m_eventQueueMsg.empty()) m_queueMsgEvent->Reset(); } - switch (event->type) { - case EventMsg::Event_DNS: - processConfigRevision(event->event.lookup); - delete event->event.lookup; - break; - case EventMsg::Event_Http: - processDownload(event->event.httpdownload); - delete event->event.httpdownload; - break; + switch (event->type) + { + case EventMsg::Event_DNS: + processConfigRevision(event->event.lookup); + delete event->event.lookup; + break; + case EventMsg::Event_Http: + processDownload(event->event.httpdownload); + delete event->event.httpdownload; + break; } delete event; } @@ -7583,17 +7178,13 @@ void Driver::ProcessEventMsg // // Retrieve MetaData about a Node. //----------------------------------------------------------------------------- -string const Driver::GetMetaData -( - uint8 const _nodeId, - Node::MetaDataFields _metadata -) +string const Driver::GetMetaData(uint8 const _nodeId, Node::MetaDataFields _metadata) { - LockGuard LG(m_nodeMutex); - Node* node = GetNode( _nodeId ); - if( node != NULL ) + Internal::LockGuard LG(m_nodeMutex); + Node* node = GetNode(_nodeId); + if (node != NULL) { - return node->GetMetaData( _metadata ); + return node->GetMetaData(_metadata); } return ""; } @@ -7602,27 +7193,20 @@ string const Driver::GetMetaData // // Retrieve MetaData about a Node. //----------------------------------------------------------------------------- -Node::ChangeLogEntry const Driver::GetChangeLog -( - uint8 const _nodeId, - uint32_t revision -) +Node::ChangeLogEntry const Driver::GetChangeLog(uint8 const _nodeId, uint32_t revision) { - LockGuard LG(m_nodeMutex); - Node* node = GetNode( _nodeId ); - if( node != NULL ) + Internal::LockGuard LG(m_nodeMutex); + Node* node = GetNode(_nodeId); + if (node != NULL) { - return node->GetChangeLog( revision ); + return node->GetChangeLog(revision); } Node::ChangeLogEntry cle; cle.revision = -1; return cle; } - -ManufacturerSpecificDB *Driver::GetManufacturerSpecificDB -( -) +Internal::ManufacturerSpecificDB *Driver::GetManufacturerSpecificDB() { return this->m_mfs; } diff --git a/cpp/src/Driver.h b/cpp/src/Driver.h index 3a3a9bf356..a41fb20baa 100644 --- a/cpp/src/Driver.h +++ b/cpp/src/Driver.h @@ -38,773 +38,868 @@ #include "Node.h" #include "platform/Event.h" #include "platform/Mutex.h" +#include "platform/Thread.h" #include "platform/TimeStamp.h" #include "aes/aescpp.h" namespace OpenZWave { - class Msg; - class Value; - class Event; - class Mutex; - class Controller; - class Thread; - class ControllerReplication; class Notification; - class DNSThread; - struct DNSLookup; - class TimerThread; - class i_HttpClient; - struct HttpDownload; - class ManufacturerSpecificDB; + namespace Internal + { + namespace CC + { + class ApplicationStatus; + class Basic; + class CommandClass; + class WakeUp; + class ControllerReplication; + class ManufacturerSpecific; + class MultiChannelAssociation; + class NodeNaming; + class Security; + class SceneActivation; + } + namespace VC + { + class Value; + class ValueStore; + } + namespace Platform + { + class Controller; + } + class DNSThread; + struct DNSLookup; + class i_HttpClient; + struct HttpDownload; + class ManufacturerSpecificDB; + class Msg; + class TimerThread; + } /** \brief The Driver class handles communication between OpenZWave * and a device attached via a serial port (typically a controller). */ class OPENZWAVE_EXPORT Driver { - friend class Manager; - friend class Node; - friend class Group; - friend class CommandClass; - friend class ControllerReplication; - friend class DNSThread; - friend class i_HttpClient; - friend class Value; - friend class ValueStore; - friend class ValueButton; - friend class Association; - friend class Basic; - friend class ManufacturerSpecific; - friend class MultiChannelAssociation; - friend class NodeNaming; - friend class NoOperation; - friend class SceneActivation; - friend class WakeUp; - friend class ApplicationStatus; /* for Notification messages */ - friend class Security; - friend class Msg; - friend class ManufacturerSpecificDB; - friend class TimerThread; - - //----------------------------------------------------------------------------- - // Controller Interfaces - //----------------------------------------------------------------------------- - public: - enum ControllerInterface - { - ControllerInterface_Unknown = 0, - ControllerInterface_Serial, - ControllerInterface_Hid - }; - - //----------------------------------------------------------------------------- - // Construction / Destruction - //----------------------------------------------------------------------------- - private: - /** - * Creates threads, events and initializes member variables and the node array. - */ - Driver( string const& _controllerPath, ControllerInterface const& _interface ); - /** Sets "exit" flags and stops the three background threads (pollThread, serialThread - * and driverThread). Then clears out the send queue and node array. Notifies - * watchers and exits. - */ - virtual ~Driver(); - - /** - * Start the driverThread - */ - void Start(); - /** - * Entry point for driverThread - */ - static void DriverThreadEntryPoint( Event* _exitEvent, void* _context ); - /** - * ThreadProc for driverThread. This is where all the "action" takes place. - *

- * First, the thread is initialized by calling Init(). If Init() fails, it will be retried - * every 5 seconds for the first two minutes and every 30 seconds thereafter. - *

- * After the thread is successfully initialized, the thread enters a loop with the - * following elements: - * - Confirm that m_exit is still false (or exit from the thread if it is true) - * - Call ReadMsg() to consume any available messages from the controller - * - Call NotifyWatchers() to send any pending notifications - * - If the thread is not waiting for an ACK, a callback or a message reply, send [any][the next] queued message[s] - * - If there was no message read or sent (workDone=false), sleep for 5 seconds. If nothing happened - * within this time frame and something was expected (ACK, callback or reply), retrieve the - * last message from the send queue and examine GetSendAttempts(). If greater than 2, give up - * and remove the message from the queue. Otherwise, resend the message. - * - If something did happen [reset m_wakeEvent] - */ - void DriverThreadProc( Event* _exitEvent ); - /** - * Initialize the controller. Open the specified serial port, start the serialThread - * and pollThread, then send a NAK to the device [presumably to flush it]. - *

- * Then queue the commands to retrieve the Z-Wave interface: - * - Get version - * - Get home and node IDs - * - Get controller capabilities - * - Get serial API capabilities - * - [Get SUC node ID] - * - Get init data [identifying the nodes on the network] - * Init() will return false if the serial port could not be opened. - */ - bool Init( uint32 _attempts ); - - /** - * Remove any messages to a node on the queues - * Used when deleting a node. - */ - void RemoveQueues( uint8 const _nodeId ); - - Thread* m_driverThread; /**< Thread for reading from the Z-Wave controller, and for creating and managing the other threads for sending, polling etc. */ - DNSThread* m_dns; /**< DNSThread Class */ - Thread* m_dnsThread; /**< Thread for DNS Queries */ - Mutex* m_initMutex; /**< Mutex to ensure proper ordering of initialization/deinitialization */ - bool m_exit; /**< Flag that is set when the application is exiting. */ - bool m_init; /**< Set to true once the driver has been initialised */ - bool m_awakeNodesQueried; /**< Set to true once the driver has polled all awake nodes */ - bool m_allNodesQueried; /**< Set to true once the driver has polled all nodes */ - bool m_notifytransactions; - TimeStamp m_startTime; /**< Time this driver started (for log report purposes) */ - - //----------------------------------------------------------------------------- - // Configuration - //----------------------------------------------------------------------------- - private: - void RequestConfig(); // Get the network configuration from the Z-Wave network - bool ReadCache(); // Read the configuration from a file - void WriteCache(); // Save the configuration to a file - - //----------------------------------------------------------------------------- - // Timer - //----------------------------------------------------------------------------- - private: - TimerThread* m_timer; /**< TimerThread Class */ - Thread* m_timerThread; /**< Thread for timer events */ - - public: - TimerThread* GetTimer() { return m_timer; } - - //----------------------------------------------------------------------------- - // Controller - //----------------------------------------------------------------------------- - private: - // Controller Capabilities (return in FUNC_ID_ZW_GET_CONTROLLER_CAPABILITIES) - enum - { - ControllerCaps_Secondary = 0x01, /**< The controller is a secondary. */ - ControllerCaps_OnOtherNetwork = 0x02, /**< The controller is not using its default HomeID. */ - ControllerCaps_SIS = 0x04, /**< There is a SUC ID Server on the network. */ - ControllerCaps_RealPrimary = 0x08, /**< Controller was the primary before the SIS was added. */ - ControllerCaps_SUC = 0x10 /**< Controller is a static update controller. */ - }; - - // Init Capabilities (return in FUNC_ID_SERIAL_API_GET_INIT_DATA) - enum - { - InitCaps_Slave = 0x01, /**< */ - InitCaps_TimerSupport = 0x02, /**< Controller supports timers. */ - InitCaps_Secondary = 0x04, /**< Controller is a secondary. */ - InitCaps_SUC = 0x08 /**< Controller is a static update controller. */ - }; - - bool IsPrimaryController()const{ return ((m_initCaps & InitCaps_Secondary) == 0); } - bool IsStaticUpdateController()const{ return ((m_initCaps & InitCaps_SUC) != 0); } - bool IsBridgeController()const{ return (m_libraryType == 7); } - bool IsInclusionController()const{ return ((m_controllerCaps & ControllerCaps_SIS) != 0); } - - bool HasExtendedTxStatus()const{ return m_hasExtendedTxStatus; } - - uint32 GetHomeId()const{ return m_homeId; } - uint8 GetControllerNodeId()const{ return m_Controller_nodeId; } - uint8 GetSUCNodeId()const{ return m_SUCNodeId; } - uint16 GetManufacturerId()const{ return m_manufacturerId; } - uint16 GetProductType()const{ return m_productType; } - uint16 GetProductId()const{ return m_productId; } - string GetControllerPath()const{ return m_controllerPath; } - ControllerInterface GetControllerInterfaceType()const{ return m_controllerInterfaceType; } - string GetLibraryVersion()const{ return m_libraryVersion; } - string GetLibraryTypeName()const{ return m_libraryTypeName; } - int32 GetSendQueueCount()const - { - int32 count = 0; - for( int32 i=0; i + * First, the thread is initialized by calling Init(). If Init() fails, it will be retried + * every 5 seconds for the first two minutes and every 30 seconds thereafter. + *

+ * After the thread is successfully initialized, the thread enters a loop with the + * following elements: + * - Confirm that m_exit is still false (or exit from the thread if it is true) + * - Call ReadMsg() to consume any available messages from the controller + * - Call NotifyWatchers() to send any pending notifications + * - If the thread is not waiting for an ACK, a callback or a message reply, send [any][the next] queued message[s] + * - If there was no message read or sent (workDone=false), sleep for 5 seconds. If nothing happened + * within this time frame and something was expected (ACK, callback or reply), retrieve the + * last message from the send queue and examine GetSendAttempts(). If greater than 2, give up + * and remove the message from the queue. Otherwise, resend the message. + * - If something did happen [reset m_wakeEvent] + */ + void DriverThreadProc(Internal::Platform::Event* _exitEvent); + /** + * Initialize the controller. Open the specified serial port, start the serialThread + * and pollThread, then send a NAK to the device [presumably to flush it]. + *

+ * Then queue the commands to retrieve the Z-Wave interface: + * - Get version + * - Get home and node IDs + * - Get controller capabilities + * - Get serial API capabilities + * - [Get SUC node ID] + * - Get init data [identifying the nodes on the network] + * Init() will return false if the serial port could not be opened. + */ + bool Init(uint32 _attempts); + + /** + * Remove any messages to a node on the queues + * Used when deleting a node. + */ + void RemoveQueues(uint8 const _nodeId); + + Internal::Platform::Thread* m_driverThread; /**< Thread for reading from the Z-Wave controller, and for creating and managing the other threads for sending, polling etc. */ + Internal::DNSThread* m_dns; /**< DNSThread Class */ + Internal::Platform::Thread* m_dnsThread; /**< Thread for DNS Queries */ + Internal::Platform::Mutex* m_initMutex; /**< Mutex to ensure proper ordering of initialization/deinitialization */ + bool m_exit; /**< Flag that is set when the application is exiting. */ + bool m_init; /**< Set to true once the driver has been initialised */ + bool m_awakeNodesQueried; /**< Set to true once the driver has polled all awake nodes */ + bool m_allNodesQueried; /**< Set to true once the driver has polled all nodes */ + bool m_notifytransactions; + Internal::Platform::TimeStamp m_startTime; /**< Time this driver started (for log report purposes) */ + + //----------------------------------------------------------------------------- + // Configuration + //----------------------------------------------------------------------------- + private: + void RequestConfig(); // Get the network configuration from the Z-Wave network + bool ReadCache(); // Read the configuration from a file + void WriteCache(); // Save the configuration to a file + + //----------------------------------------------------------------------------- + // Timer + //----------------------------------------------------------------------------- + private: + Internal::TimerThread* m_timer; /**< TimerThread Class */ + Internal::Platform::Thread* m_timerThread; /**< Thread for timer events */ + + public: + Internal::TimerThread* GetTimer() + { + return m_timer; } - return count; - } - /** - * A version of GetNode that does not have the protective "lock" and "release" requirement. - * This function can be used within driverThread, which "knows" that the node will not be - * changed or deleted while it is being used. - * \param _nodeId The nodeId (index into the node array) identifying the node to be returned - * \return - * A pointer to the specified node (if it exists) or NULL if not. - * \see GetNode - */ - Node* GetNodeUnsafe( uint8 _nodeId ); - /** - * Locks the node array and returns the specified node (if it exists). If a node is returned, - * the lock must be released after the node has been processed via a call to ReleaseNodes(). - * If the node specified by _nodeId does not exist, the lock is released and NULL is returned. - * \param _nodeId The nodeId (index into the node array) identifying the node to be returned - * \return - * A pointer to the specified node (if it exists) or NULL if not. - * \see LockNodes, ReleaseNodes - */ - Node* GetNode( uint8 _nodeId ); - /** - * Lock the nodes so no other thread can modify them. - */ - //void LockNodes(); - /** - * Release the lock on the nodes so other threads can modify them. - */ - //void ReleaseNodes(); - - ControllerInterface m_controllerInterfaceType; // Specifies the controller's hardware interface - string m_controllerPath; // name or path used to open the controller hardware. - Controller* m_controller; // Handles communications with the controller hardware. - uint32 m_homeId; // Home ID of the Z-Wave controller. Not valid until the DriverReady notification has been received. - - string m_libraryVersion; // Version of the Z-Wave Library used by the controller. - string m_libraryTypeName; // Name describing the library type. - uint8 m_libraryType; // Type of library used by the controller. - - uint8 m_serialAPIVersion[2]; - uint16 m_manufacturerId; - uint16 m_productType; - uint16 m_productId; - uint8 m_apiMask[32]; - - uint8 m_initVersion; // Version of the Serial API used by the controller. - uint8 m_initCaps; // Set of flags indicating the serial API capabilities (See IsSlave, HasTimerSupport, IsPrimaryController and IsStaticUpdateController above). - uint8 m_controllerCaps; // Set of flags indicating the controller's capabilities (See IsInclusionController above). - bool m_hasExtendedTxStatus; // True if the controller accepted SERIAL_API_SETUP_CMD_TX_STATUS_REPORT - uint8 m_Controller_nodeId; // Z-Wave Controller's own node ID. - Node* m_nodes[256]; // Array containing all the node objects. - Mutex* m_nodeMutex; // Serializes access to node data - - ControllerReplication* m_controllerReplication; // Controller replication is handled separately from the other command classes, due to older hand-held controllers using invalid node IDs. - - uint8 m_transmitOptions; - - //----------------------------------------------------------------------------- - // Receiving Z-Wave messages - //----------------------------------------------------------------------------- - private: - bool ReadMsg(); - void ProcessMsg( uint8* _data, uint8 _length ); - - void HandleGetVersionResponse( uint8* _data ); - void HandleGetRandomResponse( uint8* _data ); - void HandleSerialAPISetupResponse( uint8* _data ); - void HandleGetControllerCapabilitiesResponse( uint8* _data ); - void HandleGetSerialAPICapabilitiesResponse( uint8* _data ); - void HandleSerialAPISoftResetResponse( uint8* _data ); - void HandleEnableSUCResponse( uint8* _data ); - void HandleSetSUCNodeIdResponse( uint8* _data ); - void HandleGetSUCNodeIdResponse( uint8* _data ); - void HandleMemoryGetIdResponse( uint8* _data ); - /** - * Process a response to a FUNC_ID_SERIAL_API_GET_INIT_DATA request. - *

- * The response message contains a bitmap identifying which of the 232 possible nodes - * in the network are actually present. These bitmap values are compared with the - * node map (read in from zwcfg_0x[homeid].xml) to see if the node has already been registered - * by the OpenZWave library. If it has (the log will show it as "Known") and this is - * the first time this message was sent (m_init is false), then AddNodeQuery() is called - * to retrieve its current state. If this is a "New" node to OpenZWave, then InitNode() - * is called. - * \see AddNodeQuery, InitNode, GetNode, ReleaseNodes - */ - void HandleSerialAPIGetInitDataResponse( uint8* _data ); - void HandleGetNodeProtocolInfoResponse( uint8* _data ); - bool HandleRemoveFailedNodeResponse( uint8* _data ); - void HandleIsFailedNodeResponse( uint8* _data ); - bool HandleReplaceFailedNodeResponse( uint8* _data ); - bool HandleAssignReturnRouteResponse( uint8* _data ); - bool HandleDeleteReturnRouteResponse( uint8* _data ); - void HandleSendNodeInformationRequest( uint8* _data ); - void HandleSendDataResponse( uint8* _data, bool _replication ); - bool HandleNetworkUpdateResponse( uint8* _data ); - void HandleGetRoutingInfoResponse( uint8* _data ); - - void HandleSendDataRequest( uint8* _data, uint8 _length, bool _replication ); - void HandleAddNodeToNetworkRequest( uint8* _data ); - void HandleCreateNewPrimaryRequest( uint8* _data ); - void HandleControllerChangeRequest( uint8* _data ); - void HandleSetLearnModeRequest( uint8* _data ); - void HandleRemoveFailedNodeRequest( uint8* _data ); - void HandleReplaceFailedNodeRequest( uint8* _data ); - void HandleRemoveNodeFromNetworkRequest( uint8* _data ); - void HandleApplicationCommandHandlerRequest( uint8* _data, bool encrypted ); - void HandlePromiscuousApplicationCommandHandlerRequest( uint8* _data ); - void HandleAssignReturnRouteRequest( uint8* _data ); - void HandleDeleteReturnRouteRequest( uint8* _data ); - void HandleNodeNeighborUpdateRequest( uint8* _data ); - void HandleNetworkUpdateRequest( uint8* _data ); - bool HandleApplicationUpdateRequest( uint8* _data ); - bool HandleRfPowerLevelSetResponse( uint8* _data ); - bool HandleSerialApiSetTimeoutsResponse( uint8* _data ); - bool HandleMemoryGetByteResponse( uint8* _data ); - bool HandleReadMemoryResponse( uint8* _data ); - void HandleGetVirtualNodesResponse( uint8* _data ); - bool HandleSetSlaveLearnModeResponse( uint8* _data ); - void HandleSetSlaveLearnModeRequest( uint8* _data ); - bool HandleSendSlaveNodeInfoResponse( uint8* _data ); - void HandleSendSlaveNodeInfoRequest( uint8* _data ); - void HandleApplicationSlaveCommandRequest( uint8* _data ); - void HandleSerialAPIResetRequest( uint8* _data ); - - void CommonAddNodeStatusRequestHandler( uint8 _funcId, uint8* _data ); - - bool m_waitingForAck; // True when we are waiting for an ACK from the dongle - uint8 m_expectedCallbackId; // If non-zero, we wait for a message with this callback Id - uint8 m_expectedReply; // If non-zero, we wait for a message with this function Id - uint8 m_expectedCommandClassId; // If the expected reply is FUNC_ID_APPLICATION_COMMAND_HANDLER, this value stores the command class we're waiting to hear from - uint8 m_expectedNodeId; // If we are waiting for a FUNC_ID_APPLICATION_COMMAND_HANDLER, make sure we only accept it from this node. - - //----------------------------------------------------------------------------- - // Polling Z-Wave devices - //----------------------------------------------------------------------------- - private: - int32 GetPollInterval(){ return m_pollInterval ; } - void SetPollInterval( int32 _milliseconds, bool _bIntervalBetweenPolls ){ m_pollInterval = _milliseconds; m_bIntervalBetweenPolls = _bIntervalBetweenPolls; } - bool EnablePoll( const ValueID &_valueId, uint8 _intensity = 1 ); - bool DisablePoll( const ValueID &_valueId ); - bool isPolled( const ValueID &_valueId ); - void SetPollIntensity( const ValueID &_valueId, uint8 _intensity ); - static void PollThreadEntryPoint( Event* _exitEvent, void* _context ); - void PollThreadProc( Event* _exitEvent ); - - Thread* m_pollThread; // Thread for polling devices on the Z-Wave network - struct PollEntry - { - ValueID m_id; - uint8 m_pollCounter; - }; -OPENZWAVE_EXPORT_WARNINGS_OFF - list m_pollList; // List of nodes that need to be polled -OPENZWAVE_EXPORT_WARNINGS_ON - Mutex* m_pollMutex; // Serialize access to the polling list - int32 m_pollInterval; // Time interval during which all nodes must be polled - bool m_bIntervalBetweenPolls; // if true, the library intersperses m_pollInterval between polls; if false, the library attempts to complete all polls within m_pollInterval - - //----------------------------------------------------------------------------- - // Retrieving Node information - //----------------------------------------------------------------------------- - public: - uint8 GetNodeNumber( Msg const* _msg )const{ return ( _msg == NULL ? 0 : _msg->GetTargetNodeId() ); } - - private: - /** - * Creates a new Node object (deleting any previous Node object with the same nodeId) and - * queues a full query of the node's parameters (starting at the beginning of the query - * stages--Node::QueryStage_None). This function will send Notification::Type_NodeAdded - * and Notification::Type_NodeRemoved messages to identify these modifications. - * \param _nodeId The node ID of the node to create and query. - * \param newNode If this is a new Node added to the network, or we are just creating when we reload. - * \param _protocolInfo if this is called via a AddNode command, then this would be the Device Classes, and CommandClass list - * \param _length The length of the _protocolInfo field - * \see Notification::Type_NodeAdded, Notification::Type_NodeRemoved, Node::QueryStage_None, - */ - void InitNode( uint8 const _nodeId, bool newNode = false, bool secure = false, uint8 const *_protocolInfo = NULL, uint8 const _length = 0); - - void InitAllNodes(); // Delete all nodes and fetch the data from the Z-Wave network again. - - bool IsNodeListeningDevice( uint8 const _nodeId ); - bool IsNodeFrequentListeningDevice( uint8 const _nodeId ); - bool IsNodeBeamingDevice( uint8 const _nodeId ); - bool IsNodeRoutingDevice( uint8 const _nodeId ); - bool IsNodeSecurityDevice( uint8 const _nodeId ); - uint32 GetNodeMaxBaudRate( uint8 const _nodeId ); - uint8 GetNodeVersion( uint8 const _nodeId ); - uint8 GetNodeSecurity( uint8 const _nodeId ); - uint8 GetNodeBasic( uint8 const _nodeId ); - uint8 GetNodeGeneric( uint8 const _nodeId ); - uint8 GetNodeSpecific( uint8 const _nodeId ); - string GetNodeType( uint8 const _nodeId ); - uint32 GetNodeNeighbors( uint8 const _nodeId, uint8** o_neighbors ); - - string GetNodeManufacturerName( uint8 const _nodeId ); - string GetNodeProductName( uint8 const _nodeId ); - string GetNodeName( uint8 const _nodeId ); - string GetNodeLocation( uint8 const _nodeId ); - uint16 GetNodeDeviceType( uint8 const _nodeId ); - string GetNodeDeviceTypeString( uint8 const _nodeId ); - uint8 GetNodeRole( uint8 const _nodeId ); - string GetNodeRoleString( uint8 const _nodeId ); - uint8 GetNodePlusType( uint8 const _nodeId ); - string GetNodePlusTypeString ( uint8 const _nodeId ); - bool IsNodeZWavePlus( uint8 const _nodeId ); - - - uint16 GetNodeManufacturerId( uint8 const _nodeId ); - uint16 GetNodeProductType( uint8 const _nodeId ); - uint16 GetNodeProductId( uint8 const _nodeId ); - void SetNodeManufacturerName( uint8 const _nodeId, string const& _manufacturerName ); - void SetNodeProductName( uint8 const _nodeId, string const& _productName ); - void SetNodeName( uint8 const _nodeId, string const& _nodeName ); - void SetNodeLocation( uint8 const _nodeId, string const& _location ); - void SetNodeLevel( uint8 const _nodeId, uint8 const _level ); - void SetNodeOn( uint8 const _nodeId ); - void SetNodeOff( uint8 const _nodeId ); - - Value* GetValue( ValueID const& _id ); - - bool IsAPICallSupported( uint8 const _apinum )const{ return (( m_apiMask[( _apinum - 1 ) >> 3] & ( 1 << (( _apinum - 1 ) & 0x07 ))) != 0 ); } - void SetAPICall( uint8 const _apinum, bool _toSet ) - { - if( _toSet ) + //----------------------------------------------------------------------------- + // Controller + //----------------------------------------------------------------------------- + private: + // Controller Capabilities (return in FUNC_ID_ZW_GET_CONTROLLER_CAPABILITIES) + enum { - m_apiMask[( _apinum - 1 ) >> 3] |= ( 1 << (( _apinum - 1 ) & 0x07 )); + ControllerCaps_Secondary = 0x01, /**< The controller is a secondary. */ + ControllerCaps_OnOtherNetwork = 0x02, /**< The controller is not using its default HomeID. */ + ControllerCaps_SIS = 0x04, /**< There is a SUC ID Server on the network. */ + ControllerCaps_RealPrimary = 0x08, /**< Controller was the primary before the SIS was added. */ + ControllerCaps_SUC = 0x10 /**< Controller is a static update controller. */ + }; + + // Init Capabilities (return in FUNC_ID_SERIAL_API_GET_INIT_DATA) + enum + { + InitCaps_Slave = 0x01, /**< */ + InitCaps_TimerSupport = 0x02, /**< Controller supports timers. */ + InitCaps_Secondary = 0x04, /**< Controller is a secondary. */ + InitCaps_SUC = 0x08 /**< Controller is a static update controller. */ + }; + + bool IsPrimaryController() const + { + return ((m_initCaps & InitCaps_Secondary) == 0); } - else + bool IsStaticUpdateController() const { - m_apiMask[( _apinum - 1 ) >> 3] &= ~( 1 << (( _apinum - 1 ) & 0x07 )); + return ((m_initCaps & InitCaps_SUC) != 0); + } + bool IsBridgeController() const + { + return (m_libraryType == 7); + } + bool IsInclusionController() const + { + return ((m_controllerCaps & ControllerCaps_SIS) != 0); } - } - uint8 NodeFromMessage( uint8 const* buffer ); - - //----------------------------------------------------------------------------- - // Controller commands - //----------------------------------------------------------------------------- - public: - /** - * Controller Commands. - * Commands to be used with the BeginControllerCommand method. - * \see Manager::BeginControllerCommand - */ - enum ControllerCommand - { - ControllerCommand_None = 0, /**< No command. */ - ControllerCommand_AddDevice, /**< Add a new device or controller to the Z-Wave network. */ - ControllerCommand_CreateNewPrimary, /**< Add a new controller to the Z-Wave network. Used when old primary fails. Requires SUC. */ - ControllerCommand_ReceiveConfiguration, /**< Receive Z-Wave network configuration information from another controller. */ - ControllerCommand_RemoveDevice, /**< Remove a device or controller from the Z-Wave network. */ - ControllerCommand_RemoveFailedNode, /**< Move a node to the controller's failed nodes list. This command will only work if the node cannot respond. */ - ControllerCommand_HasNodeFailed, /**< Check whether a node is in the controller's failed nodes list. */ - ControllerCommand_ReplaceFailedNode, /**< Replace a non-responding node with another. The node must be in the controller's list of failed nodes for this command to succeed. */ - ControllerCommand_TransferPrimaryRole, /**< Make a different controller the primary. */ - ControllerCommand_RequestNetworkUpdate, /**< Request network information from the SUC/SIS. */ - ControllerCommand_RequestNodeNeighborUpdate, /**< Get a node to rebuild its neighbour list. This method also does RequestNodeNeighbors */ - ControllerCommand_AssignReturnRoute, /**< Assign a network return routes to a device. */ - ControllerCommand_DeleteAllReturnRoutes, /**< Delete all return routes from a device. */ - ControllerCommand_SendNodeInformation, /**< Send a node information frame */ - ControllerCommand_ReplicationSend, /**< Send information from primary to secondary */ - ControllerCommand_CreateButton, /**< Create an id that tracks handheld button presses */ - ControllerCommand_DeleteButton /**< Delete id that tracks handheld button presses */ - }; - - /** - * Controller States. - * States reported via the callback handler passed into the BeginControllerCommand method. - * \see Manager::BeginControllerCommand - */ - enum ControllerState - { - ControllerState_Normal = 0, /**< No command in progress. */ - ControllerState_Starting, /**< The command is starting. */ - ControllerState_Cancel, /**< The command was canceled. */ - ControllerState_Error, /**< Command invocation had error(s) and was aborted */ - ControllerState_Waiting, /**< Controller is waiting for a user action. */ - ControllerState_Sleeping, /**< Controller command is on a sleep queue wait for device. */ - ControllerState_InProgress, /**< The controller is communicating with the other device to carry out the command. */ - ControllerState_Completed, /**< The command has completed successfully. */ - ControllerState_Failed, /**< The command has failed. */ - ControllerState_NodeOK, /**< Used only with ControllerCommand_HasNodeFailed to indicate that the controller thinks the node is OK. */ - ControllerState_NodeFailed /**< Used only with ControllerCommand_HasNodeFailed to indicate that the controller thinks the node has failed. */ - }; - - /** - * Controller Errors - * Provide some more information about controller failures. - */ - enum ControllerError - { - ControllerError_None = 0, - ControllerError_ButtonNotFound, /**< Button */ - ControllerError_NodeNotFound, /**< Button */ - ControllerError_NotBridge, /**< Button */ - ControllerError_NotSUC, /**< CreateNewPrimary */ - ControllerError_NotSecondary, /**< CreateNewPrimary */ - ControllerError_NotPrimary, /**< RemoveFailedNode, AddNodeToNetwork */ - ControllerError_IsPrimary, /**< ReceiveConfiguration */ - ControllerError_NotFound, /**< RemoveFailedNode */ - ControllerError_Busy, /**< RemoveFailedNode, RequestNetworkUpdate */ - ControllerError_Failed, /**< RemoveFailedNode, RequestNetworkUpdate */ - ControllerError_Disabled, /**< RequestNetworkUpdate error */ - ControllerError_Overflow /**< RequestNetworkUpdate error */ - }; - - typedef void (*pfnControllerCallback_t)( ControllerState _state, ControllerError _err, void* _context ); - - private: - // The public interface is provided via the wrappers in the Manager class - void ResetController( Event* _evt ); - void SoftReset(); - void RequestNodeNeighbors( uint8 const _nodeId, uint32 const _requestFlags ); - - bool BeginControllerCommand( ControllerCommand _command, pfnControllerCallback_t _callback, void* _context, bool _highPower, uint8 _nodeId, uint8 _arg ); - bool CancelControllerCommand(); - void AddNodeStop( uint8 const _funcId ); // Handle different controller behaviors - - struct ControllerCommandItem - { - ControllerState m_controllerState; - bool m_controllerStateChanged; - bool m_controllerCommandDone; - ControllerCommand m_controllerCommand; - pfnControllerCallback_t m_controllerCallback; - ControllerError m_controllerReturnError; - void* m_controllerCallbackContext; - bool m_highPower; - bool m_controllerAdded; - uint8 m_controllerCommandNode; - uint8 m_controllerCommandArg; - uint8 m_controllerDeviceProtocolInfo[254]; - uint8 m_controllerDeviceProtocolInfoLength; - }; - - ControllerCommandItem* m_currentControllerCommand; - - void DoControllerCommand(); - void UpdateControllerState( ControllerState const _state, ControllerError const _error = ControllerError_None ); - - uint8 m_SUCNodeId; - - void UpdateNodeRoutes( uint8 const_nodeId, bool _doUpdate = false ); - - Event* m_controllerResetEvent; - - //----------------------------------------------------------------------------- - // Sending Z-Wave messages - //----------------------------------------------------------------------------- - public: - enum MsgQueue - { - MsgQueue_Command = 0, - MsgQueue_NoOp, - MsgQueue_Controller, - MsgQueue_WakeUp, - MsgQueue_Send, - MsgQueue_Query, - MsgQueue_Poll, - MsgQueue_Count // Number of message queues - }; - - void SendMsg( Msg* _msg, MsgQueue const _queue ); - - /** - * Fetch the transmit options - */ - uint8 GetTransmitOptions()const{ return m_transmitOptions; } - - private: - /** - * If there are messages in the send queue (m_sendQueue), gets the next message in the - * queue and writes it to the serial port. In sending the message, SendMsg also initializes - * variables tracking the message's callback ID (m_expectedCallbackId), expected reply - * (m_expectedReply) and expected command class ID (m_expectedCommandClassId). It also - * sets m_waitingForAck to true and increments the message's send attempts counter. - *

- * If there are no messages in the send queue, then SendMsg checks the query queue to - * see if there are any outstanding queries that can be processed (target node not asleep). - * If so, it retrieves the Node object that needs to be queried and calls that node's - * AdvanceQueries member function. If this call results in all of the node's queries to be - * completed, SendMsg will remove the node query item from the query queue. - * \return TRUE if data was written, FALSE if not - * \see Msg, m_sendQueue, m_expectedCallbackId, m_expectedReply, m_expectedCommandClassId, - * m_waitingForAck, Msg::GetSendAttempts, Node::AdvanceQueries, GetCurrentNodeQuery, - * RemoveNodeQuery, Node::AllQueriesCompleted - */ - bool WriteNextMsg( MsgQueue const _queue ); // Extracts the first message from the queue, and makes it the current one. - bool WriteMsg( string const &str); // Sends the current message to the Z-Wave network - void RemoveCurrentMsg(); // Deletes the current message and cleans up the callback etc states - bool MoveMessagesToWakeUpQueue( uint8 const _targetNodeId, bool const _move ); // If a node does not respond, and is of a type that can sleep, this method is used to move all its pending messages to another queue ready for when it wakes up next. - bool HandleErrorResponse( uint8 const _error, uint8 const _nodeId, char const* _funcStr, bool _sleepCheck = false ); // Handle data errors and process consistently. If message is moved to wake-up queue, return true. - bool IsExpectedReply( uint8 const _nodeId ); // Determine if reply message is the one we are expecting - void SendQueryStageComplete( uint8 const _nodeId, Node::QueryStage const _stage ); - void RetryQueryStageComplete( uint8 const _nodeId, Node::QueryStage const _stage ); - void CheckCompletedNodeQueries(); // Send notifications if all awake and/or sleeping nodes have completed their queries - - // Requests to be sent to nodes are assigned to one of five queues. - // From highest to lowest priority, these are - // - // 0) The security queue, for handling encrypted messages. This is the - // highest priority send queue, because the security process inserts - // messages to handle the encryption process that must be sent before - // a new message can be wrapped. - // - // 1) The command queue, for controller commands. This is the 2nd highest - // priority send queue, because the controller command processes are not - // permitted to be interrupted by other requests. - // - // 2) The controller queue exists to handle multi-step controller commands. These - // typically require user interaction or affect the network in some way. - // - // 3) The No Operation command class queue. This is used for device probing - // at startup as well as network diagnostics. - // - // 4) The wakeup queue. This holds messages that have been held for a - // sleeping device that has now woken up. These get a high priority - // because such devices do not stay awake for very long. - // - // 5) The send queue. This is for normal messages, usually triggered by - // a user interaction with the application. - // - // 6) The query queue. For node query messages sent when a new node is - // discovered. The query process generates a large number of requests, - // so the query queue has a low priority to avoid making the system - // unresponsive. - // - // 7) The poll queue. Requests to devices that need their state polling - // at regular intervals. These are of the lowest priority, and are only - // sent when nothing else is going on - // - enum MsgQueueCmd - { - MsgQueueCmd_SendMsg = 0, - MsgQueueCmd_QueryStageComplete, - MsgQueueCmd_Controller, - MsgQueueCmd_ReloadNode - }; - class MsgQueueItem - { + bool HasExtendedTxStatus() const + { + return m_hasExtendedTxStatus; + } + + uint32 GetHomeId() const + { + return m_homeId; + } + uint8 GetControllerNodeId() const + { + return m_Controller_nodeId; + } + uint8 GetSUCNodeId() const + { + return m_SUCNodeId; + } + uint16 GetManufacturerId() const + { + return m_manufacturerId; + } + uint16 GetProductType() const + { + return m_productType; + } + uint16 GetProductId() const + { + return m_productId; + } + string GetControllerPath() const + { + return m_controllerPath; + } + ControllerInterface GetControllerInterfaceType() const + { + return m_controllerInterfaceType; + } + string GetLibraryVersion() const + { + return m_libraryVersion; + } + string GetLibraryTypeName() const + { + return m_libraryTypeName; + } + int32 GetSendQueueCount() const + { + int32 count = 0; + for (int32 i = 0; i < MsgQueue_Count; ++i) + { + count += (int32) (m_msgQueue[i].size()); + } + return count; + } + + /** + * A version of GetNode that does not have the protective "lock" and "release" requirement. + * This function can be used within driverThread, which "knows" that the node will not be + * changed or deleted while it is being used. + * \param _nodeId The nodeId (index into the node array) identifying the node to be returned + * \return + * A pointer to the specified node (if it exists) or NULL if not. + * \see GetNode + */ + Node* GetNodeUnsafe(uint8 _nodeId); + /** + * Locks the node array and returns the specified node (if it exists). If a node is returned, + * the lock must be released after the node has been processed via a call to ReleaseNodes(). + * If the node specified by _nodeId does not exist, the lock is released and NULL is returned. + * \param _nodeId The nodeId (index into the node array) identifying the node to be returned + * \return + * A pointer to the specified node (if it exists) or NULL if not. + */ + Node* GetNode(uint8 _nodeId); + + ControllerInterface m_controllerInterfaceType; // Specifies the controller's hardware interface + string m_controllerPath; // name or path used to open the controller hardware. + Internal::Platform::Controller* m_controller; // Handles communications with the controller hardware. + uint32 m_homeId; // Home ID of the Z-Wave controller. Not valid until the DriverReady notification has been received. + string m_libraryVersion; // Version of the Z-Wave Library used by the controller. + string m_libraryTypeName; // Name describing the library type. + uint8 m_libraryType; // Type of library used by the controller. + + uint8 m_serialAPIVersion[2]; + uint16 m_manufacturerId; + uint16 m_productType; + uint16 m_productId; + uint8 m_apiMask[32]; + + uint8 m_initVersion; // Version of the Serial API used by the controller. + uint8 m_initCaps; // Set of flags indicating the serial API capabilities (See IsSlave, HasTimerSupport, IsPrimaryController and IsStaticUpdateController above). + uint8 m_controllerCaps; // Set of flags indicating the controller's capabilities (See IsInclusionController above). + bool m_hasExtendedTxStatus; // True if the controller accepted SERIAL_API_SETUP_CMD_TX_STATUS_REPORT + uint8 m_Controller_nodeId; // Z-Wave Controller's own node ID. + Node* m_nodes[256]; // Array containing all the node objects. + Internal::Platform::Mutex* m_nodeMutex; // Serializes access to node data + + Internal::CC::ControllerReplication* m_controllerReplication; // Controller replication is handled separately from the other command classes, due to older hand-held controllers using invalid node IDs. + + uint8 m_transmitOptions; + + //----------------------------------------------------------------------------- + // Receiving Z-Wave messages + //----------------------------------------------------------------------------- + private: + bool ReadMsg(); + void ProcessMsg(uint8* _data, uint8 _length); + + void HandleGetVersionResponse(uint8* _data); + void HandleGetRandomResponse(uint8* _data); + void HandleSerialAPISetupResponse(uint8* _data); + void HandleGetControllerCapabilitiesResponse(uint8* _data); + void HandleGetSerialAPICapabilitiesResponse(uint8* _data); + void HandleSerialAPISoftResetResponse(uint8* _data); + void HandleEnableSUCResponse(uint8* _data); + void HandleSetSUCNodeIdResponse(uint8* _data); + void HandleGetSUCNodeIdResponse(uint8* _data); + void HandleMemoryGetIdResponse(uint8* _data); + /** + * Process a response to a FUNC_ID_SERIAL_API_GET_INIT_DATA request. + *

+ * The response message contains a bitmap identifying which of the 232 possible nodes + * in the network are actually present. These bitmap values are compared with the + * node map (read in from zwcfg_0x[homeid].xml) to see if the node has already been registered + * by the OpenZWave library. If it has (the log will show it as "Known") and this is + * the first time this message was sent (m_init is false), then AddNodeQuery() is called + * to retrieve its current state. If this is a "New" node to OpenZWave, then InitNode() + * is called. + * \see AddNodeQuery, InitNode, GetNode, ReleaseNodes + */ + void HandleSerialAPIGetInitDataResponse(uint8* _data); + void HandleGetNodeProtocolInfoResponse(uint8* _data); + bool HandleRemoveFailedNodeResponse(uint8* _data); + void HandleIsFailedNodeResponse(uint8* _data); + bool HandleReplaceFailedNodeResponse(uint8* _data); + bool HandleAssignReturnRouteResponse(uint8* _data); + bool HandleDeleteReturnRouteResponse(uint8* _data); + void HandleSendNodeInformationRequest(uint8* _data); + void HandleSendDataResponse(uint8* _data, bool _replication); + bool HandleNetworkUpdateResponse(uint8* _data); + void HandleGetRoutingInfoResponse(uint8* _data); + + void HandleSendDataRequest(uint8* _data, uint8 _length, bool _replication); + void HandleAddNodeToNetworkRequest(uint8* _data); + void HandleCreateNewPrimaryRequest(uint8* _data); + void HandleControllerChangeRequest(uint8* _data); + void HandleSetLearnModeRequest(uint8* _data); + void HandleRemoveFailedNodeRequest(uint8* _data); + void HandleReplaceFailedNodeRequest(uint8* _data); + void HandleRemoveNodeFromNetworkRequest(uint8* _data); + void HandleApplicationCommandHandlerRequest(uint8* _data, bool encrypted); + void HandlePromiscuousApplicationCommandHandlerRequest(uint8* _data); + void HandleAssignReturnRouteRequest(uint8* _data); + void HandleDeleteReturnRouteRequest(uint8* _data); + void HandleNodeNeighborUpdateRequest(uint8* _data); + void HandleNetworkUpdateRequest(uint8* _data); + bool HandleApplicationUpdateRequest(uint8* _data); + bool HandleRfPowerLevelSetResponse(uint8* _data); + bool HandleSerialApiSetTimeoutsResponse(uint8* _data); + bool HandleMemoryGetByteResponse(uint8* _data); + bool HandleReadMemoryResponse(uint8* _data); + void HandleGetVirtualNodesResponse(uint8* _data); + bool HandleSetSlaveLearnModeResponse(uint8* _data); + void HandleSetSlaveLearnModeRequest(uint8* _data); + bool HandleSendSlaveNodeInfoResponse(uint8* _data); + void HandleSendSlaveNodeInfoRequest(uint8* _data); + void HandleApplicationSlaveCommandRequest(uint8* _data); + void HandleSerialAPIResetRequest(uint8* _data); + + void CommonAddNodeStatusRequestHandler(uint8 _funcId, uint8* _data); + + bool m_waitingForAck; // True when we are waiting for an ACK from the dongle + uint8 m_expectedCallbackId; // If non-zero, we wait for a message with this callback Id + uint8 m_expectedReply; // If non-zero, we wait for a message with this function Id + uint8 m_expectedCommandClassId; // If the expected reply is FUNC_ID_APPLICATION_COMMAND_HANDLER, this value stores the command class we're waiting to hear from + uint8 m_expectedNodeId; // If we are waiting for a FUNC_ID_APPLICATION_COMMAND_HANDLER, make sure we only accept it from this node. + + //----------------------------------------------------------------------------- + // Polling Z-Wave devices + //----------------------------------------------------------------------------- + private: + int32 GetPollInterval() + { + return m_pollInterval; + } + void SetPollInterval(int32 _milliseconds, bool _bIntervalBetweenPolls) + { + m_pollInterval = _milliseconds; + m_bIntervalBetweenPolls = _bIntervalBetweenPolls; + } + bool EnablePoll(const ValueID &_valueId, uint8 _intensity = 1); + bool DisablePoll(const ValueID &_valueId); + bool isPolled(const ValueID &_valueId); + void SetPollIntensity(const ValueID &_valueId, uint8 _intensity); + static void PollThreadEntryPoint(Internal::Platform::Event* _exitEvent, void* _context); + void PollThreadProc(Internal::Platform::Event* _exitEvent); + + Internal::Platform::Thread* m_pollThread; // Thread for polling devices on the Z-Wave network + struct PollEntry + { + ValueID m_id; + uint8 m_pollCounter; + }; + list m_pollList; // List of nodes that need to be polled + Internal::Platform::Mutex* m_pollMutex; // Serialize access to the polling list + int32 m_pollInterval; // Time interval during which all nodes must be polled + bool m_bIntervalBetweenPolls; // if true, the library intersperses m_pollInterval between polls; if false, the library attempts to complete all polls within m_pollInterval + + //----------------------------------------------------------------------------- + // Retrieving Node information + //----------------------------------------------------------------------------- public: - MsgQueueItem() : - m_msg(NULL), - m_nodeId(0), - m_queryStage(Node::QueryStage_None), - m_retry(false), - m_cci(NULL) - {} + uint8 GetNodeNumber(Internal::Msg const* _msg) const + { + return (_msg == NULL ? 0 : _msg->GetTargetNodeId()); + } - bool operator == ( MsgQueueItem const& _other )const + private: + /** + * Creates a new Node object (deleting any previous Node object with the same nodeId) and + * queues a full query of the node's parameters (starting at the beginning of the query + * stages--Node::QueryStage_None). This function will send Notification::Type_NodeAdded + * and Notification::Type_NodeRemoved messages to identify these modifications. + * \param _nodeId The node ID of the node to create and query. + * \param newNode If this is a new Node added to the network, or we are just creating when we reload. + * \param _protocolInfo if this is called via a AddNode command, then this would be the Device Classes, and CommandClass list + * \param _length The length of the _protocolInfo field + * \see Notification::Type_NodeAdded, Notification::Type_NodeRemoved, Node::QueryStage_None, + */ + void InitNode(uint8 const _nodeId, bool newNode = false, bool secure = false, uint8 const *_protocolInfo = NULL, uint8 const _length = 0); + + void InitAllNodes(); // Delete all nodes and fetch the data from the Z-Wave network again. + + bool IsNodeListeningDevice(uint8 const _nodeId); + bool IsNodeFrequentListeningDevice(uint8 const _nodeId); + bool IsNodeBeamingDevice(uint8 const _nodeId); + bool IsNodeRoutingDevice(uint8 const _nodeId); + bool IsNodeSecurityDevice(uint8 const _nodeId); + uint32 GetNodeMaxBaudRate(uint8 const _nodeId); + uint8 GetNodeVersion(uint8 const _nodeId); + uint8 GetNodeSecurity(uint8 const _nodeId); + uint8 GetNodeBasic(uint8 const _nodeId); + string GetNodeBasicString(uint8 const _nodeId); + uint8 GetNodeGeneric(uint8 const _nodeId, uint8 _instance); + string GetNodeGenericString(uint8 const _nodeId, uint8 _instance); + uint8 GetNodeSpecific(uint8 const _nodeId, uint8 _instance); + string GetNodeSpecificString(uint8 const _nodeId, uint8 _instance); + string GetNodeType(uint8 const _nodeId); + uint32 GetNodeNeighbors(uint8 const _nodeId, uint8** o_neighbors); + + string GetNodeManufacturerName(uint8 const _nodeId); + string GetNodeProductName(uint8 const _nodeId); + string GetNodeName(uint8 const _nodeId); + string GetNodeLocation(uint8 const _nodeId); + uint16 GetNodeDeviceType(uint8 const _nodeId); + string GetNodeDeviceTypeString(uint8 const _nodeId); + uint8 GetNodeRole(uint8 const _nodeId); + string GetNodeRoleString(uint8 const _nodeId); + uint8 GetNodePlusType(uint8 const _nodeId); + string GetNodePlusTypeString(uint8 const _nodeId); + bool IsNodeZWavePlus(uint8 const _nodeId); + + uint16 GetNodeManufacturerId(uint8 const _nodeId); + uint16 GetNodeProductType(uint8 const _nodeId); + uint16 GetNodeProductId(uint8 const _nodeId); + void SetNodeManufacturerName(uint8 const _nodeId, string const& _manufacturerName); + void SetNodeProductName(uint8 const _nodeId, string const& _productName); + void SetNodeName(uint8 const _nodeId, string const& _nodeName); + void SetNodeLocation(uint8 const _nodeId, string const& _location); + void SetNodeLevel(uint8 const _nodeId, uint8 const _level); + void SetNodeOn(uint8 const _nodeId); + void SetNodeOff(uint8 const _nodeId); + + Internal::VC::Value* GetValue(ValueID const& _id); + + bool IsAPICallSupported(uint8 const _apinum) const + { + return ((m_apiMask[(_apinum - 1) >> 3] & (1 << ((_apinum - 1) & 0x07))) != 0); + } + void SetAPICall(uint8 const _apinum, bool _toSet) { - if( _other.m_command == m_command ) + if (_toSet) { - if( m_command == MsgQueueCmd_SendMsg ) - { - return( (*_other.m_msg) == (*m_msg) ); - } - else if( m_command == MsgQueueCmd_QueryStageComplete ) - { - return( (_other.m_nodeId == m_nodeId) && (_other.m_queryStage == m_queryStage) ); - } - else if( m_command == MsgQueueCmd_Controller ) + m_apiMask[(_apinum - 1) >> 3] |= (1 << ((_apinum - 1) & 0x07)); + } + else + { + m_apiMask[(_apinum - 1) >> 3] &= ~(1 << ((_apinum - 1) & 0x07)); + } + } + uint8 NodeFromMessage(uint8 const* buffer); + + //----------------------------------------------------------------------------- + // Controller commands + //----------------------------------------------------------------------------- + public: + /** + * Controller Commands. + * Commands to be used with the BeginControllerCommand method. + * \see Manager::BeginControllerCommand + */ + enum ControllerCommand + { + ControllerCommand_None = 0, /**< No command. */ + ControllerCommand_AddDevice, /**< Add a new device or controller to the Z-Wave network. */ + ControllerCommand_CreateNewPrimary, /**< Add a new controller to the Z-Wave network. Used when old primary fails. Requires SUC. */ + ControllerCommand_ReceiveConfiguration, /**< Receive Z-Wave network configuration information from another controller. */ + ControllerCommand_RemoveDevice, /**< Remove a device or controller from the Z-Wave network. */ + ControllerCommand_RemoveFailedNode, /**< Move a node to the controller's failed nodes list. This command will only work if the node cannot respond. */ + ControllerCommand_HasNodeFailed, /**< Check whether a node is in the controller's failed nodes list. */ + ControllerCommand_ReplaceFailedNode, /**< Replace a non-responding node with another. The node must be in the controller's list of failed nodes for this command to succeed. */ + ControllerCommand_TransferPrimaryRole, /**< Make a different controller the primary. */ + ControllerCommand_RequestNetworkUpdate, /**< Request network information from the SUC/SIS. */ + ControllerCommand_RequestNodeNeighborUpdate, /**< Get a node to rebuild its neighbour list. This method also does RequestNodeNeighbors */ + ControllerCommand_AssignReturnRoute, /**< Assign a network return routes to a device. */ + ControllerCommand_DeleteAllReturnRoutes, /**< Delete all return routes from a device. */ + ControllerCommand_SendNodeInformation, /**< Send a node information frame */ + ControllerCommand_ReplicationSend, /**< Send information from primary to secondary */ + ControllerCommand_CreateButton, /**< Create an id that tracks handheld button presses */ + ControllerCommand_DeleteButton /**< Delete id that tracks handheld button presses */ + }; + + /** + * Controller States. + * States reported via the callback handler passed into the BeginControllerCommand method. + * \see Manager::BeginControllerCommand + */ + enum ControllerState + { + ControllerState_Normal = 0, /**< No command in progress. */ + ControllerState_Starting, /**< The command is starting. */ + ControllerState_Cancel, /**< The command was canceled. */ + ControllerState_Error, /**< Command invocation had error(s) and was aborted */ + ControllerState_Waiting, /**< Controller is waiting for a user action. */ + ControllerState_Sleeping, /**< Controller command is on a sleep queue wait for device. */ + ControllerState_InProgress, /**< The controller is communicating with the other device to carry out the command. */ + ControllerState_Completed, /**< The command has completed successfully. */ + ControllerState_Failed, /**< The command has failed. */ + ControllerState_NodeOK, /**< Used only with ControllerCommand_HasNodeFailed to indicate that the controller thinks the node is OK. */ + ControllerState_NodeFailed /**< Used only with ControllerCommand_HasNodeFailed to indicate that the controller thinks the node has failed. */ + }; + + /** + * Controller Errors + * Provide some more information about controller failures. + */ + enum ControllerError + { + ControllerError_None = 0, + ControllerError_ButtonNotFound, /**< Button */ + ControllerError_NodeNotFound, /**< Button */ + ControllerError_NotBridge, /**< Button */ + ControllerError_NotSUC, /**< CreateNewPrimary */ + ControllerError_NotSecondary, /**< CreateNewPrimary */ + ControllerError_NotPrimary, /**< RemoveFailedNode, AddNodeToNetwork */ + ControllerError_IsPrimary, /**< ReceiveConfiguration */ + ControllerError_NotFound, /**< RemoveFailedNode */ + ControllerError_Busy, /**< RemoveFailedNode, RequestNetworkUpdate */ + ControllerError_Failed, /**< RemoveFailedNode, RequestNetworkUpdate */ + ControllerError_Disabled, /**< RequestNetworkUpdate error */ + ControllerError_Overflow /**< RequestNetworkUpdate error */ + }; + + typedef void (*pfnControllerCallback_t)(ControllerState _state, ControllerError _err, void* _context); + + private: + // The public interface is provided via the wrappers in the Manager class + void ResetController(Internal::Platform::Event* _evt); + void SoftReset(); + void RequestNodeNeighbors(uint8 const _nodeId, uint32 const _requestFlags); + + bool BeginControllerCommand(ControllerCommand _command, pfnControllerCallback_t _callback, void* _context, bool _highPower, uint8 _nodeId, uint8 _arg); + bool CancelControllerCommand(); + void AddNodeStop(uint8 const _funcId); // Handle different controller behaviors + + struct ControllerCommandItem + { + ControllerState m_controllerState; + bool m_controllerStateChanged; + bool m_controllerCommandDone; + ControllerCommand m_controllerCommand; + pfnControllerCallback_t m_controllerCallback; + ControllerError m_controllerReturnError; + void* m_controllerCallbackContext; + bool m_highPower; + bool m_controllerAdded; + uint8 m_controllerCommandNode; + uint8 m_controllerCommandArg; + uint8 m_controllerDeviceProtocolInfo[254]; + uint8 m_controllerDeviceProtocolInfoLength; + }; + + ControllerCommandItem* m_currentControllerCommand; + + void DoControllerCommand(); + void UpdateControllerState(ControllerState const _state, ControllerError const _error = ControllerError_None); + + uint8 m_SUCNodeId; + + void UpdateNodeRoutes(uint8 const_nodeId, bool _doUpdate = false); + + Internal::Platform::Event* m_controllerResetEvent; + + //----------------------------------------------------------------------------- + // Sending Z-Wave messages + //----------------------------------------------------------------------------- + public: + enum MsgQueue + { + MsgQueue_Command = 0, + MsgQueue_NoOp, + MsgQueue_Controller, + MsgQueue_WakeUp, + MsgQueue_Send, + MsgQueue_Query, + MsgQueue_Poll, + MsgQueue_Count // Number of message queues + }; + + void SendMsg(Internal::Msg* _msg, MsgQueue const _queue); + + /** + * Fetch the transmit options + */ + uint8 GetTransmitOptions() const + { + return m_transmitOptions; + } + + private: + /** + * If there are messages in the send queue (m_sendQueue), gets the next message in the + * queue and writes it to the serial port. In sending the message, SendMsg also initializes + * variables tracking the message's callback ID (m_expectedCallbackId), expected reply + * (m_expectedReply) and expected command class ID (m_expectedCommandClassId). It also + * sets m_waitingForAck to true and increments the message's send attempts counter. + *

+ * If there are no messages in the send queue, then SendMsg checks the query queue to + * see if there are any outstanding queries that can be processed (target node not asleep). + * If so, it retrieves the Node object that needs to be queried and calls that node's + * AdvanceQueries member function. If this call results in all of the node's queries to be + * completed, SendMsg will remove the node query item from the query queue. + * \return TRUE if data was written, FALSE if not + * \see Msg, m_sendQueue, m_expectedCallbackId, m_expectedReply, m_expectedCommandClassId, + * m_waitingForAck, Msg::GetSendAttempts, Node::AdvanceQueries, GetCurrentNodeQuery, + * RemoveNodeQuery, Node::AllQueriesCompleted + */ + bool WriteNextMsg(MsgQueue const _queue); // Extracts the first message from the queue, and makes it the current one. + bool WriteMsg(string const &str); // Sends the current message to the Z-Wave network + void RemoveCurrentMsg(); // Deletes the current message and cleans up the callback etc states + bool MoveMessagesToWakeUpQueue(uint8 const _targetNodeId, bool const _move); // If a node does not respond, and is of a type that can sleep, this method is used to move all its pending messages to another queue ready for when it wakes up next. + bool HandleErrorResponse(uint8 const _error, uint8 const _nodeId, char const* _funcStr, bool _sleepCheck = false); // Handle data errors and process consistently. If message is moved to wake-up queue, return true. + bool IsExpectedReply(uint8 const _nodeId); // Determine if reply message is the one we are expecting + void SendQueryStageComplete(uint8 const _nodeId, Node::QueryStage const _stage); + void RetryQueryStageComplete(uint8 const _nodeId, Node::QueryStage const _stage); + void CheckCompletedNodeQueries(); // Send notifications if all awake and/or sleeping nodes have completed their queries + + // Requests to be sent to nodes are assigned to one of five queues. + // From highest to lowest priority, these are + // + // 0) The security queue, for handling encrypted messages. This is the + // highest priority send queue, because the security process inserts + // messages to handle the encryption process that must be sent before + // a new message can be wrapped. + // + // 1) The command queue, for controller commands. This is the 2nd highest + // priority send queue, because the controller command processes are not + // permitted to be interrupted by other requests. + // + // 2) The controller queue exists to handle multi-step controller commands. These + // typically require user interaction or affect the network in some way. + // + // 3) The No Operation command class queue. This is used for device probing + // at startup as well as network diagnostics. + // + // 4) The wakeup queue. This holds messages that have been held for a + // sleeping device that has now woken up. These get a high priority + // because such devices do not stay awake for very long. + // + // 5) The send queue. This is for normal messages, usually triggered by + // a user interaction with the application. + // + // 6) The query queue. For node query messages sent when a new node is + // discovered. The query process generates a large number of requests, + // so the query queue has a low priority to avoid making the system + // unresponsive. + // + // 7) The poll queue. Requests to devices that need their state polling + // at regular intervals. These are of the lowest priority, and are only + // sent when nothing else is going on + // + enum MsgQueueCmd + { + MsgQueueCmd_SendMsg = 0, + MsgQueueCmd_QueryStageComplete, + MsgQueueCmd_Controller, + MsgQueueCmd_ReloadNode + }; + + class MsgQueueItem + { + public: + MsgQueueItem() : + m_msg(NULL), m_nodeId(0), m_queryStage(Node::QueryStage_None), m_retry(false), m_cci(NULL) { - return( (_other.m_cci->m_controllerCommand == m_cci->m_controllerCommand) && (_other.m_cci->m_controllerCallback == m_cci->m_controllerCallback) ); } - else if (m_command == MsgQueueCmd_ReloadNode ) + + bool operator ==(MsgQueueItem const& _other) const { - return (_other.m_nodeId == m_nodeId); + if (_other.m_command == m_command) + { + if (m_command == MsgQueueCmd_SendMsg) + { + return ((*_other.m_msg) == (*m_msg)); + } + else if (m_command == MsgQueueCmd_QueryStageComplete) + { + return ((_other.m_nodeId == m_nodeId) && (_other.m_queryStage == m_queryStage)); + } + else if (m_command == MsgQueueCmd_Controller) + { + return ((_other.m_cci->m_controllerCommand == m_cci->m_controllerCommand) && (_other.m_cci->m_controllerCallback == m_cci->m_controllerCallback)); + } + else if (m_command == MsgQueueCmd_ReloadNode) + { + return (_other.m_nodeId == m_nodeId); + } + + } + + return false; } - } + MsgQueueCmd m_command; + Internal::Msg* m_msg; + uint8 m_nodeId; + Node::QueryStage m_queryStage; + bool m_retry; + ControllerCommandItem* m_cci; + }; - return false; + list m_msgQueue[MsgQueue_Count]; + Internal::Platform::Event* m_queueEvent[MsgQueue_Count]; // Events for each queue, which are signaled when the queue is not empty + Internal::Platform::Mutex* m_sendMutex; // Serialize access to the queues + Internal::Msg* m_currentMsg; + MsgQueue m_currentMsgQueueSource; // identifies which queue held m_currentMsg + Internal::Platform::TimeStamp m_resendTimeStamp; + + //----------------------------------------------------------------------------- + // Network functions + //----------------------------------------------------------------------------- + private: + void TestNetwork(uint8 const _nodeId, uint32 const _count); + + //----------------------------------------------------------------------------- + // Virtual Node commands + //----------------------------------------------------------------------------- + public: + /** + * Virtual Node Commands. + * Commands to be used with virtual nodes. + */ + private: + uint32 GetVirtualNeighbors(uint8** o_neighbors); + void RequestVirtualNeighbors(MsgQueue const _queue); + bool IsVirtualNode(uint8 const _nodeId) const + { + return ((m_virtualNeighbors[(_nodeId - 1) >> 3] & 1 << ((_nodeId - 1) & 0x07)) != 0); } + void SendVirtualNodeInfo(uint8 const _fromNodeId, uint8 const _ToNodeId); + void SendSlaveLearnModeOff(); + void SaveButtons(); + void ReadButtons(uint8 const _nodeId); + + bool m_virtualNeighborsReceived; + uint8 m_virtualNeighbors[NUM_NODE_BITFIELD_BYTES]; // Bitmask containing virtual neighbors + + //----------------------------------------------------------------------------- + // SwitchAll + //----------------------------------------------------------------------------- + private: + // The public interface is provided via the wrappers in the Manager class + void SwitchAllOn(); + void SwitchAllOff(); + + //----------------------------------------------------------------------------- + // Configuration Parameters (wrappers for the Node methods) + //----------------------------------------------------------------------------- + private: + // The public interface is provided via the wrappers in the Manager class + bool SetConfigParam(uint8 const _nodeId, uint8 const _param, int32 _value, uint8 const _size); + void RequestConfigParam(uint8 const _nodeId, uint8 const _param); + + //----------------------------------------------------------------------------- + // Groups (wrappers for the Node methods) + //----------------------------------------------------------------------------- + private: + // The public interface is provided via the wrappers in the Manager class + uint8 GetNumGroups(uint8 const _nodeId); + uint32 GetAssociations(uint8 const _nodeId, uint8 const _groupIdx, uint8** o_associations); + uint32 GetAssociations(uint8 const _nodeId, uint8 const _groupIdx, InstanceAssociation** o_associations); + uint8 GetMaxAssociations(uint8 const _nodeId, uint8 const _groupIdx); + bool IsMultiInstance(uint8 const _nodeId, uint8 const _groupIdx); + string GetGroupLabel(uint8 const _nodeId, uint8 const _groupIdx); + void AddAssociation(uint8 const _nodeId, uint8 const _groupIdx, uint8 const _targetNodeId, uint8 const _instance = 0x00); + void RemoveAssociation(uint8 const _nodeId, uint8 const _groupIdx, uint8 const _targetNodeId, uint8 const _instance = 0x00); + + //----------------------------------------------------------------------------- + // Notifications + //----------------------------------------------------------------------------- + private: + void QueueNotification(Notification* _notification); // Adds a notification to the list. Notifications are queued until a point in the thread where we know we do not have any nodes locked. + void NotifyWatchers(); // Passes the notifications to all the registered watcher callbacks in turn. + list m_notifications; + Internal::Platform::Event* m_notificationsEvent; + + //----------------------------------------------------------------------------- + // Statistics + //----------------------------------------------------------------------------- + public: + struct DriverData + { + uint32 m_SOFCnt; // Number of SOF bytes received + uint32 m_ACKWaiting; // Number of unsolicited messages while waiting for an ACK + uint32 m_readAborts; // Number of times read were aborted due to timeouts + uint32 m_badChecksum; // Number of bad checksums + uint32 m_readCnt; // Number of messages successfully read + uint32 m_writeCnt; // Number of messages successfully sent + uint32 m_CANCnt; // Number of CAN bytes received + uint32 m_NAKCnt; // Number of NAK bytes received + uint32 m_ACKCnt; // Number of ACK bytes received + uint32 m_OOFCnt; // Number of bytes out of framing + uint32 m_dropped; // Number of messages dropped & not delivered + uint32 m_retries; // Number of messages retransmitted + uint32 m_callbacks; // Number of unexpected callbacks + uint32 m_badroutes; // Number of failed messages due to bad route response + uint32 m_noack; // Number of no ACK returned errors + uint32 m_netbusy; // Number of network busy/failure messages + uint32 m_notidle; // Number of RF Network Busy messages + uint32 m_txverified; // Number of TX Verified messages + uint32 m_nondelivery; // Number of messages not delivered to network + uint32 m_routedbusy; // Number of messages received with routed busy status + uint32 m_broadcastReadCnt; // Number of broadcasts read + uint32 m_broadcastWriteCnt; // Number of broadcasts sent + }; + void LogDriverStatistics(); + + private: + void GetDriverStatistics(DriverData* _data); + void GetNodeStatistics(uint8 const _nodeId, Node::NodeData* _data); - MsgQueueCmd m_command; - Msg* m_msg; - uint8 m_nodeId; - Node::QueryStage m_queryStage; - bool m_retry; - ControllerCommandItem* m_cci; - }; - -OPENZWAVE_EXPORT_WARNINGS_OFF - list m_msgQueue[MsgQueue_Count]; -OPENZWAVE_EXPORT_WARNINGS_ON - Event* m_queueEvent[MsgQueue_Count]; // Events for each queue, which are signaled when the queue is not empty - Mutex* m_sendMutex; // Serialize access to the queues - Msg* m_currentMsg; - MsgQueue m_currentMsgQueueSource; // identifies which queue held m_currentMsg - TimeStamp m_resendTimeStamp; - - //----------------------------------------------------------------------------- - // Network functions - //----------------------------------------------------------------------------- - private: - void TestNetwork( uint8 const _nodeId, uint32 const _count ); - - //----------------------------------------------------------------------------- - // Virtual Node commands - //----------------------------------------------------------------------------- - public: - /** - * Virtual Node Commands. - * Commands to be used with virtual nodes. - */ - private: - uint32 GetVirtualNeighbors( uint8** o_neighbors ); - void RequestVirtualNeighbors( MsgQueue const _queue ); - bool IsVirtualNode( uint8 const _nodeId )const{ return (( m_virtualNeighbors[( _nodeId - 1 ) >> 3] & 1 << (( _nodeId - 1 ) & 0x07 )) != 0 ); } - void SendVirtualNodeInfo( uint8 const _fromNodeId, uint8 const _ToNodeId ); - void SendSlaveLearnModeOff(); - void SaveButtons(); - void ReadButtons( uint8 const _nodeId ); - - bool m_virtualNeighborsReceived; - uint8 m_virtualNeighbors[NUM_NODE_BITFIELD_BYTES]; // Bitmask containing virtual neighbors - - //----------------------------------------------------------------------------- - // SwitchAll - //----------------------------------------------------------------------------- - private: - // The public interface is provided via the wrappers in the Manager class - void SwitchAllOn(); - void SwitchAllOff(); - - //----------------------------------------------------------------------------- - // Configuration Parameters (wrappers for the Node methods) - //----------------------------------------------------------------------------- - private: - // The public interface is provided via the wrappers in the Manager class - bool SetConfigParam( uint8 const _nodeId, uint8 const _param, int32 _value, uint8 const _size ); - void RequestConfigParam( uint8 const _nodeId, uint8 const _param ); - - //----------------------------------------------------------------------------- - // Groups (wrappers for the Node methods) - //----------------------------------------------------------------------------- - private: - // The public interface is provided via the wrappers in the Manager class - uint8 GetNumGroups( uint8 const _nodeId ); - uint32 GetAssociations( uint8 const _nodeId, uint8 const _groupIdx, uint8** o_associations ); - uint32 GetAssociations( uint8 const _nodeId, uint8 const _groupIdx, InstanceAssociation** o_associations ); - uint8 GetMaxAssociations( uint8 const _nodeId, uint8 const _groupIdx ); - bool IsMultiInstance( uint8 const _nodeId, uint8 const _groupIdx ); - string GetGroupLabel( uint8 const _nodeId, uint8 const _groupIdx ); - void AddAssociation( uint8 const _nodeId, uint8 const _groupIdx, uint8 const _targetNodeId, uint8 const _instance = 0x00 ); - void RemoveAssociation( uint8 const _nodeId, uint8 const _groupIdx, uint8 const _targetNodeId, uint8 const _instance = 0x00 ); - - //----------------------------------------------------------------------------- - // Notifications - //----------------------------------------------------------------------------- - private: - void QueueNotification( Notification* _notification ); // Adds a notification to the list. Notifications are queued until a point in the thread where we know we do not have any nodes locked. - void NotifyWatchers(); // Passes the notifications to all the registered watcher callbacks in turn. - -OPENZWAVE_EXPORT_WARNINGS_OFF - list m_notifications; -OPENZWAVE_EXPORT_WARNINGS_ON - Event* m_notificationsEvent; - - //----------------------------------------------------------------------------- - // Statistics - //----------------------------------------------------------------------------- - public: - struct DriverData - { uint32 m_SOFCnt; // Number of SOF bytes received uint32 m_ACKWaiting; // Number of unsolicited messages while waiting for an ACK uint32 m_readAborts; // Number of times read were aborted due to timeouts @@ -816,141 +911,108 @@ OPENZWAVE_EXPORT_WARNINGS_ON uint32 m_ACKCnt; // Number of ACK bytes received uint32 m_OOFCnt; // Number of bytes out of framing uint32 m_dropped; // Number of messages dropped & not delivered - uint32 m_retries; // Number of messages retransmitted + uint32 m_retries; // Number of retransmitted messages uint32 m_callbacks; // Number of unexpected callbacks uint32 m_badroutes; // Number of failed messages due to bad route response uint32 m_noack; // Number of no ACK returned errors uint32 m_netbusy; // Number of network busy/failure messages - uint32 m_notidle; // Number of RF Network Busy messages + uint32 m_notidle; // Number of not idle messages uint32 m_txverified; // Number of TX Verified messages uint32 m_nondelivery; // Number of messages not delivered to network uint32 m_routedbusy; // Number of messages received with routed busy status uint32 m_broadcastReadCnt; // Number of broadcasts read uint32 m_broadcastWriteCnt; // Number of broadcasts sent - }; - void LogDriverStatistics(); - - private: - void GetDriverStatistics( DriverData* _data ); - void GetNodeStatistics( uint8 const _nodeId, Node::NodeData* _data ); - - uint32 m_SOFCnt; // Number of SOF bytes received - uint32 m_ACKWaiting; // Number of unsolicited messages while waiting for an ACK - uint32 m_readAborts; // Number of times read were aborted due to timeouts - uint32 m_badChecksum; // Number of bad checksums - uint32 m_readCnt; // Number of messages successfully read - uint32 m_writeCnt; // Number of messages successfully sent - uint32 m_CANCnt; // Number of CAN bytes received - uint32 m_NAKCnt; // Number of NAK bytes received - uint32 m_ACKCnt; // Number of ACK bytes received - uint32 m_OOFCnt; // Number of bytes out of framing - uint32 m_dropped; // Number of messages dropped & not delivered - uint32 m_retries; // Number of retransmitted messages - uint32 m_callbacks; // Number of unexpected callbacks - uint32 m_badroutes; // Number of failed messages due to bad route response - uint32 m_noack; // Number of no ACK returned errors - uint32 m_netbusy; // Number of network busy/failure messages - uint32 m_notidle; // Number of not idle messages - uint32 m_txverified; // Number of TX Verified messages - uint32 m_nondelivery; // Number of messages not delivered to network - uint32 m_routedbusy; // Number of messages received with routed busy status - uint32 m_broadcastReadCnt; // Number of broadcasts read - uint32 m_broadcastWriteCnt; // Number of broadcasts sent - //time_t m_commandStart; // Start time of last command - //time_t m_timeoutLost; // Cumulative time lost to timeouts - - - //----------------------------------------------------------------------------- - // Security Command Class Related (Version 1.1) - //----------------------------------------------------------------------------- - public: - aes_encrypt_ctx *GetAuthKey(); - aes_encrypt_ctx *GetEncKey(); - bool isNetworkKeySet(); - - private: - bool initNetworkKeys(bool newnode); - uint8 *GetNetworkKey(); - bool SendEncryptedMessage(); - bool SendNonceRequest(string logmsg); - void SendNonceKey(uint8 nodeId, uint8 *nonce); - aes_encrypt_ctx *AuthKey; - aes_encrypt_ctx *EncryptKey; - uint8 m_nonceReportSent; - uint8 m_nonceReportSentAttempt; - bool m_inclusionkeySet; - - //----------------------------------------------------------------------------- - // Event Signaling for DNS and HTTP Threads - //----------------------------------------------------------------------------- - private: - struct EventMsg { - enum EventType { - Event_DNS = 1, - Event_Http + //time_t m_commandStart; // Start time of last command + //time_t m_timeoutLost; // Cumulative time lost to timeouts + + //----------------------------------------------------------------------------- + // Security Command Class Related (Version 1.1) + //----------------------------------------------------------------------------- + public: + aes_encrypt_ctx *GetAuthKey(); + aes_encrypt_ctx *GetEncKey(); + bool isNetworkKeySet(); + + private: + bool initNetworkKeys(bool newnode); + uint8 *GetNetworkKey(); + bool SendEncryptedMessage(); + bool SendNonceRequest(string logmsg); + void SendNonceKey(uint8 nodeId, uint8 *nonce); + aes_encrypt_ctx *AuthKey; + aes_encrypt_ctx *EncryptKey; + uint8 m_nonceReportSent; + uint8 m_nonceReportSentAttempt; + bool m_inclusionkeySet; + + //----------------------------------------------------------------------------- + // Event Signaling for DNS and HTTP Threads + //----------------------------------------------------------------------------- + private: + struct EventMsg + { + enum EventType + { + Event_DNS = 1, + Event_Http + }; + EventType type; + union + { + Internal::DNSLookup *lookup; + Internal::HttpDownload *httpdownload; + } event; }; - EventType type; - union { - DNSLookup *lookup; - HttpDownload *httpdownload; - } event; - }; - - void SubmitEventMsg(EventMsg *); - void ProcessEventMsg(); - - - OPENZWAVE_EXPORT_WARNINGS_OFF - list m_eventQueueMsg; - OPENZWAVE_EXPORT_WARNINGS_ON - Event* m_queueMsgEvent; // Events for each queue, which are signalled when the queue is not empty - Mutex* m_eventMutex; // Serialize access to the queues - - - //----------------------------------------------------------------------------- - // DNS Related - //----------------------------------------------------------------------------- - - public: - bool CheckNodeConfigRevision(Node *); - bool CheckMFSConfigRevision(); - void ReloadNode(uint8 const _nodeId); - - private: - void processConfigRevision(DNSLookup *); - - //----------------------------------------------------------------------------- - // HTTP Client Related - //----------------------------------------------------------------------------- - - public: - bool setHttpClient(i_HttpClient *client); - private: - bool startConfigDownload(uint16 _manufacturerId, uint16 _productType, uint16 _productId, string configfile, uint8 node = 0); - bool startMFSDownload(string configfile); - bool refreshNodeConfig(uint8 node); - void processDownload(HttpDownload *); - i_HttpClient *m_httpClient; - - //----------------------------------------------------------------------------- - // Metadata Related - //----------------------------------------------------------------------------- - - public: - string const GetMetaData( uint8 const _nodeId, Node::MetaDataFields _metadata ); - Node::ChangeLogEntry const GetChangeLog( uint8 const _nodeId, uint32_t revision); - - - //----------------------------------------------------------------------------- - // ManufacturerSpecificDB Related - //----------------------------------------------------------------------------- - - public: - ManufacturerSpecificDB *GetManufacturerSpecificDB(); - bool downloadConfigRevision(Node *); - bool downloadMFSRevision(); - private: - ManufacturerSpecificDB *m_mfs; + + void SubmitEventMsg(EventMsg *); + void ProcessEventMsg(); + list m_eventQueueMsg; + Internal::Platform::Event* m_queueMsgEvent; // Events for each queue, which are signalled when the queue is not empty + Internal::Platform::Mutex* m_eventMutex; // Serialize access to the queues + + //----------------------------------------------------------------------------- + // DNS Related + //----------------------------------------------------------------------------- + + public: + bool CheckNodeConfigRevision(Node *); + bool CheckMFSConfigRevision(); + void ReloadNode(uint8 const _nodeId); + + private: + void processConfigRevision(Internal::DNSLookup *); + + //----------------------------------------------------------------------------- + // HTTP Client Related + //----------------------------------------------------------------------------- + + public: + bool setHttpClient(Internal::i_HttpClient *client); + private: + bool startConfigDownload(uint16 _manufacturerId, uint16 _productType, uint16 _productId, string configfile, uint8 node = 0); + bool startMFSDownload(string configfile); + bool refreshNodeConfig(uint8 node); + void processDownload(Internal::HttpDownload *); + Internal::i_HttpClient *m_httpClient; + + //----------------------------------------------------------------------------- + // Metadata Related + //----------------------------------------------------------------------------- + + public: + string const GetMetaData(uint8 const _nodeId, Node::MetaDataFields _metadata); + Node::ChangeLogEntry const GetChangeLog(uint8 const _nodeId, uint32_t revision); + + //----------------------------------------------------------------------------- + // ManufacturerSpecificDB Related + //----------------------------------------------------------------------------- + + public: + Internal::ManufacturerSpecificDB *GetManufacturerSpecificDB(); + bool downloadConfigRevision(Node *); + bool downloadMFSRevision(); + private: + Internal::ManufacturerSpecificDB *m_mfs; }; diff --git a/cpp/src/Group.cpp b/cpp/src/Group.cpp index efe26c1dfb..f78143b129 100644 --- a/cpp/src/Group.cpp +++ b/cpp/src/Group.cpp @@ -35,33 +35,22 @@ #include "command_classes/Association.h" #include "command_classes/AssociationCommandConfiguration.h" #include "command_classes/MultiChannelAssociation.h" +#include "command_classes/MultiInstance.h" #include "platform/Log.h" #include "tinyxml.h" using namespace OpenZWave; - //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -Group::Group -( - uint32 const _homeId, - uint8 const _nodeId, - uint8 const _groupIdx, - uint8 const _maxAssociations -): - m_homeId( _homeId ), - m_nodeId( _nodeId ), - m_groupIdx( _groupIdx ), - m_maxAssociations( _maxAssociations ), - m_auto( false ), - m_multiInstance( false ) +Group::Group(uint32 const _homeId, uint8 const _nodeId, uint8 const _groupIdx, uint8 const _maxAssociations) : + m_homeId(_homeId), m_nodeId(_nodeId), m_groupIdx(_groupIdx), m_maxAssociations(_maxAssociations), m_auto(false), m_multiInstance(false) { char str[16]; - snprintf( str, sizeof(str), "Group %d", m_groupIdx ); + snprintf(str, sizeof(str), "Group %d", m_groupIdx); m_label = str; CheckAuto(); @@ -71,74 +60,62 @@ Group::Group // // Constructor (from XML) //----------------------------------------------------------------------------- -Group::Group -( - uint32 const _homeId, - uint8 const _nodeId, - TiXmlElement const* _groupElement -): - m_homeId( _homeId ), - m_nodeId( _nodeId ), - m_groupIdx( 0 ), - m_maxAssociations( 0 ), - m_auto( false ), - m_multiInstance( false ) +Group::Group(uint32 const _homeId, uint8 const _nodeId, TiXmlElement const* _groupElement) : + m_homeId(_homeId), m_nodeId(_nodeId), m_groupIdx(0), m_maxAssociations(0), m_auto(false), m_multiInstance(false) { int intVal; char const* str; vector pending; - - - if( TIXML_SUCCESS == _groupElement->QueryIntAttribute( "index", &intVal ) ) + if (TIXML_SUCCESS == _groupElement->QueryIntAttribute("index", &intVal)) { - m_groupIdx = (uint8)intVal; + m_groupIdx = (uint8) intVal; } /* call this so the config can override if necessary */ CheckAuto(); - if( TIXML_SUCCESS == _groupElement->QueryIntAttribute( "max_associations", &intVal ) ) + if (TIXML_SUCCESS == _groupElement->QueryIntAttribute("max_associations", &intVal)) { - m_maxAssociations = (uint8)intVal; + m_maxAssociations = (uint8) intVal; } - str = _groupElement->Attribute( "auto" ); - if( str ) + str = _groupElement->Attribute("auto"); + if (str) { - m_auto = !strcmp( str, "true" ); + m_auto = !strcmp(str, "true"); } - str = _groupElement->Attribute( "label" ); - if( str ) + str = _groupElement->Attribute("label"); + if (str) { m_label = str; } - str = _groupElement->Attribute( "multiInstance" ); - if( str ) + str = _groupElement->Attribute("multiInstance"); + if (str) { - m_multiInstance = !strcmp( str, "true" ); + m_multiInstance = !strcmp(str, "true"); } - + // Read the associations for this group TiXmlElement const* associationElement = _groupElement->FirstChildElement(); - while( associationElement ) + while (associationElement) { char const* elementName = associationElement->Value(); - if( elementName && !strcmp( elementName, "Node" ) ) + if (elementName && !strcmp(elementName, "Node")) { - - if( associationElement->QueryIntAttribute( "id", &intVal ) == TIXML_SUCCESS ) + + if (associationElement->QueryIntAttribute("id", &intVal) == TIXML_SUCCESS) { InstanceAssociation association; - association.m_nodeId = (uint8)intVal; - if( associationElement->QueryIntAttribute( "instance", &intVal ) == TIXML_SUCCESS ) - association.m_instance = (uint8)intVal; + association.m_nodeId = (uint8) intVal; + if (associationElement->QueryIntAttribute("instance", &intVal) == TIXML_SUCCESS) + association.m_instance = (uint8) intVal; else association.m_instance = 0x00; - pending.push_back( association ); + pending.push_back(association); } } @@ -149,15 +126,14 @@ Group::Group // Since we do not want to update return routes UpdateNodeRoutes won't find the group // so nothing will go out from here. The not sending of return routes information // only works by a side effect of not finding the group. - OnGroupChanged( pending ); + OnGroupChanged(pending); } //----------------------------------------------------------------------------- // // Check if we should AutoAssociate for this group //----------------------------------------------------------------------------- -void Group::CheckAuto -( +void Group::CheckAuto( ) { @@ -165,67 +141,62 @@ void Group::CheckAuto // Group 255 is always created first, so if this is group 1, we need to turn off the // auto flag in group 255. All this messing about is to support the various behaviours // of certain Cooper devices. - if( m_groupIdx == 255 ) + if (m_groupIdx == 255) { m_auto = true; } - else if( m_groupIdx == 1 ) + else if (m_groupIdx == 1) { m_auto = true; // Clear the flag from Group 255, if it exists. - if( Driver* driver = Manager::Get()->GetDriver( m_homeId ) ) + if (Driver* driver = Manager::Get()->GetDriver(m_homeId)) { - if( Node* node = driver->GetNodeUnsafe( m_nodeId ) ) + if (Node* node = driver->GetNodeUnsafe(m_nodeId)) { - if( Group* group = node->GetGroup( 255 ) ) + if (Group* group = node->GetGroup(255)) { - group->SetAuto( false ); + group->SetAuto(false); } } } } } - - //----------------------------------------------------------------------------- // // Write ourselves to an XML document //----------------------------------------------------------------------------- -void Group::WriteXML -( - TiXmlElement* _groupElement -) +void Group::WriteXML(TiXmlElement* _groupElement) { char str[16]; - snprintf( str, 16, "%d", m_groupIdx ); - _groupElement->SetAttribute( "index", str ); + snprintf(str, 16, "%d", m_groupIdx); + _groupElement->SetAttribute("index", str); - snprintf( str, 16, "%d", m_maxAssociations ); - _groupElement->SetAttribute( "max_associations", str ); + snprintf(str, 16, "%d", m_maxAssociations); + _groupElement->SetAttribute("max_associations", str); - _groupElement->SetAttribute( "label", m_label.c_str() ); - _groupElement->SetAttribute( "auto", m_auto ? "true" : "false" ); - if( m_multiInstance ) + _groupElement->SetAttribute("label", m_label.c_str()); + _groupElement->SetAttribute("auto", m_auto ? "true" : "false"); + if (m_multiInstance) { - _groupElement->SetAttribute( "multiInstance", m_multiInstance ? "true" : "false" ); + _groupElement->SetAttribute("multiInstance", m_multiInstance ? "true" : "false"); } - - for( map::iterator it = m_associations.begin(); it != m_associations.end(); ++it ) + + for (map::iterator it = m_associations.begin(); it != m_associations.end(); ++it) { - TiXmlElement* associationElement = new TiXmlElement( "Node" ); - - snprintf( str, 16, "%d", it->first.m_nodeId ); - associationElement->SetAttribute( "id", str ); + TiXmlElement* associationElement = new TiXmlElement("Node"); + + snprintf(str, 16, "%d", it->first.m_nodeId); + associationElement->SetAttribute("id", str); if (it->first.m_instance != 0) { - snprintf( str, 16, "%d", it->first.m_instance ); - associationElement->SetAttribute( "instance", str ); + snprintf(str, 16, "%d", it->first.m_instance); + associationElement->SetAttribute("instance", str); } - _groupElement->LinkEndChild( associationElement ); + _groupElement->LinkEndChild(associationElement); } } @@ -233,15 +204,11 @@ void Group::WriteXML // // Whether a group contains a particular node //----------------------------------------------------------------------------- -bool Group::Contains -( - uint8 const _nodeId, - uint8 const _instance -) +bool Group::Contains(uint8 const _nodeId, uint8 const _endPoint) { - for( map::iterator it = m_associations.begin(); it != m_associations.end(); ++it ) + for (map::iterator it = m_associations.begin(); it != m_associations.end(); ++it) { - if ((it->first.m_nodeId == _nodeId) && (it->first.m_instance == _instance)) + if ((it->first.m_nodeId == _nodeId) && (it->first.m_instance == _endPoint)) { return true; } @@ -253,31 +220,33 @@ bool Group::Contains // // Associate a node with this group //----------------------------------------------------------------------------- -void Group::AddAssociation -( - uint8 const _nodeId, - uint8 const _instance -) +void Group::AddAssociation(uint8 const _nodeId, uint8 const _endPoint) { - if( Driver* driver = Manager::Get()->GetDriver( m_homeId ) ) + if (Driver* driver = Manager::Get()->GetDriver(m_homeId)) { - if( Node* node = driver->GetNodeUnsafe( m_nodeId ) ) + if (Node* node = driver->GetNodeUnsafe(m_nodeId)) { - MultiChannelAssociation* cc = static_cast( node->GetCommandClass( MultiChannelAssociation::StaticGetCommandClassId() )); - if( cc && IsMultiInstance() ) + Internal::CC::MultiChannelAssociation* cc = static_cast(node->GetCommandClass(Internal::CC::MultiChannelAssociation::StaticGetCommandClassId())); + Internal::CC::MultiInstance *mc = static_cast(node->GetCommandClass(Internal::CC::MultiInstance::StaticGetCommandClassId())); + if (cc && IsMultiInstance()) { - cc->Set( m_groupIdx, _nodeId, _instance ); - cc->QueryGroup( m_groupIdx, 0 ); + if (mc) { + cc->Set(m_groupIdx, _nodeId, _endPoint); + cc->QueryGroup(m_groupIdx, 0); + return; + } else { + Log::Write(LogLevel_Warning, m_nodeId, "MultiChannelAssociation is Present, but MultiChannel CC is not. Trying Plain Association..."); + } } - else if( Association* cc = static_cast( node->GetCommandClass( Association::StaticGetCommandClassId() ) ) ) + if (Internal::CC::Association* cc = static_cast(node->GetCommandClass(Internal::CC::Association::StaticGetCommandClassId()))) { - cc->Set( m_groupIdx, _nodeId ); - cc->QueryGroup( m_groupIdx, 0 ); + cc->Set(m_groupIdx, _nodeId); + cc->QueryGroup(m_groupIdx, 0); } else { - Log::Write( LogLevel_Info, m_nodeId, "No supported Association CC found" ); - } + Log::Write(LogLevel_Info, m_nodeId, "No supported Association CC found"); + } } } } @@ -286,31 +255,27 @@ void Group::AddAssociation // // Remove a node from this group //----------------------------------------------------------------------------- -void Group::RemoveAssociation -( - uint8 const _nodeId, - uint8 const _instance -) +void Group::RemoveAssociation(uint8 const _nodeId, uint8 const _endPoint) { - if( Driver* driver = Manager::Get()->GetDriver( m_homeId ) ) + if (Driver* driver = Manager::Get()->GetDriver(m_homeId)) { - if( Node* node = driver->GetNodeUnsafe( m_nodeId ) ) + if (Node* node = driver->GetNodeUnsafe(m_nodeId)) { - MultiChannelAssociation* cc = static_cast( node->GetCommandClass( MultiChannelAssociation::StaticGetCommandClassId() )); - if( cc && IsMultiInstance() ) + Internal::CC::MultiChannelAssociation* cc = static_cast(node->GetCommandClass(Internal::CC::MultiChannelAssociation::StaticGetCommandClassId())); + if (cc && IsMultiInstance()) { - cc->Remove( m_groupIdx, _nodeId, _instance ); - cc->QueryGroup( m_groupIdx, 0 ); - } - else if( Association* cc = static_cast( node->GetCommandClass( Association::StaticGetCommandClassId() ) ) ) + cc->Remove(m_groupIdx, _nodeId, _endPoint); + cc->QueryGroup(m_groupIdx, 0); + } + else if (Internal::CC::Association* cc = static_cast(node->GetCommandClass(Internal::CC::Association::StaticGetCommandClassId()))) { - cc->Remove( m_groupIdx, _nodeId ); - cc->QueryGroup( m_groupIdx, 0 ); + cc->Remove(m_groupIdx, _nodeId); + cc->QueryGroup(m_groupIdx, 0); } else { - Log::Write( LogLevel_Info, m_nodeId, "No supported Association CC found" ); - } + Log::Write(LogLevel_Info, m_nodeId, "No supported Association CC found"); + } } } } @@ -319,19 +284,16 @@ void Group::RemoveAssociation // // Change the group contents and notify the watchers //----------------------------------------------------------------------------- -void Group::OnGroupChanged -( - vector const& _associations -) +void Group::OnGroupChanged(vector const& _associations) { vector instanceAssociations; uint8 i; - for( i=0; i<_associations.size(); ++i ) + for (i = 0; i < _associations.size(); ++i) { InstanceAssociation association; - association.m_nodeId = _associations[i]; - association.m_instance = 0x00; - instanceAssociations.push_back( association ); + association.m_nodeId = _associations[i]; + association.m_instance = 0x00; + instanceAssociations.push_back(association); } OnGroupChanged(instanceAssociations); instanceAssociations.clear(); @@ -341,16 +303,13 @@ void Group::OnGroupChanged // // Change the group contents and notify the watchers //----------------------------------------------------------------------------- -void Group::OnGroupChanged -( - vector const& _associations -) +void Group::OnGroupChanged(vector const& _associations) { bool notify = false; // If the number of associations is different, we'll save // ourselves some work and clear the old set now. - if( _associations.size() != m_associations.size() ) + if (_associations.size() != m_associations.size()) { m_associations.clear(); notify = true; @@ -358,65 +317,65 @@ void Group::OnGroupChanged else { // Handle initial group creation case - if ( _associations.size() == 0 && m_associations.size() == 0 ) + if (_associations.size() == 0 && m_associations.size() == 0) { notify = true; } } // Add the new associations. - uint8 oldSize = (uint8)m_associations.size(); + uint8 oldSize = (uint8) m_associations.size(); uint8 i; - for( i=0; i<_associations.size(); ++i ) + for (i = 0; i < _associations.size(); ++i) { m_associations[_associations[i]] = AssociationCommandVec(); } - if( (!notify) && ( oldSize != m_associations.size() ) ) + if ((!notify) && (oldSize != m_associations.size())) { // The number of nodes in the original and new groups is the same, but // the number of associations has grown. There must be different nodes // in the original and new sets of nodes in the group. The easiest way // to sort this out is to clear the associations and add the new nodes again. m_associations.clear(); - for( i=0; i<_associations.size(); ++i ) + for (i = 0; i < _associations.size(); ++i) { m_associations[_associations[i]] = AssociationCommandVec(); } notify = true; } - if( notify ) + if (notify) { // If the node supports COMMAND_CLASS_ASSOCIATION_COMMAND_CONFIGURATION, we need to request the command data. - if( Driver* driver = Manager::Get()->GetDriver( m_homeId ) ) + if (Driver* driver = Manager::Get()->GetDriver(m_homeId)) { - if( Node* node = driver->GetNodeUnsafe( m_nodeId ) ) + if (Node* node = driver->GetNodeUnsafe(m_nodeId)) { - if( AssociationCommandConfiguration* cc = static_cast( node->GetCommandClass( AssociationCommandConfiguration::StaticGetCommandClassId() ) ) ) + if (Internal::CC::AssociationCommandConfiguration* cc = static_cast(node->GetCommandClass(Internal::CC::AssociationCommandConfiguration::StaticGetCommandClassId()))) { - for( map::iterator it = m_associations.begin(); it != m_associations.end(); ++it ) + for (map::iterator it = m_associations.begin(); it != m_associations.end(); ++it) { - cc->RequestCommands( m_groupIdx, it->first.m_nodeId ); + cc->RequestCommands(m_groupIdx, it->first.m_nodeId); } } } } // Send notification that the group contents have changed - Notification* notification = new Notification( Notification::Type_Group ); - notification->SetHomeAndNodeIds( m_homeId, m_nodeId ); - notification->SetGroupIdx( m_groupIdx ); - Manager::Get()->GetDriver( m_homeId )->QueueNotification( notification ); + Notification* notification = new Notification(Notification::Type_Group); + notification->SetHomeAndNodeIds(m_homeId, m_nodeId); + notification->SetGroupIdx(m_groupIdx); + Manager::Get()->GetDriver(m_homeId)->QueueNotification(notification); // Update routes on remote node if necessary bool update = false; - Options::Get()->GetOptionAsBool( "PerformReturnRoutes", &update ); - if( update ) + Options::Get()->GetOptionAsBool("PerformReturnRoutes", &update); + if (update) { - Driver *drv = Manager::Get()->GetDriver( m_homeId ); + Driver *drv = Manager::Get()->GetDriver(m_homeId); if (drv) - drv->UpdateNodeRoutes( m_nodeId ); + drv->UpdateNodeRoutes(m_nodeId); } } } @@ -425,13 +384,10 @@ void Group::OnGroupChanged // // Get a list of associations for this group //----------------------------------------------------------------------------- -uint32 Group::GetAssociations -( - uint8** o_associations -) +uint32 Group::GetAssociations(uint8** o_associations) { size_t numNodes = m_associations.size(); - if( !numNodes ) + if (!numNodes) { *o_associations = NULL; return 0; @@ -439,9 +395,9 @@ uint32 Group::GetAssociations uint8* associations = new uint8[numNodes]; // room for all associations, we only need room for the associations without instance uint32 i = 0; - for( map::iterator it = m_associations.begin(); it != m_associations.end(); ++it ) + for (map::iterator it = m_associations.begin(); it != m_associations.end(); ++it) { - if ( it->first.m_instance == 0x00) + if (it->first.m_instance == 0x00) { associations[i++] = it->first.m_nodeId; } @@ -455,13 +411,10 @@ uint32 Group::GetAssociations // // Get a list of associations for this group //----------------------------------------------------------------------------- -uint32 Group::GetAssociations -( - InstanceAssociation** o_associations -) +uint32 Group::GetAssociations(InstanceAssociation** o_associations) { size_t numNodes = m_associations.size(); - if( !numNodes ) + if (!numNodes) { *o_associations = NULL; return 0; @@ -469,7 +422,7 @@ uint32 Group::GetAssociations InstanceAssociation* associations = new InstanceAssociation[numNodes]; uint32 i = 0; - for( map::iterator it = m_associations.begin(); it != m_associations.end(); ++it ) + for (map::iterator it = m_associations.begin(); it != m_associations.end(); ++it) { associations[i++] = it->first; } @@ -486,20 +439,16 @@ uint32 Group::GetAssociations // // Clear all the commands for the specified node //----------------------------------------------------------------------------- -bool Group::ClearCommands -( - uint8 const _nodeId, - uint8 const _instance -) -{ - for( map::iterator it = m_associations.begin(); it != m_associations.end(); ++it ) +bool Group::ClearCommands(uint8 const _nodeId, uint8 const _endPoint) +{ + for (map::iterator it = m_associations.begin(); it != m_associations.end(); ++it) { - if( (it->first.m_nodeId == _nodeId) && (it->first.m_instance == _instance) ) + if ((it->first.m_nodeId == _nodeId) && (it->first.m_instance == _endPoint)) { it->second.clear(); return true; } - } + } return false; } @@ -508,23 +457,17 @@ bool Group::ClearCommands // // Add a command to the list for the specified node //----------------------------------------------------------------------------- -bool Group::AddCommand -( - uint8 const _nodeId, - uint8 const _length, - uint8 const* _data, - uint8 const _instance -) +bool Group::AddCommand(uint8 const _nodeId, uint8 const _length, uint8 const* _data, uint8 const _endPoint) { - for( map::iterator it = m_associations.begin(); it != m_associations.end(); ++it ) + for (map::iterator it = m_associations.begin(); it != m_associations.end(); ++it) { - if( (it->first.m_nodeId == _nodeId) && (it->first.m_instance == _instance) ) + if ((it->first.m_nodeId == _nodeId) && (it->first.m_instance == _endPoint)) { - it->second.push_back( AssociationCommand( _length, _data ) ); + it->second.push_back(AssociationCommand(_length, _data)); return true; } } - + return false; } @@ -532,25 +475,18 @@ bool Group::AddCommand // // Constructor //----------------------------------------------------------------------------- -Group::AssociationCommand::AssociationCommand -( - uint8 const _length, - uint8 const* _data -) +Group::AssociationCommand::AssociationCommand(uint8 const _length, uint8 const* _data) { m_data = new uint8[_length]; - memcpy( m_data, _data, _length ); + memcpy(m_data, _data, _length); } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -Group::AssociationCommand::~AssociationCommand -( -) +Group::AssociationCommand::~AssociationCommand() { - delete [] m_data; + delete[] m_data; } - diff --git a/cpp/src/Group.h b/cpp/src/Group.h index a862f1c8a9..bf24a3b652 100644 --- a/cpp/src/Group.h +++ b/cpp/src/Group.h @@ -37,91 +37,139 @@ class TiXmlElement; namespace OpenZWave { + namespace Internal + { + namespace CC + { + class Association; + class MultiChannelAssociation; + } + } + class Node; - typedef struct InstanceAssociation { - uint8 m_nodeId; - uint8 m_instance; + // When dealing with MultiInstance Devices, + // OpenZWave uses "Instance" to identify a subdevice. + // The public interface maps an Instance ID to an "End Point", which in turn + // gets used to build Z-Wave packets. + // Config files and by extension ozwcache store this map per CC, for example: + // + // The Group Aka Association commands, however, expect "End Points" + // It would make sense to change "Instance" to "End Point" in all related code but... + // InstanceAssociation is exposed by the API in Manager::GetAssociations + // Because of its exposure, m_instance cannot be renamed to m_endPoint without + // breaking existing code. + + typedef struct InstanceAssociation + { + uint8 m_nodeId; + uint8 m_instance; // "End Point" as defined in SDS13782-11B, Multi Channel Association Command Class. } InstanceAssociation; - + /** \brief Manages a group of devices (various nodes associated with each other). */ class Group { - friend class Node; - friend class Association; - friend class MultiChannelAssociation; - - //----------------------------------------------------------------------------- - // Construction - //----------------------------------------------------------------------------- - public: - Group( uint32 const _homeId, uint8 const _nodeId, uint8 const _groupIdx, uint8 const _maxAssociations ); - Group( uint32 const _homeId, uint8 const _nodeId, TiXmlElement const* _valueElement ); - ~Group(){} - - void WriteXML( TiXmlElement* _groupElement ); - - //----------------------------------------------------------------------------- - // Association methods (COMMAND_CLASS_ASSOCIATION) - //----------------------------------------------------------------------------- - public: - string const& GetLabel()const{ return m_label; } - uint32 GetAssociations( uint8** o_associations ); - uint32 GetAssociations( InstanceAssociation** o_associations ); - uint8 GetMaxAssociations()const{ return m_maxAssociations; } - uint8 GetIdx()const{ return m_groupIdx; } - bool Contains( uint8 const _nodeId, uint8 const _instance = 0x00 ); - bool IsMultiInstance()const{ return m_multiInstance; } - - private: - bool IsAuto()const{ return m_auto; } - void SetAuto( bool const _state ){ m_auto = _state; } - void CheckAuto(); - - void SetMultiInstance( bool const _state ){ m_multiInstance = _state; } - - void AddAssociation( uint8 const _nodeId, uint8 const _instance = 0x00 ); - void RemoveAssociation( uint8 const _nodeId, uint8 const _instance = 0x00 ); - void OnGroupChanged( vector const& _associations ); - void OnGroupChanged( vector const& _associations ); - - //----------------------------------------------------------------------------- - // Command methods (COMMAND_CLASS_ASSOCIATION_COMMAND_CONFIGURATION) - //----------------------------------------------------------------------------- - public: - bool ClearCommands( uint8 const _nodeId, uint8 const _instance = 0x00 ); - bool AddCommand( uint8 const _nodeId, uint8 const _length, uint8 const* _data, uint8 const _instance = 0x00 ); - - private: - class AssociationCommand - { + friend class Node; + friend class Internal::CC::Association; + friend class Internal::CC::MultiChannelAssociation; + + //----------------------------------------------------------------------------- + // Construction + //----------------------------------------------------------------------------- public: - AssociationCommand( uint8 const _length, uint8 const* _data ); - ~AssociationCommand(); + Group(uint32 const _homeId, uint8 const _nodeId, uint8 const _groupIdx, uint8 const _maxAssociations); + Group(uint32 const _homeId, uint8 const _nodeId, TiXmlElement const* _valueElement); + ~Group() + { + } + void WriteXML(TiXmlElement* _groupElement); + + //----------------------------------------------------------------------------- + // Association methods (COMMAND_CLASS_ASSOCIATION) + //----------------------------------------------------------------------------- + public: + string const& GetLabel() const + { + return m_label; + } + uint32 GetAssociations(uint8** o_associations); + uint32 GetAssociations(InstanceAssociation** o_associations); + uint8 GetMaxAssociations() const + { + return m_maxAssociations; + } + uint8 GetIdx() const + { + return m_groupIdx; + } + bool Contains(uint8 const _nodeId, uint8 const _endPoint= 0x00); + bool IsMultiInstance() const + { + return m_multiInstance; + } + + private: + bool IsAuto() const + { + return m_auto; + } + void SetAuto(bool const _state) + { + m_auto = _state; + } + void CheckAuto(); + + void SetMultiInstance(bool const _state) + { + m_multiInstance = _state; + } + + void AddAssociation(uint8 const _nodeId, uint8 const endPoint = 0x00); + void RemoveAssociation(uint8 const _nodeId, uint8 const _endPoint = 0x00); + void OnGroupChanged(vector const& _associations); + void OnGroupChanged(vector const& _associations); + + //----------------------------------------------------------------------------- + // Command methods (COMMAND_CLASS_ASSOCIATION_COMMAND_CONFIGURATION) + //----------------------------------------------------------------------------- + public: + bool ClearCommands(uint8 const _nodeId, uint8 const _endPoint = 0x00); + bool AddCommand(uint8 const _nodeId, uint8 const _length, uint8 const* _data, uint8 const _endPoint = 0x00); + + private: + class AssociationCommand + { + public: + AssociationCommand(uint8 const _length, uint8 const* _data); + ~AssociationCommand(); + + private: + uint8* m_data; + }; + + typedef vector AssociationCommandVec; + struct classcomp + { + bool operator()(const InstanceAssociation& lhs, const InstanceAssociation& rhs) const + { + return lhs.m_nodeId == rhs.m_nodeId ? lhs.m_instance < rhs.m_instance : lhs.m_nodeId < rhs.m_nodeId; + } + }; + + //----------------------------------------------------------------------------- + // Member variables + //----------------------------------------------------------------------------- private: - uint8* m_data; - }; - - typedef vector AssociationCommandVec; - struct classcomp { - bool operator() (const InstanceAssociation& lhs, const InstanceAssociation& rhs) const - {return lhs.m_nodeId == rhs.m_nodeId ? lhs.m_instance < rhs.m_instance : lhs.m_nodeId < rhs.m_nodeId;} - }; - - //----------------------------------------------------------------------------- - // Member variables - //----------------------------------------------------------------------------- - private: - string m_label; - uint32 m_homeId; - uint8 m_nodeId; - uint8 m_groupIdx; - uint8 m_maxAssociations; - bool m_auto; // If true, the controller will automatically be associated with the group - bool m_multiInstance; // If true, the group is MultiInstance capable - map m_associations; + string m_label; + uint32 m_homeId; + uint8 m_nodeId; + uint8 m_groupIdx; + uint8 m_maxAssociations; + bool m_auto; // If true, the controller will automatically be associated with the group + bool m_multiInstance; // If true, the group is MultiInstance capable + map m_associations; }; } //namespace OpenZWave diff --git a/cpp/src/Http.cpp b/cpp/src/Http.cpp index 51c6cd8bd5..b2c2e37532 100644 --- a/cpp/src/Http.cpp +++ b/cpp/src/Http.cpp @@ -37,167 +37,162 @@ #include "platform/FileOps.h" #include "Utils.h" -using namespace OpenZWave; - -i_HttpClient::i_HttpClient -( - Driver *driver -): -m_driver(driver) -{ -}; - -void i_HttpClient::FinishDownload(HttpDownload *transfer) { - /* send the response back to the Driver for processing */ - Driver::EventMsg *event = new Driver::EventMsg(); - event->type = Driver::EventMsg::Event_Http; - event->event.httpdownload = transfer; - this->m_driver->SubmitEventMsg(event); -} - - - -HttpClient::HttpClient -( - OpenZWave::Driver *drv -): -i_HttpClient(drv), -m_exitEvent( new Event() ), -m_httpThread ( new Thread( "HttpThread" ) ), -m_httpThreadRunning(false), -m_httpMutex ( new Mutex() ), -m_httpDownloadEvent ( new Event() ) +namespace OpenZWave { -} + namespace Internal + { -HttpClient::~HttpClient -( -) -{ - m_exitEvent->Set(); -} + i_HttpClient::i_HttpClient(Driver *driver) : + m_driver(driver) + { + } + ; + + void i_HttpClient::FinishDownload(HttpDownload *transfer) + { + /* send the response back to the Driver for processing */ + Driver::EventMsg *event = new Driver::EventMsg(); + event->type = Driver::EventMsg::Event_Http; + event->event.httpdownload = transfer; + this->m_driver->SubmitEventMsg(event); + } + HttpClient::HttpClient(OpenZWave::Driver *drv) : + i_HttpClient(drv), m_exitEvent(new Internal::Platform::Event()), m_httpThread(new Internal::Platform::Thread("HttpThread")), m_httpThreadRunning(false), m_httpMutex(new Internal::Platform::Mutex()), m_httpDownloadEvent(new Internal::Platform::Event()) + { + } + HttpClient::~HttpClient() + { + m_exitEvent->Set(); + m_exitEvent->Release(); + m_httpThread->Stop(); + m_httpThread->Release(); + m_httpDownloadEvent->Release(); + m_httpMutex->Release(); + } -bool HttpClient::StartDownload -( - HttpDownload *transfer -) -{ + bool HttpClient::StartDownload(HttpDownload *transfer) + { - if (!m_httpThreadRunning) - m_httpThread->Start(HttpClient::HttpThreadProc, this); - - LockGuard LG(m_httpMutex); - switch (transfer->operation) { - case HttpDownload::None: - Log::Write(LogLevel_Warning, "Got a Transfer Type of NONE for %s", transfer->url.c_str()); - delete transfer; - return false; - case HttpDownload::File: - case HttpDownload::Config: - case HttpDownload::MFSConfig: - /* make sure it has everything */ - if ((transfer->url.size() <= 0) || (transfer->filename.size() <= 0)) { - Log::Write(LogLevel_Warning, "File Transfer had incomplete Params"); - delete transfer; - return false; - } + if (!m_httpThreadRunning) + m_httpThread->Start(HttpClient::HttpThreadProc, this); - /* make sure the Folder Exists */ - if (!FileOps::Create()->FolderExists(ozwdirname(transfer->filename))) { - if (!FileOps::Create()->FolderCreate(ozwdirname(transfer->filename))) { - Log::Write(LogLevel_Warning, "File Transfer Failed. Could not create Destination Folder: %s", ozwdirname(transfer->filename).c_str()); + LockGuard LG(m_httpMutex); + switch (transfer->operation) + { + case HttpDownload::None: + Log::Write(LogLevel_Warning, "Got a Transfer Type of NONE for %s", transfer->url.c_str()); delete transfer; return false; - } + case HttpDownload::File: + case HttpDownload::Config: + case HttpDownload::MFSConfig: + /* make sure it has everything */ + if ((transfer->url.size() <= 0) || (transfer->filename.size() <= 0)) + { + Log::Write(LogLevel_Warning, "File Transfer had incomplete Params"); + delete transfer; + return false; + } + + /* make sure the Folder Exists */ + if (!Internal::Platform::FileOps::Create()->FolderExists(ozwdirname(transfer->filename))) + { + if (!Internal::Platform::FileOps::Create()->FolderCreate(ozwdirname(transfer->filename))) + { + Log::Write(LogLevel_Warning, "File Transfer Failed. Could not create Destination Folder: %s", ozwdirname(transfer->filename).c_str()); + delete transfer; + return false; + } + } + + /* does the file exist, if so, rotate it out (by doing a copy) */ + if (Internal::Platform::FileOps::Create()->FileExists(transfer->filename)) + { + if (!Internal::Platform::FileOps::Create()->FileRotate(transfer->filename)) + { + Log::Write(LogLevel_Warning, "File Transfer Failed. Could not Rotate Existing File: %s", transfer->filename.c_str()); + delete transfer; + return false; + } + } + + /* make sure the target file is writeable */ + if (!Internal::Platform::FileOps::Create()->FileWriteable(transfer->filename)) + { + Log::Write(LogLevel_Warning, "File %s is not writable", transfer->filename.c_str()); + delete transfer; + return false; + } + break; } - /* does the file exist, if so, rotate it out (by doing a copy) */ - if (FileOps::Create()->FileExists(transfer->filename)) { - if (!FileOps::Create()->FileRotate(transfer->filename)) { - Log::Write(LogLevel_Warning, "File Transfer Failed. Could not Rotate Existing File: %s", transfer->filename.c_str()); - delete transfer; - return false; - } - } + m_httpDownlist.push_back(transfer); + m_httpDownloadEvent->Set(); + return true; + } + void HttpClient::HttpThreadProc(Internal::Platform::Event* _exitEvent, void* _context) + { + HttpClient *client = (HttpClient *) _context; + client->m_httpThreadRunning = true; + Internal::Platform::InitNetwork(); + bool keepgoing = true; + while (keepgoing) + { + const uint32 count = 2; - /* make sure the target file is writeable */ - if (!FileOps::Create()->FileWriteable(transfer->filename)) { - Log::Write(LogLevel_Warning, "File %s is not writable", transfer->filename.c_str()); - delete transfer; - return false; - } - break; - } - - m_httpDownlist.push_back(transfer); - m_httpDownloadEvent->Set(); - return true; -} -void HttpClient::HttpThreadProc -( - Event* _exitEvent, - void* _context -) -{ - HttpClient *client = (HttpClient *)_context; - client->m_httpThreadRunning = true; + Internal::Platform::Wait* waitObjects[count]; - SimpleHTTPClient::InitNetwork(); - bool keepgoing = true; - while( keepgoing ) - { - const uint32 count = 2; - - Wait* waitObjects[count]; - - int32 timeout = Wait::Timeout_Infinite; - timeout = 10000; - - waitObjects[0] = client->m_exitEvent; // Thread must exit. - waitObjects[1] = client->m_httpDownloadEvent; // Http Request - // Wait for something to do - - int32 res = Wait::Multiple( waitObjects, count, timeout ); - - switch (res) { - case -1: /* timeout */ - Log::Write(LogLevel_Info, "HttpThread Exiting. No Transfers in timeout period"); - keepgoing = false; - break; - case 0: /* exitEvent */ - Log::Write(LogLevel_Info, "HttpThread Exiting."); - keepgoing = false; - break; - case 1: /* HttpEvent */ - HttpDownload *download; + int32 timeout = Internal::Platform::Wait::Timeout_Infinite; + timeout = 10000; + + waitObjects[0] = client->m_exitEvent; // Thread must exit. + waitObjects[1] = client->m_httpDownloadEvent; // Http Request + // Wait for something to do + + int32 res = Internal::Platform::Wait::Multiple(waitObjects, count, timeout); + + switch (res) { - LockGuard LG(client->m_httpMutex); - download = client->m_httpDownlist.front(); - client->m_httpDownlist.pop_front(); - if (client->m_httpDownlist.empty()) - client->m_httpDownloadEvent->Reset(); + case -1: /* timeout */ + Log::Write(LogLevel_Info, "HttpThread Exiting. No Transfers in timeout period"); + keepgoing = false; + break; + case 0: /* exitEvent */ + Log::Write(LogLevel_Info, "HttpThread Exiting."); + keepgoing = false; + break; + case 1: /* HttpEvent */ + HttpDownload *download; + { + LockGuard LG(client->m_httpMutex); + download = client->m_httpDownlist.front(); + client->m_httpDownlist.pop_front(); + if (client->m_httpDownlist.empty()) + client->m_httpDownloadEvent->Reset(); + } + Log::Write(LogLevel_Debug, "Download Starting for %s (%s)", download->url.c_str(), download->filename.c_str()); + Internal::Platform::HttpSocket *ht = new Internal::Platform::HttpSocket(); + ht->SetKeepAlive(0); + ht->SetBufsizeIn(64 * 1024); + ht->SetDownloadFile(download->filename); + ht->Download(download->url); + while (ht->isOpen()) + ht->update(); + + if (ht->IsSuccess()) + download->transferStatus = HttpDownload::Ok; + else + download->transferStatus = HttpDownload::Failed; + delete ht; + client->FinishDownload(download); + break; } - Log::Write(LogLevel_Debug, "Download Starting for %s (%s)", download->url.c_str(), download->filename.c_str()); - SimpleHTTPClient::HttpSocket *ht = new SimpleHTTPClient::HttpSocket(); - ht->SetKeepAlive(0); - ht->SetBufsizeIn(64 * 1024); - ht->SetDownloadFile(download->filename); - ht->Download(download->url); - while (ht->isOpen()) - ht->update(); - - if (ht->IsSuccess()) - download->transferStatus = HttpDownload::Ok; - else - download->transferStatus = HttpDownload::Failed; - delete ht; - client->FinishDownload(download); - break; + } + Internal::Platform::StopNetwork(); + client->m_httpThreadRunning = false; } - } - SimpleHTTPClient::StopNetwork(); - client->m_httpThreadRunning = false; -} + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/Http.h b/cpp/src/Http.h index 4a634cc4ba..6f3128e7b7 100644 --- a/cpp/src/Http.h +++ b/cpp/src/Http.h @@ -35,79 +35,79 @@ namespace OpenZWave { - - /* This is a abstract class you can implement if you wish to override the built in HTTP Client - * Code in OZW with your own code. - * - * The built in Code uses threads to download updated files to a temporary file - * and then this class moves the files into the correct place. - * - */ - - struct HttpDownload { - string filename; - string url; - uint8 node; - enum DownloadType - { - None, - File, - Config, - MFSConfig - }; - DownloadType operation; - enum Status - { - Ok, - Failed - }; - Status transferStatus; - - }; - class Driver; - class i_HttpClient { - public: - i_HttpClient(Driver *); - virtual ~i_HttpClient() {}; - virtual bool StartDownload(HttpDownload *transfer) = 0; - void FinishDownload(HttpDownload *transfer); - private: - Driver* m_driver; - }; - - - /* this is OZW's implementation of a Http Client. It uses threads to download Config Files in the background. - * - */ - - - - - class HttpClient : public i_HttpClient { - public: - HttpClient(Driver *); - ~HttpClient(); - bool StartDownload(HttpDownload *transfer); - private: - - static void HttpThreadProc(Event* _exitEvent, void* _context); - //Driver* m_driver; - Event* m_exitEvent; - - Thread* m_httpThread; - bool m_httpThreadRunning; - Mutex* m_httpMutex; - list m_httpDownlist; - Event* m_httpDownloadEvent; - - }; - - - + namespace Internal + { + /* This is a abstract class you can implement if you wish to override the built in HTTP Client + * Code in OZW with your own code. + * + * The built in Code uses threads to download updated files to a temporary file + * and then this class moves the files into the correct place. + * + */ + + struct HttpDownload + { + string filename; + string url; + uint8 node; + enum DownloadType + { + None, + File, + Config, + MFSConfig + }; + DownloadType operation; + enum Status + { + Ok, + Failed + }; + Status transferStatus; + + }; + + class i_HttpClient + { + public: + i_HttpClient(Driver *); + virtual ~i_HttpClient() + { + } + ; + virtual bool StartDownload(HttpDownload *transfer) = 0; + void FinishDownload(HttpDownload *transfer); + private: + Driver* m_driver; + }; + + /* this is OZW's implementation of a Http Client. It uses threads to download Config Files in the background. + * + */ + + class HttpClient: public i_HttpClient + { + public: + HttpClient(Driver *); + ~HttpClient(); + bool StartDownload(HttpDownload *transfer); + private: + + static void HttpThreadProc(Internal::Platform::Event* _exitEvent, void* _context); + //Driver* m_driver; + Internal::Platform::Event* m_exitEvent; + + Internal::Platform::Thread* m_httpThread; + bool m_httpThreadRunning; + Internal::Platform::Mutex* m_httpMutex; + list m_httpDownlist; + Internal::Platform::Event* m_httpDownloadEvent; + + }; + + } // namespace Internal } /* namespace OpenZWave */ - - #endif diff --git a/cpp/src/Localization.cpp b/cpp/src/Localization.cpp index 967293239c..aa65f6832d 100755 --- a/cpp/src/Localization.cpp +++ b/cpp/src/Localization.cpp @@ -33,786 +33,743 @@ #include "platform/Log.h" #include "value_classes/ValueBitSet.h" #include "command_classes/Configuration.h" +#include "command_classes/ThermostatSetpoint.h" +#include "command_classes/SoundSwitch.h" +#include "command_classes/Meter.h" -using namespace OpenZWave; - -Localization *Localization::m_instance = NULL; -map Localization::m_valueLocalizationMap; -map Localization::m_commandClassLocalizationMap; -map Localization::m_globalLabelLocalizationMap; -string Localization::m_selectedLang = ""; -uint32 Localization::m_revision = 0; - -LabelLocalizationEntry::LabelLocalizationEntry -( - uint16 _index, - uint32 _pos -): -m_index( _index ), -m_pos( _pos ) +namespace OpenZWave { -} + namespace Internal + { + Localization *Localization::m_instance = NULL; + std::map > Localization::m_valueLocalizationMap; + std::map > Localization::m_commandClassLocalizationMap; + std::map > Localization::m_globalLabelLocalizationMap; + std::string Localization::m_selectedLang = ""; + uint32 Localization::m_revision = 0; + LabelLocalizationEntry::LabelLocalizationEntry(uint16 _index, uint32 _pos) : + m_index(_index), m_pos(_pos) + { + } -void LabelLocalizationEntry::AddLabel -( - string label, - string lang -) -{ - if (lang.empty()) - m_defaultLabel = label; - else - m_Label[lang] = label; -} -uint64 LabelLocalizationEntry::GetIdx -( -) -{ - uint64 key = ((uint64)m_index << 32) | ((uint64)m_pos); - return key; - -} -string LabelLocalizationEntry::GetLabel -( - string lang -) -{ - if (lang.empty() || (m_Label.find(lang) == m_Label.end())) - return m_defaultLabel; - else - return m_Label[lang]; + void LabelLocalizationEntry::AddLabel(string label, string lang) + { + if (lang.empty()) + m_defaultLabel = label; + else + m_Label[lang] = label; + } + uint64 LabelLocalizationEntry::GetIdx() + { + uint64 key = ((uint64) m_index << 32) | ((uint64) m_pos); + return key; -} + } + std::string LabelLocalizationEntry::GetLabel(string lang) + { + if (lang.empty() || (m_Label.find(lang) == m_Label.end())) + return m_defaultLabel; + else + return m_Label[lang]; + } + bool LabelLocalizationEntry::HasLabel(string lang) + { + if (m_Label.find(lang) == m_Label.end()) + return false; + else + return true; -bool LabelLocalizationEntry::HasLabel -( - string lang -) -{ - if (m_Label.find(lang) == m_Label.end()) - return false; - else - return true; - -} - -ValueLocalizationEntry::ValueLocalizationEntry -( - uint8 _commandClass, - uint16 _index, - uint32 _pos -): -m_commandClass( _commandClass ), -m_index( _index ), -m_pos( _pos ) -{ -} + } + ValueLocalizationEntry::ValueLocalizationEntry(uint8 _commandClass, uint16 _index, uint32 _pos) : + m_commandClass(_commandClass), m_index(_index), m_pos(_pos) + { + } -uint64 ValueLocalizationEntry::GetIdx -( -) -{ - uint64 key = ((uint64)m_commandClass << 48) | ((uint64)m_index << 32) | ((uint64)m_pos); - return key; -} -string ValueLocalizationEntry::GetHelp -( - string lang -) + uint64 ValueLocalizationEntry::GetIdx() + { + uint64 key = ((uint64) m_commandClass << 48) | ((uint64) m_index << 32) | ((uint64) m_pos); + return key; + } + std::string ValueLocalizationEntry::GetHelp(string lang) -{ - if (lang.empty() || (m_HelpText.find(lang) == m_HelpText.end())) - return m_DefaultHelpText; - else - return m_HelpText[lang]; -} + { + if (lang.empty() || (m_HelpText.find(lang) == m_HelpText.end())) + return m_DefaultHelpText; + else + return m_HelpText[lang]; + } -bool ValueLocalizationEntry::HasHelp -( - string lang -) + bool ValueLocalizationEntry::HasHelp(string lang) -{ - if (m_HelpText.find(lang) == m_HelpText.end()) - return false; - else - return true; -} - -void ValueLocalizationEntry::AddHelp -( - string HelpText, - string lang -) -{ - if (lang.empty()) - m_DefaultHelpText = HelpText; - else - m_HelpText[lang] = HelpText; - -} -string ValueLocalizationEntry::GetLabel -( - string lang -) -{ - if (lang.empty() || (m_LabelText.find(lang) == m_LabelText.end())) - return m_DefaultLabelText; - else - return m_LabelText[lang]; -} -bool ValueLocalizationEntry::HasLabel -( - string lang -) + { + if (m_HelpText.find(lang) == m_HelpText.end()) + return false; + else + return true; + } -{ - if (m_LabelText.find(lang) == m_LabelText.end()) - return false; - else - return true; -} - -void ValueLocalizationEntry::AddLabel -( - string Label, - string lang -) -{ - if (lang.empty()) - m_DefaultLabelText = Label; - else - m_LabelText[lang] = Label; -} - -void ValueLocalizationEntry::AddItemLabel -( - string label, - int32 itemindex, - string lang -) -{ - if (lang.empty()) { - m_DefaultItemLabelText[itemindex] = label; - } else { - m_ItemLabelText[lang][itemindex] = label; - } - -} -string ValueLocalizationEntry::GetItemLabel -( - string lang, - int32 itemindex -) -{ - if (lang.empty() || (m_ItemLabelText.find(lang) == m_ItemLabelText.end()) || m_ItemLabelText[lang].find(itemindex) == m_ItemLabelText[lang].end()) { - if (m_DefaultItemLabelText.find(itemindex) == m_DefaultItemLabelText.end()) { - Log::Write( LogLevel_Warning, "ValueLocalizationEntry::GetItemLabel: Unable to find Default Item Label Text for Index Item %d (%s)", itemindex, m_DefaultLabelText.c_str()); - return "undefined"; - } - return m_DefaultItemLabelText[itemindex]; - } else { - return m_ItemLabelText[lang][itemindex]; - } -} - -bool ValueLocalizationEntry::HasItemLabel -( - int32 itemIndex, - string lang -) -{ - if (lang.empty() || (m_ItemLabelText.find(lang) == m_ItemLabelText.end()) || m_ItemLabelText[lang].find(itemIndex) == m_ItemLabelText[lang].end()) - return false; - return true; -} - -void ValueLocalizationEntry::AddItemHelp -( - string label, - int32 itemindex, - string lang -) -{ + void ValueLocalizationEntry::AddHelp(string HelpText, string lang) + { + if (lang.empty()) + m_DefaultHelpText = HelpText; + else + m_HelpText[lang] = HelpText; - if (lang.empty()) { - m_DefaultItemHelpText[itemindex] = label; - } else { - m_ItemHelpText[lang][itemindex] = label; - } - -} -string ValueLocalizationEntry::GetItemHelp -( - string lang, - int32 itemindex -) -{ - if (lang.empty() && (m_DefaultItemHelpText.find(itemindex) != m_DefaultItemHelpText.end())) { - return m_DefaultItemHelpText[itemindex]; - } - - if ((m_ItemHelpText.find(lang) != m_ItemHelpText.end())) { - if ((m_ItemHelpText.at(lang).find(itemindex) != m_ItemHelpText.at(lang).end())) { - return m_ItemHelpText.at(lang)[itemindex]; - } - } - if (m_DefaultItemHelpText.find(itemindex) != m_DefaultItemHelpText.end()) { - return m_DefaultItemHelpText[itemindex]; - } - Log::Write(LogLevel_Warning, "No ItemHelp Entry for Language %s (Index %d)", lang.c_str(), itemindex); - return "Undefined"; -} - -bool ValueLocalizationEntry::HasItemHelp -( - int32 itemIndex, - string lang -) -{ - if (lang.empty() && (m_DefaultItemHelpText.find(itemIndex) != m_DefaultItemHelpText.end())) { - return true; - } + } + std::string ValueLocalizationEntry::GetLabel(string lang) + { + if (lang.empty() || (m_LabelText.find(lang) == m_LabelText.end())) + return m_DefaultLabelText; + else + return m_LabelText[lang]; + } + bool ValueLocalizationEntry::HasLabel(string lang) - if ((m_ItemHelpText.find(lang) != m_ItemHelpText.end())) { - if ((m_ItemHelpText.at(lang).find(itemIndex) != m_ItemHelpText.at(lang).end())) { + { + if (m_LabelText.find(lang) == m_LabelText.end()) + return false; + else + return true; + } + + void ValueLocalizationEntry::AddLabel(string Label, string lang) + { + if (lang.empty()) + m_DefaultLabelText = Label; + else + m_LabelText[lang] = Label; + } + + void ValueLocalizationEntry::AddItemLabel(string label, int32 itemindex, string lang) + { + if (lang.empty()) + { + m_DefaultItemLabelText[itemindex] = label; + } + else + { + m_ItemLabelText[lang][itemindex] = label; + } + + } + std::string ValueLocalizationEntry::GetItemLabel(string lang, int32 itemindex) + { + if (lang.empty() || (m_ItemLabelText.find(lang) == m_ItemLabelText.end()) || m_ItemLabelText[lang].find(itemindex) == m_ItemLabelText[lang].end()) + { + if (m_DefaultItemLabelText.find(itemindex) == m_DefaultItemLabelText.end()) + { + Log::Write(LogLevel_Warning, "ValueLocalizationEntry::GetItemLabel: Unable to find Default Item Label Text for Index Item %d (%s)", itemindex, m_DefaultLabelText.c_str()); + return "undefined"; + } + return m_DefaultItemLabelText[itemindex]; + } + else + { + return m_ItemLabelText[lang][itemindex]; + } + } + + bool ValueLocalizationEntry::HasItemLabel(int32 itemIndex, string lang) + { + if (lang.empty() || (m_ItemLabelText.find(lang) == m_ItemLabelText.end()) || m_ItemLabelText[lang].find(itemIndex) == m_ItemLabelText[lang].end()) + return false; return true; } - return false; - } - return false; -} + void ValueLocalizationEntry::AddItemHelp(string label, int32 itemindex, string lang) + { + if (lang.empty()) + { + m_DefaultItemHelpText[itemindex] = label; + } + else + { + m_ItemHelpText[lang][itemindex] = label; + } -Localization::Localization() -{ -} + } + std::string ValueLocalizationEntry::GetItemHelp(string lang, int32 itemindex) + { + if (lang.empty() && (m_DefaultItemHelpText.find(itemindex) != m_DefaultItemHelpText.end())) + { + return m_DefaultItemHelpText[itemindex]; + } -void Localization::ReadXML -( -) -{ - // Parse the Z-Wave manufacturer and product XML file. - string configPath; - Options::Get()->GetOptionAsString( "ConfigPath", &configPath ); + if ((m_ItemHelpText.find(lang) != m_ItemHelpText.end())) + { + if ((m_ItemHelpText.at(lang).find(itemindex) != m_ItemHelpText.at(lang).end())) + { + return m_ItemHelpText.at(lang)[itemindex]; + } + } + if (m_DefaultItemHelpText.find(itemindex) != m_DefaultItemHelpText.end()) + { + return m_DefaultItemHelpText[itemindex]; + } + Log::Write(LogLevel_Warning, "No ItemHelp Entry for Language %s (Index %d)", lang.c_str(), itemindex); + return "Undefined"; + } - string path = configPath + "Localization.xml"; - TiXmlDocument* pDoc = new TiXmlDocument(); - if( !pDoc->LoadFile( path.c_str(), TIXML_ENCODING_UTF8 ) ) - { - Log::Write( LogLevel_Warning, "Unable to load Localization file %s: %s", path.c_str(), pDoc->ErrorDesc()); - delete pDoc; - return; - } - pDoc->SetUserData((void*)path.c_str()); - Log::Write( LogLevel_Info, "Loading Localization File %s", path.c_str() ); - - TiXmlElement const* root = pDoc->RootElement(); - char const *str = root->Value(); - if( str && !strcmp( str, "Localization" ) ) - { - // Read in the revision attributes - str = root->Attribute( "Revision" ); - if( !str ) + bool ValueLocalizationEntry::HasItemHelp(int32 itemIndex, string lang) { - Log::Write( LogLevel_Info, "Error in Product Config file at line %d - missing Revision attribute", root->Row() ); - delete pDoc; - return; + if (lang.empty() && (m_DefaultItemHelpText.find(itemIndex) != m_DefaultItemHelpText.end())) + { + return true; + } + + if ((m_ItemHelpText.find(lang) != m_ItemHelpText.end())) + { + if ((m_ItemHelpText.at(lang).find(itemIndex) != m_ItemHelpText.at(lang).end())) + { + return true; + } + return false; + } + return false; } - m_revision = atol(str); - } - TiXmlElement const* CCElement = root->FirstChildElement(); - while( CCElement ) - { - char const* str = CCElement->Value(); - char* pStopChar; - if( str && !strcmp( str, "CommandClass" ) ) + Localization::Localization() { - str = CCElement->Attribute( "id" ); - if( !str ) + } + + void Localization::ReadXML() + { + // Parse the Z-Wave manufacturer and product XML file. + string configPath; + Options::Get()->GetOptionAsString("ConfigPath", &configPath); + + string path = configPath + "Localization.xml"; + TiXmlDocument* pDoc = new TiXmlDocument(); + if (!pDoc->LoadFile(path.c_str(), TIXML_ENCODING_UTF8)) { - Log::Write( LogLevel_Warning, "Localization::ReadXML: Error in %s at line %d - missing commandclass ID attribute", CCElement->GetDocument()->GetUserData(), CCElement->Row() ); - CCElement = CCElement->NextSiblingElement(); - continue; + Log::Write(LogLevel_Warning, "Unable to load Localization file %s: %s", path.c_str(), pDoc->ErrorDesc()); + delete pDoc; + return; } - uint8 ccID = (uint8)strtol( str, &pStopChar, 10 ); - TiXmlElement const* nextElement = CCElement->FirstChildElement(); - while (nextElement) { - str = nextElement->Value(); - if (str && !strcmp( str, "Label" ) ) + pDoc->SetUserData((void*) path.c_str()); + Log::Write(LogLevel_Info, "Loading Localization File %s", path.c_str()); + + TiXmlElement const* root = pDoc->RootElement(); + char const *str = root->Value(); + if (str && !strcmp(str, "Localization")) + { + // Read in the revision attributes + str = root->Attribute("Revision"); + if (!str) { - ReadCCXMLLabel(ccID, nextElement); + Log::Write(LogLevel_Info, "Error in Product Config file at line %d - missing Revision attribute", root->Row()); + delete pDoc; + return; } - if (str && !strcmp( str, "Value" ) ) + m_revision = atol(str); + } + + TiXmlElement const* CCElement = root->FirstChildElement(); + while (CCElement) + { + char const* str = CCElement->Value(); + char* pStopChar; + if (str && !strcmp(str, "CommandClass")) { - ReadXMLValue(ccID, nextElement); + str = CCElement->Attribute("id"); + if (!str) + { + Log::Write(LogLevel_Warning, "Localization::ReadXML: Error in %s at line %d - missing commandclass ID attribute", CCElement->GetDocument()->GetUserData(), CCElement->Row()); + CCElement = CCElement->NextSiblingElement(); + continue; + } + uint8 ccID = (uint8) strtol(str, &pStopChar, 10); + TiXmlElement const* nextElement = CCElement->FirstChildElement(); + while (nextElement) + { + str = nextElement->Value(); + if (str && !strcmp(str, "Label")) + { + ReadCCXMLLabel(ccID, nextElement); + } + if (str && !strcmp(str, "Value")) + { + /* when node = 0, its a Localization that applies to all nodes. */ + ReadXMLValue(0, ccID, nextElement); + } + nextElement = nextElement->NextSiblingElement(); + } } - nextElement = nextElement->NextSiblingElement(); + else if (str && !strcmp(str, "GlobalText")) + { + TiXmlElement const* nextElement = CCElement->FirstChildElement(); + while (nextElement) + { + str = nextElement->Value(); + if (str && !strcmp(str, "Label")) + { + ReadGlobalXMLLabel(nextElement); + } + nextElement = nextElement->NextSiblingElement(); + } + } + + CCElement = CCElement->NextSiblingElement(); + } + Log::Write(LogLevel_Info, "Loaded %s With Revision %d", pDoc->GetUserData(), m_revision); + delete pDoc; + } + + void Localization::ReadGlobalXMLLabel(const TiXmlElement *labelElement) + { + + string Language; + char const *str = labelElement->Attribute("name"); + if (!str) + { + Log::Write(LogLevel_Warning, "Localization::ReadGlobalXMLLabel: Error in %s at line %d - missing GlobalText name attribute", labelElement->GetDocument()->GetUserData(), labelElement->Row()); + return; + } + if (labelElement->Attribute("lang")) + Language = labelElement->Attribute("lang"); + if (m_globalLabelLocalizationMap.find(str) == m_globalLabelLocalizationMap.end()) + { + m_globalLabelLocalizationMap[str] = std::shared_ptr(new LabelLocalizationEntry(0)); + } + else if (m_globalLabelLocalizationMap[str]->HasLabel(Language)) + { + Log::Write(LogLevel_Warning, "Localization::ReadGlobalXMLLabel: Error in %s at line %d - Duplicate Entry for GlobalText %s: %s (Lang: %s)", labelElement->GetDocument()->GetUserData(), labelElement->Row(), str, labelElement->GetText(), Language.c_str()); + return; + } + if (Language.empty()) + { + m_globalLabelLocalizationMap[str]->AddLabel(labelElement->GetText()); + + } + else + { + m_globalLabelLocalizationMap[str]->AddLabel(labelElement->GetText(), Language); + } } - else if ( str && !strcmp( str, "GlobalText" ) ) + + void Localization::ReadCCXMLLabel(uint8 ccID, const TiXmlElement *labelElement) { - TiXmlElement const* nextElement = CCElement->FirstChildElement(); - while (nextElement) { - str = nextElement->Value(); - if ( str && !strcmp( str, "Label" ) ) + + string Language; + if (labelElement->Attribute("lang")) + Language = labelElement->Attribute("lang"); + + if (m_commandClassLocalizationMap.find(ccID) == m_commandClassLocalizationMap.end()) + { + m_commandClassLocalizationMap[ccID] = std::shared_ptr(new LabelLocalizationEntry(0)); + } + else if (m_commandClassLocalizationMap[ccID]->HasLabel(Language)) + { + Log::Write(LogLevel_Warning, "Localization::ReadXMLLabel: Error in %s at line %d - Duplicate Entry for CommandClass %d: %s (Lang: %s)", labelElement->GetDocument()->GetUserData(), labelElement->Row(), ccID, labelElement->GetText(), Language.c_str()); + return; + } + if (Language.empty()) + { + m_commandClassLocalizationMap[ccID]->AddLabel(labelElement->GetText()); + } + else + { + m_commandClassLocalizationMap[ccID]->AddLabel(labelElement->GetText(), Language); + } + } + + void Localization::ReadXMLValue(uint8 node, uint8 ccID, const TiXmlElement *valueElement) + { + + char const* str = valueElement->Attribute("index"); + if (!str) + { + Log::Write(LogLevel_Info, "Localization::ReadXMLValue: Error in %s at line %d - missing Index attribute", valueElement->GetDocument()->GetUserData(), valueElement->Row()); + return; + } + char* pStopChar; + uint16 indexId = (uint16) strtol(str, &pStopChar, 10); + + uint32 pos = -1; + str = valueElement->Attribute("pos"); + if (str) + { + pos = (uint32) strtol(str, &pStopChar, 10); + } + + TiXmlElement const* valueIDElement = valueElement->FirstChildElement(); + while (valueIDElement) + { + str = valueIDElement->Value(); + if (str && !strcmp(str, "Label")) + { + ReadXMLVIDLabel(node, ccID, indexId, pos, valueIDElement); + } + if (str && !strcmp(str, "Help")) + { + ReadXMLVIDHelp(node, ccID, indexId, pos, valueIDElement); + } + if (str && !strcmp(str, "ItemLabel")) { - ReadGlobalXMLLabel(nextElement); + ReadXMLVIDItemLabel(node, ccID, indexId, pos, valueIDElement); } - nextElement = nextElement->NextSiblingElement(); + + valueIDElement = valueIDElement->NextSiblingElement(); } } + void Localization::ReadXMLVIDLabel(uint8 node, uint8 ccID, uint16 indexId, uint32 pos, const TiXmlElement *labelElement) + { - CCElement = CCElement->NextSiblingElement(); - } - Log::Write(LogLevel_Info, "Loaded %s With Revision %d", pDoc->GetUserData(), m_revision); -} + uint64 key = GetValueKey(node, ccID, indexId, pos); + string Language; + if (labelElement->Attribute("lang")) + Language = labelElement->Attribute("lang"); + if (!labelElement->GetText()) + { + Log::Write(LogLevel_Warning, "Localization::ReadXMLVIDLabel: Error in %s at line %d - No Label Entry for CommandClass %d, ValueID: %d (%d): %s (Lang: %s)", labelElement->GetDocument()->GetUserData(), labelElement->Row(), ccID, indexId, pos, labelElement->GetText(), Language.c_str()); + return; + } -void Localization::ReadGlobalXMLLabel(const TiXmlElement *labelElement) { + if (m_valueLocalizationMap.find(key) == m_valueLocalizationMap.end()) + { + m_valueLocalizationMap[key] = std::shared_ptr (new ValueLocalizationEntry(ccID, indexId, pos)); + } + else if (m_valueLocalizationMap[key]->HasLabel(Language)) + { + Log::Write(LogLevel_Warning, "Localization::ReadXMLVIDLabel: Error in %s at line %d - Duplicate Entry for CommandClass %d, ValueID: %d (%d): %s (Lang: %s)", labelElement->GetDocument()->GetUserData(), labelElement->Row(), ccID, indexId, pos, labelElement->GetText(), Language.c_str()); + return; + } - string Language; - char const *str = labelElement->Attribute( "name" ); - if ( !str ) - { - Log::Write( LogLevel_Warning, "Localization::ReadGlobalXMLLabel: Error in %s at line %d - missing GlobalText name attribute", labelElement->GetDocument()->GetUserData(), labelElement->Row() ); - return; - } - if (labelElement->Attribute( "lang" )) - Language = labelElement->Attribute( "lang" ); - if (m_globalLabelLocalizationMap.find(str) == m_globalLabelLocalizationMap.end()) { - m_globalLabelLocalizationMap[str] = new LabelLocalizationEntry(0); - } else if (m_globalLabelLocalizationMap[str]->HasLabel(Language)) { - Log::Write( LogLevel_Warning, "Localization::ReadGlobalXMLLabel: Error in %s at line %d - Duplicate Entry for GlobalText %s: %s (Lang: %s)", labelElement->GetDocument()->GetUserData(), labelElement->Row(), str, labelElement->GetText(), Language.c_str() ); - return; - } - if( Language.empty() ) - { - m_globalLabelLocalizationMap[str]->AddLabel(labelElement->GetText()); + if (Language.empty()) + { + m_valueLocalizationMap[key]->AddLabel(labelElement->GetText()); + } + else + { + m_valueLocalizationMap[key]->AddLabel(labelElement->GetText(), Language); + } + } - } - else - { - m_globalLabelLocalizationMap[str]->AddLabel(labelElement->GetText(), Language); + void Localization::ReadXMLVIDHelp(uint8 node, uint8 ccID, uint16 indexId, uint32 pos, const TiXmlElement *labelElement) + { - } -} + string Language; + if (labelElement->Attribute("lang")) + Language = labelElement->Attribute("lang"); + if (!labelElement->GetText()) + { + if (ccID != 112) + { + /* Dont Log About the Configuration CC */ + Log::Write(LogLevel_Warning, "Localization::ReadXMLVIDHelp: Error in %s at line %d - No Help Entry for CommandClass %d, ValueID: %d (%d): %s (Lang: %s)", labelElement->GetDocument()->GetUserData(), labelElement->Row(), ccID, indexId, pos, labelElement->GetText(), Language.c_str()); + } + return; -void Localization::ReadCCXMLLabel(uint8 ccID, const TiXmlElement *labelElement) { + } - string Language; - if (labelElement->Attribute( "lang" )) - Language = labelElement->Attribute( "lang" ); + uint64 key = GetValueKey(node, ccID, indexId, pos); + if (m_valueLocalizationMap.find(key) == m_valueLocalizationMap.end()) + { + m_valueLocalizationMap[key] = std::shared_ptr (new ValueLocalizationEntry(ccID, indexId, pos)); + } + else if (m_valueLocalizationMap[key]->HasLabel(Language)) + { + Log::Write(LogLevel_Warning, "Localization::ReadXMLVIDHelp: Error in %s at line %d - Duplicate Entry for CommandClass %d, ValueID: %d (%d): %s (Lang: %s)", labelElement->GetDocument()->GetUserData(), labelElement->Row(), ccID, indexId, pos, labelElement->GetText(), Language.c_str()); + return; + } + if (Language.empty()) + { + m_valueLocalizationMap[key]->AddHelp(labelElement->GetText()); + } + else + { + m_valueLocalizationMap[key]->AddHelp(labelElement->GetText(), Language); + } + } - if (m_commandClassLocalizationMap.find(ccID) == m_commandClassLocalizationMap.end()) { - m_commandClassLocalizationMap[ccID] = new LabelLocalizationEntry(0); - } else if (m_commandClassLocalizationMap[ccID]->HasLabel(Language)) { - Log::Write( LogLevel_Warning, "Localization::ReadXMLLabel: Error in %s at line %d - Duplicate Entry for CommandClass %d: %s (Lang: %s)", labelElement->GetDocument()->GetUserData(), labelElement->Row(), ccID, labelElement->GetText(), Language.c_str() ); - return; - } - if( Language.empty() ) - { - m_commandClassLocalizationMap[ccID]->AddLabel(labelElement->GetText()); - } - else - { - m_commandClassLocalizationMap[ccID]->AddLabel(labelElement->GetText(), Language); - } -} + void Localization::ReadXMLVIDItemLabel(uint8 node, uint8 ccID, uint16 indexId, uint32 pos, const TiXmlElement *labelElement) + { -void Localization::ReadXMLValue(uint8 ccID, const TiXmlElement *valueElement) { + uint64 key = GetValueKey(node, ccID, indexId, pos); + string Language; + int32 itemIndex; + if (labelElement->Attribute("lang")) + Language = labelElement->Attribute("lang"); + if (!labelElement->GetText()) + { + Log::Write(LogLevel_Warning, "Localization::ReadXMLVIDItemLabel: Error in %s at line %d - No ItemIndex Label Entry for CommandClass %d, ValueID: %d (%d): %s (Lang: %s)", labelElement->GetDocument()->GetUserData(), labelElement->Row(), ccID, indexId, pos, labelElement->GetText(), Language.c_str()); + return; + } - char const* str = valueElement->Attribute( "index"); - if ( !str ) - { - Log::Write( LogLevel_Info, "Localization::ReadXMLValue: Error in %s at line %d - missing Index attribute", valueElement->GetDocument()->GetUserData(),valueElement->Row() ); - return; - } - char* pStopChar; - uint16 indexId = (uint16)strtol( str, &pStopChar, 16 ); - - uint32 pos = -1; - str = valueElement->Attribute( "pos"); - if (str ) - { - pos = (uint32)strtol( str, &pStopChar, 16 ); - } + if (TIXML_SUCCESS != labelElement->QueryIntAttribute("itemIndex", &itemIndex)) + { + Log::Write(LogLevel_Warning, "Localization::ReadXMLVIDItemLabel: Error in %s at line %d - No itemIndex Entry for CommandClass %d, ValueID: %d (%d): %s (Lang: %s)", labelElement->GetDocument()->GetUserData(), labelElement->Row(), ccID, indexId, pos, labelElement->GetText(), Language.c_str()); + return; + } - TiXmlElement const* valueIDElement = valueElement->FirstChildElement(); - while (valueIDElement) - { - str = valueIDElement->Value(); - if (str && !strcmp( str, "Label" ) ) + if (m_valueLocalizationMap.find(key) == m_valueLocalizationMap.end()) + { + Log::Write(LogLevel_Warning, "Localization::ReadXMLVIDItemLabel: Error in %s at line %d - No Value Entry for CommandClass %d, ValueID: %d (%d): %s (Lang: %s)", labelElement->GetDocument()->GetUserData(), labelElement->Row(), ccID, indexId, pos, labelElement->GetText(), Language.c_str()); + return; + } + else if (m_valueLocalizationMap[key]->HasItemLabel(itemIndex, Language)) + { + Log::Write(LogLevel_Warning, "Localization::ReadXMLVIDItemLabel: Error in %s at line %d - Duplicate ItemLabel Entry for CommandClass %d, ValueID: %d (%d): %s (Lang: %s)", labelElement->GetDocument()->GetUserData(), labelElement->Row(), ccID, indexId, pos, labelElement->GetText(), Language.c_str()); + return; + } + + if (Language.empty()) + { + m_valueLocalizationMap[key]->AddItemLabel(labelElement->GetText(), itemIndex); + } + else + { + m_valueLocalizationMap[key]->AddItemLabel(labelElement->GetText(), itemIndex, Language); + } + } + + uint64 Localization::GetValueKey(uint8 _node, uint8 _commandClass, uint16 _index, uint32 _pos, bool unique) + { + if (unique == true) + { + return ((uint64) _node << 56 | (uint64) _commandClass << 48) | ((uint64) _index << 32) | ((uint64) _pos); + } + /* configuration CC needs its own Storage per Node. */ + if (_commandClass == Internal::CC::Configuration::StaticGetCommandClassId()) + { + return ((uint64) _node << 56 | (uint64) _commandClass << 48) | ((uint64) _index << 32) | ((uint64) _pos); + } + /* ThermoStatSetpoint index's above 100 are unique per node */ + if ((_commandClass == Internal::CC::ThermostatSetpoint::StaticGetCommandClassId()) && (_index >= 100)) + { + return ((uint64) _node << 56 | (uint64) _commandClass << 48) | ((uint64) _index << 32) | ((uint64) _pos); + } + if (_commandClass == Internal::CC::Meter::StaticGetCommandClassId()) + { + return ((uint64) _node << 56 | (uint64) _commandClass << 48) | ((uint64) _index << 32) | ((uint64) _pos); + } + return ((uint64) _commandClass << 48) | ((uint64) _index << 32) | ((uint64) _pos); + } + + void Localization::SetupCommandClass(Internal::CC::CommandClass *cc) { - ReadXMLVIDLabel(ccID, indexId, pos, valueIDElement); + uint8 ccID = cc->GetCommandClassId(); + if (m_commandClassLocalizationMap.find(ccID) != m_commandClassLocalizationMap.end()) + { + cc->SetCommandClassLabel(m_commandClassLocalizationMap[ccID]->GetLabel(m_selectedLang)); + } + else + { + Log::Write(LogLevel_Warning, "Localization::SetupCommandClass: Localization Warning: No Entry for CommandClass - CC: %d (%s)", ccID, cc->GetCommandClassName().c_str()); + cc->SetCommandClassLabel(cc->GetCommandClassName()); + } } - if (str && !strcmp( str, "Help" ) ) + + bool Localization::SetValueHelp(uint8 _node, uint8 ccID, uint16 indexId, uint32 pos, string help, string lang) { - ReadXMLVIDHelp(ccID, indexId, pos, valueIDElement); + uint64 key = GetValueKey(_node, ccID, indexId, pos); + if (m_valueLocalizationMap.find(key) == m_valueLocalizationMap.end()) + { + m_valueLocalizationMap[key] = std::shared_ptr (new ValueLocalizationEntry(ccID, indexId, pos)); + } + else if (m_valueLocalizationMap[key]->HasHelp(lang)) + { + Log::Write(LogLevel_Warning, "Localization::SetValueHelp: Duplicate Entry for CommandClass %d, ValueID: %d (%d): %s (Lang: %s)", ccID, indexId, pos, help.c_str(), lang.c_str()); + } + + if (lang.empty()) + { + m_valueLocalizationMap[key]->AddHelp(help); + } + else + { + m_valueLocalizationMap[key]->AddHelp(help, lang); + } + return true; + } + bool Localization::SetValueLabel(uint8 node, uint8 ccID, uint16 indexId, uint32 pos, string label, string lang) + { + uint64 key = GetValueKey(node, ccID, indexId, pos); + if (m_valueLocalizationMap.find(key) == m_valueLocalizationMap.end()) + { + m_valueLocalizationMap[key] = std::shared_ptr (new ValueLocalizationEntry(ccID, indexId, pos)); + } + else if (m_valueLocalizationMap[key]->HasLabel(lang)) + { + Log::Write(LogLevel_Warning, "Localization::SetValueLabel: Duplicate Entry for CommandClass %d, ValueID: %d (%d): %s (Lang: %s)", ccID, indexId, pos, label.c_str(), lang.c_str()); + } + + if (lang.empty()) + { + m_valueLocalizationMap[key]->AddLabel(label); + } + else + { + m_valueLocalizationMap[key]->AddLabel(label, lang); + } + return true; + } + + std::string const Localization::GetValueHelp(uint8 node, uint8 ccID, uint16 indexId, uint32 pos) + { + uint64 key = GetValueKey(node, ccID, indexId, pos); + if (m_valueLocalizationMap.find(key) == m_valueLocalizationMap.end()) + { + Log::Write(LogLevel_Warning, "Localization::GetValueHelp: No Help for CommandClass %xd, ValueID: %d (%d)", ccID, indexId, pos); + return ""; + } + return m_valueLocalizationMap[key]->GetHelp(m_selectedLang); } - if (str && !strcmp( str, "ItemLabel" ) ) + + std::string const Localization::GetValueLabel(uint8 node, uint8 ccID, uint16 indexId, int32 pos) const { - ReadXMLVIDItemLabel(ccID, indexId, pos, valueIDElement); + uint64 key = GetValueKey(node, ccID, indexId, pos); + if (m_valueLocalizationMap.find(key) == m_valueLocalizationMap.end()) + { + Log::Write(LogLevel_Warning, "Localization::GetValueLabel: No Label for CommandClass %xd, ValueID: %d (%d)", ccID, indexId, pos); + return ""; + } + return m_valueLocalizationMap[key]->GetLabel(m_selectedLang); } - valueIDElement = valueIDElement->NextSiblingElement(); - } -} + std::string const Localization::GetValueItemLabel(uint8 node, uint8 ccID, uint16 indexId, int32 pos, int32 itemIndex) const + { + bool unique = false; + if ((ccID == Internal::CC::SoundSwitch::StaticGetCommandClassId()) && (indexId == 1 || indexId == 3)) + { + unique = true; + } + uint64 key = GetValueKey(node, ccID, indexId, pos, unique); + if (m_valueLocalizationMap.find(key) == m_valueLocalizationMap.end()) + { + Log::Write(LogLevel_Warning, "Localization::GetValueItemLabel: No ValueLocalizationMap for CommandClass %xd, ValueID: %d (%d) ItemIndex %d", ccID, indexId, pos, itemIndex); + return ""; + } + return m_valueLocalizationMap[key]->GetItemLabel(m_selectedLang, itemIndex); + } -void Localization::ReadXMLVIDLabel(uint8 ccID, uint16 indexId, uint32 pos, const TiXmlElement *labelElement) { + bool Localization::SetValueItemLabel(uint8 node, uint8 ccID, uint16 indexId, int32 pos, int32 itemIndex, string label, string lang) + { + bool unique = false; + if ((ccID == Internal::CC::SoundSwitch::StaticGetCommandClassId()) && (indexId == 1 || indexId == 3)) + { + unique = true; + } - uint64 key = GetValueKey(ccID, indexId, pos); - string Language; - if (labelElement->Attribute( "lang" )) - Language = labelElement->Attribute( "lang" ); - if (!labelElement->GetText()) { - Log::Write( LogLevel_Warning, "Localization::ReadXMLVIDLabel: Error in %s at line %d - No Label Entry for CommandClass %d, ValueID: %d (%d): %s (Lang: %s)", labelElement->GetDocument()->GetUserData(),labelElement->Row(), ccID, indexId, pos, labelElement->GetText(), Language.c_str() ); - return; - } + uint64 key = GetValueKey(node, ccID, indexId, pos, unique); + if (m_valueLocalizationMap.find(key) == m_valueLocalizationMap.end()) + { + m_valueLocalizationMap[key] = std::shared_ptr (new ValueLocalizationEntry(ccID, indexId, pos)); + } + else if (m_valueLocalizationMap[key]->HasItemLabel(itemIndex, lang)) + { + Log::Write(LogLevel_Warning, "Localization::SetValueItemLabel: Duplicate Item Entry for CommandClass %d, ValueID: %d (%d) itemIndex %d: %s (Lang: %s)", ccID, indexId, pos, itemIndex, label.c_str(), lang.c_str()); + } + m_valueLocalizationMap[key]->AddItemLabel(label, itemIndex, lang); + return true; + } - if (m_valueLocalizationMap.find(key) == m_valueLocalizationMap.end()) { - m_valueLocalizationMap[key] = new ValueLocalizationEntry(ccID, indexId, pos); - } else if (m_valueLocalizationMap[key]->HasLabel(Language)) { - Log::Write( LogLevel_Warning, "Localization::ReadXMLVIDLabel: Error in %s at line %d - Duplicate Entry for CommandClass %d, ValueID: %d (%d): %s (Lang: %s)", labelElement->GetDocument()->GetUserData(), labelElement->Row(), ccID, indexId, pos, labelElement->GetText(), Language.c_str() ); - return; - } + std::string const Localization::GetValueItemHelp(uint8 node, uint8 ccID, uint16 indexId, int32 pos, int32 itemIndex) const + { + bool unique = false; + if ((ccID == Internal::CC::SoundSwitch::StaticGetCommandClassId()) && (indexId == 1 || indexId == 3)) + { + unique = true; + } - if( Language.empty() ) - { - m_valueLocalizationMap[key]->AddLabel(labelElement->GetText()); - } - else - { - m_valueLocalizationMap[key]->AddLabel(labelElement->GetText(), Language); - } -} - -void Localization::ReadXMLVIDHelp(uint8 ccID, uint16 indexId, uint32 pos, const TiXmlElement *labelElement) { - - string Language; - if (labelElement->Attribute( "lang" )) - Language = labelElement->Attribute( "lang" ); - if (!labelElement->GetText()) { - if (ccID != 112) { - /* Dont Log About the Configuration CC */ - Log::Write( LogLevel_Warning, "Localization::ReadXMLVIDHelp: Error in %s at line %d - No Help Entry for CommandClass %d, ValueID: %d (%d): %s (Lang: %s)", labelElement->GetDocument()->GetUserData(), labelElement->Row(), ccID, indexId, pos, labelElement->GetText(), Language.c_str() ); - } - return; - - } - - uint64 key = GetValueKey(ccID, indexId, pos); - if (m_valueLocalizationMap.find(key) == m_valueLocalizationMap.end()) { - m_valueLocalizationMap[key] = new ValueLocalizationEntry(ccID, indexId, pos); - } else if (m_valueLocalizationMap[key]->HasLabel(Language)) { - Log::Write( LogLevel_Warning, "Localization::ReadXMLVIDHelp: Error in %s at line %d - Duplicate Entry for CommandClass %d, ValueID: %d (%d): %s (Lang: %s)", labelElement->GetDocument()->GetUserData(), labelElement->Row(), ccID, indexId, pos, labelElement->GetText(), Language.c_str() ); - return; - } - if( Language.empty() ) - { - m_valueLocalizationMap[key]->AddHelp(labelElement->GetText()); - } - else - { - m_valueLocalizationMap[key]->AddHelp(labelElement->GetText(), Language); - } -} - -void Localization::ReadXMLVIDItemLabel(uint8 ccID, uint16 indexId, uint32 pos, const TiXmlElement *labelElement) { - - uint64 key = GetValueKey(ccID, indexId, pos); - string Language; - int32 itemIndex; - if (labelElement->Attribute( "lang" )) - Language = labelElement->Attribute( "lang" ); - if (!labelElement->GetText()) { - Log::Write( LogLevel_Warning, "Localization::ReadXMLVIDItemLabel: Error in %s at line %d - No ItemIndex Label Entry for CommandClass %d, ValueID: %d (%d): %s (Lang: %s)", labelElement->GetDocument()->GetUserData(), labelElement->Row(), ccID, indexId, pos, labelElement->GetText(), Language.c_str() ); - return; - } - - if (TIXML_SUCCESS != labelElement->QueryIntAttribute( "itemIndex", &itemIndex )) { - Log::Write( LogLevel_Warning, "Localization::ReadXMLVIDItemLabel: Error in %s at line %d - No itemIndex Entry for CommandClass %d, ValueID: %d (%d): %s (Lang: %s)", labelElement->GetDocument()->GetUserData(), labelElement->Row(), ccID, indexId, pos, labelElement->GetText(), Language.c_str() ); - return; - } - - if (m_valueLocalizationMap.find(key) == m_valueLocalizationMap.end()) { - Log::Write( LogLevel_Warning, "Localization::ReadXMLVIDItemLabel: Error in %s at line %d - No Value Entry for CommandClass %d, ValueID: %d (%d): %s (Lang: %s)", labelElement->GetDocument()->GetUserData(), labelElement->Row(), ccID, indexId, pos, labelElement->GetText(), Language.c_str() ); - return; - } else if (m_valueLocalizationMap[key]->HasItemLabel(itemIndex, Language)) { - Log::Write( LogLevel_Warning, "Localization::ReadXMLVIDItemLabel: Error in %s at line %d - Duplicate ItemLabel Entry for CommandClass %d, ValueID: %d (%d): %s (Lang: %s)", labelElement->GetDocument()->GetUserData(), labelElement->Row(), ccID, indexId, pos, labelElement->GetText(), Language.c_str() ); - return; - } - - if( Language.empty() ) - { - m_valueLocalizationMap[key]->AddItemLabel(labelElement->GetText(), itemIndex); - } - else - { - m_valueLocalizationMap[key]->AddItemLabel(labelElement->GetText(), itemIndex, Language); - } -} + uint64 key = GetValueKey(node, ccID, indexId, pos, unique); + if (m_valueLocalizationMap.find(key) == m_valueLocalizationMap.end()) + { + Log::Write(LogLevel_Warning, "Localization::GetValueItemHelp: No ValueLocalizationMap for CommandClass %xd, ValueID: %d (%d) ItemIndex %d", ccID, indexId, pos, itemIndex); + return ""; + } + return m_valueLocalizationMap[key]->GetItemHelp(m_selectedLang, itemIndex); + } + bool Localization::SetValueItemHelp(uint8 node, uint8 ccID, uint16 indexId, int32 pos, int32 itemIndex, string label, string lang) + { + bool unique = false; + if ((ccID == Internal::CC::SoundSwitch::StaticGetCommandClassId()) && (indexId == 1 || indexId == 3)) + { + unique = true; + } + uint64 key = GetValueKey(node, ccID, indexId, pos, unique); + if (m_valueLocalizationMap.find(key) == m_valueLocalizationMap.end()) + { + m_valueLocalizationMap[key] = std::shared_ptr (new ValueLocalizationEntry(ccID, indexId, pos)); + } + else if (m_valueLocalizationMap[key]->HasItemHelp(itemIndex, lang)) + { + Log::Write(LogLevel_Warning, "Localization::SetValueItemHelp: Duplicate Item Entry for CommandClass %d, ValueID: %d (%d) ItemIndex %d: %s (Lang: %s)", ccID, indexId, pos, itemIndex, label.c_str(), lang.c_str()); + } + m_valueLocalizationMap[key]->AddItemHelp(label, itemIndex, lang); + return true; + } -uint64 Localization::GetValueKey -( - uint8 _commandClass, - uint16 _index, - uint32 _pos -) -{ - return ((uint64)_commandClass << 48) | ((uint64)_index << 32) | ((uint64)_pos); -} + std::string const Localization::GetGlobalLabel(string index) + { + if (m_globalLabelLocalizationMap.find(index) == m_globalLabelLocalizationMap.end()) + { + Log::Write(LogLevel_Warning, "Localization::GetGlobalLabel: No globalLabelLocalizationMap for Index %s", index.c_str()); + return index; + } + return m_globalLabelLocalizationMap[index]->GetLabel(m_selectedLang); -void Localization::SetupCommandClass -( - CommandClass *cc -) -{ - uint8 ccID = cc->GetCommandClassId(); - if (m_commandClassLocalizationMap.find(ccID) != m_commandClassLocalizationMap.end()) { - cc->SetCommandClassLabel(m_commandClassLocalizationMap[ccID]->GetLabel(m_selectedLang)); - } else { - Log::Write( LogLevel_Warning, "Localization::SetupCommandClass: Localization Warning: No Entry for CommandClass - CC: %d (%s)", ccID, cc->GetCommandClassName().c_str()); - cc->SetCommandClassLabel(cc->GetCommandClassName()); - } -} - -bool Localization::SetValueHelp -( - uint8 ccID, - uint16 indexId, - uint32 pos, - string help, - string lang -) -{ - uint64 key = GetValueKey(ccID, indexId, pos); - if (m_valueLocalizationMap.find(key) == m_valueLocalizationMap.end()) { - m_valueLocalizationMap[key] = new ValueLocalizationEntry(ccID, indexId, pos); - } else if (m_valueLocalizationMap[key]->HasHelp(lang)) { - Log::Write( LogLevel_Warning, "Localization::SetValueHelp: Duplicate Entry for CommandClass %d, ValueID: %d (%d): %s (Lang: %s)", ccID, indexId, pos, help.c_str(), lang.c_str() ); - } - - if( lang.empty() ) - { - m_valueLocalizationMap[key]->AddHelp(help); - } - else - { - m_valueLocalizationMap[key]->AddHelp(help, lang); - } - return true; -} -bool Localization::SetValueLabel -( - uint8 ccID, - uint16 indexId, - uint32 pos, - string label, - string lang -) -{ - uint64 key = GetValueKey(ccID, indexId, pos); - if (m_valueLocalizationMap.find(key) == m_valueLocalizationMap.end()) { - m_valueLocalizationMap[key] = new ValueLocalizationEntry(ccID, indexId, pos); - } else if (m_valueLocalizationMap[key]->HasLabel(lang)) { - Log::Write( LogLevel_Warning, "Localization::SetValueLabel: Duplicate Entry for CommandClass %d, ValueID: %d (%d): %s (Lang: %s)", ccID, indexId, pos, label.c_str(), lang.c_str() ); - } - - if( lang.empty() ) - { - m_valueLocalizationMap[key]->AddLabel(label); - } - else - { - m_valueLocalizationMap[key]->AddLabel(label, lang); - } - return true; -} - -string const Localization::GetValueHelp -( - uint8 ccID, - uint16 indexId, - uint32 pos -) -{ - uint64 key = GetValueKey(ccID, indexId, pos); - if (m_valueLocalizationMap.find(key) == m_valueLocalizationMap.end()) { - Log::Write( LogLevel_Warning, "Localization::GetValueHelp: No Help for CommandClass %xd, ValueID: %d (%d)", ccID, indexId, pos); - return ""; - } - return m_valueLocalizationMap[key]->GetHelp(m_selectedLang); -} - -string const Localization::GetValueLabel -( - uint8 ccID, - uint16 indexId, - int32 pos -) const -{ - uint64 key = GetValueKey(ccID, indexId, pos); - if (m_valueLocalizationMap.find(key) == m_valueLocalizationMap.end()) { - Log::Write( LogLevel_Warning, "Localization::GetValueLabel: No Label for CommandClass %xd, ValueID: %d (%d)", ccID, indexId, pos); - return ""; - } - return m_valueLocalizationMap[key]->GetLabel(m_selectedLang); -} - - -string const Localization::GetValueItemLabel -( - uint8 ccID, - uint16 indexId, - int32 pos, - int32 itemIndex -) const -{ - uint64 key = GetValueKey(ccID, indexId, pos); - if (m_valueLocalizationMap.find(key) == m_valueLocalizationMap.end()) { - Log::Write( LogLevel_Warning, "Localization::GetValueItemLabel: No ValueLocalizationMap for CommandClass %xd, ValueID: %d (%d) ItemIndex %d", ccID, indexId, pos, itemIndex); - return ""; - } - return m_valueLocalizationMap[key]->GetItemLabel(m_selectedLang, itemIndex); -} - -bool Localization::SetValueItemLabel -( - uint8 ccID, - uint16 indexId, - int32 pos, - int32 itemIndex, - string label, - string lang -) -{ - uint64 key = GetValueKey(ccID, indexId, pos); - if (m_valueLocalizationMap.find(key) == m_valueLocalizationMap.end()) { - m_valueLocalizationMap[key] = new ValueLocalizationEntry(ccID, indexId, pos); - } else if (m_valueLocalizationMap[key]->HasItemLabel(itemIndex, lang)) { - Log::Write( LogLevel_Warning, "Localization::SetValueItemLabel: Duplicate Item Entry for CommandClass %d, ValueID: %d (%d) itemIndex %d: %s (Lang: %s)", ccID, indexId, pos, itemIndex, label.c_str(), lang.c_str() ); - } - m_valueLocalizationMap[key]->AddItemLabel(label, itemIndex, lang); - return true; -} - -string const Localization::GetValueItemHelp -( - uint8 ccID, - uint16 indexId, - int32 pos, - int32 itemIndex -) const -{ - uint64 key = GetValueKey(ccID, indexId, pos); - if (m_valueLocalizationMap.find(key) == m_valueLocalizationMap.end()) { - Log::Write( LogLevel_Warning, "Localization::GetValueItemHelp: No ValueLocalizationMap for CommandClass %xd, ValueID: %d (%d) ItemIndex %d", ccID, indexId, pos, itemIndex); - return ""; - } - return m_valueLocalizationMap[key]->GetItemHelp(m_selectedLang, itemIndex); -} - -bool Localization::SetValueItemHelp -( - uint8 ccID, - uint16 indexId, - int32 pos, - int32 itemIndex, - string label, - string lang -) -{ - uint64 key = GetValueKey(ccID, indexId, pos); - if (m_valueLocalizationMap.find(key) == m_valueLocalizationMap.end()) { - m_valueLocalizationMap[key] = new ValueLocalizationEntry(ccID, indexId, pos); - } else if (m_valueLocalizationMap[key]->HasItemHelp(itemIndex, lang)) { - Log::Write( LogLevel_Warning, "Localization::SetValueItemHelp: Duplicate Item Entry for CommandClass %d, ValueID: %d (%d) ItemIndex %d: %s (Lang: %s)", ccID, indexId, pos, itemIndex, label.c_str(), lang.c_str() ); - } - m_valueLocalizationMap[key]->AddItemHelp(label, itemIndex, lang); - return true; -} - -string const Localization::GetGlobalLabel -( - string index -) -{ - if (m_globalLabelLocalizationMap.find(index) == m_globalLabelLocalizationMap.end()) { - Log::Write( LogLevel_Warning, "Localization::GetGlobalLabel: No globalLabelLocalizationMap for Index %s", index.c_str()); - return index; - } - return m_globalLabelLocalizationMap[index]->GetLabel(m_selectedLang); - -} -bool Localization::SetGlobalLabel -( - string index, - string text, - string lang -) -{ - if (m_globalLabelLocalizationMap.find(index) == m_globalLabelLocalizationMap.end()) { - m_globalLabelLocalizationMap[index] = new LabelLocalizationEntry(0); - } else if (m_globalLabelLocalizationMap[index]->HasLabel(lang)) { - Log::Write( LogLevel_Warning, "Localization::SetGlobalLabel: Duplicate Entry for GlobalText %s: %s (Lang: %s)", index.c_str(), text.c_str(), lang.c_str() ); - return false; - } - if( lang.empty() ) - { - m_globalLabelLocalizationMap[index]->AddLabel(text); + } + bool Localization::SetGlobalLabel(string index, string text, string lang) + { + if (m_globalLabelLocalizationMap.find(index) == m_globalLabelLocalizationMap.end()) + { + m_globalLabelLocalizationMap[index] = std::shared_ptr(new LabelLocalizationEntry(0)); + } + else if (m_globalLabelLocalizationMap[index]->HasLabel(lang)) + { + Log::Write(LogLevel_Warning, "Localization::SetGlobalLabel: Duplicate Entry for GlobalText %s: %s (Lang: %s)", index.c_str(), text.c_str(), lang.c_str()); + return false; + } + if (lang.empty()) + { + m_globalLabelLocalizationMap[index]->AddLabel(text); - } - else - { - m_globalLabelLocalizationMap[index]->AddLabel(text, lang); - - } - return true; -} - -bool Localization::WriteXMLVIDHelp -( - uint8 ccID, - uint16 indexId, - uint32 pos, - TiXmlElement *valueElement -) -{ - uint64 key = GetValueKey(ccID, indexId, pos); - if (m_valueLocalizationMap.find(key) == m_valueLocalizationMap.end()) { - Log::Write( LogLevel_Warning, "Localization::WriteXMLVIDHelp: No Help for CommandClass %d, ValueID: %d (%d)", ccID, indexId, pos); - return false; - } - TiXmlElement* helpElement = new TiXmlElement( "Help" ); - valueElement->LinkEndChild( helpElement ); + } + else + { + m_globalLabelLocalizationMap[index]->AddLabel(text, lang); - TiXmlText* textElement = new TiXmlText( m_valueLocalizationMap[key]->GetHelp(m_selectedLang).c_str() ); - helpElement->LinkEndChild( textElement ); - return true; -} + } + return true; + } + bool Localization::WriteXMLVIDHelp(uint8 node, uint8 ccID, uint16 indexId, uint32 pos, TiXmlElement *valueElement) + { + uint64 key = GetValueKey(node, ccID, indexId, pos); + if (m_valueLocalizationMap.find(key) == m_valueLocalizationMap.end()) + { + Log::Write(LogLevel_Warning, "Localization::WriteXMLVIDHelp: No Help for CommandClass %d, ValueID: %d (%d)", ccID, indexId, pos); + return false; + } + TiXmlElement* helpElement = new TiXmlElement("Help"); + valueElement->LinkEndChild(helpElement); + TiXmlText* textElement = new TiXmlText(m_valueLocalizationMap[key]->GetHelp(m_selectedLang).c_str()); + helpElement->LinkEndChild(textElement); + return true; + } -Localization *Localization::Get -( -) -{ - if ( m_instance != NULL ) - { - return m_instance; - } - m_instance = new Localization(); - ReadXML(); - Options::Get()->GetOptionAsString( "Language", &m_selectedLang ); - return m_instance; -} + Localization *Localization::Get() + { + if (m_instance != NULL) + { + return m_instance; + } + m_instance = new Localization(); + ReadXML(); + Options::Get()->GetOptionAsString("Language", &m_selectedLang); + return m_instance; + } + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/Localization.h b/cpp/src/Localization.h index 7153a2585b..279f22ae03 100755 --- a/cpp/src/Localization.h +++ b/cpp/src/Localization.h @@ -37,108 +37,112 @@ namespace OpenZWave { - -class LabelLocalizationEntry : public Ref -{ -public: - LabelLocalizationEntry (uint16 _index, uint32 _pos = -1); - ~LabelLocalizationEntry() {} - void AddLabel(string label, string lang = ""); - string GetLabel(string lang); - uint64 GetIdx(); - bool HasLabel(string lang); - -private: - uint16 m_index; - uint32 m_pos; - map m_Label; - string m_defaultLabel; -}; - - -class ValueLocalizationEntry : public Ref -{ -public: - ValueLocalizationEntry ( uint8 _commandClass, uint16 _index, uint32 _pos = -1 ); - ~ValueLocalizationEntry() { - - } - uint64 GetIdx(); - string GetHelp(string lang); - void AddHelp(string HelpText, string lang = ""); - bool HasHelp(string lang); - string GetLabel(string lang); - void AddLabel(string Label, string lang = ""); - bool HasLabel(string lang); - void AddItemLabel(string label, int32 itemIndex, string lang = ""); - string GetItemLabel(string lang, int32 itemIndex); - bool HasItemLabel(int32 itemIndex, string lang); - void AddItemHelp(string label, int32 itemIndex, string lang = ""); - string GetItemHelp(string lang, int32 itemIndex); - bool HasItemHelp(int32 itemIndex, string lang); - - -private: - uint8 m_commandClass; - uint16 m_index; - uint32 m_pos; - map m_HelpText; - map m_LabelText; - map > m_ItemLabelText; - map > m_ItemHelpText; - string m_DefaultHelpText; - string m_DefaultLabelText; - map m_DefaultItemLabelText; - map m_DefaultItemHelpText; -}; - - - -class Localization -{ - //----------------------------------------------------------------------------- - // Construction - //----------------------------------------------------------------------------- -private: - Localization(); - ~Localization(); - - static void ReadXML(); - static void ReadCCXMLLabel(uint8 ccID, const TiXmlElement *labelElement); - static void ReadXMLValue(uint8 ccID, const TiXmlElement *valueElement); - static void ReadXMLVIDItemLabel(uint8 ccID, uint16 indexId, uint32 pos, const TiXmlElement *labelElement); - static void ReadGlobalXMLLabel(const TiXmlElement *labelElement); - static uint64 GetValueKey (uint8 _commandClass, uint16 _index, uint32 _pos = -1); -public: - static Localization* Get(); - void SetupCommandClass(CommandClass *cc); - string GetSelectedLang() { return Localization::m_selectedLang;}; - bool SetValueHelp(uint8 ccID, uint16 indexID, uint32 pos, string help, string lang=""); - string const GetValueHelp(uint8 ccID, uint16 indexId, uint32 pos); - bool SetValueLabel(uint8 ccID, uint16 indexID, uint32 pos, string label, string lang=""); - string const GetValueLabel(uint8 ccID, uint16 indexId, int32 pos) const; - string const GetValueItemLabel(uint8 ccID, uint16 indexId, int32 pos, int32 itemIndex) const; - bool SetValueItemLabel(uint8 ccID, uint16 indexId, int32 pos, int32 itemIndex, string label, string lang=""); - string const GetValueItemHelp(uint8 ccID, uint16 indexId, int32 pos, int32 itemIndex) const; - bool SetValueItemHelp(uint8 ccID, uint16 indexId, int32 pos, int32 itemIndex, string label, string lang=""); - string const GetGlobalLabel(string text); - bool SetGlobalLabel(string index, string text, string lang); - static void ReadXMLVIDLabel(uint8 ccID, uint16 indexId, uint32 pos, const TiXmlElement *labelElement); - static void ReadXMLVIDHelp(uint8 ccID, uint16 indexId, uint32 pos, const TiXmlElement *helpElement); - bool WriteXMLVIDHelp(uint8 ccID, uint16 indexId, uint32 pos, TiXmlElement *valueElement); - //----------------------------------------------------------------------------- - // Instance Functions - //----------------------------------------------------------------------------- -private: - static Localization* m_instance; - static map m_valueLocalizationMap; - static map m_commandClassLocalizationMap; - static map m_globalLabelLocalizationMap; - static string m_selectedLang; - static uint32 m_revision; - - -}; - -}; + namespace Internal + { + + class LabelLocalizationEntry: public Internal::Platform::Ref + { + public: + LabelLocalizationEntry(uint16 _index, uint32 _pos = -1); + ~LabelLocalizationEntry() + { + } + void AddLabel(string label, string lang = ""); + string GetLabel(string lang); + uint64 GetIdx(); + bool HasLabel(string lang); + + private: + uint16 m_index; + uint32 m_pos; + map m_Label; + string m_defaultLabel; + }; + + class ValueLocalizationEntry: public Internal::Platform::Ref + { + public: + ValueLocalizationEntry(uint8 _commandClass, uint16 _index, uint32 _pos = -1); + ~ValueLocalizationEntry() + { + + } + uint64 GetIdx(); + string GetHelp(string lang); + void AddHelp(string HelpText, string lang = ""); + bool HasHelp(string lang); + string GetLabel(string lang); + void AddLabel(string Label, string lang = ""); + bool HasLabel(string lang); + void AddItemLabel(string label, int32 itemIndex, string lang = ""); + string GetItemLabel(string lang, int32 itemIndex); + bool HasItemLabel(int32 itemIndex, string lang); + void AddItemHelp(string label, int32 itemIndex, string lang = ""); + string GetItemHelp(string lang, int32 itemIndex); + bool HasItemHelp(int32 itemIndex, string lang); + + private: + uint8 m_commandClass; + uint16 m_index; + uint32 m_pos; + map m_HelpText; + map m_LabelText; + map > m_ItemLabelText; + map > m_ItemHelpText; + string m_DefaultHelpText; + string m_DefaultLabelText; + map m_DefaultItemLabelText; + map m_DefaultItemHelpText; + }; + + class Localization + { + //----------------------------------------------------------------------------- + // Construction + //----------------------------------------------------------------------------- + private: + Localization(); + ~Localization(); + + static void ReadXML(); + static void ReadCCXMLLabel(uint8 ccID, const TiXmlElement *labelElement); + static void ReadXMLValue(uint8 node, uint8 ccID, const TiXmlElement *valueElement); + static void ReadXMLVIDItemLabel(uint8 node, uint8 ccID, uint16 indexId, uint32 pos, const TiXmlElement *labelElement); + static void ReadGlobalXMLLabel(const TiXmlElement *labelElement); + static uint64 GetValueKey(uint8 _node, uint8 _commandClass, uint16 _index, uint32 _pos, bool unique = false); + public: + static Localization* Get(); + void SetupCommandClass(Internal::CC::CommandClass *cc); + string GetSelectedLang() + { + return Localization::m_selectedLang; + } + ; + bool SetValueHelp(uint8 node, uint8 ccID, uint16 indexID, uint32 pos, string help, string lang = ""); + string const GetValueHelp(uint8 node, uint8 ccID, uint16 indexId, uint32 pos); + bool SetValueLabel(uint8 node, uint8 ccID, uint16 indexID, uint32 pos, string label, string lang = ""); + string const GetValueLabel(uint8 node, uint8 ccID, uint16 indexId, int32 pos) const; + string const GetValueItemLabel(uint8 node, uint8 ccID, uint16 indexId, int32 pos, int32 itemIndex) const; + bool SetValueItemLabel(uint8 node, uint8 ccID, uint16 indexId, int32 pos, int32 itemIndex, string label, string lang = ""); + string const GetValueItemHelp(uint8 node, uint8 ccID, uint16 indexId, int32 pos, int32 itemIndex) const; + bool SetValueItemHelp(uint8 node, uint8 ccID, uint16 indexId, int32 pos, int32 itemIndex, string label, string lang = ""); + string const GetGlobalLabel(string text); + bool SetGlobalLabel(string index, string text, string lang); + static void ReadXMLVIDLabel(uint8 node, uint8 ccID, uint16 indexId, uint32 pos, const TiXmlElement *labelElement); + static void ReadXMLVIDHelp(uint8 node, uint8 ccID, uint16 indexId, uint32 pos, const TiXmlElement *helpElement); + bool WriteXMLVIDHelp(uint8 node, uint8 ccID, uint16 indexId, uint32 pos, TiXmlElement *valueElement); + //----------------------------------------------------------------------------- + // Instance Functions + //----------------------------------------------------------------------------- + private: + static Localization* m_instance; + static map > m_valueLocalizationMap; + static map > m_commandClassLocalizationMap; + static map > m_globalLabelLocalizationMap; + static string m_selectedLang; + static uint32 m_revision; + + }; + } // namespace Internal +} // namespace OpenZWave #endif // VALUEHELP_H diff --git a/cpp/src/Manager.cpp b/cpp/src/Manager.cpp index 7cfcace2d9..f6966b24c0 100644 --- a/cpp/src/Manager.cpp +++ b/cpp/src/Manager.cpp @@ -40,6 +40,7 @@ #include "NotificationCCTypes.h" #include "Options.h" #include "Scene.h" +#include "SensorMultiLevelCCTypes.h" #include "Utils.h" #include "platform/Mutex.h" @@ -79,15 +80,12 @@ extern char ozw_version_string[]; // // Static creation of the singleton //----------------------------------------------------------------------------- -Manager* Manager::Create -( -) +Manager* Manager::Create() { - - if( Options::Get() && Options::Get()->AreLocked() ) + if (Options::Get() && Options::Get()->AreLocked()) { - if( NULL == s_instance ) + if ( NULL == s_instance) { s_instance = new Manager(); } @@ -95,8 +93,8 @@ Manager* Manager::Create } // Options have not been created and locked. - Log::Create( "", false, true, LogLevel_Debug, LogLevel_Debug, LogLevel_None ); - Log::Write( LogLevel_Error, "Options have not been created and locked. Exiting..." ); + Log::Create("", false, true, LogLevel_Debug, LogLevel_Debug, LogLevel_None); + Log::Write(LogLevel_Error, "Options have not been created and locked. Exiting..."); OZW_FATAL_ERROR(OZWException::OZWEXCEPTION_OPTIONS, "Options Not Created and Locked"); return NULL; } @@ -105,9 +103,7 @@ Manager* Manager::Create // // Static method to destroy the singleton. //----------------------------------------------------------------------------- -void Manager::Destroy -( -) +void Manager::Destroy() { delete s_instance; s_instance = NULL; @@ -117,7 +113,8 @@ void Manager::Destroy // // Static method to get the Version of OZW as a string. //----------------------------------------------------------------------------- -std::string Manager::getVersionAsString() { +std::string Manager::getVersionAsString() +{ std::ostringstream versionstream; versionstream << ozw_vers_major << "." << ozw_vers_minor << "." << ozw_vers_revision; return versionstream.str(); @@ -126,16 +123,18 @@ std::string Manager::getVersionAsString() { // // Static method to get the long Version of OZW as a string. //----------------------------------------------------------------------------- -std::string Manager::getVersionLongAsString() { - std::ostringstream versionstream; - versionstream << ozw_version_string; - return versionstream.str(); +std::string Manager::getVersionLongAsString() +{ + std::ostringstream versionstream; + versionstream << ozw_version_string; + return versionstream.str(); } //----------------------------------------------------------------------------- // // Static method to get the Version of OZW. //----------------------------------------------------------------------------- -ozwversion Manager::getVersion() { +ozwversion Manager::getVersion() +{ return version(ozw_vers_major, ozw_vers_minor); } @@ -143,142 +142,140 @@ ozwversion Manager::getVersion() { // // Constructor //----------------------------------------------------------------------------- -Manager::Manager -( -): -m_notificationMutex( new Mutex() ) +Manager::Manager() : + m_notificationMutex(new Internal::Platform::Mutex()) { // Ensure the singleton instance is set s_instance = this; // Create the log file (if enabled) bool logging = false; - Options::Get()->GetOptionAsBool( "Logging", &logging ); + Options::Get()->GetOptionAsBool("Logging", &logging); string userPath = ""; - Options::Get()->GetOptionAsString( "UserPath", &userPath ); + Options::Get()->GetOptionAsString("UserPath", &userPath); string logFileNameBase = "OZW_Log.txt"; - Options::Get()->GetOptionAsString( "LogFileName", &logFileNameBase ); + Options::Get()->GetOptionAsString("LogFileName", &logFileNameBase); bool bAppend = false; - Options::Get()->GetOptionAsBool( "AppendLogFile", &bAppend ); + Options::Get()->GetOptionAsBool("AppendLogFile", &bAppend); bool bConsoleOutput = true; - Options::Get()->GetOptionAsBool( "ConsoleOutput", &bConsoleOutput ); + Options::Get()->GetOptionAsBool("ConsoleOutput", &bConsoleOutput); int nSaveLogLevel = (int) LogLevel_Detail; - Options::Get()->GetOptionAsInt( "SaveLogLevel", &nSaveLogLevel ); - if ((nSaveLogLevel == 0) || (nSaveLogLevel > LogLevel_StreamDetail)) { + Options::Get()->GetOptionAsInt("SaveLogLevel", &nSaveLogLevel); + if ((nSaveLogLevel == 0) || (nSaveLogLevel > LogLevel_StreamDetail)) + { Log::Write(LogLevel_Warning, "Invalid LogLevel Specified for SaveLogLevel in Options.xml"); nSaveLogLevel = (int) LogLevel_Detail; } int nQueueLogLevel = (int) LogLevel_Debug; - Options::Get()->GetOptionAsInt( "QueueLogLevel", &nQueueLogLevel ); - if ((nQueueLogLevel == 0) || (nQueueLogLevel > LogLevel_StreamDetail)) { + Options::Get()->GetOptionAsInt("QueueLogLevel", &nQueueLogLevel); + if ((nQueueLogLevel == 0) || (nQueueLogLevel > LogLevel_StreamDetail)) + { Log::Write(LogLevel_Warning, "Invalid LogLevel Specified for QueueLogLevel in Options.xml"); nQueueLogLevel = (int) LogLevel_Debug; } int nDumpTrigger = (int) LogLevel_Warning; - Options::Get()->GetOptionAsInt( "DumpTriggerLevel", &nDumpTrigger ); + Options::Get()->GetOptionAsInt("DumpTriggerLevel", &nDumpTrigger); string logFilename = userPath + logFileNameBase; - Log::Create( logFilename, bAppend, bConsoleOutput, (LogLevel) nSaveLogLevel, (LogLevel) nQueueLogLevel, (LogLevel) nDumpTrigger ); - Log::SetLoggingState( logging ); + Log::Create(logFilename, bAppend, bConsoleOutput, (LogLevel) nSaveLogLevel, (LogLevel) nQueueLogLevel, (LogLevel) nDumpTrigger); + Log::SetLoggingState(logging); - CommandClasses::RegisterCommandClasses(); - Scene::ReadScenes(); + Internal::CC::CommandClasses::RegisterCommandClasses(); + Internal::Scene::ReadScenes(); // petergebruers replace getVersionAsString() with getVersionLongAsString() because // the latter prints more information, based on the status of the repository // when "make" was run. A Makefile gets this info from git describe --long --tags --dirty Log::Write(LogLevel_Always, "OpenZwave Version %s Starting Up", getVersionLongAsString().c_str()); - Log::Write(LogLevel_Always, "Using Language Localization %s", Localization::Get()->GetSelectedLang().c_str()); - NotificationCCTypes::Create(); - + Log::Write(LogLevel_Always, "Using Language Localization %s", Internal::Localization::Get()->GetSelectedLang().c_str()); + Internal::NotificationCCTypes::Create(); + Internal::SensorMultiLevelCCTypes::Create(); } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -Manager::~Manager -( -) +Manager::~Manager() { // Clear the pending list - while( !m_pendingDrivers.empty() ) + while (!m_pendingDrivers.empty()) { list::iterator it = m_pendingDrivers.begin(); - delete *it; - m_pendingDrivers.erase( it ); + delete *it; + m_pendingDrivers.erase(it); } m_pendingDrivers.clear(); // Clear the ready map - while( !m_readyDrivers.empty() ) + while (!m_readyDrivers.empty()) { - map::iterator it = m_readyDrivers.begin(); + map::iterator it = m_readyDrivers.begin(); delete it->second; - m_readyDrivers.erase( it ); + m_readyDrivers.erase(it); } m_readyDrivers.clear(); m_notificationMutex->Release(); // Clear the watchers list - while( !m_watchers.empty() ) + while (!m_watchers.empty()) { list::iterator it = m_watchers.begin(); delete *it; - m_watchers.erase( it ); + m_watchers.erase(it); } m_watchers.clear(); // Clear the generic device class list - while( !Node::s_genericDeviceClasses.empty() ) + while (!Node::s_genericDeviceClasses.empty()) { - map::iterator git = Node::s_genericDeviceClasses.begin(); - delete git->second; - Node::s_genericDeviceClasses.erase( git ); + map::iterator git = Node::s_genericDeviceClasses.begin(); + delete git->second; + Node::s_genericDeviceClasses.erase(git); } Node::s_genericDeviceClasses.clear(); + while (!Node::s_basicDeviceClasses.empty()) + { + map::iterator git = Node::s_basicDeviceClasses.begin(); + Node::s_basicDeviceClasses.erase(git); + } + Node::s_basicDeviceClasses.clear(); + + while (!Node::s_roleDeviceClasses.empty()) + { + map::iterator git = Node::s_roleDeviceClasses.begin(); + delete git->second; + Node::s_roleDeviceClasses.erase(git); + } + Node::s_roleDeviceClasses.clear(); + + while (!Node::s_deviceTypeClasses.empty()) + { + map::iterator git = Node::s_deviceTypeClasses.begin(); + delete git->second; + Node::s_deviceTypeClasses.erase(git); + } + Node::s_deviceTypeClasses.clear(); - while ( !Node::s_basicDeviceClasses.empty() ) - { - map::iterator git = Node::s_basicDeviceClasses.begin(); - Node::s_basicDeviceClasses.erase(git); - } - Node::s_basicDeviceClasses.clear(); - - - while ( !Node::s_roleDeviceClasses.empty() ) - { - map::iterator git = Node::s_roleDeviceClasses.begin(); - delete git->second; - Node::s_roleDeviceClasses.erase(git); - } - Node::s_roleDeviceClasses.clear(); - - while ( !Node::s_deviceTypeClasses.empty() ) - { - map::iterator git = Node::s_deviceTypeClasses.begin(); - delete git->second; - Node::s_deviceTypeClasses.erase(git); - } - Node::s_deviceTypeClasses.clear(); - - while ( !Node::s_nodeTypes.empty() ) - { - map::iterator git = Node::s_nodeTypes.begin(); - delete git->second; - Node::s_nodeTypes.erase(git); - } - Node::s_nodeTypes.clear(); + while (!Node::s_nodeTypes.empty()) + { + map::iterator git = Node::s_nodeTypes.begin(); + delete git->second; + Node::s_nodeTypes.erase(git); + } + Node::s_nodeTypes.clear(); + Node::s_deviceClassesLoaded = false; + Log::Destroy(); } @@ -290,21 +287,18 @@ Manager::~Manager // // Save the configuration of a driver to a file //----------------------------------------------------------------------------- -void Manager::WriteConfig -( - uint32 const _homeId -) +void Manager::WriteConfig(uint32 const _homeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { driver->WriteCache(); - Log::Write( LogLevel_Info, "mgr, Manager::WriteConfig completed for driver with home ID of 0x%.8x", _homeId ); + Log::Write(LogLevel_Info, "mgr, Manager::WriteConfig completed for driver with home ID of 0x%.8x", _homeId); } else { - Log::Write( LogLevel_Info, "mgr, Manager::WriteConfig failed - _homeId %d not found", _homeId ); + Log::Write(LogLevel_Info, "mgr, Manager::WriteConfig failed - _homeId %d not found", _homeId); } - Scene::WriteXML( "zwscene.xml" ); + Internal::Scene::WriteXML("zwscene.xml"); } //----------------------------------------------------------------------------- @@ -315,39 +309,35 @@ void Manager::WriteConfig // // Add a new Z-Wave PC Interface //----------------------------------------------------------------------------- -bool Manager::AddDriver -( - string const& _controllerPath, - Driver::ControllerInterface const& _interface -) +bool Manager::AddDriver(string const& _controllerPath, Driver::ControllerInterface const& _interface) { // Make sure we don't already have a driver for this controller // Search the pending list - for( list::iterator pit = m_pendingDrivers.begin(); pit != m_pendingDrivers.end(); ++pit ) + for (list::iterator pit = m_pendingDrivers.begin(); pit != m_pendingDrivers.end(); ++pit) { - if( _controllerPath == (*pit)->GetControllerPath() ) + if (_controllerPath == (*pit)->GetControllerPath()) { - Log::Write( LogLevel_Info, "mgr, Cannot add driver for controller %s - driver already exists", _controllerPath.c_str() ); + Log::Write(LogLevel_Info, "mgr, Cannot add driver for controller %s - driver already exists", _controllerPath.c_str()); return false; } } // Search the ready map - for( map::iterator rit = m_readyDrivers.begin(); rit != m_readyDrivers.end(); ++rit ) + for (map::iterator rit = m_readyDrivers.begin(); rit != m_readyDrivers.end(); ++rit) { - if( _controllerPath == rit->second->GetControllerPath() ) + if (_controllerPath == rit->second->GetControllerPath()) { - Log::Write( LogLevel_Info, "mgr, Cannot add driver for controller %s - driver already exists", _controllerPath.c_str() ); + Log::Write(LogLevel_Info, "mgr, Cannot add driver for controller %s - driver already exists", _controllerPath.c_str()); return false; } } - Driver* driver = new Driver( _controllerPath, _interface ); - m_pendingDrivers.push_back( driver ); + Driver* driver = new Driver(_controllerPath, _interface); + m_pendingDrivers.push_back(driver); driver->Start(); - Log::Write( LogLevel_Info, "mgr, Added driver for controller %s", _controllerPath.c_str() ); + Log::Write(LogLevel_Info, "mgr, Added driver for controller %s", _controllerPath.c_str()); return true; } @@ -355,27 +345,24 @@ bool Manager::AddDriver // // Remove a Z-Wave PC Interface //----------------------------------------------------------------------------- -bool Manager::RemoveDriver -( - string const& _controllerPath -) +bool Manager::RemoveDriver(string const& _controllerPath) { // Search the pending list - for( list::iterator pit = m_pendingDrivers.begin(); pit != m_pendingDrivers.end(); ++pit ) + for (list::iterator pit = m_pendingDrivers.begin(); pit != m_pendingDrivers.end(); ++pit) { - if( _controllerPath == (*pit)->GetControllerPath() ) + if (_controllerPath == (*pit)->GetControllerPath()) { delete *pit; - m_pendingDrivers.erase( pit ); - Log::Write( LogLevel_Info, "mgr, Driver for controller %s removed", _controllerPath.c_str() ); + m_pendingDrivers.erase(pit); + Log::Write(LogLevel_Info, "mgr, Driver for controller %s removed", _controllerPath.c_str()); return true; } } // Search the ready map - for( map::iterator rit = m_readyDrivers.begin(); rit != m_readyDrivers.end(); ++rit ) + for (map::iterator rit = m_readyDrivers.begin(); rit != m_readyDrivers.end(); ++rit) { - if( _controllerPath == rit->second->GetControllerPath() ) + if (_controllerPath == rit->second->GetControllerPath()) { /* data race right here: * Before, we were deleting the Driver Class direct from the Map... this was causing a datarace: @@ -390,15 +377,15 @@ bool Manager::RemoveDriver * But we can't change this, as the Driver Destructor triggers internal GetDriver calls... which * will crash and burn if they can't get a valid Driver back... */ - Log::Write( LogLevel_Info, "mgr, Driver for controller %s pending removal", _controllerPath.c_str() ); + Log::Write(LogLevel_Info, "mgr, Driver for controller %s pending removal", _controllerPath.c_str()); delete rit->second; - m_readyDrivers.erase( rit ); - Log::Write( LogLevel_Info, "mgr, Driver for controller %s removed", _controllerPath.c_str() ); + m_readyDrivers.erase(rit); + Log::Write(LogLevel_Info, "mgr, Driver for controller %s removed", _controllerPath.c_str()); return true; } } - Log::Write( LogLevel_Info, "mgr, Failed to remove driver for controller %s", _controllerPath.c_str() ); + Log::Write(LogLevel_Info, "mgr, Failed to remove driver for controller %s", _controllerPath.c_str()); return false; } @@ -406,18 +393,15 @@ bool Manager::RemoveDriver // // Get a pointer to the driver for a Z-Wave PC Interface //----------------------------------------------------------------------------- -Driver* Manager::GetDriver -( - uint32 const _homeId -) +Driver* Manager::GetDriver(uint32 const _homeId) { - map::iterator it = m_readyDrivers.find( _homeId ); - if( it != m_readyDrivers.end() ) + map::iterator it = m_readyDrivers.find(_homeId); + if (it != m_readyDrivers.end()) { return it->second; } - Log::Write( LogLevel_Error, "mgr, Manager::GetDriver failed - Home ID 0x%.8x is unknown", _homeId ); + Log::Write(LogLevel_Error, "mgr, Manager::GetDriver failed - Home ID 0x%.8x is unknown", _homeId); OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_HOMEID, "Invalid HomeId passed to GetDriver"); //assert(0); << Don't assert as this might be a valid condition when we call RemoveDriver. See comments above. return NULL; @@ -427,43 +411,39 @@ Driver* Manager::GetDriver // // Move a driver from pending to ready, and notify any watchers //----------------------------------------------------------------------------- -void Manager::SetDriverReady -( - Driver* _driver, - bool success -) +void Manager::SetDriverReady(Driver* _driver, bool success) { // Search the pending list bool found = false; - for( list::iterator it = m_pendingDrivers.begin(); it != m_pendingDrivers.end(); ++it ) + for (list::iterator it = m_pendingDrivers.begin(); it != m_pendingDrivers.end(); ++it) { - if( (*it) == _driver ) + if ((*it) == _driver) { // Remove the driver from the pending list - m_pendingDrivers.erase( it ); + m_pendingDrivers.erase(it); found = true; break; } } - if( found ) + if (found) { - if (success) { - Log::Write( LogLevel_Info, "mgr, Driver with Home ID of 0x%.8x is now ready.", _driver->GetHomeId() ); - Log::Write( LogLevel_Info, "" ); + if (success) + { + Log::Write(LogLevel_Info, "mgr, Driver with Home ID of 0x%.8x is now ready.", _driver->GetHomeId()); + Log::Write(LogLevel_Info, ""); // Add the driver to the ready map m_readyDrivers[_driver->GetHomeId()] = _driver; } - // Notify the watchers - Notification* notification = new Notification(success ? Notification::Type_DriverReady : Notification::Type_DriverFailed ); - notification->SetHomeAndNodeIds( _driver->GetHomeId(), _driver->GetControllerNodeId() ); + Notification* notification = new Notification(success ? Notification::Type_DriverReady : Notification::Type_DriverFailed); + notification->SetHomeAndNodeIds(_driver->GetHomeId(), _driver->GetControllerNodeId()); if (!success) notification->SetComPort(_driver->GetControllerPath()); - _driver->QueueNotification( notification ); + _driver->QueueNotification(notification); } } @@ -471,17 +451,14 @@ void Manager::SetDriverReady // // //----------------------------------------------------------------------------- -uint8 Manager::GetControllerNodeId -( - uint32 const _homeId -) +uint8 Manager::GetControllerNodeId(uint32 const _homeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { return driver->GetControllerNodeId(); } - Log::Write( LogLevel_Info, "mgr, GetControllerNodeId() failed - _homeId %d not found", _homeId ); + Log::Write(LogLevel_Info, "mgr, GetControllerNodeId() failed - _homeId %d not found", _homeId); return 0xff; } @@ -489,17 +466,14 @@ uint8 Manager::GetControllerNodeId // // //----------------------------------------------------------------------------- -uint8 Manager::GetSUCNodeId -( - uint32 const _homeId -) +uint8 Manager::GetSUCNodeId(uint32 const _homeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { return driver->GetSUCNodeId(); } - Log::Write( LogLevel_Info, "mgr, GetSUCNodeId() failed - _homeId %d not found", _homeId ); + Log::Write(LogLevel_Info, "mgr, GetSUCNodeId() failed - _homeId %d not found", _homeId); return 0xff; } @@ -507,17 +481,14 @@ uint8 Manager::GetSUCNodeId // // //----------------------------------------------------------------------------- -bool Manager::IsPrimaryController -( - uint32 const _homeId -) +bool Manager::IsPrimaryController(uint32 const _homeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { return driver->IsPrimaryController(); } - Log::Write( LogLevel_Info, "mgr, IsPrimaryController() failed - _homeId %d not found", _homeId ); + Log::Write(LogLevel_Info, "mgr, IsPrimaryController() failed - _homeId %d not found", _homeId); return false; } @@ -525,17 +496,14 @@ bool Manager::IsPrimaryController // // //----------------------------------------------------------------------------- -bool Manager::IsStaticUpdateController -( - uint32 const _homeId -) +bool Manager::IsStaticUpdateController(uint32 const _homeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { return driver->IsStaticUpdateController(); } - Log::Write( LogLevel_Info, "mgr, IsStaticUpdateController() failed - _homeId %d not found", _homeId ); + Log::Write(LogLevel_Info, "mgr, IsStaticUpdateController() failed - _homeId %d not found", _homeId); return false; } @@ -543,17 +511,14 @@ bool Manager::IsStaticUpdateController // // //----------------------------------------------------------------------------- -bool Manager::IsBridgeController -( - uint32 const _homeId -) +bool Manager::IsBridgeController(uint32 const _homeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { return driver->IsBridgeController(); } - Log::Write( LogLevel_Info, "mgr, IsBridgeController() failed - _homeId %d not found", _homeId ); + Log::Write(LogLevel_Info, "mgr, IsBridgeController() failed - _homeId %d not found", _homeId); return false; } @@ -561,17 +526,14 @@ bool Manager::IsBridgeController // // //----------------------------------------------------------------------------- -bool Manager::HasExtendedTxStatus -( - uint32 const _homeId -) +bool Manager::HasExtendedTxStatus(uint32 const _homeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { return driver->HasExtendedTxStatus(); } - Log::Write( LogLevel_Info, "mgr, HasExtendedTxStatus() failed - _homeId %d not found", _homeId ); + Log::Write(LogLevel_Info, "mgr, HasExtendedTxStatus() failed - _homeId %d not found", _homeId); return false; } @@ -579,17 +541,14 @@ bool Manager::HasExtendedTxStatus // // //----------------------------------------------------------------------------- -string Manager::GetLibraryVersion -( - uint32 const _homeId -) +string Manager::GetLibraryVersion(uint32 const _homeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { return driver->GetLibraryVersion(); } - Log::Write( LogLevel_Info, "mgr, GetLibraryVersion() failed - _homeId %d not found", _homeId ); + Log::Write(LogLevel_Info, "mgr, GetLibraryVersion() failed - _homeId %d not found", _homeId); return ""; } @@ -597,17 +556,14 @@ string Manager::GetLibraryVersion // // //----------------------------------------------------------------------------- -string Manager::GetLibraryTypeName -( - uint32 const _homeId -) +string Manager::GetLibraryTypeName(uint32 const _homeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { return driver->GetLibraryTypeName(); } - Log::Write( LogLevel_Info, "mgr, GetLibraryTypeName() failed - _homeId %d not found", _homeId ); + Log::Write(LogLevel_Info, "mgr, GetLibraryTypeName() failed - _homeId %d not found", _homeId); return ""; } @@ -615,17 +571,14 @@ string Manager::GetLibraryTypeName // // //----------------------------------------------------------------------------- -int32 Manager::GetSendQueueCount -( - uint32 const _homeId -) +int32 Manager::GetSendQueueCount(uint32 const _homeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { return driver->GetSendQueueCount(); } - Log::Write( LogLevel_Info, "mgr, GetSendQueueCount() failed - _homeId %d not found", _homeId ); + Log::Write(LogLevel_Info, "mgr, GetSendQueueCount() failed - _homeId %d not found", _homeId); return -1; } @@ -633,30 +586,24 @@ int32 Manager::GetSendQueueCount // // Send driver statistics to the log file //----------------------------------------------------------------------------- -void Manager::LogDriverStatistics -( - uint32 const _homeId -) +void Manager::LogDriverStatistics(uint32 const _homeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { return driver->LogDriverStatistics(); } - Log::Write( LogLevel_Warning, "mgr, LogDriverStatistics() failed - _homeId %d not found", _homeId ); + Log::Write(LogLevel_Warning, "mgr, LogDriverStatistics() failed - _homeId %d not found", _homeId); } //----------------------------------------------------------------------------- // // Retrieve controller interface type //----------------------------------------------------------------------------- -Driver::ControllerInterface Manager::GetControllerInterfaceType -( - uint32 const _homeId -) +Driver::ControllerInterface Manager::GetControllerInterfaceType(uint32 const _homeId) { Driver::ControllerInterface ifType = Driver::ControllerInterface_Unknown; - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { ifType = driver->GetControllerInterfaceType(); } @@ -667,13 +614,10 @@ Driver::ControllerInterface Manager::GetControllerInterfaceType // // Retrieve controller interface path //----------------------------------------------------------------------------- -string Manager::GetControllerPath -( - uint32 const _homeId -) +string Manager::GetControllerPath(uint32 const _homeId) { string path = ""; - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { path = driver->GetControllerPath(); } @@ -687,15 +631,13 @@ string Manager::GetControllerPath // // Return the polling interval //----------------------------------------------------------------------------- -int32 Manager::GetPollInterval -( -) +int32 Manager::GetPollInterval() { - for( map::iterator rit = m_readyDrivers.begin(); rit != m_readyDrivers.end(); ++rit ) + for (map::iterator rit = m_readyDrivers.begin(); rit != m_readyDrivers.end(); ++rit) { return rit->second->GetPollInterval(); } - for( list::iterator pit = m_pendingDrivers.begin(); pit != m_pendingDrivers.end(); ++pit ) + for (list::iterator pit = m_pendingDrivers.begin(); pit != m_pendingDrivers.end(); ++pit) { return (*pit)->GetPollInterval(); } @@ -707,20 +649,16 @@ int32 Manager::GetPollInterval // // Set the polling interval on all drivers //----------------------------------------------------------------------------- -void Manager::SetPollInterval -( - int32 _milliseconds, - bool _bIntervalBetweenPolls -) +void Manager::SetPollInterval(int32 _milliseconds, bool _bIntervalBetweenPolls) { - for( list::iterator pit = m_pendingDrivers.begin(); pit != m_pendingDrivers.end(); ++pit ) + for (list::iterator pit = m_pendingDrivers.begin(); pit != m_pendingDrivers.end(); ++pit) { - (*pit)->SetPollInterval( _milliseconds, _bIntervalBetweenPolls ); + (*pit)->SetPollInterval(_milliseconds, _bIntervalBetweenPolls); } - for( map::iterator rit = m_readyDrivers.begin(); rit != m_readyDrivers.end(); ++rit ) + for (map::iterator rit = m_readyDrivers.begin(); rit != m_readyDrivers.end(); ++rit) { - rit->second->SetPollInterval( _milliseconds, _bIntervalBetweenPolls ); + rit->second->SetPollInterval(_milliseconds, _bIntervalBetweenPolls); } } @@ -728,18 +666,14 @@ void Manager::SetPollInterval // // Enable polling of a value //----------------------------------------------------------------------------- -bool Manager::EnablePoll -( - ValueID const &_valueId, - uint8 const _intensity -) +bool Manager::EnablePoll(ValueID const &_valueId, uint8 const _intensity) { - if( Driver* driver = GetDriver( _valueId.GetHomeId() ) ) + if (Driver* driver = GetDriver(_valueId.GetHomeId())) { - return( driver->EnablePoll( _valueId, _intensity ) ); + return (driver->EnablePoll(_valueId, _intensity)); } - Log::Write( LogLevel_Info, "mgr, EnablePoll failed - Driver with Home ID 0x%.8x is not available", _valueId.GetHomeId() ); + Log::Write(LogLevel_Info, "mgr, EnablePoll failed - Driver with Home ID 0x%.8x is not available", _valueId.GetHomeId()); return false; } @@ -747,17 +681,14 @@ bool Manager::EnablePoll // // Disable polling of a value //----------------------------------------------------------------------------- -bool Manager::DisablePoll -( - ValueID const &_valueId -) +bool Manager::DisablePoll(ValueID const &_valueId) { - if( Driver* driver = GetDriver( _valueId.GetHomeId() ) ) + if (Driver* driver = GetDriver(_valueId.GetHomeId())) { - return( driver->DisablePoll( _valueId ) ); + return (driver->DisablePoll(_valueId)); } - Log::Write( LogLevel_Info, "mgr, DisablePoll failed - Driver with Home ID 0x%.8x is not available", _valueId.GetHomeId() ); + Log::Write(LogLevel_Info, "mgr, DisablePoll failed - Driver with Home ID 0x%.8x is not available", _valueId.GetHomeId()); return false; } @@ -765,17 +696,14 @@ bool Manager::DisablePoll // // Check polling status of a value //----------------------------------------------------------------------------- -bool Manager::isPolled -( - ValueID const &_valueId -) +bool Manager::isPolled(ValueID const &_valueId) { - if( Driver* driver = GetDriver( _valueId.GetHomeId() ) ) + if (Driver* driver = GetDriver(_valueId.GetHomeId())) { - return( driver->isPolled( _valueId ) ); + return (driver->isPolled(_valueId)); } - Log::Write( LogLevel_Info, "mgr, isPolled failed - Driver with Home ID 0x%.8x is not available", _valueId.GetHomeId() ); + Log::Write(LogLevel_Info, "mgr, isPolled failed - Driver with Home ID 0x%.8x is not available", _valueId.GetHomeId()); return false; } @@ -783,38 +711,33 @@ bool Manager::isPolled // // Change the intensity with which this value is polled //----------------------------------------------------------------------------- -void Manager::SetPollIntensity -( - ValueID const &_valueId, - uint8 const _intensity -) +void Manager::SetPollIntensity(ValueID const &_valueId, uint8 const _intensity) { - if( Driver* driver = GetDriver( _valueId.GetHomeId() ) ) + if (Driver* driver = GetDriver(_valueId.GetHomeId())) { - return( driver->SetPollIntensity( _valueId, _intensity ) ); + return (driver->SetPollIntensity(_valueId, _intensity)); } - Log::Write( LogLevel_Error, "mgr, SetPollIntensity failed - Driver with Home ID 0x%.8x is not available", _valueId.GetHomeId() ); + Log::Write(LogLevel_Error, "mgr, SetPollIntensity failed - Driver with Home ID 0x%.8x is not available", _valueId.GetHomeId()); } //----------------------------------------------------------------------------- // // Change the intensity with which this value is polled //----------------------------------------------------------------------------- -uint8 Manager::GetPollIntensity -( - ValueID const &_valueId -) +uint8 Manager::GetPollIntensity(ValueID const &_valueId) { uint8 intensity = 0; - if( Driver* driver = GetDriver( _valueId.GetHomeId() ) ) + if (Driver* driver = GetDriver(_valueId.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( Value* value = driver->GetValue( _valueId ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::Value* value = driver->GetValue(_valueId)) { intensity = value->GetPollIntensity(); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetPollIntensity"); } } @@ -830,17 +753,13 @@ uint8 Manager::GetPollIntensity // // Fetch the data for a node from the Z-Wave network //----------------------------------------------------------------------------- -bool Manager::RefreshNodeInfo -( - uint32 const _homeId, - uint8 const _nodeId -) +bool Manager::RefreshNodeInfo(uint32 const _homeId, uint8 const _nodeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { // Cause the node's data to be obtained from the Z-Wave network // in the same way as if it had just been added. - LockGuard LG(driver->m_nodeMutex); + Internal::LockGuard LG(driver->m_nodeMutex); driver->ReloadNode(_nodeId); return true; } @@ -852,20 +771,16 @@ bool Manager::RefreshNodeInfo // // Fetch the command class data for a node from the Z-Wave network //----------------------------------------------------------------------------- -bool Manager::RequestNodeState -( - uint32 const _homeId, - uint8 const _nodeId -) +bool Manager::RequestNodeState(uint32 const _homeId, uint8 const _nodeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - LockGuard LG(driver->m_nodeMutex); + Internal::LockGuard LG(driver->m_nodeMutex); // Retreive the Node's session and dynamic data - Node* node = driver->GetNode( _nodeId ); - if( node ) + Node* node = driver->GetNode(_nodeId); + if (node) { - node->SetQueryStage( Node::QueryStage_Associations ); + node->SetQueryStage(Node::QueryStage_Associations); return true; } } @@ -876,20 +791,16 @@ bool Manager::RequestNodeState // // Fetch only the dynamic command class data for a node from the Z-Wave network //----------------------------------------------------------------------------- -bool Manager::RequestNodeDynamic -( - uint32 const _homeId, - uint8 const _nodeId -) +bool Manager::RequestNodeDynamic(uint32 const _homeId, uint8 const _nodeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - LockGuard LG(driver->m_nodeMutex); + Internal::LockGuard LG(driver->m_nodeMutex); // Retreive the Node's dynamic data - Node* node = driver->GetNode( _nodeId ); - if( node ) + Node* node = driver->GetNode(_nodeId); + if (node) { - node->SetQueryStage( Node::QueryStage_Dynamic ); + node->SetQueryStage(Node::QueryStage_Dynamic); return true; } } @@ -900,16 +811,12 @@ bool Manager::RequestNodeDynamic // // Get whether the node is a listening device that does not go to sleep //----------------------------------------------------------------------------- -bool Manager::IsNodeListeningDevice -( - uint32 const _homeId, - uint8 const _nodeId -) +bool Manager::IsNodeListeningDevice(uint32 const _homeId, uint8 const _nodeId) { bool res = false; - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - res = driver->IsNodeListeningDevice( _nodeId ); + res = driver->IsNodeListeningDevice(_nodeId); } return res; @@ -919,16 +826,12 @@ bool Manager::IsNodeListeningDevice // // Get whether the node is a listening device that does not go to sleep //----------------------------------------------------------------------------- -bool Manager::IsNodeFrequentListeningDevice -( - uint32 const _homeId, - uint8 const _nodeId -) +bool Manager::IsNodeFrequentListeningDevice(uint32 const _homeId, uint8 const _nodeId) { bool res = false; - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - res = driver->IsNodeFrequentListeningDevice( _nodeId ); + res = driver->IsNodeFrequentListeningDevice(_nodeId); } return res; @@ -938,16 +841,12 @@ bool Manager::IsNodeFrequentListeningDevice // // Get whether the node is a beam capable device. //----------------------------------------------------------------------------- -bool Manager::IsNodeBeamingDevice -( - uint32 const _homeId, - uint8 const _nodeId -) +bool Manager::IsNodeBeamingDevice(uint32 const _homeId, uint8 const _nodeId) { bool res = false; - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - res = driver->IsNodeBeamingDevice( _nodeId ); + res = driver->IsNodeBeamingDevice(_nodeId); } return res; @@ -957,16 +856,12 @@ bool Manager::IsNodeBeamingDevice // // Get whether the node is a routing device that passes messages to other nodes //----------------------------------------------------------------------------- -bool Manager::IsNodeRoutingDevice -( - uint32 const _homeId, - uint8 const _nodeId -) +bool Manager::IsNodeRoutingDevice(uint32 const _homeId, uint8 const _nodeId) { bool res = false; - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - res = driver->IsNodeRoutingDevice( _nodeId ); + res = driver->IsNodeRoutingDevice(_nodeId); } return res; @@ -976,16 +871,12 @@ bool Manager::IsNodeRoutingDevice // // Get the security attribute for a node. //----------------------------------------------------------------------------- -bool Manager::IsNodeSecurityDevice -( - uint32 const _homeId, - uint8 const _nodeId -) +bool Manager::IsNodeSecurityDevice(uint32 const _homeId, uint8 const _nodeId) { bool security = 0; - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - security = driver->IsNodeSecurityDevice( _nodeId ); + security = driver->IsNodeSecurityDevice(_nodeId); } return security; @@ -995,16 +886,12 @@ bool Manager::IsNodeSecurityDevice // // Get the maximum baud rate of a node's communications //----------------------------------------------------------------------------- -uint32 Manager::GetNodeMaxBaudRate -( - uint32 const _homeId, - uint8 const _nodeId -) +uint32 Manager::GetNodeMaxBaudRate(uint32 const _homeId, uint8 const _nodeId) { uint32 baud = 0; - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - baud = driver->GetNodeMaxBaudRate( _nodeId ); + baud = driver->GetNodeMaxBaudRate(_nodeId); } return baud; @@ -1014,16 +901,12 @@ uint32 Manager::GetNodeMaxBaudRate // // Get the version number of a node //----------------------------------------------------------------------------- -uint8 Manager::GetNodeVersion -( - uint32 const _homeId, - uint8 const _nodeId -) +uint8 Manager::GetNodeVersion(uint32 const _homeId, uint8 const _nodeId) { uint8 version = 0; - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - version = driver->GetNodeVersion( _nodeId ); + version = driver->GetNodeVersion(_nodeId); } return version; @@ -1033,116 +916,132 @@ uint8 Manager::GetNodeVersion // // Get the security byte of a node //----------------------------------------------------------------------------- -uint8 Manager::GetNodeSecurity -( - uint32 const _homeId, - uint8 const _nodeId -) +uint8 Manager::GetNodeSecurity(uint32 const _homeId, uint8 const _nodeId) { uint8 version = 0; - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - version = driver->GetNodeSecurity( _nodeId ); + version = driver->GetNodeSecurity(_nodeId); } return version; } - //----------------------------------------------------------------------------- // // Get if the Node is a ZWave Plus Supported Node //----------------------------------------------------------------------------- -bool Manager::IsNodeZWavePlus -( - uint32 const _homeId, - uint8 const _nodeId -) +bool Manager::IsNodeZWavePlus(uint32 const _homeId, uint8 const _nodeId) { bool version = false; - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - version = driver->IsNodeZWavePlus( _nodeId ); + version = driver->IsNodeZWavePlus(_nodeId); } return version; } - - //----------------------------------------------------------------------------- // // Get the basic type of a node //----------------------------------------------------------------------------- -uint8 Manager::GetNodeBasic -( - uint32 const _homeId, - uint8 const _nodeId -) +uint8 Manager::GetNodeBasic(uint32 const _homeId, uint8 const _nodeId) { uint8 basic = 0; - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - basic = driver->GetNodeBasic( _nodeId ); + basic = driver->GetNodeBasic(_nodeId); } return basic; } +//----------------------------------------------------------------------------- +// +// Get the basic type of a node +//----------------------------------------------------------------------------- +string Manager::GetNodeBasicString(uint32 const _homeId, uint8 const _nodeId) +{ + if (Driver* driver = GetDriver(_homeId)) + { + return driver->GetNodeBasicString(_nodeId); + } + + return "Unknown"; +} + + //----------------------------------------------------------------------------- // // Get the generic type of a node //----------------------------------------------------------------------------- -uint8 Manager::GetNodeGeneric -( - uint32 const _homeId, - uint8 const _nodeId -) +uint8 Manager::GetNodeGeneric(uint32 const _homeId, uint8 const _nodeId, uint8 const _instance) { uint8 genericType = 0; - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - genericType = driver->GetNodeGeneric( _nodeId ); + genericType = driver->GetNodeGeneric(_nodeId, _instance); } return genericType; } +//----------------------------------------------------------------------------- +// +// Get the generic type of a node +//----------------------------------------------------------------------------- + +string Manager::GetNodeGenericString(uint32 const _homeId, uint8 const _nodeId, uint8 const _instance) +{ + if (Driver *driver = GetDriver(_homeId)) + { + return driver->GetNodeGenericString(_nodeId, _instance); + } + return "Unknown"; +} + //----------------------------------------------------------------------------- // // Get the specific type of a node //----------------------------------------------------------------------------- -uint8 Manager::GetNodeSpecific -( - uint32 const _homeId, - uint8 const _nodeId -) +uint8 Manager::GetNodeSpecific(uint32 const _homeId, uint8 const _nodeId, uint8 const _instance) { uint8 specific = 0; - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - specific = driver->GetNodeSpecific( _nodeId ); + specific = driver->GetNodeSpecific(_nodeId, _instance); } return specific; } +//----------------------------------------------------------------------------- +// +// Get the specific type of a node +//----------------------------------------------------------------------------- +string Manager::GetNodeSpecificString(uint32 const _homeId, uint8 const _nodeId, uint8 const _instance) +{ + if (Driver* driver = GetDriver(_homeId)) + { + return driver->GetNodeSpecificString(_nodeId, _instance); + } + + return "Unknown"; +} + //----------------------------------------------------------------------------- // // Get a string describing the type of a node //----------------------------------------------------------------------------- -string Manager::GetNodeType -( - uint32 const _homeId, - uint8 const _nodeId -) +string Manager::GetNodeType(uint32 const _homeId, uint8 const _nodeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { if (driver->IsNodeZWavePlus(_nodeId)) return driver->GetNodeDeviceTypeString(_nodeId); else - return driver->GetNodeType( _nodeId ); + return driver->GetNodeType(_nodeId); } return "Unknown"; @@ -1152,34 +1051,40 @@ string Manager::GetNodeType // // Get the bitmap of this node's neighbors //----------------------------------------------------------------------------- -uint32 Manager::GetNodeNeighbors -( - uint32 const _homeId, - uint8 const _nodeId, - uint8** o_neighbors -) +uint32 Manager::GetNodeNeighbors(uint32 const _homeId, uint8 const _nodeId, uint8** o_neighbors) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - return driver->GetNodeNeighbors( _nodeId, o_neighbors ); + return driver->GetNodeNeighbors(_nodeId, o_neighbors); } return 0; } +//----------------------------------------------------------------------------- +// +// Syncronise OZW's copy of the Neighbor List for a Node with the Controller +//----------------------------------------------------------------------------- +void Manager::SyncronizeNodeNeighbors(uint32 const _homeId, uint8 const _nodeId) +{ + if (Driver* driver = GetDriver(_homeId)) + { + driver->RequestNodeNeighbors(_nodeId, 0); + } + + return; +} + + //----------------------------------------------------------------------------- // // Get the manufacturer name of a node //----------------------------------------------------------------------------- -string Manager::GetNodeManufacturerName -( - uint32 const _homeId, - uint8 const _nodeId -) +string Manager::GetNodeManufacturerName(uint32 const _homeId, uint8 const _nodeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - return driver->GetNodeManufacturerName( _nodeId ); + return driver->GetNodeManufacturerName(_nodeId); } return "Unknown"; @@ -1189,15 +1094,11 @@ string Manager::GetNodeManufacturerName // // Get the product name of a node //----------------------------------------------------------------------------- -string Manager::GetNodeProductName -( - uint32 const _homeId, - uint8 const _nodeId -) +string Manager::GetNodeProductName(uint32 const _homeId, uint8 const _nodeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - return driver->GetNodeProductName( _nodeId ); + return driver->GetNodeProductName(_nodeId); } return "Unknown"; @@ -1207,15 +1108,11 @@ string Manager::GetNodeProductName // // Get the user-editable name of a node //----------------------------------------------------------------------------- -string Manager::GetNodeName -( - uint32 const _homeId, - uint8 const _nodeId -) +string Manager::GetNodeName(uint32 const _homeId, uint8 const _nodeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - return driver->GetNodeName( _nodeId ); + return driver->GetNodeName(_nodeId); } return "Unknown"; @@ -1225,15 +1122,11 @@ string Manager::GetNodeName // // Get the location of a node //----------------------------------------------------------------------------- -string Manager::GetNodeLocation -( - uint32 const _homeId, - uint8 const _nodeId -) +string Manager::GetNodeLocation(uint32 const _homeId, uint8 const _nodeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - return driver->GetNodeLocation( _nodeId ); + return driver->GetNodeLocation(_nodeId); } return "Unknown"; @@ -1243,16 +1136,11 @@ string Manager::GetNodeLocation // // Set the manufacturer name a node //----------------------------------------------------------------------------- -void Manager::SetNodeManufacturerName -( - uint32 const _homeId, - uint8 const _nodeId, - string const& _manufacturerName -) +void Manager::SetNodeManufacturerName(uint32 const _homeId, uint8 const _nodeId, string const& _manufacturerName) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - driver->SetNodeManufacturerName( _nodeId, _manufacturerName ); + driver->SetNodeManufacturerName(_nodeId, _manufacturerName); } } @@ -1260,16 +1148,11 @@ void Manager::SetNodeManufacturerName // // Set the product name of a node //----------------------------------------------------------------------------- -void Manager::SetNodeProductName -( - uint32 const _homeId, - uint8 const _nodeId, - string const& _productName -) +void Manager::SetNodeProductName(uint32 const _homeId, uint8 const _nodeId, string const& _productName) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - driver->SetNodeProductName( _nodeId, _productName ); + driver->SetNodeProductName(_nodeId, _productName); } } @@ -1277,16 +1160,11 @@ void Manager::SetNodeProductName // // Set the node name value with the specified ID //----------------------------------------------------------------------------- -void Manager::SetNodeName -( - uint32 const _homeId, - uint8 const _nodeId, - string const& _nodeName -) +void Manager::SetNodeName(uint32 const _homeId, uint8 const _nodeId, string const& _nodeName) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - driver->SetNodeName( _nodeId, _nodeName ); + driver->SetNodeName(_nodeId, _nodeName); } } @@ -1294,17 +1172,13 @@ void Manager::SetNodeName // // Set a string describing the location of a node //----------------------------------------------------------------------------- -void Manager::SetNodeLocation -( - uint32 const _homeId, - uint8 const _nodeId, - string const& _location +void Manager::SetNodeLocation(uint32 const _homeId, uint8 const _nodeId, string const& _location ) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - driver->SetNodeLocation( _nodeId, _location ); + driver->SetNodeLocation(_nodeId, _location); } } @@ -1312,15 +1186,11 @@ void Manager::SetNodeLocation // // Get the manufacturer ID value of a node //----------------------------------------------------------------------------- -string Manager::GetNodeManufacturerId -( - uint32 const _homeId, - uint8 const _nodeId -) +string Manager::GetNodeManufacturerId(uint32 const _homeId, uint8 const _nodeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - uint16 mid = driver->GetNodeManufacturerId( _nodeId ); + uint16 mid = driver->GetNodeManufacturerId(_nodeId); std::stringstream ss; ss << "0x" << std::hex << std::setw(4) << std::setfill('0') << mid; return ss.str(); @@ -1333,15 +1203,11 @@ string Manager::GetNodeManufacturerId // // Get the product type value of a node //----------------------------------------------------------------------------- -string Manager::GetNodeProductType -( - uint32 const _homeId, - uint8 const _nodeId -) +string Manager::GetNodeProductType(uint32 const _homeId, uint8 const _nodeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - uint16 mid = driver->GetNodeProductType( _nodeId ); + uint16 mid = driver->GetNodeProductType(_nodeId); std::stringstream ss; ss << "0x" << std::hex << std::setw(4) << std::setfill('0') << mid; return ss.str(); @@ -1350,20 +1216,15 @@ string Manager::GetNodeProductType return "Unknown"; } - //----------------------------------------------------------------------------- // // Get the node device type as reported in the Z-Wave+ Info report. //----------------------------------------------------------------------------- -uint16 Manager::GetNodeDeviceType -( - uint32 const _homeId, - uint8 const _nodeId -) +uint16 Manager::GetNodeDeviceType(uint32 const _homeId, uint8 const _nodeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - return driver->GetNodeDeviceType( _nodeId ); + return driver->GetNodeDeviceType(_nodeId); } return 0x00; // unknown @@ -1373,35 +1234,25 @@ uint16 Manager::GetNodeDeviceType // // Get the node device type as reported in the Z-Wave+ Info report. //----------------------------------------------------------------------------- -string Manager::GetNodeDeviceTypeString -( - uint32 const _homeId, - uint8 const _nodeId -) +string Manager::GetNodeDeviceTypeString(uint32 const _homeId, uint8 const _nodeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - return driver->GetNodeDeviceTypeString( _nodeId ); + return driver->GetNodeDeviceTypeString(_nodeId); } return ""; // unknown } - - //----------------------------------------------------------------------------- // // Get the node role as reported in the Z-Wave+ Info report. //----------------------------------------------------------------------------- -uint8 Manager::GetNodeRole -( - uint32 const _homeId, - uint8 const _nodeId -) +uint8 Manager::GetNodeRole(uint32 const _homeId, uint8 const _nodeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - return driver->GetNodeRole( _nodeId ); + return driver->GetNodeRole(_nodeId); } return 0x00; // unknown @@ -1411,45 +1262,32 @@ uint8 Manager::GetNodeRole // // Get the node role as reported in the Z-Wave+ Info report. //----------------------------------------------------------------------------- -string Manager::GetNodeRoleString -( - uint32 const _homeId, - uint8 const _nodeId -) +string Manager::GetNodeRoleString(uint32 const _homeId, uint8 const _nodeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - return driver->GetNodeRoleString( _nodeId ); + return driver->GetNodeRoleString(_nodeId); } return ""; // unknown } - -uint8 Manager::GetNodePlusType -( - uint32 const _homeId, - uint8 const _nodeId -) +uint8 Manager::GetNodePlusType(uint32 const _homeId, uint8 const _nodeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - return driver->GetNodePlusType( _nodeId ); + return driver->GetNodePlusType(_nodeId); } return 0x00; // unknown } -string Manager::GetNodePlusTypeString -( - uint32 const _homeId, - uint8 const _nodeId -) +string Manager::GetNodePlusTypeString(uint32 const _homeId, uint8 const _nodeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - return driver->GetNodePlusTypeString( _nodeId ); + return driver->GetNodePlusTypeString(_nodeId); } return ""; // unknown @@ -1460,15 +1298,11 @@ string Manager::GetNodePlusTypeString // // Get the product Id value with the specified ID //----------------------------------------------------------------------------- -string Manager::GetNodeProductId -( - uint32 const _homeId, - uint8 const _nodeId -) +string Manager::GetNodeProductId(uint32 const _homeId, uint8 const _nodeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - uint16 mid = driver->GetNodeProductId( _nodeId ); + uint16 mid = driver->GetNodeProductId(_nodeId); std::stringstream ss; ss << "0x" << std::hex << std::setw(4) << std::setfill('0') << mid; return ss.str(); @@ -1481,15 +1315,11 @@ string Manager::GetNodeProductId // // Helper method to turn a node on //----------------------------------------------------------------------------- -void Manager::SetNodeOn -( - uint32 const _homeId, - uint8 const _nodeId -) +void Manager::SetNodeOn(uint32 const _homeId, uint8 const _nodeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - driver->SetNodeOn( _nodeId ); + driver->SetNodeOn(_nodeId); } } @@ -1497,15 +1327,11 @@ void Manager::SetNodeOn // // Helper method to turn a node off //----------------------------------------------------------------------------- -void Manager::SetNodeOff -( - uint32 const _homeId, - uint8 const _nodeId -) +void Manager::SetNodeOff(uint32 const _homeId, uint8 const _nodeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - driver->SetNodeOff( _nodeId ); + driver->SetNodeOff(_nodeId); } } @@ -1513,22 +1339,18 @@ void Manager::SetNodeOff // // Helper method to return whether a particular class is available in a node //----------------------------------------------------------------------------- -bool Manager::IsNodeInfoReceived -( - uint32 const _homeId, - uint8 const _nodeId -) +bool Manager::IsNodeInfoReceived(uint32 const _homeId, uint8 const _nodeId) { bool result = false; - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { Node *node; // Need to lock and unlock nodes to check this information - LockGuard LG(driver->m_nodeMutex); + Internal::LockGuard LG(driver->m_nodeMutex); - if( (node = driver->GetNode( _nodeId ) ) != NULL) + if ((node = driver->GetNode(_nodeId)) != NULL) { result = node->NodeInfoReceived(); } @@ -1541,34 +1363,27 @@ bool Manager::IsNodeInfoReceived // // Helper method to return whether a particular class is available in a node //----------------------------------------------------------------------------- -bool Manager::GetNodeClassInformation -( - uint32 const _homeId, - uint8 const _nodeId, - uint8 const _commandClassId, - string *_className, - uint8 *_classVersion -) +bool Manager::GetNodeClassInformation(uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, string *_className, uint8 *_classVersion) { bool result = false; - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { Node *node; // Need to lock and unlock nodes to check this information - LockGuard LG(driver->m_nodeMutex); + Internal::LockGuard LG(driver->m_nodeMutex); - if( ( node = driver->GetNode( _nodeId ) ) != NULL ) + if ((node = driver->GetNode(_nodeId)) != NULL) { - CommandClass *cc; - if( node->NodeInfoReceived() && ( ( cc = node->GetCommandClass( _commandClassId ) ) != NULL ) ) + Internal::CC::CommandClass *cc; + if (node->NodeInfoReceived() && ((cc = node->GetCommandClass(_commandClassId)) != NULL)) { - if( _className ) + if (_className) { *_className = cc->GetCommandClassName(); } - if( _classVersion ) + if (_classVersion) { *_classVersion = cc->GetVersion(); } @@ -1582,29 +1397,33 @@ bool Manager::GetNodeClassInformation return result; } +//----------------------------------------------------------------------------- +// +// Get a String representing the Command Class Name +//----------------------------------------------------------------------------- +string Manager::GetCommandClassName(uint8 const _commandClassId) { + return OpenZWave::Internal::CC::CommandClasses::GetName(_commandClassId); +} + //----------------------------------------------------------------------------- // // Helper method to return whether a node is awake or sleeping //----------------------------------------------------------------------------- -bool Manager::IsNodeAwake -( - uint32 const _homeId, - uint8 const _nodeId -) +bool Manager::IsNodeAwake(uint32 const _homeId, uint8 const _nodeId) { - if( IsNodeListeningDevice( _homeId, _nodeId ) ) + if (IsNodeListeningDevice(_homeId, _nodeId)) { return true; // if listening then always awake } bool result = true; - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { // Need to lock and unlock nodes to check this information - LockGuard LG(driver->m_nodeMutex); + Internal::LockGuard LG(driver->m_nodeMutex); - if( Node* node = driver->GetNode( _nodeId ) ) + if (Node* node = driver->GetNode(_nodeId)) { - if( WakeUp* wcc = static_cast( node->GetCommandClass( WakeUp::StaticGetCommandClassId() ) ) ) + if (Internal::CC::WakeUp* wcc = static_cast(node->GetCommandClass(Internal::CC::WakeUp::StaticGetCommandClassId()))) { result = wcc->IsAwake(); } @@ -1617,17 +1436,13 @@ bool Manager::IsNodeAwake // // Helper method to return whether a node is on the network or not //----------------------------------------------------------------------------- -bool Manager::IsNodeFailed -( - uint32 const _homeId, - uint8 const _nodeId -) +bool Manager::IsNodeFailed(uint32 const _homeId, uint8 const _nodeId) { bool result = false; - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - LockGuard LG(driver->m_nodeMutex); - if( Node* node = driver->GetNode( _nodeId ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Node* node = driver->GetNode(_nodeId)) { result = !node->IsNodeAlive(); } @@ -1639,19 +1454,15 @@ bool Manager::IsNodeFailed // // Helper method to return whether a node's query stage //----------------------------------------------------------------------------- -string Manager::GetNodeQueryStage -( - uint32 const _homeId, - uint8 const _nodeId -) +string Manager::GetNodeQueryStage(uint32 const _homeId, uint8 const _nodeId) { string result = "Unknown"; - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - LockGuard LG(driver->m_nodeMutex); - if( Node* node = driver->GetNode( _nodeId ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Node* node = driver->GetNode(_nodeId)) { - result = node->GetQueryStageName( node->GetCurrentQueryStage() ); + result = node->GetQueryStageName(node->GetCurrentQueryStage()); } } return result; @@ -1661,16 +1472,11 @@ string Manager::GetNodeQueryStage // // Helper method to set the basic level of a node //----------------------------------------------------------------------------- -void Manager::SetNodeLevel -( - uint32 const _homeId, - uint8 const _nodeId, - uint8 const _level -) +void Manager::SetNodeLevel(uint32 const _homeId, uint8 const _nodeId, uint8 const _level) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - return driver->SetNodeLevel( _nodeId, _level ); + return driver->SetNodeLevel(_nodeId, _level); } } @@ -1682,10 +1488,7 @@ void Manager::SetNodeLevel // // Gets the user-friendly Instance label for the valueID //----------------------------------------------------------------------------- -string Manager::GetInstanceLabel -( - ValueID const &_id -) +string Manager::GetInstanceLabel(ValueID const &_id) { return GetInstanceLabel(_id.GetHomeId(), _id.GetNodeId(), _id.GetCommandClassId(), _id.GetInstance()); } @@ -1693,19 +1496,13 @@ string Manager::GetInstanceLabel // // Gets the user-friendly Instance label for the cc and instance //----------------------------------------------------------------------------- -string Manager::GetInstanceLabel -( - uint32 const _homeId, - uint8 const _node, - uint8 const _cc, - uint8 const _instance -) +string Manager::GetInstanceLabel(uint32 const _homeId, uint8 const _node, uint8 const _cc, uint8 const _instance) { string label; - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - LockGuard LG(driver->m_nodeMutex); - if( Node* node = driver->GetNode( _node ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Node* node = driver->GetNode(_node)) { label = node->GetInstanceLabel(_cc, _instance); return label; @@ -1727,37 +1524,37 @@ string Manager::GetInstanceLabel // // Gets the user-friendly label for the value //----------------------------------------------------------------------------- -string Manager::GetValueLabel -( - ValueID const& _id, - int32 _pos -) +string Manager::GetValueLabel(ValueID const& _id, int32 _pos) { string label; - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if (_pos != -1) { - if (_id.GetType() != ValueID::ValueType_BitSet) { + Internal::LockGuard LG(driver->m_nodeMutex); + if (_pos != -1) + { + if (_id.GetType() != ValueID::ValueType_BitSet) + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "ValueID passed to GetValueLabel is not a BitSet but a position was requested"); return label; } - ValueBitSet *value = static_cast(driver->GetValue( _id )); + Internal::VC::ValueBitSet *value = static_cast(driver->GetValue(_id)); label = value->GetBitLabel(_pos); value->Release(); return label; - } else { + } + else + { bool useinstancelabels = true; - Options::Get()->GetOptionAsBool( "IncludeInstanceLabel", &useinstancelabels ); - Node* node = driver->GetNode( _id.GetNodeId() ); - if ( (useinstancelabels) && ( node ) ) + Options::Get()->GetOptionAsBool("IncludeInstanceLabel", &useinstancelabels); + Node* node = driver->GetNode(_id.GetNodeId()); + if ((useinstancelabels) && (node)) { - if ( node->GetNumInstances(_id.GetCommandClassId()) > 1 ) + if (node->GetNumInstances(_id.GetCommandClassId()) > 1) { label = GetInstanceLabel(_id).append(" "); } } - if ( Value* value = driver->GetValue( _id ) ) + if (Internal::VC::Value* value = driver->GetValue(_id)) { label.append(value->GetLabel()); @@ -1774,29 +1571,28 @@ string Manager::GetValueLabel // // Sets the user-friendly label for the value //----------------------------------------------------------------------------- -void Manager::SetValueLabel -( - ValueID const& _id, - string const& _value, - int32 _pos -) +void Manager::SetValueLabel(ValueID const& _id, string const& _value, int32 _pos) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if (_pos != -1) { - if (_id.GetType() != ValueID::ValueType_BitSet) { + Internal::LockGuard LG(driver->m_nodeMutex); + if (_pos != -1) + { + if (_id.GetType() != ValueID::ValueType_BitSet) + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "ValueID passed to SetValueLabel is not a BitSet but a position was requested"); return; } - ValueBitSet *value = static_cast(driver->GetValue( _id )); + Internal::VC::ValueBitSet *value = static_cast(driver->GetValue(_id)); value->SetBitLabel(_pos, _value); value->Release(); return; - } else { - if( Value* value = driver->GetValue( _id ) ) + } + else + { + if (Internal::VC::Value* value = driver->GetValue(_id)) { - value->SetLabel( _value ); + value->SetLabel(_value); value->Release(); return; } @@ -1809,20 +1605,19 @@ void Manager::SetValueLabel // // Gets the units that the value is measured in //----------------------------------------------------------------------------- -string Manager::GetValueUnits -( - ValueID const& _id -) +string Manager::GetValueUnits(ValueID const& _id) { string units; - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( Value* value = driver->GetValue( _id ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::Value* value = driver->GetValue(_id)) { units = value->GetUnits(); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueUnits"); } } @@ -1834,20 +1629,18 @@ string Manager::GetValueUnits // // Sets the units that the value is measured in //----------------------------------------------------------------------------- -void Manager::SetValueUnits -( - ValueID const& _id, - string const& _value -) +void Manager::SetValueUnits(ValueID const& _id, string const& _value) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( Value* value = driver->GetValue( _id ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::Value* value = driver->GetValue(_id)) { - value->SetUnits( _value ); + value->SetUnits(_value); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValueUnits"); } } @@ -1857,27 +1650,27 @@ void Manager::SetValueUnits // // Gets a help string describing the value's purpose and usage //----------------------------------------------------------------------------- -string Manager::GetValueHelp -( - ValueID const& _id, - int32 _pos -) +string Manager::GetValueHelp(ValueID const& _id, int32 _pos) { string help; - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if (_pos != -1) { - if (_id.GetType() != ValueID::ValueType_BitSet) { + Internal::LockGuard LG(driver->m_nodeMutex); + if (_pos != -1) + { + if (_id.GetType() != ValueID::ValueType_BitSet) + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "ValueID passed to GetValueHelp is not a BitSet but a position was requested"); return help; } - ValueBitSet *value = static_cast(driver->GetValue( _id )); + Internal::VC::ValueBitSet *value = static_cast(driver->GetValue(_id)); help = value->GetBitHelp(_pos); value->Release(); return help; - } else { - if( Value* value = driver->GetValue( _id ) ) + } + else + { + if (Internal::VC::Value* value = driver->GetValue(_id)) { help = value->GetHelp(); value->Release(); @@ -1893,29 +1686,28 @@ string Manager::GetValueHelp // // Sets a help string describing the value's purpose and usage //----------------------------------------------------------------------------- -void Manager::SetValueHelp -( - ValueID const& _id, - string const& _value, - int32 _pos -) +void Manager::SetValueHelp(ValueID const& _id, string const& _value, int32 _pos) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if (_pos != -1) { - if (_id.GetType() != ValueID::ValueType_BitSet) { + Internal::LockGuard LG(driver->m_nodeMutex); + if (_pos != -1) + { + if (_id.GetType() != ValueID::ValueType_BitSet) + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "ValueID passed to SetValueHelp is not a BitSet but a position was requested"); return; } - ValueBitSet *value = static_cast(driver->GetValue( _id )); + Internal::VC::ValueBitSet *value = static_cast(driver->GetValue(_id)); value->SetBitHelp(_pos, _value); value->Release(); return; - } else { - if( Value* value = driver->GetValue( _id ) ) + } + else + { + if (Internal::VC::Value* value = driver->GetValue(_id)) { - value->SetHelp( _value ); + value->SetHelp(_value); value->Release(); return; } @@ -1928,20 +1720,19 @@ void Manager::SetValueHelp // // Gets the minimum for a value //----------------------------------------------------------------------------- -int32 Manager::GetValueMin -( - ValueID const& _id -) +int32 Manager::GetValueMin(ValueID const& _id) { int32 limit = 0; - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( Value* value = driver->GetValue( _id ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::Value* value = driver->GetValue(_id)) { limit = value->GetMin(); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueMin"); } } @@ -1953,20 +1744,19 @@ int32 Manager::GetValueMin // // Gets the maximum for a value //----------------------------------------------------------------------------- -int32 Manager::GetValueMax -( - ValueID const& _id -) +int32 Manager::GetValueMax(ValueID const& _id) { int32 limit = 0; - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( Value* value = driver->GetValue( _id ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::Value* value = driver->GetValue(_id)) { limit = value->GetMax(); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueMax"); } } @@ -1978,20 +1768,19 @@ int32 Manager::GetValueMax // // Test whether the value is read-only //----------------------------------------------------------------------------- -bool Manager::IsValueReadOnly -( - ValueID const& _id -) +bool Manager::IsValueReadOnly(ValueID const& _id) { bool res = false; - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( Value* value = driver->GetValue( _id ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::Value* value = driver->GetValue(_id)) { res = value->IsReadOnly(); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to IsValueReadOnly"); } } @@ -2003,20 +1792,19 @@ bool Manager::IsValueReadOnly // // Test whether the value is write-only //----------------------------------------------------------------------------- -bool Manager::IsValueWriteOnly -( - ValueID const& _id -) +bool Manager::IsValueWriteOnly(ValueID const& _id) { bool res = false; - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( Value* value = driver->GetValue( _id ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::Value* value = driver->GetValue(_id)) { res = value->IsWriteOnly(); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to IsValueWriteOnly"); } } @@ -2028,20 +1816,19 @@ bool Manager::IsValueWriteOnly // // Test whether the value has been set by a status message from the device //----------------------------------------------------------------------------- -bool Manager::IsValueSet -( - ValueID const& _id -) +bool Manager::IsValueSet(ValueID const& _id) { bool res = false; - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( Value* value = driver->GetValue( _id ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::Value* value = driver->GetValue(_id)) { res = value->IsSet(); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to IsValueSet"); } } @@ -2053,20 +1840,19 @@ bool Manager::IsValueSet // // Test whether the value is currently being polled //----------------------------------------------------------------------------- -bool Manager::IsValuePolled -( - ValueID const& _id -) +bool Manager::IsValuePolled(ValueID const& _id) { bool res = false; - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( Value* value = driver->GetValue( _id ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::Value* value = driver->GetValue(_id)) { res = value->IsPolled(); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to IsValuePolled"); } } @@ -2074,35 +1860,53 @@ bool Manager::IsValuePolled return res; } +//----------------------------------------------------------------------------- +// +// Test whether the valueID is Valid +//----------------------------------------------------------------------------- +bool Manager::IsValueValid(ValueID const& _id) +{ + if (Driver* driver = GetDriver(_id.GetHomeId())) + { + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::Value* value = driver->GetValue(_id)) + { + value->Release(); + return true; + } + } + return false; +} + + //----------------------------------------------------------------------------- // // Gets a bit from a BitSet as a bool //----------------------------------------------------------------------------- -bool Manager::GetValueAsBitSet -( - ValueID const& _id, - uint8 _pos, - bool* o_value -) +bool Manager::GetValueAsBitSet(ValueID const& _id, uint8 _pos, bool* o_value) { - if( o_value ) + if (o_value) { - if( ValueID::ValueType_BitSet == _id.GetType() ) + if (ValueID::ValueType_BitSet == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( ValueBitSet* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueBitSet* value = static_cast(driver->GetValue(_id))) { *o_value = value->GetBit(_pos); value->Release(); return true; - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueAsBitSet"); } } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetValueAsBitSet is not a BitSet Value"); } } @@ -2113,46 +1917,48 @@ bool Manager::GetValueAsBitSet // // Gets a value as a bool //----------------------------------------------------------------------------- -bool Manager::GetValueAsBool -( - ValueID const& _id, - bool* o_value -) +bool Manager::GetValueAsBool(ValueID const& _id, bool* o_value) { bool res = false; - if( o_value ) + if (o_value) { - if( ValueID::ValueType_Bool == _id.GetType() ) + if (ValueID::ValueType_Bool == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( ValueBool* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueBool* value = static_cast(driver->GetValue(_id))) { *o_value = value->GetValue(); value->Release(); res = true; - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueAsBool"); } } } - else if( ValueID::ValueType_Button == _id.GetType() ) + else if (ValueID::ValueType_Button == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( ValueButton* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueButton* value = static_cast(driver->GetValue(_id))) { *o_value = value->IsPressed(); value->Release(); res = true; - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueAsBool"); } } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetValueAsBool is not a Bool or Button Value"); } } @@ -2164,31 +1970,31 @@ bool Manager::GetValueAsBool // // Gets a value as an 8-bit unsigned integer //----------------------------------------------------------------------------- -bool Manager::GetValueAsByte -( - ValueID const& _id, - uint8* o_value -) +bool Manager::GetValueAsByte(ValueID const& _id, uint8* o_value) { bool res = false; - if( o_value ) + if (o_value) { - if( ValueID::ValueType_Byte == _id.GetType() ) + if (ValueID::ValueType_Byte == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( ValueByte* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueByte* value = static_cast(driver->GetValue(_id))) { *o_value = value->GetValue(); value->Release(); res = true; - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueAsByte"); } } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetValueAsByte is not a Byte Value"); } } @@ -2200,32 +2006,32 @@ bool Manager::GetValueAsByte // // Gets a value as a floating point number //----------------------------------------------------------------------------- -bool Manager::GetValueAsFloat -( - ValueID const& _id, - float* o_value -) +bool Manager::GetValueAsFloat(ValueID const& _id, float* o_value) { bool res = false; - if( o_value ) + if (o_value) { - if( ValueID::ValueType_Decimal == _id.GetType() ) + if (ValueID::ValueType_Decimal == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( ValueDecimal* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueDecimal* value = static_cast(driver->GetValue(_id))) { string str = value->GetValue(); - *o_value = (float)atof( str.c_str() ); + *o_value = (float) atof(str.c_str()); value->Release(); res = true; - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueAsFloat"); } } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetValueAsFloat is not a Float Value"); } } @@ -2237,23 +2043,19 @@ bool Manager::GetValueAsFloat // // Gets a value as a 32-bit signed integer //----------------------------------------------------------------------------- -bool Manager::GetValueAsInt -( - ValueID const& _id, - int32* o_value -) +bool Manager::GetValueAsInt(ValueID const& _id, int32* o_value) { bool res = false; - if( o_value ) + if (o_value) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); + Internal::LockGuard LG(driver->m_nodeMutex); - if( ValueID::ValueType_Int == _id.GetType() ) + if (ValueID::ValueType_Int == _id.GetType()) { - if( ValueInt* value = static_cast( driver->GetValue( _id ) ) ) + if (Internal::VC::ValueInt* value = static_cast(driver->GetValue(_id))) { *o_value = value->GetValue(); value->Release(); @@ -2264,9 +2066,9 @@ bool Manager::GetValueAsInt OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueAsInt"); } } - else if (ValueID::ValueType_BitSet == _id.GetType() ) + else if (ValueID::ValueType_BitSet == _id.GetType()) { - if (ValueBitSet* value = static_cast( driver->GetValue( _id ) ) ) + if (Internal::VC::ValueBitSet* value = static_cast(driver->GetValue(_id))) { *o_value = value->GetValue(); value->Release(); @@ -2279,7 +2081,7 @@ bool Manager::GetValueAsInt } else { - OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetValueAsInt is not a Int or BitSet Value"); + OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetValueAsInt is not a Int or BitSet Value"); } } } @@ -2291,37 +2093,36 @@ bool Manager::GetValueAsInt // // Gets a value as a collection of bytes //----------------------------------------------------------------------------- -bool Manager::GetValueAsRaw -( - ValueID const& _id, - uint8** o_value, - uint8* o_length -) +bool Manager::GetValueAsRaw(ValueID const& _id, uint8** o_value, uint8* o_length) { bool res = false; - if( o_value && o_length ) + if (o_value && o_length) { - if( ValueID::ValueType_Raw == _id.GetType() ) + if (ValueID::ValueType_Raw == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( ValueRaw* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueRaw* value = static_cast(driver->GetValue(_id))) { *o_length = value->GetLength(); *o_value = new uint8[*o_length]; - memcpy( *o_value, value->GetValue(), *o_length ); + memcpy(*o_value, value->GetValue(), *o_length); value->Release(); res = true; - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueAsRaw"); } } - } else { - OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetValueAsRaw is not a Raw Value"); } - } + else + { + OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetValueAsRaw is not a Raw Value"); + } + } return res; } @@ -2330,31 +2131,31 @@ bool Manager::GetValueAsRaw // // Gets a value as a 16-bit signed integer //----------------------------------------------------------------------------- -bool Manager::GetValueAsShort -( - ValueID const& _id, - int16* o_value -) +bool Manager::GetValueAsShort(ValueID const& _id, int16* o_value) { bool res = false; - if( o_value ) + if (o_value) { - if( ValueID::ValueType_Short == _id.GetType() ) + if (ValueID::ValueType_Short == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( ValueShort* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueShort* value = static_cast(driver->GetValue(_id))) { *o_value = value->GetValue(); value->Release(); res = true; - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueAsShort"); } } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetValueAsShort is not a Short Value"); } } @@ -2366,161 +2167,183 @@ bool Manager::GetValueAsShort // // Creates a string representation of the value, regardless of type //----------------------------------------------------------------------------- -bool Manager::GetValueAsString -( - ValueID const& _id, - string* o_value -) +bool Manager::GetValueAsString(ValueID const& _id, string* o_value) { bool res = false; - char str[256] = {0}; + char str[256] = + { 0 }; - if( o_value ) + if (o_value) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); + Internal::LockGuard LG(driver->m_nodeMutex); - switch( _id.GetType() ) + switch (_id.GetType()) { case ValueID::ValueType_BitSet: { - if( ValueBitSet* value = static_cast( driver->GetValue( _id ) ) ) + if (Internal::VC::ValueBitSet* value = static_cast(driver->GetValue(_id))) { *o_value = value->GetAsString(); value->Release(); res = true; - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueAsString"); } break; } case ValueID::ValueType_Bool: { - if( ValueBool* value = static_cast( driver->GetValue( _id ) ) ) + if (Internal::VC::ValueBool* value = static_cast(driver->GetValue(_id))) { *o_value = value->GetValue() ? "True" : "False"; value->Release(); res = true; - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueAsString"); } break; } case ValueID::ValueType_Byte: { - if( ValueByte* value = static_cast( driver->GetValue( _id ) ) ) + if (Internal::VC::ValueByte* value = static_cast(driver->GetValue(_id))) { - snprintf( str, sizeof(str), "%u", value->GetValue() ); + snprintf(str, sizeof(str), "%u", value->GetValue()); *o_value = str; value->Release(); res = true; - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueAsString"); } break; } case ValueID::ValueType_Decimal: { - if( ValueDecimal* value = static_cast( driver->GetValue( _id ) ) ) + if (Internal::VC::ValueDecimal* value = static_cast(driver->GetValue(_id))) { *o_value = value->GetValue(); value->Release(); res = true; - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueAsString"); } break; } case ValueID::ValueType_Int: { - if( ValueInt* value = static_cast( driver->GetValue( _id ) ) ) + if (Internal::VC::ValueInt* value = static_cast(driver->GetValue(_id))) { - snprintf( str, sizeof(str), "%d", value->GetValue() ); + snprintf(str, sizeof(str), "%d", value->GetValue()); *o_value = str; value->Release(); res = true; - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueAsString"); } break; } case ValueID::ValueType_List: { - if( ValueList* value = static_cast( driver->GetValue( _id ) ) ) + if (Internal::VC::ValueList* value = static_cast(driver->GetValue(_id))) { - ValueList::Item const *item = value->GetItem(); - if (item == NULL) { + Internal::VC::ValueList::Item const *item = value->GetItem(); + if (item == NULL) + { o_value = NULL; res = false; - } else { + } + else + { *o_value = item->m_label; res = true; } value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueAsString"); } break; } case ValueID::ValueType_Raw: { - if( ValueRaw* value = static_cast( driver->GetValue( _id ) ) ) + if (Internal::VC::ValueRaw* value = static_cast(driver->GetValue(_id))) { *o_value = value->GetAsString(); value->Release(); res = true; - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueAsString"); } break; } case ValueID::ValueType_Short: { - if( ValueShort* value = static_cast( driver->GetValue( _id ) ) ) + if (Internal::VC::ValueShort* value = static_cast(driver->GetValue(_id))) { - snprintf( str, sizeof(str), "%d", value->GetValue() ); + snprintf(str, sizeof(str), "%d", value->GetValue()); *o_value = str; value->Release(); res = true; - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueAsString"); } break; } case ValueID::ValueType_String: { - if( ValueString* value = static_cast( driver->GetValue( _id ) ) ) + if (Internal::VC::ValueString* value = static_cast(driver->GetValue(_id))) { *o_value = value->GetValue(); value->Release(); res = true; - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueAsString"); } break; } case ValueID::ValueType_Button: { - if( ValueButton* value = static_cast( driver->GetValue( _id ) ) ) + if (Internal::VC::ValueButton* value = static_cast(driver->GetValue(_id))) { *o_value = value->IsPressed() ? "True" : "False"; value->Release(); res = true; - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueAsString"); } break; } case ValueID::ValueType_Schedule: { - if( ValueSchedule* value = static_cast( driver->GetValue( _id ) ) ) + if (Internal::VC::ValueSchedule* value = static_cast(driver->GetValue(_id))) { *o_value = value->GetAsString(); value->Release(); res = true; - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueAsString"); } break; @@ -2537,38 +2360,40 @@ bool Manager::GetValueAsString // // Gets the selected item from a list value (returning a string) //----------------------------------------------------------------------------- -bool Manager::GetValueListSelection -( - ValueID const& _id, - string* o_value -) +bool Manager::GetValueListSelection(ValueID const& _id, string* o_value) { bool res = false; - if( o_value ) + if (o_value) { - if( ValueID::ValueType_List == _id.GetType() ) + if (ValueID::ValueType_List == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( ValueList* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueList* value = static_cast(driver->GetValue(_id))) { - ValueList::Item const *item = value->GetItem(); - if( item != NULL && item->m_label.length() > 0) + Internal::VC::ValueList::Item const *item = value->GetItem(); + if (item != NULL && item->m_label.length() > 0) { *o_value = item->m_label; res = true; - } else { + } + else + { o_value = NULL; Log::Write(LogLevel_Warning, "ValueList returned a NULL value for GetValueListSelection: %s", value->GetLabel().c_str()); } value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueListSelection"); } } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetValueListSelection is not a List Value"); } } @@ -2580,37 +2405,40 @@ bool Manager::GetValueListSelection // // Gets the selected item from a list value (returning the index) //----------------------------------------------------------------------------- -bool Manager::GetValueListSelection -( - ValueID const& _id, - int32* o_value -) +bool Manager::GetValueListSelection(ValueID const& _id, int32* o_value) { bool res = false; - if( o_value ) + if (o_value) { - if( ValueID::ValueType_List == _id.GetType() ) + if (ValueID::ValueType_List == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( ValueList* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueList* value = static_cast(driver->GetValue(_id))) { - ValueList::Item const *item = value->GetItem(); - if (item == NULL) { + Internal::VC::ValueList::Item const *item = value->GetItem(); + if (item == NULL) + { res = false; - } else { + } + else + { *o_value = item->m_value; res = true; } value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueListSelection"); } } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetValueListSelection is not a List Value"); } } @@ -2622,31 +2450,31 @@ bool Manager::GetValueListSelection // // Gets the list of items from a list value //----------------------------------------------------------------------------- -bool Manager::GetValueListItems -( - ValueID const& _id, - vector* o_value -) +bool Manager::GetValueListItems(ValueID const& _id, vector* o_value) { bool res = false; - if( o_value ) + if (o_value) { - if( ValueID::ValueType_List == _id.GetType() ) + if (ValueID::ValueType_List == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( ValueList* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueList* value = static_cast(driver->GetValue(_id))) { o_value->clear(); - res = value->GetItemLabels( o_value ); + res = value->GetItemLabels(o_value); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueListItems"); } } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetValueListItems is not a List Value"); } } @@ -2658,31 +2486,31 @@ bool Manager::GetValueListItems // // Gets the list of values from a list value //----------------------------------------------------------------------------- -bool Manager::GetValueListValues -( - ValueID const& _id, - vector* o_value -) +bool Manager::GetValueListValues(ValueID const& _id, vector* o_value) { bool res = false; - if( o_value ) + if (o_value) { - if( ValueID::ValueType_List == _id.GetType() ) + if (ValueID::ValueType_List == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( ValueList* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueList* value = static_cast(driver->GetValue(_id))) { o_value->clear(); - res = value->GetItemValues( o_value ); + res = value->GetItemValues(o_value); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueListValues"); } } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetValueListValues is not a List Value"); } } @@ -2690,36 +2518,35 @@ bool Manager::GetValueListValues return res; } - //----------------------------------------------------------------------------- // // Gets a value's scale as a uint8 //----------------------------------------------------------------------------- -bool Manager::GetValueFloatPrecision -( - ValueID const& _id, - uint8* o_value -) +bool Manager::GetValueFloatPrecision(ValueID const& _id, uint8* o_value) { bool res = false; - if( o_value ) + if (o_value) { - if( ValueID::ValueType_Decimal == _id.GetType() ) + if (ValueID::ValueType_Decimal == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( ValueDecimal* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueDecimal* value = static_cast(driver->GetValue(_id))) { *o_value = value->GetPrecision(); value->Release(); res = true; - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueFloatPrecision"); } } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetValueFloatPrecision is not a Decimal Value"); } } @@ -2731,35 +2558,34 @@ bool Manager::GetValueFloatPrecision // // Sets a bit in a BitSet Value //----------------------------------------------------------------------------- -bool Manager::SetValue -( - ValueID const& _id, - uint8 _pos, - bool const _value -) +bool Manager::SetValue(ValueID const& _id, uint8 _pos, bool const _value) { bool res = false; - if( ValueID::ValueType_BitSet == _id.GetType() ) + if (ValueID::ValueType_BitSet == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - if( _id.GetNodeId() != driver->GetControllerNodeId() ) + if (_id.GetNodeId() != driver->GetControllerNodeId()) { - LockGuard LG(driver->m_nodeMutex); - if( ValueBitSet* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueBitSet* value = static_cast(driver->GetValue(_id))) { if (_value) res = value->SetBit(_pos); else res = value->ClearBit(_pos); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValue"); } } } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to SetValue is not a BitSet Value"); } @@ -2770,31 +2596,31 @@ bool Manager::SetValue // // Sets the value from a bool //----------------------------------------------------------------------------- -bool Manager::SetValue -( - ValueID const& _id, - bool const _value -) +bool Manager::SetValue(ValueID const& _id, bool const _value) { bool res = false; - if( ValueID::ValueType_Bool == _id.GetType() ) + if (ValueID::ValueType_Bool == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - if( _id.GetNodeId() != driver->GetControllerNodeId() ) + if (_id.GetNodeId() != driver->GetControllerNodeId()) { - LockGuard LG(driver->m_nodeMutex); - if( ValueBool* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueBool* value = static_cast(driver->GetValue(_id))) { - res = value->Set( _value ); + res = value->Set(_value); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValue"); } } } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to SetValue is not a bool Value"); } @@ -2805,51 +2631,57 @@ bool Manager::SetValue // // Sets the value from a byte //----------------------------------------------------------------------------- -bool Manager::SetValue -( - ValueID const& _id, - uint8 const _value -) +bool Manager::SetValue(ValueID const& _id, uint8 const _value) { bool res = false; - if( ValueID::ValueType_Byte == _id.GetType() ) + if (ValueID::ValueType_Byte == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - if( _id.GetNodeId() != driver->GetControllerNodeId() ) + if (_id.GetNodeId() != driver->GetControllerNodeId()) { - LockGuard LG(driver->m_nodeMutex); - if( ValueByte* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueByte* value = static_cast(driver->GetValue(_id))) { - res = value->Set( _value ); + res = value->Set(_value); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValue"); } } } - } else if( ValueID::ValueType_BitSet == _id.GetType() ) + } + else if (ValueID::ValueType_BitSet == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - if( _id.GetNodeId() != driver->GetControllerNodeId() ) + if (_id.GetNodeId() != driver->GetControllerNodeId()) { - LockGuard LG(driver->m_nodeMutex); - if( ValueBitSet* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueBitSet* value = static_cast(driver->GetValue(_id))) { - if (value->GetSize() == 1) { + if (value->GetSize() == 1) + { res = value->Set(_value); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "BitSet ValueID is Not of Size 1 (SetValue uint8)"); } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValue"); } } } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to SetValue is not a Byte Value"); } @@ -2860,51 +2692,51 @@ bool Manager::SetValue // // Sets the value from a floating point number //----------------------------------------------------------------------------- -bool Manager::SetValue -( - ValueID const& _id, - float const _value -) +bool Manager::SetValue(ValueID const& _id, float const _value) { bool res = false; - if( ValueID::ValueType_Decimal == _id.GetType() ) + if (ValueID::ValueType_Decimal == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - if( _id.GetNodeId() != driver->GetControllerNodeId() ) + if (_id.GetNodeId() != driver->GetControllerNodeId()) { - LockGuard LG(driver->m_nodeMutex); - if( ValueDecimal* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueDecimal* value = static_cast(driver->GetValue(_id))) { char str[256]; - snprintf( str, sizeof(str), "%f", _value ); + snprintf(str, sizeof(str), "%f", _value); // remove trailing zeros (and the decimal point, if present) // TODO: better way of figuring out which locale is being used ('.' or ',' to separate decimals) size_t nLen; - if( ( strchr( str, '.' ) != NULL) || (strchr( str, ',' ) != NULL ) ) + if ((strchr(str, '.') != NULL) || (strchr(str, ',') != NULL)) { - for( nLen = strlen( str ) - 1; nLen > 0; nLen-- ) + for (nLen = strlen(str) - 1; nLen > 0; nLen--) { - if( str[nLen] == '0' ) + if (str[nLen] == '0') str[nLen] = 0; else break; } - if( (str[nLen] == '.') || (str[nLen] == ',') ) + if ((str[nLen] == '.') || (str[nLen] == ',')) str[nLen] = 0; } // now set the value - res = value->Set( str ); + res = value->Set(str); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValue"); } } } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to SetValue is not a Decimal Value"); } @@ -2915,51 +2747,57 @@ bool Manager::SetValue // // Sets the value from a 32-bit signed integer //----------------------------------------------------------------------------- -bool Manager::SetValue -( - ValueID const& _id, - int32 const _value -) +bool Manager::SetValue(ValueID const& _id, int32 const _value) { bool res = false; - if( ValueID::ValueType_Int == _id.GetType() ) + if (ValueID::ValueType_Int == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - if( _id.GetNodeId() != driver->GetControllerNodeId() ) + if (_id.GetNodeId() != driver->GetControllerNodeId()) { - LockGuard LG(driver->m_nodeMutex); - if( ValueInt* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueInt* value = static_cast(driver->GetValue(_id))) { - res = value->Set( _value ); + res = value->Set(_value); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValue"); } } } - } else if( ValueID::ValueType_BitSet == _id.GetType() ) + } + else if (ValueID::ValueType_BitSet == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - if( _id.GetNodeId() != driver->GetControllerNodeId() ) + if (_id.GetNodeId() != driver->GetControllerNodeId()) { - LockGuard LG(driver->m_nodeMutex); - if( ValueBitSet* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueBitSet* value = static_cast(driver->GetValue(_id))) { - if (value->GetSize() == 4) { + if (value->GetSize() == 4) + { res = value->Set(_value); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "BitSet ValueID is Not of Size 4 (SetValue uint32)"); } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValue"); } } } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to SetValue is not a Int Value"); } @@ -2970,32 +2808,31 @@ bool Manager::SetValue // // Sets the value from a collection of bytes //----------------------------------------------------------------------------- -bool Manager::SetValue -( - ValueID const& _id, - uint8 const* _value, - uint8 const _length -) +bool Manager::SetValue(ValueID const& _id, uint8 const* _value, uint8 const _length) { bool res = false; - if( ValueID::ValueType_Raw == _id.GetType() ) + if (ValueID::ValueType_Raw == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - if( _id.GetNodeId() != driver->GetControllerNodeId() ) + if (_id.GetNodeId() != driver->GetControllerNodeId()) { - LockGuard LG(driver->m_nodeMutex); - if( ValueRaw* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueRaw* value = static_cast(driver->GetValue(_id))) { - res = value->Set( _value, _length ); + res = value->Set(_value, _length); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValue"); } } } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to SetValue is not a Raw Value"); } @@ -3006,51 +2843,57 @@ bool Manager::SetValue // // Sets the value from a 16-bit signed integer //----------------------------------------------------------------------------- -bool Manager::SetValue -( - ValueID const& _id, - int16 const _value -) +bool Manager::SetValue(ValueID const& _id, int16 const _value) { bool res = false; - if( ValueID::ValueType_Short == _id.GetType() ) + if (ValueID::ValueType_Short == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - if( _id.GetNodeId() != driver->GetControllerNodeId() ) + if (_id.GetNodeId() != driver->GetControllerNodeId()) { - LockGuard LG(driver->m_nodeMutex); - if( ValueShort* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueShort* value = static_cast(driver->GetValue(_id))) { - res = value->Set( _value ); + res = value->Set(_value); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValue"); } } } - } else if( ValueID::ValueType_BitSet == _id.GetType() ) + } + else if (ValueID::ValueType_BitSet == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - if( _id.GetNodeId() != driver->GetControllerNodeId() ) + if (_id.GetNodeId() != driver->GetControllerNodeId()) { - LockGuard LG(driver->m_nodeMutex); - if( ValueBitSet* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueBitSet* value = static_cast(driver->GetValue(_id))) { - if (value->GetSize() == 2) { + if (value->GetSize() == 2) + { res = value->Set(_value); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "BitSet ValueID is Not of Size 2 (SetValue uint16)"); } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValue"); } } } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to SetValue is not a Short Value"); } @@ -3061,32 +2904,32 @@ bool Manager::SetValue // // Sets the selected item in a list by value //----------------------------------------------------------------------------- -bool Manager::SetValueListSelection -( - ValueID const& _id, - string const& _selectedItem -) +bool Manager::SetValueListSelection(ValueID const& _id, string const& _selectedItem) { bool res = false; - if( ValueID::ValueType_List == _id.GetType() ) + if (ValueID::ValueType_List == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - if( _id.GetNodeId() != driver->GetControllerNodeId() ) + if (_id.GetNodeId() != driver->GetControllerNodeId()) { - LockGuard LG(driver->m_nodeMutex); - if( ValueList* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueList* value = static_cast(driver->GetValue(_id))) { - res = value->SetByLabel( _selectedItem ); + res = value->SetByLabel(_selectedItem); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValueListSelection"); } } } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to SetValueListSelection is not a List Value"); } @@ -3097,134 +2940,148 @@ bool Manager::SetValueListSelection // // Sets the value from a string //----------------------------------------------------------------------------- -bool Manager::SetValue -( - ValueID const& _id, - string const& _value -) +bool Manager::SetValue(ValueID const& _id, string const& _value) { bool res = false; - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - if( _id.GetNodeId() != driver->GetControllerNodeId() ) + if (_id.GetNodeId() != driver->GetControllerNodeId()) { - LockGuard LG(driver->m_nodeMutex); + Internal::LockGuard LG(driver->m_nodeMutex); - switch( _id.GetType() ) + switch (_id.GetType()) { case ValueID::ValueType_BitSet: { - if( ValueBitSet* value = static_cast( driver->GetValue( _id ) ) ) + if (Internal::VC::ValueBitSet* value = static_cast(driver->GetValue(_id))) { res = value->SetFromString(_value); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValue"); } break; } case ValueID::ValueType_Bool: { - if( ValueBool* value = static_cast( driver->GetValue( _id ) ) ) + if (Internal::VC::ValueBool* value = static_cast(driver->GetValue(_id))) { - if( !strcasecmp( "true", _value.c_str() ) ) + if (!strcasecmp("true", _value.c_str())) { - res = value->Set( true ); + res = value->Set(true); } - else if( !strcasecmp( "false", _value.c_str() ) ) + else if (!strcasecmp("false", _value.c_str())) { - res = value->Set( false ); + res = value->Set(false); } value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValue"); } break; } case ValueID::ValueType_Byte: { - if( ValueByte* value = static_cast( driver->GetValue( _id ) ) ) + if (Internal::VC::ValueByte* value = static_cast(driver->GetValue(_id))) { - uint32 val = (uint32)atoi( _value.c_str() ); - if( val < 256 ) + uint32 val = (uint32) atoi(_value.c_str()); + if (val < 256) { - res = value->Set( (uint8)val ); + res = value->Set((uint8) val); } value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValue"); } break; } case ValueID::ValueType_Decimal: { - if( ValueDecimal* value = static_cast( driver->GetValue( _id ) ) ) + if (Internal::VC::ValueDecimal* value = static_cast(driver->GetValue(_id))) { - res = value->Set( _value ); + res = value->Set(_value); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValue"); } break; } case ValueID::ValueType_Int: { - if( ValueInt* value = static_cast( driver->GetValue( _id ) ) ) + if (Internal::VC::ValueInt* value = static_cast(driver->GetValue(_id))) { - int32 val = atoi( _value.c_str() ); - res = value->Set( val ); + int32 val = atoi(_value.c_str()); + res = value->Set(val); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValue"); } break; } case ValueID::ValueType_List: { - if( ValueList* value = static_cast( driver->GetValue( _id ) ) ) + if (Internal::VC::ValueList* value = static_cast(driver->GetValue(_id))) { - res = value->SetByLabel( _value ); + res = value->SetByLabel(_value); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValue"); } break; } case ValueID::ValueType_Short: { - if( ValueShort* value = static_cast( driver->GetValue( _id ) ) ) + if (Internal::VC::ValueShort* value = static_cast(driver->GetValue(_id))) { - int32 val = (uint32)atoi( _value.c_str() ); - if( ( val < 32768 ) && ( val >= -32768 ) ) + int32 val = (uint32) atoi(_value.c_str()); + if ((val < 32768) && (val >= -32768)) { - res = value->Set( (int16)val ); + res = value->Set((int16) val); } value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValue"); } break; } case ValueID::ValueType_String: { - if( ValueString* value = static_cast( driver->GetValue( _id ) ) ) + if (Internal::VC::ValueString* value = static_cast(driver->GetValue(_id))) { - res = value->Set( _value ); + res = value->Set(_value); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValue"); } break; } case ValueID::ValueType_Raw: { - if( ValueRaw* value = static_cast( driver->GetValue( _id ) ) ) + if (Internal::VC::ValueRaw* value = static_cast(driver->GetValue(_id))) { - res = value->SetFromString( _value ); + res = value->SetFromString(_value); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValue"); } break; @@ -3245,30 +3102,30 @@ bool Manager::SetValue // // Instruct the driver to refresh this value by sending a message to the device //----------------------------------------------------------------------------- -bool Manager::RefreshValue -( - ValueID const& _id -) +bool Manager::RefreshValue(ValueID const& _id) { bool bRet = false; // return value - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { Node *node; // Need to lock and unlock nodes to check this information - LockGuard LG(driver->m_nodeMutex); + Internal::LockGuard LG(driver->m_nodeMutex); - if( (node = driver->GetNode( _id.GetNodeId() ) ) != NULL) + if ((node = driver->GetNode(_id.GetNodeId())) != NULL) { - CommandClass* cc = node->GetCommandClass( _id.GetCommandClassId() ); - if (cc) { + Internal::CC::CommandClass* cc = node->GetCommandClass(_id.GetCommandClassId()); + if (cc) + { uint16_t index = _id.GetIndex(); uint8 instance = _id.GetInstance(); - Log::Write( LogLevel_Info, "mgr, Refreshing node %d: %s index = %d instance = %d (to confirm a reported change)", node->m_nodeId, cc->GetCommandClassName().c_str(), index, instance ); - cc->RequestValue( 0, index, instance, Driver::MsgQueue_Send ); + Log::Write(LogLevel_Info, "mgr, Refreshing node %d: %s index = %d instance = %d (to confirm a reported change)", node->m_nodeId, cc->GetCommandClassName().c_str(), index, instance); + cc->RequestValue(0, index, instance, Driver::MsgQueue_Send); bRet = true; - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to RefreshValue"); bRet = false; } @@ -3281,20 +3138,18 @@ bool Manager::RefreshValue // // Set the verify changes flag for the specified value //----------------------------------------------------------------------------- -void Manager::SetChangeVerified -( - ValueID const& _id, - bool _verify -) +void Manager::SetChangeVerified(ValueID const& _id, bool _verify) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( Value* value = driver->GetValue( _id ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::Value* value = driver->GetValue(_id)) { - value->SetChangeVerified( _verify ); + value->SetChangeVerified(_verify); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetChangeVerified"); } } @@ -3304,52 +3159,51 @@ void Manager::SetChangeVerified // // Get the verify changes flag for the specified value //----------------------------------------------------------------------------- -bool Manager::GetChangeVerified -( - ValueID const& _id -) +bool Manager::GetChangeVerified(ValueID const& _id) { bool res = false; - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( Value* value = driver->GetValue( _id ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::Value* value = driver->GetValue(_id)) { res = value->GetChangeVerified(); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetChangeVerified"); } } return res; } - //----------------------------------------------------------------------------- // // Starts an activity in a device. //----------------------------------------------------------------------------- -bool Manager::PressButton -( - ValueID const& _id -) +bool Manager::PressButton(ValueID const& _id) { bool res = false; - if( ValueID::ValueType_Button == _id.GetType() ) + if (ValueID::ValueType_Button == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( ValueButton* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueButton* value = static_cast(driver->GetValue(_id))) { res = value->PressButton(); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to PressButton"); } } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to PressButton is not a Button Value"); } @@ -3360,27 +3214,28 @@ bool Manager::PressButton // // Stops an activity in a device. //----------------------------------------------------------------------------- -bool Manager::ReleaseButton -( - ValueID const& _id -) +bool Manager::ReleaseButton(ValueID const& _id) { bool res = false; - if( ValueID::ValueType_Button == _id.GetType() ) + if (ValueID::ValueType_Button == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( ValueButton* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueButton* value = static_cast(driver->GetValue(_id))) { res = value->ReleaseButton(); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to ReleaseButton"); } } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to ReleaseButton is not a Button Value"); } @@ -3391,28 +3246,28 @@ bool Manager::ReleaseButton // // Sets a BitMask on a BitSet ValueID //----------------------------------------------------------------------------- -bool Manager::SetBitMask -( - ValueID const& _id, - uint32 _mask -) +bool Manager::SetBitMask(ValueID const& _id, uint32 _mask) { bool res = false; - if( ValueID::ValueType_BitSet == _id.GetType() ) + if (ValueID::ValueType_BitSet == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( ValueBitSet* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueBitSet* value = static_cast(driver->GetValue(_id))) { res = value->SetBitMask(_mask); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetBitMask"); } } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to SetBitMask is not a BitSet Value"); } @@ -3424,31 +3279,31 @@ bool Manager::SetBitMask // // Gets a BitMask on a BitSet ValueID //----------------------------------------------------------------------------- -bool Manager::GetBitMask -( - ValueID const& _id, - int32* o_mask -) +bool Manager::GetBitMask(ValueID const& _id, int32* o_mask) { bool res = false; - if( o_mask ) + if (o_mask) { - if( ValueID::ValueType_BitSet == _id.GetType() ) + if (ValueID::ValueType_BitSet == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( ValueBitSet* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueBitSet* value = static_cast(driver->GetValue(_id))) { *o_mask = value->GetBitMask(); value->Release(); res = true; - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetBitMask"); } } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetBitMask is not a BitSet Value"); } } @@ -3460,31 +3315,31 @@ bool Manager::GetBitMask // m_nodeMutex); - if( ValueBitSet* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueBitSet* value = static_cast(driver->GetValue(_id))) { *o_size = value->GetSize(); value->Release(); res = true; - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetBitSetSize"); } } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetBitSetSize is not a BitSet Value"); } } @@ -3492,9 +3347,6 @@ bool Manager::GetBitSetSize return res; } - - - //----------------------------------------------------------------------------- // Climate Control Schedules //----------------------------------------------------------------------------- @@ -3503,28 +3355,29 @@ bool Manager::GetBitSetSize // // Get the number of switch points defined in a schedule //----------------------------------------------------------------------------- -uint8 Manager::GetNumSwitchPoints -( - ValueID const& _id -) +uint8 Manager::GetNumSwitchPoints(ValueID const& _id) { // bool res = false; uint8 numSwitchPoints = 0; - if( ValueID::ValueType_Schedule == _id.GetType() ) + if (ValueID::ValueType_Schedule == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( ValueSchedule* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueSchedule* value = static_cast(driver->GetValue(_id))) { numSwitchPoints = value->GetNumSwitchPoints(); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetNumSwitchPoints"); } } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetNumSwitchPoints is not a Schedule Value"); } @@ -3535,30 +3388,28 @@ uint8 Manager::GetNumSwitchPoints // // Set a switch point in the schedule //----------------------------------------------------------------------------- -bool Manager::SetSwitchPoint -( - ValueID const& _id, - uint8 const _hours, - uint8 const _minutes, - int8 const _setback -) +bool Manager::SetSwitchPoint(ValueID const& _id, uint8 const _hours, uint8 const _minutes, int8 const _setback) { bool res = false; - if( ValueID::ValueType_Schedule == _id.GetType() ) + if (ValueID::ValueType_Schedule == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( ValueSchedule* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueSchedule* value = static_cast(driver->GetValue(_id))) { - res = value->SetSwitchPoint( _hours, _minutes, _setback ); + res = value->SetSwitchPoint(_hours, _minutes, _setback); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetSwitchPoint"); } } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to SetSwitchPoint is not a Schedule Value"); } @@ -3569,35 +3420,34 @@ bool Manager::SetSwitchPoint // // Remove a switch point from the schedule //----------------------------------------------------------------------------- -bool Manager::RemoveSwitchPoint -( - ValueID const& _id, - uint8 const _hours, - uint8 const _minutes -) +bool Manager::RemoveSwitchPoint(ValueID const& _id, uint8 const _hours, uint8 const _minutes) { bool res = false; - if( ValueID::ValueType_Schedule == _id.GetType() ) + if (ValueID::ValueType_Schedule == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( ValueSchedule* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueSchedule* value = static_cast(driver->GetValue(_id))) { uint8 idx; - res = value->FindSwitchPoint( _hours, _minutes, &idx ); + res = value->FindSwitchPoint(_hours, _minutes, &idx); - if( res ) + if (res) { - res = value->RemoveSwitchPoint( idx ); + res = value->RemoveSwitchPoint(idx); } value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to RemoveSwitchPoint"); } } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to RemoveSwitchPoint is not a Schedule Value"); } @@ -3608,25 +3458,26 @@ bool Manager::RemoveSwitchPoint // // Clears all switch points from the schedule //----------------------------------------------------------------------------- -void Manager::ClearSwitchPoints -( - ValueID const& _id -) +void Manager::ClearSwitchPoints(ValueID const& _id) { - if( ValueID::ValueType_Schedule == _id.GetType() ) + if (ValueID::ValueType_Schedule == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( ValueSchedule* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueSchedule* value = static_cast(driver->GetValue(_id))) { value->ClearSwitchPoints(); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to ClearSwitchPoints"); } } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to ClearSwitchPoints is not a Schedule Value"); } } @@ -3635,31 +3486,28 @@ void Manager::ClearSwitchPoints // // Gets switch point data from the schedule //----------------------------------------------------------------------------- -bool Manager::GetSwitchPoint -( - ValueID const& _id, - uint8 const _idx, - uint8* o_hours, - uint8* o_minutes, - int8* o_setback -) +bool Manager::GetSwitchPoint(ValueID const& _id, uint8 const _idx, uint8* o_hours, uint8* o_minutes, int8* o_setback) { bool res = false; - if( ValueID::ValueType_Schedule == _id.GetType() ) + if (ValueID::ValueType_Schedule == _id.GetType()) { - if( Driver* driver = GetDriver( _id.GetHomeId() ) ) + if (Driver* driver = GetDriver(_id.GetHomeId())) { - LockGuard LG(driver->m_nodeMutex); - if( ValueSchedule* value = static_cast( driver->GetValue( _id ) ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + if (Internal::VC::ValueSchedule* value = static_cast(driver->GetValue(_id))) { - res = value->GetSwitchPoint( _idx, o_hours, o_minutes, o_setback ); + res = value->GetSwitchPoint(_idx, o_hours, o_minutes, o_setback); value->Release(); - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetSwitchPoint"); } } - } else { + } + else + { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetSwitchPoint is not a Schedule Value"); } @@ -3674,12 +3522,9 @@ bool Manager::GetSwitchPoint // // All devices that support the SwitchAll command class will be turned on //----------------------------------------------------------------------------- -void Manager::SwitchAllOn -( - uint32 const _homeId -) +void Manager::SwitchAllOn(uint32 const _homeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { return driver->SwitchAllOn(); } @@ -3689,12 +3534,9 @@ void Manager::SwitchAllOn // // All devices that support the SwitchAll command class will be turned off //----------------------------------------------------------------------------- -void Manager::SwitchAllOff -( - uint32 const _homeId -) +void Manager::SwitchAllOff(uint32 const _homeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { return driver->SwitchAllOff(); } @@ -3708,18 +3550,11 @@ void Manager::SwitchAllOff // // Set the value of one of the configuration parameters of a device //----------------------------------------------------------------------------- -bool Manager::SetConfigParam -( - uint32 const _homeId, - uint8 const _nodeId, - uint8 const _param, - int32 _value, - uint8 const _size -) +bool Manager::SetConfigParam(uint32 const _homeId, uint8 const _nodeId, uint8 const _param, int32 _value, uint8 const _size) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - return driver->SetConfigParam( _nodeId, _param, _value, _size ); + return driver->SetConfigParam(_nodeId, _param, _value, _size); } return false; @@ -3729,16 +3564,11 @@ bool Manager::SetConfigParam // // Request the value of one of the configuration parameters of a device //----------------------------------------------------------------------------- -void Manager::RequestConfigParam -( - uint32 const _homeId, - uint8 const _nodeId, - uint8 const _param -) +void Manager::RequestConfigParam(uint32 const _homeId, uint8 const _nodeId, uint8 const _param) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - driver->RequestConfigParam( _nodeId, _param ); + driver->RequestConfigParam(_nodeId, _param); } } @@ -3746,19 +3576,15 @@ void Manager::RequestConfigParam // // Request the values of all of the known configuration parameters of a device //----------------------------------------------------------------------------- -void Manager::RequestAllConfigParams -( - uint32 const _homeId, - uint8 const _nodeId -) +void Manager::RequestAllConfigParams(uint32 const _homeId, uint8 const _nodeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - LockGuard LG(driver->m_nodeMutex); - Node* node = driver->GetNode( _nodeId ); - if( node ) + Internal::LockGuard LG(driver->m_nodeMutex); + Node* node = driver->GetNode(_nodeId); + if (node) { - node->SetQueryStage( Node::QueryStage_Configuration ); + node->SetQueryStage(Node::QueryStage_Configuration); } } } @@ -3771,15 +3597,11 @@ void Manager::RequestAllConfigParams // // Gets the number of association groups reported by this node //----------------------------------------------------------------------------- -uint8 Manager::GetNumGroups -( - uint32 const _homeId, - uint8 const _nodeId -) +uint8 Manager::GetNumGroups(uint32 const _homeId, uint8 const _nodeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - return driver->GetNumGroups( _nodeId ); + return driver->GetNumGroups(_nodeId); } return 0; @@ -3789,17 +3611,11 @@ uint8 Manager::GetNumGroups // // Gets the associations for a group //----------------------------------------------------------------------------- -uint32 Manager::GetAssociations -( - uint32 const _homeId, - uint8 const _nodeId, - uint8 const _groupIdx, - uint8** o_associations -) +uint32 Manager::GetAssociations(uint32 const _homeId, uint8 const _nodeId, uint8 const _groupIdx, uint8** o_associations) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - return driver->GetAssociations( _nodeId, _groupIdx, o_associations ); + return driver->GetAssociations(_nodeId, _groupIdx, o_associations); } return 0; @@ -3808,18 +3624,14 @@ uint32 Manager::GetAssociations //----------------------------------------------------------------------------- // // Gets the associations for a group +// struct InstanceAssociation is defined in Group.h and contains +// a (NodeID, End Point) pair. //----------------------------------------------------------------------------- -uint32 Manager::GetAssociations -( - uint32 const _homeId, - uint8 const _nodeId, - uint8 const _groupIdx, - InstanceAssociation** o_associations -) +uint32 Manager::GetAssociations(uint32 const _homeId, uint8 const _nodeId, uint8 const _groupIdx, InstanceAssociation** o_associations) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - return driver->GetAssociations( _nodeId, _groupIdx, o_associations ); + return driver->GetAssociations(_nodeId, _groupIdx, o_associations); } return 0; @@ -3829,16 +3641,11 @@ uint32 Manager::GetAssociations // // Gets the maximum number of associations for a group //----------------------------------------------------------------------------- -uint8 Manager::GetMaxAssociations -( - uint32 const _homeId, - uint8 const _nodeId, - uint8 const _groupIdx -) +uint8 Manager::GetMaxAssociations(uint32 const _homeId, uint8 const _nodeId, uint8 const _groupIdx) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - return driver->GetMaxAssociations( _nodeId, _groupIdx ); + return driver->GetMaxAssociations(_nodeId, _groupIdx); } return 0; @@ -3848,16 +3655,11 @@ uint8 Manager::GetMaxAssociations // // Returns true is group supports multi instance. //----------------------------------------------------------------------------- -bool Manager::IsMultiInstance -( - uint32 const _homeId, - uint8 const _nodeId, - uint8 const _groupIdx -) +bool Manager::IsMultiInstance(uint32 const _homeId, uint8 const _nodeId, uint8 const _groupIdx) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - return driver->IsMultiInstance( _nodeId, _groupIdx ); + return driver->IsMultiInstance(_nodeId, _groupIdx); } return 0; } @@ -3866,16 +3668,11 @@ bool Manager::IsMultiInstance // // Gets the label for a particular group //----------------------------------------------------------------------------- -string Manager::GetGroupLabel -( - uint32 const _homeId, - uint8 const _nodeId, - uint8 const _groupIdx -) +string Manager::GetGroupLabel(uint32 const _homeId, uint8 const _nodeId, uint8 const _groupIdx) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - return driver->GetGroupLabel( _nodeId, _groupIdx ); + return driver->GetGroupLabel(_nodeId, _groupIdx); } return ""; @@ -3885,18 +3682,11 @@ string Manager::GetGroupLabel // // Adds a node to an association group //----------------------------------------------------------------------------- -void Manager::AddAssociation -( - uint32 const _homeId, - uint8 const _nodeId, - uint8 const _groupIdx, - uint8 const _targetNodeId, - uint8 const _instance -) +void Manager::AddAssociation(uint32 const _homeId, uint8 const _nodeId, uint8 const _groupIdx, uint8 const _targetNodeId, uint8 const _endPoint) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - driver->AddAssociation( _nodeId, _groupIdx, _targetNodeId, _instance ); + driver->AddAssociation(_nodeId, _groupIdx, _targetNodeId, _endPoint); } } @@ -3904,22 +3694,14 @@ void Manager::AddAssociation // // Removes a node from an association group //----------------------------------------------------------------------------- -void Manager::RemoveAssociation -( - uint32 const _homeId, - uint8 const _nodeId, - uint8 const _groupIdx, - uint8 const _targetNodeId, - uint8 const _instance -) +void Manager::RemoveAssociation(uint32 const _homeId, uint8 const _nodeId, uint8 const _groupIdx, uint8 const _targetNodeId, uint8 const _endPoint) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - driver->RemoveAssociation( _nodeId, _groupIdx, _targetNodeId, _instance ); + driver->RemoveAssociation(_nodeId, _groupIdx, _targetNodeId, _endPoint); } } - //----------------------------------------------------------------------------- // Notifications //----------------------------------------------------------------------------- @@ -3928,17 +3710,13 @@ void Manager::RemoveAssociation // // Add a watcher to the list //----------------------------------------------------------------------------- -bool Manager::AddWatcher -( - pfnOnNotification_t _watcher, - void* _context -) +bool Manager::AddWatcher(pfnOnNotification_t _watcher, void* _context) { // Ensure this watcher is not already on the list m_notificationMutex->Lock(); - for( list::iterator it = m_watchers.begin(); it != m_watchers.end(); ++it ) + for (list::iterator it = m_watchers.begin(); it != m_watchers.end(); ++it) { - if( ((*it)->m_callback == _watcher ) && ( (*it)->m_context == _context ) ) + if (((*it)->m_callback == _watcher) && ((*it)->m_context == _context)) { // Already in the list m_notificationMutex->Unlock(); @@ -3946,7 +3724,7 @@ bool Manager::AddWatcher } } - m_watchers.push_back( new Watcher( _watcher, _context ) ); + m_watchers.push_back(new Watcher(_watcher, _context)); m_notificationMutex->Unlock(); return true; } @@ -3955,23 +3733,19 @@ bool Manager::AddWatcher // // Remove a watcher from the list //----------------------------------------------------------------------------- -bool Manager::RemoveWatcher -( - pfnOnNotification_t _watcher, - void* _context -) +bool Manager::RemoveWatcher(pfnOnNotification_t _watcher, void* _context) { m_notificationMutex->Lock(); list::iterator it = m_watchers.begin(); - while( it != m_watchers.end() ) + while (it != m_watchers.end()) { - if( ((*it)->m_callback == _watcher ) && ( (*it)->m_context == _context ) ) + if (((*it)->m_callback == _watcher) && ((*it)->m_context == _context)) { delete (*it); - list::iterator next = m_watchers.erase( it ); - for( list::iterator*>::iterator extIt = m_watcherIterators.begin(); extIt != m_watcherIterators.end(); ++extIt ) + list::iterator next = m_watchers.erase(it); + for (list::iterator*>::iterator extIt = m_watcherIterators.begin(); extIt != m_watcherIterators.end(); ++extIt) { - if( (**extIt) == it ) + if ((**extIt) == it) { (**extIt) = next; } @@ -3990,18 +3764,15 @@ bool Manager::RemoveWatcher // // Notify any watching objects of a value change //----------------------------------------------------------------------------- -void Manager::NotifyWatchers -( - Notification* _notification -) +void Manager::NotifyWatchers(Notification* _notification) { m_notificationMutex->Lock(); list::iterator it = m_watchers.begin(); m_watcherIterators.push_back(&it); - while( it != m_watchers.end() ) + while (it != m_watchers.end()) { Watcher* pWatcher = *(it++); - pWatcher->m_callback( _notification, pWatcher->m_context ); + pWatcher->m_callback(_notification, pWatcher->m_context); } m_watcherIterators.pop_back(); m_notificationMutex->Unlock(); @@ -4015,38 +3786,31 @@ void Manager::NotifyWatchers // // Reset controller and erase all node information //----------------------------------------------------------------------------- -void Manager::ResetController -( - uint32 const _homeId -) +void Manager::ResetController(uint32 const _homeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - Event *event = new Event(); - driver->ResetController( event ); - Wait::Single( event ); + Internal::Platform::Event *event = new Internal::Platform::Event(); + driver->ResetController(event); + Internal::Platform::Wait::Single(event); event->Release(); string path = driver->GetControllerPath(); Driver::ControllerInterface intf = driver->GetControllerInterfaceType(); - RemoveDriver( path ); - AddDriver( path, intf ); - Wait::Multiple( NULL, 0, 500 ); - } -OPENZWAVE_DEPRECATED_WARNINGS_OFF; - RemoveAllScenes( _homeId ); -OPENZWAVE_DEPRECATED_WARNINGS_ON; + RemoveDriver(path); + AddDriver(path, intf); + Internal::Platform::Wait::Multiple( NULL, 0, 500); + } OPENZWAVE_DEPRECATED_WARNINGS_OFF; + RemoveAllScenes(_homeId); + OPENZWAVE_DEPRECATED_WARNINGS_ON; } //----------------------------------------------------------------------------- // // Soft-reset the Z-Wave controller chip //----------------------------------------------------------------------------- -void Manager::SoftReset -( - uint32 const _homeId -) +void Manager::SoftReset(uint32 const _homeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { driver->SoftReset(); } @@ -4056,20 +3820,16 @@ void Manager::SoftReset // // Start the controller performing one of its network management functions //----------------------------------------------------------------------------- -bool Manager::BeginControllerCommand -( - uint32 const _homeId, - Driver::ControllerCommand _command, - Driver::pfnControllerCallback_t _callback, // = NULL +bool Manager::BeginControllerCommand(uint32 const _homeId, Driver::ControllerCommand _command, Driver::pfnControllerCallback_t _callback, // = NULL void* _context, // = NULL bool _highPower, // = false uint8 _nodeId, // = 0xff uint8 _arg // = 0 -) + ) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - return driver->BeginControllerCommand( _command, _callback, _context, _highPower, _nodeId, _arg ); + return driver->BeginControllerCommand(_command, _callback, _context, _highPower, _nodeId, _arg); } return false; @@ -4079,14 +3839,11 @@ bool Manager::BeginControllerCommand // // Stop the current controller function //----------------------------------------------------------------------------- -bool Manager::CancelControllerCommand -( - uint32 const _homeId -) +bool Manager::CancelControllerCommand(uint32 const _homeId) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - return( driver->CancelControllerCommand() ); + return (driver->CancelControllerCommand()); } return false; @@ -4096,16 +3853,11 @@ bool Manager::CancelControllerCommand // // Send a number of test messages to a node and record results. //----------------------------------------------------------------------------- -void Manager::TestNetworkNode -( - uint32 const _homeId, - uint8 const _nodeId, - uint32 const _count -) +void Manager::TestNetworkNode(uint32 const _homeId, uint8 const _nodeId, uint32 const _count) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - driver->TestNetwork( _nodeId, _count ); + driver->TestNetwork(_nodeId, _count); } } @@ -4113,15 +3865,11 @@ void Manager::TestNetworkNode // // Send a number of test messages to every node and record results. //----------------------------------------------------------------------------- -void Manager::TestNetwork -( - uint32 const _homeId, - uint32 const _count -) +void Manager::TestNetwork(uint32 const _homeId, uint32 const _count) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - driver->TestNetwork( 0, _count ); + driver->TestNetwork(0, _count); } } @@ -4129,23 +3877,18 @@ void Manager::TestNetwork // // Heal a single node in the network //----------------------------------------------------------------------------- -void Manager::HealNetworkNode -( - uint32 const _homeId, - uint8 const _nodeId, - bool _doRR -) +void Manager::HealNetworkNode(uint32 const _homeId, uint8 const _nodeId, bool _doRR) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - LockGuard LG(driver->m_nodeMutex); - Node* node = driver->GetNode( _nodeId ); - if( node ) + Internal::LockGuard LG(driver->m_nodeMutex); + Node* node = driver->GetNode(_nodeId); + if (node) { - driver->BeginControllerCommand( Driver::ControllerCommand_RequestNodeNeighborUpdate, NULL, NULL, true, _nodeId, 0 ); - if( _doRR ) + driver->BeginControllerCommand(Driver::ControllerCommand_RequestNodeNeighborUpdate, NULL, NULL, true, _nodeId, 0); + if (_doRR) { - driver->UpdateNodeRoutes( _nodeId, true ); + driver->UpdateNodeRoutes(_nodeId, true); } } } @@ -4155,23 +3898,19 @@ void Manager::HealNetworkNode // // Heal the Z-Wave network one node at a time. //----------------------------------------------------------------------------- -void Manager::HealNetwork -( - uint32 const _homeId, - bool _doRR -) +void Manager::HealNetwork(uint32 const _homeId, bool _doRR) { - if( Driver* driver = GetDriver( _homeId ) ) + if (Driver* driver = GetDriver(_homeId)) { - LockGuard LG(driver->m_nodeMutex); - for( uint8 i=0; i<255; i++ ) + Internal::LockGuard LG(driver->m_nodeMutex); + for (uint8 i = 0; i < 255; i++) { - if( driver->m_nodes[i] != NULL ) + if (driver->m_nodes[i] != NULL) { - driver->BeginControllerCommand( Driver::ControllerCommand_RequestNodeNeighborUpdate, NULL, NULL, true, i, 0 ); - if( _doRR ) + driver->BeginControllerCommand(Driver::ControllerCommand_RequestNodeNeighborUpdate, NULL, NULL, true, i, 0); + if (_doRR) { - driver->UpdateNodeRoutes( i, true ); + driver->UpdateNodeRoutes(i, true); } } } @@ -4181,17 +3920,14 @@ void Manager::HealNetwork // // Add a Device to the Network. //----------------------------------------------------------------------------- -bool Manager::AddNode -( - uint32 const _homeId, bool _doSecurity -) +bool Manager::AddNode(uint32 const _homeId, bool _doSecurity) { - if (Driver *driver = GetDriver( _homeId ) ) { - LockGuard LG(driver->m_nodeMutex); + if (Driver *driver = GetDriver(_homeId)) + { + Internal::LockGuard LG(driver->m_nodeMutex); /* we use the Args option to communicate if Security CC should be initialized */ - return driver->BeginControllerCommand( - Driver::ControllerCommand_AddDevice, - NULL, NULL, true, 0, (_doSecurity == true ? 1 : 0)); + return driver->BeginControllerCommand(Driver::ControllerCommand_AddDevice, + NULL, NULL, true, 0, (_doSecurity == true ? 1 : 0)); } return false; } @@ -4200,16 +3936,13 @@ bool Manager::AddNode // // Remove a Device from the Network. //----------------------------------------------------------------------------- -bool Manager::RemoveNode -( - uint32 const _homeId -) +bool Manager::RemoveNode(uint32 const _homeId) { - if (Driver *driver = GetDriver( _homeId ) ) { - LockGuard LG(driver->m_nodeMutex); - return driver->BeginControllerCommand( - Driver::ControllerCommand_RemoveDevice, - NULL, NULL, true, 0, 0); + if (Driver *driver = GetDriver(_homeId)) + { + Internal::LockGuard LG(driver->m_nodeMutex); + return driver->BeginControllerCommand(Driver::ControllerCommand_RemoveDevice, + NULL, NULL, true, 0, 0); } return false; } @@ -4218,17 +3951,13 @@ bool Manager::RemoveNode // // Remove a Specific Device from the network if its non-responsive. //----------------------------------------------------------------------------- -bool Manager::RemoveFailedNode -( - uint32 const _homeId, - uint8 const _nodeId -) +bool Manager::RemoveFailedNode(uint32 const _homeId, uint8 const _nodeId) { - if (Driver *driver = GetDriver( _homeId ) ) { - LockGuard LG(driver->m_nodeMutex); - return driver->BeginControllerCommand( - Driver::ControllerCommand_RemoveFailedNode, - NULL, NULL, true, _nodeId, 0); + if (Driver *driver = GetDriver(_homeId)) + { + Internal::LockGuard LG(driver->m_nodeMutex); + return driver->BeginControllerCommand(Driver::ControllerCommand_RemoveFailedNode, + NULL, NULL, true, _nodeId, 0); } return false; } @@ -4237,17 +3966,13 @@ bool Manager::RemoveFailedNode // // Test if the Controller Believes the Node has Failed. //----------------------------------------------------------------------------- -bool Manager::HasNodeFailed -( - uint32 const _homeId, - uint8 const _nodeId -) +bool Manager::HasNodeFailed(uint32 const _homeId, uint8 const _nodeId) { - if (Driver *driver = GetDriver( _homeId ) ) { - LockGuard LG(driver->m_nodeMutex); - return driver->BeginControllerCommand( - Driver::ControllerCommand_HasNodeFailed, - NULL, NULL, true, _nodeId, 0); + if (Driver *driver = GetDriver(_homeId)) + { + Internal::LockGuard LG(driver->m_nodeMutex); + return driver->BeginControllerCommand(Driver::ControllerCommand_HasNodeFailed, + NULL, NULL, true, _nodeId, 0); } return false; } @@ -4256,17 +3981,13 @@ bool Manager::HasNodeFailed // // Ask a Node to update its Return Route to the Controller //----------------------------------------------------------------------------- -bool Manager::AssignReturnRoute -( - uint32 const _homeId, - uint8 const _nodeId -) +bool Manager::AssignReturnRoute(uint32 const _homeId, uint8 const _nodeId) { - if (Driver *driver = GetDriver( _homeId ) ) { - LockGuard LG(driver->m_nodeMutex); - return driver->BeginControllerCommand( - Driver::ControllerCommand_AssignReturnRoute, - NULL, NULL, true, _nodeId, 0); + if (Driver *driver = GetDriver(_homeId)) + { + Internal::LockGuard LG(driver->m_nodeMutex); + return driver->BeginControllerCommand(Driver::ControllerCommand_AssignReturnRoute, + NULL, NULL, true, _nodeId, 0); } return false; } @@ -4275,37 +3996,28 @@ bool Manager::AssignReturnRoute // // Ask a Node to update its Neighbor Table. //----------------------------------------------------------------------------- -bool Manager::RequestNodeNeighborUpdate -( - uint32 const _homeId, - uint8 const _nodeId -) +bool Manager::RequestNodeNeighborUpdate(uint32 const _homeId, uint8 const _nodeId) { - if (Driver *driver = GetDriver( _homeId ) ) { - LockGuard LG(driver->m_nodeMutex); - return driver->BeginControllerCommand( - Driver::ControllerCommand_RequestNodeNeighborUpdate, - NULL, NULL, true, _nodeId, 0); + if (Driver *driver = GetDriver(_homeId)) + { + Internal::LockGuard LG(driver->m_nodeMutex); + return driver->BeginControllerCommand(Driver::ControllerCommand_RequestNodeNeighborUpdate, + NULL, NULL, true, _nodeId, 0); } return false; } - //----------------------------------------------------------------------------- // // Ask a Node to delete all its Return Routes //----------------------------------------------------------------------------- -bool Manager::DeleteAllReturnRoutes -( - uint32 const _homeId, - uint8 const _nodeId -) +bool Manager::DeleteAllReturnRoutes(uint32 const _homeId, uint8 const _nodeId) { - if (Driver *driver = GetDriver( _homeId ) ) { - LockGuard LG(driver->m_nodeMutex); - return driver->BeginControllerCommand( - Driver::ControllerCommand_DeleteAllReturnRoutes, - NULL, NULL, true, _nodeId, 0); + if (Driver *driver = GetDriver(_homeId)) + { + Internal::LockGuard LG(driver->m_nodeMutex); + return driver->BeginControllerCommand(Driver::ControllerCommand_DeleteAllReturnRoutes, + NULL, NULL, true, _nodeId, 0); } return false; } @@ -4314,17 +4026,13 @@ bool Manager::DeleteAllReturnRoutes // // Send a NIF frame from the Controller to the Node //----------------------------------------------------------------------------- -bool Manager::SendNodeInformation -( - uint32 const _homeId, - uint8 const _nodeId -) +bool Manager::SendNodeInformation(uint32 const _homeId, uint8 const _nodeId) { - if (Driver *driver = GetDriver( _homeId ) ) { - LockGuard LG(driver->m_nodeMutex); - return driver->BeginControllerCommand( - Driver::ControllerCommand_SendNodeInformation, - NULL, NULL, true, _nodeId, 0); + if (Driver *driver = GetDriver(_homeId)) + { + Internal::LockGuard LG(driver->m_nodeMutex); + return driver->BeginControllerCommand(Driver::ControllerCommand_SendNodeInformation, + NULL, NULL, true, _nodeId, 0); } return false; } @@ -4333,16 +4041,13 @@ bool Manager::SendNodeInformation // // Send a NIF frame from the Controller to the Node //----------------------------------------------------------------------------- -bool Manager::CreateNewPrimary -( - uint32 const _homeId -) +bool Manager::CreateNewPrimary(uint32 const _homeId) { - if (Driver *driver = GetDriver( _homeId ) ) { - LockGuard LG(driver->m_nodeMutex); - return driver->BeginControllerCommand( - Driver::ControllerCommand_CreateNewPrimary, - NULL, NULL, true, 0, 0); + if (Driver *driver = GetDriver(_homeId)) + { + Internal::LockGuard LG(driver->m_nodeMutex); + return driver->BeginControllerCommand(Driver::ControllerCommand_CreateNewPrimary, + NULL, NULL, true, 0, 0); } return false; } @@ -4351,16 +4056,13 @@ bool Manager::CreateNewPrimary // // Send a NIF frame from the Controller to the Node //----------------------------------------------------------------------------- -bool Manager::ReceiveConfiguration -( - uint32 const _homeId -) +bool Manager::ReceiveConfiguration(uint32 const _homeId) { - if (Driver *driver = GetDriver( _homeId ) ) { - LockGuard LG(driver->m_nodeMutex); - return driver->BeginControllerCommand( - Driver::ControllerCommand_ReceiveConfiguration, - NULL, NULL, true, 0, 0); + if (Driver *driver = GetDriver(_homeId)) + { + Internal::LockGuard LG(driver->m_nodeMutex); + return driver->BeginControllerCommand(Driver::ControllerCommand_ReceiveConfiguration, + NULL, NULL, true, 0, 0); } return false; } @@ -4369,17 +4071,13 @@ bool Manager::ReceiveConfiguration // // Send a NIF frame from the Controller to the Node //----------------------------------------------------------------------------- -bool Manager::ReplaceFailedNode -( - uint32 const _homeId, - uint8 const _nodeId -) +bool Manager::ReplaceFailedNode(uint32 const _homeId, uint8 const _nodeId) { - if (Driver *driver = GetDriver( _homeId ) ) { - LockGuard LG(driver->m_nodeMutex); - return driver->BeginControllerCommand( - Driver::ControllerCommand_ReplaceFailedNode, - NULL, NULL, true, _nodeId, 0); + if (Driver *driver = GetDriver(_homeId)) + { + Internal::LockGuard LG(driver->m_nodeMutex); + return driver->BeginControllerCommand(Driver::ControllerCommand_ReplaceFailedNode, + NULL, NULL, true, _nodeId, 0); } return false; } @@ -4388,16 +4086,13 @@ bool Manager::ReplaceFailedNode // // Send a NIF frame from the Controller to the Node //----------------------------------------------------------------------------- -bool Manager::TransferPrimaryRole -( - uint32 const _homeId -) +bool Manager::TransferPrimaryRole(uint32 const _homeId) { - if (Driver *driver = GetDriver( _homeId ) ) { - LockGuard LG(driver->m_nodeMutex); - return driver->BeginControllerCommand( - Driver::ControllerCommand_TransferPrimaryRole, - NULL, NULL, true, 0, 0); + if (Driver *driver = GetDriver(_homeId)) + { + Internal::LockGuard LG(driver->m_nodeMutex); + return driver->BeginControllerCommand(Driver::ControllerCommand_TransferPrimaryRole, + NULL, NULL, true, 0, 0); } return false; } @@ -4406,17 +4101,13 @@ bool Manager::TransferPrimaryRole // // Send a NIF frame from the Controller to the Node //----------------------------------------------------------------------------- -bool Manager::RequestNetworkUpdate -( - uint32 const _homeId, - uint8 const _nodeId -) +bool Manager::RequestNetworkUpdate(uint32 const _homeId, uint8 const _nodeId) { - if (Driver *driver = GetDriver( _homeId ) ) { - LockGuard LG(driver->m_nodeMutex); - return driver->BeginControllerCommand( - Driver::ControllerCommand_RequestNetworkUpdate, - NULL, NULL, true, _nodeId, 0); + if (Driver *driver = GetDriver(_homeId)) + { + Internal::LockGuard LG(driver->m_nodeMutex); + return driver->BeginControllerCommand(Driver::ControllerCommand_RequestNetworkUpdate, + NULL, NULL, true, _nodeId, 0); } return false; } @@ -4425,17 +4116,13 @@ bool Manager::RequestNetworkUpdate // // Send a NIF frame from the Controller to the Node //----------------------------------------------------------------------------- -bool Manager::ReplicationSend -( - uint32 const _homeId, - uint8 const _nodeId -) +bool Manager::ReplicationSend(uint32 const _homeId, uint8 const _nodeId) { - if (Driver *driver = GetDriver( _homeId ) ) { - LockGuard LG(driver->m_nodeMutex); - return driver->BeginControllerCommand( - Driver::ControllerCommand_ReplicationSend, - NULL, NULL, true, _nodeId, 0); + if (Driver *driver = GetDriver(_homeId)) + { + Internal::LockGuard LG(driver->m_nodeMutex); + return driver->BeginControllerCommand(Driver::ControllerCommand_ReplicationSend, + NULL, NULL, true, _nodeId, 0); } return false; } @@ -4444,18 +4131,13 @@ bool Manager::ReplicationSend // // Send a NIF frame from the Controller to the Node //----------------------------------------------------------------------------- -bool Manager::CreateButton -( - uint32 const _homeId, - uint8 const _nodeId, - uint8 const _buttonid -) +bool Manager::CreateButton(uint32 const _homeId, uint8 const _nodeId, uint8 const _buttonid) { - if (Driver *driver = GetDriver( _homeId ) ) { - LockGuard LG(driver->m_nodeMutex); - return driver->BeginControllerCommand( - Driver::ControllerCommand_CreateButton, - NULL, NULL, true, _nodeId, _buttonid); + if (Driver *driver = GetDriver(_homeId)) + { + Internal::LockGuard LG(driver->m_nodeMutex); + return driver->BeginControllerCommand(Driver::ControllerCommand_CreateButton, + NULL, NULL, true, _nodeId, _buttonid); } return false; } @@ -4464,18 +4146,13 @@ bool Manager::CreateButton // // Send a NIF frame from the Controller to the Node //----------------------------------------------------------------------------- -bool Manager::DeleteButton -( - uint32 const _homeId, - uint8 const _nodeId, - uint8 const _buttonid -) +bool Manager::DeleteButton(uint32 const _homeId, uint8 const _nodeId, uint8 const _buttonid) { - if (Driver *driver = GetDriver( _homeId ) ) { - LockGuard LG(driver->m_nodeMutex); - return driver->BeginControllerCommand( - Driver::ControllerCommand_DeleteButton, - NULL, NULL, true, _nodeId, _buttonid); + if (Driver *driver = GetDriver(_homeId)) + { + Internal::LockGuard LG(driver->m_nodeMutex); + return driver->BeginControllerCommand(Driver::ControllerCommand_DeleteButton, + NULL, NULL, true, _nodeId, _buttonid); } return false; } @@ -4483,757 +4160,590 @@ bool Manager::DeleteButton //----------------------------------------------------------------------------- // // Send a custom message to a node. +// XXX TODO - Move the implementation to the Driver Class //----------------------------------------------------------------------------- -void Manager::SendRawData -( - uint32 const _homeId, - uint8 const _nodeId, - string const& _logText, - uint8 const _msgType, - bool const _sendSecure, - uint8 const* _content, - uint8 const _length -) +void Manager::SendRawData(uint32 const _homeId, uint8 const _nodeId, string const& _logText, uint8 const _msgType, bool const _sendSecure, uint8 const* _content, uint8 const _length) { - if ( Driver *driver = GetDriver( _homeId ) ) + if (Driver *driver = GetDriver(_homeId)) { - LockGuard LG(driver->m_nodeMutex); - Node* node = driver->GetNode( _nodeId ); - if ( node ) + Internal::LockGuard LG(driver->m_nodeMutex); + Node* node = driver->GetNode(_nodeId); + if (node) { - Msg* msg = new Msg( _logText, _nodeId, _msgType, FUNC_ID_ZW_SEND_DATA, true ); - for( uint8 i = 0; i < _length; i++ ) + Internal::Msg* msg = new Internal::Msg(_logText, _nodeId, _msgType, FUNC_ID_ZW_SEND_DATA, true); + for (uint8 i = 0; i < _length; i++) { - msg->Append( _content[i] ); + msg->Append(_content[i]); } - msg->Append( driver->GetTransmitOptions() ); - if ( _sendSecure ) + msg->Append(driver->GetTransmitOptions()); + if (_sendSecure) { msg->setEncrypted(); } - driver->SendMsg( msg, Driver::MsgQueue_Send ); + driver->SendMsg(msg, Driver::MsgQueue_Send); } } } - //----------------------------------------------------------------------------- // // Return the number of defined scenes. //----------------------------------------------------------------------------- -uint8 Manager::GetNumScenes -( -) +uint8 Manager::GetNumScenes() { - return Scene::s_sceneCnt; + return Internal::Scene::s_sceneCnt; } //----------------------------------------------------------------------------- // // Return an array of all Scene Ids //----------------------------------------------------------------------------- -uint8 Manager::GetAllScenes -( - uint8** _sceneIds -) +uint8 Manager::GetAllScenes(uint8** _sceneIds) { *_sceneIds = NULL; - return Scene::GetAllScenes( _sceneIds ); + return Internal::Scene::GetAllScenes(_sceneIds); } //----------------------------------------------------------------------------- // // Remove every scene id //----------------------------------------------------------------------------- -void Manager::RemoveAllScenes -( - uint32 const _homeId -) +void Manager::RemoveAllScenes(uint32 const _homeId) { - for( int i = 1; i < 256; i++ ) + for (int i = 1; i < 256; i++) { - if( _homeId == 0 ) // remove every device from every scene + if (_homeId == 0) // remove every device from every scene { OPENZWAVE_DEPRECATED_WARNINGS_OFF - RemoveScene( i ); - OPENZWAVE_DEPRECATED_WARNINGS_ON - } - else + RemoveScene(i); + OPENZWAVE_DEPRECATED_WARNINGS_ON + } + else + { + Internal::Scene *scene = Internal::Scene::Get(i); + if (scene != NULL) { - Scene *scene = Scene::Get( i ); - if( scene != NULL ) - { - scene->RemoveValues( _homeId ); - } + scene->RemoveValues(_homeId); } } } +} //----------------------------------------------------------------------------- // // Create a new scene and return new Scene ID. //----------------------------------------------------------------------------- -uint8 Manager::CreateScene -( -) +uint8 Manager::CreateScene() { - for( int i = 1; i < 256; i++ ) +for (int i = 1; i < 256; i++) +{ + Internal::Scene* scene = Internal::Scene::Get(i); + if (scene != NULL) { - Scene* scene = Scene::Get( i ); - if( scene != NULL ) - { - continue; - } - new Scene( i ); - return i; + continue; } - return 0; + new Internal::Scene(i); + return i; +} +return 0; } //----------------------------------------------------------------------------- // // Remove scene and delete its contents //----------------------------------------------------------------------------- -bool Manager::RemoveScene -( - uint8 const _sceneId -) +bool Manager::RemoveScene(uint8 const _sceneId) { - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) - { - delete scene; - return true; - } - return false; +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) +{ + delete scene; + return true; +} +return false; } //----------------------------------------------------------------------------- // // Add a bool ValueID/value pair to the scene //----------------------------------------------------------------------------- -bool Manager::AddSceneValue -( - uint8 const _sceneId, - ValueID const& _valueId, - bool const _value -) +bool Manager::AddSceneValue(uint8 const _sceneId, ValueID const& _valueId, bool const _value) { - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) - { - return scene->AddValue( _valueId, _value ? "True" : "False"); - } - return false; +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) +{ + return scene->AddValue(_valueId, _value ? "True" : "False"); +} +return false; } //----------------------------------------------------------------------------- // // Add a byte ValueID/value pair to the scene //----------------------------------------------------------------------------- -bool Manager::AddSceneValue -( - uint8 const _sceneId, - ValueID const& _valueId, - uint8 const _value -) +bool Manager::AddSceneValue(uint8 const _sceneId, ValueID const& _valueId, uint8 const _value) { - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) - { - char str[16]; - snprintf( str, sizeof(str), "%d", _value ); - return scene->AddValue( _valueId, str ); - } - return false; +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) +{ + char str[16]; + snprintf(str, sizeof(str), "%d", _value); + return scene->AddValue(_valueId, str); +} +return false; } //----------------------------------------------------------------------------- // // Add a decimal ValueID/value pair to the scene //----------------------------------------------------------------------------- -bool Manager::AddSceneValue -( - uint8 const _sceneId, - ValueID const& _valueId, - float const _value -) +bool Manager::AddSceneValue(uint8 const _sceneId, ValueID const& _valueId, float const _value) { - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) - { - char str[16]; - snprintf( str, sizeof(str), "%f", _value ); - return scene->AddValue( _valueId, str ); - } - return false; +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) +{ + char str[16]; + snprintf(str, sizeof(str), "%f", _value); + return scene->AddValue(_valueId, str); +} +return false; } //----------------------------------------------------------------------------- // // Add an integer ValueID/value pair to the scene //----------------------------------------------------------------------------- -bool Manager::AddSceneValue -( - uint8 const _sceneId, - ValueID const& _valueId, - int32 const _value -) +bool Manager::AddSceneValue(uint8 const _sceneId, ValueID const& _valueId, int32 const _value) { - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) - { - char str[16]; - snprintf( str, sizeof(str), "%d", _value ); - return scene->AddValue( _valueId, str ); - } - return false; +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) +{ + char str[16]; + snprintf(str, sizeof(str), "%d", _value); + return scene->AddValue(_valueId, str); +} +return false; } //----------------------------------------------------------------------------- // // Add a short ValueID/value pair to the scene //----------------------------------------------------------------------------- -bool Manager::AddSceneValue -( - uint8 const _sceneId, - ValueID const& _valueId, - int16 const _value -) +bool Manager::AddSceneValue(uint8 const _sceneId, ValueID const& _valueId, int16 const _value) { - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) - { - char str[16]; - snprintf( str, sizeof(str), "%d", _value ); - return scene->AddValue( _valueId, str ); - } - return false; +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) +{ + char str[16]; + snprintf(str, sizeof(str), "%d", _value); + return scene->AddValue(_valueId, str); +} +return false; } //----------------------------------------------------------------------------- // // Add a string ValueID/value pair to the scene //----------------------------------------------------------------------------- -bool Manager::AddSceneValue -( - uint8 const _sceneId, - ValueID const& _valueId, - string const& _value -) +bool Manager::AddSceneValue(uint8 const _sceneId, ValueID const& _valueId, string const& _value) { - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) - { - return scene->AddValue( _valueId, _value ); - } - return false; +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) +{ + return scene->AddValue(_valueId, _value); +} +return false; } //----------------------------------------------------------------------------- // // Add a list selection item ValueID/value pair to the scene (as string) //----------------------------------------------------------------------------- -bool Manager::AddSceneValueListSelection -( - uint8 const _sceneId, - ValueID const& _valueId, - string const& _value -) +bool Manager::AddSceneValueListSelection(uint8 const _sceneId, ValueID const& _valueId, string const& _value) { - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) - { - return scene->AddValue( _valueId, _value ); - } - return false; +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) +{ + return scene->AddValue(_valueId, _value); +} +return false; } //----------------------------------------------------------------------------- // // Add a list selection item ValueID/value pair to the scene (as integer) //----------------------------------------------------------------------------- -bool Manager::AddSceneValueListSelection -( - uint8 const _sceneId, - ValueID const& _valueId, - int32 const _value -) +bool Manager::AddSceneValueListSelection(uint8 const _sceneId, ValueID const& _valueId, int32 const _value) { - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) - { - char str[16]; - snprintf( str, sizeof(str), "%d", _value ); - return scene->AddValue( _valueId, str ); - } - return false; +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) +{ + char str[16]; + snprintf(str, sizeof(str), "%d", _value); + return scene->AddValue(_valueId, str); +} +return false; } //----------------------------------------------------------------------------- // // Remove a ValueID/value pair from the scene //----------------------------------------------------------------------------- -bool Manager::RemoveSceneValue -( - uint8 const _sceneId, - ValueID const& _valueId -) +bool Manager::RemoveSceneValue(uint8 const _sceneId, ValueID const& _valueId) { - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) - { - return scene->RemoveValue( _valueId ); - } - return false; +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) +{ + return scene->RemoveValue(_valueId); +} +return false; } //----------------------------------------------------------------------------- // // Return a scene's Value ID //----------------------------------------------------------------------------- -int Manager::SceneGetValues -( - uint8 const _sceneId, - vector* o_value -) +int Manager::SceneGetValues(uint8 const _sceneId, vector* o_value) { - o_value->clear(); - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) - { - return scene->GetValues( o_value ); - } - return 0; +o_value->clear(); +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) +{ + return scene->GetValues(o_value); +} +return 0; } //----------------------------------------------------------------------------- // // Return a scene's Value ID bool value //----------------------------------------------------------------------------- -bool Manager::SceneGetValueAsBool -( - uint8 const _sceneId, - ValueID const& _valueId, - bool* o_value -) +bool Manager::SceneGetValueAsBool(uint8 const _sceneId, ValueID const& _valueId, bool* o_value) { - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) +{ + string str; + if (scene->GetValue(_valueId, &str)) { - string str; - if( scene->GetValue( _valueId, &str ) ) - { - *o_value = !strcasecmp( "true", str.c_str() ); - return true; - } + *o_value = !strcasecmp("true", str.c_str()); + return true; } - return false; +} +return false; } //----------------------------------------------------------------------------- // // Return a scene's Value ID byte value //----------------------------------------------------------------------------- -bool Manager::SceneGetValueAsByte -( - uint8 const _sceneId, - ValueID const& _valueId, - uint8* o_value -) +bool Manager::SceneGetValueAsByte(uint8 const _sceneId, ValueID const& _valueId, uint8* o_value) { - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) +{ + string str; + if (scene->GetValue(_valueId, &str)) { - string str; - if( scene->GetValue( _valueId, &str ) ) - { - *o_value = (uint8)atoi( str.c_str() ); - return true; - } + *o_value = (uint8) atoi(str.c_str()); + return true; } - return false; +} +return false; } //----------------------------------------------------------------------------- // // Return a scene's Value ID float value //----------------------------------------------------------------------------- -bool Manager::SceneGetValueAsFloat -( - uint8 const _sceneId, - ValueID const& _valueId, - float* o_value -) +bool Manager::SceneGetValueAsFloat(uint8 const _sceneId, ValueID const& _valueId, float* o_value) +{ +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) { - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) + string str; + if (scene->GetValue(_valueId, &str)) { - string str; - if( scene->GetValue( _valueId, &str ) ) - { - *o_value = (float)atof( str.c_str() ); - return true; - } + *o_value = (float) atof(str.c_str()); + return true; } - return false; +} +return false; } //----------------------------------------------------------------------------- // // Return a scene's Value ID integer value //----------------------------------------------------------------------------- -bool Manager::SceneGetValueAsInt -( - uint8 const _sceneId, - ValueID const& _valueId, - int32* o_value -) +bool Manager::SceneGetValueAsInt(uint8 const _sceneId, ValueID const& _valueId, int32* o_value) +{ +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) { - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) + string str; + if (scene->GetValue(_valueId, &str)) { - string str; - if( scene->GetValue( _valueId, &str ) ) - { - *o_value = (int32)atoi( str.c_str() ); - return true; - } + *o_value = (int32) atoi(str.c_str()); + return true; } - return false; +} +return false; } //----------------------------------------------------------------------------- // // Return a scene's Value ID short value //----------------------------------------------------------------------------- -bool Manager::SceneGetValueAsShort -( - uint8 const _sceneId, - ValueID const& _valueId, - int16* o_value -) +bool Manager::SceneGetValueAsShort(uint8 const _sceneId, ValueID const& _valueId, int16* o_value) +{ +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) { - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) + string str; + if (scene->GetValue(_valueId, &str)) { - string str; - if( scene->GetValue( _valueId, &str ) ) - { - *o_value = (int16)atoi( str.c_str() ); - return true; - } + *o_value = (int16) atoi(str.c_str()); + return true; } - return false; +} +return false; } //----------------------------------------------------------------------------- // // Return a scene's Value ID string value //----------------------------------------------------------------------------- -bool Manager::SceneGetValueAsString -( - uint8 const _sceneId, - ValueID const& _valueId, - string* o_value -) +bool Manager::SceneGetValueAsString(uint8 const _sceneId, ValueID const& _valueId, string* o_value) { - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) +{ + if (scene->GetValue(_valueId, o_value)) { - if( scene->GetValue( _valueId, o_value ) ) - { - return true; - } + return true; } - return false; +} +return false; } //----------------------------------------------------------------------------- // // Return a scene's Value ID list selection (as string) value //----------------------------------------------------------------------------- -bool Manager::SceneGetValueListSelection -( - uint8 const _sceneId, - ValueID const& _valueId, - string* o_value -) +bool Manager::SceneGetValueListSelection(uint8 const _sceneId, ValueID const& _valueId, string* o_value) { - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) +{ + if (scene->GetValue(_valueId, o_value)) { - if( scene->GetValue( _valueId, o_value ) ) - { - return true; - } + return true; } - return false; +} +return false; } //----------------------------------------------------------------------------- // // Return a scene's Value ID list selection (as integer) value //----------------------------------------------------------------------------- -bool Manager::SceneGetValueListSelection -( - uint8 const _sceneId, - ValueID const& _valueId, - int32* o_value -) +bool Manager::SceneGetValueListSelection(uint8 const _sceneId, ValueID const& _valueId, int32* o_value) +{ +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) { - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) + string str; + if (scene->GetValue(_valueId, &str)) { - string str; - if( scene->GetValue( _valueId, &str ) ) - { - *o_value = (int32)atoi( str.c_str() ); - return true; - } + *o_value = (int32) atoi(str.c_str()); + return true; } - return false; +} +return false; } //----------------------------------------------------------------------------- // // Set a scene's ValueID bool value. //----------------------------------------------------------------------------- -bool Manager::SetSceneValue -( - uint8 const _sceneId, - ValueID const& _valueId, - bool const _value -) +bool Manager::SetSceneValue(uint8 const _sceneId, ValueID const& _valueId, bool const _value) { - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) - { - return scene->SetValue( _valueId, _value ? "True" : "False" ); - } - return false; +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) +{ + return scene->SetValue(_valueId, _value ? "True" : "False"); +} +return false; } //----------------------------------------------------------------------------- // // Set a scene's ValueID byte value. //----------------------------------------------------------------------------- -bool Manager::SetSceneValue -( - uint8 const _sceneId, - ValueID const& _valueId, - uint8 const _value -) +bool Manager::SetSceneValue(uint8 const _sceneId, ValueID const& _valueId, uint8 const _value) { - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) - { - char str[16]; - snprintf( str, sizeof(str), "%d", _value ); - return scene->SetValue( _valueId, str ); - } - return false; +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) +{ + char str[16]; + snprintf(str, sizeof(str), "%d", _value); + return scene->SetValue(_valueId, str); +} +return false; } //----------------------------------------------------------------------------- // // Set a scene's ValueID float value. //----------------------------------------------------------------------------- -bool Manager::SetSceneValue -( - uint8 const _sceneId, - ValueID const& _valueId, - float const _value -) +bool Manager::SetSceneValue(uint8 const _sceneId, ValueID const& _valueId, float const _value) { - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) - { - char str[16]; - snprintf( str, sizeof(str), "%f", _value ); - return scene->SetValue( _valueId, str ); - } - return false; +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) +{ + char str[16]; + snprintf(str, sizeof(str), "%f", _value); + return scene->SetValue(_valueId, str); +} +return false; } //----------------------------------------------------------------------------- // // Set a scene's ValueID integer value. //----------------------------------------------------------------------------- -bool Manager::SetSceneValue -( - uint8 const _sceneId, - ValueID const& _valueId, - int32 const _value -) +bool Manager::SetSceneValue(uint8 const _sceneId, ValueID const& _valueId, int32 const _value) { - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) - { - char str[16]; - snprintf( str, sizeof(str), "%d", _value ); - return scene->SetValue( _valueId, str ); - } - return false; +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) +{ + char str[16]; + snprintf(str, sizeof(str), "%d", _value); + return scene->SetValue(_valueId, str); +} +return false; } //----------------------------------------------------------------------------- // // Set a scene's ValueID short value. //----------------------------------------------------------------------------- -bool Manager::SetSceneValue -( - uint8 const _sceneId, - ValueID const& _valueId, - int16 const _value -) +bool Manager::SetSceneValue(uint8 const _sceneId, ValueID const& _valueId, int16 const _value) { - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) - { - char str[16]; - snprintf( str, sizeof(str), "%d", _value ); - return scene->SetValue( _valueId, str ); - } - return false; +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) +{ + char str[16]; + snprintf(str, sizeof(str), "%d", _value); + return scene->SetValue(_valueId, str); +} +return false; } //----------------------------------------------------------------------------- // // Set a scene's ValueID string value. //----------------------------------------------------------------------------- -bool Manager::SetSceneValue -( - uint8 const _sceneId, - ValueID const& _valueId, - string const& _value -) +bool Manager::SetSceneValue(uint8 const _sceneId, ValueID const& _valueId, string const& _value) { - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) - { - return scene->SetValue( _valueId, _value ); - } - return false; +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) +{ + return scene->SetValue(_valueId, _value); +} +return false; } //----------------------------------------------------------------------------- // // Set a scene's ValueID list item value (as string). //----------------------------------------------------------------------------- -bool Manager::SetSceneValueListSelection -( - uint8 const _sceneId, - ValueID const& _valueId, - string const& _value -) +bool Manager::SetSceneValueListSelection(uint8 const _sceneId, ValueID const& _valueId, string const& _value) { - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) - { - return scene->SetValue( _valueId, _value ); - } - return false; +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) +{ + return scene->SetValue(_valueId, _value); +} +return false; } //----------------------------------------------------------------------------- // // Set a scene's ValueID list item value (as integer). //----------------------------------------------------------------------------- -bool Manager::SetSceneValueListSelection -( - uint8 const _sceneId, - ValueID const& _valueId, - int32 const _value -) +bool Manager::SetSceneValueListSelection(uint8 const _sceneId, ValueID const& _valueId, int32 const _value) { - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) - { - char str[16]; - snprintf( str, sizeof(str), "%d", _value ); - return scene->SetValue( _valueId, str ); - } - return false; +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) +{ + char str[16]; + snprintf(str, sizeof(str), "%d", _value); + return scene->SetValue(_valueId, str); +} +return false; } //----------------------------------------------------------------------------- // // Return a scene's label //----------------------------------------------------------------------------- -string Manager::GetSceneLabel -( - uint8 const _sceneId -) +string Manager::GetSceneLabel(uint8 const _sceneId) { - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) - { - return scene->GetLabel(); - } - return NULL; +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) +{ + return scene->GetLabel(); +} +return NULL; } //----------------------------------------------------------------------------- // // Set a scene's label //----------------------------------------------------------------------------- -void Manager::SetSceneLabel -( - uint8 const _sceneId, - string const& _value -) +void Manager::SetSceneLabel(uint8 const _sceneId, string const& _value) { - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) - { - scene->SetLabel( _value ); - } +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) +{ + scene->SetLabel(_value); +} } //----------------------------------------------------------------------------- // // Check if a Scene ID exists //----------------------------------------------------------------------------- -bool Manager::SceneExists -( - uint8 const _sceneId -) +bool Manager::SceneExists(uint8 const _sceneId) { - return Scene::Get( _sceneId ) != NULL; +return Internal::Scene::Get(_sceneId) != NULL; } //----------------------------------------------------------------------------- // // Perform all the settings for the given Scene ID //----------------------------------------------------------------------------- -bool Manager::ActivateScene -( - uint8 const _sceneId -) +bool Manager::ActivateScene(uint8 const _sceneId) { - Scene *scene = Scene::Get( _sceneId ); - if( scene != NULL ) - { - return scene->Activate(); - } - return false; +Internal::Scene *scene = Internal::Scene::Get(_sceneId); +if (scene != NULL) +{ + return scene->Activate(); +} +return false; } //----------------------------------------------------------------------------- // // Retrieve driver based counters. //----------------------------------------------------------------------------- -void Manager::GetDriverStatistics -( - uint32 const _homeId, - Driver::DriverData* _data -) +void Manager::GetDriverStatistics(uint32 const _homeId, Driver::DriverData* _data) { - if( Driver* driver = GetDriver( _homeId ) ) - { - driver->GetDriverStatistics( _data ); - } +if (Driver* driver = GetDriver(_homeId)) +{ + driver->GetDriverStatistics(_data); +} } @@ -5241,17 +4751,12 @@ void Manager::GetDriverStatistics // // Retrieve driver based counters. //----------------------------------------------------------------------------- -void Manager::GetNodeStatistics -( - uint32 const _homeId, - uint8 const _nodeId, - Node::NodeData* _data -) +void Manager::GetNodeStatistics(uint32 const _homeId, uint8 const _nodeId, Node::NodeData* _data) { - if( Driver* driver = GetDriver( _homeId ) ) - { - driver->GetNodeStatistics( _nodeId, _data ); - } +if (Driver* driver = GetDriver(_homeId)) +{ + driver->GetNodeStatistics(_nodeId, _data); +} } @@ -5259,166 +4764,137 @@ void Manager::GetNodeStatistics // // Convert the RouteScheme to a String //----------------------------------------------------------------------------- -string Manager::GetNodeRouteScheme -( - Node::NodeData *_data -) +string Manager::GetNodeRouteScheme(Node::NodeData *_data) { - switch (_data->m_routeScheme) { - case ROUTINGSCHEME_IDLE: - return "Idle"; - case ROUTINGSCHEME_DIRECT: - return "Direct"; - case ROUTINGSCHEME_CACHED_ROUTE_SR: - return "Static Route"; - case ROUTINGSCHEME_CACHED_ROUTE: - return "Last Working Route"; - case ROUTINGSCHEME_CACHED_ROUTE_NLWR: - return "Next to Last Working Route"; - case ROUTINGSCHEME_ROUTE: - return "Auto Route"; - case ROUTINGSCHEME_RESORT_DIRECT: - return "Resort to Direct"; - case ROUTINGSCHEME_RESORT_EXPLORE: - return "Explorer Route"; - } - return "Unknown"; +switch (_data->m_routeScheme) +{ + case ROUTINGSCHEME_IDLE: + return "Idle"; + case ROUTINGSCHEME_DIRECT: + return "Direct"; + case ROUTINGSCHEME_CACHED_ROUTE_SR: + return "Static Route"; + case ROUTINGSCHEME_CACHED_ROUTE: + return "Last Working Route"; + case ROUTINGSCHEME_CACHED_ROUTE_NLWR: + return "Next to Last Working Route"; + case ROUTINGSCHEME_ROUTE: + return "Auto Route"; + case ROUTINGSCHEME_RESORT_DIRECT: + return "Resort to Direct"; + case ROUTINGSCHEME_RESORT_EXPLORE: + return "Explorer Route"; +} +return "Unknown"; } //----------------------------------------------------------------------------- // // Convert the RouteSpeed to a String. //----------------------------------------------------------------------------- -string Manager::GetNodeRouteSpeed -( - Node::NodeData *_data -) +string Manager::GetNodeRouteSpeed(Node::NodeData *_data) { - switch(_data->m_routeSpeed) { - case ROUTE_SPEED_AUTO: - return "Auto"; - case ROUTE_SPEED_9600: - return "9600"; - case ROUTE_SPEED_40K: - return "40K"; - case ROUTE_SPEED_100K: - return "100K"; - } - return "Unknown"; +switch (_data->m_routeSpeed) +{ + case ROUTE_SPEED_AUTO: + return "Auto"; + case ROUTE_SPEED_9600: + return "9600"; + case ROUTE_SPEED_40K: + return "40K"; + case ROUTE_SPEED_100K: + return "100K"; +} +return "Unknown"; } //----------------------------------------------------------------------------- // // Retrieve MetaData about a Node. //----------------------------------------------------------------------------- -string const Manager::GetMetaData -( - uint32 const _homeId, - uint8 const _nodeId, - Node::MetaDataFields _metadata -) +string const Manager::GetMetaData(uint32 const _homeId, uint8 const _nodeId, Node::MetaDataFields _metadata) { - if( Driver* driver = GetDriver( _homeId ) ) - { - return driver->GetMetaData( _nodeId, _metadata ); - } - return ""; +if (Driver* driver = GetDriver(_homeId)) +{ + return driver->GetMetaData(_nodeId, _metadata); +} +return ""; } //----------------------------------------------------------------------------- // // Retrieve ChangeLog of a Configuration File about a Node. //----------------------------------------------------------------------------- -Node::ChangeLogEntry const Manager::GetChangeLog -( - uint32 const _homeId, - uint8 const _nodeId, - uint32_t revision -) +Node::ChangeLogEntry const Manager::GetChangeLog(uint32 const _homeId, uint8 const _nodeId, uint32_t revision) { - if( Driver* driver = GetDriver( _homeId ) ) - { - return driver->GetChangeLog( _nodeId, revision ); - } - Node::ChangeLogEntry cle; - cle.revision = -1; - return cle; +if (Driver* driver = GetDriver(_homeId)) +{ + return driver->GetChangeLog(_nodeId, revision); +} +Node::ChangeLogEntry cle; +cle.revision = -1; +return cle; } - //----------------------------------------------------------------------------- // // get the latest config file revision //----------------------------------------------------------------------------- -bool Manager::checkLatestConfigFileRevision -( - uint32 const _homeId, - uint8 const _nodeId -) +bool Manager::checkLatestConfigFileRevision(uint32 const _homeId, uint8 const _nodeId) +{ +if (Driver *driver = GetDriver(_homeId)) { - if (Driver *driver = GetDriver( _homeId ) ) + Internal::LockGuard LG(driver->m_nodeMutex); + Node* node = driver->GetNode(_nodeId); + if (node) { - LockGuard LG(driver->m_nodeMutex); - Node* node = driver->GetNode( _nodeId ); - if( node ) - { - return driver->CheckNodeConfigRevision(node); - } + return driver->CheckNodeConfigRevision(node); } - return false; +} +return false; } //----------------------------------------------------------------------------- // // get the latest ManufacturerSpecific.xml file revision //----------------------------------------------------------------------------- -bool Manager::checkLatestMFSRevision -( - uint32 const _homeId -) +bool Manager::checkLatestMFSRevision(uint32 const _homeId) { - if (Driver *driver = GetDriver( _homeId ) ) - { - return driver->CheckMFSConfigRevision(); - } - return false; +if (Driver *driver = GetDriver(_homeId)) +{ + return driver->CheckMFSConfigRevision(); +} +return false; } //----------------------------------------------------------------------------- // // Download the latest Config File Revision for a node. //----------------------------------------------------------------------------- -bool Manager::downloadLatestConfigFileRevision -( - uint32 const _homeId, - uint8 const _nodeId -) +bool Manager::downloadLatestConfigFileRevision(uint32 const _homeId, uint8 const _nodeId) { - if (Driver *driver = GetDriver( _homeId ) ) +if (Driver *driver = GetDriver(_homeId)) +{ + Internal::LockGuard LG(driver->m_nodeMutex); + Node* node = driver->GetNode(_nodeId); + if (node) { - LockGuard LG(driver->m_nodeMutex); - Node* node = driver->GetNode( _nodeId ); - if( node ) - { - return driver->downloadConfigRevision(node); - } + return driver->downloadConfigRevision(node); } - return false; +} +return false; } //----------------------------------------------------------------------------- // // Download the Latest ManufacturerSpecific Revision //----------------------------------------------------------------------------- -bool Manager::downloadLatestMFSRevision -( - uint32 const _homeId -) +bool Manager::downloadLatestMFSRevision(uint32 const _homeId) { - if (Driver *driver = GetDriver( _homeId ) ) - { - return driver->downloadMFSRevision(); - } - return false; +if (Driver *driver = GetDriver(_homeId)) +{ + return driver->downloadMFSRevision(); +} +return false; } diff --git a/cpp/src/Manager.h b/cpp/src/Manager.h index 386f07320f..3abe392f53 100644 --- a/cpp/src/Manager.h +++ b/cpp/src/Manager.h @@ -42,24 +42,22 @@ namespace OpenZWave { + namespace Internal + { + namespace CC + { + class CommandClass; + } + namespace VC + { + class Value; + class ValueStore; + } + class Msg; + } class Options; class Node; - class Msg; - class Value; - class Event; - class Mutex; - class SerialPort; - class Thread; class Notification; - class ValueBitSet; - class ValueBool; - class ValueByte; - class ValueDecimal; - class ValueInt; - class ValueList; - class ValueShort; - class ValueString; - class ValueRaw; /** \brief * The main public interface to OpenZWave. @@ -89,7 +87,7 @@ namespace OpenZWave * to install a notification callback handler. This handler will receive * notifications of Z-Wave network changes and updates to device values, and is * an essential element of OpenZWave. - *

+ *

* Next, a call should be made to Manager::AddDriver for each Z-Wave controller * attached to the PC. Each Driver will handle the sending and receiving of * messages for all the devices in its controller's Z-Wave network. The Driver @@ -109,2512 +107,2561 @@ namespace OpenZWave */ class OPENZWAVE_EXPORT Manager { - friend class Driver; - friend class CommandClass; - friend class Group; - friend class Node; - friend class Value; - friend class ValueStore; - friend class ValueButton; - friend class Msg; - - public: - typedef void (*pfnOnNotification_t)( Notification const* _pNotification, void* _context ); - - //----------------------------------------------------------------------------- - // Construction - //----------------------------------------------------------------------------- - /** \name Construction - * For creating and destroying the Manager singleton. - */ - /*@{*/ - public: - /** - * \brief Creates the Manager singleton object. - * The Manager provides the public interface to OpenZWave, exposing all the functionality required - * to add Z-Wave support to an application. There can be only one Manager in an OpenZWave application. - * An Options object must be created and Locked first, otherwise the call to Manager::Create will - * fail. Once the Manager has been created, call AddWatcher to install a notification callback handler, - * and then call the AddDriver method for each attached PC Z-Wave controller in turn. - * \param _options a locked Options object containing all the application's configurable option values. - * \return a pointer to the newly created Manager object, or NULL if creation failed. - * \throws OZWException with Type OZWException::OZWEXCEPTION_OPTIONS if the Options Class is not setup and Locked - * \see Options, Get, Destroy, AddWatcher, AddDriver - */ - static Manager* Create(); + friend class Driver; + friend class Internal::CC::CommandClass; + friend class Group; + friend class Node; + friend class Internal::VC::Value; + friend class Internal::VC::ValueStore; + friend class Internal::Msg; - /** - * \brief Gets a pointer to the Manager object. - * \return pointer to the Manager object, or NULL if Create has not yet been called. - * \see Create, Destroy - */ - static Manager* Get(){ return s_instance; } + public: + typedef void (*pfnOnNotification_t)(Notification const* _pNotification, void* _context); - /** - * \brief Deletes the Manager and cleans up any associated objects. - * \see Create, Get - */ - static void Destroy(); + //----------------------------------------------------------------------------- + // Construction + //----------------------------------------------------------------------------- + /** \name Construction + * For creating and destroying the Manager singleton. + */ + /*@{*/ + public: + /** + * \brief Creates the Manager singleton object. + * The Manager provides the public interface to OpenZWave, exposing all the functionality required + * to add Z-Wave support to an application. There can be only one Manager in an OpenZWave application. + * An Options object must be created and Locked first, otherwise the call to Manager::Create will + * fail. Once the Manager has been created, call AddWatcher to install a notification callback handler, + * and then call the AddDriver method for each attached PC Z-Wave controller in turn. + * \param _options a locked Options object containing all the application's configurable option values. + * \return a pointer to the newly created Manager object, or NULL if creation failed. + * \throws OZWException with Type OZWException::OZWEXCEPTION_OPTIONS if the Options Class is not setup and Locked + * \see Options, Get, Destroy, AddWatcher, AddDriver + */ + static Manager* Create(); - /** - * \brief Get the Version Number of OZW as a string - * \return a String representing the version number as MAJOR.MINOR.REVISION - */ - static std::string getVersionAsString(); + /** + * \brief Gets a pointer to the Manager object. + * \return pointer to the Manager object, or NULL if Create has not yet been called. + * \see Create, Destroy + */ + static Manager* Get() + { + return s_instance; + } - /** - * \brief Get the Version Number including Git commit of OZW as a string - * \return a String representing the version number as MAJOR.MINOR.REVISION-gCOMMIT - */ - static std::string getVersionLongAsString(); + /** + * \brief Deletes the Manager and cleans up any associated objects. + * \see Create, Get + */ + static void Destroy(); - /** - * \brief Get the Version Number as the Version Struct (Only Major/Minor returned) - * \return the version struct representing the version - */ - static ozwversion getVersion(); - /*@}*/ - - private: - Manager(); // Constructor, to be called only via the static Create method. - virtual ~Manager(); // Destructor, to be called only via the static Destroy method. - - bool m_exit; // Flag indicating that program exit is in progress. - static Manager* s_instance; // Pointer to the instance of the Manager singleton. - - //----------------------------------------------------------------------------- - // Configuration - //----------------------------------------------------------------------------- - /** \name Configuration - * For saving the Z-Wave network configuration so that the entire network does not need to be - * polled every time the application starts. - */ - /*@{*/ - public: - /** - * \brief Saves a cache of a PC Controller's Z-Wave network to the application's user data folder. - * This method does not normally need to be called, since OpenZWave will save the state automatically - * during the shutdown process. It is provided here only as an aid to development. - * The configuration of each PC Controller's Z-Wave network is stored in a separate file. The filename - * consists of the 8 digit hexadecimal version of the controller's Home ID, prefixed with the string 'ozwcache_'. - * This convention allows OpenZWave to find the correct configuration file for a controller, even if it is - * attached to a different serial port, USB device path, etc. - * \deprecated OZW handles writing out the cache automatically. This does not need to be called anymore. - * \param _homeId The Home ID of the Z-Wave controller to save. - */ - DEPRECATED void WriteConfig( uint32 const _homeId ); + /** + * \brief Get the Version Number of OZW as a string + * \return a String representing the version number as MAJOR.MINOR.REVISION + */ + static std::string getVersionAsString(); - /** - * \brief Gets a pointer to the locked Options object. - * \return pointer to the Options object. - * \see Create - */ - Options* GetOptions()const{ return m_options; } - /*@}*/ + /** + * \brief Get the Version Number including Git commit of OZW as a string + * \return a String representing the version number as MAJOR.MINOR.REVISION-gCOMMIT + */ + static std::string getVersionLongAsString(); - private: - Options* m_options; // Pointer to the locked Options object that was passed in during creation. + /** + * \brief Get the Version Number as the Version Struct (Only Major/Minor returned) + * \return the version struct representing the version + */ + static ozwversion getVersion(); + /*@}*/ + + private: + Manager(); // Constructor, to be called only via the static Create method. + virtual ~Manager(); // Destructor, to be called only via the static Destroy method. + + bool m_exit; // Flag indicating that program exit is in progress. + static Manager* s_instance; // Pointer to the instance of the Manager singleton. + + //----------------------------------------------------------------------------- + // Configuration + //----------------------------------------------------------------------------- + /** \name Configuration + * For saving the Z-Wave network configuration so that the entire network does not need to be + * polled every time the application starts. + */ + /*@{*/ + public: + /** + * \brief Saves a cache of a PC Controller's Z-Wave network to the application's user data folder. + * This method does not normally need to be called, since OpenZWave will save the state automatically + * during the shutdown process. It is provided here only as an aid to development. + * The configuration of each PC Controller's Z-Wave network is stored in a separate file. The filename + * consists of the 8 digit hexadecimal version of the controller's Home ID, prefixed with the string 'ozwcache_'. + * This convention allows OpenZWave to find the correct configuration file for a controller, even if it is + * attached to a different serial port, USB device path, etc. + * \deprecated OZW handles writing out the cache automatically. This does not need to be called anymore. + * \param _homeId The Home ID of the Z-Wave controller to save. + */ + DEPRECATED void WriteConfig(uint32 const _homeId); - //----------------------------------------------------------------------------- - // Drivers - //----------------------------------------------------------------------------- - /** \name Drivers - * Methods for adding and removing drivers and obtaining basic controller information. - */ - /*@{*/ - public: - /** - * \brief Creates a new driver for a Z-Wave controller. - * This method creates a Driver object for handling communications with a single Z-Wave controller. In the background, the - * driver first tries to read configuration data saved during a previous run. It then queries the controller directly for any - * missing information, and a refresh of the list of nodes that it controls. Once this information - * has been received, a DriverReady notification callback is sent, containing the Home ID of the controller. This Home ID is - * required by most of the OpenZWave Manager class methods. - * @param _controllerPath The string used to open the controller. On Windows this might be something like - * "\\.\COM3", or on Linux "/dev/ttyUSB0". - * \return True if a new driver was created, false if a driver for the controller already exists. - * \see Create, Get, RemoveDriver - */ - bool AddDriver( string const& _controllerPath, Driver::ControllerInterface const& _interface = Driver::ControllerInterface_Serial); - - /** - * \brief Removes the driver for a Z-Wave controller, and closes the controller. - * Drivers do not need to be explicitly removed before calling Destroy - this is handled automatically. - * \warning You should NOT call any Manager methods that require the Driver Reference (eg, in response to - * Notifications received about NodeRemoved etc) once you call this, as your application will most likely - * break - * @param _controllerPath The same string as was passed in the original call to AddDriver. - * @returns True if the driver was removed, false if it could not be found. - * @see Destroy, AddDriver - */ - bool RemoveDriver( string const& _controllerPath ); + /** + * \brief Gets a pointer to the locked Options object. + * \return pointer to the Options object. + * \see Create + */ + Options* GetOptions() const + { + return m_options; + } + /*@}*/ - /** - * \brief Get the node ID of the Z-Wave controller. - * \param _homeId The Home ID of the Z-Wave controller. - * \return the node ID of the Z-Wave controller. - */ - uint8 GetControllerNodeId( uint32 const _homeId ); + private: + Options* m_options; // Pointer to the locked Options object that was passed in during creation. - /** - * \brief Get the node ID of the Static Update Controller. - * \param _homeId The Home ID of the Z-Wave controller. - * \return the node ID of the Z-Wave controller. - */ - uint8 GetSUCNodeId( uint32 const _homeId ); - - /** - * \brief Query if the controller is a primary controller. - * The primary controller is the main device used to configure and control a Z-Wave network. - * There can only be one primary controller - all other controllers are secondary controllers. - *

- * The only difference between a primary and secondary controller is that the primary is the - * only one that can be used to add or remove other devices. For this reason, it is usually - * better for the primary controller to be portable, since most devices must be added when - * installed in their final location. - *

- * Calls to BeginControllerCommand will fail if the controller is not the primary. - * \param _homeId The Home ID of the Z-Wave controller. - * \return true if it is a primary controller, false if not. - */ - bool IsPrimaryController( uint32 const _homeId ); - - /** - * \brief Query if the controller is a static update controller. - * A Static Update Controller (SUC) is a controller that must never be moved in normal operation - * and which can be used by other nodes to receive information about network changes. - * \param _homeId The Home ID of the Z-Wave controller. - * \return true if it is a static update controller, false if not. - */ - bool IsStaticUpdateController( uint32 const _homeId ); - - /** - * \brief Query if the controller is using the bridge controller library. - * A bridge controller is able to create virtual nodes that can be associated - * with other controllers to enable events to be passed on. - * \param _homeId The Home ID of the Z-Wave controller. - * \return true if it is a bridge controller, false if not. - */ - bool IsBridgeController( uint32 const _homeId ); - - /** - * \brief Query if the controller support "extended status information" - * On IMA enabled targets build on SDK >= 6.60.00 - * ZW_SendData can return information about TX time, route tries and more. - * \param _homeId The Home ID of the Z-Wave controller. - * \return true if the controller accepted to turn on extended status. - */ - bool HasExtendedTxStatus( uint32 const _homeId ); + //----------------------------------------------------------------------------- + // Drivers + //----------------------------------------------------------------------------- + /** \name Drivers + * Methods for adding and removing drivers and obtaining basic controller information. + */ + /*@{*/ + public: + /** + * \brief Creates a new driver for a Z-Wave controller. + * This method creates a Driver object for handling communications with a single Z-Wave controller. In the background, the + * driver first tries to read configuration data saved during a previous run. It then queries the controller directly for any + * missing information, and a refresh of the list of nodes that it controls. Once this information + * has been received, a DriverReady notification callback is sent, containing the Home ID of the controller. This Home ID is + * required by most of the OpenZWave Manager class methods. + * @param _controllerPath The string used to open the controller. On Windows this might be something like + * "\\.\COM3", or on Linux "/dev/ttyUSB0". + * \return True if a new driver was created, false if a driver for the controller already exists. + * \see Create, Get, RemoveDriver + */ + bool AddDriver(string const& _controllerPath, Driver::ControllerInterface const& _interface = Driver::ControllerInterface_Serial); - /** - * \brief Get the version of the Z-Wave API library used by a controller. - * \param _homeId The Home ID of the Z-Wave controller. - * \return a string containing the library version. For example, "Z-Wave 2.48". - */ - string GetLibraryVersion( uint32 const _homeId ); - - /** - * \brief Get a string containing the Z-Wave API library type used by a controller. - * The possible library types are: - * - Static Controller - * - Controller - * - Enhanced Slave - * - Slave - * - Installer - * - Routing Slave - * - Bridge Controller - * - Device Under Test - * - * The controller should never return a slave library type. - * For a more efficient test of whether a controller is a Bridge Controller, use - * the IsBridgeController method. - * \param _homeId The Home ID of the Z-Wave controller. - * \return a string containing the library type. - * \see GetLibraryVersion, IsBridgeController - */ - string GetLibraryTypeName( uint32 const _homeId ); + /** + * \brief Removes the driver for a Z-Wave controller, and closes the controller. + * Drivers do not need to be explicitly removed before calling Destroy - this is handled automatically. + * \warning You should NOT call any Manager methods that require the Driver Reference (eg, in response to + * Notifications received about NodeRemoved etc) once you call this, as your application will most likely + * break + * @param _controllerPath The same string as was passed in the original call to AddDriver. + * @returns True if the driver was removed, false if it could not be found. + * @see Destroy, AddDriver + */ + bool RemoveDriver(string const& _controllerPath); - /** - * \brief Get count of messages in the outgoing send queue. - * \param _homeId The Home ID of the Z-Wave controller. - * \return a integer message count - */ - int32 GetSendQueueCount( uint32 const _homeId ); + /** + * \brief Get the node ID of the Z-Wave controller. + * \param _homeId The Home ID of the Z-Wave controller. + * \return the node ID of the Z-Wave controller. + */ + uint8 GetControllerNodeId(uint32 const _homeId); - /** - * \brief Send current driver statistics to the log file - * \param _homeId The Home ID of the Z-Wave controller. - */ - void LogDriverStatistics( uint32 const _homeId ); + /** + * \brief Get the node ID of the Static Update Controller. + * \param _homeId The Home ID of the Z-Wave controller. + * \return the node ID of the Z-Wave controller. + */ + uint8 GetSUCNodeId(uint32 const _homeId); - /** - * \brief Obtain controller interface type - * \param _homeId The Home ID of the Z-Wave controller. - */ - Driver::ControllerInterface GetControllerInterfaceType( uint32 const _homeId ); + /** + * \brief Query if the controller is a primary controller. + * The primary controller is the main device used to configure and control a Z-Wave network. + * There can only be one primary controller - all other controllers are secondary controllers. + *

+ * The only difference between a primary and secondary controller is that the primary is the + * only one that can be used to add or remove other devices. For this reason, it is usually + * better for the primary controller to be portable, since most devices must be added when + * installed in their final location. + *

+ * Calls to BeginControllerCommand will fail if the controller is not the primary. + * \param _homeId The Home ID of the Z-Wave controller. + * \return true if it is a primary controller, false if not. + */ + bool IsPrimaryController(uint32 const _homeId); - /** - * \brief Obtain controller interface path - * \param _homeId The Home ID of the Z-Wave controller. - */ - string GetControllerPath( uint32 const _homeId ); - /*@}*/ - - private: - Driver* GetDriver( uint32 const _homeId ); /**< Get a pointer to a Driver object from the HomeID. Only to be used by OpenZWave. */ - void SetDriverReady( Driver* _driver, bool success ); /**< Indicate that the Driver is ready to be used, and send the notification callback. */ - -OPENZWAVE_EXPORT_WARNINGS_OFF - list m_pendingDrivers; /**< Drivers that are in the process of reading saved data and querying their Z-Wave network for basic information. */ - map m_readyDrivers; /**< Drivers that are ready to be used by the application. */ -OPENZWAVE_EXPORT_WARNINGS_ON - - //----------------------------------------------------------------------------- - // Polling Z-Wave devices - //----------------------------------------------------------------------------- - /** \name Polling Z-Wave devices - * Methods for controlling the polling of Z-Wave devices. Modern devices will not - * require polling. Some old devices need to be polled as the only way to detect - * status changes. - */ - /*@{*/ - public: - /** - * \brief Get the time period between polls of a node's state. - */ - int32 GetPollInterval(); - - /** - * \brief Set the time period between polls of a node's state. - * Due to patent concerns, some devices do not report state changes automatically to the controller. - * These devices need to have their state polled at regular intervals. The length of the interval - * is the same for all devices. To even out the Z-Wave network traffic generated by polling, OpenZWave - * divides the polling interval by the number of devices that have polling enabled, and polls each - * in turn. It is recommended that if possible, the interval should not be set shorter than the - * number of polled devices in seconds (so that the network does not have to cope with more than one - * poll per second). - * \param _seconds The length of the polling interval in seconds. - */ - void SetPollInterval( int32 _milliseconds, bool _bIntervalBetweenPolls ); + /** + * \brief Query if the controller is a static update controller. + * A Static Update Controller (SUC) is a controller that must never be moved in normal operation + * and which can be used by other nodes to receive information about network changes. + * \param _homeId The Home ID of the Z-Wave controller. + * \return true if it is a static update controller, false if not. + */ + bool IsStaticUpdateController(uint32 const _homeId); - /** - * \brief Enable the polling of a device's state. - * \param _valueId The ID of the value to start polling. - * \param _intensity, number of polling for one polling interval. - * \return True if polling was enabled. - */ - bool EnablePoll( ValueID const &_valueId, uint8 const _intensity = 1 ); + /** + * \brief Query if the controller is using the bridge controller library. + * A bridge controller is able to create virtual nodes that can be associated + * with other controllers to enable events to be passed on. + * \param _homeId The Home ID of the Z-Wave controller. + * \return true if it is a bridge controller, false if not. + */ + bool IsBridgeController(uint32 const _homeId); - /** - * \brief Disable the polling of a device's state. - * \param _valueId The ID of the value to stop polling. - * \return True if polling was disabled. - */ - bool DisablePoll( ValueID const &_valueId ); + /** + * \brief Query if the controller support "extended status information" + * On IMA enabled targets build on SDK >= 6.60.00 + * ZW_SendData can return information about TX time, route tries and more. + * \param _homeId The Home ID of the Z-Wave controller. + * \return true if the controller accepted to turn on extended status. + */ + bool HasExtendedTxStatus(uint32 const _homeId); - /** - * \brief Determine the polling of a device's state. - * \param _valueId The ID of the value to check polling. - * \return True if polling is active. - */ - bool isPolled( ValueID const &_valueId ); + /** + * \brief Get the version of the Z-Wave API library used by a controller. + * \param _homeId The Home ID of the Z-Wave controller. + * \return a string containing the library version. For example, "Z-Wave 2.48". + */ + string GetLibraryVersion(uint32 const _homeId); - /** - * \brief Set the frequency of polling (0=none, 1=every time through the list, 2-every other time, etc) - * \param _valueId The ID of the value whose intensity should be set - */ - void SetPollIntensity( ValueID const &_valueId, uint8 const _intensity ); - - /** - * \brief Get the polling intensity of a device's state. - * \param _valueId The ID of the value to check polling. - * \return Intensity, number of polling for one polling interval. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - */ - uint8 GetPollIntensity( ValueID const &_valueId ); + /** + * \brief Get a string containing the Z-Wave API library type used by a controller. + * The possible library types are: + * - Static Controller + * - Controller + * - Enhanced Slave + * - Slave + * - Installer + * - Routing Slave + * - Bridge Controller + * - Device Under Test + * + * The controller should never return a slave library type. + * For a more efficient test of whether a controller is a Bridge Controller, use + * the IsBridgeController method. + * \param _homeId The Home ID of the Z-Wave controller. + * \return a string containing the library type. + * \see GetLibraryVersion, IsBridgeController + */ + string GetLibraryTypeName(uint32 const _homeId); - /*@}*/ + /** + * \brief Get count of messages in the outgoing send queue. + * \param _homeId The Home ID of the Z-Wave controller. + * \return a integer message count + */ + int32 GetSendQueueCount(uint32 const _homeId); - //----------------------------------------------------------------------------- - // Node information - //----------------------------------------------------------------------------- - /** \name Node information - * Methods for accessing information on individual nodes. - */ - /*@{*/ - public: - /** - * \brief Refresh a Node and Reload it into OZW - * Causes the node's Supported CommandClasses and Capabilities to be obtained from the Z-Wave network - * This method would normally be called automatically by OpenZWave, but if you know that a node's capabilities or command classes - * has been changed, calling this method will force a refresh of that information. - * This call shouldn't be needed except in special circumstances. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return True if the request was sent successfully. - */ - bool RefreshNodeInfo( uint32 const _homeId, uint8 const _nodeId ); + /** + * \brief Send current driver statistics to the log file + * \param _homeId The Home ID of the Z-Wave controller. + */ + void LogDriverStatistics(uint32 const _homeId); + /** + * \brief Obtain controller interface type + * \param _homeId The Home ID of the Z-Wave controller. + */ + Driver::ControllerInterface GetControllerInterfaceType(uint32 const _homeId); - /** - * \brief Trigger the fetching of dynamic value data for a node. - * Causes the node's values to be requested from the Z-Wave network. This is the - * same as the query state starting from the associations state. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return True if the request was sent successfully. - */ - bool RequestNodeState( uint32 const _homeId, uint8 const _nodeId ); - - /** - * \brief Trigger the fetching of just the dynamic value data for a node. - * Causes the node's values to be requested from the Z-Wave network. This is the - * same as the query state starting from the dynamic state. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return True if the request was sent successfully. - */ - bool RequestNodeDynamic( uint32 const _homeId, uint8 const _nodeId ); + /** + * \brief Obtain controller interface path + * \param _homeId The Home ID of the Z-Wave controller. + */ + string GetControllerPath(uint32 const _homeId); + /*@}*/ - /** - * \brief Get whether the node is a listening device that does not go to sleep - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return True if it is a listening node. - */ - bool IsNodeListeningDevice( uint32 const _homeId, uint8 const _nodeId ); - - /** - * \brief Get whether the node is a frequent listening device that goes to sleep but - * can be woken up by a beam. Useful to determine node and controller consistency. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return True if it is a frequent listening node. - */ - bool IsNodeFrequentListeningDevice( uint32 const _homeId, uint8 const _nodeId ); + private: + Driver* GetDriver(uint32 const _homeId); /**< Get a pointer to a Driver object from the HomeID. Only to be used by OpenZWave. */ + void SetDriverReady(Driver* _driver, bool success); /**< Indicate that the Driver is ready to be used, and send the notification callback. */ + list m_pendingDrivers; /**< Drivers that are in the process of reading saved data and querying their Z-Wave network for basic information. */ + map m_readyDrivers; /**< Drivers that are ready to be used by the application. */ - /** - * \brief Get whether the node is a beam capable device. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return True if it is a beam capable node. + //----------------------------------------------------------------------------- + // Polling Z-Wave devices + //----------------------------------------------------------------------------- + /** \name Polling Z-Wave devices + * Methods for controlling the polling of Z-Wave devices. Modern devices will not + * require polling. Some old devices need to be polled as the only way to detect + * status changes. */ - bool IsNodeBeamingDevice( uint32 const _homeId, uint8 const _nodeId ); + /*@{*/ + public: + /** + * \brief Get the time period between polls of a node's state. + */ + int32 GetPollInterval(); - /** - * \brief Get whether the node is a routing device that passes messages to other nodes - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return True if the node is a routing device - */ - bool IsNodeRoutingDevice( uint32 const _homeId, uint8 const _nodeId ); + /** + * \brief Set the time period between polls of a node's state. + * Due to patent concerns, some devices do not report state changes automatically to the controller. + * These devices need to have their state polled at regular intervals. The length of the interval + * is the same for all devices. To even out the Z-Wave network traffic generated by polling, OpenZWave + * divides the polling interval by the number of devices that have polling enabled, and polls each + * in turn. It is recommended that if possible, the interval should not be set shorter than the + * number of polled devices in seconds (so that the network does not have to cope with more than one + * poll per second). + * \param _seconds The length of the polling interval in seconds. + */ + void SetPollInterval(int32 _milliseconds, bool _bIntervalBetweenPolls); - /** - * \brief Get the security attribute for a node. True if node supports security features. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return true if security features implemented. - */ - bool IsNodeSecurityDevice( uint32 const _homeId, uint8 const _nodeId ); + /** + * \brief Enable the polling of a device's state. + * \param _valueId The ID of the value to start polling. + * \param _intensity, number of polling for one polling interval. + * \return True if polling was enabled. + */ + bool EnablePoll(ValueID const &_valueId, uint8 const _intensity = 1); - /** - * \brief Get the maximum baud rate of a node's communications - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return the baud rate in bits per second. - */ - uint32 GetNodeMaxBaudRate( uint32 const _homeId, uint8 const _nodeId ); + /** + * \brief Disable the polling of a device's state. + * \param _valueId The ID of the value to stop polling. + * \return True if polling was disabled. + */ + bool DisablePoll(ValueID const &_valueId); - /** - * \brief Get the version number of a node - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return the node's version number - */ - uint8 GetNodeVersion( uint32 const _homeId, uint8 const _nodeId ); + /** + * \brief Determine the polling of a device's state. + * \param _valueId The ID of the value to check polling. + * \return True if polling is active. + */ + bool isPolled(ValueID const &_valueId); - /** - * \brief Get the security byte of a node - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return the node's security byte - */ - uint8 GetNodeSecurity( uint32 const _homeId, uint8 const _nodeId ); + /** + * \brief Set the frequency of polling (0=none, 1=every time through the list, 2-every other time, etc) + * \param _valueId The ID of the value whose intensity should be set + */ + void SetPollIntensity(ValueID const &_valueId, uint8 const _intensity); - /** - * \brief Is this a ZWave+ Supported Node? - * \param _homeId the HomeID of the Z-Wave controller that managed the node. - * \param _nodeId the ID of the node to query. - * \return If this node is a Z-Wave Plus Node - */ + /** + * \brief Get the polling intensity of a device's state. + * \param _valueId The ID of the value to check polling. + * \return Intensity, number of polling for one polling interval. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + */ + uint8 GetPollIntensity(ValueID const &_valueId); - bool IsNodeZWavePlus( uint32 const _homeId, uint8 const _nodeId ); + /*@}*/ - /** - * \brief Get the basic type of a node. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return the node's basic type. - */ - uint8 GetNodeBasic( uint32 const _homeId, uint8 const _nodeId ); + //----------------------------------------------------------------------------- + // Node information + //----------------------------------------------------------------------------- + /** \name Node information + * Methods for accessing information on individual nodes. + */ + /*@{*/ + public: + /** + * \brief Refresh a Node and Reload it into OZW + * Causes the node's Supported CommandClasses and Capabilities to be obtained from the Z-Wave network + * This method would normally be called automatically by OpenZWave, but if you know that a node's capabilities or command classes + * has been changed, calling this method will force a refresh of that information. + * This call shouldn't be needed except in special circumstances. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return True if the request was sent successfully. + */ + bool RefreshNodeInfo(uint32 const _homeId, uint8 const _nodeId); - /** - * \brief Get the generic type of a node. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return the node's generic type. - */ - uint8 GetNodeGeneric( uint32 const _homeId, uint8 const _nodeId ); + /** + * \brief Trigger the fetching of dynamic value data for a node. + * Causes the node's values to be requested from the Z-Wave network. This is the + * same as the query state starting from the associations state. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return True if the request was sent successfully. + */ + bool RequestNodeState(uint32 const _homeId, uint8 const _nodeId); - /** - * \brief Get the specific type of a node. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return the node's specific type. - */ - uint8 GetNodeSpecific( uint32 const _homeId, uint8 const _nodeId ); - - /** - * \brief Get a human-readable label describing the node - * The label is taken from the Z-Wave specific, generic or basic type, depending on which of those values are specified by the node. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return A string containing the label text. - */ - string GetNodeType( uint32 const _homeId, uint8 const _nodeId ); - - /** - * \brief Get the bitmap of this node's neighbors - * - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \param _nodeNeighbors An array of 29 uint8s to hold the neighbor bitmap - */ - uint32 GetNodeNeighbors( uint32 const _homeId, uint8 const _nodeId, uint8** _nodeNeighbors ); - - /** - * \brief Get the manufacturer name of a device - * The manufacturer name would normally be handled by the Manufacturer Specific command class, - * taking the manufacturer ID reported by the device and using it to look up the name from the - * manufacturer_specific.xml file in the OpenZWave config folder. - * However, there are some devices that do not support the command class, so to enable the user - * to manually set the name, it is stored with the node data and accessed via this method rather - * than being reported via a command class Value object. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return A string containing the node's manufacturer name. - * \see SetNodeManufacturerName, GetNodeProductName, SetNodeProductName - */ - string GetNodeManufacturerName( uint32 const _homeId, uint8 const _nodeId ); - - /** - * \brief Get the product name of a device - * The product name would normally be handled by the Manufacturer Specific command class, - * taking the product Type and ID reported by the device and using it to look up the name from the - * manufacturer_specific.xml file in the OpenZWave config folder. - * However, there are some devices that do not support the command class, so to enable the user - * to manually set the name, it is stored with the node data and accessed via this method rather - * than being reported via a command class Value object. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return A string containing the node's product name. - * \see SetNodeProductName, GetNodeManufacturerName, SetNodeManufacturerName - */ - string GetNodeProductName( uint32 const _homeId, uint8 const _nodeId ); - - /** - * \brief Get the name of a node - * The node name is a user-editable label for the node that would normally be handled by the - * Node Naming command class, but many devices do not support it. So that a node can always - * be named, OpenZWave stores it with the node data, and provides access through this method - * and SetNodeName, rather than reporting it via a command class Value object. - * The maximum length of a node name is 16 characters. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return A string containing the node's name. - * \see SetNodeName, GetNodeLocation, SetNodeLocation - */ - string GetNodeName( uint32 const _homeId, uint8 const _nodeId ); - - /** - * \brief Get the location of a node - * The node location is a user-editable string that would normally be handled by the Node Naming - * command class, but many devices do not support it. So that a node can always report its - * location, OpenZWave stores it with the node data, and provides access through this method - * and SetNodeLocation, rather than reporting it via a command class Value object. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return A string containing the node's location. - * \see SetNodeLocation, GetNodeName, SetNodeName - */ - string GetNodeLocation( uint32 const _homeId, uint8 const _nodeId ); - - /** - * \brief Get the manufacturer ID of a device - * The manufacturer ID is a four digit hex code and would normally be handled by the Manufacturer - * Specific command class, but not all devices support it. Although the value reported by this - * method will be an empty string if the command class is not supported and cannot be set by the - * user, the manufacturer ID is still stored with the node data (rather than being reported via a - * command class Value object) to retain a consistent approach with the other manufacturer specific data. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return A string containing the node's manufacturer ID, or an empty string if the manufacturer - * specific command class is not supported by the device. - * \see GetNodeProductType, GetNodeProductId, GetNodeManufacturerName, GetNodeProductName - * \todo Change the return to uint16 in 2.0 time frame - */ - string GetNodeManufacturerId( uint32 const _homeId, uint8 const _nodeId ); - - /** - * \brief Get the product type of a device - * The product type is a four digit hex code and would normally be handled by the Manufacturer Specific - * command class, but not all devices support it. Although the value reported by this method will - * be an empty string if the command class is not supported and cannot be set by the user, the product - * type is still stored with the node data (rather than being reported via a command class Value object) - * to retain a consistent approach with the other manufacturer specific data. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return A string containing the node's product type, or an empty string if the manufacturer - * specific command class is not supported by the device. - * \see GetNodeManufacturerId, GetNodeProductId, GetNodeManufacturerName, GetNodeProductName - * \todo Change the return to uint16 in 2.0 time frame - */ - string GetNodeProductType( uint32 const _homeId, uint8 const _nodeId ); - - /** - * \brief Get the product ID of a device - * The product ID is a four digit hex code and would normally be handled by the Manufacturer Specific - * command class, but not all devices support it. Although the value reported by this method will - * be an empty string if the command class is not supported and cannot be set by the user, the product - * ID is still stored with the node data (rather than being reported via a command class Value object) - * to retain a consistent approach with the other manufacturer specific data. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return A string containing the node's product ID, or an empty string if the manufacturer - * specific command class is not supported by the device. - * \see GetNodeManufacturerId, GetNodeProductType, GetNodeManufacturerName, GetNodeProductName - * \todo Change the return to uint16 in 2.0 time frame - */ - string GetNodeProductId( uint32 const _homeId, uint8 const _nodeId ); - - /** - * \brief Set the manufacturer name of a device - * The manufacturer name would normally be handled by the Manufacturer Specific command class, - * taking the manufacturer ID reported by the device and using it to look up the name from the - * manufacturer_specific.xml file in the OpenZWave config folder. - * However, there are some devices that do not support the command class, so to enable the user - * to manually set the name, it is stored with the node data and accessed via this method rather - * than being reported via a command class Value object. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \param _manufacturerName A string containing the node's manufacturer name. - * \see GetNodeManufacturerName, GetNodeProductName, SetNodeProductName - */ - void SetNodeManufacturerName( uint32 const _homeId, uint8 const _nodeId, string const& _manufacturerName ); - - /** - * \brief Set the product name of a device - * The product name would normally be handled by the Manufacturer Specific command class, - * taking the product Type and ID reported by the device and using it to look up the name from the - * manufacturer_specific.xml file in the OpenZWave config folder. - * However, there are some devices that do not support the command class, so to enable the user - * to manually set the name, it is stored with the node data and accessed via this method rather - * than being reported via a command class Value object. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \param _productName A string containing the node's product name. - * \see GetNodeProductName, GetNodeManufacturerName, SetNodeManufacturerName - */ - void SetNodeProductName( uint32 const _homeId, uint8 const _nodeId, string const& _productName ); - - /** - * \brief Set the name of a node - * The node name is a user-editable label for the node that would normally be handled by the - * Node Naming command class, but many devices do not support it. So that a node can always - * be named, OpenZWave stores it with the node data, and provides access through this method - * and GetNodeName, rather than reporting it via a command class Value object. - * If the device does support the Node Naming command class, the new name will be sent to the node. - * The maximum length of a node name is 16 characters. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \param _nodeName A string containing the node's name. - * \see GetNodeName, GetNodeLocation, SetNodeLocation - */ - void SetNodeName( uint32 const _homeId, uint8 const _nodeId, string const& _nodeName ); - - /** - * \brief Set the location of a node - * The node location is a user-editable string that would normally be handled by the Node Naming - * command class, but many devices do not support it. So that a node can always report its - * location, OpenZWave stores it with the node data, and provides access through this method - * and GetNodeLocation, rather than reporting it via a command class Value object. - * If the device does support the Node Naming command class, the new location will be sent to the node. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \param _location A string containing the node's location. - * \see GetNodeLocation, GetNodeName, SetNodeName - */ - void SetNodeLocation( uint32 const _homeId, uint8 const _nodeId, string const& _location ); - - /** - * \brief Turns a node on - * This is a helper method to simplify basic control of a node. It is the equivalent of - * changing the level reported by the node's Basic command class to 255, and will generate a - * ValueChanged notification from that class. This command will turn on the device at its - * last known level, if supported by the device, otherwise it will turn it on at 100%. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to be changed. - * \deprecated This method has been depreciated in setting the ValueID's directly (Remove in 1.8) - * - * \see SetNodeOff, SetNodeLevel - */ - DEPRECATED void SetNodeOn( uint32 const _homeId, uint8 const _nodeId ); - - /** - * \brief Turns a node off - * This is a helper method to simplify basic control of a node. It is the equivalent of - * changing the level reported by the node's Basic command class to zero, and will generate - * a ValueChanged notification from that class. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to be changed. - * \deprecated This method has been depreciated in setting the ValueID's directly (Remove in 1.8) - * \see SetNodeOn, SetNodeLevel - */ - DEPRECATED void SetNodeOff( uint32 const _homeId, uint8 const _nodeId ); - - /** - * \brief Sets the basic level of a node - * This is a helper method to simplify basic control of a node. It is the equivalent of - * changing the value reported by the node's Basic command class and will generate a - * ValueChanged notification from that class. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to be changed. - * \param _level The level to set the node. Valid values are 0-99 and 255. Zero is off and - * 99 is fully on. 255 will turn on the device at its last known level (if supported). - * \deprecated This method has been depreciated in setting the ValueID's directly (Remove in 1.8) - * \see SetNodeOn, SetNodeOff - */ - DEPRECATED void SetNodeLevel( uint32 const _homeId, uint8 const _nodeId, uint8 const _level ); + /** + * \brief Trigger the fetching of just the dynamic value data for a node. + * Causes the node's values to be requested from the Z-Wave network. This is the + * same as the query state starting from the dynamic state. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return True if the request was sent successfully. + */ + bool RequestNodeDynamic(uint32 const _homeId, uint8 const _nodeId); - /** - * \brief Get whether the node information has been received - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return True if the node information has been received yet - */ - bool IsNodeInfoReceived( uint32 const _homeId, uint8 const _nodeId ); - - /** - * \brief Get whether the node has the defined class available or not - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \param _commandClassId Id of the class to test for - * \return True if the node does have the class instantiated, will return name & version - */ - bool GetNodeClassInformation( uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, - string *_className = NULL, uint8 *_classVersion = NULL); - /** - * \brief Get whether the node is awake or asleep - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return True if the node is awake - */ - bool IsNodeAwake( uint32 const _homeId, uint8 const _nodeId ); + /** + * \brief Get whether the node is a listening device that does not go to sleep + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return True if it is a listening node. + */ + bool IsNodeListeningDevice(uint32 const _homeId, uint8 const _nodeId); - /** - * \brief Get whether the node is working or has failed - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return True if the node has failed and is no longer part of the network - */ - bool IsNodeFailed( uint32 const _homeId, uint8 const _nodeId ); + /** + * \brief Get whether the node is a frequent listening device that goes to sleep but + * can be woken up by a beam. Useful to determine node and controller consistency. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return True if it is a frequent listening node. + */ + bool IsNodeFrequentListeningDevice(uint32 const _homeId, uint8 const _nodeId); - /** - * \brief Get whether the node's query stage as a string - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return name of current query stage as a string. - */ - string GetNodeQueryStage( uint32 const _homeId, uint8 const _nodeId ); + /** + * \brief Get whether the node is a beam capable device. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return True if it is a beam capable node. + */ + bool IsNodeBeamingDevice(uint32 const _homeId, uint8 const _nodeId); + /** + * \brief Get whether the node is a routing device that passes messages to other nodes + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return True if the node is a routing device + */ + bool IsNodeRoutingDevice(uint32 const _homeId, uint8 const _nodeId); - /** - * \brief Get the node device type as reported in the Z-Wave+ Info report. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return the node's DeviceType - */ - uint16 GetNodeDeviceType( uint32 const _homeId, uint8 const _nodeId ); + /** + * \brief Get the security attribute for a node. True if node supports security features. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return true if security features implemented. + */ + bool IsNodeSecurityDevice(uint32 const _homeId, uint8 const _nodeId); - /** - * \brief Get the node device type as reported in the Z-Wave+ Info report. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return the node's Device Type as a string. - */ - string GetNodeDeviceTypeString( uint32 const _homeId, uint8 const _nodeId ); + /** + * \brief Get the maximum baud rate of a node's communications + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return the baud rate in bits per second. + */ + uint32 GetNodeMaxBaudRate(uint32 const _homeId, uint8 const _nodeId); - /** - * \brief Get the node role as reported in the Z-Wave+ Info report. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return the node's user icon. - */ - uint8 GetNodeRole( uint32 const _homeId, uint8 const _nodeId ); + /** + * \brief Get the version number of a node + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return the node's version number + */ + uint8 GetNodeVersion(uint32 const _homeId, uint8 const _nodeId); - /** - * \brief Get the node role as reported in the Z-Wave+ Info report. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return the node's role type as a string - */ - string GetNodeRoleString( uint32 const _homeId, uint8 const _nodeId ); + /** + * \brief Get the security byte of a node + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return the node's security byte + */ + uint8 GetNodeSecurity(uint32 const _homeId, uint8 const _nodeId); - /** - * \brief Get the node PlusType as reported in the Z-Wave+ Info report. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return the node's PlusType - */ - uint8 GetNodePlusType( uint32 const _homeId, uint8 const _nodeId ); - /** - * \brief Get the node PlusType as reported in the Z-Wave+ Info report. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to query. - * \return the node's PlusType as a string - */ - string GetNodePlusTypeString ( uint32 const _homeId, uint8 const _nodeId ); + /** + * \brief Is this a ZWave+ Supported Node? + * \param _homeId the HomeID of the Z-Wave controller that managed the node. + * \param _nodeId the ID of the node to query. + * \return If this node is a Z-Wave Plus Node + */ + bool IsNodeZWavePlus(uint32 const _homeId, uint8 const _nodeId); + /** + * \brief Get the basic type of a node. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return the node's basic type. + */ + uint8 GetNodeBasic(uint32 const _homeId, uint8 const _nodeId); - /*@}*/ + /** + * \brief Get the basic type of a node. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return the node's basic type. + */ + string GetNodeBasicString(uint32 const _homeId, uint8 const _nodeId); - //----------------------------------------------------------------------------- - // Instances - //----------------------------------------------------------------------------- - /** \name Instances - * Methods for accessing Instance Information. - */ - /*@{*/ - public: - /** - *\brief Get the Instance Label for a specific ValueID - * returns the Instance Label for a Specific ValueID on a CommandClass, or the Global Instance Label - * if there is no specific label for the CommandClass - *\param _id The unique identifier of the value - *\return The Instance Label - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - */ - string GetInstanceLabel( ValueID const &_id); - - /** - *\brief Get the Instance Label for a specific CommandClass - * returns the Label for a Specific Instance on a Specific CommandClass, or the Global Instance Label - * if there is no specific label for the CommandClass - *\param _homeId the HomeID for the network you are querying - *\param _node The Node you are interested in. - *\param _cc The CommandClass for the Label you are interested in - *\param _instance the Instance you are querying for - *\return The Instance Label - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - */ - string GetInstanceLabel(uint32 const _homeId, uint8 const _node, uint8 const _cc, uint8 const _instance); - - /*@}*/ - //----------------------------------------------------------------------------- - // Values - //----------------------------------------------------------------------------- - /** \name Values - * Methods for accessing device values. All the methods require a ValueID, which will have been provided - * in the ValueAdded Notification callback when the the value was first discovered by OpenZWave. - */ - /*@{*/ - public: - /** - * \brief Gets the user-friendly label for the value. - * \param _id The unique identifier of the value. - * \param _pos the Bit To Get the Label for if its a BitSet ValueID - * \return The value label. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \see ValueID - */ - string GetValueLabel( ValueID const& _id, int32 _pos = -1 ); - - /** - * \brief Sets the user-friendly label for the value. - * \param _id The unique identifier of the value. - * \param _pos the Bit To set the Label for if its a BitSet ValueID - * \param _value The new value of the label. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \see ValueID - */ - void SetValueLabel( ValueID const& _id, string const& _value, int32 _pos = -1 ); - - /** - * \brief Gets the units that the value is measured in. - * \param _id The unique identifier of the value. - * \return The value units. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \see ValueID - */ - string GetValueUnits( ValueID const& _id ); - - /** - * \brief Sets the units that the value is measured in. - * \param _id The unique identifier of the value. - * \param _value The new value of the units. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \see ValueID - */ - void SetValueUnits( ValueID const& _id, string const& _value ); - - /** - * \brief Gets a help string describing the value's purpose and usage. - * \param _id The unique identifier of the value. - * \param _pos Get the Help for associated Bits (Valid with ValueBitSet only) - * \return The value help text. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \see ValueID - */ - string GetValueHelp( ValueID const& _id, int32 _pos = -1 ); - - /** - * \brief Sets a help string describing the value's purpose and usage. - * \param _id The unique identifier of the value. - * \param _value The new value of the help text. - * \param __pos Set the Help for a associated Bit (Valid with ValueBitSet Only) - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \see ValueID - */ - void SetValueHelp( ValueID const& _id, string const& _value, int32 _pos = -1 ); - - /** - * \brief Gets the minimum that this value may contain. - * \param _id The unique identifier of the value. - * \return The value minimum. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \see ValueID - */ - int32 GetValueMin( ValueID const& _id ); - - /** - * \brief Gets the maximum that this value may contain. - * \param _id The unique identifier of the value. - * \return The value maximum. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \see ValueID - */ - int32 GetValueMax( ValueID const& _id ); - - /** - * \brief Test whether the value is read-only. - * \param _id The unique identifier of the value. - * \return true if the value cannot be changed by the user. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \see ValueID - */ - bool IsValueReadOnly( ValueID const& _id ); - - /** - * \brief Test whether the value is write-only. - * \param _id The unique identifier of the value. - * \return true if the value can only be written to and not read. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \see ValueID - */ - bool IsValueWriteOnly( ValueID const& _id ); - - /** - * \brief Test whether the value has been set. - * \param _id The unique identifier of the value. - * \return true if the value has actually been set by a status message from the device, rather than simply being the default. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \see ValueID - */ - bool IsValueSet( ValueID const& _id ); - - /** - * \brief Test whether the value is currently being polled. - * \param _id The unique identifier of the value. - * \return true if the value is being polled, otherwise false. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \see ValueID - */ - bool IsValuePolled( ValueID const& _id ); - - /** - * \brief Gets a the value of a Bit from a BitSet ValueID - * \param _id The unique identifier of the value. - * \param _pos the Bit you want to test for - * \param o_value Pointer to a bool that will be filled with the value. - * \return true if the value was obtained. Returns false if the value is not a ValueID::ValueType_BitSet. The type can be tested with a call to ValueID::GetType. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \see ValueID::GetType, GetValueAsBitSet, GetValueAsByte, GetValueAsFloat, GetValueAsInt, GetValueAsShort, GetValueAsString, GetValueListSelection, GetValueListItems, GetValueAsRaw - */ - bool GetValueAsBitSet( ValueID const& _id, uint8 _pos, bool* o_value ); - - /** - * \brief Gets a value as a bool. - * \param _id The unique identifier of the value. - * \param o_value Pointer to a bool that will be filled with the value. - * \return true if the value was obtained. Returns false if the value is not a ValueID::ValueType_Bool. The type can be tested with a call to ValueID::GetType. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \see ValueID::GetType, GetValueAsBitSet, GetValueAsByte, GetValueAsFloat, GetValueAsInt, GetValueAsShort, GetValueAsString, GetValueListSelection, GetValueListItems, GetValueAsRaw - */ - bool GetValueAsBool( ValueID const& _id, bool* o_value ); - - /** - * \brief Gets a value as an 8-bit unsigned integer. - * \param _id The unique identifier of the value. - * \param o_value Pointer to a uint8 that will be filled with the value. - * \return true if the value was obtained. Returns false if the value is not a ValueID::ValueType_Byte. The type can be tested with a call to ValueID::GetType - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \see ValueID::GetType, GetValueAsBitSet, GetValueAsBool, GetValueAsFloat, GetValueAsInt, GetValueAsShort, GetValueAsString, GetValueListSelection, GetValueListItems, GetValueAsRaw - */ - bool GetValueAsByte( ValueID const& _id, uint8* o_value ); - - /** - * \brief Gets a value as a float. - * \param _id The unique identifier of the value. - * \param o_value Pointer to a float that will be filled with the value. - * \return true if the value was obtained. Returns false if the value is not a ValueID::ValueType_Decimal. The type can be tested with a call to ValueID::GetType - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \see ValueID::GetType, GetValueAsBitSet, GetValueAsBool, GetValueAsByte, GetValueAsInt, GetValueAsShort, GetValueAsString, GetValueListSelection, GetValueListItems, GetValueAsRaw - */ - bool GetValueAsFloat( ValueID const& _id, float* o_value ); - - /** - * \brief Gets a value as a 32-bit signed integer. - * \param _id The unique identifier of the value. - * \param o_value Pointer to an int32 that will be filled with the value. - * \return true if the value was obtained. Returns false if the value is not a ValueID::ValueType_Int. The type can be tested with a call to ValueID::GetType - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \see ValueID::GetType, GetValueAsBitSet, GetValueAsBool, GetValueAsByte, GetValueAsFloat, GetValueAsShort, GetValueAsString, GetValueListSelection, GetValueListItems, GetValueAsRaw - */ - bool GetValueAsInt( ValueID const& _id, int32* o_value ); - - /** - * \brief Gets a value as a 16-bit signed integer. - * \param _id The unique identifier of the value. - * \param o_value Pointer to an int16 that will be filled with the value. - * \return true if the value was obtained. Returns false if the value is not a ValueID::ValueType_Short. The type can be tested with a call to ValueID::GetType. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \see ValueID::GetType, GetValueAsBitSet, GetValueAsBool, GetValueAsByte, GetValueAsFloat, GetValueAsInt, GetValueAsString, GetValueListSelection, GetValueListItems, GetValueAsRaw - */ - bool GetValueAsShort( ValueID const& _id, int16* o_value ); - - /** - * \brief Gets a value as a string. - * Creates a string representation of a value, regardless of type. - * \param _id The unique identifier of the value. - * \param o_value Pointer to a string that will be filled with the value. - * \return true if the value was obtained. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \see ValueID::GetType, GetValueAsBitSet, GetValueAsBool, GetValueAsByte, GetValueAsFloat, GetValueAsInt, GetValueAsShort, GetValueListSelection, GetValueListItems, GetValueAsRaw - */ - bool GetValueAsString( ValueID const& _id, string* o_value ); - - /** - * \brief Gets a value as a collection of bytes. - * \param _id The unique identifier of the value. - * \param o_value Pointer to a uint8* that will be filled with the value. This return value will need to be freed as it was dynamically allocated. - * \param o_length Pointer to a uint8 that will be fill with the data length. - * \return true if the value was obtained. Returns false if the value is not a ValueID::ValueType_Raw. The type can be tested with a call to ValueID::GetType. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \see ValueID::GetType, GetValueAsBitSet, GetValueAsBool, GetValueAsByte, GetValueAsFloat, GetValueAsInt, GetValueAsShort, GetValueListSelection, GetValueListItems, GetValueAsRaw - */ - bool GetValueAsRaw( ValueID const& _id, uint8** o_value, uint8* o_length ); - - /** - * \brief Gets the selected item from a list (as a string). - * \param _id The unique identifier of the value. - * \param o_value Pointer to a string that will be filled with the selected item. - * \return True if the value was obtained. Returns false if the value is not a ValueID::ValueType_List. The type can be tested with a call to ValueID::GetType. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \see ValueID::GetType, GetValueAsBitSet, GetValueAsBool, GetValueAsByte, GetValueAsFloat, GetValueAsInt, GetValueAsShort, GetValueAsString, GetValueListItems, GetValueAsRaw - */ - bool GetValueListSelection( ValueID const& _id, string* o_value ); - - /** - * \brief Gets the selected item from a list (as an integer). - * \param _id The unique identifier of the value. - * \param o_value Pointer to an integer that will be filled with the selected item. - * \return True if the value was obtained. Returns false if the value is not a ValueID::ValueType_List. The type can be tested with a call to ValueID::GetType. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \see ValueID::GetType, GetValueAsBitSet, GetValueAsBool, GetValueAsByte, GetValueAsFloat, GetValueAsInt, GetValueAsShort, GetValueAsString, GetValueListItems, GetValueAsRaw - */ - bool GetValueListSelection( ValueID const& _id, int32* o_value ); - - /** - * \brief Gets the list of items from a list value. - * \param _id The unique identifier of the value. - * \param o_value Pointer to a vector of strings that will be filled with list items. The vector will be cleared before the items are added. - * \return true if the list items were obtained. Returns false if the value is not a ValueID::ValueType_List. The type can be tested with a call to ValueID::GetType. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \see ValueID::GetType, GetValueAsBitSet, GetValueAsBool, GetValueAsByte, GetValueAsFloat, GetValueAsInt, GetValueAsShort, GetValueAsString, GetValueListSelection, GetValueAsRaw - */ - bool GetValueListItems( ValueID const& _id, vector* o_value ); - - /** - * \brief Gets the list of values from a list value. - * \param _id The unique identifier of the value. - * \param o_value Pointer to a vector of integers that will be filled with list items. The vector will be cleared before the items are added. - * \return true if the list values were obtained. Returns false if the value is not a ValueID::ValueType_List. The type can be tested with a call to ValueID::GetType. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \see ValueID::GetType, GetValueAsBitSet, GetValueAsBool, GetValueAsByte, GetValueAsFloat, GetValueAsInt, GetValueAsShort, GetValueAsString, GetValueListSelection, GetValueAsRaw - */ - bool GetValueListValues( ValueID const& _id, vector* o_value ); - - /** - * \brief Gets a float value's precision. - * \param _id The unique identifier of the value. - * \param o_value Pointer to a uint8 that will be filled with the precision value. - * \return true if the value was obtained. Returns false if the value is not a ValueID::ValueType_Decimal. The type can be tested with a call to ValueID::GetType - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \see ValueID::GetType, GetValueAsBitSet, GetValueAsBool, GetValueAsByte, GetValueAsInt, GetValueAsShort, GetValueAsString, GetValueListSelection, GetValueListItems - */ - bool GetValueFloatPrecision( ValueID const& _id, uint8* o_value ); - - /** - * \brief Sets the state of a bit in a BitSet ValueID. - * Due to the possibility of a device being asleep, the command is assumed to succeed, and the value - * held by the node is updated directly. This will be reverted by a future status message from the device - * if the Z-Wave message actually failed to get through. Notification callbacks will be sent in both cases. - * \param _id The unique identifier of the BitSet value. - * \param _pos the Position of the Bit you want to Set - * \param _value The new value of the Bitset at the _pos position. - * \return true if the value was set. Returns false if the value is not a ValueID::ValueType_Bool. The type can be tested with a call to ValueID::GetType. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * - */ - bool SetValue( ValueID const& _id, uint8 _pos, bool const _value ); - - /** - * \brief Sets the state of a bool. - * Due to the possibility of a device being asleep, the command is assumed to succeed, and the value - * held by the node is updated directly. This will be reverted by a future status message from the device - * if the Z-Wave message actually failed to get through. Notification callbacks will be sent in both cases. - * \param _id The unique identifier of the bool value. - * \param _value The new value of the bool. - * \return true if the value was set. Returns false if the value is not a ValueID::ValueType_Bool. The type can be tested with a call to ValueID::GetType. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * - */ - bool SetValue( ValueID const& _id, bool const _value ); - - /** - * \brief Sets the value of a byte. - * Due to the possibility of a device being asleep, the command is assumed to succeed, and the value - * held by the node is updated directly. This will be reverted by a future status message from the device - * if the Z-Wave message actually failed to get through. Notification callbacks will be sent in both cases. - * \param _id The unique identifier of the byte value. - * \param _value The new value of the byte. - * \return true if the value was set. Returns false if the value is not a ValueID::ValueType_Byte. The type can be tested with a call to ValueID::GetType. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - */ - bool SetValue( ValueID const& _id, uint8 const _value ); - - /** - * \brief Sets the value of a decimal. - * It is usually better to handle decimal values using strings rather than floats, to avoid floating point accuracy issues. - * Due to the possibility of a device being asleep, the command is assumed to succeed, and the value - * held by the node is updated directly. This will be reverted by a future status message from the device - * if the Z-Wave message actually failed to get through. Notification callbacks will be sent in both cases. - * \param _id The unique identifier of the decimal value. - * \param _value The new value of the decimal. - * \return true if the value was set. Returns false if the value is not a ValueID::ValueType_Decimal. The type can be tested with a call to ValueID::GetType. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - */ - bool SetValue( ValueID const& _id, float const _value ); - - /** - * \brief Sets the value of a 32-bit signed integer. - * Due to the possibility of a device being asleep, the command is assumed to succeed, and the value - * held by the node is updated directly. This will be reverted by a future status message from the device - * if the Z-Wave message actually failed to get through. Notification callbacks will be sent in both cases. - * \param _id The unique identifier of the integer value. - * \param _value The new value of the integer. - * \return true if the value was set. Returns false if the value is not a ValueID::ValueType_Int. The type can be tested with a call to ValueID::GetType. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - */ - bool SetValue( ValueID const& _id, int32 const _value ); - - /** - * \brief Sets the value of a 16-bit signed integer. - * Due to the possibility of a device being asleep, the command is assumed to succeed, and the value - * held by the node is updated directly. This will be reverted by a future status message from the device - * if the Z-Wave message actually failed to get through. Notification callbacks will be sent in both cases. - * \param _id The unique identifier of the integer value. - * \param _value The new value of the integer. - * \return true if the value was set. Returns false if the value is not a ValueID::ValueType_Short. The type can be tested with a call to ValueID::GetType. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - */ - bool SetValue( ValueID const& _id, int16 const _value ); - - /** - * \brief Sets the value of a collection of bytes. - * Due to the possibility of a device being asleep, the command is assumed to succeed, and the value - * held by the node is updated directly. This will be reverted by a future status message from the device - * if the Z-Wave message actually failed to get through. Notification callbacks will be sent in both cases. - * \param _id The unique identifier of the raw value. - * \param _value The new collection of bytes. - * \return true if the value was set. Returns false if the value is not a ValueID::ValueType_Raw. The type can be tested with a call to ValueID::GetType. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - */ - bool SetValue( ValueID const& _id, uint8 const* _value, uint8 const _length ); - - /** - * \brief Sets the value from a string, regardless of type. - * Due to the possibility of a device being asleep, the command is assumed to succeed, and the value - * held by the node is updated directly. This will be reverted by a future status message from the device - * if the Z-Wave message actually failed to get through. Notification callbacks will be sent in both cases. - * \param _id The unique identifier of the integer value. - * \param _value The new value of the string. - * \return true if the value was set. Returns false if the value could not be parsed into the correct type for the value. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - */ - bool SetValue( ValueID const& _id, string const& _value ); - - /** - * \brief Sets the selected item in a list. - * Due to the possibility of a device being asleep, the command is assumed to succeed, and the value - * held by the node is updated directly. This will be reverted by a future status message from the device - * if the Z-Wave message actually failed to get through. Notification callbacks will be sent in both cases. - * \param _id The unique identifier of the list value. - * \param _selectedItem A string matching the new selected item in the list. - * \return true if the value was set. Returns false if the selection is not in the list, or if the value is not a ValueID::ValueType_List. - * The type can be tested with a call to ValueID::GetType - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - */ - bool SetValueListSelection( ValueID const& _id, string const& _selectedItem ); - - /** - * \brief Refreshes the specified value from the Z-Wave network. - * A call to this function causes the library to send a message to the network to retrieve the current value - * of the specified ValueID (just like a poll, except only one-time, not recurring). - * \param _id The unique identifier of the value to be refreshed. - * \return true if the driver and node were found; false otherwise - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - */ - bool RefreshValue( ValueID const& _id); - - /** - * \brief Sets a flag indicating whether value changes noted upon a refresh should be verified. If so, the - * library will immediately refresh the value a second time whenever a change is observed. This helps to filter - * out spurious data reported occasionally by some devices. - * \param _id The unique identifier of the value whose changes should or should not be verified. - * \param _verify if true, verify changes; if false, don't verify changes. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \sa Manager::GetChangeVerified - */ - void SetChangeVerified( ValueID const& _id, bool _verify ); - - /** - * \brief determine if value changes upon a refresh should be verified. If so, the - * library will immediately refresh the value a second time whenever a change is observed. This helps to filter - * out spurious data reported occasionally by some devices. - * \param _id The unique identifier of the value whose changes should or should not be verified. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \sa Manager::SetChangeVerified - */ - bool GetChangeVerified( ValueID const& _id ); - - /** - * \brief Starts an activity in a device. - * Since buttons are write-only values that do not report a state, no notification callbacks are sent. - * \param _id The unique identifier of the integer value. - * \return true if the activity was started. Returns false if the value is not a ValueID::ValueType_Button. The type can be tested with a call to ValueID::GetType. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - */ - bool PressButton( ValueID const& _id ); - - /** - * \brief Stops an activity in a device. - * Since buttons are write-only values that do not report a state, no notification callbacks are sent. - * \param _id The unique identifier of the integer value. - * \return true if the activity was stopped. Returns false if the value is not a ValueID::ValueType_Button. The type can be tested with a call to ValueID::GetType. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - */ - bool ReleaseButton( ValueID const& _id ); - - /** - * \brief Sets the Valid BitMask for a BitSet ValueID - * Sets a BitMask of Valid Bits for a BitSet ValueID - * \param _id The unique identifier of the integer value. - * \param _mask The Mask to set - * \return true if the mask was applied. Returns false if the value is not a ValueID::ValueType_BitSet or the Mask was invalid. The type can be tested with a call to ValueID::GetType. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - */ - bool SetBitMask( ValueID const& _id, uint32 _mask ); - - /** - * \brief Gets the Valid BitMask for a BitSet ValueID - * Gets a BitMask of Valid Bits for a BitSet ValueID - * \param _id The unique identifier of the integer value. - * \param o_mask The Mask to for the BitSet - * \return true if the mask was retrieved. Returns false if the value is not a ValueID::ValueType_BitSet or the Mask was invalid. The type can be tested with a call to ValueID::GetType. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - */ - bool GetBitMask( ValueID const& _id, int32* o_mask ); - - /** - * \brief Gets the size of a BitMask ValueID - * Gets the size of a BitMask ValueID - Either 1, 2 or 4 - * \param _id The unique identifier of the integer value. - * \param o_size The Size of the BitSet - * \return true if the size was retrieved. Returns false if the value is not a ValueID::ValueType_BitSet or the Mask was invalid. The type can be tested with a call to ValueID::GetType. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - */ - bool GetBitSetSize( ValueID const& _id, uint8* o_size ); - - - - /*@}*/ - - //----------------------------------------------------------------------------- - // Climate Control Schedules - //----------------------------------------------------------------------------- - /** \name Climate Control Schedules - * Methods for accessing schedule values. All the methods require a ValueID, which will have been provided - * in the ValueAdded Notification callback when the the value was first discovered by OpenZWave. - *

The ValueType_Schedule is a specialized Value used to simplify access to the switch point schedule - * information held by a setback thermostat that supports the Climate Control Schedule command class. - * Each schedule contains up to nine switch points for a single day, consisting of a time in - * hours and minutes (24 hour clock) and a setback in tenths of a degree Celsius. The setback value can - * range from -128 (-12.8C) to 120 (12.0C). There are two special setback values - 121 is used to set - * Frost Protection mode, and 122 is used to set Energy Saving mode. - *

The switch point methods only modify OpenZWave's copy of the schedule information. Once all changes - * have been made, they are sent to the device by calling SetSchedule. - */ - /*@{*/ - - /** - * \brief Get the number of switch points defined in a schedule. - * \param _id The unique identifier of the schedule value. - * \return the number of switch points defined in this schedule. Returns zero if the value is not a ValueID::ValueType_Schedule. The type can be tested with a call to ValueID::GetType. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - */ - uint8 GetNumSwitchPoints( ValueID const& _id ); - - /** - * \brief Set a switch point in the schedule. - * Inserts a new switch point into the schedule, unless a switch point already exists at the specified - * time in which case that switch point is updated with the new setback value instead. - * A maximum of nine switch points can be set in the schedule. - * \param _id The unique identifier of the schedule value. - * \param _hours The hours part of the time when the switch point will trigger. The time is set using - * the 24-hour clock, so this value must be between 0 and 23. - * \param _minutes The minutes part of the time when the switch point will trigger. This value must be - * between 0 and 59. - * \param _setback The setback in tenths of a degree Celsius. The setback value can range from -128 (-12.8C) - * to 120 (12.0C). There are two special setback values - 121 is used to set Frost Protection mode, and - * 122 is used to set Energy Saving mode. - * \return true if successful. Returns false if the value is not a ValueID::ValueType_Schedule. The type can be tested with a call to ValueID::GetType. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \see GetNumSwitchPoints, RemoveSwitchPoint, ClearSwitchPoints - */ - bool SetSwitchPoint( ValueID const& _id, uint8 const _hours, uint8 const _minutes, int8 const _setback ); - - /** - * \brief Remove a switch point from the schedule. - * Removes the switch point at the specified time from the schedule. - * \param _id The unique identifier of the schedule value. - * \param _hours The hours part of the time when the switch point will trigger. The time is set using - * the 24-hour clock, so this value must be between 0 and 23. - * \param _minutes The minutes part of the time when the switch point will trigger. This value must be - * between 0 and 59. - * \return true if successful. Returns false if the value is not a ValueID::ValueType_Schedule or if there - * is not switch point with the specified time values. The type can be tested with a call to ValueID::GetType. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \see GetNumSwitchPoints, SetSwitchPoint, ClearSwitchPoints - */ - bool RemoveSwitchPoint( ValueID const& _id, uint8 const _hours, uint8 const _minutes ); - - /** - * \brief Clears all switch points from the schedule. - * \param _id The unique identifier of the schedule value. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \see GetNumSwitchPoints, SetSwitchPoint, RemoveSwitchPoint - */ - void ClearSwitchPoints( ValueID const& _id ); - - /** - * \brief Gets switch point data from the schedule. - * Retrieves the time and setback values from a switch point in the schedule. - * \param _id The unique identifier of the schedule value. - * \param _idx The index of the switch point, between zero and one less than the value - * returned by GetNumSwitchPoints. - * \param o_hours a pointer to a uint8 that will be filled with the hours part of the switch point data. - * \param o_minutes a pointer to a uint8 that will be filled with the minutes part of the switch point data. - * \param o_setback a pointer to an int8 that will be filled with the setback value. This can range from -128 - * (-12.8C)to 120 (12.0C). There are two special setback values - 121 is used to set Frost Protection mode, and - * 122 is used to set Energy Saving mode. - * \return true if successful. Returns false if the value is not a ValueID::ValueType_Schedule. The type can be tested with a call to ValueID::GetType. - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid - * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type - * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found - * \see GetNumSwitchPoints - */ - bool GetSwitchPoint( ValueID const& _id, uint8 const _idx, uint8* o_hours, uint8* o_minutes, int8* o_setback ); - - /*@}*/ - - //----------------------------------------------------------------------------- - // SwitchAll - //----------------------------------------------------------------------------- - /** \name SwitchAll - * Methods for switching all devices on or off together. The devices must support - * the SwitchAll command class. The command is first broadcast to all nodes, and - * then followed up with individual commands to each node (because broadcasts are - * not routed, the message might not otherwise reach all the nodes). - */ - /*@{*/ - /** - * \brief Switch all devices on. - * All devices that support the SwitchAll command class will be turned on. - * \deprecated This method has been depreciated. Please use the ValueID interface instead. - */ - DEPRECATED void SwitchAllOn( uint32 const _homeId ); + /** + * \brief Get the generic type of a node. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \param _instance If Specified, Get the Generic Type for a Instance + * \return the node's generic type. + */ + uint8 GetNodeGeneric(uint32 const _homeId, uint8 const _nodeId, uint8 const _instance = 0); - /** - * \brief Switch all devices off. - * All devices that support the SwitchAll command class will be turned off. - * \deprecated This method has been depreciated. Please use the ValueID interface instead. - */ - DEPRECATED void SwitchAllOff( uint32 const _homeId ); - - /*@}*/ - - //----------------------------------------------------------------------------- - // Configuration Parameters - //----------------------------------------------------------------------------- - /** \name Configuration Parameters - * Methods for accessing device configuration parameters. - * Configuration parameters are values that are managed by the Configuration command class. - * The values are device-specific and are not reported by the devices. Information on parameters - * is provided only in the device user manual. - *

An ongoing task for the OpenZWave project is to create XML files describing the available - * parameters for every Z-Wave. See the config folder in the project source code for examples. - */ - /*@{*/ - public: - /** - * \brief Set the value of a configurable parameter in a device. - * Some devices have various parameters that can be configured to control the device behavior. - * These are not reported by the device over the Z-Wave network, but can usually be found in - * the device's user manual. - * This method returns immediately, without waiting for confirmation from the device that the - * change has been made. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to configure. - * \param _param The index of the parameter. - * \param _value The value to which the parameter should be set. - * \param _size Is an optional number of bytes to be sent for the parameter _value. Defaults to 2. - * \return true if the a message setting the value was sent to the device. - * \see RequestConfigParam - */ - bool SetConfigParam( uint32 const _homeId, uint8 const _nodeId, uint8 const _param, int32 _value, uint8 const _size = 2 ); - - /** - * \brief Request the value of a configurable parameter from a device. - * Some devices have various parameters that can be configured to control the device behavior. - * These are not reported by the device over the Z-Wave network, but can usually be found in - * the device's user manual. - * This method requests the value of a parameter from the device, and then returns immediately, - * without waiting for a response. If the parameter index is valid for this device, and the - * device is awake, the value will eventually be reported via a ValueChanged notification callback. - * The ValueID reported in the callback will have an index set the same as _param and a command class - * set to the same value as returned by a call to Configuration::StaticGetCommandClassId. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to configure. - * \param _param The index of the parameter. - * \see SetConfigParam, ValueID, Notification - */ - void RequestConfigParam( uint32 const _homeId, uint8 const _nodeId, uint8 const _param ); + /** + * \brief Get the generic type of a node as a String + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \param _instance If Specified, Get the Generic Type for a Instance + * \return the node's generic type. + */ + string GetNodeGenericString(uint32 const _homeId, uint8 const _nodeId, uint8 const _instance = 0); - /** - * \brief Request the values of all known configurable parameters from a device. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node to configure. - * \see SetConfigParam, ValueID, Notification - */ - void RequestAllConfigParams( uint32 const _homeId, uint8 const _nodeId ); - /*@}*/ - - //----------------------------------------------------------------------------- - // Groups (wrappers for the Node methods) - //----------------------------------------------------------------------------- - /** \name Groups - * Methods for accessing device association groups. - */ - /*@{*/ - public: - /** - * \brief Gets the number of association groups reported by this node - * In Z-Wave, groups are numbered starting from one. For example, if a call to GetNumGroups returns 4, the _groupIdx - * value to use in calls to GetAssociations, AddAssociation and RemoveAssociation will be a number between 1 and 4. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node whose groups we are interested in. - * \return The number of groups. - * \see GetAssociations, GetMaxAssociations, AddAssociation, RemoveAssociation - */ - uint8 GetNumGroups( uint32 const _homeId, uint8 const _nodeId ); - - /** - * \brief Gets the associations for a group. - * Makes a copy of the list of associated nodes in the group, and returns it in an array of uint8's. - * The caller is responsible for freeing the array memory with a call to delete []. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node whose associations we are interested in. - * \param _groupIdx One-based index of the group (because Z-Wave product manuals use one-based group numbering). - * \param o_associations If the number of associations returned is greater than zero, o_associations will be set to point to an array containing the IDs of the associated nodes. - * \return The number of nodes in the associations array. If zero, the array will point to NULL, and does not need to be deleted. - * \see GetNumGroups, AddAssociation, RemoveAssociation, GetMaxAssociations - */ - uint32 GetAssociations( uint32 const _homeId, uint8 const _nodeId, uint8 const _groupIdx, uint8** o_associations ); - - /** - * \brief Gets the associations for a group. - * Makes a copy of the list of associated nodes in the group, and returns it in an array of InstanceAssociation's. - * The caller is responsible for freeing the array memory with a call to delete []. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node whose associations we are interested in. - * \param _groupIdx One-based index of the group (because Z-Wave product manuals use one-based group numbering). - * \param o_associations If the number of associations returned is greater than zero, o_associations will be set to point to an array containing the IDs and instances of the associated nodes. - * \return The number of items in the associations array. If zero, the array will point to NULL, and does not need to be deleted. - * \see GetNumGroups, AddAssociation, RemoveAssociation, GetMaxAssociations - */ - uint32 GetAssociations( uint32 const _homeId, uint8 const _nodeId, uint8 const _groupIdx, InstanceAssociation** o_associations ); - - /** - * \brief Gets the maximum number of associations for a group. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node whose associations we are interested in. - * \param _groupIdx one-based index of the group (because Z-Wave product manuals use one-based group numbering). - * \return The maximum number of nodes that can be associated into the group. - * \see GetNumGroups, AddAssociation, RemoveAssociation, GetAssociations - */ - uint8 GetMaxAssociations( uint32 const _homeId, uint8 const _nodeId, uint8 const _groupIdx ); - - /** - * \brief Returns true is group supports multi instance. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node whose associations we are interested in. - * \param _groupIdx one-based index of the group (because Z-Wave product manuals use one-based group numbering). - * \return True if group supports multi instance. - * \see GetNumGroups, AddAssociation, RemoveAssociation, GetAssociations, GetMaxAssociations - */ - bool IsMultiInstance( uint32 const _homeId, uint8 const _nodeId, uint8 const _groupIdx ); - - /** - * \brief Returns a label for the particular group of a node. - * This label is populated by the device specific configuration files. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node whose associations are to be changed. - * \param _groupIdx One-based index of the group (because Z-Wave product manuals use one-based group numbering). - * \see GetNumGroups, GetAssociations, GetMaxAssociations, AddAssociation - */ - string GetGroupLabel( uint32 const _homeId, uint8 const _nodeId, uint8 const _groupIdx ); - - /** - * \brief Adds a node to an association group. - * Due to the possibility of a device being asleep, the command is assumed to succeed, and the association data - * held in this class is updated directly. This will be reverted by a future Association message from the device - * if the Z-Wave message actually failed to get through. Notification callbacks will be sent in both cases. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node whose associations are to be changed. - * \param _groupIdx One-based index of the group (because Z-Wave product manuals use one-based group numbering). - * \param _targetNodeId Identifier for the node that will be added to the association group. - * \param _instance Identifier for the instance that will be added to the association group. - * \see GetNumGroups, GetAssociations, GetMaxAssociations, RemoveAssociation - */ - void AddAssociation( uint32 const _homeId, uint8 const _nodeId, uint8 const _groupIdx, uint8 const _targetNodeId, uint8 const _instance = 0x00 ); - - /** - * \brief Removes a node from an association group. - * Due to the possibility of a device being asleep, the command is assumed to succeed, and the association data - * held in this class is updated directly. This will be reverted by a future Association message from the device - * if the Z-Wave message actually failed to get through. Notification callbacks will be sent in both cases. - * \param _homeId The Home ID of the Z-Wave controller that manages the node. - * \param _nodeId The ID of the node whose associations are to be changed. - * \param _groupIdx One-based index of the group (because Z-Wave product manuals use one-based group numbering). - * \param _targetNodeId Identifier for the node that will be removed from the association group. - * \param _instance Identifier for the instance that will be removed to the association group. - * \see GetNumGroups, GetAssociations, GetMaxAssociations, AddAssociation - */ - void RemoveAssociation( uint32 const _homeId, uint8 const _nodeId, uint8 const _groupIdx, uint8 const _targetNodeId, uint8 const _instance = 0x00 ); + /** + * \brief Get the specific type of a node. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \param _instance If Specified, Get the Specific Type for a Instance + * \return the node's specific type. + */ + uint8 GetNodeSpecific(uint32 const _homeId, uint8 const _nodeId, uint8 const _instance = 0); - /*@}*/ + /** + * \brief Get the specific type of a node as a string + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \param _instance If Specified, Get the Specific Type for a Instance + * \return the node's specific type. + */ + string GetNodeSpecificString(uint32 const _homeId, uint8 const _nodeId, uint8 const _instance = 0); + + + /** + * \brief Get a human-readable label describing the node + * The label is taken from the Z-Wave specific, generic or basic type, depending on which of those values are specified by the node. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return A string containing the label text. + */ + string GetNodeType(uint32 const _homeId, uint8 const _nodeId); + + /** + * \brief Get the bitmap of this node's neighbors + * + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \param _nodeNeighbors An array of 29 uint8s to hold the neighbor bitmap + * \sa SyncronizeNodeNeighbors + */ + uint32 GetNodeNeighbors(uint32 const _homeId, uint8 const _nodeId, uint8** _nodeNeighbors); + + /** + * \brief Update the List of Neighbors on a particular node + * + * This retrieves the latest copy of the Neighbor lists for a particular node and should be called + * before calling GetNodeNeighbors to ensure OZW returns the most recent list of Neighbors + * + * \param _homeId The HomeID of the Z-Wave controller than manages the node. + * \param _nodeId The ID of the node to get a updated list of Neighbors from + * \sa GetNodeNeighbors + */ + + void SyncronizeNodeNeighbors(uint32 const _homeId, uint8 const _nodeId); + + /** + * \brief Get the manufacturer name of a device + * The manufacturer name would normally be handled by the Manufacturer Specific command class, + * taking the manufacturer ID reported by the device and using it to look up the name from the + * manufacturer_specific.xml file in the OpenZWave config folder. + * However, there are some devices that do not support the command class, so to enable the user + * to manually set the name, it is stored with the node data and accessed via this method rather + * than being reported via a command class Value object. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return A string containing the node's manufacturer name. + * \see SetNodeManufacturerName, GetNodeProductName, SetNodeProductName + */ + string GetNodeManufacturerName(uint32 const _homeId, uint8 const _nodeId); + + /** + * \brief Get the product name of a device + * The product name would normally be handled by the Manufacturer Specific command class, + * taking the product Type and ID reported by the device and using it to look up the name from the + * manufacturer_specific.xml file in the OpenZWave config folder. + * However, there are some devices that do not support the command class, so to enable the user + * to manually set the name, it is stored with the node data and accessed via this method rather + * than being reported via a command class Value object. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return A string containing the node's product name. + * \see SetNodeProductName, GetNodeManufacturerName, SetNodeManufacturerName + */ + string GetNodeProductName(uint32 const _homeId, uint8 const _nodeId); + + /** + * \brief Get the name of a node + * The node name is a user-editable label for the node that would normally be handled by the + * Node Naming command class, but many devices do not support it. So that a node can always + * be named, OpenZWave stores it with the node data, and provides access through this method + * and SetNodeName, rather than reporting it via a command class Value object. + * The maximum length of a node name is 16 characters. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return A string containing the node's name. + * \see SetNodeName, GetNodeLocation, SetNodeLocation + */ + string GetNodeName(uint32 const _homeId, uint8 const _nodeId); + + /** + * \brief Get the location of a node + * The node location is a user-editable string that would normally be handled by the Node Naming + * command class, but many devices do not support it. So that a node can always report its + * location, OpenZWave stores it with the node data, and provides access through this method + * and SetNodeLocation, rather than reporting it via a command class Value object. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return A string containing the node's location. + * \see SetNodeLocation, GetNodeName, SetNodeName + */ + string GetNodeLocation(uint32 const _homeId, uint8 const _nodeId); + + /** + * \brief Get the manufacturer ID of a device + * The manufacturer ID is a four digit hex code and would normally be handled by the Manufacturer + * Specific command class, but not all devices support it. Although the value reported by this + * method will be an empty string if the command class is not supported and cannot be set by the + * user, the manufacturer ID is still stored with the node data (rather than being reported via a + * command class Value object) to retain a consistent approach with the other manufacturer specific data. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return A string containing the node's manufacturer ID, or an empty string if the manufacturer + * specific command class is not supported by the device. + * \see GetNodeProductType, GetNodeProductId, GetNodeManufacturerName, GetNodeProductName + * \todo Change the return to uint16 in 2.0 time frame + */ + string GetNodeManufacturerId(uint32 const _homeId, uint8 const _nodeId); + + /** + * \brief Get the product type of a device + * The product type is a four digit hex code and would normally be handled by the Manufacturer Specific + * command class, but not all devices support it. Although the value reported by this method will + * be an empty string if the command class is not supported and cannot be set by the user, the product + * type is still stored with the node data (rather than being reported via a command class Value object) + * to retain a consistent approach with the other manufacturer specific data. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return A string containing the node's product type, or an empty string if the manufacturer + * specific command class is not supported by the device. + * \see GetNodeManufacturerId, GetNodeProductId, GetNodeManufacturerName, GetNodeProductName + * \todo Change the return to uint16 in 2.0 time frame + */ + string GetNodeProductType(uint32 const _homeId, uint8 const _nodeId); + + /** + * \brief Get the product ID of a device + * The product ID is a four digit hex code and would normally be handled by the Manufacturer Specific + * command class, but not all devices support it. Although the value reported by this method will + * be an empty string if the command class is not supported and cannot be set by the user, the product + * ID is still stored with the node data (rather than being reported via a command class Value object) + * to retain a consistent approach with the other manufacturer specific data. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return A string containing the node's product ID, or an empty string if the manufacturer + * specific command class is not supported by the device. + * \see GetNodeManufacturerId, GetNodeProductType, GetNodeManufacturerName, GetNodeProductName + * \todo Change the return to uint16 in 2.0 time frame + */ + string GetNodeProductId(uint32 const _homeId, uint8 const _nodeId); + + /** + * \brief Set the manufacturer name of a device + * The manufacturer name would normally be handled by the Manufacturer Specific command class, + * taking the manufacturer ID reported by the device and using it to look up the name from the + * manufacturer_specific.xml file in the OpenZWave config folder. + * However, there are some devices that do not support the command class, so to enable the user + * to manually set the name, it is stored with the node data and accessed via this method rather + * than being reported via a command class Value object. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \param _manufacturerName A string containing the node's manufacturer name. + * \see GetNodeManufacturerName, GetNodeProductName, SetNodeProductName + */ + void SetNodeManufacturerName(uint32 const _homeId, uint8 const _nodeId, string const& _manufacturerName); + + /** + * \brief Set the product name of a device + * The product name would normally be handled by the Manufacturer Specific command class, + * taking the product Type and ID reported by the device and using it to look up the name from the + * manufacturer_specific.xml file in the OpenZWave config folder. + * However, there are some devices that do not support the command class, so to enable the user + * to manually set the name, it is stored with the node data and accessed via this method rather + * than being reported via a command class Value object. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \param _productName A string containing the node's product name. + * \see GetNodeProductName, GetNodeManufacturerName, SetNodeManufacturerName + */ + void SetNodeProductName(uint32 const _homeId, uint8 const _nodeId, string const& _productName); + + /** + * \brief Set the name of a node + * The node name is a user-editable label for the node that would normally be handled by the + * Node Naming command class, but many devices do not support it. So that a node can always + * be named, OpenZWave stores it with the node data, and provides access through this method + * and GetNodeName, rather than reporting it via a command class Value object. + * If the device does support the Node Naming command class, the new name will be sent to the node. + * The maximum length of a node name is 16 characters. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \param _nodeName A string containing the node's name. + * \see GetNodeName, GetNodeLocation, SetNodeLocation + */ + void SetNodeName(uint32 const _homeId, uint8 const _nodeId, string const& _nodeName); + + /** + * \brief Set the location of a node + * The node location is a user-editable string that would normally be handled by the Node Naming + * command class, but many devices do not support it. So that a node can always report its + * location, OpenZWave stores it with the node data, and provides access through this method + * and GetNodeLocation, rather than reporting it via a command class Value object. + * If the device does support the Node Naming command class, the new location will be sent to the node. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \param _location A string containing the node's location. + * \see GetNodeLocation, GetNodeName, SetNodeName + */ + void SetNodeLocation(uint32 const _homeId, uint8 const _nodeId, string const& _location); + + /** + * \brief Turns a node on + * This is a helper method to simplify basic control of a node. It is the equivalent of + * changing the level reported by the node's Basic command class to 255, and will generate a + * ValueChanged notification from that class. This command will turn on the device at its + * last known level, if supported by the device, otherwise it will turn it on at 100%. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to be changed. + * \deprecated This method has been depreciated in setting the ValueID's directly (Remove in 1.8) + * + * \see SetNodeOff, SetNodeLevel + */ + DEPRECATED void SetNodeOn(uint32 const _homeId, uint8 const _nodeId); + + /** + * \brief Turns a node off + * This is a helper method to simplify basic control of a node. It is the equivalent of + * changing the level reported by the node's Basic command class to zero, and will generate + * a ValueChanged notification from that class. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to be changed. + * \deprecated This method has been depreciated in setting the ValueID's directly (Remove in 1.8) + * \see SetNodeOn, SetNodeLevel + */ + DEPRECATED void SetNodeOff(uint32 const _homeId, uint8 const _nodeId); + + /** + * \brief Sets the basic level of a node + * This is a helper method to simplify basic control of a node. It is the equivalent of + * changing the value reported by the node's Basic command class and will generate a + * ValueChanged notification from that class. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to be changed. + * \param _level The level to set the node. Valid values are 0-99 and 255. Zero is off and + * 99 is fully on. 255 will turn on the device at its last known level (if supported). + * \deprecated This method has been depreciated in setting the ValueID's directly (Remove in 1.8) + * \see SetNodeOn, SetNodeOff + */ + DEPRECATED void SetNodeLevel(uint32 const _homeId, uint8 const _nodeId, uint8 const _level); + + /** + * \brief Get whether the node information has been received + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return True if the node information has been received yet + */ + bool IsNodeInfoReceived(uint32 const _homeId, uint8 const _nodeId); + + /** + * \brief Get whether the node has the defined class available or not + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \param _commandClassId Id of the class to test for + * \return True if the node does have the class instantiated, will return name & version + */ + bool GetNodeClassInformation(uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, string *_className = NULL, uint8 *_classVersion = NULL); + + /** + * \brief Get a friendly name for the CommandClass ID + * \param _commandClassId Id of the class to test for + * \return String returning the CommandClass Name + */ + string GetCommandClassName(uint8 const _commandClassId); + + /** + * \brief Get whether the node is awake or asleep + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return True if the node is awake + */ + bool IsNodeAwake(uint32 const _homeId, uint8 const _nodeId); + + /** + * \brief Get whether the node is working or has failed + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return True if the node has failed and is no longer part of the network + */ + bool IsNodeFailed(uint32 const _homeId, uint8 const _nodeId); + + /** + * \brief Get whether the node's query stage as a string + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return name of current query stage as a string. + */ + string GetNodeQueryStage(uint32 const _homeId, uint8 const _nodeId); + + /** + * \brief Get the node device type as reported in the Z-Wave+ Info report. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return the node's DeviceType + */ + uint16 GetNodeDeviceType(uint32 const _homeId, uint8 const _nodeId); + + /** + * \brief Get the node device type as reported in the Z-Wave+ Info report. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return the node's Device Type as a string. + */ + string GetNodeDeviceTypeString(uint32 const _homeId, uint8 const _nodeId); + + /** + * \brief Get the node role as reported in the Z-Wave+ Info report. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return the node's user icon. + */ + uint8 GetNodeRole(uint32 const _homeId, uint8 const _nodeId); + + /** + * \brief Get the node role as reported in the Z-Wave+ Info report. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return the node's role type as a string + */ + string GetNodeRoleString(uint32 const _homeId, uint8 const _nodeId); + + /** + * \brief Get the node PlusType as reported in the Z-Wave+ Info report. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return the node's PlusType + */ + uint8 GetNodePlusType(uint32 const _homeId, uint8 const _nodeId); + /** + * \brief Get the node PlusType as reported in the Z-Wave+ Info report. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to query. + * \return the node's PlusType as a string + */ + string GetNodePlusTypeString(uint32 const _homeId, uint8 const _nodeId); + + /*@}*/ + + //----------------------------------------------------------------------------- + // Instances + //----------------------------------------------------------------------------- + /** \name Instances + * Methods for accessing Instance Information. + */ + /*@{*/ + public: + /** + *\brief Get the Instance Label for a specific ValueID + * returns the Instance Label for a Specific ValueID on a CommandClass, or the Global Instance Label + * if there is no specific label for the CommandClass + *\param _id The unique identifier of the value + *\return The Instance Label + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + */ + string GetInstanceLabel(ValueID const &_id); + + /** + *\brief Get the Instance Label for a specific CommandClass + * returns the Label for a Specific Instance on a Specific CommandClass, or the Global Instance Label + * if there is no specific label for the CommandClass + *\param _homeId the HomeID for the network you are querying + *\param _node The Node you are interested in. + *\param _cc The CommandClass for the Label you are interested in + *\param _instance the Instance you are querying for + *\return The Instance Label + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + */ + string GetInstanceLabel(uint32 const _homeId, uint8 const _node, uint8 const _cc, uint8 const _instance); + + /*@}*/ + //----------------------------------------------------------------------------- + // Values + //----------------------------------------------------------------------------- + /** \name Values + * Methods for accessing device values. All the methods require a ValueID, which will have been provided + * in the ValueAdded Notification callback when the the value was first discovered by OpenZWave. + */ + /*@{*/ + public: + /** + * \brief Gets the user-friendly label for the value. + * \param _id The unique identifier of the value. + * \param _pos the Bit To Get the Label for if its a BitSet ValueID + * \return The value label. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \see ValueID + */ + string GetValueLabel(ValueID const& _id, int32 _pos = -1); + + /** + * \brief Sets the user-friendly label for the value. + * \param _id The unique identifier of the value. + * \param _pos the Bit To set the Label for if its a BitSet ValueID + * \param _value The new value of the label. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \see ValueID + */ + void SetValueLabel(ValueID const& _id, string const& _value, int32 _pos = -1); + + /** + * \brief Gets the units that the value is measured in. + * \param _id The unique identifier of the value. + * \return The value units. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \see ValueID + */ + string GetValueUnits(ValueID const& _id); + + /** + * \brief Sets the units that the value is measured in. + * \param _id The unique identifier of the value. + * \param _value The new value of the units. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \see ValueID + */ + void SetValueUnits(ValueID const& _id, string const& _value); + + /** + * \brief Gets a help string describing the value's purpose and usage. + * \param _id The unique identifier of the value. + * \param _pos Get the Help for associated Bits (Valid with ValueBitSet only) + * \return The value help text. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \see ValueID + */ + string GetValueHelp(ValueID const& _id, int32 _pos = -1); + + /** + * \brief Sets a help string describing the value's purpose and usage. + * \param _id The unique identifier of the value. + * \param _value The new value of the help text. + * \param __pos Set the Help for a associated Bit (Valid with ValueBitSet Only) + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \see ValueID + */ + void SetValueHelp(ValueID const& _id, string const& _value, int32 _pos = -1); + + /** + * \brief Gets the minimum that this value may contain. + * \param _id The unique identifier of the value. + * \return The value minimum. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \see ValueID + */ + int32 GetValueMin(ValueID const& _id); + + /** + * \brief Gets the maximum that this value may contain. + * \param _id The unique identifier of the value. + * \return The value maximum. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \see ValueID + */ + int32 GetValueMax(ValueID const& _id); + + /** + * \brief Test whether the value is read-only. + * \param _id The unique identifier of the value. + * \return true if the value cannot be changed by the user. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \see ValueID + */ + bool IsValueReadOnly(ValueID const& _id); + + /** + * \brief Test whether the value is write-only. + * \param _id The unique identifier of the value. + * \return true if the value can only be written to and not read. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \see ValueID + */ + bool IsValueWriteOnly(ValueID const& _id); + + /** + * \brief Test whether the value has been set. + * \param _id The unique identifier of the value. + * \return true if the value has actually been set by a status message from the device, rather than simply being the default. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \see ValueID + */ + bool IsValueSet(ValueID const& _id); + + /** + * \brief Test whether the value is currently being polled. + * \param _id The unique identifier of the value. + * \return true if the value is being polled, otherwise false. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \see ValueID + */ + bool IsValuePolled(ValueID const& _id); + + /** + * \brief Test whether the ValueID is valid. + * \param _id The unique identifier of the value. + * \return true if the valueID is valid, otherwise false. + * \see ValueID + */ + bool IsValueValid(ValueID const& _id); + + + /** + * \brief Gets a the value of a Bit from a BitSet ValueID + * \param _id The unique identifier of the value. + * \param _pos the Bit you want to test for + * \param o_value Pointer to a bool that will be filled with the value. + * \return true if the value was obtained. Returns false if the value is not a ValueID::ValueType_BitSet. The type can be tested with a call to ValueID::GetType. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \see ValueID::GetType, GetValueAsBitSet, GetValueAsByte, GetValueAsFloat, GetValueAsInt, GetValueAsShort, GetValueAsString, GetValueListSelection, GetValueListItems, GetValueAsRaw + */ + bool GetValueAsBitSet(ValueID const& _id, uint8 _pos, bool* o_value); + + /** + * \brief Gets a value as a bool. + * \param _id The unique identifier of the value. + * \param o_value Pointer to a bool that will be filled with the value. + * \return true if the value was obtained. Returns false if the value is not a ValueID::ValueType_Bool. The type can be tested with a call to ValueID::GetType. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \see ValueID::GetType, GetValueAsBitSet, GetValueAsByte, GetValueAsFloat, GetValueAsInt, GetValueAsShort, GetValueAsString, GetValueListSelection, GetValueListItems, GetValueAsRaw + */ + bool GetValueAsBool(ValueID const& _id, bool* o_value); + + /** + * \brief Gets a value as an 8-bit unsigned integer. + * \param _id The unique identifier of the value. + * \param o_value Pointer to a uint8 that will be filled with the value. + * \return true if the value was obtained. Returns false if the value is not a ValueID::ValueType_Byte. The type can be tested with a call to ValueID::GetType + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \see ValueID::GetType, GetValueAsBitSet, GetValueAsBool, GetValueAsFloat, GetValueAsInt, GetValueAsShort, GetValueAsString, GetValueListSelection, GetValueListItems, GetValueAsRaw + */ + bool GetValueAsByte(ValueID const& _id, uint8* o_value); + + /** + * \brief Gets a value as a float. + * \param _id The unique identifier of the value. + * \param o_value Pointer to a float that will be filled with the value. + * \return true if the value was obtained. Returns false if the value is not a ValueID::ValueType_Decimal. The type can be tested with a call to ValueID::GetType + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \see ValueID::GetType, GetValueAsBitSet, GetValueAsBool, GetValueAsByte, GetValueAsInt, GetValueAsShort, GetValueAsString, GetValueListSelection, GetValueListItems, GetValueAsRaw + */ + bool GetValueAsFloat(ValueID const& _id, float* o_value); + + /** + * \brief Gets a value as a 32-bit signed integer. + * \param _id The unique identifier of the value. + * \param o_value Pointer to an int32 that will be filled with the value. + * \return true if the value was obtained. Returns false if the value is not a ValueID::ValueType_Int. The type can be tested with a call to ValueID::GetType + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \see ValueID::GetType, GetValueAsBitSet, GetValueAsBool, GetValueAsByte, GetValueAsFloat, GetValueAsShort, GetValueAsString, GetValueListSelection, GetValueListItems, GetValueAsRaw + */ + bool GetValueAsInt(ValueID const& _id, int32* o_value); + + /** + * \brief Gets a value as a 16-bit signed integer. + * \param _id The unique identifier of the value. + * \param o_value Pointer to an int16 that will be filled with the value. + * \return true if the value was obtained. Returns false if the value is not a ValueID::ValueType_Short. The type can be tested with a call to ValueID::GetType. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \see ValueID::GetType, GetValueAsBitSet, GetValueAsBool, GetValueAsByte, GetValueAsFloat, GetValueAsInt, GetValueAsString, GetValueListSelection, GetValueListItems, GetValueAsRaw + */ + bool GetValueAsShort(ValueID const& _id, int16* o_value); + + /** + * \brief Gets a value as a string. + * Creates a string representation of a value, regardless of type. + * \param _id The unique identifier of the value. + * \param o_value Pointer to a string that will be filled with the value. + * \return true if the value was obtained. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \see ValueID::GetType, GetValueAsBitSet, GetValueAsBool, GetValueAsByte, GetValueAsFloat, GetValueAsInt, GetValueAsShort, GetValueListSelection, GetValueListItems, GetValueAsRaw + */ + bool GetValueAsString(ValueID const& _id, string* o_value); + + /** + * \brief Gets a value as a collection of bytes. + * \param _id The unique identifier of the value. + * \param o_value Pointer to a uint8* that will be filled with the value. This return value will need to be freed as it was dynamically allocated. + * \param o_length Pointer to a uint8 that will be fill with the data length. + * \return true if the value was obtained. Returns false if the value is not a ValueID::ValueType_Raw. The type can be tested with a call to ValueID::GetType. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \see ValueID::GetType, GetValueAsBitSet, GetValueAsBool, GetValueAsByte, GetValueAsFloat, GetValueAsInt, GetValueAsShort, GetValueListSelection, GetValueListItems, GetValueAsRaw + */ + bool GetValueAsRaw(ValueID const& _id, uint8** o_value, uint8* o_length); + + /** + * \brief Gets the selected item from a list (as a string). + * \param _id The unique identifier of the value. + * \param o_value Pointer to a string that will be filled with the selected item. + * \return True if the value was obtained. Returns false if the value is not a ValueID::ValueType_List. The type can be tested with a call to ValueID::GetType. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \see ValueID::GetType, GetValueAsBitSet, GetValueAsBool, GetValueAsByte, GetValueAsFloat, GetValueAsInt, GetValueAsShort, GetValueAsString, GetValueListItems, GetValueAsRaw + */ + bool GetValueListSelection(ValueID const& _id, string* o_value); + + /** + * \brief Gets the selected item from a list (as an integer). + * \param _id The unique identifier of the value. + * \param o_value Pointer to an integer that will be filled with the selected item. + * \return True if the value was obtained. Returns false if the value is not a ValueID::ValueType_List. The type can be tested with a call to ValueID::GetType. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \see ValueID::GetType, GetValueAsBitSet, GetValueAsBool, GetValueAsByte, GetValueAsFloat, GetValueAsInt, GetValueAsShort, GetValueAsString, GetValueListItems, GetValueAsRaw + */ + bool GetValueListSelection(ValueID const& _id, int32* o_value); + + /** + * \brief Gets the list of items from a list value. + * \param _id The unique identifier of the value. + * \param o_value Pointer to a vector of strings that will be filled with list items. The vector will be cleared before the items are added. + * \return true if the list items were obtained. Returns false if the value is not a ValueID::ValueType_List. The type can be tested with a call to ValueID::GetType. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \see ValueID::GetType, GetValueAsBitSet, GetValueAsBool, GetValueAsByte, GetValueAsFloat, GetValueAsInt, GetValueAsShort, GetValueAsString, GetValueListSelection, GetValueAsRaw + */ + bool GetValueListItems(ValueID const& _id, vector* o_value); + + /** + * \brief Gets the list of values from a list value. + * \param _id The unique identifier of the value. + * \param o_value Pointer to a vector of integers that will be filled with list items. The vector will be cleared before the items are added. + * \return true if the list values were obtained. Returns false if the value is not a ValueID::ValueType_List. The type can be tested with a call to ValueID::GetType. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \see ValueID::GetType, GetValueAsBitSet, GetValueAsBool, GetValueAsByte, GetValueAsFloat, GetValueAsInt, GetValueAsShort, GetValueAsString, GetValueListSelection, GetValueAsRaw + */ + bool GetValueListValues(ValueID const& _id, vector* o_value); + + /** + * \brief Gets a float value's precision. + * \param _id The unique identifier of the value. + * \param o_value Pointer to a uint8 that will be filled with the precision value. + * \return true if the value was obtained. Returns false if the value is not a ValueID::ValueType_Decimal. The type can be tested with a call to ValueID::GetType + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \see ValueID::GetType, GetValueAsBitSet, GetValueAsBool, GetValueAsByte, GetValueAsInt, GetValueAsShort, GetValueAsString, GetValueListSelection, GetValueListItems + */ + bool GetValueFloatPrecision(ValueID const& _id, uint8* o_value); + + /** + * \brief Sets the state of a bit in a BitSet ValueID. + * Due to the possibility of a device being asleep, the command is assumed to succeed, and the value + * held by the node is updated directly. This will be reverted by a future status message from the device + * if the Z-Wave message actually failed to get through. Notification callbacks will be sent in both cases. + * \param _id The unique identifier of the BitSet value. + * \param _pos the Position of the Bit you want to Set + * \param _value The new value of the Bitset at the _pos position. + * \return true if the value was set. Returns false if the value is not a ValueID::ValueType_Bool. The type can be tested with a call to ValueID::GetType. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * + */ + bool SetValue(ValueID const& _id, uint8 _pos, bool const _value); + + /** + * \brief Sets the state of a bool. + * Due to the possibility of a device being asleep, the command is assumed to succeed, and the value + * held by the node is updated directly. This will be reverted by a future status message from the device + * if the Z-Wave message actually failed to get through. Notification callbacks will be sent in both cases. + * \param _id The unique identifier of the bool value. + * \param _value The new value of the bool. + * \return true if the value was set. Returns false if the value is not a ValueID::ValueType_Bool. The type can be tested with a call to ValueID::GetType. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * + */ + bool SetValue(ValueID const& _id, bool const _value); + + /** + * \brief Sets the value of a byte. + * Due to the possibility of a device being asleep, the command is assumed to succeed, and the value + * held by the node is updated directly. This will be reverted by a future status message from the device + * if the Z-Wave message actually failed to get through. Notification callbacks will be sent in both cases. + * \param _id The unique identifier of the byte value. + * \param _value The new value of the byte. + * \return true if the value was set. Returns false if the value is not a ValueID::ValueType_Byte. The type can be tested with a call to ValueID::GetType. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + */ + bool SetValue(ValueID const& _id, uint8 const _value); + + /** + * \brief Sets the value of a decimal. + * It is usually better to handle decimal values using strings rather than floats, to avoid floating point accuracy issues. + * Due to the possibility of a device being asleep, the command is assumed to succeed, and the value + * held by the node is updated directly. This will be reverted by a future status message from the device + * if the Z-Wave message actually failed to get through. Notification callbacks will be sent in both cases. + * \param _id The unique identifier of the decimal value. + * \param _value The new value of the decimal. + * \return true if the value was set. Returns false if the value is not a ValueID::ValueType_Decimal. The type can be tested with a call to ValueID::GetType. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + */ + bool SetValue(ValueID const& _id, float const _value); + + /** + * \brief Sets the value of a 32-bit signed integer. + * Due to the possibility of a device being asleep, the command is assumed to succeed, and the value + * held by the node is updated directly. This will be reverted by a future status message from the device + * if the Z-Wave message actually failed to get through. Notification callbacks will be sent in both cases. + * \param _id The unique identifier of the integer value. + * \param _value The new value of the integer. + * \return true if the value was set. Returns false if the value is not a ValueID::ValueType_Int. The type can be tested with a call to ValueID::GetType. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + */ + bool SetValue(ValueID const& _id, int32 const _value); + + /** + * \brief Sets the value of a 16-bit signed integer. + * Due to the possibility of a device being asleep, the command is assumed to succeed, and the value + * held by the node is updated directly. This will be reverted by a future status message from the device + * if the Z-Wave message actually failed to get through. Notification callbacks will be sent in both cases. + * \param _id The unique identifier of the integer value. + * \param _value The new value of the integer. + * \return true if the value was set. Returns false if the value is not a ValueID::ValueType_Short. The type can be tested with a call to ValueID::GetType. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + */ + bool SetValue(ValueID const& _id, int16 const _value); + + /** + * \brief Sets the value of a collection of bytes. + * Due to the possibility of a device being asleep, the command is assumed to succeed, and the value + * held by the node is updated directly. This will be reverted by a future status message from the device + * if the Z-Wave message actually failed to get through. Notification callbacks will be sent in both cases. + * \param _id The unique identifier of the raw value. + * \param _value The new collection of bytes. + * \return true if the value was set. Returns false if the value is not a ValueID::ValueType_Raw. The type can be tested with a call to ValueID::GetType. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + */ + bool SetValue(ValueID const& _id, uint8 const* _value, uint8 const _length); + + /** + * \brief Sets the value from a string, regardless of type. + * Due to the possibility of a device being asleep, the command is assumed to succeed, and the value + * held by the node is updated directly. This will be reverted by a future status message from the device + * if the Z-Wave message actually failed to get through. Notification callbacks will be sent in both cases. + * \param _id The unique identifier of the integer value. + * \param _value The new value of the string. + * \return true if the value was set. Returns false if the value could not be parsed into the correct type for the value. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + */ + bool SetValue(ValueID const& _id, string const& _value); + + /** + * \brief Sets the selected item in a list. + * Due to the possibility of a device being asleep, the command is assumed to succeed, and the value + * held by the node is updated directly. This will be reverted by a future status message from the device + * if the Z-Wave message actually failed to get through. Notification callbacks will be sent in both cases. + * \param _id The unique identifier of the list value. + * \param _selectedItem A string matching the new selected item in the list. + * \return true if the value was set. Returns false if the selection is not in the list, or if the value is not a ValueID::ValueType_List. + * The type can be tested with a call to ValueID::GetType + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + */ + bool SetValueListSelection(ValueID const& _id, string const& _selectedItem); + + /** + * \brief Refreshes the specified value from the Z-Wave network. + * A call to this function causes the library to send a message to the network to retrieve the current value + * of the specified ValueID (just like a poll, except only one-time, not recurring). + * \param _id The unique identifier of the value to be refreshed. + * \return true if the driver and node were found; false otherwise + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + */ + bool RefreshValue(ValueID const& _id); + + /** + * \brief Sets a flag indicating whether value changes noted upon a refresh should be verified. If so, the + * library will immediately refresh the value a second time whenever a change is observed. This helps to filter + * out spurious data reported occasionally by some devices. + * \param _id The unique identifier of the value whose changes should or should not be verified. + * \param _verify if true, verify changes; if false, don't verify changes. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \sa Manager::GetChangeVerified + */ + void SetChangeVerified(ValueID const& _id, bool _verify); + + /** + * \brief determine if value changes upon a refresh should be verified. If so, the + * library will immediately refresh the value a second time whenever a change is observed. This helps to filter + * out spurious data reported occasionally by some devices. + * \param _id The unique identifier of the value whose changes should or should not be verified. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \sa Manager::SetChangeVerified + */ + bool GetChangeVerified(ValueID const& _id); + + /** + * \brief Starts an activity in a device. + * Since buttons are write-only values that do not report a state, no notification callbacks are sent. + * \param _id The unique identifier of the integer value. + * \return true if the activity was started. Returns false if the value is not a ValueID::ValueType_Button. The type can be tested with a call to ValueID::GetType. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + */ + bool PressButton(ValueID const& _id); + + /** + * \brief Stops an activity in a device. + * Since buttons are write-only values that do not report a state, no notification callbacks are sent. + * \param _id The unique identifier of the integer value. + * \return true if the activity was stopped. Returns false if the value is not a ValueID::ValueType_Button. The type can be tested with a call to ValueID::GetType. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + */ + bool ReleaseButton(ValueID const& _id); + + /** + * \brief Sets the Valid BitMask for a BitSet ValueID + * Sets a BitMask of Valid Bits for a BitSet ValueID + * \param _id The unique identifier of the integer value. + * \param _mask The Mask to set + * \return true if the mask was applied. Returns false if the value is not a ValueID::ValueType_BitSet or the Mask was invalid. The type can be tested with a call to ValueID::GetType. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + */ + bool SetBitMask(ValueID const& _id, uint32 _mask); + + /** + * \brief Gets the Valid BitMask for a BitSet ValueID + * Gets a BitMask of Valid Bits for a BitSet ValueID + * \param _id The unique identifier of the integer value. + * \param o_mask The Mask to for the BitSet + * \return true if the mask was retrieved. Returns false if the value is not a ValueID::ValueType_BitSet or the Mask was invalid. The type can be tested with a call to ValueID::GetType. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + */ + bool GetBitMask(ValueID const& _id, int32* o_mask); + + /** + * \brief Gets the size of a BitMask ValueID + * Gets the size of a BitMask ValueID - Either 1, 2 or 4 + * \param _id The unique identifier of the integer value. + * \param o_size The Size of the BitSet + * \return true if the size was retrieved. Returns false if the value is not a ValueID::ValueType_BitSet or the Mask was invalid. The type can be tested with a call to ValueID::GetType. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + */ + bool GetBitSetSize(ValueID const& _id, uint8* o_size); + + /*@}*/ + + //----------------------------------------------------------------------------- + // Climate Control Schedules + //----------------------------------------------------------------------------- + /** \name Climate Control Schedules + * Methods for accessing schedule values. All the methods require a ValueID, which will have been provided + * in the ValueAdded Notification callback when the the value was first discovered by OpenZWave. + *

The ValueType_Schedule is a specialized Value used to simplify access to the switch point schedule + * information held by a setback thermostat that supports the Climate Control Schedule command class. + * Each schedule contains up to nine switch points for a single day, consisting of a time in + * hours and minutes (24 hour clock) and a setback in tenths of a degree Celsius. The setback value can + * range from -128 (-12.8C) to 120 (12.0C). There are two special setback values - 121 is used to set + * Frost Protection mode, and 122 is used to set Energy Saving mode. + *

The switch point methods only modify OpenZWave's copy of the schedule information. Once all changes + * have been made, they are sent to the device by calling SetSchedule. + */ + /*@{*/ + + /** + * \brief Get the number of switch points defined in a schedule. + * \param _id The unique identifier of the schedule value. + * \return the number of switch points defined in this schedule. Returns zero if the value is not a ValueID::ValueType_Schedule. The type can be tested with a call to ValueID::GetType. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + */ + uint8 GetNumSwitchPoints(ValueID const& _id); + + /** + * \brief Set a switch point in the schedule. + * Inserts a new switch point into the schedule, unless a switch point already exists at the specified + * time in which case that switch point is updated with the new setback value instead. + * A maximum of nine switch points can be set in the schedule. + * \param _id The unique identifier of the schedule value. + * \param _hours The hours part of the time when the switch point will trigger. The time is set using + * the 24-hour clock, so this value must be between 0 and 23. + * \param _minutes The minutes part of the time when the switch point will trigger. This value must be + * between 0 and 59. + * \param _setback The setback in tenths of a degree Celsius. The setback value can range from -128 (-12.8C) + * to 120 (12.0C). There are two special setback values - 121 is used to set Frost Protection mode, and + * 122 is used to set Energy Saving mode. + * \return true if successful. Returns false if the value is not a ValueID::ValueType_Schedule. The type can be tested with a call to ValueID::GetType. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \see GetNumSwitchPoints, RemoveSwitchPoint, ClearSwitchPoints + */ + bool SetSwitchPoint(ValueID const& _id, uint8 const _hours, uint8 const _minutes, int8 const _setback); + + /** + * \brief Remove a switch point from the schedule. + * Removes the switch point at the specified time from the schedule. + * \param _id The unique identifier of the schedule value. + * \param _hours The hours part of the time when the switch point will trigger. The time is set using + * the 24-hour clock, so this value must be between 0 and 23. + * \param _minutes The minutes part of the time when the switch point will trigger. This value must be + * between 0 and 59. + * \return true if successful. Returns false if the value is not a ValueID::ValueType_Schedule or if there + * is not switch point with the specified time values. The type can be tested with a call to ValueID::GetType. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \see GetNumSwitchPoints, SetSwitchPoint, ClearSwitchPoints + */ + bool RemoveSwitchPoint(ValueID const& _id, uint8 const _hours, uint8 const _minutes); + + /** + * \brief Clears all switch points from the schedule. + * \param _id The unique identifier of the schedule value. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \see GetNumSwitchPoints, SetSwitchPoint, RemoveSwitchPoint + */ + void ClearSwitchPoints(ValueID const& _id); + + /** + * \brief Gets switch point data from the schedule. + * Retrieves the time and setback values from a switch point in the schedule. + * \param _id The unique identifier of the schedule value. + * \param _idx The index of the switch point, between zero and one less than the value + * returned by GetNumSwitchPoints. + * \param o_hours a pointer to a uint8 that will be filled with the hours part of the switch point data. + * \param o_minutes a pointer to a uint8 that will be filled with the minutes part of the switch point data. + * \param o_setback a pointer to an int8 that will be filled with the setback value. This can range from -128 + * (-12.8C)to 120 (12.0C). There are two special setback values - 121 is used to set Frost Protection mode, and + * 122 is used to set Energy Saving mode. + * \return true if successful. Returns false if the value is not a ValueID::ValueType_Schedule. The type can be tested with a call to ValueID::GetType. + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_VALUEID if the ValueID is invalid + * \throws OZWException with Type OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID if the Actual Value is off a different type + * \throws OZWException with Type OZWException::OZWEXCEPTION_INVALID_HOMEID if the Driver cannot be found + * \see GetNumSwitchPoints + */ + bool GetSwitchPoint(ValueID const& _id, uint8 const _idx, uint8* o_hours, uint8* o_minutes, int8* o_setback); + + /*@}*/ + + //----------------------------------------------------------------------------- + // SwitchAll + //----------------------------------------------------------------------------- + /** \name SwitchAll + * Methods for switching all devices on or off together. The devices must support + * the SwitchAll command class. The command is first broadcast to all nodes, and + * then followed up with individual commands to each node (because broadcasts are + * not routed, the message might not otherwise reach all the nodes). + */ + /*@{*/ + + /** + * \brief Switch all devices on. + * All devices that support the SwitchAll command class will be turned on. + * \deprecated This method has been depreciated. Please use the ValueID interface instead. + */ + DEPRECATED void SwitchAllOn(uint32 const _homeId); + + /** + * \brief Switch all devices off. + * All devices that support the SwitchAll command class will be turned off. + * \deprecated This method has been depreciated. Please use the ValueID interface instead. + */ + DEPRECATED void SwitchAllOff(uint32 const _homeId); + + /*@}*/ + + //----------------------------------------------------------------------------- + // Configuration Parameters + //----------------------------------------------------------------------------- + /** \name Configuration Parameters + * Methods for accessing device configuration parameters. + * Configuration parameters are values that are managed by the Configuration command class. + * The values are device-specific and are not reported by the devices. Information on parameters + * is provided only in the device user manual. + *

An ongoing task for the OpenZWave project is to create XML files describing the available + * parameters for every Z-Wave. See the config folder in the project source code for examples. + */ + /*@{*/ + public: + /** + * \brief Set the value of a configurable parameter in a device. + * Some devices have various parameters that can be configured to control the device behavior. + * These are not reported by the device over the Z-Wave network, but can usually be found in + * the device's user manual. + * This method returns immediately, without waiting for confirmation from the device that the + * change has been made. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to configure. + * \param _param The index of the parameter. + * \param _value The value to which the parameter should be set. + * \param _size Is an optional number of bytes to be sent for the parameter _value. Defaults to 2. + * \return true if the a message setting the value was sent to the device. + * \see RequestConfigParam + */ + bool SetConfigParam(uint32 const _homeId, uint8 const _nodeId, uint8 const _param, int32 _value, uint8 const _size = 2); + + /** + * \brief Request the value of a configurable parameter from a device. + * Some devices have various parameters that can be configured to control the device behavior. + * These are not reported by the device over the Z-Wave network, but can usually be found in + * the device's user manual. + * This method requests the value of a parameter from the device, and then returns immediately, + * without waiting for a response. If the parameter index is valid for this device, and the + * device is awake, the value will eventually be reported via a ValueChanged notification callback. + * The ValueID reported in the callback will have an index set the same as _param and a command class + * set to the same value as returned by a call to Configuration::StaticGetCommandClassId. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to configure. + * \param _param The index of the parameter. + * \see SetConfigParam, ValueID, Notification + */ + void RequestConfigParam(uint32 const _homeId, uint8 const _nodeId, uint8 const _param); + + /** + * \brief Request the values of all known configurable parameters from a device. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node to configure. + * \see SetConfigParam, ValueID, Notification + */ + void RequestAllConfigParams(uint32 const _homeId, uint8 const _nodeId); + /*@}*/ + + //----------------------------------------------------------------------------- + // Groups (wrappers for the Node methods) + //----------------------------------------------------------------------------- + /** \name Groups + * Methods for accessing device association groups. + */ + /*@{*/ + public: + /** + * \brief Gets the number of association groups reported by this node + * In Z-Wave, groups are numbered starting from one. For example, if a call to GetNumGroups returns 4, the _groupIdx + * value to use in calls to GetAssociations, AddAssociation and RemoveAssociation will be a number between 1 and 4. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node whose groups we are interested in. + * \return The number of groups. + * \see GetAssociations, GetMaxAssociations, AddAssociation, RemoveAssociation + */ + uint8 GetNumGroups(uint32 const _homeId, uint8 const _nodeId); + + /** + * \brief Gets the associations for a group. + * Makes a copy of the list of associated nodes in the group, and returns it in an array of uint8's. + * The caller is responsible for freeing the array memory with a call to delete []. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node whose associations we are interested in. + * \param _groupIdx One-based index of the group (because Z-Wave product manuals use one-based group numbering). + * \param o_associations If the number of associations returned is greater than zero, o_associations will be set to point to an array containing the IDs of the associated nodes. + * \return The number of nodes in the associations array. If zero, the array will point to NULL, and does not need to be deleted. + * \see GetNumGroups, AddAssociation, RemoveAssociation, GetMaxAssociations + */ + uint32 GetAssociations(uint32 const _homeId, uint8 const _nodeId, uint8 const _groupIdx, uint8** o_associations); + + /** + * \brief Gets the associations for a group. + * Makes a copy of the list of associated nodes in the group, and returns it in an array of InstanceAssociation's. + * struct InstanceAssociation is defined in Group.h and contains + * a (NodeID, End Point) pair. See SDS13783-11B Z-Wave Transport-Encapsulation Command Class Specification + * chapter 2.3.1 Terminology for the definition of "End Point" and "Multi Channel Encapsulation" + * The caller is responsible for freeing the array memory with a call to delete []. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node whose associations we are interested in. + * \param _groupIdx One-based index of the group (because Z-Wave product manuals use one-based group numbering). + * \param o_associations If the number of associations returned is greater than zero, o_associations will be set to point to an array containing the IDs and instances of the associated nodes. + * \return The number of items in the associations array. If zero, the array will point to NULL, and does not need to be deleted. + * \see GetNumGroups, AddAssociation, RemoveAssociation, GetMaxAssociations + */ + uint32 GetAssociations(uint32 const _homeId, uint8 const _nodeId, uint8 const _groupIdx, InstanceAssociation** o_associations); + + /** + * \brief Gets the maximum number of associations for a group. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node whose associations we are interested in. + * \param _groupIdx one-based index of the group (because Z-Wave product manuals use one-based group numbering). + * \return The maximum number of nodes that can be associated into the group. + * \see GetNumGroups, AddAssociation, RemoveAssociation, GetAssociations + */ + uint8 GetMaxAssociations(uint32 const _homeId, uint8 const _nodeId, uint8 const _groupIdx); + + /** + * \brief Returns true is group supports multi instance. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node whose associations we are interested in. + * \param _groupIdx one-based index of the group (because Z-Wave product manuals use one-based group numbering). + * \return True if group supports multi instance. + * \see GetNumGroups, AddAssociation, RemoveAssociation, GetAssociations, GetMaxAssociations + */ + bool IsMultiInstance(uint32 const _homeId, uint8 const _nodeId, uint8 const _groupIdx); + + /** + * \brief Returns a label for the particular group of a node. + * This label is populated by the device specific configuration files. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node whose associations are to be changed. + * \param _groupIdx One-based index of the group (because Z-Wave product manuals use one-based group numbering). + * \see GetNumGroups, GetAssociations, GetMaxAssociations, AddAssociation + */ + string GetGroupLabel(uint32 const _homeId, uint8 const _nodeId, uint8 const _groupIdx); + + /** + * \brief Adds a node to an association group. + * Due to the possibility of a device being asleep, the command is assumed to succeed, and the association data + * held in this class is updated directly. This will be reverted by a future Association message from the device + * if the Z-Wave message actually failed to get through. Notification callbacks will be sent in both cases. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node whose associations are to be changed. + * \param _groupIdx One-based index of the group (because Z-Wave product manuals use one-based group numbering). + * \param _targetNodeId Identifier for the node that will be added to the association group. + * \param _instance Identifier for the instance that will be added to the association group. + * \see GetNumGroups, GetAssociations, GetMaxAssociations, RemoveAssociation + */ + void AddAssociation(uint32 const _homeId, uint8 const _nodeId, uint8 const _groupIdx, uint8 const _targetNodeId, uint8 const _instance = 0x00); + + /** + * \brief Removes a node from an association group. + * Due to the possibility of a device being asleep, the command is assumed to succeed, and the association data + * held in this class is updated directly. This will be reverted by a future Association message from the device + * if the Z-Wave message actually failed to get through. Notification callbacks will be sent in both cases. + * \param _homeId The Home ID of the Z-Wave controller that manages the node. + * \param _nodeId The ID of the node whose associations are to be changed. + * \param _groupIdx One-based index of the group (because Z-Wave product manuals use one-based group numbering). + * \param _targetNodeId Identifier for the node that will be removed from the association group. + * \param _instance Identifier for the instance that will be removed to the association group. + * \see GetNumGroups, GetAssociations, GetMaxAssociations, AddAssociation + */ + void RemoveAssociation(uint32 const _homeId, uint8 const _nodeId, uint8 const _groupIdx, uint8 const _targetNodeId, uint8 const _instance = 0x00); + + /*@}*/ + + //----------------------------------------------------------------------------- + // Notifications + //----------------------------------------------------------------------------- + /** \name Notifications + * For notification of changes to the Z-Wave network or device values and associations. + */ + /*@{*/ + public: + /** + * \brief Add a notification watcher. + * In OpenZWave, all feedback from the Z-Wave network is sent to the application via callbacks. + * This method allows the application to add a notification callback handler, known as a "watcher" to OpenZWave. + * An application needs only add a single watcher - all notifications will be reported to it. + * \param _watcher pointer to a function that will be called by the notification system. + * \param _context pointer to user defined data that will be passed to the watcher function with each notification. + * \return true if the watcher was successfully added. + * \see RemoveWatcher, Notification + */ + bool AddWatcher(pfnOnNotification_t _watcher, void* _context); + + /** + * \brief Remove a notification watcher. + * \param _watcher pointer to a function that must match that passed to a previous call to AddWatcher + * \param _context pointer to user defined data that must match the one passed in that same previous call to AddWatcher. + * \return true if the watcher was successfully removed. + * \see AddWatcher, Notification + */ + bool RemoveWatcher(pfnOnNotification_t _watcher, void* _context); + /*@}*/ + + private: + void NotifyWatchers(Notification* _notification); // Passes the notifications to all the registered watcher callbacks in turn. + + struct Watcher + { + pfnOnNotification_t m_callback; + void* m_context; + + Watcher(pfnOnNotification_t _callback, void* _context) : + m_callback(_callback), m_context(_context) + { + } + }; + + list m_watchers; // List of all the registered watchers. + list::iterator*> m_watcherIterators; // Iterators currently operating on the list of watchers + Internal::Platform::Mutex* m_notificationMutex; + + //----------------------------------------------------------------------------- + // Controller commands + //----------------------------------------------------------------------------- + /** \name Controller Commands + * Commands for Z-Wave network management using the PC Controller. + */ + /*@{*/ + public: + /** + * \brief Hard Reset a PC Z-Wave Controller. + * Resets a controller and erases its network configuration settings. The controller becomes a primary controller ready to add devices to a new network. + * \param _homeId The Home ID of the Z-Wave controller to be reset. + * \see SoftReset + */ + void ResetController(uint32 const _homeId); + + /** + * \brief Soft Reset a PC Z-Wave Controller. + * Resets a controller without erasing its network configuration settings. + * \param _homeId The Home ID of the Z-Wave controller to be reset. + * \see SoftReset + */ + void SoftReset(uint32 const _homeId); + + /** + * \brief Start a controller command process. + * Most Controller Commands are implemented via Other Manager methods, you should + * only use this method if you need advanced control over a existing Controller Command + * or if a ControllerCommand is not implemented. + * + * \param _homeId The Home ID of the Z-Wave controller. + * \param _command The command to be sent to the controller. + * \param _callback pointer to a function that will be called at various stages during the command process + * to notify the user of progress or to request actions on the user's part. Defaults to NULL. Callbacks are also sent + * via Notification mechanism with type of Notification::Type_ControllerCommand + * \param _context pointer to user defined data that will be passed into to the callback function. Defaults to NULL. + * \param _highPower used only with the AddDevice, AddController, RemoveDevice and RemoveController commands. + * Usually when adding or removing devices, the controller operates at low power so that the controller must + * be physically close to the device for security reasons. If _highPower is true, the controller will + * operate at normal power levels instead. Defaults to false. + * \param _nodeId is the node ID used by the command if necessary. + * \param _arg is an optional argument, usually another node ID, that is used by the command. + * \return true if the command was accepted and has queued to be executed. + * \see CancelControllerCommand, HasNodeFailed, RemoveFailedNode, Driver::ControllerCommand, Driver::pfnControllerCallback_t, + *

Commands + * - Driver::ControllerCommand_AddDevice - Add a new device or controller to the Z-Wave network. + * - Driver::ControllerCommand_CreateNewPrimary - Create a new primary controller when old primary fails. Requires SUC. + * - Driver::ControllerCommand_ReceiveConfiguration - Receive network configuration information from primary controller. Requires secondary. + * - Driver::ControllerCommand_RemoveDevice - Remove a device or controller from the Z-Wave network. + * - Driver::ControllerCommand_RemoveFailedNode - Remove a node from the network. The node must not be responding + * and be on the controller's failed node list. + * - Driver::ControllerCommand_HasNodeFailed - Check whether a node is in the controller's failed nodes list. + * - Driver::ControllerCommand_ReplaceFailedNode - Replace a failed device with another. If the node is not in + * the controller's failed nodes list, or the node responds, this command will fail. + * - Driver:: ControllerCommand_TransferPrimaryRole - Add a new controller to the network and + * make it the primary. The existing primary will become a secondary controller. + * - Driver::ControllerCommand_RequestNetworkUpdate - Update the controller with network information from the SUC/SIS. + * - Driver::ControllerCommand_RequestNodeNeighborUpdate - Get a node to rebuild its neighbour list. This method also does RequestNodeNeighbors afterwards. + * - Driver::ControllerCommand_AssignReturnRoute - Assign a network return route to a device. + * - Driver::ControllerCommand_DeleteAllReturnRoutes - Delete all network return routes from a device. + * - Driver::ControllerCommand_SendNodeInformation - Send a node information frame. + * - Driver::ControllerCommand_ReplicationSend - Send information from primary to secondary + * - Driver::ControllerCommand_CreateButton - Create a handheld button id. + * - Driver::ControllerCommand_DeleteButton - Delete a handheld button id. + *

Callbacks + * - Driver::ControllerState_Starting, the controller command has begun + * - Driver::ControllerState_Waiting, the controller is waiting for a user action. A notice should be displayed + * to the user at this point, telling them what to do next. + * For the add, remove, replace and transfer primary role commands, the user needs to be told to press the + * inclusion button on the device that is going to be added or removed. For ControllerCommand_ReceiveConfiguration, + * they must set their other controller to send its data, and for ControllerCommand_CreateNewPrimary, set the other + * controller to learn new data. + * - Driver::ControllerState_InProgress - the controller is in the process of adding or removing the chosen node. It is now too late to cancel the command. + * - Driver::ControllerState_Complete - the controller has finished adding or removing the node, and the command is complete. + * - Driver::ControllerState_Failed - will be sent if the command fails for any reason. + * \deprecated This method has been depreciated in favour of the methods in the \ref Network_Commands section (Remove in 1.8) + * + * \see AddNode RemoveNode RemoveFailedNode HasNodeFailed RequestNodeNeighborUpdate AssignReturnRoute DeleteAllReturnRoutes SendNodeInformation CreateNewPrimary ReceiveConfiguration ReplaceFailedNode TransferPrimaryRole RequestNetworkUpdate ReplicationSend CreateButton DeleteButton + * + */ + DEPRECATED bool BeginControllerCommand(uint32 const _homeId, Driver::ControllerCommand _command, Driver::pfnControllerCallback_t _callback = NULL, void* _context = NULL, bool _highPower = false, uint8 _nodeId = 0xff, uint8 _arg = 0); + + /** + * \brief Cancels any in-progress command running on a controller. + * \param _homeId The Home ID of the Z-Wave controller. + * \return true if a command was running and was cancelled. + * \see BeginControllerCommand + */ + bool CancelControllerCommand(uint32 const _homeId); + /*@}*/ + + //----------------------------------------------------------------------------- + // Network commands + //----------------------------------------------------------------------------- + /** \name Network Commands + * Commands for Z-Wave network for testing, routing and other internal + * operations. + */ + /*@{*/ + public: + /** + * \brief Test network node. + * Sends a series of messages to a network node for testing network reliability. + * \param _homeId The Home ID of the Z-Wave controller to be reset. + * \param _count This is the number of test messages to send. + * \see TestNetwork + */ + void TestNetworkNode(uint32 const _homeId, uint8 const _nodeId, uint32 const _count); + + /** + * \brief Test network. + * Sends a series of messages to every node on the network for testing network reliability. + * \param _homeId The Home ID of the Z-Wave controller to be reset. + * \param _count This is the number of test messages to send. + * \see TestNetwork + */ + void TestNetwork(uint32 const _homeId, uint32 const _count); + + /** + * \brief Heal network node by requesting the node rediscover their neighbors. + * Sends a ControllerCommand_RequestNodeNeighborUpdate to the node. + * \param _homeId The Home ID of the Z-Wave network to be healed. + * \param _nodeId The node to heal. + * \param _doRR Whether to perform return routes initialization. + */ + void HealNetworkNode(uint32 const _homeId, uint8 const _nodeId, bool _doRR); + + /** + * \brief Heal network by requesting node's rediscover their neighbors. + * Sends a ControllerCommand_RequestNodeNeighborUpdate to every node. + * Can take a while on larger networks. + * \param _homeId The Home ID of the Z-Wave network to be healed. + * \param _doRR Whether to perform return routes initialization. + */ + void HealNetwork(uint32 const _homeId, bool _doRR); + + /** + * \brief Start the Inclusion Process to add a Node to the Network. + * The Status of the Node Inclusion is communicated via Notifications. Specifically, you should + * monitor ControllerCommand Notifications. + * + * Results of the AddNode Command will be send as a Notification with the Notification type as + * Notification::Type_ControllerCommand + * + * \param _homeId The Home ID of the Z-Wave network where the device should be added. + * \param _doSecurity Whether to initialize the Network Key on the device if it supports the Security CC + * \return if the Command was sent successfully to the Controller + * \sa CancelControllerCommand + */ + bool AddNode(uint32 const _homeId, bool _doSecurity = true); + + /** + * \brief Remove a Device from the Z-Wave Network + * The Status of the Node Removal is communicated via Notifications. Specifically, you should + * monitor ControllerCommand Notifications. + * + * Results of the RemoveNode Command will be send as a Notification with the Notification type as + * Notification::Type_ControllerCommand + * + * \param _homeId The HomeID of the Z-Wave network where you want to remove the device + * \return if the Command was send successfully to the Controller + * \sa CancelControllerCommand + */ + bool RemoveNode(uint32 const _homeId); + + /** + * \brief Remove a Failed Device from the Z-Wave Network + * This Command will remove a failed node from the network. The Node should be on the Controllers Failed + * Node List, otherwise this command will fail. You can use the HasNodeFailed function below to test if the Controller + * believes the Node has Failed. + * The Status of the Node Removal is communicated via Notifications. Specifically, you should + * monitor ControllerCommand Notifications. + * + * Results of the RemoveFailedNode Command will be send as a Notification with the Notification type as + * Notification::Type_ControllerCommand + * + * \param _homeId The HomeID of the Z-Wave network where you want to remove the device + * \param _nodeId The NodeID of the Failed Node. + * \return if the Command was send successfully to the Controller + * \sa CancelControllerCommand + */ + bool RemoveFailedNode(uint32 const _homeId, uint8 const _nodeId); + + /** + * \brief Check if the Controller Believes a Node has Failed. + * This is different from the IsNodeFailed call in that we test the Controllers Failed Node List, whereas the IsNodeFailed is testing + * our list of Failed Nodes, which might be different. + * The Results will be communicated via Notifications. Specifically, you should monitor the ControllerCommand notifications + * + * Results of the HasNodeFailed Command will be send as a Notification with the Notification type as + * Notification::Type_ControllerCommand + * + * \param _homeId The HomeID of the Z-Wave network where you want to test the device + * \param _nodeId The NodeID of the Failed Node. + * \return if the RemoveDevice Command was send successfully to the Controller + * \sa CancelControllerCommand + */ + bool HasNodeFailed(uint32 const _homeId, uint8 const _nodeId); + + /** + * \brief Ask a Node to update its Neighbor Tables + * This command will ask a Node to update its Neighbor Tables. + * + * Results of the RequestNodeNeighborUpdate Command will be send as a Notification with the Notification type as + * Notification::Type_ControllerCommand + * + * \param _homeId The HomeID of the Z-Wave network where you want to update the device + * \param _nodeId The NodeID of the Node. + * \return if the Command was send successfully to the Controller + * \sa CancelControllerCommand + */ + bool RequestNodeNeighborUpdate(uint32 const _homeId, uint8 const _nodeId); + + /** + * \brief Ask a Node to update its update its Return Route to the Controller + * This command will ask a Node to update its Return Route to the Controller + * + * Results of the AssignReturnRoute Command will be send as a Notification with the Notification type as + * Notification::Type_ControllerCommand + * + * \param _homeId The HomeID of the Z-Wave network where you want to update the device + * \param _nodeId The NodeID of the Node. + * \return if the Command was send successfully to the Controller + * \sa CancelControllerCommand + */ + bool AssignReturnRoute(uint32 const _homeId, uint8 const _nodeId); + + /** + * \brief Ask a Node to delete all Return Route. + * This command will ask a Node to delete all its return routes, and will rediscover when needed. + * + * Results of the DeleteAllReturnRoutes Command will be send as a Notification with the Notification type as + * Notification::Type_ControllerCommand + * + * \param _homeId The HomeID of the Z-Wave network where you want to update the device + * \param _nodeId The NodeID of the Node. + * \return if the Command was send successfully to the Controller + * \sa CancelControllerCommand + */ + bool DeleteAllReturnRoutes(uint32 const _homeId, uint8 const _nodeId); + + /** + * \brief Send a NIF frame from the Controller to a Node. + * This command send a NIF frame from the Controller to a Node + * + * \param _homeId The HomeID of the Z-Wave network + * \param _nodeId The NodeID of the Node to receive the NIF + * \return if the sendNIF Command was send successfully to the Controller + * \sa CancelControllerCommand + */ + bool SendNodeInformation(uint32 const _homeId, uint8 const _nodeId); - //----------------------------------------------------------------------------- - // Notifications - //----------------------------------------------------------------------------- - /** \name Notifications - * For notification of changes to the Z-Wave network or device values and associations. - */ - /*@{*/ - public: - /** - * \brief Add a notification watcher. - * In OpenZWave, all feedback from the Z-Wave network is sent to the application via callbacks. - * This method allows the application to add a notification callback handler, known as a "watcher" to OpenZWave. - * An application needs only add a single watcher - all notifications will be reported to it. - * \param _watcher pointer to a function that will be called by the notification system. - * \param _context pointer to user defined data that will be passed to the watcher function with each notification. - * \return true if the watcher was successfully added. - * \see RemoveWatcher, Notification - */ - bool AddWatcher( pfnOnNotification_t _watcher, void* _context ); - - /** - * \brief Remove a notification watcher. - * \param _watcher pointer to a function that must match that passed to a previous call to AddWatcher - * \param _context pointer to user defined data that must match the one passed in that same previous call to AddWatcher. - * \return true if the watcher was successfully removed. - * \see AddWatcher, Notification - */ - bool RemoveWatcher( pfnOnNotification_t _watcher, void* _context ); - /*@}*/ + /** + * \brief Create a new primary controller when old primary fails. Requires SUC. + * This command Creates a new Primary Controller when the Old Primary has Failed. Requires a SUC on the network to function + * + * Results of the CreateNewPrimary Command will be send as a Notification with the Notification type as + * Notification::Type_ControllerCommand + * + * \param _homeId The HomeID of the Z-Wave network + * \return if the CreateNewPrimary Command was send successfully to the Controller + * \sa CancelControllerCommand + */ + bool CreateNewPrimary(uint32 const _homeId); - private: - void NotifyWatchers( Notification* _notification ); // Passes the notifications to all the registered watcher callbacks in turn. + /** + * \brief Receive network configuration information from primary controller. Requires secondary. + * This command prepares the controller to receive Network Configuration from a Secondary Controller. + * + * Results of the ReceiveConfiguration Command will be send as a Notification with the Notification type as + * Notification::Type_ControllerCommand + * + * \param _homeId The HomeID of the Z-Wave network + * \return if the ReceiveConfiguration Command was send successfully to the Controller + * \sa CancelControllerCommand + */ + bool ReceiveConfiguration(uint32 const _homeId); - struct Watcher - { - pfnOnNotification_t m_callback; - void* m_context; - - Watcher - ( - pfnOnNotification_t _callback, - void* _context - ): - m_callback( _callback ), - m_context( _context ) - { - } - }; - -OPENZWAVE_EXPORT_WARNINGS_OFF - list m_watchers; // List of all the registered watchers. - list::iterator*> m_watcherIterators; // Iterators currently operating on the list of watchers -OPENZWAVE_EXPORT_WARNINGS_ON - Mutex* m_notificationMutex; - - //----------------------------------------------------------------------------- - // Controller commands - //----------------------------------------------------------------------------- - /** \name Controller Commands - * Commands for Z-Wave network management using the PC Controller. - */ - /*@{*/ - public: - /** - * \brief Hard Reset a PC Z-Wave Controller. - * Resets a controller and erases its network configuration settings. The controller becomes a primary controller ready to add devices to a new network. - * \param _homeId The Home ID of the Z-Wave controller to be reset. - * \see SoftReset - */ - void ResetController( uint32 const _homeId ); + /** + * \brief Replace a failed device with another. + * If the node is not in the controller's failed nodes list, or the node responds, this command will fail. + * You can check if a Node is in the Controllers Failed node list by using the HasNodeFailed method + * + * Results of the ReplaceFailedNode Command will be send as a Notification with the Notification type as + * Notification::Type_ControllerCommand + * + * \param _homeId The HomeID of the Z-Wave network + * \param _nodeId the ID of the Failed Node + * \return if the ReplaceFailedNode Command was send successfully to the Controller + * \sa HasNodeFailed + * \sa CancelControllerCommand + */ + bool ReplaceFailedNode(uint32 const _homeId, uint8 const _nodeId); - /** - * \brief Soft Reset a PC Z-Wave Controller. - * Resets a controller without erasing its network configuration settings. - * \param _homeId The Home ID of the Z-Wave controller to be reset. - * \see SoftReset - */ - void SoftReset( uint32 const _homeId ); - - /** - * \brief Start a controller command process. - * Most Controller Commands are implemented via Other Manager methods, you should - * only use this method if you need advanced control over a existing Controller Command - * or if a ControllerCommand is not implemented. - * - * \param _homeId The Home ID of the Z-Wave controller. - * \param _command The command to be sent to the controller. - * \param _callback pointer to a function that will be called at various stages during the command process - * to notify the user of progress or to request actions on the user's part. Defaults to NULL. Callbacks are also sent - * via Notification mechanism with type of Notification::Type_ControllerCommand - * \param _context pointer to user defined data that will be passed into to the callback function. Defaults to NULL. - * \param _highPower used only with the AddDevice, AddController, RemoveDevice and RemoveController commands. - * Usually when adding or removing devices, the controller operates at low power so that the controller must - * be physically close to the device for security reasons. If _highPower is true, the controller will - * operate at normal power levels instead. Defaults to false. - * \param _nodeId is the node ID used by the command if necessary. - * \param _arg is an optional argument, usually another node ID, that is used by the command. - * \return true if the command was accepted and has queued to be executed. - * \see CancelControllerCommand, HasNodeFailed, RemoveFailedNode, Driver::ControllerCommand, Driver::pfnControllerCallback_t, - *

Commands - * - Driver::ControllerCommand_AddDevice - Add a new device or controller to the Z-Wave network. - * - Driver::ControllerCommand_CreateNewPrimary - Create a new primary controller when old primary fails. Requires SUC. - * - Driver::ControllerCommand_ReceiveConfiguration - Receive network configuration information from primary controller. Requires secondary. - * - Driver::ControllerCommand_RemoveDevice - Remove a device or controller from the Z-Wave network. - * - Driver::ControllerCommand_RemoveFailedNode - Remove a node from the network. The node must not be responding - * and be on the controller's failed node list. - * - Driver::ControllerCommand_HasNodeFailed - Check whether a node is in the controller's failed nodes list. - * - Driver::ControllerCommand_ReplaceFailedNode - Replace a failed device with another. If the node is not in - * the controller's failed nodes list, or the node responds, this command will fail. - * - Driver:: ControllerCommand_TransferPrimaryRole - Add a new controller to the network and - * make it the primary. The existing primary will become a secondary controller. - * - Driver::ControllerCommand_RequestNetworkUpdate - Update the controller with network information from the SUC/SIS. - * - Driver::ControllerCommand_RequestNodeNeighborUpdate - Get a node to rebuild its neighbour list. This method also does RequestNodeNeighbors afterwards. - * - Driver::ControllerCommand_AssignReturnRoute - Assign a network return route to a device. - * - Driver::ControllerCommand_DeleteAllReturnRoutes - Delete all network return routes from a device. - * - Driver::ControllerCommand_SendNodeInformation - Send a node information frame. - * - Driver::ControllerCommand_ReplicationSend - Send information from primary to secondary - * - Driver::ControllerCommand_CreateButton - Create a handheld button id. - * - Driver::ControllerCommand_DeleteButton - Delete a handheld button id. - *

Callbacks - * - Driver::ControllerState_Starting, the controller command has begun - * - Driver::ControllerState_Waiting, the controller is waiting for a user action. A notice should be displayed - * to the user at this point, telling them what to do next. - * For the add, remove, replace and transfer primary role commands, the user needs to be told to press the - * inclusion button on the device that is going to be added or removed. For ControllerCommand_ReceiveConfiguration, - * they must set their other controller to send its data, and for ControllerCommand_CreateNewPrimary, set the other - * controller to learn new data. - * - Driver::ControllerState_InProgress - the controller is in the process of adding or removing the chosen node. It is now too late to cancel the command. - * - Driver::ControllerState_Complete - the controller has finished adding or removing the node, and the command is complete. - * - Driver::ControllerState_Failed - will be sent if the command fails for any reason. - * \deprecated This method has been depreciated in favour of the methods in the \ref Network_Commands section (Remove in 1.8) - * - * \see AddNode RemoveNode RemoveFailedNode HasNodeFailed RequestNodeNeighborUpdate AssignReturnRoute DeleteAllReturnRoutes SendNodeInformation CreateNewPrimary ReceiveConfiguration ReplaceFailedNode TransferPrimaryRole RequestNetworkUpdate ReplicationSend CreateButton DeleteButton - * - */ - DEPRECATED bool BeginControllerCommand( uint32 const _homeId, Driver::ControllerCommand _command, Driver::pfnControllerCallback_t _callback = NULL, void* _context = NULL, bool _highPower = false, uint8 _nodeId = 0xff, uint8 _arg = 0 ); + /** + * \brief Add a new controller to the network and make it the primary. + * The existing primary will become a secondary controller. + * + * Results of the TransferPrimaryRole Command will be send as a Notification with the Notification type as + * Notification::Type_ControllerCommand + * + * \param _homeId The HomeID of the Z-Wave network + * \return if the TransferPrimaryRole Command was send successfully to the Controller + * \sa CancelControllerCommand + */ + bool TransferPrimaryRole(uint32 const _homeId); - /** - * \brief Cancels any in-progress command running on a controller. - * \param _homeId The Home ID of the Z-Wave controller. - * \return true if a command was running and was cancelled. - * \see BeginControllerCommand - */ - bool CancelControllerCommand( uint32 const _homeId ); - /*@}*/ - - //----------------------------------------------------------------------------- - // Network commands - //----------------------------------------------------------------------------- - /** \name Network Commands - * Commands for Z-Wave network for testing, routing and other internal - * operations. - */ - /*@{*/ - public: - /** - * \brief Test network node. - * Sends a series of messages to a network node for testing network reliability. - * \param _homeId The Home ID of the Z-Wave controller to be reset. - * \param _count This is the number of test messages to send. - * \see TestNetwork - */ - void TestNetworkNode( uint32 const _homeId, uint8 const _nodeId, uint32 const _count ); - - /** - * \brief Test network. - * Sends a series of messages to every node on the network for testing network reliability. - * \param _homeId The Home ID of the Z-Wave controller to be reset. - * \param _count This is the number of test messages to send. - * \see TestNetwork - */ - void TestNetwork( uint32 const _homeId, uint32 const _count ); - - /** - * \brief Heal network node by requesting the node rediscover their neighbors. - * Sends a ControllerCommand_RequestNodeNeighborUpdate to the node. - * \param _homeId The Home ID of the Z-Wave network to be healed. - * \param _nodeId The node to heal. - * \param _doRR Whether to perform return routes initialization. - */ - void HealNetworkNode( uint32 const _homeId, uint8 const _nodeId, bool _doRR ); - - /** - * \brief Heal network by requesting node's rediscover their neighbors. - * Sends a ControllerCommand_RequestNodeNeighborUpdate to every node. - * Can take a while on larger networks. - * \param _homeId The Home ID of the Z-Wave network to be healed. - * \param _doRR Whether to perform return routes initialization. - */ - void HealNetwork( uint32 const _homeId, bool _doRR ); - - /** - * \brief Start the Inclusion Process to add a Node to the Network. - * The Status of the Node Inclusion is communicated via Notifications. Specifically, you should - * monitor ControllerCommand Notifications. - * - * Results of the AddNode Command will be send as a Notification with the Notification type as - * Notification::Type_ControllerCommand - * - * \param _homeId The Home ID of the Z-Wave network where the device should be added. - * \param _doSecurity Whether to initialize the Network Key on the device if it supports the Security CC - * \return if the Command was sent successfully to the Controller - * \sa CancelControllerCommand - */ - bool AddNode( uint32 const _homeId, bool _doSecurity = true ); - - /** - * \brief Remove a Device from the Z-Wave Network - * The Status of the Node Removal is communicated via Notifications. Specifically, you should - * monitor ControllerCommand Notifications. - * - * Results of the RemoveNode Command will be send as a Notification with the Notification type as - * Notification::Type_ControllerCommand - * - * \param _homeId The HomeID of the Z-Wave network where you want to remove the device - * \return if the Command was send successfully to the Controller - * \sa CancelControllerCommand - */ - bool RemoveNode(uint32 const _homeId); - - /** - * \brief Remove a Failed Device from the Z-Wave Network - * This Command will remove a failed node from the network. The Node should be on the Controllers Failed - * Node List, otherwise this command will fail. You can use the HasNodeFailed function below to test if the Controller - * believes the Node has Failed. - * The Status of the Node Removal is communicated via Notifications. Specifically, you should - * monitor ControllerCommand Notifications. - * - * Results of the RemoveFailedNode Command will be send as a Notification with the Notification type as - * Notification::Type_ControllerCommand - * - * \param _homeId The HomeID of the Z-Wave network where you want to remove the device - * \param _nodeId The NodeID of the Failed Node. - * \return if the Command was send successfully to the Controller - * \sa CancelControllerCommand - */ - bool RemoveFailedNode(uint32 const _homeId, uint8 const _nodeId); - - /** - * \brief Check if the Controller Believes a Node has Failed. - * This is different from the IsNodeFailed call in that we test the Controllers Failed Node List, whereas the IsNodeFailed is testing - * our list of Failed Nodes, which might be different. - * The Results will be communicated via Notifications. Specifically, you should monitor the ControllerCommand notifications - * - * Results of the HasNodeFailed Command will be send as a Notification with the Notification type as - * Notification::Type_ControllerCommand - * - * \param _homeId The HomeID of the Z-Wave network where you want to test the device - * \param _nodeId The NodeID of the Failed Node. - * \return if the RemoveDevice Command was send successfully to the Controller - * \sa CancelControllerCommand - */ - bool HasNodeFailed(uint32 const _homeId, uint8 const _nodeId); - - /** - * \brief Ask a Node to update its Neighbor Tables - * This command will ask a Node to update its Neighbor Tables. - * - * Results of the RequestNodeNeighborUpdate Command will be send as a Notification with the Notification type as - * Notification::Type_ControllerCommand - * - * \param _homeId The HomeID of the Z-Wave network where you want to update the device - * \param _nodeId The NodeID of the Node. - * \return if the Command was send successfully to the Controller - * \sa CancelControllerCommand - */ - bool RequestNodeNeighborUpdate(uint32 const _homeId, uint8 const _nodeId); - - /** - * \brief Ask a Node to update its update its Return Route to the Controller - * This command will ask a Node to update its Return Route to the Controller - * - * Results of the AssignReturnRoute Command will be send as a Notification with the Notification type as - * Notification::Type_ControllerCommand - * - * \param _homeId The HomeID of the Z-Wave network where you want to update the device - * \param _nodeId The NodeID of the Node. - * \return if the Command was send successfully to the Controller - * \sa CancelControllerCommand - */ - bool AssignReturnRoute(uint32 const _homeId, uint8 const _nodeId); - - /** - * \brief Ask a Node to delete all Return Route. - * This command will ask a Node to delete all its return routes, and will rediscover when needed. - * - * Results of the DeleteAllReturnRoutes Command will be send as a Notification with the Notification type as - * Notification::Type_ControllerCommand - * - * \param _homeId The HomeID of the Z-Wave network where you want to update the device - * \param _nodeId The NodeID of the Node. - * \return if the Command was send successfully to the Controller - * \sa CancelControllerCommand - */ - bool DeleteAllReturnRoutes(uint32 const _homeId, uint8 const _nodeId); - - /** - * \brief Send a NIF frame from the Controller to a Node. - * This command send a NIF frame from the Controller to a Node - * - * \param _homeId The HomeID of the Z-Wave network - * \param _nodeId The NodeID of the Node to receive the NIF - * \return if the sendNIF Command was send successfully to the Controller - * \sa CancelControllerCommand - */ - bool SendNodeInformation(uint32 const _homeId, uint8 const _nodeId); - - /** - * \brief Create a new primary controller when old primary fails. Requires SUC. - * This command Creates a new Primary Controller when the Old Primary has Failed. Requires a SUC on the network to function - * - * Results of the CreateNewPrimary Command will be send as a Notification with the Notification type as - * Notification::Type_ControllerCommand - * - * \param _homeId The HomeID of the Z-Wave network - * \return if the CreateNewPrimary Command was send successfully to the Controller - * \sa CancelControllerCommand - */ - bool CreateNewPrimary(uint32 const _homeId); - - /** - * \brief Receive network configuration information from primary controller. Requires secondary. - * This command prepares the controller to receive Network Configuration from a Secondary Controller. - * - * Results of the ReceiveConfiguration Command will be send as a Notification with the Notification type as - * Notification::Type_ControllerCommand - * - * \param _homeId The HomeID of the Z-Wave network - * \return if the ReceiveConfiguration Command was send successfully to the Controller - * \sa CancelControllerCommand - */ - bool ReceiveConfiguration (uint32 const _homeId); - - /** - * \brief Replace a failed device with another. - * If the node is not in the controller's failed nodes list, or the node responds, this command will fail. - * You can check if a Node is in the Controllers Failed node list by using the HasNodeFailed method - * - * Results of the ReplaceFailedNode Command will be send as a Notification with the Notification type as - * Notification::Type_ControllerCommand - * - * \param _homeId The HomeID of the Z-Wave network - * \param _nodeId the ID of the Failed Node - * \return if the ReplaceFailedNode Command was send successfully to the Controller - * \sa HasNodeFailed - * \sa CancelControllerCommand - */ - bool ReplaceFailedNode(uint32 const _homeId, uint8 const _nodeId); - - /** - * \brief Add a new controller to the network and make it the primary. - * The existing primary will become a secondary controller. - * - * Results of the TransferPrimaryRole Command will be send as a Notification with the Notification type as - * Notification::Type_ControllerCommand - * - * \param _homeId The HomeID of the Z-Wave network - * \return if the TransferPrimaryRole Command was send successfully to the Controller - * \sa CancelControllerCommand - */ - bool TransferPrimaryRole(uint32 const _homeId); - - /** - * \brief Update the controller with network information from the SUC/SIS. - * - * Results of the RequestNetworkUpdate Command will be send as a Notification with the Notification type as - * Notification::Type_ControllerCommand - * - * \param _homeId The HomeID of the Z-Wave network - * \param _nodeId the ID of the Node - * \return if the RequestNetworkUpdate Command was send successfully to the Controller - * \sa CancelControllerCommand - */ - bool RequestNetworkUpdate(uint32 const _homeId, uint8 const _nodeId); - - /** - * \brief Send information from primary to secondary - * - * Results of the ReplicationSend Command will be send as a Notification with the Notification type as - * Notification::Type_ControllerCommand - * - * \param _homeId The HomeID of the Z-Wave network - * \param _nodeId the ID of the Node - * \return if the ReplicationSend Command was send successfully to the Controller - * \sa CancelControllerCommand - */ - bool ReplicationSend(uint32 const _homeId, uint8 const _nodeId); - - /** - * \brief Create a handheld button id. - * - * Only intended for Bridge Firmware Controllers. - * - * Results of the CreateButton Command will be send as a Notification with the Notification type as - * Notification::Type_ControllerCommand - * - * \param _homeId The HomeID of the Z-Wave network - * \param _nodeId the ID of the Virtual Node - * \param _buttonId the ID of the Button to create - * \return if the CreateButton Command was send successfully to the Controller - * \sa CancelControllerCommand - */ - bool CreateButton(uint32 const _homeId, uint8 const _nodeId, uint8 const _buttonid); - - /** - * \brief Delete a handheld button id. - * - * Only intended for Bridge Firmware Controllers. - * - * Results of the DeleteButton Command will be send as a Notification with the Notification type as - * Notification::Type_ControllerCommand - * - * \param _homeId The HomeID of the Z-Wave network - * \param _nodeId the ID of the Virtual Node - * \param _buttonId the ID of the Button to delete - * \return if the DeleteButton Command was send successfully to the Controller - * \sa CancelControllerCommand - */ - bool DeleteButton(uint32 const _homeId, uint8 const _nodeId, uint8 const _buttonid); - - /** - * \brief Send a raw packet to a node. - * - * Send a Raw Packet to a Node. No confirmation that the node accepted the packet etc will be available. - * This is for testing only and should not be used for anything production - * - * \param _homeId the HomeID of the Z-Wave Network - * \param _nodeId the ID of the Node - * \param _logText Text to Log when sending the packet - * \param _msgType The Type of Message to Send - * \param _sendSecure if we should attempt to encrypt the packet - * \param _content A array of bytes to send - * \param _length the length of the array - */ - void SendRawData(uint32 const _homeId, uint8 const _nodeId, string const& _logText, uint8 const _msgType, const bool _sendSecure, uint8 const* _content, uint8 const _length); - - - - - /*@}*/ - - //----------------------------------------------------------------------------- - // Scene commands - //----------------------------------------------------------------------------- - /** \name Scene Commands - * Commands for Z-Wave scene interface. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * - */ - /*@{*/ - public: - /** - * \brief Gets the number of scenes that have been defined. - * \return The number of scenes. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetAllScenes, RemoveAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED uint8 GetNumScenes( ); - - /** - * \brief Gets a list of all the SceneIds. - * \param _sceneIds is a pointer to an array of integers. - * \return The number of scenes. If zero, _sceneIds will be NULL and doesn't need to be freed. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED uint8 GetAllScenes( uint8** _sceneIds ); + /** + * \brief Update the controller with network information from the SUC/SIS. + * + * Results of the RequestNetworkUpdate Command will be send as a Notification with the Notification type as + * Notification::Type_ControllerCommand + * + * \param _homeId The HomeID of the Z-Wave network + * \param _nodeId the ID of the Node + * \return if the RequestNetworkUpdate Command was send successfully to the Controller + * \sa CancelControllerCommand + */ + bool RequestNetworkUpdate(uint32 const _homeId, uint8 const _nodeId); - /** - * \brief Remove all the SceneIds. - * \param _homeId The Home ID of the Z-Wave controller. 0 for all devices from all scenes. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetAllScenes, GetNumScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED void RemoveAllScenes( uint32 const _homeId ); + /** + * \brief Send information from primary to secondary + * + * Results of the ReplicationSend Command will be send as a Notification with the Notification type as + * Notification::Type_ControllerCommand + * + * \param _homeId The HomeID of the Z-Wave network + * \param _nodeId the ID of the Node + * \return if the ReplicationSend Command was send successfully to the Controller + * \sa CancelControllerCommand + */ + bool ReplicationSend(uint32 const _homeId, uint8 const _nodeId); - /** - * \brief Create a new Scene passing in Scene ID - * \return uint8 Scene ID used to reference the scene. 0 is failure result. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + /** + * \brief Create a handheld button id. + * + * Only intended for Bridge Firmware Controllers. + * + * Results of the CreateButton Command will be send as a Notification with the Notification type as + * Notification::Type_ControllerCommand + * + * \param _homeId The HomeID of the Z-Wave network + * \param _nodeId the ID of the Virtual Node + * \param _buttonId the ID of the Button to create + * \return if the CreateButton Command was send successfully to the Controller + * \sa CancelControllerCommand + */ + bool CreateButton(uint32 const _homeId, uint8 const _nodeId, uint8 const _buttonid); - */ - DEPRECATED uint8 CreateScene(); - - /** - * \brief Remove an existing Scene. - * \param _sceneId is an integer representing the unique Scene ID to be removed. - * \return true if scene was removed. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED bool RemoveScene( uint8 const _sceneId ); - - /** - * \brief Add a bool Value ID to an existing scene. - * \param _sceneId is an integer representing the unique Scene ID. - * \param _valueId is the Value ID to be added. - * \param _value is the bool value to be saved. - * \return true if Value ID was added. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED bool AddSceneValue( uint8 const _sceneId, ValueID const& _valueId, bool const _value ); - - /** - * \brief Add a byte Value ID to an existing scene. - * \param _sceneId is an integer representing the unique Scene ID. - * \param _valueId is the Value ID to be added. - * \param _value is the byte value to be saved. - * \return true if Value ID was added. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED bool AddSceneValue( uint8 const _sceneId, ValueID const& _valueId, uint8 const _value ); - - /** - * \brief Add a decimal Value ID to an existing scene. - * \param _sceneId is an integer representing the unique Scene ID. - * \param _valueId is the Value ID to be added. - * \param _value is the float value to be saved. - * \return true if Value ID was added. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED bool AddSceneValue( uint8 const _sceneId, ValueID const& _valueId, float const _value ); - - /** - * \brief Add a 32-bit signed integer Value ID to an existing scene. - * \param _sceneId is an integer representing the unique Scene ID. - * \param _valueId is the Value ID to be added. - * \param _value is the int32 value to be saved. - * \return true if Value ID was added. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED bool AddSceneValue( uint8 const _sceneId, ValueID const& _valueId, int32 const _value ); - - /** - * \brief Add a 16-bit signed integer Value ID to an existing scene. - * \param _sceneId is an integer representing the unique Scene ID. - * \param _valueId is the Value ID to be added. - * \param _value is the int16 value to be saved. - * \return true if Value ID was added. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED bool AddSceneValue( uint8 const _sceneId, ValueID const& _valueId, int16 const _value ); - - /** - * \brief Add a string Value ID to an existing scene. - * \param _sceneId is an integer representing the unique Scene ID. - * \param _valueId is the Value ID to be added. - * \param _value is the string value to be saved. - * \return true if Value ID was added. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED bool AddSceneValue( uint8 const _sceneId, ValueID const& _valueId, string const& _value ); - - /** - * \brief Add the selected item list Value ID to an existing scene (as a string). - * \param _sceneId is an integer representing the unique Scene ID. - * \param _valueId is the Value ID to be added. - * \param _value is the string value to be saved. - * \return true if Value ID was added. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED bool AddSceneValueListSelection( uint8 const _sceneId, ValueID const& _valueId, string const& _value ); - - /** - * \brief Add the selected item list Value ID to an existing scene (as a integer). - * \param _sceneId is an integer representing the unique Scene ID. - * \param _valueId is the Value ID to be added. - * \param _value is the integer value to be saved. - * \return true if Value ID was added. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED bool AddSceneValueListSelection( uint8 const _sceneId, ValueID const& _valueId, int32 const _value ); - - /** - * \brief Remove the Value ID from an existing scene. - * \param _sceneId is an integer representing the unique Scene ID. - * \param _valueId is the Value ID to be removed. - * \return true if Value ID was removed. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED bool RemoveSceneValue( uint8 const _sceneId, ValueID const& _valueId ); - - /** - * \brief Retrieves the scene's list of values. - * \param _sceneId The Scene ID of the scene to retrieve the value from. - * \param o_value Pointer to an array of ValueIDs if return is non-zero. - * \return The number of nodes in the o_value array. If zero, the array will point to NULL and does not need to be deleted. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED int SceneGetValues( uint8 const _sceneId, vector* o_value ); - - /** - * \brief Retrieves a scene's value as a bool. - * \param _sceneId The Scene ID of the scene to retrieve the value from. - * \param _valueId The Value ID of the value to retrieve. - * \param o_value Pointer to a bool that will be filled with the returned value. - * \return true if the value was obtained. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED bool SceneGetValueAsBool( uint8 const _sceneId, ValueID const& _valueId, bool* o_value ); - - /** - * \brief Retrieves a scene's value as an 8-bit unsigned integer. - * \param _sceneId The Scene ID of the scene to retrieve the value from. - * \param _valueId The Value ID of the value to retrieve. - * \param o_value Pointer to a uint8 that will be filled with the returned value. - * \return true if the value was obtained. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED bool SceneGetValueAsByte( uint8 const _sceneId, ValueID const& _valueId, uint8* o_value ); - - /** - * \brief Retrieves a scene's value as a float. - * \param _sceneId The Scene ID of the scene to retrieve the value from. - * \param _valueId The Value ID of the value to retrieve. - * \param o_value Pointer to a float that will be filled with the returned value. - * \return true if the value was obtained. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED bool SceneGetValueAsFloat( uint8 const _sceneId, ValueID const& _valueId, float* o_value ); - - /** - * \brief Retrieves a scene's value as a 32-bit signed integer. - * \param _sceneId The Scene ID of the scene to retrieve the value from. - * \param _valueId The Value ID of the value to retrieve. - * \param o_value Pointer to a int32 that will be filled with the returned value. - * \return true if the value was obtained. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED bool SceneGetValueAsInt( uint8 const _sceneId, ValueID const& _valueId, int32* o_value ); - - /** - * \brief Retrieves a scene's value as a 16-bit signed integer. - * \param _sceneId The Scene ID of the scene to retrieve the value from. - * \param _valueId The Value ID of the value to retrieve. - * \param o_value Pointer to a int16 that will be filled with the returned value. - * \return true if the value was obtained. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED bool SceneGetValueAsShort( uint8 const _sceneId, ValueID const& _valueId, int16* o_value ); - - /** - * \brief Retrieves a scene's value as a string. - * \param _sceneId The Scene ID of the scene to retrieve the value from. - * \param _valueId The Value ID of the value to retrieve. - * \param o_value Pointer to a string that will be filled with the returned value. - * \return true if the value was obtained. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED bool SceneGetValueAsString( uint8 const _sceneId, ValueID const& _valueId, string* o_value ); - - /** - * \brief Retrieves a scene's value as a list (as a string). - * \param _sceneId The Scene ID of the scene to retrieve the value from. - * \param _valueId The Value ID of the value to retrieve. - * \param o_value Pointer to a string that will be filled with the returned value. - * \return true if the value was obtained. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED bool SceneGetValueListSelection( uint8 const _sceneId, ValueID const& _valueId, string* o_value ); - - /** - * \brief Retrieves a scene's value as a list (as a integer). - * \param _sceneId The Scene ID of the scene to retrieve the value from. - * \param _valueId The Value ID of the value to retrieve. - * \param o_value Pointer to a integer that will be filled with the returned value. - * \return true if the value was obtained. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED bool SceneGetValueListSelection( uint8 const _sceneId, ValueID const& _valueId, int32* o_value ); - - /** - * \brief Set a bool Value ID to an existing scene's ValueID - * \param _sceneId is an integer representing the unique Scene ID. - * \param _valueId is the Value ID to be added. - * \param _value is the bool value to be saved. - * \return true if Value ID was added. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED bool SetSceneValue( uint8 const _sceneId, ValueID const& _valueId, bool const _value ); - - /** - * \brief Set a byte Value ID to an existing scene's ValueID - * \param _sceneId is an integer representing the unique Scene ID. - * \param _valueId is the Value ID to be added. - * \param _value is the byte value to be saved. - * \return true if Value ID was added. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED bool SetSceneValue( uint8 const _sceneId, ValueID const& _valueId, uint8 const _value ); - - /** - * \brief Set a decimal Value ID to an existing scene's ValueID - * \param _sceneId is an integer representing the unique Scene ID. - * \param _valueId is the Value ID to be added. - * \param _value is the float value to be saved. - * \return true if Value ID was added. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED bool SetSceneValue( uint8 const _sceneId, ValueID const& _valueId, float const _value ); - - /** - * \brief Set a 32-bit signed integer Value ID to an existing scene's ValueID - * \param _sceneId is an integer representing the unique Scene ID. - * \param _valueId is the Value ID to be added. - * \param _value is the int32 value to be saved. - * \return true if Value ID was added. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED bool SetSceneValue( uint8 const _sceneId, ValueID const& _valueId, int32 const _value ); - - /** - * \brief Set a 16-bit integer Value ID to an existing scene's ValueID - * \param _sceneId is an integer representing the unique Scene ID. - * \param _valueId is the Value ID to be added. - * \param _value is the int16 value to be saved. - * \return true if Value ID was added. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED bool SetSceneValue( uint8 const _sceneId, ValueID const& _valueId, int16 const _value ); - - /** - * \brief Set a string Value ID to an existing scene's ValueID - * \param _sceneId is an integer representing the unique Scene ID. - * \param _valueId is the Value ID to be added. - * \param _value is the string value to be saved. - * \return true if Value ID was added. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED bool SetSceneValue( uint8 const _sceneId, ValueID const& _valueId, string const& _value ); - - /** - * \brief Set the list selected item Value ID to an existing scene's ValueID (as a string). - * \param _sceneId is an integer representing the unique Scene ID. - * \param _valueId is the Value ID to be added. - * \param _value is the string value to be saved. - * \return true if Value ID was added. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED bool SetSceneValueListSelection( uint8 const _sceneId, ValueID const& _valueId, string const& _value ); - - /** - * \brief Set the list selected item Value ID to an existing scene's ValueID (as a integer). - * \param _sceneId is an integer representing the unique Scene ID. - * \param _valueId is the Value ID to be added. - * \param _value is the integer value to be saved. - * \return true if Value ID was added. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED bool SetSceneValueListSelection( uint8 const _sceneId, ValueID const& _valueId, int32 const _value ); - - /** - * \brief Returns a label for the particular scene. - * \param _sceneId The Scene ID - * \return The label string. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, SetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED string GetSceneLabel( uint8 const _sceneId ); - - /** - * \brief Sets a label for the particular scene. - * \param _sceneId The Scene ID - * \param _value The new value of the label. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SceneExists, ActivateScene - */ - DEPRECATED void SetSceneLabel( uint8 const _sceneId, string const& _value ); - - /** - * \brief Check if a Scene ID is defined. - * \param _sceneId The Scene ID. - * \return true if Scene ID exists. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, ActivateScene - */ - DEPRECATED bool SceneExists( uint8 const _sceneId ); - - /** - * \brief Activate given scene to perform all its actions. - * \param _sceneId The Scene ID. - * \return true if it is successful. - * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) - * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists - */ - DEPRECATED bool ActivateScene( uint8 const _sceneId ); + /** + * \brief Delete a handheld button id. + * + * Only intended for Bridge Firmware Controllers. + * + * Results of the DeleteButton Command will be send as a Notification with the Notification type as + * Notification::Type_ControllerCommand + * + * \param _homeId The HomeID of the Z-Wave network + * \param _nodeId the ID of the Virtual Node + * \param _buttonId the ID of the Button to delete + * \return if the DeleteButton Command was send successfully to the Controller + * \sa CancelControllerCommand + */ + bool DeleteButton(uint32 const _homeId, uint8 const _nodeId, uint8 const _buttonid); - /*@}*/ + /** + * \brief Send a raw packet to a node. + * + * Send a Raw Packet to a Node. No confirmation that the node accepted the packet etc will be available. + * This is for testing only and should not be used for anything production + * + * \param _homeId the HomeID of the Z-Wave Network + * \param _nodeId the ID of the Node + * \param _logText Text to Log when sending the packet + * \param _msgType The Type of Message to Send + * \param _sendSecure if we should attempt to encrypt the packet + * \param _content A array of bytes to send + * \param _length the length of the array + */ + void SendRawData(uint32 const _homeId, uint8 const _nodeId, string const& _logText, uint8 const _msgType, const bool _sendSecure, uint8 const* _content, uint8 const _length); - //----------------------------------------------------------------------------- - // Statistics interface - //----------------------------------------------------------------------------- - /** \name Statistics retrieval interface - * Commands for Z-Wave statistics interface. - */ - /*@{*/ - public: - /** - * \brief Retrieve statistics from driver - * \param _homeId The Home ID of the driver to obtain counters - * \param _data Pointer to structure DriverData to return values - */ - void GetDriverStatistics( uint32 const _homeId, Driver::DriverData* _data ); + /*@}*/ - /** - * \brief Retrieve statistics per node - * \param _homeId The Home ID of the driver for the node - * \param _nodeId The node number - * \param _data Pointer to structure NodeData to return values - */ - void GetNodeStatistics( uint32 const _homeId, uint8 const _nodeId, Node::NodeData* _data ); + //----------------------------------------------------------------------------- + // Scene commands + //----------------------------------------------------------------------------- + /** \name Scene Commands + * Commands for Z-Wave scene interface. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * + */ + /*@{*/ + public: + /** + * \brief Gets the number of scenes that have been defined. + * \return The number of scenes. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetAllScenes, RemoveAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED uint8 GetNumScenes(); - /** - * \brief Get a Human Readable String for the RouteScheme in the Extended TX Status Frame - * \param _data Pointer to the structure Node::NodeData return from GetNodeStatistics - * \return String containing the Route Scheme Used - */ - static string GetNodeRouteScheme(Node::NodeData *_data); + /** + * \brief Gets a list of all the SceneIds. + * \param _sceneIds is a pointer to an array of integers. + * \return The number of scenes. If zero, _sceneIds will be NULL and doesn't need to be freed. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED uint8 GetAllScenes(uint8** _sceneIds); - /** - * \brief Get Humand Readable String for the RouteSpeed in the Extended TX Status Frame - * \param _data Pointer to the structure Node::NodeData returned from GetNodeStatistics - * \return String containing the Speed - */ - static string GetNodeRouteSpeed(Node::NodeData *_data); + /** + * \brief Remove all the SceneIds. + * \param _homeId The Home ID of the Z-Wave controller. 0 for all devices from all scenes. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetAllScenes, GetNumScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED void RemoveAllScenes(uint32 const _homeId); - /*@}*/ + /** + * \brief Create a new Scene passing in Scene ID + * \return uint8 Scene ID used to reference the scene. 0 is failure result. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene - //----------------------------------------------------------------------------- - // MetaData interface - //----------------------------------------------------------------------------- - /** \name MetaData Interface - * Commands for retrieving information about Devices. - */ - /*@{*/ - public: - /** - * \brief Retrieve metadata about a node - * \param _homeId The Home ID of the driver for the node - * \param _nodeId The node number - * \param _metadata the MetadataFields you are requesting. - * \return a string containing the requested metadata - */ - string const GetMetaData( uint32 const _homeId, uint8 const _nodeId, Node::MetaDataFields _metadata ); - /** - * \brief Retrieve ChangeLogs about a configuration revision - * \param _homeId The Home ID of the driver for the node - * \param _nodeId The node number - * \param revision the revision you are requesting - * \return a Node::ChangeLogEntry struct with the ChangeLog Details. if the revision paramater is -1, then then revision passed to this function is invalid - */ - Node::ChangeLogEntry const GetChangeLog( uint32 const _homeId, uint8 const _nodeId, uint32_t revision); + */ + DEPRECATED uint8 CreateScene(); - /*@}*/ - //----------------------------------------------------------------------------- - // Config File Revision interface - //----------------------------------------------------------------------------- - /** \name Config File Revision Methods - * These commands deal with checking/updating Config File's from the OZW master repository - */ - /*@{*/ + /** + * \brief Remove an existing Scene. + * \param _sceneId is an integer representing the unique Scene ID to be removed. + * \return true if scene was removed. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED bool RemoveScene(uint8 const _sceneId); + + /** + * \brief Add a bool Value ID to an existing scene. + * \param _sceneId is an integer representing the unique Scene ID. + * \param _valueId is the Value ID to be added. + * \param _value is the bool value to be saved. + * \return true if Value ID was added. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED bool AddSceneValue(uint8 const _sceneId, ValueID const& _valueId, bool const _value); + + /** + * \brief Add a byte Value ID to an existing scene. + * \param _sceneId is an integer representing the unique Scene ID. + * \param _valueId is the Value ID to be added. + * \param _value is the byte value to be saved. + * \return true if Value ID was added. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED bool AddSceneValue(uint8 const _sceneId, ValueID const& _valueId, uint8 const _value); + + /** + * \brief Add a decimal Value ID to an existing scene. + * \param _sceneId is an integer representing the unique Scene ID. + * \param _valueId is the Value ID to be added. + * \param _value is the float value to be saved. + * \return true if Value ID was added. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED bool AddSceneValue(uint8 const _sceneId, ValueID const& _valueId, float const _value); + + /** + * \brief Add a 32-bit signed integer Value ID to an existing scene. + * \param _sceneId is an integer representing the unique Scene ID. + * \param _valueId is the Value ID to be added. + * \param _value is the int32 value to be saved. + * \return true if Value ID was added. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED bool AddSceneValue(uint8 const _sceneId, ValueID const& _valueId, int32 const _value); + + /** + * \brief Add a 16-bit signed integer Value ID to an existing scene. + * \param _sceneId is an integer representing the unique Scene ID. + * \param _valueId is the Value ID to be added. + * \param _value is the int16 value to be saved. + * \return true if Value ID was added. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED bool AddSceneValue(uint8 const _sceneId, ValueID const& _valueId, int16 const _value); + + /** + * \brief Add a string Value ID to an existing scene. + * \param _sceneId is an integer representing the unique Scene ID. + * \param _valueId is the Value ID to be added. + * \param _value is the string value to be saved. + * \return true if Value ID was added. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED bool AddSceneValue(uint8 const _sceneId, ValueID const& _valueId, string const& _value); + + /** + * \brief Add the selected item list Value ID to an existing scene (as a string). + * \param _sceneId is an integer representing the unique Scene ID. + * \param _valueId is the Value ID to be added. + * \param _value is the string value to be saved. + * \return true if Value ID was added. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED bool AddSceneValueListSelection(uint8 const _sceneId, ValueID const& _valueId, string const& _value); + + /** + * \brief Add the selected item list Value ID to an existing scene (as a integer). + * \param _sceneId is an integer representing the unique Scene ID. + * \param _valueId is the Value ID to be added. + * \param _value is the integer value to be saved. + * \return true if Value ID was added. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED bool AddSceneValueListSelection(uint8 const _sceneId, ValueID const& _valueId, int32 const _value); + + /** + * \brief Remove the Value ID from an existing scene. + * \param _sceneId is an integer representing the unique Scene ID. + * \param _valueId is the Value ID to be removed. + * \return true if Value ID was removed. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED bool RemoveSceneValue(uint8 const _sceneId, ValueID const& _valueId); + + /** + * \brief Retrieves the scene's list of values. + * \param _sceneId The Scene ID of the scene to retrieve the value from. + * \param o_value Pointer to an array of ValueIDs if return is non-zero. + * \return The number of nodes in the o_value array. If zero, the array will point to NULL and does not need to be deleted. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED int SceneGetValues(uint8 const _sceneId, vector* o_value); + + /** + * \brief Retrieves a scene's value as a bool. + * \param _sceneId The Scene ID of the scene to retrieve the value from. + * \param _valueId The Value ID of the value to retrieve. + * \param o_value Pointer to a bool that will be filled with the returned value. + * \return true if the value was obtained. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED bool SceneGetValueAsBool(uint8 const _sceneId, ValueID const& _valueId, bool* o_value); + + /** + * \brief Retrieves a scene's value as an 8-bit unsigned integer. + * \param _sceneId The Scene ID of the scene to retrieve the value from. + * \param _valueId The Value ID of the value to retrieve. + * \param o_value Pointer to a uint8 that will be filled with the returned value. + * \return true if the value was obtained. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED bool SceneGetValueAsByte(uint8 const _sceneId, ValueID const& _valueId, uint8* o_value); + + /** + * \brief Retrieves a scene's value as a float. + * \param _sceneId The Scene ID of the scene to retrieve the value from. + * \param _valueId The Value ID of the value to retrieve. + * \param o_value Pointer to a float that will be filled with the returned value. + * \return true if the value was obtained. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED bool SceneGetValueAsFloat(uint8 const _sceneId, ValueID const& _valueId, float* o_value); + + /** + * \brief Retrieves a scene's value as a 32-bit signed integer. + * \param _sceneId The Scene ID of the scene to retrieve the value from. + * \param _valueId The Value ID of the value to retrieve. + * \param o_value Pointer to a int32 that will be filled with the returned value. + * \return true if the value was obtained. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED bool SceneGetValueAsInt(uint8 const _sceneId, ValueID const& _valueId, int32* o_value); + + /** + * \brief Retrieves a scene's value as a 16-bit signed integer. + * \param _sceneId The Scene ID of the scene to retrieve the value from. + * \param _valueId The Value ID of the value to retrieve. + * \param o_value Pointer to a int16 that will be filled with the returned value. + * \return true if the value was obtained. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED bool SceneGetValueAsShort(uint8 const _sceneId, ValueID const& _valueId, int16* o_value); + + /** + * \brief Retrieves a scene's value as a string. + * \param _sceneId The Scene ID of the scene to retrieve the value from. + * \param _valueId The Value ID of the value to retrieve. + * \param o_value Pointer to a string that will be filled with the returned value. + * \return true if the value was obtained. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED bool SceneGetValueAsString(uint8 const _sceneId, ValueID const& _valueId, string* o_value); + + /** + * \brief Retrieves a scene's value as a list (as a string). + * \param _sceneId The Scene ID of the scene to retrieve the value from. + * \param _valueId The Value ID of the value to retrieve. + * \param o_value Pointer to a string that will be filled with the returned value. + * \return true if the value was obtained. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED bool SceneGetValueListSelection(uint8 const _sceneId, ValueID const& _valueId, string* o_value); + + /** + * \brief Retrieves a scene's value as a list (as a integer). + * \param _sceneId The Scene ID of the scene to retrieve the value from. + * \param _valueId The Value ID of the value to retrieve. + * \param o_value Pointer to a integer that will be filled with the returned value. + * \return true if the value was obtained. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED bool SceneGetValueListSelection(uint8 const _sceneId, ValueID const& _valueId, int32* o_value); + + /** + * \brief Set a bool Value ID to an existing scene's ValueID + * \param _sceneId is an integer representing the unique Scene ID. + * \param _valueId is the Value ID to be added. + * \param _value is the bool value to be saved. + * \return true if Value ID was added. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED bool SetSceneValue(uint8 const _sceneId, ValueID const& _valueId, bool const _value); + + /** + * \brief Set a byte Value ID to an existing scene's ValueID + * \param _sceneId is an integer representing the unique Scene ID. + * \param _valueId is the Value ID to be added. + * \param _value is the byte value to be saved. + * \return true if Value ID was added. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED bool SetSceneValue(uint8 const _sceneId, ValueID const& _valueId, uint8 const _value); + + /** + * \brief Set a decimal Value ID to an existing scene's ValueID + * \param _sceneId is an integer representing the unique Scene ID. + * \param _valueId is the Value ID to be added. + * \param _value is the float value to be saved. + * \return true if Value ID was added. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED bool SetSceneValue(uint8 const _sceneId, ValueID const& _valueId, float const _value); + + /** + * \brief Set a 32-bit signed integer Value ID to an existing scene's ValueID + * \param _sceneId is an integer representing the unique Scene ID. + * \param _valueId is the Value ID to be added. + * \param _value is the int32 value to be saved. + * \return true if Value ID was added. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED bool SetSceneValue(uint8 const _sceneId, ValueID const& _valueId, int32 const _value); + + /** + * \brief Set a 16-bit integer Value ID to an existing scene's ValueID + * \param _sceneId is an integer representing the unique Scene ID. + * \param _valueId is the Value ID to be added. + * \param _value is the int16 value to be saved. + * \return true if Value ID was added. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED bool SetSceneValue(uint8 const _sceneId, ValueID const& _valueId, int16 const _value); + + /** + * \brief Set a string Value ID to an existing scene's ValueID + * \param _sceneId is an integer representing the unique Scene ID. + * \param _valueId is the Value ID to be added. + * \param _value is the string value to be saved. + * \return true if Value ID was added. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED bool SetSceneValue(uint8 const _sceneId, ValueID const& _valueId, string const& _value); + + /** + * \brief Set the list selected item Value ID to an existing scene's ValueID (as a string). + * \param _sceneId is an integer representing the unique Scene ID. + * \param _valueId is the Value ID to be added. + * \param _value is the string value to be saved. + * \return true if Value ID was added. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED bool SetSceneValueListSelection(uint8 const _sceneId, ValueID const& _valueId, string const& _value); + + /** + * \brief Set the list selected item Value ID to an existing scene's ValueID (as a integer). + * \param _sceneId is an integer representing the unique Scene ID. + * \param _valueId is the Value ID to be added. + * \param _value is the integer value to be saved. + * \return true if Value ID was added. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED bool SetSceneValueListSelection(uint8 const _sceneId, ValueID const& _valueId, int32 const _value); + + /** + * \brief Returns a label for the particular scene. + * \param _sceneId The Scene ID + * \return The label string. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, SetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED string GetSceneLabel(uint8 const _sceneId); + + /** + * \brief Sets a label for the particular scene. + * \param _sceneId The Scene ID + * \param _value The new value of the label. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SceneExists, ActivateScene + */ + DEPRECATED void SetSceneLabel(uint8 const _sceneId, string const& _value); + + /** + * \brief Check if a Scene ID is defined. + * \param _sceneId The Scene ID. + * \return true if Scene ID exists. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, ActivateScene + */ + DEPRECATED bool SceneExists(uint8 const _sceneId); + + /** + * \brief Activate given scene to perform all its actions. + * \param _sceneId The Scene ID. + * \return true if it is successful. + * \deprecated The Scene Methods have been depreciated. (This is not the same as the CENTRAL_SCENE CommandClass) + * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists + */ + DEPRECATED bool ActivateScene(uint8 const _sceneId); + + /*@}*/ + + //----------------------------------------------------------------------------- + // Statistics interface + //----------------------------------------------------------------------------- + /** \name Statistics retrieval interface + * Commands for Z-Wave statistics interface. + */ + /*@{*/ + public: + /** + * \brief Retrieve statistics from driver + * \param _homeId The Home ID of the driver to obtain counters + * \param _data Pointer to structure DriverData to return values + */ + void GetDriverStatistics(uint32 const _homeId, Driver::DriverData* _data); + + /** + * \brief Retrieve statistics per node + * \param _homeId The Home ID of the driver for the node + * \param _nodeId The node number + * \param _data Pointer to structure NodeData to return values + */ + void GetNodeStatistics(uint32 const _homeId, uint8 const _nodeId, Node::NodeData* _data); + + /** + * \brief Get a Human Readable String for the RouteScheme in the Extended TX Status Frame + * \param _data Pointer to the structure Node::NodeData return from GetNodeStatistics + * \return String containing the Route Scheme Used + */ + static string GetNodeRouteScheme(Node::NodeData *_data); + + /** + * \brief Get Humand Readable String for the RouteSpeed in the Extended TX Status Frame + * \param _data Pointer to the structure Node::NodeData returned from GetNodeStatistics + * \return String containing the Speed + */ + static string GetNodeRouteSpeed(Node::NodeData *_data); + + /*@}*/ + + //----------------------------------------------------------------------------- + // MetaData interface + //----------------------------------------------------------------------------- + /** \name MetaData Interface + * Commands for retrieving information about Devices. + */ + /*@{*/ + public: + /** + * \brief Retrieve metadata about a node + * \param _homeId The Home ID of the driver for the node + * \param _nodeId The node number + * \param _metadata the MetadataFields you are requesting. + * \return a string containing the requested metadata + */ + string const GetMetaData(uint32 const _homeId, uint8 const _nodeId, Node::MetaDataFields _metadata); + /** + * \brief Retrieve ChangeLogs about a configuration revision + * \param _homeId The Home ID of the driver for the node + * \param _nodeId The node number + * \param revision the revision you are requesting + * \return a Node::ChangeLogEntry struct with the ChangeLog Details. if the revision paramater is -1, then then revision passed to this function is invalid + */ + Node::ChangeLogEntry const GetChangeLog(uint32 const _homeId, uint8 const _nodeId, uint32_t revision); + + /*@}*/ + //----------------------------------------------------------------------------- + // Config File Revision interface + //----------------------------------------------------------------------------- + /** \name Config File Revision Methods + * These commands deal with checking/updating Config File's from the OZW master repository + */ + /*@{*/ public: /** * \brief Check the Latest Revision of the Config File for this device @@ -2673,13 +2720,10 @@ OPENZWAVE_EXPORT_WARNINGS_ON */ bool downloadLatestMFSRevision(uint32 const _homeId); - /*@}*/ - - - + /*@}*/ }; - /*@}*/ +/*@}*/ } // namespace OpenZWave #endif // _Manager_H diff --git a/cpp/src/ManufacturerSpecificDB.cpp b/cpp/src/ManufacturerSpecificDB.cpp index 3c68d47e9f..2b0afc9e86 100644 --- a/cpp/src/ManufacturerSpecificDB.cpp +++ b/cpp/src/ManufacturerSpecificDB.cpp @@ -25,7 +25,6 @@ // //----------------------------------------------------------------------------- - #include "ManufacturerSpecificDB.h" #include "tinyxml.h" @@ -37,444 +36,436 @@ #include "Notification.h" #include "Utils.h" -using namespace OpenZWave; - -ManufacturerSpecificDB *ManufacturerSpecificDB::s_instance = NULL; -map ManufacturerSpecificDB::s_manufacturerMap; -map ManufacturerSpecificDB::s_productMap; -bool ManufacturerSpecificDB::s_bXmlLoaded = false; - -ManufacturerSpecificDB *ManufacturerSpecificDB::Create -( -) +namespace OpenZWave { - - if( NULL == s_instance ) + namespace Internal { - s_instance = new ManufacturerSpecificDB(); - } - return s_instance; -} + ManufacturerSpecificDB *ManufacturerSpecificDB::s_instance = NULL; + std::map ManufacturerSpecificDB::s_manufacturerMap; + std::map > ManufacturerSpecificDB::s_productMap; + bool ManufacturerSpecificDB::s_bXmlLoaded = false; + ManufacturerSpecificDB *ManufacturerSpecificDB::Create() + { -void ManufacturerSpecificDB::Destroy -( -) -{ - delete s_instance; - s_instance = NULL; -} - -ManufacturerSpecificDB::ManufacturerSpecificDB -( -): -m_MfsMutex(new Mutex()), -m_revision(0), -m_latestRevision(0), -m_initializing(true) -{ - // Ensure the singleton instance is set - s_instance = this; + if ( NULL == s_instance) + { + s_instance = new ManufacturerSpecificDB(); + } + return s_instance; - if (!s_bXmlLoaded) LoadProductXML(); + } + void ManufacturerSpecificDB::Destroy() + { + delete s_instance; + s_instance = NULL; + } -} + ManufacturerSpecificDB::ManufacturerSpecificDB() : + m_MfsMutex(new Internal::Platform::Mutex()), m_revision(0), m_latestRevision(0), m_initializing(true) + { + // Ensure the singleton instance is set + s_instance = this; -ManufacturerSpecificDB::~ManufacturerSpecificDB -( -) -{ + if (!s_bXmlLoaded) + LoadProductXML(); - if (!s_bXmlLoaded) UnloadProductXML(); + } + + ManufacturerSpecificDB::~ManufacturerSpecificDB() + { -} + if (!s_bXmlLoaded) + UnloadProductXML(); + + } //----------------------------------------------------------------------------- // // Load the Config File Revision from each config file specified in our // ManufacturerSpecific.xml file //----------------------------------------------------------------------------- -void ManufacturerSpecificDB::LoadConfigFileRevision -( - ProductDescriptor *product -) -{ - // Parse the Z-Wave manufacturer and product XML file. - string configPath; - Options::Get()->GetOptionAsString( "ConfigPath", &configPath ); - - if (product->GetConfigPath().size() > 0) { - string path = configPath + product->GetConfigPath(); - - TiXmlDocument* pDoc = new TiXmlDocument(); - if( !pDoc->LoadFile( path.c_str(), TIXML_ENCODING_UTF8 ) ) - { - delete pDoc; - Log::Write( LogLevel_Info, "Unable to load config file %s", path.c_str() ); - return; - } - pDoc->SetUserData((void *)path.c_str()); - TiXmlElement const* root = pDoc->RootElement(); - char const *str = root->Value(); - if( str && !strcmp( str, "Product" ) ) + void ManufacturerSpecificDB::LoadConfigFileRevision(ProductDescriptor *product) { - // Read in the revision attributes - str = root->Attribute( "Revision" ); - if( !str ) + // Parse the Z-Wave manufacturer and product XML file. + string configPath; + Options::Get()->GetOptionAsString("ConfigPath", &configPath); + + if (product->GetConfigPath().size() > 0) { - Log::Write( LogLevel_Info, "Error in Product Config file at line %d - missing Revision attribute", root->Row() ); + string path = configPath + product->GetConfigPath(); + + TiXmlDocument* pDoc = new TiXmlDocument(); + if (!pDoc->LoadFile(path.c_str(), TIXML_ENCODING_UTF8)) + { + delete pDoc; + Log::Write(LogLevel_Info, "Unable to load config file %s", path.c_str()); + return; + } + pDoc->SetUserData((void *) path.c_str()); + TiXmlElement const* root = pDoc->RootElement(); + char const *str = root->Value(); + if (str && !strcmp(str, "Product")) + { + str = root->Attribute("xmlns"); + if (str && strcmp(str, "https://github.com/OpenZWave/open-zwave")) + { + Log::Write(LogLevel_Info, "Product Config File % has incorrect xml Namespace", path.c_str()); + delete pDoc; + return; + } + // Read in the revision attributes + str = root->Attribute("Revision"); + if (!str) + { + Log::Write(LogLevel_Info, "Error in Product Config file at line %d - missing Revision attribute", root->Row()); + delete pDoc; + return; + } + product->SetConfigRevision(atol(str)); + } delete pDoc; - return; } - product->SetConfigRevision(atol(str)); } - delete pDoc; - } -} - //----------------------------------------------------------------------------- // // Load the XML that maps manufacturer and product IDs to human-readable names //----------------------------------------------------------------------------- -bool ManufacturerSpecificDB::LoadProductXML -( -) -{ - LockGuard LG(m_MfsMutex); - + bool ManufacturerSpecificDB::LoadProductXML() + { + LockGuard LG(m_MfsMutex); - // Parse the Z-Wave manufacturer and product XML file. - string configPath; - Options::Get()->GetOptionAsString( "ConfigPath", &configPath ); + // Parse the Z-Wave manufacturer and product XML file. + string configPath; + Options::Get()->GetOptionAsString("ConfigPath", &configPath); - string filename = configPath + "manufacturer_specific.xml"; + string filename = configPath + "manufacturer_specific.xml"; - TiXmlDocument* pDoc = new TiXmlDocument(); - if( !pDoc->LoadFile( filename.c_str(), TIXML_ENCODING_UTF8 ) ) - { - delete pDoc; - Log::Write( LogLevel_Info, "Unable to load %s", filename.c_str() ); - return false; - } - pDoc->SetUserData((void *)filename.c_str()); - TiXmlElement const* root = pDoc->RootElement(); - - char const* str; - char* pStopChar; - - str = root->Attribute("Revision"); - if (str) { - Log::Write(LogLevel_Info, "Manufacturer_Specific.xml file Revision is %s", str); - m_revision = atoi(str); - } else { - Log::Write(LogLevel_Warning, "Manufacturer_Specific.xml file has no Revision"); - m_revision = 0; - } - - TiXmlElement const* manufacturerElement = root->FirstChildElement(); - while( manufacturerElement ) - { - str = manufacturerElement->Value(); - if( str && !strcmp( str, "Manufacturer" ) ) - { - // Read in the manufacturer attributes - str = manufacturerElement->Attribute( "id" ); - if( !str ) + TiXmlDocument* pDoc = new TiXmlDocument(); + if (!pDoc->LoadFile(filename.c_str(), TIXML_ENCODING_UTF8)) { - Log::Write( LogLevel_Info, "Error in manufacturer_specific.xml at line %d - missing manufacturer id attribute", manufacturerElement->Row() ); delete pDoc; + Log::Write(LogLevel_Info, "Unable to load %s", filename.c_str()); return false; } - uint16 manufacturerId = (uint16)strtol( str, &pStopChar, 16 ); + pDoc->SetUserData((void *) filename.c_str()); + TiXmlElement const* root = pDoc->RootElement(); + + char const* str; + char* pStopChar; - str = manufacturerElement->Attribute( "name" ); - if( !str ) + str = root->Attribute("Revision"); + if (str) { - Log::Write( LogLevel_Info, "Error in manufacturer_specific.xml at line %d - missing manufacturer name attribute", manufacturerElement->Row() ); - delete pDoc; - return false; + Log::Write(LogLevel_Info, "Manufacturer_Specific.xml file Revision is %s", str); + m_revision = atoi(str); + } + else + { + Log::Write(LogLevel_Warning, "Manufacturer_Specific.xml file has no Revision"); + m_revision = 0; } - // Add this manufacturer to the map - s_manufacturerMap[manufacturerId] = str; - - // Parse all the products for this manufacturer - TiXmlElement const* productElement = manufacturerElement->FirstChildElement(); - while( productElement ) + TiXmlElement const* manufacturerElement = root->FirstChildElement(); + while (manufacturerElement) { - str = productElement->Value(); - if( str && !strcmp( str, "Product" ) ) + str = manufacturerElement->Value(); + if (str && !strcmp(str, "Manufacturer")) { - str = productElement->Attribute( "type" ); - if( !str ) - { - Log::Write( LogLevel_Info, "Error in manufacturer_specific.xml at line %d - missing product type attribute", productElement->Row() ); - delete pDoc; - return false; - } - uint16 productType = (uint16)strtol( str, &pStopChar, 16 ); - - str = productElement->Attribute( "id" ); - if( !str ) + // Read in the manufacturer attributes + str = manufacturerElement->Attribute("id"); + if (!str) { - Log::Write( LogLevel_Info, "Error in manufacturer_specific.xml at line %d - missing product id attribute", productElement->Row() ); + Log::Write(LogLevel_Info, "Error in manufacturer_specific.xml at line %d - missing manufacturer id attribute", manufacturerElement->Row()); delete pDoc; return false; } - uint16 productId = (uint16)strtol( str, &pStopChar, 16 ); + uint16 manufacturerId = (uint16) strtol(str, &pStopChar, 16); - str = productElement->Attribute( "name" ); - if( !str ) + str = manufacturerElement->Attribute("name"); + if (!str) { - Log::Write( LogLevel_Info, "Error in manufacturer_specific.xml at line %d - missing product name attribute", productElement->Row() ); + Log::Write(LogLevel_Info, "Error in manufacturer_specific.xml at line %d - missing manufacturer name attribute", manufacturerElement->Row()); delete pDoc; return false; } - string productName = str; - // Optional config path - string dconfigPath; - str = productElement->Attribute( "config" ); - if( str ) - { - dconfigPath = str; - } + // Add this manufacturer to the map + s_manufacturerMap[manufacturerId] = str; - // Add the product to the map - ProductDescriptor* product = new ProductDescriptor( manufacturerId, productType, productId, productName, s_manufacturerMap[manufacturerId], dconfigPath ); - if ( s_productMap[product->GetKey()] != NULL ) + // Parse all the products for this manufacturer + TiXmlElement const* productElement = manufacturerElement->FirstChildElement(); + while (productElement) { - ProductDescriptor *c = s_productMap[product->GetKey()]; - Log::Write( LogLevel_Info, "Product name collision: %s type %x id %x manufacturerid %x, collides with %s, type %x id %x manufacturerid %x", productName.c_str(), productType, productId, manufacturerId, c->GetProductName().c_str(), c->GetProductType(), c->GetProductId(), c->GetManufacturerId()); - delete product; - } - else - { - LoadConfigFileRevision(product); - s_productMap[product->GetKey()] = product; + str = productElement->Value(); + if (str && !strcmp(str, "Product")) + { + str = productElement->Attribute("type"); + if (!str) + { + Log::Write(LogLevel_Info, "Error in manufacturer_specific.xml at line %d - missing product type attribute", productElement->Row()); + delete pDoc; + return false; + } + uint16 productType = (uint16) strtol(str, &pStopChar, 16); + + str = productElement->Attribute("id"); + if (!str) + { + Log::Write(LogLevel_Info, "Error in manufacturer_specific.xml at line %d - missing product id attribute", productElement->Row()); + delete pDoc; + return false; + } + uint16 productId = (uint16) strtol(str, &pStopChar, 16); + + str = productElement->Attribute("name"); + if (!str) + { + Log::Write(LogLevel_Info, "Error in manufacturer_specific.xml at line %d - missing product name attribute", productElement->Row()); + delete pDoc; + return false; + } + string productName = str; + + // Optional config path + string dconfigPath; + str = productElement->Attribute("config"); + if (str) + { + dconfigPath = str; + } + + // Add the product to the map + ProductDescriptor* product = new ProductDescriptor(manufacturerId, productType, productId, productName, s_manufacturerMap[manufacturerId], dconfigPath); + if (s_productMap[product->GetKey()] != NULL) + { + std::shared_ptr c = s_productMap[product->GetKey()]; + Log::Write(LogLevel_Info, "Product name collision: %s type %x id %x manufacturerid %x, collides with %s, type %x id %x manufacturerid %x", productName.c_str(), productType, productId, manufacturerId, c->GetProductName().c_str(), c->GetProductType(), c->GetProductId(), c->GetManufacturerId()); + delete product; + } + else + { + LoadConfigFileRevision(product); + s_productMap[product->GetKey()] = std::shared_ptr(product); + } + } + + // Move on to the next product. + productElement = productElement->NextSiblingElement(); } } - // Move on to the next product. - productElement = productElement->NextSiblingElement(); + // Move on to the next manufacturer. + manufacturerElement = manufacturerElement->NextSiblingElement(); } - } + s_bXmlLoaded = true; - // Move on to the next manufacturer. - manufacturerElement = manufacturerElement->NextSiblingElement(); - } - s_bXmlLoaded = true; - - delete pDoc; - return true; -} + delete pDoc; + return true; + } //----------------------------------------------------------------------------- // // Free the XML that maps manufacturer and product IDs //----------------------------------------------------------------------------- -void ManufacturerSpecificDB::UnloadProductXML -( -) -{ - LockGuard LG(m_MfsMutex); - if (s_bXmlLoaded) - { - map::iterator pit = s_productMap.begin(); - while( !s_productMap.empty() ) + void ManufacturerSpecificDB::UnloadProductXML() { - pit->second->Release(); - s_productMap.erase( pit ); - pit = s_productMap.begin(); - } + LockGuard LG(m_MfsMutex); + if (s_bXmlLoaded) + { + map >::iterator pit = s_productMap.begin(); + while (!s_productMap.empty()) + { + s_productMap.erase(pit); + pit = s_productMap.begin(); + } - map::iterator mit = s_manufacturerMap.begin(); - while( !s_manufacturerMap.empty() ) - { - s_manufacturerMap.erase( mit ); - mit = s_manufacturerMap.begin(); + map::iterator mit = s_manufacturerMap.begin(); + while (!s_manufacturerMap.empty()) + { + s_manufacturerMap.erase(mit); + mit = s_manufacturerMap.begin(); + } + + s_bXmlLoaded = false; + } } - s_bXmlLoaded = false; - } -} + void ManufacturerSpecificDB::checkConfigFiles(Driver *driver) + { + LockGuard LG(m_MfsMutex); + if (!s_bXmlLoaded) + LoadProductXML(); -void ManufacturerSpecificDB::checkConfigFiles -( - Driver *driver -) -{ - LockGuard LG(m_MfsMutex); - if (!s_bXmlLoaded) - LoadProductXML(); + string configPath; + Options::Get()->GetOptionAsString("ConfigPath", &configPath); - string configPath; - Options::Get()->GetOptionAsString( "ConfigPath", &configPath ); + map >::iterator pit; + for (pit = s_productMap.begin(); pit != s_productMap.end(); pit++) + { + std::shared_ptr c = pit->second; + if (c->GetConfigPath().size() > 0) + { + string path = configPath + c->GetConfigPath(); - map::iterator pit; - for (pit = s_productMap.begin(); pit != s_productMap.end(); pit++) { - ProductDescriptor *c = pit->second; - if (c->GetConfigPath().size() > 0) { - string path = configPath + c->GetConfigPath(); + /* check if we are downloading already */ + std::list::iterator iter = std::find(m_downloading.begin(), m_downloading.end(), path); + /* check if the file exists */ + if (iter == m_downloading.end() && !Internal::Platform::FileOps::Create()->FileExists(path)) + { + Log::Write(LogLevel_Warning, "Config File for %s does not exist - %s", c->GetProductName().c_str(), path.c_str()); + /* try to download it */ + if (driver->startConfigDownload(c->GetManufacturerId(), c->GetProductType(), c->GetProductId(), path)) + { + m_downloading.push_back(path); + } + else + { + Log::Write(LogLevel_Warning, "Can't download file %s", path.c_str()); + Notification* notification = new Notification(Notification::Type_UserAlerts); + notification->SetUserAlertNotification(Notification::Alert_ConfigFileDownloadFailed); + driver->QueueNotification(notification); + } + } + else if (iter != m_downloading.end()) + { + Log::Write(LogLevel_Debug, "Config file for %s already queued", c->GetProductName().c_str()); + } + } + } + checkInitialized(); + } + void ManufacturerSpecificDB::configDownloaded(Driver *driver, string file, uint8 node, bool success) + { /* check if we are downloading already */ - std::list::iterator iter = std::find (m_downloading.begin(), m_downloading.end(), path); - /* check if the file exists */ - if (iter == m_downloading.end() && !FileOps::Create()->FileExists(path)) { - Log::Write( LogLevel_Warning, "Config File for %s does not exist - %s", c->GetProductName().c_str(), path.c_str()); - /* try to download it */ - if (driver->startConfigDownload(c->GetManufacturerId(), c->GetProductType(), c->GetProductId(), path)) { - m_downloading.push_back(path); - } else { - Log::Write(LogLevel_Warning, "Can't download file %s", path.c_str()); - Notification* notification = new Notification( Notification::Type_UserAlerts ); - notification->SetUserAlertNotification(Notification::Alert_ConfigFileDownloadFailed); - driver->QueueNotification( notification ); + std::list::iterator iter = std::find(m_downloading.begin(), m_downloading.end(), file); + if (iter != m_downloading.end()) + { + m_downloading.erase(iter); + if ((node > 0) && success) + { + driver->refreshNodeConfig(node); + } + else + { + checkInitialized(); } - } else if (iter != m_downloading.end()) { - Log::Write(LogLevel_Debug, "Config file for %s already queued", c->GetProductName().c_str()); + } + else + { + Log::Write(LogLevel_Warning, "File is not in the list of downloading files: %s", file.c_str()); + checkInitialized(); } } - } - checkInitialized(); -} - -void ManufacturerSpecificDB::configDownloaded -( - Driver *driver, - string file, - uint8 node, - bool success -) -{ - /* check if we are downloading already */ - std::list::iterator iter = std::find (m_downloading.begin(), m_downloading.end(), file); - if (iter != m_downloading.end()) { - m_downloading.erase(iter); - if ((node > 0) && success) { - driver->refreshNodeConfig(node); - } else { + + void ManufacturerSpecificDB::mfsConfigDownloaded(Driver *driver, string file, bool success) + { + /* check if we are downloading already */ + std::list::iterator iter = std::find(m_downloading.begin(), m_downloading.end(), file); + if (iter != m_downloading.end()) + { + m_downloading.erase(iter); + if (success) + { + UnloadProductXML(); + LoadProductXML(); + checkConfigFiles(driver); + } + } + else + { + Log::Write(LogLevel_Warning, "File is not in the list of downloading files: %s", file.c_str()); + } checkInitialized(); } - } else { - Log::Write(LogLevel_Warning, "File is not in the list of downloading files: %s", file.c_str()); - checkInitialized(); - } -} - -void ManufacturerSpecificDB::mfsConfigDownloaded -( - Driver *driver, - string file, - bool success -) -{ - /* check if we are downloading already */ - std::list::iterator iter = std::find (m_downloading.begin(), m_downloading.end(), file); - if (iter != m_downloading.end()) { - m_downloading.erase(iter); - if (success) { - UnloadProductXML(); - LoadProductXML(); - checkConfigFiles(driver); + + bool ManufacturerSpecificDB::isReady() + { + if (!m_initializing && (m_downloading.size() == 0)) + return true; + return false; } - } else { - Log::Write(LogLevel_Warning, "File is not in the list of downloading files: %s", file.c_str()); - } - checkInitialized(); -} - -bool ManufacturerSpecificDB::isReady -( -) -{ - if (!m_initializing && (m_downloading.size() == 0)) - return true; - return false; -} - -void ManufacturerSpecificDB::checkInitialized() { - if (!m_initializing) - return; - Log::Write(LogLevel_Debug, "Downloads Remaining: %d", m_downloading.size()); - if (m_downloading.size() == 0) { - Log::Write(LogLevel_Info, "ManufacturerSpecificDB Initialized"); - m_initializing = false; - } -} - -ProductDescriptor *ManufacturerSpecificDB::getProduct -( - uint16 _manufacturerId, - uint16 _productType, - uint16 _productId -) -{ - if (!s_bXmlLoaded) LoadProductXML(); + void ManufacturerSpecificDB::checkInitialized() + { + if (!m_initializing) + return; + Log::Write(LogLevel_Debug, "Downloads Remaining: %d", m_downloading.size()); + if (m_downloading.size() == 0) + { + Log::Write(LogLevel_Info, "ManufacturerSpecificDB Initialized"); + m_initializing = false; + } + } + std::shared_ptr ManufacturerSpecificDB::getProduct(uint16 _manufacturerId, uint16 _productType, uint16 _productId) + { - // Try to get the real manufacturer and product names - map::iterator mit = s_manufacturerMap.find( _manufacturerId ); - if( mit != s_manufacturerMap.end() ) - { - // Get the product - map::iterator pit = s_productMap.find( ProductDescriptor::GetKey( _manufacturerId, _productType, _productId ) ); - if( pit != s_productMap.end() ) + if (!s_bXmlLoaded) + LoadProductXML(); + + // Try to get the real manufacturer and product names + map::iterator mit = s_manufacturerMap.find(_manufacturerId); + if (mit != s_manufacturerMap.end()) + { + // Get the product + map >::iterator pit = s_productMap.find(ProductDescriptor::GetKey(_manufacturerId, _productType, _productId)); + if (pit != s_productMap.end()) + { + return pit->second; + } + } + return NULL; + } + + bool ManufacturerSpecificDB::updateConfigFile(Driver *driver, Node *node) { - return pit->second; + string configPath; + bool ret = false; + Options::Get()->GetOptionAsString("ConfigPath", &configPath); + string path = configPath + node->getConfigPath(); + + if (driver->startConfigDownload(node->GetManufacturerId(), node->GetProductType(), node->GetProductId(), path, node->GetNodeId())) + { + m_downloading.push_back(path); + ret = true; + } + else + { + Log::Write(LogLevel_Warning, "Can't download Config file %s", node->getConfigPath().c_str()); + Notification* notification = new Notification(Notification::Type_UserAlerts); + notification->SetUserAlertNotification(Notification::Alert_ConfigFileDownloadFailed); + driver->QueueNotification(notification); + } + checkInitialized(); + return ret; } - } - return NULL; -} - -bool ManufacturerSpecificDB::updateConfigFile -( - Driver *driver, - Node *node -) -{ - string configPath; - bool ret = false; - Options::Get()->GetOptionAsString( "ConfigPath", &configPath ); - string path = configPath + node->getConfigPath(); - - if (driver->startConfigDownload(node->GetManufacturerId(), node->GetProductType(), node->GetProductId(), path, node->GetNodeId())) { - m_downloading.push_back(path); - ret = true; - } else { - Log::Write(LogLevel_Warning, "Can't download Config file %s", node->getConfigPath().c_str()); - Notification* notification = new Notification( Notification::Type_UserAlerts ); - notification->SetUserAlertNotification(Notification::Alert_ConfigFileDownloadFailed); - driver->QueueNotification( notification ); - } - checkInitialized(); - return ret; -} -bool ManufacturerSpecificDB::updateMFSConfigFile -( - Driver *driver -) -{ - bool ret = false; - string configPath; - Options::Get()->GetOptionAsString( "ConfigPath", &configPath ); - string path = configPath + "manufacturer_specific.xml"; - - if (driver->startMFSDownload(path)) { - m_downloading.push_back(path); - ret = true; - } else { - Log::Write(LogLevel_Warning, "Can't download ManufacturerSpecifix.xml Config file"); - Notification* notification = new Notification( Notification::Type_UserAlerts ); - notification->SetUserAlertNotification(Notification::Alert_ConfigFileDownloadFailed); - driver->QueueNotification( notification ); - } - - checkInitialized(); - return ret; -} + bool ManufacturerSpecificDB::updateMFSConfigFile(Driver *driver) + { + bool ret = false; + string configPath; + Options::Get()->GetOptionAsString("ConfigPath", &configPath); + string path = configPath + "manufacturer_specific.xml"; + + if (driver->startMFSDownload(path)) + { + m_downloading.push_back(path); + ret = true; + } + else + { + Log::Write(LogLevel_Warning, "Can't download ManufacturerSpecifix.xml Config file"); + Notification* notification = new Notification(Notification::Type_UserAlerts); + notification->SetUserAlertNotification(Notification::Alert_ConfigFileDownloadFailed); + driver->QueueNotification(notification); + } + checkInitialized(); + return ret; + } + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/ManufacturerSpecificDB.h b/cpp/src/ManufacturerSpecificDB.h index 58b3ce559c..3d05e24bcc 100644 --- a/cpp/src/ManufacturerSpecificDB.h +++ b/cpp/src/ManufacturerSpecificDB.h @@ -25,7 +25,6 @@ // //----------------------------------------------------------------------------- - #ifndef _ManufacturerSpecificDB_H #define _ManufacturerSpecificDB_H @@ -39,116 +38,139 @@ namespace OpenZWave { - class Mutex; class Driver; - - - class ProductDescriptor : public Ref - { + namespace Internal + { + namespace Platform + { + class Mutex; + } + + class ProductDescriptor + { public: - ProductDescriptor - ( - uint16 _manufacturerId, - uint16 _productType, - uint16 _productId, - string const& _productName, - string const& _manufacturerName, - string const& _configPath - ): - m_manufacturerId( _manufacturerId ), - m_productType( _productType ), - m_productId( _productId ), - m_productName( _productName ), - m_manufacturerName ( _manufacturerName ), - m_configPath( _configPath ), - m_configrevision( 0 ) + ProductDescriptor(uint16 _manufacturerId, uint16 _productType, uint16 _productId, string const& _productName, string const& _manufacturerName, string const& _configPath) : + m_manufacturerId(_manufacturerId), m_productType(_productType), m_productId(_productId), m_productName(_productName), m_manufacturerName(_manufacturerName), m_configPath(_configPath), m_configrevision(0) { } - ~ProductDescriptor() { + ~ProductDescriptor() + { } - int64 GetKey()const + int64 GetKey() const { - return( GetKey( m_manufacturerId, m_productType, m_productId ) ); + return (GetKey(m_manufacturerId, m_productType, m_productId)); } - static int64 GetKey( uint16 _manufacturerId, uint16 _productType, uint16 _productId ) + static int64 GetKey(uint16 _manufacturerId, uint16 _productType, uint16 _productId) { - int64 key = (((int64)_manufacturerId)<<32) | (((int64)_productType)<<16) | (int64)_productId; + int64 key = (((int64) _manufacturerId) << 32) | (((int64) _productType) << 16) | (int64) _productId; return key; } - uint16 GetManufacturerId()const{ return m_manufacturerId; } - string GetManufacturerName() const {return m_manufacturerName; } - uint16 GetProductType()const{ return m_productType; } - uint16 GetProductId()const{ return m_productId; } - string GetProductName()const{ return m_productName; } - string GetConfigPath()const{ return m_configPath; } - void SetConfigRevision(uint32 revision) { m_configrevision = revision;} - uint32 GetConfigRevision()const{ return m_configrevision; } + uint16 GetManufacturerId() const + { + return m_manufacturerId; + } + string GetManufacturerName() const + { + return m_manufacturerName; + } + uint16 GetProductType() const + { + return m_productType; + } + uint16 GetProductId() const + { + return m_productId; + } + string GetProductName() const + { + return m_productName; + } + string GetConfigPath() const + { + return m_configPath; + } + void SetConfigRevision(uint32 revision) + { + m_configrevision = revision; + } + uint32 GetConfigRevision() const + { + return m_configrevision; + } private: - uint16 m_manufacturerId; - uint16 m_productType; - uint16 m_productId; - string m_productName; - string m_manufacturerName; - string m_configPath; - uint32 m_configrevision; - }; - - - - - - /** \brief The _ManufacturerSpecificDB class handles the Config File Database - * that we use to configure devices. - */ - class OPENZWAVE_EXPORT ManufacturerSpecificDB { - public: - static ManufacturerSpecificDB *Create(); - static ManufacturerSpecificDB *Get() { return s_instance; } - static void Destroy(); - - bool LoadProductXML(); - void UnloadProductXML(); - uint32 getRevision() { return m_revision;} - uint32 getLatestRevision() { return m_latestRevision;}; - void setLatestRevision(uint32 rev) { m_latestRevision = rev;}; - void checkConfigFiles(Driver *); - void configDownloaded(Driver *, string file, uint8 node, bool success = true); - void mfsConfigDownloaded(Driver *, string file, bool success = true); - bool isReady(); - bool updateConfigFile(Driver *, Node *); - bool updateMFSConfigFile(Driver *); - void checkInitialized(); - - private: - void LoadConfigFileRevision (ProductDescriptor *product); - ManufacturerSpecificDB(); - ~ManufacturerSpecificDB(); - - + uint16 m_manufacturerId; + uint16 m_productType; + uint16 m_productId; + string m_productName; + string m_manufacturerName; + string m_configPath; + uint32 m_configrevision; + }; + + /** \brief The _ManufacturerSpecificDB class handles the Config File Database + * that we use to configure devices. + */ + class OPENZWAVE_EXPORT ManufacturerSpecificDB + { + public: + static ManufacturerSpecificDB *Create(); + static ManufacturerSpecificDB *Get() + { + return s_instance; + } + static void Destroy(); - Mutex* m_MfsMutex; /**< Mutex to ensure its accessed by a single thread at a time */ + bool LoadProductXML(); + void UnloadProductXML(); + uint32 getRevision() + { + return m_revision; + } + uint32 getLatestRevision() + { + return m_latestRevision; + } + ; + void setLatestRevision(uint32 rev) + { + m_latestRevision = rev; + } + ; + void checkConfigFiles(Driver *); + void configDownloaded(Driver *, string file, uint8 node, bool success = true); + void mfsConfigDownloaded(Driver *, string file, bool success = true); + bool isReady(); + bool updateConfigFile(Driver *, Node *); + bool updateMFSConfigFile(Driver *); + void checkInitialized(); - static ManufacturerSpecificDB *s_instance; - public: - ProductDescriptor *getProduct(uint16 _manufacturerId, uint16 _productType, uint16 _productId); + private: + void LoadConfigFileRevision(ProductDescriptor *product); + ManufacturerSpecificDB(); + ~ManufacturerSpecificDB(); -private: - static map s_manufacturerMap; - static map s_productMap; - static bool s_bXmlLoaded; + Internal::Platform::Mutex* m_MfsMutex; /**< Mutex to ensure its accessed by a single thread at a time */ - list m_downloading; - uint32 m_revision; - uint32 m_latestRevision; - bool m_initializing; + static ManufacturerSpecificDB *s_instance; + public: + std::shared_ptr getProduct(uint16 _manufacturerId, uint16 _productType, uint16 _productId); - }; + private: + static map s_manufacturerMap; + static map > s_productMap; + static bool s_bXmlLoaded; + list m_downloading; + uint32 m_revision; + uint32 m_latestRevision; + bool m_initializing; -} + }; + } // namespace Internal +} // namespace OpenZWave #endif diff --git a/cpp/src/Msg.cpp b/cpp/src/Msg.cpp index ef9f49d3f2..80357e93cb 100644 --- a/cpp/src/Msg.cpp +++ b/cpp/src/Msg.cpp @@ -36,308 +36,273 @@ #include "command_classes/Security.h" #include "aes/aescpp.h" -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { -/* Callback for normal messages start at 10. Special Messages using a Callback prior to 10 */ -uint8 Msg::s_nextCallbackId = 10; + /* Callback for normal messages start at 10. Special Messages using a Callback prior to 10 */ + uint8 Msg::s_nextCallbackId = 10; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -Msg::Msg -( - string const& _logText, - uint8 _targetNodeId, - uint8 const _msgType, - uint8 const _function, - bool const _bCallbackRequired, - bool const _bReplyRequired, // = true - uint8 const _expectedReply, // = 0 - uint8 const _expectedCommandClassId // = 0 -): - m_logText( _logText ), - m_bFinal( false ), - m_bCallbackRequired( _bCallbackRequired ), - m_callbackId( 0 ), - m_expectedReply( 0 ), - m_expectedCommandClassId( _expectedCommandClassId ), - m_length( 4 ), - m_targetNodeId( _targetNodeId ), - m_sendAttempts( 0 ), - m_maxSendAttempts( MAX_TRIES ), - m_instance( 1 ), - m_endPoint( 0 ), - m_flags( 0 ), - m_encrypted ( false ), - m_noncerecvd ( false ), - m_homeId ( 0 ) -{ - if( _bReplyRequired ) - { - // Wait for this message before considering the transaction complete - m_expectedReply = _expectedReply ? _expectedReply : _function; - } + Msg::Msg(string const& _logText, uint8 _targetNodeId, uint8 const _msgType, uint8 const _function, bool const _bCallbackRequired, bool const _bReplyRequired, // = true + uint8 const _expectedReply, // = 0 + uint8 const _expectedCommandClassId // = 0 + ) : + m_logText(_logText), m_bFinal(false), m_bCallbackRequired(_bCallbackRequired), m_callbackId(0), m_expectedReply(0), m_expectedCommandClassId(_expectedCommandClassId), m_length(4), m_targetNodeId(_targetNodeId), m_sendAttempts(0), m_maxSendAttempts( MAX_TRIES), m_instance(1), m_endPoint(0), m_flags(0), m_encrypted(false), m_noncerecvd(false), m_homeId(0) + { + if (_bReplyRequired) + { + // Wait for this message before considering the transaction complete + m_expectedReply = _expectedReply ? _expectedReply : _function; + } - memset(m_buffer, 0x00, 256); - memset(e_buffer, 0x00, 256); + memset(m_buffer, 0x00, 256); + memset(e_buffer, 0x00, 256); - m_buffer[0] = SOF; - m_buffer[1] = 0; // Length of the following data, filled in during Finalize. - m_buffer[2] = _msgType; - m_buffer[3] = _function; -} + m_buffer[0] = SOF; + m_buffer[1] = 0; // Length of the following data, filled in during Finalize. + m_buffer[2] = _msgType; + m_buffer[3] = _function; + } //----------------------------------------------------------------------------- // // Used to enable wrapping with MultiInstance/MultiChannel during finalize. //----------------------------------------------------------------------------- -void Msg::SetInstance -( - CommandClass* _cc, - uint8 const _instance -) -{ - // Determine whether we should encapsulate the message in MultiInstance or MultiCommand - if( Node* node = _cc->GetNodeUnsafe() ) - { - MultiInstance* micc = static_cast( node->GetCommandClass( MultiInstance::StaticGetCommandClassId() ) ); - m_instance = _instance; - if( micc ) + void Msg::SetInstance(Internal::CC::CommandClass* _cc, uint8 const _instance) { - if( micc->GetVersion() > 1 ) + // Determine whether we should encapsulate the message in MultiInstance or MultiCommand + if (Node* node = _cc->GetNodeUnsafe()) { - m_endPoint = _cc->GetEndPoint( _instance ); - if( m_endPoint != 0 ) + Internal::CC::MultiInstance* micc = static_cast(node->GetCommandClass(Internal::CC::MultiInstance::StaticGetCommandClassId())); + m_instance = _instance; + if (micc) { - // Set the flag bit to indicate MultiChannel rather than MultiInstance - m_flags |= m_MultiChannel; - m_expectedCommandClassId = MultiInstance::StaticGetCommandClassId(); + if (micc->GetVersion() > 1) + { + m_endPoint = _cc->GetEndPoint(_instance); + if (m_endPoint != 0) + { + // Set the flag bit to indicate MultiChannel rather than MultiInstance + m_flags |= m_MultiChannel; + m_expectedCommandClassId = Internal::CC::MultiInstance::StaticGetCommandClassId(); + } + } + else if (m_instance > 1) + { + // Set the flag bit to indicate MultiInstance rather than MultiChannel + m_flags |= m_MultiInstance; + m_expectedCommandClassId = Internal::CC::MultiInstance::StaticGetCommandClassId(); + } } } - else if( m_instance > 1 ) - { - // Set the flag bit to indicate MultiInstance rather than MultiChannel - m_flags |= m_MultiInstance; - m_expectedCommandClassId = MultiInstance::StaticGetCommandClassId(); - } } - } -} //----------------------------------------------------------------------------- // // Add a byte to the message //----------------------------------------------------------------------------- -void Msg::Append -( - uint8 const _data -) -{ - m_buffer[m_length++] = _data; -} + void Msg::Append(uint8 const _data) + { + m_buffer[m_length++] = _data; + } //----------------------------------------------------------------------------- // // Add a byte array to the message //----------------------------------------------------------------------------- -void Msg::AppendArray -( - const uint8* const _data, - const uint8 _length -) -{ - for (uint8 i=0 ; i<_length ; i++) { - this->Append( _data[i] ); - } -} + void Msg::AppendArray(const uint8* const _data, const uint8 _length) + { + for (uint8 i = 0; i < _length; i++) + { + this->Append(_data[i]); + } + } //----------------------------------------------------------------------------- // // Fill in the length and checksum values for the message //----------------------------------------------------------------------------- -void Msg::Finalize() -{ - if( m_bFinal ) - { - // Already finalized - return; - } - - // Deal with Multi-Channel/Instance encapsulation - if( ( m_flags & ( m_MultiChannel | m_MultiInstance ) ) != 0 ) - { - MultiEncap(); - } + void Msg::Finalize() + { + if (m_bFinal) + { + // Already finalized + return; + } - // Add the callback id - if( m_bCallbackRequired ) - { - // Set the length byte - m_buffer[1] = m_length; // Length of following data + // Deal with Multi-Channel/Instance encapsulation + if ((m_flags & (m_MultiChannel | m_MultiInstance)) != 0) + { + MultiEncap(); + } - if( 0 == s_nextCallbackId ) - { - s_nextCallbackId = 10; - } + // Add the callback id + if (m_bCallbackRequired) + { + // Set the length byte + m_buffer[1] = m_length; // Length of following data - m_buffer[m_length++] = s_nextCallbackId; - m_callbackId = s_nextCallbackId++; - } - else - { - // Set the length byte - m_buffer[1] = m_length - 1; // Length of following data - } + if (0 == s_nextCallbackId) + { + s_nextCallbackId = 10; + } - // Calculate the checksum - uint8 checksum = 0xff; - for( uint32 i=1; i // If this message has a callback ID, increment it and recalculate the checksum //----------------------------------------------------------------------------- -void Msg::UpdateCallbackId() -{ - if( m_bCallbackRequired ) - { - if( 0 == s_nextCallbackId ) + void Msg::UpdateCallbackId() { - s_nextCallbackId = 10; - } + if (m_bCallbackRequired) + { + if (0 == s_nextCallbackId) + { + s_nextCallbackId = 10; + } - // update the callback ID - m_buffer[m_length-2] = s_nextCallbackId; - m_callbackId = s_nextCallbackId++; + // update the callback ID + m_buffer[m_length - 2] = s_nextCallbackId; + m_callbackId = s_nextCallbackId++; - // Recalculate the checksum - uint8 checksum = 0xff; - for( int32 i=1; i // Create a string containing the raw data //----------------------------------------------------------------------------- -string Msg::GetAsString() -{ - string str = m_logText; + std::string Msg::GetAsString() + { + string str = m_logText; - char byteStr[16]; - if( m_targetNodeId != 0xff ) - { - snprintf( byteStr, sizeof(byteStr), " (Node=%d)", m_targetNodeId ); - str += byteStr; - } + char byteStr[16]; + if (m_targetNodeId != 0xff) + { + snprintf(byteStr, sizeof(byteStr), " (Node=%d)", m_targetNodeId); + str += byteStr; + } - str += ": "; + str += ": "; - for( uint32 i=0; i // Encapsulate the data inside a MultiInstance/Multicommand message //----------------------------------------------------------------------------- -void Msg::MultiEncap -( -) -{ - char str[256]; - if( m_buffer[3] != FUNC_ID_ZW_SEND_DATA ) - { - return; - } - - // Insert the encap header - if( ( m_flags & m_MultiChannel ) != 0 ) - { - // MultiChannel - for( uint32 i=m_length-1; i>=6; --i ) + void Msg::MultiEncap() { - m_buffer[i+4] = m_buffer[i]; - } + char str[256]; + if (m_buffer[3] != FUNC_ID_ZW_SEND_DATA) + { + return; + } - m_buffer[5] += 4; - m_buffer[6] = MultiInstance::StaticGetCommandClassId(); - m_buffer[7] = MultiInstance::MultiChannelCmd_Encap; - m_buffer[8] = 1; - m_buffer[9] = m_endPoint; - m_length += 4; - - snprintf( str, sizeof(str), "MultiChannel Encapsulated (instance=%d): %s", m_instance, m_logText.c_str() ); - m_logText = str; - } - else - { - // MultiInstance - for( uint32 i=m_length-1; i>=6; --i ) - { - m_buffer[i+3] = m_buffer[i]; - } + // Insert the encap header + if ((m_flags & m_MultiChannel) != 0) + { + // MultiChannel + for (uint32 i = m_length - 1; i >= 6; --i) + { + m_buffer[i + 4] = m_buffer[i]; + } + + m_buffer[5] += 4; + m_buffer[6] = Internal::CC::MultiInstance::StaticGetCommandClassId(); + m_buffer[7] = Internal::CC::MultiInstance::MultiChannelCmd_Encap; + m_buffer[8] = 1; + m_buffer[9] = m_endPoint; + m_length += 4; - m_buffer[5] += 3; - m_buffer[6] = MultiInstance::StaticGetCommandClassId(); - m_buffer[7] = MultiInstance::MultiInstanceCmd_Encap; - m_buffer[8] = m_instance; - m_length += 3; + snprintf(str, sizeof(str), "MultiChannel Encapsulated (instance=%d): %s", m_instance, m_logText.c_str()); + m_logText = str; + } + else + { + // MultiInstance + for (uint32 i = m_length - 1; i >= 6; --i) + { + m_buffer[i + 3] = m_buffer[i]; + } + + m_buffer[5] += 3; + m_buffer[6] = Internal::CC::MultiInstance::StaticGetCommandClassId(); + m_buffer[7] = Internal::CC::MultiInstance::MultiInstanceCmd_Encap; + m_buffer[8] = m_instance; + m_length += 3; - snprintf( str, sizeof(str), "MultiInstance Encapsulated (instance=%d): %s", m_instance, m_logText.c_str() ); - m_logText = str; - } -} + snprintf(str, sizeof(str), "MultiInstance Encapsulated (instance=%d): %s", m_instance, m_logText.c_str()); + m_logText = str; + } + } //----------------------------------------------------------------------------- // // Get a pointer to our driver //----------------------------------------------------------------------------- -Driver* Msg::GetDriver -( -)const -{ - return( Manager::Get()->GetDriver( m_homeId ) ); -} - - -uint8* Msg::GetBuffer -( -) -{ - Log::Write(LogLevel_Info, m_targetNodeId, "Encrypted Flag is %d", m_encrypted); - if (m_encrypted == false) - return m_buffer; - else - if (EncyrptBuffer(m_buffer, m_length, GetDriver(), GetDriver()->GetControllerNodeId(), m_targetNodeId, m_nonce, e_buffer)) { - return e_buffer; - } else { - Log::Write(LogLevel_Warning, m_targetNodeId, "Failed to Encrypt Packet"); - return NULL; + OpenZWave::Driver* Msg::GetDriver() const + { + return (Manager::Get()->GetDriver(m_homeId)); } -} + uint8* Msg::GetBuffer() + { + Log::Write(LogLevel_Info, m_targetNodeId, "Encrypted Flag is %d", m_encrypted); + if (m_encrypted == false) + return m_buffer; + else if (EncryptBuffer(m_buffer, m_length, GetDriver(), GetDriver()->GetControllerNodeId(), m_targetNodeId, m_nonce, e_buffer)) + { + return e_buffer; + } + else + { + Log::Write(LogLevel_Warning, m_targetNodeId, "Failed to Encrypt Packet"); + return NULL; + } + } + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/Msg.h b/cpp/src/Msg.h index 06f4203933..97f2a5ac2f 100644 --- a/cpp/src/Msg.h +++ b/cpp/src/Msg.h @@ -36,169 +36,220 @@ namespace OpenZWave { - class CommandClass; class Driver; - /** \brief Message object to be passed to and from devices on the Z-Wave network. - */ - class OPENZWAVE_EXPORT Msg + namespace Internal { - public: - enum MessageFlags + namespace CC { - m_MultiChannel = 0x01, // Indicate MultiChannel encapsulation - m_MultiInstance = 0x02, // Indicate MultiInstance encapsulation - }; + class CommandClass; + } - Msg( string const& _logtext, uint8 _targetNodeId, uint8 const _msgType, uint8 const _function, bool const _bCallbackRequired, bool const _bReplyRequired = true, uint8 const _expectedReply = 0, uint8 const _expectedCommandClassId = 0 ); - ~Msg(){} + /** \brief Message object to be passed to and from devices on the Z-Wave network. + */ + class OPENZWAVE_EXPORT Msg + { + public: + enum MessageFlags + { + m_MultiChannel = 0x01, // Indicate MultiChannel encapsulation + m_MultiInstance = 0x02, // Indicate MultiInstance encapsulation + }; - void SetInstance( CommandClass* _cc, uint8 const _instance ); // Used to enable wrapping with MultiInstance/MultiChannel during finalize. + Msg(string const& _logtext, uint8 _targetNodeId, uint8 const _msgType, uint8 const _function, bool const _bCallbackRequired, bool const _bReplyRequired = true, uint8 const _expectedReply = 0, uint8 const _expectedCommandClassId = 0); + ~Msg() + { + } - void Append( uint8 const _data ); - void AppendArray( const uint8* const _data, const uint8 _length ); - void Finalize(); - void UpdateCallbackId(); + void SetInstance(OpenZWave::Internal::CC::CommandClass * _cc, uint8 const _instance); // Used to enable wrapping with MultiInstance/MultiChannel during finalize. - /** - * \brief Identifies the Node ID of the "target" node (if any) for this function. - * \return Node ID of the target. - */ - uint8 GetTargetNodeId()const{ return m_targetNodeId; } + void Append(uint8 const _data); + void AppendArray(const uint8* const _data, const uint8 _length); + void Finalize(); + void UpdateCallbackId(); - /** - * \brief Identifies the Callback ID (if any) for this message. Callback ID is a value (OpenZWave uses sequential IDs) that - * helps the application associate message responses with the original message request. - * \return Callback ID for this message. - */ - uint8 GetCallbackId()const{ return m_callbackId; } - - /** - * \brief Identifies the expected reply type (if any) for this message. The expected reply is a function code...one - * of the FUNC_ID... values defined in Defs.h. Many Z-Wave functions generate responses with the same function code - * (for example, a FUNC_ID_ZW_GET_VERSION message generates a FUNC_ID_ZW_GET_VERSION response. But other functions - * generate a different response. FUNC_ID_ZW_SEND_DATA triggers several responses, but ultimately, a "Get" sent with - * this function should result in a FUNC_ID_APPLICATION_COMMAND_HANDLER response. - * \return Expected reply (function code) for this message. - */ - uint8 GetExpectedReply()const{ return m_expectedReply; } + /** + * \brief Identifies the Node ID of the "target" node (if any) for this function. + * \return Node ID of the target. + */ + uint8 GetTargetNodeId() const + { + return m_targetNodeId; + } - /** - * \brief Identifies the expected Command Class ID (if any) for this message. - * \return Expected command class ID for this message. - */ - uint8 GetExpectedCommandClassId()const{ return m_expectedCommandClassId; } + /** + * \brief Identifies the Callback ID (if any) for this message. Callback ID is a value (OpenZWave uses sequential IDs) that + * helps the application associate message responses with the original message request. + * \return Callback ID for this message. + */ + uint8 GetCallbackId() const + { + return m_callbackId; + } - /** - * \brief For messages that request a Report for a specified command class, identifies the expected Instance - * for the variable being obtained in the report. - * \return Expected Instance value for this message. - */ - uint8 GetExpectedInstance()const{ return m_instance; } + /** + * \brief Identifies the expected reply type (if any) for this message. The expected reply is a function code...one + * of the FUNC_ID... values defined in Defs.h. Many Z-Wave functions generate responses with the same function code + * (for example, a FUNC_ID_ZW_GET_VERSION message generates a FUNC_ID_ZW_GET_VERSION response. But other functions + * generate a different response. FUNC_ID_ZW_SEND_DATA triggers several responses, but ultimately, a "Get" sent with + * this function should result in a FUNC_ID_APPLICATION_COMMAND_HANDLER response. + * \return Expected reply (function code) for this message. + */ + uint8 GetExpectedReply() const + { + return m_expectedReply; + } - /** - * \brief For messages that request a Report for a specified command class, identifies the expected Index - * for the variable being obtained in the report. - * \return Expected Index value for this message. - */ -// uint8 GetExpectedIndex()const{ return m_expectedIndex; } - /** - * \brief get the LogText Associated with this message - * \return the LogText used during the constructor - */ - string GetLogText()const{ return m_logText; } + /** + * \brief Identifies the expected Command Class ID (if any) for this message. + * \return Expected command class ID for this message. + */ + uint8 GetExpectedCommandClassId() const + { + return m_expectedCommandClassId; + } - uint32 GetLength()const{ return m_encrypted == true ? m_length + 20 + 6 : m_length; } - uint8* GetBuffer(); - string GetAsString(); + /** + * \brief For messages that request a Report for a specified command class, identifies the expected Instance + * for the variable being obtained in the report. + * \return Expected Instance value for this message. + */ + uint8 GetExpectedInstance() const + { + return m_instance; + } - uint8 GetSendAttempts()const{ return m_sendAttempts; } - void SetSendAttempts( uint8 _count ){ m_sendAttempts = _count; } + /** + * \brief For messages that request a Report for a specified command class, identifies the expected Index + * for the variable being obtained in the report. + * \return Expected Index value for this message. + */ +// uint8 GetExpectedIndex()const{ return m_expectedIndex; } + /** + * \brief get the LogText Associated with this message + * \return the LogText used during the constructor + */ + string GetLogText() const + { + return m_logText; + } - uint8 GetMaxSendAttempts()const{ return m_maxSendAttempts; } - void SetMaxSendAttempts( uint8 _count ){ if( _count < MAX_MAX_TRIES ) m_maxSendAttempts = _count; } + uint32 GetLength() const + { + return m_encrypted == true ? m_length + 20 + 6 : m_length; + } + uint8* GetBuffer(); + string GetAsString(); - bool IsWakeUpNoMoreInformationCommand() - { - return( m_bFinal && (m_length==11) && (m_buffer[3]==0x13) && (m_buffer[6]==0x84) && (m_buffer[7]==0x08) ); - } - bool IsNoOperation() - { - return( m_bFinal && (m_length==11) && (m_buffer[3]==0x13) && (m_buffer[6]==0x00) && (m_buffer[7]==0x00) ); - } + uint8 GetSendAttempts() const + { + return m_sendAttempts; + } + void SetSendAttempts(uint8 _count) + { + m_sendAttempts = _count; + } - bool operator == ( Msg const& _other )const - { - if( m_bFinal && _other.m_bFinal ) - { - // Do not include the callback Id or checksum in the comparison. - uint8 length = m_length - (m_bCallbackRequired ? 2: 1 ); - return( !memcmp( m_buffer, _other.m_buffer, length ) ); - } - - return false; - } - uint8 GetSendingCommandClass() { - if (m_buffer[3] == 0x13) { - return m_buffer[6]; - } - return 0; - } - bool isEncrypted() { - return m_encrypted; - } - void setEncrypted() { - m_encrypted = true; - } - bool isNonceRecieved() { - return m_noncerecvd; - } - void setNonce(uint8 nonce[8]) { - memcpy(m_nonce, nonce, 8); - m_noncerecvd = true; - UpdateCallbackId(); - } - void clearNonce() { - memset((m_nonce), '\0', 8); - m_noncerecvd = false; - } - void SetHomeId(uint32 homeId) { m_homeId = homeId; }; + uint8 GetMaxSendAttempts() const + { + return m_maxSendAttempts; + } + void SetMaxSendAttempts(uint8 _count) + { + if (_count < MAX_MAX_TRIES) + m_maxSendAttempts = _count; + } - /** Returns a pointer to the driver (interface with a Z-Wave controller) - * associated with this node. - */ - Driver* GetDriver()const; - private: + bool IsWakeUpNoMoreInformationCommand() + { + return (m_bFinal && (m_length == 11) && (m_buffer[3] == 0x13) && (m_buffer[6] == 0x84) && (m_buffer[7] == 0x08)); + } + bool IsNoOperation() + { + return (m_bFinal && (m_length == 11) && (m_buffer[3] == 0x13) && (m_buffer[6] == 0x00) && (m_buffer[7] == 0x00)); + } + bool operator ==(Msg const& _other) const + { + if (m_bFinal && _other.m_bFinal) + { + // Do not include the callback Id or checksum in the comparison. + uint8 length = m_length - (m_bCallbackRequired ? 2 : 1); + return (!memcmp(m_buffer, _other.m_buffer, length)); + } - void MultiEncap(); // Encapsulate the data inside a MultiInstance/Multicommand message + return false; + } + uint8 GetSendingCommandClass() + { + if (m_buffer[3] == 0x13) + { + return m_buffer[6]; + } + return 0; + } + bool isEncrypted() + { + return m_encrypted; + } + void setEncrypted() + { + m_encrypted = true; + } + bool isNonceRecieved() + { + return m_noncerecvd; + } + void setNonce(uint8 nonce[8]) + { + memcpy(m_nonce, nonce, 8); + m_noncerecvd = true; + UpdateCallbackId(); + } + void clearNonce() + { + memset((m_nonce), '\0', 8); + m_noncerecvd = false; + } + void SetHomeId(uint32 homeId) + { + m_homeId = homeId; + } + ; - string m_logText; - bool m_bFinal; - bool m_bCallbackRequired; + /** Returns a pointer to the driver (interface with a Z-Wave controller) + * associated with this node. + */ + Driver* GetDriver() const; + private: - uint8 m_callbackId; - uint8 m_expectedReply; - uint8 m_expectedCommandClassId; - uint8 m_length; - uint8 m_buffer[256]; - uint8 e_buffer[256]; + void MultiEncap(); // Encapsulate the data inside a MultiInstance/Multicommand message + string m_logText; + bool m_bFinal; + bool m_bCallbackRequired; - uint8 m_targetNodeId; - uint8 m_sendAttempts; - uint8 m_maxSendAttempts; + uint8 m_callbackId; + uint8 m_expectedReply; + uint8 m_expectedCommandClassId; + uint8 m_length; + uint8 m_buffer[256]; + uint8 e_buffer[256]; - uint8 m_instance; - uint8 m_endPoint; // Endpoint to use if the message must be wrapped in a multiInstance or multiChannel command class - uint8 m_flags; + uint8 m_targetNodeId; + uint8 m_sendAttempts; + uint8 m_maxSendAttempts; - bool m_encrypted; - bool m_noncerecvd; - uint8 m_nonce[8]; - uint32 m_homeId; - static uint8 s_nextCallbackId; // counter to get a unique callback id - }; + uint8 m_instance; + uint8 m_endPoint; // Endpoint to use if the message must be wrapped in a multiInstance or multiChannel command class + uint8 m_flags; + bool m_encrypted; + bool m_noncerecvd; + uint8 m_nonce[8]; + uint32 m_homeId; + static uint8 s_nextCallbackId; // counter to get a unique callback id + }; + } // namespace Internal } // namespace OpenZWave #endif //_Msg_H diff --git a/cpp/src/Node.cpp b/cpp/src/Node.cpp index 362ab0752b..288cd9c790 100644 --- a/cpp/src/Node.cpp +++ b/cpp/src/Node.cpp @@ -27,7 +27,6 @@ #include - #include "Node.h" #include "Defs.h" #include "Group.h" @@ -86,183 +85,94 @@ using namespace OpenZWave; // Statics //----------------------------------------------------------------------------- bool Node::s_deviceClassesLoaded = false; -map Node::s_basicDeviceClasses; -map Node::s_genericDeviceClasses; -map Node::s_roleDeviceClasses; -map Node::s_deviceTypeClasses; -map Node::s_nodeTypes; +map Node::s_basicDeviceClasses; +map Node::s_genericDeviceClasses; +map Node::s_roleDeviceClasses; +map Node::s_deviceTypeClasses; +map Node::s_nodeTypes; static char const* c_queryStageNames[] = -{ - "None", - "ProtocolInfo", - "Probe", - "WakeUp", - "ManufacturerSpecific1", - "NodeInfo", - "NodePlusInfo", - "SecurityReport", - "ManufacturerSpecific2", - "Versions", - "Instances", - "Static", - "CacheLoad", - "Associations", - "Neighbors", - "Session", - "Dynamic", - "Configuration", - "Complete" -}; +{ "None", "ProtocolInfo", "Probe", "WakeUp", "ManufacturerSpecific1", "NodeInfo", "NodePlusInfo", "SecurityReport", "ManufacturerSpecific2", "Versions", "Instances", "Static", "CacheLoad", "Associations", "Neighbors", "Session", "Dynamic", "Configuration", "Complete" }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -Node::Node -( - uint32 const _homeId, - uint8 const _nodeId -): -m_queryStage( QueryStage_None ), -m_queryPending( false ), -m_queryConfiguration( false ), -m_queryRetries( 0 ), -m_protocolInfoReceived( false ), -m_basicprotocolInfoReceived( false ), -m_nodeInfoReceived( false ), -m_nodePlusInfoReceived( false ), -m_manufacturerSpecificClassReceived( false ), -m_nodeInfoSupported( true ), -m_refreshonNodeInfoFrame ( true ), -m_nodeAlive( true ), // assome live node -m_listening( true ), // assume we start out listening -m_frequentListening( false ), -m_beaming( false ), -m_routing( false ), -m_maxBaudRate( 0 ), -m_version( 0 ), -m_security( false ), -m_homeId( _homeId ), -m_nodeId( _nodeId ), -m_basic( 0 ), -m_generic( 0 ), -m_specific( 0 ), -m_type( "" ), -m_addingNode( false ), -m_manufacturerName( "" ), -m_productName( "" ), -m_nodeName( "" ), -m_location( "" ), -m_manufacturerId( 0 ), -m_productType( 0 ), -m_productId( 0 ), -m_deviceType( 0 ), -m_role( 0 ), -m_nodeType ( 0 ), -m_secured ( false ), -m_Product ( NULL ), -m_fileConfigRevision ( 0 ), -m_loadedConfigRevision ( 0 ), -m_latestConfigRevision ( 0 ), -m_values( new ValueStore() ), -m_sentCnt( 0 ), -m_sentFailed( 0 ), -m_retries( 0 ), -m_receivedCnt( 0 ), -m_receivedDups( 0 ), -m_receivedUnsolicited( 0 ), -m_lastRequestRTT( 0 ), -m_lastResponseRTT( 0 ), -m_averageRequestRTT( 0 ), -m_averageResponseRTT( 0 ), -m_quality( 0 ), -m_lastReceivedMessage(), -m_errors( 0 ), -m_txStatusReportSupported ( false ), -m_txTime( 0 ), -m_hops( 0 ), -m_ackChannel( 0 ), -m_lastTxChannel( 0 ), -m_routeScheme( (TXSTATUS_ROUTING_SCHEME)0 ), -m_routeUsed { }, -m_routeSpeed( (TXSTATUS_ROUTE_SPEED)0 ), -m_routeTries( 0 ), -m_lastFailedLinkFrom( 0 ), -m_lastFailedLinkTo( 0 ), -m_lastnonce ( 0 ) -{ - memset( m_neighbors, 0, sizeof(m_neighbors) ); - memset( m_nonces, 0, sizeof(m_nonces) ); - memset( m_rssi_1, 0, sizeof(m_rssi_1) ); - memset( m_rssi_2, 0, sizeof(m_rssi_2) ); - memset( m_rssi_3, 0, sizeof(m_rssi_3) ); - memset( m_rssi_4, 0, sizeof(m_rssi_4) ); - memset( m_rssi_5, 0, sizeof(m_rssi_5) ); +Node::Node(uint32 const _homeId, uint8 const _nodeId) : + m_queryStage(QueryStage_None), m_queryPending(false), m_queryConfiguration(false), m_queryRetries(0), m_protocolInfoReceived(false), m_basicprotocolInfoReceived(false), m_nodeInfoReceived(false), m_nodePlusInfoReceived(false), m_manufacturerSpecificClassReceived(false), m_nodeInfoSupported(true), m_refreshonNodeInfoFrame(true), m_nodeAlive(true), // assome live node + m_listening(true), // assume we start out listening + m_frequentListening(false), m_beaming(false), m_routing(false), m_maxBaudRate(0), m_version(0), m_security(false), m_homeId(_homeId), m_nodeId(_nodeId), m_basic(0), m_generic(0), m_specific(0), m_type(""), m_addingNode(false), m_manufacturerName(""), m_productName(""), m_nodeName(""), m_location(""), m_manufacturerId(0), m_productType(0), m_productId(0), m_deviceType(0), m_role(0), m_nodeType(0), m_secured(false), m_nodeCache( NULL), m_Product( NULL), m_fileConfigRevision(0), m_loadedConfigRevision( + 0), m_latestConfigRevision(0), m_values(new Internal::VC::ValueStore()), m_sentCnt(0), m_sentFailed(0), m_retries(0), m_receivedCnt(0), m_receivedDups(0), m_receivedUnsolicited(0), m_lastRequestRTT(0), m_lastResponseRTT(0), m_averageRequestRTT(0), m_averageResponseRTT(0), m_quality(0), m_lastReceivedMessage(), m_errors(0), m_txStatusReportSupported(false), m_txTime(0), m_hops(0), m_ackChannel(0), m_lastTxChannel(0), m_routeScheme((TXSTATUS_ROUTING_SCHEME) 0), m_routeUsed + { }, m_routeSpeed((TXSTATUS_ROUTE_SPEED) 0), m_routeTries(0), m_lastFailedLinkFrom(0), m_lastFailedLinkTo(0), m_lastnonce(0) +{ + memset(m_neighbors, 0, sizeof(m_neighbors)); + memset(m_nonces, 0, sizeof(m_nonces)); + memset(m_rssi_1, 0, sizeof(m_rssi_1)); + memset(m_rssi_2, 0, sizeof(m_rssi_2)); + memset(m_rssi_3, 0, sizeof(m_rssi_3)); + memset(m_rssi_4, 0, sizeof(m_rssi_4)); + memset(m_rssi_5, 0, sizeof(m_rssi_5)); /* Add NoOp Class */ - AddCommandClass( NoOperation::StaticGetCommandClassId() ); + AddCommandClass(Internal::CC::NoOperation::StaticGetCommandClassId()); /* Add ManufacturerSpecific Class */ - AddCommandClass( ManufacturerSpecific::StaticGetCommandClassId() ); + AddCommandClass(Internal::CC::ManufacturerSpecific::StaticGetCommandClassId()); } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -Node::~Node -( -) +Node::~Node() { // Remove any messages from queues - GetDriver()->RemoveQueues( m_nodeId ); + GetDriver()->RemoveQueues(m_nodeId); // Remove the values from the poll list - for( ValueStore::Iterator it = m_values->Begin(); it != m_values->End(); ++it ) + for (Internal::VC::ValueStore::Iterator it = m_values->Begin(); it != m_values->End(); ++it) { ValueID const& valueId = it->second->GetID(); - if( GetDriver()->isPolled( valueId ) ) + if (GetDriver()->isPolled(valueId)) { - GetDriver()->DisablePoll( valueId ); + GetDriver()->DisablePoll(valueId); } } - Scene::RemoveValues( m_homeId, m_nodeId ); + Internal::Scene::RemoveValues(m_homeId, m_nodeId); // Delete the values delete m_values; // Delete the command classes - while( !m_commandClassMap.empty() ) + while (!m_commandClassMap.empty()) { - map::iterator it = m_commandClassMap.begin(); + map::iterator it = m_commandClassMap.begin(); delete it->second; - m_commandClassMap.erase( it ); + m_commandClassMap.erase(it); } // Delete the groups - while( !m_groups.empty() ) + while (!m_groups.empty()) { - map::iterator it = m_groups.begin(); + map::iterator it = m_groups.begin(); delete it->second; - m_groups.erase( it ); + m_groups.erase(it); } // Delete the button map - while( !m_buttonMap.empty() ) + while (!m_buttonMap.empty()) { - map::iterator it = m_buttonMap.begin(); - m_buttonMap.erase( it ); + map::iterator it = m_buttonMap.begin(); + m_buttonMap.erase(it); } + delete m_nodeCache; } //----------------------------------------------------------------------------- // // Proceed through the initialisation process //----------------------------------------------------------------------------- -void Node::AdvanceQueries -( -) +void Node::AdvanceQueries() { // For OpenZWave to discover everything about a node, we have to follow a certain // order of queries, because the results of one stage may affect what is requested @@ -277,11 +187,11 @@ void Node::AdvanceQueries // assumptions are made in later code (RemoveMsg) that this is the case. This means // each stage is only visited once. - Log::Write( LogLevel_Detail, m_nodeId, "AdvanceQueries queryPending=%d queryRetries=%d queryStage=%s live=%d", m_queryPending, m_queryRetries, c_queryStageNames[m_queryStage], m_nodeAlive ); + Log::Write(LogLevel_Detail, m_nodeId, "AdvanceQueries queryPending=%d queryRetries=%d queryStage=%s live=%d", m_queryPending, m_queryRetries, c_queryStageNames[m_queryStage], m_nodeAlive); bool addQSC = false; // We only want to add a query stage complete if we did some work. - while( !m_queryPending && m_nodeAlive ) + while (!m_queryPending && m_nodeAlive) { - switch( m_queryStage ) + switch (m_queryStage) { case QueryStage_None: { @@ -293,18 +203,18 @@ void Node::AdvanceQueries case QueryStage_ProtocolInfo: { // determines, among other things, whether this node is a listener, its maximum baud rate and its device classes - if( !ProtocolInfoReceived() ) + if (!ProtocolInfoReceived()) { - Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_ProtocolInfo" ); - Msg* msg = new Msg( "Get Node Protocol Info", m_nodeId, REQUEST, FUNC_ID_ZW_GET_NODE_PROTOCOL_INFO, false ); - msg->Append( m_nodeId ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Query ); + Log::Write(LogLevel_Detail, m_nodeId, "QueryStage_ProtocolInfo"); + Internal::Msg* msg = new Internal::Msg("Get Node Protocol Info", m_nodeId, REQUEST, FUNC_ID_ZW_GET_NODE_PROTOCOL_INFO, false); + msg->Append(m_nodeId); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Query); m_queryPending = true; addQSC = true; } else { - // This stage has been done already, so move to the Neighbours stage + // This stage has been done already, so move to the Probe stage m_queryStage = QueryStage_Probe; m_queryRetries = 0; } @@ -312,17 +222,17 @@ void Node::AdvanceQueries } case QueryStage_Probe: { - Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_Probe" ); + Log::Write(LogLevel_Detail, m_nodeId, "QueryStage_Probe"); // // Send a NoOperation message to see if the node is awake // and alive. Based on the response or lack of response // will determine next step. // - NoOperation* noop = static_cast( GetCommandClass( NoOperation::StaticGetCommandClassId() ) ); + Internal::CC::NoOperation* noop = static_cast(GetCommandClass(Internal::CC::NoOperation::StaticGetCommandClassId())); /* don't Probe the Controller */ - if( GetDriver()->GetControllerNodeId() != m_nodeId ) + if (GetDriver()->GetControllerNodeId() != m_nodeId) { - noop->Set( true ); + noop->Set(true); m_queryPending = true; addQSC = true; } @@ -337,14 +247,14 @@ void Node::AdvanceQueries { // For sleeping devices other than controllers, we need to defer the usual requests until // we have told the device to send it's wake-up notifications to the PC controller. - Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_WakeUp" ); + Log::Write(LogLevel_Detail, m_nodeId, "QueryStage_WakeUp"); - WakeUp* wakeUp = static_cast( GetCommandClass( WakeUp::StaticGetCommandClassId() ) ); + Internal::CC::WakeUp* wakeUp = static_cast(GetCommandClass(Internal::CC::WakeUp::StaticGetCommandClassId())); // if this device is a "sleeping device" and not a controller and not a // FLiRS device. FLiRS will wake up when you send them something and they // don't seem to support Wakeup - if( wakeUp && !IsController() && !IsFrequentListeningDevice() ) + if (wakeUp && !IsController() && !IsFrequentListeningDevice()) { // start the process of requesting node state from this sleeping device wakeUp->Init(); @@ -364,16 +274,17 @@ void Node::AdvanceQueries // Obtain manufacturer, product type and product ID code from the node device // Manufacturer Specific data is requested before the other command class data so // that we can modify the supported command classes list through the product XML files. - Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_ManufacturerSpecific1" ); + Log::Write(LogLevel_Detail, m_nodeId, "QueryStage_ManufacturerSpecific1"); /* if its the Controller, then we can just load up the XML straight away */ - if( GetDriver()->GetControllerNodeId() == m_nodeId ) + if (GetDriver()->GetControllerNodeId() == m_nodeId) { - Log::Write( LogLevel_Detail, m_nodeId, "Load Controller Manufacturer Specific Config"); - ManufacturerSpecific* cc = static_cast( GetCommandClass( ManufacturerSpecific::StaticGetCommandClassId() ) ); - if( cc ) { + Log::Write(LogLevel_Detail, m_nodeId, "Load Controller Manufacturer Specific Config"); + Internal::CC::ManufacturerSpecific* cc = static_cast(GetCommandClass(Internal::CC::ManufacturerSpecific::StaticGetCommandClassId())); + if (cc) + { cc->SetInstance(1); - cc->SetProductDetails(GetDriver()->GetManufacturerId(), GetDriver()->GetProductType(), GetDriver()->GetProductId() ); + cc->SetProductDetails(GetDriver()->GetManufacturerId(), GetDriver()->GetProductType(), GetDriver()->GetProductId()); cc->LoadConfigXML(); } m_queryStage = QueryStage_NodeInfo; @@ -381,21 +292,21 @@ void Node::AdvanceQueries } else { - Log::Write( LogLevel_Detail, m_nodeId, "Checking for ManufacturerSpecific CC and Requesting values if present on this node"); + Log::Write(LogLevel_Detail, m_nodeId, "Checking for ManufacturerSpecific CC and Requesting values if present on this node"); /* if the ManufacturerSpecific CC was not specified in the ProtocolInfo packet for the Generic/Specific Device type (as part a Mandatory Command Class) * then this will fail, but we will retry in ManufacturerSpecific2 * * XXX TODO: This could probably be reworked a bit to make this a Mandatory CC for all devices regardless * of Generic/Specific Type. Then we can drop the Second ManufacturerSpecific QueryStage later. */ - ManufacturerSpecific* cc = static_cast( GetCommandClass( ManufacturerSpecific::StaticGetCommandClassId() ) ); - if( cc ) + Internal::CC::ManufacturerSpecific* cc = static_cast(GetCommandClass(Internal::CC::ManufacturerSpecific::StaticGetCommandClassId())); + if (cc) { cc->SetInstance(1); - m_queryPending = cc->RequestState( CommandClass::RequestFlag_Static, 1, Driver::MsgQueue_Query ); + m_queryPending = cc->RequestState(Internal::CC::CommandClass::RequestFlag_Static, 1, Driver::MsgQueue_Query); addQSC = m_queryPending; } - if( !m_queryPending ) + if (!m_queryPending) { m_queryStage = QueryStage_NodeInfo; m_queryRetries = 0; @@ -405,13 +316,13 @@ void Node::AdvanceQueries } case QueryStage_NodeInfo: { - if( !NodeInfoReceived() && m_nodeInfoSupported && (GetDriver()->GetControllerNodeId() != m_nodeId)) + if (!NodeInfoReceived() && m_nodeInfoSupported && (GetDriver()->GetControllerNodeId() != m_nodeId)) { // obtain from the node a list of command classes that it 1) supports and 2) controls (separated by a mark in the buffer) - Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_NodeInfo" ); - Msg* msg = new Msg( "Request Node Info", m_nodeId, REQUEST, FUNC_ID_ZW_REQUEST_NODE_INFO, false, true, FUNC_ID_ZW_APPLICATION_UPDATE ); - msg->Append( m_nodeId ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Query ); + Log::Write(LogLevel_Detail, m_nodeId, "QueryStage_NodeInfo"); + Internal::Msg* msg = new Internal::Msg("Request Node Info", m_nodeId, REQUEST, FUNC_ID_ZW_REQUEST_NODE_INFO, false, true, FUNC_ID_ZW_APPLICATION_UPDATE); + msg->Append(m_nodeId); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Query); m_queryPending = true; addQSC = true; } @@ -425,12 +336,12 @@ void Node::AdvanceQueries } case QueryStage_NodePlusInfo: { - Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_NodePlusInfo" ); - ZWavePlusInfo* pluscc = static_cast( GetCommandClass( ZWavePlusInfo::StaticGetCommandClassId() ) ); + Log::Write(LogLevel_Detail, m_nodeId, "QueryStage_NodePlusInfo"); + Internal::CC::ZWavePlusInfo* pluscc = static_cast(GetCommandClass(Internal::CC::ZWavePlusInfo::StaticGetCommandClassId())); - if ( pluscc ) + if (pluscc) { - m_queryPending = pluscc->RequestState( CommandClass::RequestFlag_Static, 1, Driver::MsgQueue_Query ); + m_queryPending = pluscc->RequestState(Internal::CC::CommandClass::RequestFlag_Static, 1, Driver::MsgQueue_Query); } if (m_queryPending) { @@ -450,11 +361,11 @@ void Node::AdvanceQueries /* For Devices that Support the Security Class, we have to request a list of * Command Classes that Require Security. */ - Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_SecurityReport" ); + Log::Write(LogLevel_Detail, m_nodeId, "QueryStage_SecurityReport"); - Security* seccc = static_cast( GetCommandClass( Security::StaticGetCommandClassId() ) ); + Internal::CC::Security* seccc = static_cast(GetCommandClass(Internal::CC::Security::StaticGetCommandClassId())); - if( seccc ) + if (seccc) { // start the process setting up the Security CommandClass m_queryPending = seccc->Init(); @@ -475,21 +386,21 @@ void Node::AdvanceQueries } case QueryStage_ManufacturerSpecific2: { - if( !m_manufacturerSpecificClassReceived ) + if (!m_manufacturerSpecificClassReceived) { // Obtain manufacturer, product type and product ID code from the node device // Manufacturer Specific data is requested before the other command class data so // that we can modify the supported command classes list through the product XML files. - Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_ManufacturerSpecific2" ); - ManufacturerSpecific* cc = static_cast( GetCommandClass( ManufacturerSpecific::StaticGetCommandClassId() ) ); + Log::Write(LogLevel_Detail, m_nodeId, "QueryStage_ManufacturerSpecific2"); + Internal::CC::ManufacturerSpecific* cc = static_cast(GetCommandClass(Internal::CC::ManufacturerSpecific::StaticGetCommandClassId())); /* don't do this if its the Controller Node */ - if( cc && (GetDriver()->GetControllerNodeId() != m_nodeId)) + if (cc && (GetDriver()->GetControllerNodeId() != m_nodeId)) { cc->SetInstance(1); - m_queryPending = cc->RequestState( CommandClass::RequestFlag_Static, 1, Driver::MsgQueue_Query ); + m_queryPending = cc->RequestState(Internal::CC::CommandClass::RequestFlag_Static, 1, Driver::MsgQueue_Query); addQSC = m_queryPending; } - if( !m_queryPending ) + if (!m_queryPending) { m_queryStage = QueryStage_Versions; m_queryRetries = 0; @@ -497,8 +408,8 @@ void Node::AdvanceQueries } else { - ManufacturerSpecific* cc = static_cast( GetCommandClass( ManufacturerSpecific::StaticGetCommandClassId() ) ); - if( cc ) + Internal::CC::ManufacturerSpecific* cc = static_cast(GetCommandClass(Internal::CC::ManufacturerSpecific::StaticGetCommandClassId())); + if (cc) { cc->SetInstance(1); cc->ReLoadConfigXML(); @@ -511,32 +422,32 @@ void Node::AdvanceQueries case QueryStage_Versions: { // Get the version information (if the device supports COMMAND_CLASS_VERSION - Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_Versions" ); - Version* vcc = static_cast( GetCommandClass( Version::StaticGetCommandClassId() ) ); - if( vcc ) + Log::Write(LogLevel_Detail, m_nodeId, "QueryStage_Versions"); + Internal::CC::Version* vcc = static_cast(GetCommandClass(Internal::CC::Version::StaticGetCommandClassId())); + if (vcc) { Log::Write(LogLevel_Info, m_nodeId, "Requesting Versions"); - for( map::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it ) + for (map::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it) { - CommandClass* cc = it->second; + Internal::CC::CommandClass* cc = it->second; Log::Write(LogLevel_Info, m_nodeId, "Requesting Versions for %s", cc->GetCommandClassName().c_str()); - if( cc->GetMaxVersion() > 1 ) + if (cc->GetMaxVersion() > 1) { // Get the version for each supported command class that // we have implemented at greater than version one. - m_queryPending |= vcc->RequestCommandClassVersion( it->second ); - } - else + m_queryPending |= vcc->RequestCommandClassVersion(it->second); + } + else { // set the Version to 1 - cc->SetVersion( 1 ); + cc->SetVersion(1); } } addQSC = m_queryPending; } // advance to Instances stage when finished - if( !m_queryPending ) + if (!m_queryPending) { m_queryStage = QueryStage_Instances; m_queryRetries = 0; @@ -546,24 +457,24 @@ void Node::AdvanceQueries case QueryStage_Instances: { // if the device at this node supports multiple instances, obtain a list of these instances - Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_Instances" ); - MultiInstance* micc = static_cast( GetCommandClass( MultiInstance::StaticGetCommandClassId() ) ); - if( micc ) + Log::Write(LogLevel_Detail, m_nodeId, "QueryStage_Instances"); + Internal::CC::MultiInstance* micc = static_cast(GetCommandClass(Internal::CC::MultiInstance::StaticGetCommandClassId())); + if (micc) { m_queryPending = micc->RequestInstances(); addQSC = m_queryPending; } // when done, advance to the Static stage - if( !m_queryPending ) + if (!m_queryPending) { m_queryStage = QueryStage_Static; m_queryRetries = 0; - Log::Write( LogLevel_Info, m_nodeId, "Essential node queries are complete" ); - Notification* notification = new Notification( Notification::Type_EssentialNodeQueriesComplete ); - notification->SetHomeAndNodeIds( m_homeId, m_nodeId ); - GetDriver()->QueueNotification( notification ); + Log::Write(LogLevel_Info, m_nodeId, "Essential node queries are complete"); + Notification* notification = new Notification(Notification::Type_EssentialNodeQueriesComplete); + notification->SetHomeAndNodeIds(m_homeId, m_nodeId); + GetDriver()->QueueNotification(notification); } break; } @@ -571,23 +482,26 @@ void Node::AdvanceQueries { // Request any other static values associated with each command class supported by this node // examples are supported thermostat operating modes, setpoints and fan modes - Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_Static" ); + Log::Write(LogLevel_Detail, m_nodeId, "QueryStage_Static"); /* Dont' do this for Controller Nodes */ - if ( GetDriver()->GetControllerNodeId() != m_nodeId ) { - for( map::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it ) + if (GetDriver()->GetControllerNodeId() != m_nodeId) + { + for (map::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it) { - if( !it->second->IsAfterMark() ) + if (!it->second->IsAfterMark()) + { + m_queryPending |= it->second->RequestStateForAllInstances(Internal::CC::CommandClass::RequestFlag_Static, Driver::MsgQueue_Query); + } + else { - m_queryPending |= it->second->RequestStateForAllInstances( CommandClass::RequestFlag_Static, Driver::MsgQueue_Query ); - } else { /* Controlling CC's might still need to retrieve some info */ - m_queryPending |= it->second->RequestStateForAllInstances( CommandClass::RequestFlag_AfterMark, Driver::MsgQueue_Query ); + m_queryPending |= it->second->RequestStateForAllInstances(Internal::CC::CommandClass::RequestFlag_AfterMark, Driver::MsgQueue_Query); } } } addQSC = m_queryPending; - if( !m_queryPending ) + if (!m_queryPending) { // when all (if any) static information has been retrieved, advance to the Associations stage // CacheLoad stage is for Nodes that are read in via the zw state file, as is skipped as we would @@ -597,24 +511,24 @@ void Node::AdvanceQueries } break; } - /* CacheLoad is where we start if we are loading a device from our zwcfg_*.xml file rather than - * a brand new device. - */ + /* CacheLoad is where we start if we are loading a device from our zwcfg_*.xml file rather than + * a brand new device. + */ case QueryStage_CacheLoad: { - Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_CacheLoad" ); - Log::Write( LogLevel_Info, GetNodeId(), "Loading Cache for node %d: Manufacturer=%s, Product=%s", GetNodeId(), GetManufacturerName().c_str(), GetProductName().c_str() ); - Log::Write( LogLevel_Info, GetNodeId(), "Node Identity Codes: %.4x:%.4x:%.4x", GetManufacturerId(), GetProductType(), GetProductId() ); + Log::Write(LogLevel_Detail, m_nodeId, "QueryStage_CacheLoad"); + Log::Write(LogLevel_Info, GetNodeId(), "Loading Cache for node %d: Manufacturer=%s, Product=%s", GetNodeId(), GetManufacturerName().c_str(), GetProductName().c_str()); + Log::Write(LogLevel_Info, GetNodeId(), "Node Identity Codes: %.4x:%.4x:%.4x", GetManufacturerId(), GetProductType(), GetProductId()); // // Send a NoOperation message to see if the node is awake // and alive. Based on the response or lack of response // will determine next step. Called here when configuration exists. // - NoOperation* noop = static_cast( GetCommandClass( NoOperation::StaticGetCommandClassId() ) ); + Internal::CC::NoOperation* noop = static_cast(GetCommandClass(Internal::CC::NoOperation::StaticGetCommandClassId())); /* Don't do this if its to the Controller */ - if( GetDriver()->GetControllerNodeId() != m_nodeId ) + if (GetDriver()->GetControllerNodeId() != m_nodeId) { - noop->Set( true ); + noop->Set(true); m_queryPending = true; addQSC = true; } @@ -628,20 +542,20 @@ void Node::AdvanceQueries case QueryStage_Associations: { // if this device supports COMMAND_CLASS_ASSOCIATION, determine to which groups this node belong - Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_Associations" ); - MultiChannelAssociation* macc = static_cast( GetCommandClass( MultiChannelAssociation::StaticGetCommandClassId() ) ); - if( macc ) + Log::Write(LogLevel_Detail, m_nodeId, "QueryStage_Associations"); + Internal::CC::MultiChannelAssociation* macc = static_cast(GetCommandClass(Internal::CC::MultiChannelAssociation::StaticGetCommandClassId())); + if (macc) { - macc->RequestAllGroups( 0 ); + macc->RequestAllGroups(0); m_queryPending = true; addQSC = true; } else { - Association* acc = static_cast( GetCommandClass( Association::StaticGetCommandClassId() ) ); - if( acc ) + Internal::CC::Association* acc = static_cast(GetCommandClass(Internal::CC::Association::StaticGetCommandClassId())); + if (acc) { - acc->RequestAllGroups( 0 ); + acc->RequestAllGroups(0); m_queryPending = true; addQSC = true; } @@ -657,8 +571,8 @@ void Node::AdvanceQueries case QueryStage_Neighbors: { // retrieves this node's neighbors and stores the neighbor bitmap in the node object - Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_Neighbors" ); - GetDriver()->RequestNodeNeighbors( m_nodeId, 0 ); + Log::Write(LogLevel_Detail, m_nodeId, "QueryStage_Neighbors"); + GetDriver()->RequestNodeNeighbors(m_nodeId, 0); m_queryPending = true; addQSC = true; break; @@ -667,16 +581,16 @@ void Node::AdvanceQueries { // Request the session values from the command classes in turn // examples of Session information are: current thermostat setpoints, node names and climate control schedules - Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_Session" ); - for( map::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it ) + Log::Write(LogLevel_Detail, m_nodeId, "QueryStage_Session"); + for (map::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it) { - if( !it->second->IsAfterMark() ) + if (!it->second->IsAfterMark()) { - m_queryPending |= it->second->RequestStateForAllInstances( CommandClass::RequestFlag_Session, Driver::MsgQueue_Query ); + m_queryPending |= it->second->RequestStateForAllInstances(Internal::CC::CommandClass::RequestFlag_Session, Driver::MsgQueue_Query); } } addQSC = m_queryPending; - if( !m_queryPending ) + if (!m_queryPending) { m_queryStage = QueryStage_Dynamic; m_queryRetries = 0; @@ -687,11 +601,11 @@ void Node::AdvanceQueries { // Request the dynamic values from the node, that can change at any time // Examples include on/off state, heating mode, temperature, etc. - Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_Dynamic" ); + Log::Write(LogLevel_Detail, m_nodeId, "QueryStage_Dynamic"); m_queryPending = RequestDynamicValues(); addQSC = m_queryPending; - if( !m_queryPending ) + if (!m_queryPending) { m_queryStage = QueryStage_Configuration; m_queryRetries = 0; @@ -701,17 +615,17 @@ void Node::AdvanceQueries case QueryStage_Configuration: { // Request the configurable parameter values from the node. - Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_Configuration" ); - if( m_queryConfiguration ) + Log::Write(LogLevel_Detail, m_nodeId, "QueryStage_Configuration"); + if (m_queryConfiguration) { - if( RequestAllConfigParams( 0 ) ) + if (RequestAllConfigParams(0)) { m_queryPending = true; addQSC = true; } m_queryConfiguration = false; } - if( !m_queryPending ) + if (!m_queryPending) { m_queryStage = QueryStage_Complete; m_queryRetries = 0; @@ -722,14 +636,14 @@ void Node::AdvanceQueries { ClearAddingNode(); // Notify the watchers that the queries are complete for this node - Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_Complete" ); - Notification* notification = new Notification( Notification::Type_NodeQueriesComplete ); - notification->SetHomeAndNodeIds( m_homeId, m_nodeId ); - GetDriver()->QueueNotification( notification ); + Log::Write(LogLevel_Detail, m_nodeId, "QueryStage_Complete"); + Notification* notification = new Notification(Notification::Type_NodeQueriesComplete); + notification->SetHomeAndNodeIds(m_homeId, m_nodeId); + GetDriver()->QueueNotification(notification); /* if its a sleeping node, this will send a NoMoreInformation Packet to the device */ - WakeUp* cc = static_cast( GetCommandClass( WakeUp::StaticGetCommandClassId() ) ); - if( cc ) + Internal::CC::WakeUp* cc = static_cast(GetCommandClass(Internal::CC::WakeUp::StaticGetCommandClassId())); + if (cc) { cc->SendPending(); } @@ -744,11 +658,11 @@ void Node::AdvanceQueries } } - if( addQSC && m_nodeAlive ) + if (addQSC && m_nodeAlive) { // Add a marker to the query queue so this advance method // gets called again once this stage has completed. - GetDriver()->SendQueryStageComplete( m_nodeId, m_queryStage ); + GetDriver()->SendQueryStageComplete(m_nodeId, m_queryStage); } } @@ -756,25 +670,22 @@ void Node::AdvanceQueries // // We are done with a stage in the query process //----------------------------------------------------------------------------- -void Node::QueryStageComplete -( - QueryStage const _stage -) +void Node::QueryStageComplete(QueryStage const _stage) { // Check that we are actually on the specified stage - if( _stage != m_queryStage ) + if (_stage != m_queryStage) { return; } - if( m_queryStage != QueryStage_Complete ) + if (m_queryStage != QueryStage_Complete) { // Move to the next stage m_queryPending = false; - m_queryStage = (QueryStage)( (uint32)m_queryStage + 1 ); - if( m_queryStage == QueryStage_CacheLoad ) + m_queryStage = (QueryStage) ((uint32) m_queryStage + 1); + if (m_queryStage == QueryStage_CacheLoad) { - m_queryStage = (QueryStage)( (uint32)m_queryStage + 1 ); + m_queryStage = (QueryStage) ((uint32) m_queryStage + 1); } m_queryRetries = 0; } @@ -784,56 +695,50 @@ void Node::QueryStageComplete // // Retry a stage up to the specified maximum //----------------------------------------------------------------------------- -void Node::QueryStageRetry -( - QueryStage const _stage, - uint8 const _maxAttempts // = 0 -) +void Node::QueryStageRetry(QueryStage const _stage, uint8 const _maxAttempts // = 0 + ) { - Log::Write( LogLevel_Info, m_nodeId, "QueryStageRetry stage %s requested stage %s max %d retries %d pending %d", c_queryStageNames[_stage], c_queryStageNames[m_queryStage], _maxAttempts, m_queryRetries, m_queryPending); + Log::Write(LogLevel_Info, m_nodeId, "QueryStageRetry stage %s requested stage %s max %d retries %d pending %d", c_queryStageNames[_stage], c_queryStageNames[m_queryStage], _maxAttempts, m_queryRetries, m_queryPending); // Check that we are actually on the specified stage - if( _stage != m_queryStage ) + if (_stage != m_queryStage) { return; } m_queryPending = false; - if( _maxAttempts && ( ++m_queryRetries >= _maxAttempts ) ) + if (_maxAttempts && (++m_queryRetries >= _maxAttempts)) { m_queryRetries = 0; // We've retried too many times. Move to the next stage but only if // we aren't in any of the probe stages. - if( m_queryStage != QueryStage_Probe && m_queryStage != QueryStage_CacheLoad ) + if (m_queryStage != QueryStage_Probe && m_queryStage != QueryStage_CacheLoad) { - m_queryStage = (Node::QueryStage)( (uint32)(m_queryStage + 1) ); + m_queryStage = (Node::QueryStage) ((uint32) (m_queryStage + 1)); } } // Repeat the current query stage - GetDriver()->RetryQueryStageComplete( m_nodeId, m_queryStage ); + GetDriver()->RetryQueryStageComplete(m_nodeId, m_queryStage); } //----------------------------------------------------------------------------- // // Set the query stage (but only to an earlier stage) //----------------------------------------------------------------------------- -void Node::SetQueryStage -( - QueryStage const _stage, - bool const _advance // = true -) +void Node::SetQueryStage(QueryStage const _stage, bool const _advance // = true + ) { - if( (int)_stage < (int)m_queryStage ) + if ((int) _stage < (int) m_queryStage) { m_queryStage = _stage; m_queryPending = false; - if( QueryStage_Configuration == _stage ) + if (QueryStage_Configuration == _stage) { m_queryConfiguration = true; } } - if( _advance ) + if (_advance) { AdvanceQueries(); } @@ -843,10 +748,7 @@ void Node::SetQueryStage // // Gets the query stage name //----------------------------------------------------------------------------- -string Node::GetQueryStageName -( - QueryStage const _stage -) +string Node::GetQueryStageName(QueryStage const _stage) { return c_queryStageNames[_stage]; } @@ -855,28 +757,25 @@ string Node::GetQueryStageName // // Gets the neighbors of a node //----------------------------------------------------------------------------- -uint32 Node::GetNeighbors -( - uint8** o_neighbors -) +uint32 Node::GetNeighbors(uint8** o_neighbors) { // determine how many neighbors there are int i; uint32 numNeighbors = 0; - if( m_queryStage < QueryStage_Session ) + if (m_queryStage < QueryStage_Session) { *o_neighbors = NULL; return 0; } - for( i = 0; i < 29; i++ ) + for (i = 0; i < 29; i++) { - for( unsigned char mask = 0x80; mask != 0; mask >>= 1 ) - if( ( m_neighbors[i] & mask ) != 0 ) + for (unsigned char mask = 0x80; mask != 0; mask >>= 1) + if ((m_neighbors[i] & mask) != 0) numNeighbors++; } // handle the possibility that no neighbors are reported - if( !numNeighbors ) + if (!numNeighbors) { *o_neighbors = NULL; return 0; @@ -885,12 +784,12 @@ uint32 Node::GetNeighbors // create and populate an array with neighbor node ids uint8* neighbors = new uint8[numNeighbors]; uint32 index = 0; - for( int by=0; by<29; by++ ) + for (int by = 0; by < 29; by++) { - for( int bi=0; bi<8; bi++ ) + for (int bi = 0; bi < 8; bi++) { - if( (m_neighbors[by] & ( 0x01< // Read the node config from the OZW Cache File... //----------------------------------------------------------------------------- -void Node::ReadXML -( - TiXmlElement const* _node -) +void Node::ReadXML(TiXmlElement const* _node) { char const* str; int intVal; - str = _node->Attribute( "query_stage" ); - if( str ) + str = _node->Attribute("query_stage"); + if (str) { - // After restoring state from a file, we need to at least refresh the association, session and dynamic values. - QueryStage queryStage = QueryStage_Associations; - for( uint32 i=0; i<(uint32)QueryStage_Associations; ++i ) + // After restoring state from a file, we need to at least refresh the session and dynamic values. + QueryStage queryStage = QueryStage_Session; + for (uint32 i = 0; i < (uint32) QueryStage_Session; ++i) { - if( !strcmp( str, c_queryStageNames[i] ) ) + if (!strcmp(str, c_queryStageNames[i])) { - queryStage = (QueryStage)i; + queryStage = (QueryStage) i; break; } } @@ -933,219 +829,240 @@ void Node::ReadXML m_queryStage = queryStage; m_queryPending = false; - if( QueryStage_Configuration == queryStage ) + if (QueryStage_Configuration == queryStage) { m_queryConfiguration = true; } } - if( m_queryStage != QueryStage_None ) + if (m_queryStage != QueryStage_None) { - if( m_queryStage > QueryStage_ProtocolInfo ) + if (m_queryStage > QueryStage_ProtocolInfo) { // Notify the watchers of the protocol info. // We do the notification here so that it gets into the queue ahead of // any other notifications generated by adding command classes etc. m_protocolInfoReceived = true; - Notification* notification = new Notification( Notification::Type_NodeProtocolInfo ); - notification->SetHomeAndNodeIds( m_homeId, m_nodeId ); - GetDriver()->QueueNotification( notification ); + Notification* notification = new Notification(Notification::Type_NodeProtocolInfo); + notification->SetHomeAndNodeIds(m_homeId, m_nodeId); + GetDriver()->QueueNotification(notification); } - if( m_queryStage > QueryStage_NodeInfo ) + if (m_queryStage > QueryStage_NodeInfo) { m_nodeInfoReceived = true; } - if( m_queryStage > QueryStage_Instances ) + if (m_queryStage > QueryStage_Instances) + { + Notification* notification = new Notification(Notification::Type_EssentialNodeQueriesComplete); + notification->SetHomeAndNodeIds(m_homeId, m_nodeId); + GetDriver()->QueueNotification(notification); + } + if (m_queryStage > QueryStage_CacheLoad) { - Notification* notification = new Notification( Notification::Type_EssentialNodeQueriesComplete ); - notification->SetHomeAndNodeIds( m_homeId, m_nodeId ); - GetDriver()->QueueNotification( notification ); + m_nodeCache = _node->Clone(); } } - str = _node->Attribute( "name" ); - if( str ) + str = _node->Attribute("name"); + if (str) { m_nodeName = str; } - str = _node->Attribute( "location" ); - if( str ) + str = _node->Attribute("location"); + if (str) { m_location = str; } - if( TIXML_SUCCESS == _node->QueryIntAttribute( "basic", &intVal ) ) + if (TIXML_SUCCESS == _node->QueryIntAttribute("basic", &intVal)) { - m_basic = (uint8)intVal; + m_basic = (uint8) intVal; } - if( TIXML_SUCCESS == _node->QueryIntAttribute( "generic", &intVal ) ) + if (TIXML_SUCCESS == _node->QueryIntAttribute("generic", &intVal)) { - m_generic = (uint8)intVal; + m_generic = (uint8) intVal; } - if( TIXML_SUCCESS == _node->QueryIntAttribute( "specific", &intVal ) ) + if (TIXML_SUCCESS == _node->QueryIntAttribute("specific", &intVal)) { - m_specific = (uint8)intVal; + m_specific = (uint8) intVal; } - if( TIXML_SUCCESS == _node->QueryIntAttribute( "roletype", &intVal ) ) + if (TIXML_SUCCESS == _node->QueryIntAttribute("roletype", &intVal)) { - m_role = (uint8)intVal; + m_role = (uint8) intVal; m_nodePlusInfoReceived = true; } - if( TIXML_SUCCESS == _node->QueryIntAttribute( "devicetype", &intVal ) ) + if (TIXML_SUCCESS == _node->QueryIntAttribute("devicetype", &intVal)) { - m_deviceType = (uint16)intVal; + m_deviceType = (uint16) intVal; m_nodePlusInfoReceived = true; } - if (TIXML_SUCCESS == _node->QueryIntAttribute ( "nodetype", &intVal ) ) + if (TIXML_SUCCESS == _node->QueryIntAttribute("nodetype", &intVal)) { - m_nodeType = (uint8)intVal; + m_nodeType = (uint8) intVal; m_nodePlusInfoReceived = true; } - str = _node->Attribute( "type" ); - if( str ) + str = _node->Attribute("type"); + if (str) { m_type = str; } m_listening = true; - str = _node->Attribute( "listening" ); - if( str ) + str = _node->Attribute("listening"); + if (str) { - m_listening = !strcmp( str, "true" ); + m_listening = !strcmp(str, "true"); } m_frequentListening = false; - str = _node->Attribute( "frequentListening" ); - if( str ) + str = _node->Attribute("frequentListening"); + if (str) { - m_frequentListening = !strcmp( str, "true" ); + m_frequentListening = !strcmp(str, "true"); } m_beaming = false; - str = _node->Attribute( "beaming" ); - if( str ) + str = _node->Attribute("beaming"); + if (str) { - m_beaming = !strcmp( str, "true" ); + m_beaming = !strcmp(str, "true"); } m_routing = true; - str = _node->Attribute( "routing" ); - if( str ) + str = _node->Attribute("routing"); + if (str) { - m_routing = !strcmp( str, "true" ); + m_routing = !strcmp(str, "true"); } m_maxBaudRate = 0; - if( TIXML_SUCCESS == _node->QueryIntAttribute( "max_baud_rate", &intVal ) ) + if (TIXML_SUCCESS == _node->QueryIntAttribute("max_baud_rate", &intVal)) { - m_maxBaudRate = (uint32)intVal; + m_maxBaudRate = (uint32) intVal; } m_version = 0; - if( TIXML_SUCCESS == _node->QueryIntAttribute( "version", &intVal ) ) + if (TIXML_SUCCESS == _node->QueryIntAttribute("version", &intVal)) { - m_version = (uint8)intVal; + m_version = (uint8) intVal; } m_security = false; - str = _node->Attribute( "security" ); - if( str ) + str = _node->Attribute("security"); + if (str) { - m_security = !strcmp( str, "true" ); + m_security = !strcmp(str, "true"); } m_secured = false; - str = _node->Attribute( "secured" ); - if( str ) + str = _node->Attribute("secured"); + if (str) { - m_secured = !strcmp( str, "true" ); + m_secured = !strcmp(str, "true"); } m_nodeInfoSupported = true; - str = _node->Attribute( "nodeinfosupported" ); - if( str ) + str = _node->Attribute("nodeinfosupported"); + if (str) { - m_nodeInfoSupported = !strcmp( str, "true" ); + m_nodeInfoSupported = !strcmp(str, "true"); } m_refreshonNodeInfoFrame = true; - str = _node->Attribute( "refreshonnodeinfoframe" ); - if ( str ) - m_refreshonNodeInfoFrame = !strcmp (str, "true" ); - + str = _node->Attribute("refreshonnodeinfoframe"); + if (str) + m_refreshonNodeInfoFrame = !strcmp(str, "true"); /* this is the revision of the config file that was present when we created the cache */ - str = _node->Attribute( "configrevision" ); - if ( str ) + str = _node->Attribute("configrevision"); + if (str) this->setLoadedConfigRevision(atol(str)); else this->setLoadedConfigRevision(0); - // Read the manufacturer info and create the command classes TiXmlElement const* child = _node->FirstChildElement(); - while( child ) + while (child) { str = child->Value(); - if( str ) + if (str) { - if( !strcmp( str, "CommandClasses" ) ) + if (!strcmp(str, "Neighbors")) { - ReadCommandClassesXML( child ); + TiXmlNode const *NeighborList = child->FirstChild(); + char const *neighbors = NeighborList->Value(); + int i = 0; + char* pos = const_cast(neighbors); + while (*pos && i < 29) + { + m_neighbors[i] = strtol(pos, &pos, 10); + if ((*pos) == ',') + { + ++pos; + ++i; + } + } } - else if( !strcmp( str, "Manufacturer" ) ) + else if (!strcmp(str, "CommandClasses")) + { + ReadCommandClassesXML(child); + } + else if (!strcmp(str, "Manufacturer")) { uint16 manufacturerId = 0; uint16 productType = 0; uint16 productId = 0; - str = child->Attribute( "id" ); - if( str ) + str = child->Attribute("id"); + if (str) { - manufacturerId = (uint16_t)(strtol(str, NULL, 16) & 0xFFFF); + manufacturerId = (uint16_t) (strtol(str, NULL, 16) & 0xFFFF); } - str = child->Attribute( "name" ); - if( str ) + str = child->Attribute("name"); + if (str) { m_manufacturerName = str; } TiXmlElement const* product = child->FirstChildElement(); - if( !strcmp( product->Value(), "Product" ) ) + if (!strcmp(product->Value(), "Product")) { - str = product->Attribute( "type" ); - if( str ) + str = product->Attribute("type"); + if (str) { - productType = (uint16_t)(strtol(str, NULL, 16) & 0xFFFF); + productType = (uint16_t) (strtol(str, NULL, 16) & 0xFFFF); } - str = product->Attribute( "id" ); - if( str ) + str = product->Attribute("id"); + if (str) { - productId = (uint16_t)(strtol(str, NULL, 16) & 0xFFFF); + productId = (uint16_t) (strtol(str, NULL, 16) & 0xFFFF); } - str = product->Attribute( "name" ); - if( str ) + str = product->Attribute("name"); + if (str) { m_productName = str; } - ManufacturerSpecific* cc = static_cast( GetCommandClass( ManufacturerSpecific::StaticGetCommandClassId() ) ); + Internal::CC::ManufacturerSpecific* cc = static_cast(GetCommandClass(Internal::CC::ManufacturerSpecific::StaticGetCommandClassId())); /* don't do this if its the Controller Node */ - if( cc ) { + if (cc) + { cc->SetProductDetails(manufacturerId, productType, productId); cc->setLoadedConfigRevision(m_loadedConfigRevision); - } else { + } + else + { Log::Write(LogLevel_Warning, GetNodeId(), "ManufacturerSpecific Class not loaded for ReadXML"); } @@ -1158,12 +1075,12 @@ void Node::ReadXML child = child->NextSiblingElement(); } - if( m_nodeName.length() > 0 || m_location.length() > 0 || m_manufacturerId > 0 ) + if (m_nodeName.length() > 0 || m_location.length() > 0 || m_manufacturerId > 0) { // Notify the watchers of the name changes - Notification* notification = new Notification( Notification::Type_NodeNaming ); - notification->SetHomeAndNodeIds( m_homeId, m_nodeId ); - GetDriver()->QueueNotification( notification ); + Notification* notification = new Notification(Notification::Type_NodeNaming); + notification->SetHomeAndNodeIds(m_homeId, m_nodeId); + GetDriver()->QueueNotification(notification); } } @@ -1172,57 +1089,57 @@ void Node::ReadXML // Read the device's protocol configuration from a device config file (Not // cache) //----------------------------------------------------------------------------- -void Node::ReadDeviceProtocolXML -( - TiXmlElement const* _ccsElement -) +void Node::ReadDeviceProtocolXML(TiXmlElement const* _ccsElement) { char const *str = _ccsElement->Attribute("Revision"); - if ( str ) { + if (str) + { /* as we are loading the Node from the device config file, both the * File and Loaded Revisions will be the same */ this->setFileConfigRevision(atol(str)); this->setLoadedConfigRevision(m_fileConfigRevision); Log::Write(LogLevel_Info, GetNodeId(), " Configuration File Revision is %d", m_fileConfigRevision); - } else { + } + else + { this->setFileConfigRevision(0); this->setLoadedConfigRevision(m_fileConfigRevision); } TiXmlElement const* ccElement = _ccsElement->FirstChildElement(); - while( ccElement ) + while (ccElement) { str = ccElement->Value(); - if( str && !strcmp( str, "Protocol" ) ) + if (str && !strcmp(str, "Protocol")) { - str = ccElement->Attribute( "nodeinfosupported" ); - if( str ) + str = ccElement->Attribute("nodeinfosupported"); + if (str) { - m_nodeInfoSupported = !strcmp( str, "true" ); + m_nodeInfoSupported = !strcmp(str, "true"); } - str = ccElement->Attribute( "refreshonnodeinfoframe" ); - if ( str ) + str = ccElement->Attribute("refreshonnodeinfoframe"); + if (str) { - m_refreshonNodeInfoFrame = !strcmp( str, "true" ); + m_refreshonNodeInfoFrame = !strcmp(str, "true"); } // Some controllers support API calls that aren't advertised in their returned data. // So provide a way to manipulate the returned data to reflect reality. TiXmlElement const* childElement = _ccsElement->FirstChildElement(); - while( childElement ) + while (childElement) { str = childElement->Value(); - if( str && !strcmp( str, "APIcall" ) ) + if (str && !strcmp(str, "APIcall")) { - char const* funcStr = childElement->Attribute( "function" ); + char const* funcStr = childElement->Attribute("function"); char *p; - uint8 func = (uint8)strtol( funcStr, &p, 16 ); - if( p != funcStr ) + uint8 func = (uint8) strtol(funcStr, &p, 16); + if (p != funcStr) { - char const* presStr = ccElement->Attribute( "present" ); - GetDriver()->SetAPICall( func, !strcmp( presStr, "true" ) ); + char const* presStr = ccElement->Attribute("present"); + GetDriver()->SetAPICall(func, !strcmp(presStr, "true")); } } childElement = childElement->NextSiblingElement(); @@ -1237,56 +1154,54 @@ void Node::ReadDeviceProtocolXML // // Read the command classes from XML //----------------------------------------------------------------------------- -void Node::ReadCommandClassesXML -( - TiXmlElement const* _ccsElement -) +void Node::ReadCommandClassesXML(TiXmlElement const* _ccsElement) { char const* str; int32 intVal; TiXmlElement const* ccElement = _ccsElement->FirstChildElement(); - while( ccElement ) + while (ccElement) { str = ccElement->Value(); - if( str && !strcmp( str, "CommandClass" ) ) + if (str && !strcmp(str, "CommandClass")) { - if( TIXML_SUCCESS == ccElement->QueryIntAttribute( "id", &intVal ) ) + if (TIXML_SUCCESS == ccElement->QueryIntAttribute("id", &intVal)) { - uint8 id = (uint8)intVal; + uint8 id = (uint8) intVal; // Check whether this command class is to be removed (product XMLs might // request this if a class is not implemented properly by the device) bool remove = false; - char const* action = ccElement->Attribute( "action" ); - if( action && !strcasecmp( action, "remove" ) ) + char const* action = ccElement->Attribute("action"); + if (action && !strcasecmp(action, "remove")) { remove = true; } - CommandClass* cc = GetCommandClass( id ); - if( remove ) + Internal::CC::CommandClass* cc = GetCommandClass(id); + if (remove) { // Remove support for the command class - RemoveCommandClass( id ); + RemoveCommandClass(id); } else { - if( NULL == cc ) + if ( NULL == cc) { - if (Security::StaticGetCommandClassId() == id && !GetDriver()->isNetworkKeySet()) { + if (Internal::CC::Security::StaticGetCommandClassId() == id && !GetDriver()->isNetworkKeySet()) + { Log::Write(LogLevel_Warning, "Security Command Class cannot be Loaded. NetworkKey is not set"); ccElement = ccElement->NextSiblingElement(); continue; } // Command class support does not exist yet, so we create it - cc = AddCommandClass( id ); + cc = AddCommandClass(id); } - if( NULL != cc ) + if ( NULL != cc) { - cc->ReadXML( ccElement ); + cc->ReadXML(ccElement); } } } @@ -1300,132 +1215,149 @@ void Node::ReadCommandClassesXML // // Save the static node configuration data //----------------------------------------------------------------------------- -void Node::WriteXML -( - TiXmlElement* _driverElement -) +void Node::WriteXML(TiXmlElement* _driverElement) { + if (m_queryStage <= QueryStage_CacheLoad) + { + /* Just return our cached copy of the "Cache" as nothing new should be here */ + _driverElement->LinkEndChild(m_nodeCache->Clone()); + return; + } + char str[32]; - TiXmlElement* nodeElement = new TiXmlElement( "Node" ); - _driverElement->LinkEndChild( nodeElement ); + TiXmlElement* nodeElement = new TiXmlElement("Node"); + _driverElement->LinkEndChild(nodeElement); - snprintf( str, 32, "%d", m_nodeId ); - nodeElement->SetAttribute( "id", str ); + snprintf(str, 32, "%d", m_nodeId); + nodeElement->SetAttribute("id", str); - nodeElement->SetAttribute( "name", m_nodeName.c_str() ); - nodeElement->SetAttribute( "location", m_location.c_str() ); + nodeElement->SetAttribute("name", m_nodeName.c_str()); + nodeElement->SetAttribute("location", m_location.c_str()); - snprintf( str, 32, "%d", m_basic ); - nodeElement->SetAttribute( "basic", str ); + snprintf(str, 32, "%d", m_basic); + nodeElement->SetAttribute("basic", str); - snprintf( str, 32, "%d", m_generic ); - nodeElement->SetAttribute( "generic", str ); + snprintf(str, 32, "%d", m_generic); + nodeElement->SetAttribute("generic", str); - snprintf( str, 32, "%d", m_specific ); - nodeElement->SetAttribute( "specific", str ); + snprintf(str, 32, "%d", m_specific); + nodeElement->SetAttribute("specific", str); - if( m_nodePlusInfoReceived ) + if (m_nodePlusInfoReceived) { - snprintf( str, 32, "%d", m_role ); - nodeElement->SetAttribute( "roletype", str ); + snprintf(str, 32, "%d", m_role); + nodeElement->SetAttribute("roletype", str); - snprintf( str, 32, "%d", m_deviceType ); - nodeElement->SetAttribute( "devicetype", str ); + snprintf(str, 32, "%d", m_deviceType); + nodeElement->SetAttribute("devicetype", str); - snprintf( str, 32, "%d", m_nodeType ); - nodeElement->SetAttribute ( "nodetype", str ); + snprintf(str, 32, "%d", m_nodeType); + nodeElement->SetAttribute("nodetype", str); } - nodeElement->SetAttribute( "type", m_type.c_str() ); + nodeElement->SetAttribute("type", m_type.c_str()); - nodeElement->SetAttribute( "listening", m_listening ? "true" : "false" ); - nodeElement->SetAttribute( "frequentListening", m_frequentListening ? "true" : "false" ); - nodeElement->SetAttribute( "beaming", m_beaming ? "true" : "false" ); - nodeElement->SetAttribute( "routing", m_routing ? "true" : "false" ); + nodeElement->SetAttribute("listening", m_listening ? "true" : "false"); + nodeElement->SetAttribute("frequentListening", m_frequentListening ? "true" : "false"); + nodeElement->SetAttribute("beaming", m_beaming ? "true" : "false"); + nodeElement->SetAttribute("routing", m_routing ? "true" : "false"); - snprintf( str, 32, "%d", m_maxBaudRate ); - nodeElement->SetAttribute( "max_baud_rate", str ); + snprintf(str, 32, "%d", m_maxBaudRate); + nodeElement->SetAttribute("max_baud_rate", str); - snprintf( str, 32, "%d", m_version ); - nodeElement->SetAttribute( "version", str ); + snprintf(str, 32, "%d", m_version); + nodeElement->SetAttribute("version", str); - if( m_security ) + if (m_security) { - nodeElement->SetAttribute( "security", "true" ); + nodeElement->SetAttribute("security", "true"); } - if( m_secured ) + if (m_secured) { - nodeElement->SetAttribute( "secured", "true" ); + nodeElement->SetAttribute("secured", "true"); } - - if( !m_nodeInfoSupported ) + if (!m_nodeInfoSupported) { - nodeElement->SetAttribute( "nodeinfosupported", "false" ); + nodeElement->SetAttribute("nodeinfosupported", "false"); } if (!m_refreshonNodeInfoFrame) { - nodeElement->SetAttribute( "refreshonnodeinfoframe", "false" ); + nodeElement->SetAttribute("refreshonnodeinfoframe", "false"); } - snprintf( str, 32, "%d", m_loadedConfigRevision); - nodeElement->SetAttribute( "configrevision", str ); + snprintf(str, 32, "%d", m_loadedConfigRevision); + nodeElement->SetAttribute("configrevision", str); - nodeElement->SetAttribute( "query_stage", c_queryStageNames[m_queryStage] ); + nodeElement->SetAttribute("query_stage", c_queryStageNames[m_queryStage]); + + TiXmlElement* neighborElement = new TiXmlElement("Neighbors"); + nodeElement->LinkEndChild(neighborElement); + { + std::string NeighborList; + for (int i = 0; i < 29; i++) + { + if ((i > 0) && (i != 29)) + NeighborList.append(","); + NeighborList.append(Internal::intToString(m_neighbors[i])); + } + TiXmlText* textElement = new TiXmlText(NeighborList.c_str()); + neighborElement->LinkEndChild(textElement); + } // Write the manufacturer and product data in the same format // as used in the ManyfacturerSpecfic.xml file. This will // allow new devices to be added via a simple cut and paste. - TiXmlElement* manufacturerElement = new TiXmlElement( "Manufacturer" ); - nodeElement->LinkEndChild( manufacturerElement ); + TiXmlElement* manufacturerElement = new TiXmlElement("Manufacturer"); + nodeElement->LinkEndChild(manufacturerElement); /* this should be written in hex to avoid confusion... */ { std::stringstream ss; ss << std::hex << m_manufacturerId; - manufacturerElement->SetAttribute( "id", ss.str().c_str() ); + manufacturerElement->SetAttribute("id", ss.str().c_str()); } - manufacturerElement->SetAttribute( "name", m_manufacturerName.c_str() ); + manufacturerElement->SetAttribute("name", m_manufacturerName.c_str()); - TiXmlElement* productElement = new TiXmlElement( "Product" ); - manufacturerElement->LinkEndChild( productElement ); + TiXmlElement* productElement = new TiXmlElement("Product"); + manufacturerElement->LinkEndChild(productElement); /* this should be written in hex to avoid confusion... */ { std::stringstream ss; ss << std::hex << m_productType; - productElement->SetAttribute( "type", ss.str().c_str() ); + productElement->SetAttribute("type", ss.str().c_str()); } /* this should be written in hex to avoid confusion... */ { std::stringstream ss; ss << std::hex << m_productId; - productElement->SetAttribute( "id", ss.str().c_str() ); + productElement->SetAttribute("id", ss.str().c_str()); } - productElement->SetAttribute( "name", m_productName.c_str() ); + productElement->SetAttribute("name", m_productName.c_str()); // Write the MetaData out - TiXmlElement* mdElement = new TiXmlElement( "MetaData" ); - productElement->LinkEndChild( mdElement ); + TiXmlElement* mdElement = new TiXmlElement("MetaData"); + productElement->LinkEndChild(mdElement); WriteMetaDataXML(mdElement); // Write the command classes - TiXmlElement* ccsElement = new TiXmlElement( "CommandClasses" ); - nodeElement->LinkEndChild( ccsElement ); + TiXmlElement* ccsElement = new TiXmlElement("CommandClasses"); + nodeElement->LinkEndChild(ccsElement); - for( map::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it ) + for (map::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it) { - if( it->second->GetCommandClassId() == NoOperation::StaticGetCommandClassId() ) // don't output NoOperation + if (it->second->GetCommandClassId() == Internal::CC::NoOperation::StaticGetCommandClassId()) // don't output NoOperation { continue; } - TiXmlElement* ccElement = new TiXmlElement( "CommandClass" ); - ccsElement->LinkEndChild( ccElement ); - it->second->WriteXML( ccElement ); + TiXmlElement* ccElement = new TiXmlElement("CommandClass"); + ccsElement->LinkEndChild(ccElement); + it->second->WriteXML(ccElement); } } @@ -1433,84 +1365,108 @@ void Node::WriteXML // // Handle the FUNC_ID_ZW_GET_NODE_PROTOCOL_INFO response //----------------------------------------------------------------------------- -void Node::UpdateProtocolInfo -( - uint8 const* _data -) +void Node::UpdateProtocolInfo(uint8 const* _data) { - if( ProtocolInfoReceived() ) + if (ProtocolInfoReceived()) { // We already have this info return; } - if( _data[4] == 0 ) + if (_data[4] == 0) { // Node doesn't exist if Generic class is zero. - Log::Write( LogLevel_Info, m_nodeId, " Protocol Info for Node %d reports node nonexistent", m_nodeId ); - SetNodeAlive( false ); + Log::Write(LogLevel_Info, m_nodeId, " Protocol Info for Node %d reports node nonexistent", m_nodeId); + SetNodeAlive(false); return; } // Capabilities - m_listening = ( ( _data[0] & 0x80 ) != 0 ); - m_routing = ( ( _data[0] & 0x40 ) != 0 ); + m_listening = ((_data[0] & 0x80) != 0); + m_routing = ((_data[0] & 0x40) != 0); m_maxBaudRate = 9600; - if( ( _data[0] & 0x38 ) == 0x10 ) + if ((_data[0] & 0x38) == 0x10) { m_maxBaudRate = 40000; } - m_version = ( _data[0] & 0x07 ) + 1; + // Reverse engineered by looking at Zniffer capture of crafted NIF packets + // Note 2019-05-19 I have never seen a 200k device, but Zniffer decodes it, + // this is not a typo... + + int speed_extension = _data[2] & 0x07; + + switch (speed_extension) + { + case 0: + // No speed_extension + break; + case 1: + m_maxBaudRate = 100000; + break; + case 2: + m_maxBaudRate = 200000; + break; + default: + Log::Write(LogLevel_Warning, m_nodeId, " Protocol Info speed_extension = %d is 'Reserved', reported Max Baud Rate might be wrong.", speed_extension); + break; + } + + m_version = (_data[0] & 0x07) + 1; - m_frequentListening = ( ( _data[1] & ( SecurityFlag_Sensor250ms | SecurityFlag_Sensor1000ms ) ) != 0 ); - m_beaming = ( ( _data[1] & SecurityFlag_BeamCapability ) != 0 ); + m_frequentListening = ((_data[1] & (SecurityFlag_Sensor250ms | SecurityFlag_Sensor1000ms)) != 0); + m_beaming = ((_data[1] & SecurityFlag_BeamCapability) != 0); // Security - m_security = ( ( _data[1] & SecurityFlag_Security ) != 0 ); + m_security = ((_data[1] & SecurityFlag_Security) != 0); // Optional flag is true if the device reports optional command classes. // NOTE: We stopped using this because not all devices report it properly, // and now just request the optional classes regardless. // bool optional = (( _data[1] & 0x80 ) != 0 ); - /* dont do any further processing if we have already recieved our Protocol Info, or basicprotocolInfo */ - if( ProtocolInfoReceived()) + /* dont do any further processing if we have already received our Protocol Info, or basicprotocolInfo */ + if (ProtocolInfoReceived()) { // We already have this info return; } - Log::Write( LogLevel_Info, m_nodeId, " Protocol Info for Node %d:", m_nodeId ); - if( m_listening ) - Log::Write( LogLevel_Info, m_nodeId, " Listening = true" ); + Log::Write(LogLevel_Info, m_nodeId, " Protocol Info for Node %d:", m_nodeId); + if (m_listening) + Log::Write(LogLevel_Info, m_nodeId, " Listening = true"); else { - Log::Write( LogLevel_Info, m_nodeId, " Listening = false" ); - Log::Write( LogLevel_Info, m_nodeId, " Frequent = %s", m_frequentListening ? "true" : "false" ); + Log::Write(LogLevel_Info, m_nodeId, " Listening = false"); + Log::Write(LogLevel_Info, m_nodeId, " Frequent = %s", m_frequentListening ? "true" : "false"); } - Log::Write( LogLevel_Info, m_nodeId, " Beaming = %s", m_beaming ? "true" : "false" ); - Log::Write( LogLevel_Info, m_nodeId, " Routing = %s", m_routing ? "true" : "false" ); - Log::Write( LogLevel_Info, m_nodeId, " Max Baud Rate = %d", m_maxBaudRate ); - Log::Write( LogLevel_Info, m_nodeId, " Version = %d", m_version ); - Log::Write( LogLevel_Info, m_nodeId, " Security = %s", m_security ? "true" : "false" ); + Log::Write(LogLevel_Info, m_nodeId, " Beaming = %s", m_beaming ? "true" : "false"); + Log::Write(LogLevel_Info, m_nodeId, " Routing = %s", m_routing ? "true" : "false"); + Log::Write(LogLevel_Info, m_nodeId, " Max Baud Rate = %d", m_maxBaudRate); + Log::Write(LogLevel_Info, m_nodeId, " Version = %d", m_version); + Log::Write(LogLevel_Info, m_nodeId, " Security = %s", m_security ? "true" : "false"); - if (m_basicprotocolInfoReceived == false) { + if (m_basicprotocolInfoReceived == false) + { // Notify the watchers of the protocol info. // We do the notification here so that it gets into the queue ahead of // any other notifications generated by adding command classes etc. - Notification* notification = new Notification( Notification::Type_NodeProtocolInfo ); - notification->SetHomeAndNodeIds( m_homeId, m_nodeId ); - GetDriver()->QueueNotification( notification ); + Notification* notification = new Notification(Notification::Type_NodeProtocolInfo); + notification->SetHomeAndNodeIds(m_homeId, m_nodeId); + GetDriver()->QueueNotification(notification); // Set up the device class based data for the node, including mandatory command classes - SetDeviceClasses( _data[3], _data[4], _data[5] ); + SetDeviceClasses(_data[3], _data[4], _data[5]); // Do this for every controller. A little extra work but it won't be a large file. - if( IsController() ) + if (IsController()) { - GetDriver()->ReadButtons( m_nodeId ); + GetDriver()->ReadButtons(m_nodeId); } +#if 0 + /* come back to this. We need to find a better way to Route Messages + * from Nodes to CC's that are advertised by the ControllerNode + */ /* load the Advertised CommandClasses on the Controller Node * */ @@ -1518,26 +1474,32 @@ void Node::UpdateProtocolInfo { Log::Write( LogLevel_Info, m_nodeId, " Advertised CommandClasses on Controller Node:"); list advertisedCommandClasses = CommandClasses::GetAdvertisedCommandClasses(); - for (list::iterator it = advertisedCommandClasses.begin(); it != advertisedCommandClasses.end(); ++it) { + for (list::iterator it = advertisedCommandClasses.begin(); it != advertisedCommandClasses.end(); ++it) + { CommandClass *cc = AddCommandClass(*it, true); - Log::Write( LogLevel_Info, m_nodeId, " %s", cc->GetCommandClassName().c_str()); + if ( cc ) + { + Log::Write(LogLevel_Info, m_nodeId, " %s", cc->GetCommandClassName().c_str()); + } } } - +#endif m_basicprotocolInfoReceived = true; - } else { + } + else + { /* we have to setup the Wakeup CC if needed here, because * it wouldn't have been created in the SetProtocolInfo function, as we didn't * have the Device Flags then */ - if( !m_listening && !IsFrequentListeningDevice()) + if (!m_listening && !IsFrequentListeningDevice()) { // Device does not always listen, so we need the WakeUp handler. We can't // wait for the command class list because the request for the command // classes may need to go in the wakeup queue itself! - if( CommandClass* pCommandClass = AddCommandClass( WakeUp::StaticGetCommandClassId() ) ) + if (Internal::CC::CommandClass* pCommandClass = AddCommandClass(Internal::CC::WakeUp::StaticGetCommandClassId())) { - pCommandClass->SetInstance( 1 ); + pCommandClass->SetInstance(1); } } @@ -1545,131 +1507,123 @@ void Node::UpdateProtocolInfo m_protocolInfoReceived = true; } -void Node::SetProtocolInfo -( - uint8 const* _protocolInfo, - uint8 const _length -) +void Node::SetProtocolInfo(uint8 const* _protocolInfo, uint8 const _length) { - if( ProtocolInfoReceived() || m_basicprotocolInfoReceived == true ) + if (ProtocolInfoReceived() || m_basicprotocolInfoReceived == true) { // We already have this info return; } - if( _protocolInfo[1] == 0 ) + if (_protocolInfo[1] == 0) { // Node doesn't exist if Generic class is zero. - Log::Write( LogLevel_Info, m_nodeId, " Protocol Info for Node %d reports node nonexistent", m_nodeId ); - SetNodeAlive( false ); + Log::Write(LogLevel_Info, m_nodeId, " Protocol Info for Node %d reports node nonexistent", m_nodeId); + SetNodeAlive(false); return; } // Notify the watchers of the protocol info. // We do the notification here so that it gets into the queue ahead of // any other notifications generated by adding command classes etc. - Notification* notification = new Notification( Notification::Type_NodeProtocolInfo ); - notification->SetHomeAndNodeIds( m_homeId, m_nodeId ); - GetDriver()->QueueNotification( notification ); - + Notification* notification = new Notification(Notification::Type_NodeProtocolInfo); + notification->SetHomeAndNodeIds(m_homeId, m_nodeId); + GetDriver()->QueueNotification(notification); // Set up the device class based data for the node, including mandatory command classes - SetDeviceClasses( _protocolInfo[0], _protocolInfo[1], _protocolInfo[2] ); + SetDeviceClasses(_protocolInfo[0], _protocolInfo[1], _protocolInfo[2]); /* Remaining Bytes in _protocolInfo are the CommandClasses this device supports */ /* first iterate over them and check for the Security CC, as we want to quickly start exchanging the Network Keys * first (before other CC's start sending stuff and slowing down our exchange */ - if (m_secured) { - if (Security *pCommandClass = static_cast(GetCommandClass(Security::StaticGetCommandClassId()))) { + if (m_secured) + { + if (Internal::CC::Security *pCommandClass = static_cast(GetCommandClass(Internal::CC::Security::StaticGetCommandClassId()))) + { /* Security CC has already been loaded, most likely via the SetDeviceClasses Function above */ - if (!GetDriver()->isNetworkKeySet()) { + if (!GetDriver()->isNetworkKeySet()) + { Log::Write(LogLevel_Warning, m_nodeId, "Security Command Class Disabled. NetworkKey is not Set"); - } else { + } + else + { pCommandClass->ExchangeNetworkKeys(); } - } else { + } + else + { /* Security CC is not loaded, see if its in our NIF frame and load if necessary */ - for (int i = 3; i < _length; i++) { - if (_protocolInfo[i] == Security::StaticGetCommandClassId()) { - pCommandClass = static_cast(AddCommandClass(_protocolInfo[i])); - if (!GetDriver()->isNetworkKeySet()) { + for (int i = 3; i < _length; i++) + { + if (_protocolInfo[i] == Internal::CC::Security::StaticGetCommandClassId()) + { + pCommandClass = static_cast(AddCommandClass(_protocolInfo[i])); + if (!GetDriver()->isNetworkKeySet()) + { Log::Write(LogLevel_Warning, m_nodeId, "Security Command Class Disabled. NetworkKey is not Set"); - } else { + } + else + { pCommandClass->ExchangeNetworkKeys(); } } } } } - UpdateNodeInfo(&_protocolInfo[3], _length-3); - + UpdateNodeInfo(&_protocolInfo[3], _length - 3); m_basicprotocolInfoReceived = true; } -void Node::SetSecured -( - bool secure -) +void Node::SetSecured(bool secure) { m_secured = secure; } -bool Node::IsSecured -( -) +bool Node::IsSecured() { return m_secured; } -void Node::SetInstanceLabel -( - uint8 const _instance, - char *label -) +void Node::SetInstanceLabel(uint8 const _instance, char *label) { m_globalInstanceLabel[_instance] = string(label); } -string Node::GetInstanceLabel -( - uint8 const _ccid, - uint8 const _instance -) +string Node::GetInstanceLabel(uint8 const _ccid, uint8 const _instance) { string label; /* find the CommandClass */ - CommandClass *_cc = GetCommandClass(_ccid); - if ( _cc ) + Internal::CC::CommandClass *_cc = GetCommandClass(_ccid); + if (_cc) label = _cc->GetInstanceLabel(_instance); /* if the Label is Empty - Then use the Global Label */ - if ( label.empty() ) { - if ( m_globalInstanceLabel.count(_instance) ) + if (label.empty()) + { + if (m_globalInstanceLabel.count(_instance)) label = m_globalInstanceLabel[_instance]; - else { + else + { /* construct a Default Label */ std::ostringstream sstream; - sstream << Localization::Get()->GetGlobalLabel("Instance") << " " << (int)_instance << ":"; + sstream << Internal::Localization::Get()->GetGlobalLabel("Instance") << " " << (int) _instance << ":"; label = sstream.str(); } } return label; } -uint8 Node::GetNumInstances -( - uint8 const _ccid -) +uint8 Node::GetNumInstances(uint8 const _ccid) { uint8 ccid = _ccid; int instances = 1; - if ( _ccid == 0 ) + if (_ccid == 0) { - ccid = MultiInstance::StaticGetCommandClassId(); + ccid = Internal::CC::MultiInstance::StaticGetCommandClassId(); } - if ( CommandClass *cc = GetCommandClass(ccid) ) + if (Internal::CC::CommandClass *cc = GetCommandClass(ccid)) { return cc->GetNumInstances(); } @@ -1677,59 +1631,158 @@ uint8 Node::GetNumInstances return instances; } +string Node::GetBasicString() +{ + char str[32]; + string label; + uint8 _basic = GetBasic(); -void Node::SetSecuredClasses -( - uint8 const* _data, - uint8 const _length, - uint32 const _instance -) + snprintf(str, sizeof(str), "Basic 0x%.2x", _basic); + label = str; + + // Read in the device class data if it has not been read already. + if (!s_deviceClassesLoaded) + { + ReadDeviceClasses(); + } + if (s_basicDeviceClasses.find(_basic) != s_basicDeviceClasses.end()) { + return s_basicDeviceClasses.at(_basic); + } + return "Unknown"; +} + +uint8 Node::GetGeneric(uint8 const _instance) const +{ + if (_instance > 0) { + if (Internal::CC::MultiInstance *cc = static_cast(GetCommandClass(Internal::CC::MultiInstance::StaticGetCommandClassId()))) + { + return cc->GetGenericInstanceDeviceType(_instance); + } + } + return m_generic; +} +string Node::GetGenericString(uint8 const _instance) +{ + char str[32]; + string label; + uint8 _generic = GetGeneric(_instance); + + snprintf(str, sizeof(str), "Generic 0x%.2x", _generic); + label = str; + + // Read in the device class data if it has not been read already. + if (!s_deviceClassesLoaded) + { + ReadDeviceClasses(); + } + + // Get the Generic device class label + if (s_genericDeviceClasses.find(_generic) != s_genericDeviceClasses.end()) + { + GenericDeviceClass* genericDeviceClass = s_genericDeviceClasses.at(_generic); + label = genericDeviceClass->GetLabel(); + } + return label; +} + + +uint8 Node::GetSpecific(uint8 const _instance) const +{ + if (_instance > 0) { + if (Internal::CC::MultiInstance *cc = static_cast(GetCommandClass(Internal::CC::MultiInstance::StaticGetCommandClassId()))) + { + return cc->GetSpecificInstanceDeviceType(_instance); + } + } + return m_specific; +} + +string Node::GetSpecificString(uint8 const _instance) +{ + char str[32]; + string label; + uint8 _generic = GetGeneric(_instance); + uint8 _specific = GetSpecific(_instance); + + snprintf(str, sizeof(str), "Specific 0x%.2x", _specific); + label = str; + + // Read in the device class data if it has not been read already. + if (!s_deviceClassesLoaded) + { + ReadDeviceClasses(); + } + + // Get the Generic device class label + if (s_genericDeviceClasses.find(_generic) != s_genericDeviceClasses.end()) + { + GenericDeviceClass* genericDeviceClass = s_genericDeviceClasses.at(_generic); + label = genericDeviceClass->GetLabel(); + // Override with any specific device class label + if (DeviceClass* specificDeviceClass = genericDeviceClass->GetSpecificDeviceClass(_specific)) + { + label = specificDeviceClass->GetLabel(); + } + + } + return label; +} + +void Node::SetSecuredClasses(uint8 const* _data, uint8 const _length, uint32 const _instance) { uint32 i; m_secured = true; - Log::Write( LogLevel_Info, m_nodeId, " Secured command classes for node %d (instance %d):", m_nodeId, _instance ); - if (!GetDriver()->isNetworkKeySet()) { - Log::Write (LogLevel_Warning, m_nodeId, " Secured Command Classes cannot be enabled as Network Key is not set"); + Log::Write(LogLevel_Info, m_nodeId, " Secured CommandClasses for node %d (instance %d):", m_nodeId, _instance); + Log::Write(LogLevel_Info, m_nodeId, " Controlled CommandClasses:"); + if (!GetDriver()->isNetworkKeySet()) + { + Log::Write(LogLevel_Warning, m_nodeId, " Secured CommandClasses cannot be enabled as Network Key is not set"); return; } - bool afterMark = false; - for( i=0; i<_length; ++i ) + for (i = 0; i < _length; ++i) { - if( _data[i] == 0xef ) + if (_data[i] == 0xef) { // COMMAND_CLASS_MARK. // Marks the end of the list of supported command classes. The remaining classes // are those that can be controlled by the device. These classes are created // without values. Messages received cause notification events instead. afterMark = true; + Log::Write(LogLevel_Info, m_nodeId, " Controlling CommandClasses:"); continue; } /* Check if this is a CC that is already registered with the node */ - if (CommandClass *pCommandClass = GetCommandClass(_data[i], afterMark)) + if (Internal::CC::CommandClass *pCommandClass = GetCommandClass(_data[i])) { /* if it was specified the he NIF frame, and came in as part of the Security SupportedReport message * then it can support both Clear Text and Secured Comms. So do a check first */ - if (pCommandClass->IsInNIF()) { + if (pCommandClass->IsInNIF()) + { /* if the CC Supports Security and our SecurityStrategy says we should encrypt it, then mark it as encrypted */ - if (pCommandClass->IsSecureSupported() && (ShouldSecureCommandClass(_data[i]) == SecurityStrategy_Supported )) { + if (pCommandClass->IsSecureSupported() && (Internal::ShouldSecureCommandClass(_data[i]) == Internal::SecurityStrategy_Supported)) + { pCommandClass->SetSecured(); - Log::Write( LogLevel_Info, m_nodeId, " %s (Secured) - %s", pCommandClass->GetCommandClassName().c_str(), pCommandClass->IsInNIF() ? "InNIF": "NotInNIF"); + Log::Write(LogLevel_Info, m_nodeId, " %s (Secured) - %s", pCommandClass->GetCommandClassName().c_str(), pCommandClass->IsInNIF() ? "InNIF" : "NotInNIF"); } /* if it wasn't in the NIF frame, then it will only support Secured Comms. */ - } else { - if (pCommandClass->IsSecureSupported()) { + } + else + { + if (pCommandClass->IsSecureSupported()) + { pCommandClass->SetSecured(); - Log::Write( LogLevel_Info, m_nodeId, " %s (Secured) - %s", pCommandClass->GetCommandClassName().c_str(), pCommandClass->IsInNIF() ? "InNIF": "NotInNIF"); + Log::Write(LogLevel_Info, m_nodeId, " %s (Secured) - %s", pCommandClass->GetCommandClassName().c_str(), pCommandClass->IsInNIF() ? "InNIF" : "NotInNIF"); } } - if (_instance > 1) { + if (_instance > 1) + { /* we need to get the endpoint from the Security CC, to map over to the target CC if this * is triggered by a SecurityCmd_SupportedReport from a instance */ - CommandClass *secc = GetCommandClass(Security::StaticGetCommandClassId(), false); + Internal::CC::CommandClass *secc = GetCommandClass(Internal::CC::Security::StaticGetCommandClassId()); int ep = secc->GetEndPoint(_instance); pCommandClass->SetEndPoint(_instance, ep); pCommandClass->SetInstance(_instance); @@ -1738,84 +1791,80 @@ void Node::SetSecuredClasses /* it might be a new CC we havn't seen as part of the NIF. In that case * its only supported via the Security CC, so no need to check our SecurityStrategy, just * encrypt it regardless */ - else if( CommandClasses::IsSupported( _data[i] ) ) + else if (Internal::CC::CommandClasses::IsSupported(_data[i])) { - if( CommandClass* pCommandClass = AddCommandClass( _data[i], afterMark ) ) + if (Internal::CC::CommandClass* pCommandClass = AddCommandClass(_data[i])) { // If this class came after the COMMAND_CLASS_MARK, then we do not create values. - if( afterMark ) + if (afterMark) { pCommandClass->SetAfterMark(); } - if (pCommandClass->IsSecureSupported()) { + if (pCommandClass->IsSecureSupported()) + { pCommandClass->SetSecured(); - Log::Write( LogLevel_Info, m_nodeId, " %s (Secured) - %s", pCommandClass->GetCommandClassName().c_str(), pCommandClass->IsInNIF() ? "InNIF" : "NotInNIF" ); + Log::Write(LogLevel_Info, m_nodeId, " %s (Secured) - %s", pCommandClass->GetCommandClassName().c_str(), pCommandClass->IsInNIF() ? "InNIF" : "NotInNIF"); } // Start with an instance count of one. If the device supports COMMMAND_CLASS_MULTI_INSTANCE // then some command class instance counts will increase once the responses to the RequestState // call at the end of this method have been processed. if (_instance > 1) - pCommandClass->SetInstance( _instance ); + pCommandClass->SetInstance(_instance); else - pCommandClass->SetInstance( 1 ); + pCommandClass->SetInstance(1); /* set our Static Request Flags */ uint8 request = 0; - if( GetCommandClass( MultiInstance::StaticGetCommandClassId() ) ) + if (GetCommandClass(Internal::CC::MultiInstance::StaticGetCommandClassId())) { // Request instances - request |= (uint8)CommandClass::StaticRequest_Instances; + request |= (uint8) Internal::CC::CommandClass::StaticRequest_Instances; } - if( GetCommandClass( Version::StaticGetCommandClassId() ) ) + if (GetCommandClass(Internal::CC::Version::StaticGetCommandClassId())) { // Request versions - request |= (uint8)CommandClass::StaticRequest_Version; + request |= (uint8) Internal::CC::CommandClass::StaticRequest_Version; } - if( request ) + if (request) { - pCommandClass->SetStaticRequest( request ); + pCommandClass->SetStaticRequest(request); } } } else { - Log::Write( LogLevel_Info, m_nodeId, " Secure CommandClass 0x%.2x - NOT SUPPORTED", _data[i] ); + Log::Write(LogLevel_Info, m_nodeId, " Secure CommandClass 0x%.2x - NOT SUPPORTED", _data[i]); } } - Log::Write( LogLevel_Info, m_nodeId, " UnSecured command classes for node %d (instance %d):", m_nodeId, _instance ); - for( map::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it ) + Log::Write(LogLevel_Info, m_nodeId, " UnSecured command classes for node %d (instance %d):", m_nodeId, _instance); + for (map::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it) { if (!it->second->IsSecured()) - Log::Write( LogLevel_Info, m_nodeId, " %s (Unsecured) - %s", it->second->GetCommandClassName().c_str(), it->second->IsInNIF() ? "InNIF" : "NotInNIF" ); + Log::Write(LogLevel_Info, m_nodeId, " %s (Unsecured) - %s", it->second->GetCommandClassName().c_str(), it->second->IsInNIF() ? "InNIF" : "NotInNIF"); } - } //----------------------------------------------------------------------------- // // Set up the command classes from the node info frame //----------------------------------------------------------------------------- -void Node::UpdateNodeInfo -( - uint8 const* _data, - uint8 const _length -) +void Node::UpdateNodeInfo(uint8 const* _data, uint8 const _length) { - if( !NodeInfoReceived() ) + if (!NodeInfoReceived()) { // Add the command classes specified by the device - Log::Write( LogLevel_Info, m_nodeId, " Optional command classes for node %d:", m_nodeId ); + Log::Write(LogLevel_Info, m_nodeId, " Optional CommandClasses for node %d:", m_nodeId); bool newCommandClasses = false; uint32 i; bool afterMark = false; - for( i=0; i<_length; ++i ) + for (i = 0; i < _length; ++i) { - if( _data[i] == 0xef ) + if (_data[i] == 0xef) { // COMMAND_CLASS_MARK. // Marks the end of the list of supported command classes. The remaining classes @@ -1823,27 +1872,28 @@ void Node::UpdateNodeInfo // without values. Messages received cause notification events instead. afterMark = true; - if( !newCommandClasses ) + if (!newCommandClasses) { - Log::Write( LogLevel_Info, m_nodeId, " None" ); + Log::Write(LogLevel_Info, m_nodeId, " None"); } - Log::Write( LogLevel_Info, m_nodeId, " Optional command classes controlled by node %d:", m_nodeId ); + Log::Write(LogLevel_Info, m_nodeId, " Optional CommandClasses controlled by node %d:", m_nodeId); newCommandClasses = false; continue; } - if( CommandClasses::IsSupported( _data[i] ) ) + if (Internal::CC::CommandClasses::IsSupported(_data[i])) { - if (Security::StaticGetCommandClassId() == _data[i] && !GetDriver()->isNetworkKeySet()) { - Log::Write (LogLevel_Info, m_nodeId, " %s (Disabled - Network Key Not Set)", Security::StaticGetCommandClassName().c_str()); + if (Internal::CC::Security::StaticGetCommandClassId() == _data[i] && !GetDriver()->isNetworkKeySet()) + { + Log::Write(LogLevel_Info, m_nodeId, " %s (Disabled - Network Key Not Set)", Internal::CC::Security::StaticGetCommandClassName().c_str()); continue; } - if( CommandClass* pCommandClass = AddCommandClass( _data[i] , afterMark) ) + if (Internal::CC::CommandClass* pCommandClass = AddCommandClass(_data[i])) { /* this CC was in the NIF frame */ pCommandClass->SetInNIF(); // If this class came after the COMMAND_CLASS_MARK, then we do not create values. - if( afterMark ) + if (afterMark) { pCommandClass->SetAfterMark(); } @@ -1851,29 +1901,27 @@ void Node::UpdateNodeInfo // Start with an instance count of one. If the device supports COMMMAND_CLASS_MULTI_INSTANCE // then some command class instance counts will increase once the responses to the RequestState // call at the end of this method have been processed. - pCommandClass->SetInstance( 1 ); + pCommandClass->SetInstance(1); newCommandClasses = true; - Log::Write( LogLevel_Info, m_nodeId, " %s", pCommandClass->GetCommandClassName().c_str() ); - } else if (CommandClass *pCommandClass = GetCommandClass( _data[i] ) ) { - /* this CC was in the NIF frame */ - pCommandClass->SetInNIF(); - Log::Write( LogLevel_Info, m_nodeId, " %s (Existing)", pCommandClass->GetCommandClassName().c_str() ); - } else if (CommandClass *pCommandClass = GetCommandClass( _data[i], true ) ) { + Log::Write(LogLevel_Info, m_nodeId, " %s", pCommandClass->GetCommandClassName().c_str()); + } + else if (Internal::CC::CommandClass *pCommandClass = GetCommandClass(_data[i])) + { /* this CC was in the NIF frame */ pCommandClass->SetInNIF(); - Log::Write( LogLevel_Info, m_nodeId, " %s (Existing)", pCommandClass->GetCommandClassName().c_str() ); + Log::Write(LogLevel_Info, m_nodeId, " %s (Existing)", pCommandClass->GetCommandClassName().c_str()); } } else { - Log::Write( LogLevel_Info, m_nodeId, " CommandClass 0x%.2x - NOT REQUIRED", _data[i] ); + Log::Write(LogLevel_Info, m_nodeId, " CommandClass 0x%.2x - NOT REQUIRED", _data[i]); } } - if( !newCommandClasses ) + if (!newCommandClasses) { // No additional command classes over the mandatory ones. - Log::Write( LogLevel_Info, m_nodeId, " None" ); + Log::Write(LogLevel_Info, m_nodeId, " None"); } SetStaticRequests(); @@ -1883,57 +1931,53 @@ void Node::UpdateNodeInfo { /* Only Refresh if the Device Config Specifies it - Only the dynamic stuff */ if (m_refreshonNodeInfoFrame) - SetQueryStage( QueryStage_Dynamic ); + SetQueryStage(QueryStage_Dynamic); } // Treat the node info frame as a sign that the node is awake - if( WakeUp* wakeUp = static_cast( GetCommandClass( WakeUp::StaticGetCommandClassId() ) ) ) + if (Internal::CC::WakeUp* wakeUp = static_cast(GetCommandClass(Internal::CC::WakeUp::StaticGetCommandClassId()))) { - wakeUp->SetAwake( true ); + wakeUp->SetAwake(true); } - } //----------------------------------------------------------------------------- // // Track alive state of a node for dead node detection. //----------------------------------------------------------------------------- -void Node::SetNodeAlive -( - bool const _isAlive -) +void Node::SetNodeAlive(bool const _isAlive) { Notification* notification; - if( _isAlive ) + if (_isAlive) { - Log::Write( LogLevel_Error, m_nodeId, "WARNING: node revived" ); + Log::Write(LogLevel_Error, m_nodeId, "WARNING: node revived"); m_nodeAlive = true; m_errors = 0; - if( m_queryStage != Node::QueryStage_Complete ) + if (m_queryStage != Node::QueryStage_Complete) { m_queryRetries = 0; // restart at last stage AdvanceQueries(); } - notification = new Notification( Notification::Type_Notification ); - notification->SetHomeAndNodeIds( m_homeId, m_nodeId ); - notification->SetNotification( Notification::Code_Alive ); + notification = new Notification(Notification::Type_Notification); + notification->SetHomeAndNodeIds(m_homeId, m_nodeId); + notification->SetNotification(Notification::Code_Alive); } else { - Log::Write( LogLevel_Error, m_nodeId, "ERROR: node presumed dead" ); + Log::Write(LogLevel_Error, m_nodeId, "ERROR: node presumed dead"); m_nodeAlive = false; - if( m_queryStage != Node::QueryStage_Complete ) + if (m_queryStage != Node::QueryStage_Complete) { // Check whether all nodes are now complete GetDriver()->CheckCompletedNodeQueries(); } - notification = new Notification( Notification::Type_Notification ); - notification->SetHomeAndNodeIds( m_homeId, m_nodeId ); - notification->SetNotification( Notification::Code_Dead ); + notification = new Notification(Notification::Type_Notification); + notification->SetHomeAndNodeIds(m_homeId, m_nodeId); + notification->SetNotification(Notification::Code_Dead); } - GetDriver()->QueueNotification( notification ); + GetDriver()->QueueNotification(notification); } //----------------------------------------------------------------------------- @@ -1942,31 +1986,29 @@ void Node::SetNodeAlive // need to request certain static data from the device. This is so that // we can track which data has been received, and which has not. //----------------------------------------------------------------------------- -void Node::SetStaticRequests -( -) +void Node::SetStaticRequests() { uint8 request = 0; - if( GetCommandClass( MultiInstance::StaticGetCommandClassId(), false ) ) + if (GetCommandClass(Internal::CC::MultiInstance::StaticGetCommandClassId())) { // Request instances - request |= (uint8)CommandClass::StaticRequest_Instances; + request |= (uint8) Internal::CC::CommandClass::StaticRequest_Instances; } - if( GetCommandClass( Version::StaticGetCommandClassId(), false ) ) + if (GetCommandClass(Internal::CC::Version::StaticGetCommandClassId())) { // Request versions - request |= (uint8)CommandClass::StaticRequest_Version; + request |= (uint8) Internal::CC::CommandClass::StaticRequest_Version; } - if( request ) + if (request) { - for( map::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it ) + for (map::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it) { - it->second->SetStaticRequest( request ); + it->second->SetStaticRequest(request); } - SetQueryStage( QueryStage_ManufacturerSpecific2 ); + SetQueryStage(QueryStage_ManufacturerSpecific2); } } @@ -1974,20 +2016,17 @@ void Node::SetStaticRequests // // Set the name of the node //----------------------------------------------------------------------------- -void Node::SetNodeName -( - string const& _nodeName -) +void Node::SetNodeName(string const& _nodeName) { m_nodeName = _nodeName; // Notify the watchers of the name changes - Notification* notification = new Notification( Notification::Type_NodeNaming ); - notification->SetHomeAndNodeIds( m_homeId, m_nodeId ); - GetDriver()->QueueNotification( notification ); - if( NodeNaming* cc = static_cast( GetCommandClass( NodeNaming::StaticGetCommandClassId() ) ) ) + Notification* notification = new Notification(Notification::Type_NodeNaming); + notification->SetHomeAndNodeIds(m_homeId, m_nodeId); + GetDriver()->QueueNotification(notification); + if (Internal::CC::NodeNaming* cc = static_cast(GetCommandClass(Internal::CC::NodeNaming::StaticGetCommandClassId()))) { // The node supports naming, so we try to write the name into the device - cc->SetName( _nodeName ); + cc->SetName(_nodeName); } } @@ -1995,20 +2034,17 @@ void Node::SetNodeName // // Set the location of the node //----------------------------------------------------------------------------- -void Node::SetLocation -( - string const& _location -) +void Node::SetLocation(string const& _location) { m_location = _location; // Notify the watchers of the name changes - Notification* notification = new Notification( Notification::Type_NodeNaming ); - notification->SetHomeAndNodeIds( m_homeId, m_nodeId ); - GetDriver()->QueueNotification( notification ); - if( NodeNaming* cc = static_cast( GetCommandClass( NodeNaming::StaticGetCommandClassId() ) ) ) + Notification* notification = new Notification(Notification::Type_NodeNaming); + notification->SetHomeAndNodeIds(m_homeId, m_nodeId); + GetDriver()->QueueNotification(notification); + if (Internal::CC::NodeNaming* cc = static_cast(GetCommandClass(Internal::CC::NodeNaming::StaticGetCommandClassId()))) { // The node supports naming, so we try to write the location into the device - cc->SetLocation( _location ); + cc->SetLocation(_location); } } @@ -2016,86 +2052,90 @@ void Node::SetLocation // // Handle a command class message //----------------------------------------------------------------------------- -void Node::ApplicationCommandHandler -( - uint8 const* _data, - bool encrypted +void Node::ApplicationCommandHandler(uint8 const* _data, bool encrypted ) { - if( CommandClass* pCommandClass = GetCommandClass( _data[5] ) ) + if (Internal::CC::CommandClass* pCommandClass = GetCommandClass(_data[5])) { - if (pCommandClass->IsSecured() && !encrypted) { - Log::Write( LogLevel_Warning, m_nodeId, "Received a Clear Text Message for the CommandClass %s which is Secured", pCommandClass->GetCommandClassName().c_str()); + if (pCommandClass->IsSecured() && !encrypted) + { + Log::Write(LogLevel_Warning, m_nodeId, "Received a Clear Text Message for the CommandClass %s which is Secured", pCommandClass->GetCommandClassName().c_str()); bool drop = true; Options::Get()->GetOptionAsBool("EnforceSecureReception", &drop); - if (drop) { - Log::Write( LogLevel_Warning, m_nodeId, " Dropping Message"); + if (drop) + { + Log::Write(LogLevel_Warning, m_nodeId, " Dropping Message"); return; - } else { - Log::Write( LogLevel_Warning, m_nodeId, " Allowing Message (EnforceSecureReception is not set)"); + } + else + { + Log::Write(LogLevel_Warning, m_nodeId, " Allowing Message (EnforceSecureReception is not set)"); } } pCommandClass->ReceivedCntIncr(); - if (!pCommandClass->HandleMsg( &_data[6], _data[4] ) ) + if (!pCommandClass->IsAfterMark()) { - Log::Write( LogLevel_Warning, m_nodeId, "CommandClass %s HandlerMsg Returned False", pCommandClass->GetCommandClassName().c_str()); - } - } - else if( CommandClass* pCommandClass = GetCommandClass( _data[5], true ) ) - { - if (pCommandClass->IsSecured() && !encrypted) { - Log::Write( LogLevel_Warning, m_nodeId, "Received a Clear Text Message for the Advertised CommandClass %s which is Secured", pCommandClass->GetCommandClassName().c_str()); - bool drop = true; - Options::Get()->GetOptionAsBool("EnforceSecureReception", &drop); - if (drop) { - Log::Write( LogLevel_Warning, m_nodeId, " Dropping Message"); - return; - } else { - Log::Write( LogLevel_Warning, m_nodeId, " Allowing Message (EnforceSecureReception is not set)"); + if (!pCommandClass->HandleMsg(&_data[6], _data[4])) + { + Log::Write(LogLevel_Warning, m_nodeId, "CommandClass %s HandlerMsg Returned False", pCommandClass->GetCommandClassName().c_str()); } } - - pCommandClass->ReceivedCntIncr(); - if (!pCommandClass->HandleIncomingMsg( &_data[6], _data[4] ) ) + else { - Log::Write (LogLevel_Warning, m_nodeId, "CommandClass %s HandleIncommingMsg returned false", pCommandClass->GetCommandClassName().c_str()); + if (!pCommandClass->HandleIncomingMsg(&_data[6], _data[4])) + { + Log::Write(LogLevel_Warning, m_nodeId, "CommandClass %s HandleIncomingMsg Returned False", pCommandClass->GetCommandClassName().c_str()); + } } } else { - if( _data[5] == ControllerReplication::StaticGetCommandClassId() ) + if (_data[5] == Internal::CC::ControllerReplication::StaticGetCommandClassId()) { // This is a controller replication message, and we do not support it. // We have to at least acknowledge the message to avoid locking the sending device. - Log::Write( LogLevel_Info, m_nodeId, "ApplicationCommandHandler - Default acknowledgement of controller replication data" ); + Log::Write(LogLevel_Info, m_nodeId, "ApplicationCommandHandler - Default acknowledgment of controller replication data"); - Msg* msg = new Msg( "Replication Command Complete", m_nodeId, REQUEST, FUNC_ID_ZW_REPLICATION_COMMAND_COMPLETE, false ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Command ); + Internal::Msg* msg = new Internal::Msg("Replication Command Complete", m_nodeId, REQUEST, FUNC_ID_ZW_REPLICATION_COMMAND_COMPLETE, false); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Command); } - else if ( _data[5] == MultiInstance::StaticGetCommandClassId() ) { + else if (_data[5] == Internal::CC::MultiInstance::StaticGetCommandClassId()) + { // Devices that support MultiChannelAssociation may send a MultiChannel Encapsulated message if there is a Instance set in the Association Groups // So we will dynamically load the MultiChannel CC if we receive a encapsulated message // We only do this after the QueryStage is Complete as we don't want to Add this CC to the list, and then confusing OZW that // The device supports the MultiChannel CC (eg, the Device might be asleep, we have not got the NIF and it actually does support it versus sending to a MultiChannelAssociation Endpoint - if (GetCurrentQueryStage() != QueryStage_Complete) { - Log::Write( LogLevel_Info, m_nodeId, "ApplicationCommandHandler - Received a MultiInstance Message, but QueryStage Isn't Complete yet"); + if (GetCurrentQueryStage() != QueryStage_Complete) + { + Log::Write(LogLevel_Info, m_nodeId, "ApplicationCommandHandler - Received a MultiInstance Message, but QueryStage Isn't Complete yet"); return; } - Log::Write (LogLevel_Info, m_nodeId, "ApplicationCommandHandler - Received a MultiInstance Message but MulitInstance CC isn't loaded. Loading it... "); - if (CommandClass* pCommandClass = AddCommandClass(MultiInstance::StaticGetCommandClassId(), true)) { + Log::Write(LogLevel_Info, m_nodeId, "ApplicationCommandHandler - Received a MultiInstance Message but MulitInstance CC isn't loaded. Loading it... "); + if (Internal::CC::CommandClass* pCommandClass = AddCommandClass(Internal::CC::MultiInstance::StaticGetCommandClassId())) + { pCommandClass->ReceivedCntIncr(); - if (!pCommandClass->HandleIncomingMsg( &_data[6], _data[4] ) ) + if (!pCommandClass->IsAfterMark()) { - Log::Write (LogLevel_Warning, m_nodeId, "CommandClass %s HandleIncommingMsg returned false", pCommandClass->GetCommandClassName().c_str()); + if (!pCommandClass->HandleMsg(&_data[6], _data[4])) + { + Log::Write(LogLevel_Warning, m_nodeId, "CommandClass %s HandleMsg returned false", pCommandClass->GetCommandClassName().c_str()); + } + } + else + { + if (!pCommandClass->HandleIncomingMsg(&_data[6], _data[4])) + { + Log::Write(LogLevel_Warning, m_nodeId, "CommandClass %s HandleIncommingMsg returned false", pCommandClass->GetCommandClassName().c_str()); + } } } } else { - Log::Write( LogLevel_Info, m_nodeId, "ApplicationCommandHandler - Unhandled Command Class 0x%.2x", _data[5] ); + Log::Write(LogLevel_Info, m_nodeId, "ApplicationCommandHandler - Unhandled Command Class 0x%.2x", _data[5]); } } } @@ -2104,26 +2144,12 @@ void Node::ApplicationCommandHandler // // Get the specified command class object if supported, otherwise NULL //----------------------------------------------------------------------------- -CommandClass* Node::GetCommandClass -( - uint8 const _commandClassId, - bool advertised -)const +Internal::CC::CommandClass* Node::GetCommandClass(uint8 const _commandClassId) const { - if (!advertised) { - map::const_iterator it = m_commandClassMap.find( _commandClassId ); - if( it != m_commandClassMap.end() ) - { - return it->second; - } - } - else + map::const_iterator it = m_commandClassMap.find(_commandClassId); + if (it != m_commandClassMap.end()) { - map::const_iterator it = m_advertisedCommandClassMap.find( _commandClassId ); - if (it != m_advertisedCommandClassMap.end() ) - { - return it->second; - } + return it->second; } // Not found @@ -2134,35 +2160,23 @@ CommandClass* Node::GetCommandClass // // Add a command class to the node //----------------------------------------------------------------------------- -CommandClass* Node::AddCommandClass -( - uint8 const _commandClassId, - bool advertised -) +Internal::CC::CommandClass* Node::AddCommandClass(uint8 const _commandClassId) { - if( GetCommandClass( _commandClassId ) || GetCommandClass( _commandClassId, true)) + if (GetCommandClass(_commandClassId)) { // Class and instance have already been added return NULL; } // Create the command class object and add it to our map - if( CommandClass* pCommandClass = CommandClasses::CreateCommandClass( _commandClassId, m_homeId, m_nodeId ) ) + if (Internal::CC::CommandClass* pCommandClass = Internal::CC::CommandClasses::CreateCommandClass(_commandClassId, m_homeId, m_nodeId)) { - if (!advertised) - { - m_commandClassMap[_commandClassId] = pCommandClass; - } - else - { - m_advertisedCommandClassMap[_commandClassId] = pCommandClass; - pCommandClass->SetAfterMark(); - } + m_commandClassMap[_commandClassId] = pCommandClass; return pCommandClass; } else { - Log::Write( LogLevel_Info, m_nodeId, "AddCommandClass - Unsupported Command Class 0x%.2x", _commandClassId ); + Log::Write(LogLevel_Info, m_nodeId, "AddCommandClass - Unsupported CommandClass 0x%.2x", _commandClassId); } return NULL; @@ -2172,77 +2186,69 @@ CommandClass* Node::AddCommandClass // // Remove a command class from the node //----------------------------------------------------------------------------- -void Node::RemoveCommandClass -( - uint8 const _commandClassId -) +void Node::RemoveCommandClass(uint8 const _commandClassId) { - map::iterator it = m_commandClassMap.find( _commandClassId ); - if( it == m_commandClassMap.end() ) + map::iterator it = m_commandClassMap.find(_commandClassId); + if (it == m_commandClassMap.end()) { // Class is not found return; } // Remove all the values associated with this class - if( ValueStore* store = GetValueStore() ) + if (Internal::VC::ValueStore* store = GetValueStore()) { - store->RemoveCommandClassValues( _commandClassId ); + store->RemoveCommandClassValues(_commandClassId); } // Destroy the command class object and remove it from our map - Log::Write( LogLevel_Info, m_nodeId, "RemoveCommandClass - Removed support for %s", it->second->GetCommandClassName().c_str() ); + Log::Write(LogLevel_Info, m_nodeId, "RemoveCommandClass - Removed support for %s", it->second->GetCommandClassName().c_str()); delete it->second; - m_commandClassMap.erase( it ); + m_commandClassMap.erase(it); } //----------------------------------------------------------------------------- // // Set a configuration parameter in a device //----------------------------------------------------------------------------- -bool Node::SetConfigParam -( - uint8 const _param, - int32 _value, - uint8 const _size -) +bool Node::SetConfigParam(uint8 const _param, int32 _value, uint8 const _size) { - if( Configuration* cc = static_cast( GetCommandClass( Configuration::StaticGetCommandClassId() ) ) ) + if (Internal::CC::Configuration* cc = static_cast(GetCommandClass(Internal::CC::Configuration::StaticGetCommandClassId()))) { // First try to find an existing value representing the parameter, and set that. - if( Value* value = cc->GetValue( 1, _param ) ) + if (Internal::VC::Value* value = cc->GetValue(1, _param)) { - switch( value->GetID().GetType() ) + switch (value->GetID().GetType()) { case ValueID::ValueType_Bool: { - ValueBool* valueBool = static_cast( value ); - valueBool->Set( _value != 0 ); + Internal::VC::ValueBool* valueBool = static_cast(value); + valueBool->Set(_value != 0); break; } case ValueID::ValueType_Byte: { - ValueByte* valueByte = static_cast( value ); - valueByte->Set( (uint8)_value ); + Internal::VC::ValueByte* valueByte = static_cast(value); + valueByte->Set((uint8) _value); break; } case ValueID::ValueType_Short: { - ValueShort* valueShort = static_cast( value ); - valueShort->Set( (uint16)_value ); + Internal::VC::ValueShort* valueShort = static_cast(value); + valueShort->Set((uint16) _value); break; } case ValueID::ValueType_Int: { - ValueInt* valueInt = static_cast( value ); - valueInt->Set( _value ); + Internal::VC::ValueInt* valueInt = static_cast(value); + valueInt->Set(_value); break; } case ValueID::ValueType_List: { - ValueList* valueList = static_cast( value ); - valueList->SetByValue( _value ); + Internal::VC::ValueList* valueList = static_cast(value); + valueList->SetByValue(_value); break; } default: @@ -2256,7 +2262,7 @@ bool Node::SetConfigParam // Failed to find an existing value object representing this // configuration parameter, so we try using the default or // included size through the Configuration command class. - cc->Set( _param, _value, _size ); + cc->Set(_param, _value, _size); return true; } @@ -2267,14 +2273,11 @@ bool Node::SetConfigParam // // Request the value of a configuration parameter from the device //----------------------------------------------------------------------------- -void Node::RequestConfigParam -( - uint8 const _param -) +void Node::RequestConfigParam(uint8 const _param) { - if( Configuration* cc = static_cast( GetCommandClass( Configuration::StaticGetCommandClassId() ) ) ) + if (Internal::CC::Configuration* cc = static_cast(GetCommandClass(Internal::CC::Configuration::StaticGetCommandClassId()))) { - cc->RequestValue( 0, _param, 1, Driver::MsgQueue_Send ); + cc->RequestValue(0, _param, 1, Driver::MsgQueue_Send); } } @@ -2282,25 +2285,22 @@ void Node::RequestConfigParam // // Request the values of all known configuration parameters from the device //----------------------------------------------------------------------------- -bool Node::RequestAllConfigParams -( - uint32 const _requestFlags -) +bool Node::RequestAllConfigParams(uint32 const _requestFlags) { bool res = false; - if( Configuration* cc = static_cast( GetCommandClass( Configuration::StaticGetCommandClassId() ) ) ) + if (Internal::CC::Configuration* cc = static_cast(GetCommandClass(Internal::CC::Configuration::StaticGetCommandClassId()))) { // Go through all the values in the value store, and request all those which are in the Configuration command class - for( ValueStore::Iterator it = m_values->Begin(); it != m_values->End(); ++it ) + for (Internal::VC::ValueStore::Iterator it = m_values->Begin(); it != m_values->End(); ++it) { - Value* value = it->second; - if( value->GetID().GetCommandClassId() == Configuration::StaticGetCommandClassId() && !value->IsWriteOnly() ) + Internal::VC::Value* value = it->second; + if (value->GetID().GetCommandClassId() == Internal::CC::Configuration::StaticGetCommandClassId() && !value->IsWriteOnly()) { /* put the ConfigParams Request into the MsgQueue_Query queue. This is so MsgQueue_Send doesn't get backlogged with a * lot of ConfigParams requests, and should help speed up any user generated messages being sent out (as the MsgQueue_Send has a higher * priority than MsgQueue_Query */ - res |= cc->RequestValue( _requestFlags, value->GetID().GetIndex(), 1, Driver::MsgQueue_Query ); + res |= cc->RequestValue(_requestFlags, value->GetID().GetIndex(), 1, Driver::MsgQueue_Query); } } } @@ -2312,16 +2312,14 @@ bool Node::RequestAllConfigParams // // Request an update of all known dynamic values from the device //----------------------------------------------------------------------------- -bool Node::RequestDynamicValues -( -) +bool Node::RequestDynamicValues() { bool res = false; - for( map::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it ) + for (map::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it) { - if( !it->second->IsAfterMark() ) + if (!it->second->IsAfterMark()) { - res |= it->second->RequestStateForAllInstances( CommandClass::RequestFlag_Dynamic, Driver::MsgQueue_Send ); + res |= it->second->RequestStateForAllInstances(Internal::CC::CommandClass::RequestFlag_Dynamic, Driver::MsgQueue_Send); } } @@ -2331,13 +2329,11 @@ bool Node::RequestDynamicValues // // Request an update of all known dynamic values from the device //----------------------------------------------------------------------------- -void Node::RefreshValuesOnWakeup -( -) +void Node::RefreshValuesOnWakeup() { - for( map::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it ) + for (map::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it) { - if( !it->second->IsAfterMark() ) + if (!it->second->IsAfterMark()) { it->second->refreshValuesOnWakeup(); } @@ -2348,21 +2344,18 @@ void Node::RefreshValuesOnWakeup // // Helper method to set a device's basic level //----------------------------------------------------------------------------- -void Node::SetLevel -( - uint8 const _level -) +void Node::SetLevel(uint8 const _level) { // Level is 0-99, with 0 = off and 99 = fully on. 255 = turn on at last level. uint8 adjustedLevel = _level; - if( ( _level > 99 ) && ( _level < 255 ) ) + if ((_level > 99) && (_level < 255)) { adjustedLevel = 99; } - if( Basic* cc = static_cast( GetCommandClass( Basic::StaticGetCommandClassId() ) ) ) + if (Internal::CC::Basic* cc = static_cast(GetCommandClass(Internal::CC::Basic::StaticGetCommandClassId()))) { - cc->Set( adjustedLevel ); + cc->Set(adjustedLevel); } } @@ -2370,14 +2363,12 @@ void Node::SetLevel // // Helper method to set a device to be on //----------------------------------------------------------------------------- -void Node::SetNodeOn -( -) +void Node::SetNodeOn() { // Level is 0-99, with 0 = off and 99 = fully on. 255 = turn on at last level. - if( Basic* cc = static_cast( GetCommandClass( Basic::StaticGetCommandClassId() ) ) ) + if (Internal::CC::Basic* cc = static_cast(GetCommandClass(Internal::CC::Basic::StaticGetCommandClassId()))) { - cc->Set( 255 ); + cc->Set(255); } } @@ -2385,14 +2376,12 @@ void Node::SetNodeOn // // Helper method to set a device to be off //----------------------------------------------------------------------------- -void Node::SetNodeOff -( -) +void Node::SetNodeOff() { // Level is 0-99, with 0 = off and 99 = fully on. 255 = turn on at last level. - if( Basic* cc = static_cast( GetCommandClass( Basic::StaticGetCommandClassId() ) ) ) + if (Internal::CC::Basic* cc = static_cast(GetCommandClass(Internal::CC::Basic::StaticGetCommandClassId()))) { - cc->Set( 0 ); + cc->Set(0); } } @@ -2400,39 +2389,20 @@ void Node::SetNodeOff // // Helper to create a ValueID //----------------------------------------------------------------------------- -ValueID Node::CreateValueID -( - ValueID::ValueGenre const _genre, - uint8 const _commandClassId, - uint8 const _instance, - uint16 const _valueIndex, - ValueID::ValueType const _type -) +ValueID Node::CreateValueID(ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, ValueID::ValueType const _type) { - return ValueID( m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _type ); + return ValueID(m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _type); } //----------------------------------------------------------------------------- // // Helper to create a BitSet ValueID //----------------------------------------------------------------------------- -bool Node::CreateValueBitSet -( - ValueID::ValueGenre const _genre, - uint8 const _commandClassId, - uint8 const _instance, - uint16 const _valueIndex, - string const& _label, - string const& _units, - bool const _readOnly, - bool const _writeOnly, - int32 const _default, - uint8 const _pollIntensity -) +bool Node::CreateValueBitSet(ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, int32 const _default, uint8 const _pollIntensity) { - ValueBitSet* value = new ValueBitSet( m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _units, _readOnly, _writeOnly, _default, _pollIntensity ); - ValueStore* store = GetValueStore(); - if( store->AddValue( value ) ) + Internal::VC::ValueBitSet* value = new Internal::VC::ValueBitSet(m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _units, _readOnly, _writeOnly, _default, _pollIntensity); + Internal::VC::ValueStore* store = GetValueStore(); + if (store->AddValue(value)) { value->Release(); return true; @@ -2442,30 +2412,15 @@ bool Node::CreateValueBitSet return false; } - - - //----------------------------------------------------------------------------- // // Helper to create a new bool value and add it to the value store //----------------------------------------------------------------------------- -bool Node::CreateValueBool -( - ValueID::ValueGenre const _genre, - uint8 const _commandClassId, - uint8 const _instance, - uint16 const _valueIndex, - string const& _label, - string const& _units, - bool const _readOnly, - bool const _writeOnly, - bool const _default, - uint8 const _pollIntensity -) +bool Node::CreateValueBool(ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, bool const _default, uint8 const _pollIntensity) { - ValueBool* value = new ValueBool( m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _units, _readOnly, _writeOnly, _default, _pollIntensity ); - ValueStore* store = GetValueStore(); - if( store->AddValue( value ) ) + Internal::VC::ValueBool* value = new Internal::VC::ValueBool(m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _units, _readOnly, _writeOnly, _default, _pollIntensity); + Internal::VC::ValueStore* store = GetValueStore(); + if (store->AddValue(value)) { value->Release(); return true; @@ -2479,19 +2434,11 @@ bool Node::CreateValueBool // // Helper to create a new trigger value and add it to the value store //----------------------------------------------------------------------------- -bool Node::CreateValueButton -( - ValueID::ValueGenre const _genre, - uint8 const _commandClassId, - uint8 const _instance, - uint16 const _valueIndex, - string const& _label, - uint8 const _pollIntensity -) +bool Node::CreateValueButton(ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, uint8 const _pollIntensity) { - ValueButton* value = new ValueButton( m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _pollIntensity ); - ValueStore* store = GetValueStore(); - if( store->AddValue( value ) ) + Internal::VC::ValueButton* value = new Internal::VC::ValueButton(m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _pollIntensity); + Internal::VC::ValueStore* store = GetValueStore(); + if (store->AddValue(value)) { value->Release(); return true; @@ -2505,23 +2452,11 @@ bool Node::CreateValueButton // // Helper to create a new byte value and add it to the value store //----------------------------------------------------------------------------- -bool Node::CreateValueByte -( - ValueID::ValueGenre const _genre, - uint8 const _commandClassId, - uint8 const _instance, - uint16 const _valueIndex, - string const& _label, - string const& _units, - bool const _readOnly, - bool const _writeOnly, - uint8 const _default, - uint8 const _pollIntensity -) +bool Node::CreateValueByte(ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, uint8 const _default, uint8 const _pollIntensity) { - ValueByte* value = new ValueByte( m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _units, _readOnly, _writeOnly, _default, _pollIntensity ); - ValueStore* store = GetValueStore(); - if( store->AddValue( value ) ) + Internal::VC::ValueByte* value = new Internal::VC::ValueByte(m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _units, _readOnly, _writeOnly, _default, _pollIntensity); + Internal::VC::ValueStore* store = GetValueStore(); + if (store->AddValue(value)) { value->Release(); return true; @@ -2535,23 +2470,11 @@ bool Node::CreateValueByte // // Helper to create a new decimal value and add it to the value store //----------------------------------------------------------------------------- -bool Node::CreateValueDecimal -( - ValueID::ValueGenre const _genre, - uint8 const _commandClassId, - uint8 const _instance, - uint16 const _valueIndex, - string const& _label, - string const& _units, - bool const _readOnly, - bool const _writeOnly, - string const& _default, - uint8 const _pollIntensity -) +bool Node::CreateValueDecimal(ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, string const& _default, uint8 const _pollIntensity) { - ValueDecimal* value = new ValueDecimal( m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _units, _readOnly, _writeOnly, _default, _pollIntensity ); - ValueStore* store = GetValueStore(); - if( store->AddValue( value ) ) + Internal::VC::ValueDecimal* value = new Internal::VC::ValueDecimal(m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _units, _readOnly, _writeOnly, _default, _pollIntensity); + Internal::VC::ValueStore* store = GetValueStore(); + if (store->AddValue(value)) { value->Release(); return true; @@ -2565,23 +2488,11 @@ bool Node::CreateValueDecimal // // Helper to create a new int value and add it to the value store //----------------------------------------------------------------------------- -bool Node::CreateValueInt -( - ValueID::ValueGenre const _genre, - uint8 const _commandClassId, - uint8 const _instance, - uint16 const _valueIndex, - string const& _label, - string const& _units, - bool const _readOnly, - bool const _writeOnly, - int32 const _default, - uint8 const _pollIntensity -) +bool Node::CreateValueInt(ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, int32 const _default, uint8 const _pollIntensity) { - ValueInt* value = new ValueInt( m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _units, _readOnly, _writeOnly, _default, _pollIntensity ); - ValueStore* store = GetValueStore(); - if( store->AddValue( value ) ) + Internal::VC::ValueInt* value = new Internal::VC::ValueInt(m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _units, _readOnly, _writeOnly, _default, _pollIntensity); + Internal::VC::ValueStore* store = GetValueStore(); + if (store->AddValue(value)) { value->Release(); return true; @@ -2595,24 +2506,10 @@ bool Node::CreateValueInt // // Helper to create a new list value and add it to the value store //----------------------------------------------------------------------------- -bool Node::CreateValueList -( - ValueID::ValueGenre const _genre, - uint8 const _commandClassId, - uint8 const _instance, - uint16 const _valueIndex, - string const& _label, - string const& _units, - bool const _readOnly, - bool const _writeOnly, - uint8 const _size, - vector const& _items, - int32 const _default, - uint8 const _pollIntensity -) +bool Node::CreateValueList(ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, uint8 const _size, vector const& _items, int32 const _default, uint8 const _pollIntensity) { - ValueList* value = new ValueList(m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _units, _readOnly, _writeOnly, _items, _default, _pollIntensity, _size); - ValueStore* store = GetValueStore(); + Internal::VC::ValueList* value = new Internal::VC::ValueList(m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _units, _readOnly, _writeOnly, _items, _default, _pollIntensity, _size); + Internal::VC::ValueStore* store = GetValueStore(); if (store->AddValue(value)) { value->Release(); @@ -2626,24 +2523,11 @@ bool Node::CreateValueList // // Helper to create a new raw value and add it to the value store //----------------------------------------------------------------------------- -bool Node::CreateValueRaw -( - ValueID::ValueGenre const _genre, - uint8 const _commandClassId, - uint8 const _instance, - uint16 const _valueIndex, - string const& _label, - string const& _units, - bool const _readOnly, - bool const _writeOnly, - uint8 const* _default, - uint8 const _length, - uint8 const _pollIntensity -) +bool Node::CreateValueRaw(ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, uint8 const* _default, uint8 const _length, uint8 const _pollIntensity) { - ValueRaw* value = new ValueRaw( m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _units, _readOnly, _writeOnly, _default, _length, _pollIntensity ); - ValueStore* store = GetValueStore(); - if( store->AddValue( value ) ) + Internal::VC::ValueRaw* value = new Internal::VC::ValueRaw(m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _units, _readOnly, _writeOnly, _default, _length, _pollIntensity); + Internal::VC::ValueStore* store = GetValueStore(); + if (store->AddValue(value)) { value->Release(); return true; @@ -2657,22 +2541,11 @@ bool Node::CreateValueRaw // // Helper to create a new schedule value and add it to the value store //----------------------------------------------------------------------------- -bool Node::CreateValueSchedule -( - ValueID::ValueGenre const _genre, - uint8 const _commandClassId, - uint8 const _instance, - uint16 const _valueIndex, - string const& _label, - string const& _units, - bool const _readOnly, - bool const _writeOnly, - uint8 const _pollIntensity -) +bool Node::CreateValueSchedule(ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, uint8 const _pollIntensity) { - ValueSchedule* value = new ValueSchedule( m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _units, _readOnly, _writeOnly, _pollIntensity ); - ValueStore* store = GetValueStore(); - if( store->AddValue( value ) ) + Internal::VC::ValueSchedule* value = new Internal::VC::ValueSchedule(m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _units, _readOnly, _writeOnly, _pollIntensity); + Internal::VC::ValueStore* store = GetValueStore(); + if (store->AddValue(value)) { value->Release(); return true; @@ -2686,23 +2559,11 @@ bool Node::CreateValueSchedule // // Helper to create a new short value and add it to the value store //----------------------------------------------------------------------------- -bool Node::CreateValueShort -( - ValueID::ValueGenre const _genre, - uint8 const _commandClassId, - uint8 const _instance, - uint16 const _valueIndex, - string const& _label, - string const& _units, - bool const _readOnly, - bool const _writeOnly, - int16 const _default, - uint8 const _pollIntensity -) +bool Node::CreateValueShort(ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, int16 const _default, uint8 const _pollIntensity) { - ValueShort* value = new ValueShort( m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _units, _readOnly, _writeOnly, _default, _pollIntensity ); - ValueStore* store = GetValueStore(); - if( store->AddValue( value ) ) + Internal::VC::ValueShort* value = new Internal::VC::ValueShort(m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _units, _readOnly, _writeOnly, _default, _pollIntensity); + Internal::VC::ValueStore* store = GetValueStore(); + if (store->AddValue(value)) { value->Release(); return true; @@ -2716,23 +2577,11 @@ bool Node::CreateValueShort // // Helper to create a new string value and add it to the value store //----------------------------------------------------------------------------- -bool Node::CreateValueString -( - ValueID::ValueGenre const _genre, - uint8 const _commandClassId, - uint8 const _instance, - uint16 const _valueIndex, - string const& _label, - string const& _units, - bool const _readOnly, - bool const _writeOnly, - string const& _default, - uint8 const _pollIntensity -) +bool Node::CreateValueString(ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, string const& _default, uint8 const _pollIntensity) { - ValueString* value = new ValueString( m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _units, _readOnly, _writeOnly, _default, _pollIntensity ); - ValueStore* store = GetValueStore(); - if( store->AddValue( value ) ) + Internal::VC::ValueString* value = new Internal::VC::ValueString(m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _label, _units, _readOnly, _writeOnly, _default, _pollIntensity); + Internal::VC::ValueStore* store = GetValueStore(); + if (store->AddValue(value)) { value->Release(); return true; @@ -2746,58 +2595,97 @@ bool Node::CreateValueString // // Helper to remove an existing list value from the value store //----------------------------------------------------------------------------- -void Node::RemoveValueList -( - ValueList* _value -) +void Node::RemoveValueList(Internal::VC::ValueList* _value) { - ValueStore* store = GetValueStore(); - store->RemoveValue( _value->GetID().GetValueStoreKey() ); + Internal::VC::ValueStore* store = GetValueStore(); + store->RemoveValue(_value->GetID().GetValueStoreKey()); } //----------------------------------------------------------------------------- // // Get the value object with the specified ID //----------------------------------------------------------------------------- -bool Node::CreateValueFromXML -( - uint8 const _commandClassId, - TiXmlElement const* _valueElement -) +bool Node::CreateValueFromXML(uint8 const _commandClassId, TiXmlElement const* _valueElement) { - Value* value = NULL; + Internal::VC::Value* value = NULL; // Create the value - ValueID::ValueType type = Value::GetTypeEnumFromName( _valueElement->Attribute( "type" ) ); + ValueID::ValueType type = Internal::VC::Value::GetTypeEnumFromName(_valueElement->Attribute("type")); - switch( type ) + switch (type) { - case ValueID::ValueType_BitSet: { value = new ValueBitSet(); break; } - case ValueID::ValueType_Bool: { value = new ValueBool(); break; } - case ValueID::ValueType_Byte: { value = new ValueByte(); break; } - case ValueID::ValueType_Decimal: { value = new ValueDecimal(); break; } - case ValueID::ValueType_Int: { value = new ValueInt(); break; } - case ValueID::ValueType_List: { value = new ValueList(); break; } - case ValueID::ValueType_Schedule: { value = new ValueSchedule(); break; } - case ValueID::ValueType_Short: { value = new ValueShort(); break; } - case ValueID::ValueType_String: { value = new ValueString(); break; } - case ValueID::ValueType_Button: { value = new ValueButton(); break; } - case ValueID::ValueType_Raw: { value = new ValueRaw(); break; } + case ValueID::ValueType_BitSet: + { + value = new Internal::VC::ValueBitSet(); + break; + } + case ValueID::ValueType_Bool: + { + value = new Internal::VC::ValueBool(); + break; + } + case ValueID::ValueType_Byte: + { + value = new Internal::VC::ValueByte(); + break; + } + case ValueID::ValueType_Decimal: + { + value = new Internal::VC::ValueDecimal(); + break; + } + case ValueID::ValueType_Int: + { + value = new Internal::VC::ValueInt(); + break; + } + case ValueID::ValueType_List: + { + value = new Internal::VC::ValueList(); + break; + } + case ValueID::ValueType_Schedule: + { + value = new Internal::VC::ValueSchedule(); + break; + } + case ValueID::ValueType_Short: + { + value = new Internal::VC::ValueShort(); + break; + } + case ValueID::ValueType_String: + { + value = new Internal::VC::ValueString(); + break; + } + case ValueID::ValueType_Button: + { + value = new Internal::VC::ValueButton(); + break; + } + case ValueID::ValueType_Raw: + { + value = new Internal::VC::ValueRaw(); + break; + } } - if( value ) + if (value) { - value->ReadXML( m_homeId, m_nodeId, _commandClassId, _valueElement ); - ValueStore* store = GetValueStore(); - if( store->AddValue( value ) ) + value->ReadXML(m_homeId, m_nodeId, _commandClassId, _valueElement); + Internal::VC::ValueStore* store = GetValueStore(); + if (store->AddValue(value)) { value->Release(); return true; } value->Release(); - } else { - Log::Write( LogLevel_Info, m_nodeId, "Unknown ValueType in XML: %s", _valueElement->Attribute( "type" ) ); + } + else + { + Log::Write(LogLevel_Info, m_nodeId, "Unknown ValueType in XML: %s", _valueElement->Attribute("type")); } return false; @@ -2807,52 +2695,51 @@ bool Node::CreateValueFromXML // // Apply XML differences to a value //----------------------------------------------------------------------------- -void Node::ReadValueFromXML -( - uint8 const _commandClassId, - TiXmlElement const* _valueElement -) +void Node::ReadValueFromXML(uint8 const _commandClassId, TiXmlElement const* _valueElement) { int32 intVal; - ValueID::ValueGenre genre = Value::GetGenreEnumFromName( _valueElement->Attribute( "genre" ) ); - ValueID::ValueType type = Value::GetTypeEnumFromName( _valueElement->Attribute( "type" ) ); + ValueID::ValueGenre genre = Internal::VC::Value::GetGenreEnumFromName(_valueElement->Attribute("genre")); + ValueID::ValueType type = Internal::VC::Value::GetTypeEnumFromName(_valueElement->Attribute("type")); uint8 instance = 0; - if( TIXML_SUCCESS == _valueElement->QueryIntAttribute( "instance", &intVal ) ) + if (TIXML_SUCCESS == _valueElement->QueryIntAttribute("instance", &intVal)) { - instance = (uint8)intVal; + instance = (uint8) intVal; } uint16 index = 0; - if( TIXML_SUCCESS == _valueElement->QueryIntAttribute( "index", &intVal ) ) + if (TIXML_SUCCESS == _valueElement->QueryIntAttribute("index", &intVal)) { - index = (uint16)intVal; + index = (uint16) intVal; } - ValueID id = ValueID( m_homeId, m_nodeId, genre, _commandClassId, instance, index, type ); + ValueID id = ValueID(m_homeId, m_nodeId, genre, _commandClassId, instance, index, type); // Try to get the value from the ValueStore (everything except configuration parameters // should already have been created when the command class instance count was read in). // Create it if it doesn't already exist. - if( ValueStore* store = GetValueStore() ) + if (Internal::VC::ValueStore* store = GetValueStore()) { - if( Value* value = store->GetValue( id.GetValueStoreKey() ) ) + if (Internal::VC::Value* value = store->GetValue(id.GetValueStoreKey())) { // Check if values type are the same ValueID::ValueType v_type = value->GetID().GetType(); - if ( v_type == type ) { - value->ReadXML( m_homeId, m_nodeId, _commandClassId, _valueElement ); + if (v_type == type) + { + value->ReadXML(m_homeId, m_nodeId, _commandClassId, _valueElement); value->Release(); - } else { - Log::Write( LogLevel_Info, m_nodeId, "xml value type (%s) is different to stored value type (%s). Value is recreate with xml params.", value->GetTypeNameFromEnum(type), value->GetTypeNameFromEnum(v_type) ); - store->RemoveValue( value->GetID().GetValueStoreKey() ); - CreateValueFromXML( _commandClassId, _valueElement ); + } + else + { + Log::Write(LogLevel_Info, m_nodeId, "xml value type (%s) is different to stored value type (%s). Value is recreate with xml params.", value->GetTypeNameFromEnum(type), value->GetTypeNameFromEnum(v_type)); + store->RemoveValue(value->GetID().GetValueStoreKey()); + CreateValueFromXML(_commandClassId, _valueElement); } } else { - CreateValueFromXML( _commandClassId, _valueElement ); + CreateValueFromXML(_commandClassId, _valueElement); } } } @@ -2861,30 +2748,22 @@ void Node::ReadValueFromXML // // Get the value object with the specified ID //----------------------------------------------------------------------------- -Value* Node::GetValue -( - ValueID const& _id -) +Internal::VC::Value* Node::GetValue(ValueID const& _id) { // This increments the value's reference count - return GetValueStore()->GetValue( _id.GetValueStoreKey() ); + return GetValueStore()->GetValue(_id.GetValueStoreKey()); } //----------------------------------------------------------------------------- // // Get the value object with the specified settings //----------------------------------------------------------------------------- -Value* Node::GetValue -( - uint8 const _commandClassId, - uint8 const _instance, - uint16 const _valueIndex -) +Internal::VC::Value* Node::GetValue(uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex) { - Value* value = NULL; - ValueStore* store = GetValueStore(); + Internal::VC::Value* value = NULL; + Internal::VC::ValueStore* store = GetValueStore(); // This increments the value's reference count - value = store->GetValue( ValueID::GetValueStoreKey( _commandClassId, _instance, _valueIndex ) ); + value = store->GetValue(ValueID::GetValueStoreKey(_commandClassId, _instance, _valueIndex)); return value; } @@ -2892,28 +2771,20 @@ Value* Node::GetValue // // Remove the value object with the specified settings //----------------------------------------------------------------------------- -bool Node::RemoveValue -( - uint8 const _commandClassId, - uint8 const _instance, - uint16 const _valueIndex -) +bool Node::RemoveValue(uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex) { - ValueStore* store = GetValueStore(); - return store->RemoveValue( ValueID::GetValueStoreKey( _commandClassId, _instance, _valueIndex ) ); + Internal::VC::ValueStore* store = GetValueStore(); + return store->RemoveValue(ValueID::GetValueStoreKey(_commandClassId, _instance, _valueIndex)); } //----------------------------------------------------------------------------- // // Get a Group from the node's map //----------------------------------------------------------------------------- -Group* Node::GetGroup -( - uint8 const _groupIdx -) +Group* Node::GetGroup(uint8 const _groupIdx) { - map::iterator it = m_groups.find( _groupIdx ); - if( it == m_groups.end() ) + map::iterator it = m_groups.find(_groupIdx); + if (it == m_groups.end()) { return NULL; } @@ -2925,17 +2796,14 @@ Group* Node::GetGroup // // Add a group into the node's map //----------------------------------------------------------------------------- -void Node::AddGroup -( - Group* _group -) +void Node::AddGroup(Group* _group) { - map::iterator it = m_groups.find( _group->GetIdx() ); - if( it != m_groups.end() ) + map::iterator it = m_groups.find(_group->GetIdx()); + if (it != m_groups.end()) { // There is already a group with this id. We will replace it. delete it->second; - m_groups.erase( it ); + m_groups.erase(it); } m_groups[_group->GetIdx()] = _group; @@ -2945,18 +2813,15 @@ void Node::AddGroup // // Save the group data //----------------------------------------------------------------------------- -void Node::WriteGroups -( - TiXmlElement* _associationsElement -) +void Node::WriteGroups(TiXmlElement* _associationsElement) { - for( map::iterator it = m_groups.begin(); it != m_groups.end(); ++it ) + for (map::iterator it = m_groups.begin(); it != m_groups.end(); ++it) { Group* group = it->second; - TiXmlElement* groupElement = new TiXmlElement( "Group" ); - _associationsElement->LinkEndChild( groupElement ); - group->WriteXML( groupElement ); + TiXmlElement* groupElement = new TiXmlElement("Group"); + _associationsElement->LinkEndChild(groupElement); + group->WriteXML(groupElement); } } @@ -2964,9 +2829,7 @@ void Node::WriteGroups // // Gets the number of association groups reported by this node //----------------------------------------------------------------------------- -uint8 Node::GetNumGroups -( -) +uint8 Node::GetNumGroups() { return (uint8) m_groups.size(); } @@ -2975,16 +2838,12 @@ uint8 Node::GetNumGroups // // Gets the associations for a group //----------------------------------------------------------------------------- -uint32 Node::GetAssociations -( - uint8 const _groupIdx, - uint8** o_associations -) +uint32 Node::GetAssociations(uint8 const _groupIdx, uint8** o_associations) { uint32 numAssociations = 0; - if( Group* group = GetGroup( _groupIdx ) ) + if (Group* group = GetGroup(_groupIdx)) { - numAssociations = group->GetAssociations( o_associations ); + numAssociations = group->GetAssociations(o_associations); } return numAssociations; @@ -2994,16 +2853,12 @@ uint32 Node::GetAssociations // // Gets the associations for a group //----------------------------------------------------------------------------- -uint32 Node::GetAssociations -( - uint8 const _groupIdx, - InstanceAssociation** o_associations -) +uint32 Node::GetAssociations(uint8 const _groupIdx, InstanceAssociation** o_associations) { uint32 numAssociations = 0; - if( Group* group = GetGroup( _groupIdx ) ) + if (Group* group = GetGroup(_groupIdx)) { - numAssociations = group->GetAssociations( o_associations ); + numAssociations = group->GetAssociations(o_associations); } return numAssociations; @@ -3013,13 +2868,10 @@ uint32 Node::GetAssociations // // Gets the maximum number of associations for a group //----------------------------------------------------------------------------- -uint8 Node::GetMaxAssociations -( - uint8 const _groupIdx -) +uint8 Node::GetMaxAssociations(uint8 const _groupIdx) { uint8 maxAssociations = 0; - if( Group* group = GetGroup( _groupIdx ) ) + if (Group* group = GetGroup(_groupIdx)) { maxAssociations = group->GetMaxAssociations(); } @@ -3031,13 +2883,10 @@ uint8 Node::GetMaxAssociations // // Returns true if group supports multi instance //----------------------------------------------------------------------------- -bool Node::IsMultiInstance -( - uint8 const _groupIdx -) +bool Node::IsMultiInstance(uint8 const _groupIdx) { bool multiInstance = false; - if( Group* group = GetGroup( _groupIdx ) ) + if (Group* group = GetGroup(_groupIdx)) { multiInstance = group->IsMultiInstance(); } @@ -3048,13 +2897,10 @@ bool Node::IsMultiInstance // // Gets the label for a particular group //----------------------------------------------------------------------------- -string Node::GetGroupLabel -( - uint8 const _groupIdx -) +string Node::GetGroupLabel(uint8 const _groupIdx) { string label = ""; - if( Group* group = GetGroup( _groupIdx ) ) + if (Group* group = GetGroup(_groupIdx)) { label = group->GetLabel(); } @@ -3066,16 +2912,11 @@ string Node::GetGroupLabel // // Adds a node to an association group //----------------------------------------------------------------------------- -void Node::AddAssociation -( - uint8 const _groupIdx, - uint8 const _targetNodeId, - uint8 const _instance -) +void Node::AddAssociation(uint8 const _groupIdx, uint8 const _targetNodeId, uint8 const _instance) { - if( Group* group = GetGroup( _groupIdx ) ) + if (Group* group = GetGroup(_groupIdx)) { - group->AddAssociation( _targetNodeId, _instance ); + group->AddAssociation(_targetNodeId, _instance); } } @@ -3083,16 +2924,11 @@ void Node::AddAssociation // // Removes a node from an association group //----------------------------------------------------------------------------- -void Node::RemoveAssociation -( - uint8 const _groupIdx, - uint8 const _targetNodeId, - uint8 const _instance -) +void Node::RemoveAssociation(uint8 const _groupIdx, uint8 const _targetNodeId, uint8 const _instance) { - if( Group* group = GetGroup( _groupIdx ) ) + if (Group* group = GetGroup(_groupIdx)) { - group->RemoveAssociation( _targetNodeId, _instance ); + group->RemoveAssociation(_targetNodeId, _instance); } } @@ -3100,25 +2936,23 @@ void Node::RemoveAssociation // // Automatically associate the controller with certain groups //----------------------------------------------------------------------------- -void Node::AutoAssociate -( -) +void Node::AutoAssociate() { bool autoAssociate = false; - Options::Get()->GetOptionAsBool( "Associate", &autoAssociate ); - if( autoAssociate ) + Options::Get()->GetOptionAsBool("Associate", &autoAssociate); + if (autoAssociate) { // Try to automatically associate with any groups that have been flagged. uint8 controllerNodeId = GetDriver()->GetControllerNodeId(); - for( map::iterator it = m_groups.begin(); it != m_groups.end(); ++it ) + for (map::iterator it = m_groups.begin(); it != m_groups.end(); ++it) { Group* group = it->second; - if( group->IsAuto() && !group->Contains( controllerNodeId ) ) + if (group->IsAuto() && !group->Contains(controllerNodeId)) { // Associate the controller into the group - Log::Write( LogLevel_Info, m_nodeId, "Adding the controller to group %d (%s) of node %d", group->GetIdx(), group->GetLabel().c_str(), GetNodeId() ); - group->AddAssociation( controllerNodeId ); + Log::Write(LogLevel_Info, m_nodeId, "Adding the controller to group %d (%s) of node %d", group->GetIdx(), group->GetLabel().c_str(), GetNodeId()); + group->AddAssociation(controllerNodeId); } } } @@ -3128,11 +2962,9 @@ void Node::AutoAssociate // // Get a pointer to our driver //----------------------------------------------------------------------------- -Driver* Node::GetDriver -( -)const +Driver* Node::GetDriver() const { - return( Manager::Get()->GetDriver( m_homeId ) ); + return (Manager::Get()->GetDriver(m_homeId)); } //----------------------------------------------------------------------------- @@ -3143,33 +2975,29 @@ Driver* Node::GetDriver // // Use the device class data to get a label for a MultiChannel EndPoint. //----------------------------------------------------------------------------- -string Node::GetEndPointDeviceClassLabel -( - uint8 const _generic, - uint8 const _specific -) +string Node::GetEndPointDeviceClassLabel(uint8 const _generic, uint8 const _specific) { char str[32]; string label; - snprintf( str, sizeof(str), "Generic 0x%.2x Specific 0x%.2x", _generic, _specific ); + snprintf(str, sizeof(str), "Generic 0x%.2x Specific 0x%.2x", _generic, _specific); label = str; // Read in the device class data if it has not been read already. - if( !s_deviceClassesLoaded ) + if (!s_deviceClassesLoaded) { ReadDeviceClasses(); } // Get the Generic device class label - map::iterator git = s_genericDeviceClasses.find( _generic ); - if( git != s_genericDeviceClasses.end() ) + map::iterator git = s_genericDeviceClasses.find(_generic); + if (git != s_genericDeviceClasses.end()) { GenericDeviceClass* genericDeviceClass = git->second; label = genericDeviceClass->GetLabel(); // Override with any specific device class label - if( DeviceClass* specificDeviceClass = genericDeviceClass->GetSpecificDeviceClass( _specific ) ) + if (DeviceClass* specificDeviceClass = genericDeviceClass->GetSpecificDeviceClass(_specific)) { label = specificDeviceClass->GetLabel(); } @@ -3182,62 +3010,57 @@ string Node::GetEndPointDeviceClassLabel // // Set the device class data for the node //----------------------------------------------------------------------------- -bool Node::SetDeviceClasses -( - uint8 const _basic, - uint8 const _generic, - uint8 const _specific -) +bool Node::SetDeviceClasses(uint8 const _basic, uint8 const _generic, uint8 const _specific) { m_basic = _basic; m_generic = _generic; m_specific = _specific; // Read in the device class data if it has not been read already. - if( !s_deviceClassesLoaded ) + if (!s_deviceClassesLoaded) { ReadDeviceClasses(); } // Get the basic device class label - map::iterator bit = s_basicDeviceClasses.find( _basic ); - if( bit != s_basicDeviceClasses.end() ) + map::iterator bit = s_basicDeviceClasses.find(_basic); + if (bit != s_basicDeviceClasses.end()) { m_type = bit->second; - Log::Write( LogLevel_Info, m_nodeId, " Basic device class (0x%.2x) - %s", m_basic, m_type.c_str() ); + Log::Write(LogLevel_Info, m_nodeId, " Basic device class (0x%.2x) - %s", m_basic, m_type.c_str()); } else { - Log::Write( LogLevel_Info, m_nodeId, " Basic device class unknown" ); + Log::Write(LogLevel_Info, m_nodeId, " Basic device class unknown"); } // Apply any Generic device class data uint8 basicMapping = 0; - map::iterator git = s_genericDeviceClasses.find( _generic ); - if( git != s_genericDeviceClasses.end() ) + map::iterator git = s_genericDeviceClasses.find(_generic); + if (git != s_genericDeviceClasses.end()) { GenericDeviceClass* genericDeviceClass = git->second; m_type = genericDeviceClass->GetLabel(); - Log::Write( LogLevel_Info, m_nodeId, " Generic device Class (0x%.2x) - %s", m_generic, m_type.c_str() ); + Log::Write(LogLevel_Info, m_nodeId, " Generic device Class (0x%.2x) - %s", m_generic, m_type.c_str()); // Add the mandatory command classes for this generic class type - AddMandatoryCommandClasses( genericDeviceClass->GetMandatoryCommandClasses() ); + AddMandatoryCommandClasses(genericDeviceClass->GetMandatoryCommandClasses()); // Get the command class that COMMAND_CLASS_BASIC maps to. basicMapping = genericDeviceClass->GetBasicMapping(); // Apply any Specific device class data - if( DeviceClass* specificDeviceClass = genericDeviceClass->GetSpecificDeviceClass( _specific ) ) + if (DeviceClass* specificDeviceClass = genericDeviceClass->GetSpecificDeviceClass(_specific)) { m_type = specificDeviceClass->GetLabel(); - Log::Write( LogLevel_Info, m_nodeId, " Specific device class (0x%.2x) - %s", m_specific, m_type.c_str() ); + Log::Write(LogLevel_Info, m_nodeId, " Specific device class (0x%.2x) - %s", m_specific, m_type.c_str()); // Add the mandatory command classes for this specific class type - AddMandatoryCommandClasses( specificDeviceClass->GetMandatoryCommandClasses() ); + AddMandatoryCommandClasses(specificDeviceClass->GetMandatoryCommandClasses()); - if( specificDeviceClass->GetBasicMapping() ) + if (specificDeviceClass->GetBasicMapping()) { // Override the generic device class basic mapping with the specific device class one. basicMapping = specificDeviceClass->GetBasicMapping(); @@ -3245,65 +3068,65 @@ bool Node::SetDeviceClasses } else { - Log::Write( LogLevel_Info, m_nodeId, " No specific device class defined" ); + Log::Write(LogLevel_Info, m_nodeId, " No specific device class defined"); } } else { - Log::Write( LogLevel_Info, m_nodeId, " No generic or specific device classes defined" ); + Log::Write(LogLevel_Info, m_nodeId, " No generic or specific device classes defined"); } // Deal with sleeping devices - if( !m_listening && !IsFrequentListeningDevice()) + if (!m_listening && !IsFrequentListeningDevice()) { // Device does not always listen, so we need the WakeUp handler. We can't // wait for the command class list because the request for the command // classes may need to go in the wakeup queue itself! - if( CommandClass* pCommandClass = AddCommandClass( WakeUp::StaticGetCommandClassId() ) ) + if (Internal::CC::CommandClass* pCommandClass = AddCommandClass(Internal::CC::WakeUp::StaticGetCommandClassId())) { - pCommandClass->SetInstance( 1 ); + pCommandClass->SetInstance(1); } } // Apply any COMMAND_CLASS_BASIC remapping - if( Basic* cc = static_cast( GetCommandClass( Basic::StaticGetCommandClassId() ) ) ) + if (Internal::CC::Basic* cc = static_cast(GetCommandClass(Internal::CC::Basic::StaticGetCommandClassId()))) { - cc->SetMapping( basicMapping ); + cc->SetMapping(basicMapping); } // Write the mandatory command classes to the log - if( !m_commandClassMap.empty() ) + if (!m_commandClassMap.empty()) { - map::const_iterator cit; + map::const_iterator cit; - Log::Write( LogLevel_Info, m_nodeId, " Mandatory Command Classes for Node %d:", m_nodeId ); + Log::Write(LogLevel_Info, m_nodeId, " Mandatory Command Classes for Node %d:", m_nodeId); bool reportedClasses = false; - for( cit = m_commandClassMap.begin(); cit != m_commandClassMap.end(); ++cit ) + for (cit = m_commandClassMap.begin(); cit != m_commandClassMap.end(); ++cit) { - if( !cit->second->IsAfterMark() && cit->second->GetCommandClassId() != NoOperation::StaticGetCommandClassId() ) + if (!cit->second->IsAfterMark() && cit->second->GetCommandClassId() != Internal::CC::NoOperation::StaticGetCommandClassId()) { - Log::Write( LogLevel_Info, m_nodeId, " %s", cit->second->GetCommandClassName().c_str() ); + Log::Write(LogLevel_Info, m_nodeId, " %s", cit->second->GetCommandClassName().c_str()); reportedClasses = true; } } - if( !reportedClasses ) + if (!reportedClasses) { - Log::Write( LogLevel_Info, m_nodeId, " None" ); + Log::Write(LogLevel_Info, m_nodeId, " None"); } - Log::Write( LogLevel_Info, m_nodeId, " Mandatory Command Classes controlled by Node %d:", m_nodeId ); + Log::Write(LogLevel_Info, m_nodeId, " Mandatory Command Classes controlled by Node %d:", m_nodeId); reportedClasses = false; - for( cit = m_commandClassMap.begin(); cit != m_commandClassMap.end(); ++cit ) + for (cit = m_commandClassMap.begin(); cit != m_commandClassMap.end(); ++cit) { - if( cit->second->IsAfterMark() ) + if (cit->second->IsAfterMark()) { - Log::Write( LogLevel_Info, m_nodeId, " %s", cit->second->GetCommandClassName().c_str() ); + Log::Write(LogLevel_Info, m_nodeId, " %s", cit->second->GetCommandClassName().c_str()); reportedClasses = true; } } - if( !reportedClasses ) + if (!reportedClasses) { - Log::Write( LogLevel_Info, m_nodeId, " None" ); + Log::Write(LogLevel_Info, m_nodeId, " None"); } } @@ -3314,19 +3137,14 @@ bool Node::SetDeviceClasses // // Set the device class data for the node based on the Zwave+ info report //----------------------------------------------------------------------------- -bool Node::SetPlusDeviceClasses -( - uint8 const _role, - uint8 const _nodeType, - uint16 const _deviceType -) +bool Node::SetPlusDeviceClasses(uint8 const _role, uint8 const _nodeType, uint16 const _deviceType) { - if ( m_nodePlusInfoReceived ) + if (m_nodePlusInfoReceived) { return false; // already set } - if( !s_deviceClassesLoaded ) + if (!s_deviceClassesLoaded) { ReadDeviceClasses(); } @@ -3336,13 +3154,13 @@ bool Node::SetPlusDeviceClasses m_deviceType = _deviceType; m_nodeType = _nodeType; - Log::Write (LogLevel_Info, m_nodeId, "ZWave+ Info Received from Node %d", m_nodeId); - map::iterator nit = s_nodeTypes.find( m_nodeType ); + Log::Write(LogLevel_Info, m_nodeId, "ZWave+ Info Received from Node %d", m_nodeId); + map::iterator nit = s_nodeTypes.find(m_nodeType); if (nit != s_nodeTypes.end()) { DeviceClass* deviceClass = nit->second; - Log::Write( LogLevel_Info, m_nodeId, " Zwave+ Node Type (0x%.2x) - %s. Mandatory Command Classes:", m_nodeType, deviceClass->GetLabel().c_str() ); + Log::Write(LogLevel_Info, m_nodeId, " Zwave+ Node Type (0x%02x) - %s. Mandatory Command Classes:", m_nodeType, deviceClass->GetLabel().c_str()); uint8 const *_commandClasses = deviceClass->GetMandatoryCommandClasses(); /* no CommandClasses to add */ @@ -3351,39 +3169,37 @@ bool Node::SetPlusDeviceClasses int i = 0; while (uint8 ccid = _commandClasses[i++]) { - if( CommandClasses::IsSupported( ccid ) ) + if (Internal::CC::CommandClasses::IsSupported(ccid)) { - Log::Write( LogLevel_Info, m_nodeId, " %s", CommandClasses::GetName(ccid).c_str()); + Log::Write(LogLevel_Info, m_nodeId, " %s", Internal::CC::CommandClasses::GetName(ccid).c_str()); } else { - Log::Write( LogLevel_Info, m_nodeId, " 0x%.2x (Not Supported)", ccid); + Log::Write(LogLevel_Info, m_nodeId, " 0x%02x (Not Supported)", ccid); } } - // Add the mandatory command classes for this Roletype - AddMandatoryCommandClasses( deviceClass->GetMandatoryCommandClasses() ); + AddMandatoryCommandClasses(deviceClass->GetMandatoryCommandClasses()); } else { - Log::Write( LogLevel_Info, m_nodeId, " NONE"); + Log::Write(LogLevel_Info, m_nodeId, " NONE"); } } else { - Log::Write (LogLevel_Warning, m_nodeId, " Zwave+ Node Type (0x%.2x) - NOT FOUND. No Mandatory Command Classes Loaded:", m_nodeType); + Log::Write(LogLevel_Warning, m_nodeId, " Zwave+ Node Type (0x%02x) - NOT FOUND. No Mandatory Command Classes Loaded:", m_nodeType); } - // Apply any Zwave+ device class data - map::iterator dit = s_deviceTypeClasses.find( _deviceType ); - if( dit != s_deviceTypeClasses.end() ) + map::iterator dit = s_deviceTypeClasses.find(_deviceType); + if (dit != s_deviceTypeClasses.end()) { DeviceClass* deviceClass = dit->second; // m_type = deviceClass->GetLabel(); // do we what to update the type with the zwave+ info?? - Log::Write( LogLevel_Info, m_nodeId, " Zwave+ Device Type (0x%.2x) - %s. Mandatory Command Classes:", _deviceType, deviceClass->GetLabel().c_str() ); + Log::Write(LogLevel_Info, m_nodeId, " Zwave+ Device Type (0x%04x) - %s. Mandatory Command Classes:", _deviceType, deviceClass->GetLabel().c_str()); uint8 const *_commandClasses = deviceClass->GetMandatoryCommandClasses(); /* no CommandClasses to add */ @@ -3392,37 +3208,36 @@ bool Node::SetPlusDeviceClasses int i = 0; while (uint8 ccid = _commandClasses[i++]) { - if( CommandClasses::IsSupported( ccid ) ) + if (Internal::CC::CommandClasses::IsSupported(ccid)) { - Log::Write( LogLevel_Info, m_nodeId, " %s", CommandClasses::GetName(ccid).c_str()); + Log::Write(LogLevel_Info, m_nodeId, " %s", Internal::CC::CommandClasses::GetName(ccid).c_str()); } else { - Log::Write( LogLevel_Info, m_nodeId, " 0x%.2x (Not Supported)", ccid); + Log::Write(LogLevel_Info, m_nodeId, " 0x%02x (Not Supported)", ccid); } } - // Add the mandatory command classes for this device class type - AddMandatoryCommandClasses( deviceClass->GetMandatoryCommandClasses() ); + AddMandatoryCommandClasses(deviceClass->GetMandatoryCommandClasses()); } else { - Log::Write( LogLevel_Info, m_nodeId, " NONE"); + Log::Write(LogLevel_Info, m_nodeId, " NONE"); } } else { - Log::Write (LogLevel_Warning, m_nodeId, " Zwave+ Device Type (0x%.2x) - NOT FOUND. No Mandatory Command Classes Loaded:", m_nodeType); + Log::Write(LogLevel_Warning, m_nodeId, " Zwave+ Device Type (0x%04x) - NOT FOUND. No Mandatory Command Classes Loaded:", _deviceType); } // Apply any Role device class data - map::iterator rit = s_roleDeviceClasses.find( _role ); - if( rit != s_roleDeviceClasses.end() ) + map::iterator rit = s_roleDeviceClasses.find(_role); + if (rit != s_roleDeviceClasses.end()) { DeviceClass* roleDeviceClass = rit->second; - Log::Write( LogLevel_Info, m_nodeId, " ZWave+ Role Type (0x%.2x) - %s", m_generic, roleDeviceClass->GetLabel().c_str() ); + Log::Write(LogLevel_Info, m_nodeId, " ZWave+ Role Type (0x%02x) - %s", _role, roleDeviceClass->GetLabel().c_str()); uint8 const *_commandClasses = roleDeviceClass->GetMandatoryCommandClasses(); @@ -3432,32 +3247,30 @@ bool Node::SetPlusDeviceClasses int i = 0; while (uint8 ccid = _commandClasses[i++]) { - if( CommandClasses::IsSupported( ccid ) ) + if (Internal::CC::CommandClasses::IsSupported(ccid)) { - Log::Write( LogLevel_Info, m_nodeId, " %s", CommandClasses::GetName(ccid).c_str()); + Log::Write(LogLevel_Info, m_nodeId, " %s", Internal::CC::CommandClasses::GetName(ccid).c_str()); } else { - Log::Write( LogLevel_Info, m_nodeId, " 0x%.2x (Not Supported)", ccid); + Log::Write(LogLevel_Info, m_nodeId, " 0x%02x (Not Supported)", ccid); } } - // Add the mandatory command classes for this role class type - AddMandatoryCommandClasses( roleDeviceClass->GetMandatoryCommandClasses() ); + AddMandatoryCommandClasses(roleDeviceClass->GetMandatoryCommandClasses()); } else { - Log::Write( LogLevel_Info, m_nodeId, " NONE"); + Log::Write(LogLevel_Info, m_nodeId, " NONE"); } } else { - Log::Write (LogLevel_Warning, m_nodeId, " ZWave+ Role Type (0x%.2x) - NOT FOUND. No Mandatory Command Classes Loaded:", m_nodeType); + Log::Write(LogLevel_Warning, m_nodeId, " ZWave+ Role Type (0x%02x) - NOT FOUND. No Mandatory Command Classes Loaded:", _role); } - return true; } @@ -3465,22 +3278,19 @@ bool Node::SetPlusDeviceClasses // // Add mandatory command classes to the node //----------------------------------------------------------------------------- -bool Node::AddMandatoryCommandClasses -( - uint8 const* _commandClasses -) +bool Node::AddMandatoryCommandClasses(uint8 const* _commandClasses) { - if( NULL == _commandClasses ) + if ( NULL == _commandClasses) { // No command classes to add return false; } - int i=0; + int i = 0; bool afterMark = false; - while( uint8 cc = _commandClasses[i++] ) + while (uint8 cc = _commandClasses[i++]) { - if( cc == 0xef ) + if (cc == 0xef) { // COMMAND_CLASS_MARK. // Marks the end of the list of supported command classes. The remaining classes @@ -3489,24 +3299,25 @@ bool Node::AddMandatoryCommandClasses continue; } - if( CommandClasses::IsSupported( cc ) ) + if (Internal::CC::CommandClasses::IsSupported(cc)) { - if (Security::StaticGetCommandClassId() == cc && !GetDriver()->isNetworkKeySet()) { + if (Internal::CC::Security::StaticGetCommandClassId() == cc && !GetDriver()->isNetworkKeySet()) + { Log::Write(LogLevel_Warning, m_nodeId, "Security Command Class Cannot be Enabled - NetworkKey is not set"); continue; } - if( CommandClass* commandClass = AddCommandClass( cc ) ) + if (Internal::CC::CommandClass* commandClass = AddCommandClass(cc)) { // If this class came after the COMMAND_CLASS_MARK, then we do not create values. - if( afterMark ) + if (afterMark) { commandClass->SetAfterMark(); } // Start with an instance count of one. If the device supports COMMMAND_CLASS_MULTI_INSTANCE // then some command class instance counts will increase. - commandClass->SetInstance( 1 ); + commandClass->SetInstance(1); } } } @@ -3518,63 +3329,81 @@ bool Node::AddMandatoryCommandClasses // // Read the static device class data from the device_classes.xml file //----------------------------------------------------------------------------- -void Node::ReadDeviceClasses -( -) +void Node::ReadDeviceClasses() { // Load the XML document that contains the device class information string configPath; - Options::Get()->GetOptionAsString( "ConfigPath", &configPath ); + Options::Get()->GetOptionAsString("ConfigPath", &configPath); - string filename = configPath + string("device_classes.xml"); + string filename = configPath + string("device_classes.xml"); TiXmlDocument doc; - if( !doc.LoadFile( filename.c_str(), TIXML_ENCODING_UTF8 ) ) + if (!doc.LoadFile(filename.c_str(), TIXML_ENCODING_UTF8)) { - Log::Write( LogLevel_Info, "Failed to load device_classes.xml" ); - Log::Write( LogLevel_Info, "Check that the config path provided when creating the Manager points to the correct location." ); + Log::Write(LogLevel_Info, "Failed to load device_classes.xml"); + Log::Write(LogLevel_Info, "Check that the config path provided when creating the Manager points to the correct location."); return; } - doc.SetUserData((void *)filename.c_str()); + doc.SetUserData((void *) filename.c_str()); TiXmlElement const* deviceClassesElement = doc.RootElement(); // Read the basic and generic device classes TiXmlElement const* child = deviceClassesElement->FirstChildElement(); - while( child ) + while (child) { char const* str = child->Value(); - if( str ) + if (str) { - char const* keyStr = child->Attribute( "key" ); - if( keyStr ) + char const* keyStr = child->Attribute("key"); + if (keyStr) { char* pStop; /* we do a short here, as they key can be a DeviceType Key which is short */ - uint16_t key = (uint16)strtol( keyStr, &pStop, 16 ); + uint16_t key = (uint16) strtol(keyStr, &pStop, 16); - if( !strcmp( str, "Generic" ) ) + if (!strcmp(str, "Generic")) { - s_genericDeviceClasses[(uint8_t)(key & 0xFF)] = new GenericDeviceClass( child ); + if (s_genericDeviceClasses.find((uint8_t)(key & 0xFF)) == s_genericDeviceClasses.end()) { + s_genericDeviceClasses[(uint8_t) (key & 0xFF)] = new GenericDeviceClass(child); + } else { + Log::Write(LogLevel_Warning, "Duplicate Entry for Generic Device Class %d", key); + } } - else if( !strcmp( str, "Basic" ) ) + else if (!strcmp(str, "Basic")) { - char const* label = child->Attribute( "label" ); - if( label ) - { - s_basicDeviceClasses[(uint8_t)(key & 0xFF)] = label; + if (s_basicDeviceClasses.find((uint8_t)(key & 0xFF)) == s_basicDeviceClasses.end()) { + char const* label = child->Attribute("label"); + if (label) + { + s_basicDeviceClasses[(uint8_t) (key & 0xFF)] = label; + } + } else { + Log::Write(LogLevel_Warning, "Duplicate Entry for Basic Device Class %d", key); } } - else if( !strcmp( str, "Role" ) ) + else if (!strcmp(str, "Role")) { - s_roleDeviceClasses[(uint8_t)(key & 0xFF)] = new DeviceClass( child ); + if (s_roleDeviceClasses.find((uint8_t)(key & 0xFF)) == s_roleDeviceClasses.end()) { + s_roleDeviceClasses[(uint8_t) (key & 0xFF)] = new DeviceClass(child); + } else { + Log::Write(LogLevel_Warning, "Duplicate Entry for Role Device Classes %d", key); + } } - else if( !strcmp( str, "DeviceType" ) ) + else if (!strcmp(str, "DeviceType")) { - s_deviceTypeClasses[key] = new DeviceClass( child ); + if (s_deviceTypeClasses.find(key) == s_deviceTypeClasses.end()) { + s_deviceTypeClasses[key] = new DeviceClass(child); + } else { + Log::Write(LogLevel_Warning, "Duplicate Entry for Device Type Class %d", key); + } } - else if (!strcmp( str, "NodeType" ) ) + else if (!strcmp(str, "NodeType")) { - s_nodeTypes[(uint8_t)(key & 0xFF)] = new DeviceClass( child ); + if (s_nodeTypes.find((uint8_t)(key & 0xFF)) == s_nodeTypes.end()) { + s_nodeTypes[(uint8_t) (key & 0xFF)] = new DeviceClass(child); + } else { + Log::Write(LogLevel_Warning, "Duplicate Entry for Node Type %d", key); + } } } } @@ -3589,10 +3418,7 @@ void Node::ReadDeviceClasses // // Return driver statistics //----------------------------------------------------------------------------- -void Node::GetNodeStatistics -( - NodeData* _data -) +void Node::GetNodeStatistics(NodeData* _data) { _data->m_sentCnt = m_sentCnt; _data->m_sentFailed = m_sentFailed; @@ -3625,20 +3451,20 @@ void Node::GetNodeStatistics _data->m_routeUsed[2] = m_routeUsed[2]; _data->m_routeUsed[3] = m_routeUsed[3]; //petergebruers: missed m_routeSpeed - _data->m_routeSpeed= m_routeSpeed; + _data->m_routeSpeed = m_routeSpeed; _data->m_routeTries = m_routeTries; _data->m_lastFailedLinkFrom = m_lastFailedLinkFrom; _data->m_lastFailedLinkTo = m_lastFailedLinkTo; _data->m_quality = m_quality; - memcpy( _data->m_lastReceivedMessage, m_lastReceivedMessage, sizeof(m_lastReceivedMessage) ); - for( map::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it ) + memcpy(_data->m_lastReceivedMessage, m_lastReceivedMessage, sizeof(m_lastReceivedMessage)); + for (map::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it) { CommandClassData ccData; ccData.m_commandClassId = it->second->GetCommandClassId(); ccData.m_sentCnt = it->second->GetSentCnt(); ccData.m_receivedCnt = it->second->GetReceivedCnt(); - _data->m_ccData.push_back( ccData ); + _data->m_ccData.push_back(ccData); } } @@ -3646,30 +3472,26 @@ void Node::GetNodeStatistics // // Constructor //----------------------------------------------------------------------------- -Node::DeviceClass::DeviceClass -( - TiXmlElement const* _el -): -m_mandatoryCommandClasses(NULL), -m_basicMapping(0) +Node::DeviceClass::DeviceClass(TiXmlElement const* _el) : + m_mandatoryCommandClasses(NULL), m_basicMapping(0) { - char const* str = _el->Attribute( "label" ); - if( str ) + char const* str = _el->Attribute("label"); + if (str) { m_label = str; } - str = _el->Attribute( "command_classes" ); - if( str ) + str = _el->Attribute("command_classes"); + if (str) { // Parse the comma delimted command class // list into a temporary vector. vector ccs; char* pos = const_cast(str); - while( *pos ) + while (*pos) { - ccs.push_back( (uint8)strtol( pos, &pos, 16 ) ); - if( (*pos) == ',' ) + ccs.push_back((uint8) strtol(pos, &pos, 16)); + if ((*pos) == ',') { ++pos; } @@ -3677,20 +3499,20 @@ m_basicMapping(0) // Copy the vector contents into an array. size_t numCCs = ccs.size(); - m_mandatoryCommandClasses = new uint8[numCCs+1]; + m_mandatoryCommandClasses = new uint8[numCCs + 1]; m_mandatoryCommandClasses[numCCs] = 0; // Zero terminator - for( uint32 i=0; iAttribute( "basic" ); - if( str ) + str = _el->Attribute("basic"); + if (str) { char* pStop; - m_basicMapping = (uint8)strtol( str, &pStop, 16 ); + m_basicMapping = (uint8) strtol(str, &pStop, 16); } } @@ -3698,26 +3520,23 @@ m_basicMapping(0) // // Constructor //----------------------------------------------------------------------------- -Node::GenericDeviceClass::GenericDeviceClass -( - TiXmlElement const* _el -): -DeviceClass( _el ) +Node::GenericDeviceClass::GenericDeviceClass(TiXmlElement const* _el) : + DeviceClass(_el) { // Add any specific device classes TiXmlElement const* child = _el->FirstChildElement(); - while( child ) + while (child) { char const* str = child->Value(); - if( str && !strcmp( str, "Specific" ) ) + if (str && !strcmp(str, "Specific")) { - char const* keyStr = child->Attribute( "key" ); - if( keyStr ) + char const* keyStr = child->Attribute("key"); + if (keyStr) { char* pStop; - uint8 key = (uint8)strtol( keyStr, &pStop, 16 ); + uint8 key = (uint8) strtol(keyStr, &pStop, 16); - m_specificDeviceClasses[key] = new DeviceClass( child ); + m_specificDeviceClasses[key] = new DeviceClass(child); } } @@ -3729,15 +3548,13 @@ DeviceClass( _el ) // // Destructor //----------------------------------------------------------------------------- -Node::GenericDeviceClass::~GenericDeviceClass -( -) +Node::GenericDeviceClass::~GenericDeviceClass() { - while( !m_specificDeviceClasses.empty() ) + while (!m_specificDeviceClasses.empty()) { - map::iterator it = m_specificDeviceClasses.begin(); + map::iterator it = m_specificDeviceClasses.begin(); delete it->second; - m_specificDeviceClasses.erase( it ); + m_specificDeviceClasses.erase(it); } } @@ -3745,13 +3562,10 @@ Node::GenericDeviceClass::~GenericDeviceClass // // Get a specific device class object //----------------------------------------------------------------------------- -Node::DeviceClass* Node::GenericDeviceClass::GetSpecificDeviceClass -( - uint8 const& _specific -) +Node::DeviceClass* Node::GenericDeviceClass::GetSpecificDeviceClass(uint8 const& _specific) { - map::iterator it = m_specificDeviceClasses.find( _specific ); - if( it != m_specificDeviceClasses.end() ) + map::iterator it = m_specificDeviceClasses.find(_specific); + if (it != m_specificDeviceClasses.end()) { return it->second; } @@ -3763,38 +3577,45 @@ Node::DeviceClass* Node::GenericDeviceClass::GetSpecificDeviceClass // // Generate a NONCE key for this node //----------------------------------------------------------------------------- -uint8 *Node::GenerateNonceKey() { +uint8 *Node::GenerateNonceKey() +{ uint8 idx = this->m_lastnonce; /* The first byte must be unique and non-zero. The others are random. - Per Numerical Recipes in C its best to use the high-order byte. The - floating point calculation here doesn't assume the size of the random - integer, otherwise we could just shift the high byte over. - */ + Per Numerical Recipes in C its best to use the high-order byte. The + floating point calculation here doesn't assume the size of the random + integer, otherwise we could just shift the high byte over. + */ uint8 match = 0; - do { + do + { this->m_nonces[idx][0] = 1 + (uint8) (255.0 * rand() / (RAND_MAX + 1.0)); match = 0; - for (int i = 0; i < 8; i++) { - if (i == idx) { + for (int i = 0; i < 8; i++) + { + if (i == idx) + { continue; } - if (this->m_nonces[idx][0] == this->m_nonces[i][0]) { + if (this->m_nonces[idx][0] == this->m_nonces[i][0]) + { match = 1; } } } while (match); /* The other bytes have no restrictions. */ - for (int i = 1; i < 8; i++) { + for (int i = 1; i < 8; i++) + { this->m_nonces[idx][i] = (int) (256.0 * rand() / (RAND_MAX + 1.0)); } this->m_lastnonce++; if (this->m_lastnonce >= 8) this->m_lastnonce = 0; - for (uint8 i = 0; i < 8; i++) { - PrintHex("NONCES", (const uint8_t*)this->m_nonces[i], 8); + for (uint8 i = 0; i < 8; i++) + { + Internal::PrintHex("NONCES", (const uint8_t*) this->m_nonces[i], 8); } return &this->m_nonces[idx][0]; } @@ -3803,16 +3624,20 @@ uint8 *Node::GenerateNonceKey() { // Get a NONCE key for this node that matches the nonceid. //----------------------------------------------------------------------------- -uint8 *Node::GetNonceKey(uint32 nonceid) { - for (uint8 i = 0; i < 8; i++) { +uint8 *Node::GetNonceKey(uint32 nonceid) +{ + for (uint8 i = 0; i < 8; i++) + { /* make sure the nonceid matches the first byte of our stored Nonce */ - if (nonceid == this->m_nonces[i][0]) { + if (nonceid == this->m_nonces[i][0]) + { return &this->m_nonces[i][0]; } } Log::Write(LogLevel_Warning, m_nodeId, "A Nonce with id %x does not exist", nonceid); - for (uint8 i = 0; i < 8; i++) { - PrintHex("NONCES", (const uint8_t*)this->m_nonces[i], 8); + for (uint8 i = 0; i < 8; i++) + { + Internal::PrintHex("NONCES", (const uint8_t*) this->m_nonces[i], 8); } return NULL; } @@ -3821,13 +3646,14 @@ uint8 *Node::GetNonceKey(uint32 nonceid) { // // Get the ZWave+ DeviceType as a String //----------------------------------------------------------------------------- -string Node::GetDeviceTypeString() { +string Node::GetDeviceTypeString() +{ - if( !s_deviceClassesLoaded ) + if (!s_deviceClassesLoaded) { ReadDeviceClasses(); } - map::iterator nit = s_deviceTypeClasses.find( m_deviceType ); + map::iterator nit = s_deviceTypeClasses.find(m_deviceType); if (nit != s_deviceTypeClasses.end()) { DeviceClass* deviceClass = nit->second; @@ -3839,12 +3665,13 @@ string Node::GetDeviceTypeString() { // // Get the ZWave+ RoleType as a String //----------------------------------------------------------------------------- -string Node::GetRoleTypeString() { - if( !s_deviceClassesLoaded ) +string Node::GetRoleTypeString() +{ + if (!s_deviceClassesLoaded) { ReadDeviceClasses(); } - map::iterator nit = s_roleDeviceClasses.find( m_role ); + map::iterator nit = s_roleDeviceClasses.find(m_role); if (nit != s_roleDeviceClasses.end()) { DeviceClass* deviceClass = nit->second; @@ -3856,12 +3683,13 @@ string Node::GetRoleTypeString() { // // Get the ZWave+ NodeType as a String //----------------------------------------------------------------------------- -string Node::GetNodeTypeString() { - if( !s_deviceClassesLoaded ) +string Node::GetNodeTypeString() +{ + if (!s_deviceClassesLoaded) { ReadDeviceClasses(); } - map::iterator nit = s_nodeTypes.find( m_nodeType ); + map::iterator nit = s_nodeTypes.find(m_nodeType); if (nit != s_nodeTypes.end()) { DeviceClass* deviceClass = nit->second; @@ -3876,39 +3704,29 @@ string Node::GetNodeTypeString() { //----------------------------------------------------------------------------- bool Node::IsNodeReset() { - DeviceResetLocally *drl = static_cast(GetCommandClass(DeviceResetLocally::StaticGetCommandClassId())); + Internal::CC::DeviceResetLocally *drl = static_cast(GetCommandClass(Internal::CC::DeviceResetLocally::StaticGetCommandClassId())); if (drl) return drl->IsDeviceReset(); - else return false; - + else + return false; } - //----------------------------------------------------------------------------- // // Assign a ProductDetails class to this node //----------------------------------------------------------------------------- -void Node::SetProductDetails -( - ProductDescriptor *product -) +void Node::SetProductDetails(std::shared_ptr product) { - /* if there is a ProductDescriptor already assigned, remove the reference */ - if (m_Product) - m_Product->Release(); /* add the new ProductDescriptor */ m_Product = product; - m_Product->AddRef(); } //----------------------------------------------------------------------------- // // get the Path to the configFile for this device. //----------------------------------------------------------------------------- -string Node::getConfigPath -( -) +string Node::getConfigPath() { if (m_Product) return m_Product->GetConfigPath(); @@ -3921,14 +3739,11 @@ string Node::getConfigPath // // Set Loaded Config File Revision //----------------------------------------------------------------------------- -void Node::setFileConfigRevision -( - uint32 rev -) +void Node::setFileConfigRevision(uint32 rev) { m_fileConfigRevision = rev; - ManufacturerSpecific* cc = static_cast( GetCommandClass( ManufacturerSpecific::StaticGetCommandClassId() ) ); - if( cc ) + Internal::CC::ManufacturerSpecific* cc = static_cast(GetCommandClass(Internal::CC::ManufacturerSpecific::StaticGetCommandClassId())); + if (cc) { cc->setFileConfigRevision(rev); } @@ -3940,66 +3755,53 @@ void Node::setFileConfigRevision // // Set Loaded Config File Revision //----------------------------------------------------------------------------- -void Node::setLoadedConfigRevision -( - uint32 rev -) +void Node::setLoadedConfigRevision(uint32 rev) { m_loadedConfigRevision = rev; - ManufacturerSpecific* cc = static_cast( GetCommandClass( ManufacturerSpecific::StaticGetCommandClassId() ) ); - if( cc ) + Internal::CC::ManufacturerSpecific* cc = static_cast(GetCommandClass(Internal::CC::ManufacturerSpecific::StaticGetCommandClassId())); + if (cc) { cc->setLoadedConfigRevision(rev); } } - //----------------------------------------------------------------------------- // // Set Latest Config File Revision //----------------------------------------------------------------------------- -void Node::setLatestConfigRevision -( - uint32 rev -) +void Node::setLatestConfigRevision(uint32 rev) { m_latestConfigRevision = rev; - ManufacturerSpecific* cc = static_cast( GetCommandClass( ManufacturerSpecific::StaticGetCommandClassId() ) ); - if( cc ) + Internal::CC::ManufacturerSpecific* cc = static_cast(GetCommandClass(Internal::CC::ManufacturerSpecific::StaticGetCommandClassId())); + if (cc) { cc->setLatestConfigRevision(rev); } } - //----------------------------------------------------------------------------- // // Check if our Config File is the latest //----------------------------------------------------------------------------- -void Node::checkLatestConfigRevision -( -) +void Node::checkLatestConfigRevision() { - if (m_fileConfigRevision != 0) { + if (m_fileConfigRevision != 0) + { GetDriver()->CheckNodeConfigRevision(this); } } - - //----------------------------------------------------------------------------- // // Get MetaData about a node //----------------------------------------------------------------------------- -string const Node::GetMetaData -( - MetaDataFields field -) +string const Node::GetMetaData(MetaDataFields field) { - if (this->m_metadata.find(field) != this->m_metadata.end()) { + if (this->m_metadata.find(field) != this->m_metadata.end()) + { return this->m_metadata[field]; } return string(); @@ -4009,12 +3811,10 @@ string const Node::GetMetaData // // Get MetaData about a node //----------------------------------------------------------------------------- -Node::ChangeLogEntry const Node::GetChangeLog -( - uint32_t revision -) +Node::ChangeLogEntry const Node::GetChangeLog(uint32_t revision) { - if (this->m_changeLog.find(revision) != this->m_changeLog.end()) { + if (this->m_changeLog.find(revision) != this->m_changeLog.end()) + { return this->m_changeLog[revision]; } ChangeLogEntry cle; @@ -4026,59 +3826,76 @@ Node::ChangeLogEntry const Node::GetChangeLog // // Translate the MetaData String to a ID //----------------------------------------------------------------------------- -Node::MetaDataFields const Node::GetMetaDataId(string name) { - if (name == "OzwInfoPage") return MetaData_OzwInfoPage_URL; - if (name == "ZWProductPage") return MetaData_ZWProductPage_URL; - if (name == "ProductPic") return MetaData_ProductPic; - if (name == "Description") return MetaData_Description; - if (name == "ProductManual") return MetaData_ProductManual_URL; - if (name == "ProductPage") return MetaData_ProductPage_URL; - if (name == "InclusionDescription") return MetaData_InclusionHelp; - if (name == "ExclusionDescription") return MetaData_ExclusionHelp; - if (name == "ResetDescription") return MetaData_ResetHelp; - if (name == "WakeupDescription") return MetaData_WakeupHelp; - if (name == "ProductSupport") return MetaData_ProductSupport_URL; - if (name == "FrequencyName") return MetaData_Frequency; - if (name == "Name") return MetaData_Name; - if (name == "Identifier") return MetaData_Identifier; +Node::MetaDataFields Node::GetMetaDataId(string name) +{ + if (name == "OzwInfoPage") + return MetaData_OzwInfoPage_URL; + if (name == "ZWProductPage") + return MetaData_ZWProductPage_URL; + if (name == "ProductPic") + return MetaData_ProductPic; + if (name == "Description") + return MetaData_Description; + if (name == "ProductManual") + return MetaData_ProductManual_URL; + if (name == "ProductPage") + return MetaData_ProductPage_URL; + if (name == "InclusionDescription") + return MetaData_InclusionHelp; + if (name == "ExclusionDescription") + return MetaData_ExclusionHelp; + if (name == "ResetDescription") + return MetaData_ResetHelp; + if (name == "WakeupDescription") + return MetaData_WakeupHelp; + if (name == "ProductSupport") + return MetaData_ProductSupport_URL; + if (name == "FrequencyName") + return MetaData_Frequency; + if (name == "Name") + return MetaData_Name; + if (name == "Identifier") + return MetaData_Identifier; return MetaData_Invalid; } //----------------------------------------------------------------------------- // // Translate the MetaDataID to a String //----------------------------------------------------------------------------- -string const Node::GetMetaDataString(Node::MetaDataFields id) { - switch (id) { - case MetaData_OzwInfoPage_URL: - return "OzwInfoPage"; - case MetaData_ZWProductPage_URL: - return "ZWProductPage"; - case MetaData_ProductPic: - return "ProductPic"; - case MetaData_Description: - return "Description"; - case MetaData_ProductManual_URL: - return "ProductManual"; - case MetaData_ProductPage_URL: - return "ProductPage"; - case MetaData_InclusionHelp: - return "InclusionDescription"; - case MetaData_ExclusionHelp: - return "ExclusionDescription"; - case MetaData_ResetHelp: - return "ResetDescription"; - case MetaData_WakeupHelp: - return "WakeupDescription"; - case MetaData_ProductSupport_URL: - return "ProductSupport"; - case MetaData_Frequency: - return "FrequencyName"; - case MetaData_Name: - return "Name"; - case MetaData_Identifier: - return "Identifier"; - case MetaData_Invalid: - return ""; +string const Node::GetMetaDataString(Node::MetaDataFields id) +{ + switch (id) + { + case MetaData_OzwInfoPage_URL: + return "OzwInfoPage"; + case MetaData_ZWProductPage_URL: + return "ZWProductPage"; + case MetaData_ProductPic: + return "ProductPic"; + case MetaData_Description: + return "Description"; + case MetaData_ProductManual_URL: + return "ProductManual"; + case MetaData_ProductPage_URL: + return "ProductPage"; + case MetaData_InclusionHelp: + return "InclusionDescription"; + case MetaData_ExclusionHelp: + return "ExclusionDescription"; + case MetaData_ResetHelp: + return "ResetDescription"; + case MetaData_WakeupHelp: + return "WakeupDescription"; + case MetaData_ProductSupport_URL: + return "ProductSupport"; + case MetaData_Frequency: + return "FrequencyName"; + case MetaData_Name: + return "Name"; + case MetaData_Identifier: + return "Identifier"; + case MetaData_Invalid: + return ""; } return ""; } @@ -4087,109 +3904,121 @@ string const Node::GetMetaDataString(Node::MetaDataFields id) { // // Read the MetaData from the Config File //----------------------------------------------------------------------------- -void Node::ReadMetaDataFromXML(TiXmlElement const* _valueElement) { +void Node::ReadMetaDataFromXML(TiXmlElement const* _valueElement) +{ TiXmlElement const* ccElement = _valueElement->FirstChildElement(); - while( ccElement ) + while (ccElement) + { + if (!strcmp(ccElement->Value(), "MetaData")) { - if(!strcmp( ccElement->Value(), "MetaData" ) ) + TiXmlElement const* metadata = ccElement->FirstChildElement(); + while (metadata) { - TiXmlElement const* metadata = ccElement->FirstChildElement(); - while (metadata) { - if( !strcmp( metadata->Value(), "MetaDataItem" ) ) + if (!strcmp(metadata->Value(), "MetaDataItem")) + { + string name = metadata->Attribute("name"); + if (GetMetaDataId(name) == MetaData_Invalid) { - string name = metadata->Attribute( "name" ); - if (GetMetaDataId(name) == MetaData_Invalid) { - Log::Write(LogLevel_Warning, m_nodeId, "Invalid MetaData Name in Config: %s", name.c_str()); - metadata = metadata->NextSiblingElement(); - continue; - } - /* these are the MetaData that have type/id entries */ - switch (GetMetaDataId(name)) { - case MetaData_ZWProductPage_URL: - case MetaData_Identifier: - case MetaData_Frequency: + Log::Write(LogLevel_Warning, m_nodeId, "Invalid MetaData Name in Config: %s", name.c_str()); + metadata = metadata->NextSiblingElement(); + continue; + } + /* these are the MetaData that have type/id entries */ + switch (GetMetaDataId(name)) + { + case MetaData_ZWProductPage_URL: + case MetaData_Identifier: + case MetaData_Frequency: + { + int intVal; + uint16_t type = 0; + uint16_t id = 0; + if (TIXML_SUCCESS == metadata->QueryIntAttribute("type", &intVal)) { - int intVal; - uint16_t type = 0; - uint16_t id = 0; - if( TIXML_SUCCESS == metadata->QueryIntAttribute( "type", &intVal ) ) - { - type = (uint16_t)intVal; - } - if( TIXML_SUCCESS == metadata->QueryIntAttribute( "id", &intVal ) ) - { - id = (uint16_t)intVal; - } - if ((type != GetProductType()) || - (id != GetProductId()) ) { - metadata = metadata->NextSiblingElement(); - continue; - } - break; + type = (uint16_t) intVal; } - /* for the rest, just take the standard entry */ - default: - break; + if (TIXML_SUCCESS == metadata->QueryIntAttribute("id", &intVal)) + { + id = (uint16_t) intVal; + } + if ((type != GetProductType()) || (id != GetProductId())) + { + metadata = metadata->NextSiblingElement(); + continue; + } + break; } + /* for the rest, just take the standard entry */ + default: + break; + } + if (metadata->GetText()) this->m_metadata[GetMetaDataId(name)] = metadata->GetText(); - } else if (!strcmp( metadata->Value(), "ChangeLog" )) { - TiXmlElement const* entry = metadata->FirstChildElement("Entry"); - while (entry) { - ChangeLogEntry cle; - cle.author = entry->Attribute("author"); - cle.date = entry->Attribute("date"); - cle.description = entry->GetText(); - metadata->QueryIntAttribute( "id", &cle.revision ); - m_changeLog[cle.revision] = cle; - entry = entry->NextSiblingElement("Entry"); - } - + } + else if (!strcmp(metadata->Value(), "ChangeLog")) + { + TiXmlElement const* entry = metadata->FirstChildElement("Entry"); + while (entry) + { + ChangeLogEntry cle; + cle.author = entry->Attribute("author"); + cle.date = entry->Attribute("date"); + cle.description = entry->GetText(); + entry->QueryIntAttribute("revision", &cle.revision); + m_changeLog.insert(std::pair(cle.revision, cle)); + entry = entry->NextSiblingElement("Entry"); } - metadata = metadata->NextSiblingElement(); } + metadata = metadata->NextSiblingElement(); } - ccElement = ccElement->NextSiblingElement(); } + ccElement = ccElement->NextSiblingElement(); + } } //----------------------------------------------------------------------------- // // Write the MetaData to the Cache File //----------------------------------------------------------------------------- -void Node::WriteMetaDataXML(TiXmlElement *mdElement) { +void Node::WriteMetaDataXML(TiXmlElement *mdElement) +{ // Write out the MetaDataItems - for( map::iterator it = m_metadata.begin(); it != m_metadata.end(); ++ it ) + for (map::iterator it = m_metadata.begin(); it != m_metadata.end(); ++it) { /* only write if its a valid MetaData */ - if (it->first < Node::MetaData_Invalid) { - TiXmlElement* mdiElement = new TiXmlElement( "MetaDataItem" ); - mdiElement->SetAttribute( "name", GetMetaDataString(it->first).c_str() ); - switch (it->first) { + if (it->first < Node::MetaData_Invalid) + { + TiXmlElement* mdiElement = new TiXmlElement("MetaDataItem"); + mdiElement->SetAttribute("name", GetMetaDataString(it->first).c_str()); + switch (it->first) + { case MetaData_ZWProductPage_URL: case MetaData_Identifier: case MetaData_Frequency: mdiElement->SetAttribute("type", GetProductType()); mdiElement->SetAttribute("id", GetProductId()); break; - /* for the rest, just take the standard entry */ + /* for the rest, just take the standard entry */ default: break; } - TiXmlText* textElement = new TiXmlText( it->second.c_str() ); - mdiElement->LinkEndChild( textElement ); - mdElement->LinkEndChild( mdiElement ); + TiXmlText* textElement = new TiXmlText(it->second.c_str()); + mdiElement->LinkEndChild(textElement); + mdElement->LinkEndChild(mdiElement); } } - if (m_changeLog.size() > 0) { - TiXmlElement* cl = new TiXmlElement( "ChangeLog" ); - for (map::iterator it = m_changeLog.begin(); it != m_changeLog.end(); ++ it ) + if (m_changeLog.size() > 0) + { + TiXmlElement* cl = new TiXmlElement("ChangeLog"); + for (map::iterator it = m_changeLog.begin(); it != m_changeLog.end(); ++it) { - TiXmlElement* cle = new TiXmlElement( "Entry" ); - cle->SetAttribute( "author", it->second.author.c_str() ); - cle->SetAttribute( "date", it->second.date.c_str() ); - cle->SetAttribute( "revision", it->second.revision ); - TiXmlText* textElement = new TiXmlText( it->second.description.c_str() ); + TiXmlElement* cle = new TiXmlElement("Entry"); + cle->SetAttribute("author", it->second.author.c_str()); + cle->SetAttribute("date", it->second.date.c_str()); + cle->SetAttribute("revision", it->second.revision); + TiXmlText* textElement = new TiXmlText(it->second.description.c_str()); cle->LinkEndChild(textElement); + cl->LinkEndChild(cle); } mdElement->LinkEndChild(cl); } diff --git a/cpp/src/Node.h b/cpp/src/Node.h index 37a900abc7..374b7bc49b 100644 --- a/cpp/src/Node.h +++ b/cpp/src/Node.h @@ -40,24 +40,40 @@ #include "Group.h" class TiXmlElement; +class TiXmlNode; namespace OpenZWave { - class CommandClass; + namespace Internal + { + namespace CC + { + class CommandClass; + class Association; + class AssociationCommandConfiguration; + class ControllerReplication; + class Hail; + class ManufacturerSpecific; + class MultiChannelAssociation; + class MultiInstance; + class NodeNaming; + class Version; + class ZWavePlusInfo; + } + namespace VC + { + class Value; + class ValueStore; + } + namespace Platform + { + class Mutex; + } + class ProductDescriptor; + class ManufacturerSpecificDB; + } class Driver; class Group; - class ValueStore; - class Value; - class ValueBool; - class ValueButton; - class ValueByte; - class ValueDecimal; - class ValueInt; - class ValueSchedule; - class ValueShort; - class ValueString; - class Mutex; - class ProductDescriptor; /** \brief The Node class describes a Z-Wave node object...typically a device on the * Z-Wave network. @@ -67,47 +83,20 @@ namespace OpenZWave friend class Manager; friend class Driver; friend class Group; - friend class Value; + friend class Internal::VC::Value; friend class ValueButton; - friend class Alarm; - friend class Association; - friend class AssociationCommandConfiguration; - friend class Basic; - friend class Battery; - friend class ClimateControlSchedule; - friend class Clock; - friend class CommandClass; - friend class ControllerReplication; - friend class EnergyProduction; - friend class Hail; - friend class Indicator; - friend class Language; - friend class Lock; - friend class ManufacturerSpecific; - friend class ManufacturerSpecificDB; - friend class Meter; - friend class MeterPulse; - friend class MultiInstance; - friend class MultiChannelAssociation; - friend class NodeNaming; - friend class Protection; - friend class Security; - friend class SensorAlarm; - friend class SensorBinary; - friend class SensorMultilevel; - friend class SwitchAll; - friend class SwitchBinary; - friend class SwitchMultilevel; - friend class SwitchToggleBinary; - friend class SwitchToggleMultilevel; - friend class ThermostatFanMode; - friend class ThermostatFanState; - friend class ThermostatMode; - friend class ThermostatOperatingState; - friend class ThermostatSetpoint; - friend class Version; - friend class WakeUp; - friend class ZWavePlusInfo; + friend class Internal::CC::Association; + friend class Internal::CC::AssociationCommandConfiguration; + friend class Internal::CC::CommandClass; + friend class Internal::CC::ControllerReplication; + friend class Internal::CC::Hail; + friend class Internal::CC::ManufacturerSpecific; + friend class Internal::CC::MultiInstance; + friend class Internal::CC::MultiChannelAssociation; + friend class Internal::CC::NodeNaming; + friend class Internal::CC::Version; + friend class Internal::CC::ZWavePlusInfo; + friend class Internal::ManufacturerSpecificDB; //----------------------------------------------------------------------------- // Construction @@ -118,7 +107,7 @@ namespace OpenZWave * \param _homeId The homeId of the network to which this node is connected. * \param _nodeId The nodeId of this node. */ - Node( uint32 const _homeId, uint8 const _nodeId ); + Node(uint32 const _homeId, uint8 const _nodeId); /** Destructor cleans up memory allocated to node and its child objects. */ virtual ~Node(); @@ -127,7 +116,7 @@ namespace OpenZWave /** Returns a pointer to the driver (interface with a Z-Wave controller) * associated with this node. */ - Driver* GetDriver()const; + Driver* GetDriver() const; //----------------------------------------------------------------------------- // Initialization @@ -135,29 +124,28 @@ namespace OpenZWave public: enum QueryStage { - QueryStage_None, /**< Query process hasn't started for this node */ - QueryStage_ProtocolInfo, /**< Retrieve protocol information */ - QueryStage_Probe, /**< Ping device to see if alive */ - QueryStage_WakeUp, /**< Start wake up process if a sleeping node */ - QueryStage_ManufacturerSpecific1, /**< Retrieve manufacturer name and product ids if ProtocolInfo lets us */ - QueryStage_NodeInfo, /**< Retrieve info about supported, controlled command classes */ - QueryStage_NodePlusInfo, /**< Retrieve ZWave+ info and update device classes */ - QueryStage_SecurityReport, /**< Retrieve a list of Command Classes that require Security */ - QueryStage_ManufacturerSpecific2, /**< Retrieve manufacturer name and product ids */ - QueryStage_Versions, /**< Retrieve version information */ - QueryStage_Instances, /**< Retrieve information about multiple command class instances */ - QueryStage_Static, /**< Retrieve static information (doesn't change) */ - QueryStage_CacheLoad, /**< Ping a device upon restarting with cached config for the device */ - QueryStage_Probe1 = QueryStage_CacheLoad, /** < Depreciated name. /todo Remove in 2.0 timeframe */ - QueryStage_Associations, /**< Retrieve information about associations */ - QueryStage_Neighbors, /**< Retrieve node neighbor list */ - QueryStage_Session, /**< Retrieve session information (changes infrequently) */ - QueryStage_Dynamic, /**< Retrieve dynamic information (changes frequently) */ - QueryStage_Configuration, /**< Retrieve configurable parameter information (only done on request) */ - QueryStage_Complete /**< Query process is completed for this node */ + QueryStage_None, /**< Query process hasn't started for this node */ + QueryStage_ProtocolInfo, /**< Retrieve protocol information */ + QueryStage_Probe, /**< Ping device to see if alive */ + QueryStage_WakeUp, /**< Start wake up process if a sleeping node */ + QueryStage_ManufacturerSpecific1, /**< Retrieve manufacturer name and product ids if ProtocolInfo lets us */ + QueryStage_NodeInfo, /**< Retrieve info about supported, controlled command classes */ + QueryStage_NodePlusInfo, /**< Retrieve ZWave+ info and update device classes */ + QueryStage_SecurityReport, /**< Retrieve a list of Command Classes that require Security */ + QueryStage_ManufacturerSpecific2, /**< Retrieve manufacturer name and product ids */ + QueryStage_Versions, /**< Retrieve version information */ + QueryStage_Instances, /**< Retrieve information about multiple command class instances */ + QueryStage_Static, /**< Retrieve static information (doesn't change) */ + QueryStage_CacheLoad, /**< Ping a device upon restarting with cached config for the device */ + QueryStage_Probe1 = QueryStage_CacheLoad, /** < Depreciated name. /todo Remove in 2.0 timeframe */ + QueryStage_Associations, /**< Retrieve information about associations */ + QueryStage_Neighbors, /**< Retrieve node neighbor list */ + QueryStage_Session, /**< Retrieve session information (changes infrequently) */ + QueryStage_Dynamic, /**< Retrieve dynamic information (changes frequently) */ + QueryStage_Configuration, /**< Retrieve configurable parameter information (only done on request) */ + QueryStage_Complete /**< Query process is completed for this node */ }; - /** * This function advances the query process (see Remarks below for more detail on the * process). It iterates through the various query stages enumerated in Node::QueryStage. @@ -182,7 +170,7 @@ namespace OpenZWave * Otherwise, the function returns with no action. * \param _stage The current stage of the query process. */ - void QueryStageComplete( QueryStage const _stage ); + void QueryStageComplete(QueryStage const _stage); /** * Retry the specified query stage (up to _maxAttempts retries). This will @@ -191,7 +179,7 @@ namespace OpenZWave * \param _stage The query stage to retry. * \param _maxAttempts */ - void QueryStageRetry( QueryStage const _stage, uint8 const _maxAttempts = 0 ); // maxAttempts of zero means no limit + void QueryStageRetry(QueryStage const _stage, uint8 const _maxAttempts = 0); // maxAttempts of zero means no limit /** * This function sets the query stage for the node (but only to an earlier stage). @@ -199,14 +187,17 @@ namespace OpenZWave * \param _stage The desired query stage. * \see m_queryStage, m_queryPending */ - void SetQueryStage( QueryStage const _stage, bool const _advance = true ); + void SetQueryStage(QueryStage const _stage, bool const _advance = true); /** * Returns the current query stage enum. * \return Enum value with the current query stage. * \see m_queryStage */ - Node::QueryStage GetCurrentQueryStage() { return m_queryStage; } + Node::QueryStage GetCurrentQueryStage() + { + return m_queryStage; + } /** * Returns the specified query stage string. @@ -214,13 +205,16 @@ namespace OpenZWave * \return Specified query stage string. * \see m_queryStage, m_queryPending */ - string GetQueryStageName( QueryStage const _stage ); + string GetQueryStageName(QueryStage const _stage); /** * Returns whether the library thinks a node is functioning properly * \return boolean status of node. */ - bool IsNodeAlive()const{ return m_nodeAlive; } + bool IsNodeAlive() const + { + return m_nodeAlive; + } /** * This function handles a response to the FUNC_ID_ZW_GET_NODE_PROTOCOL_INFO @@ -235,7 +229,7 @@ namespace OpenZWave * - m_frequentListening (device can be woken up with a beam) * - m_beaming (device is beam capable) */ - void UpdateProtocolInfo( uint8 const* _data ); + void UpdateProtocolInfo(uint8 const* _data); /** * this function is called when the Node is added via a AddNode request. the ProtocolInfo field contains the * devices classes and the CommandClasses that the node supports, so we can build a pretty good Node out of that @@ -244,38 +238,53 @@ namespace OpenZWave * @param _length length of the _protocolInfo field. */ void SetProtocolInfo(uint8 const* _protocolInfo, uint8 const _length); - void UpdateNodeInfo( uint8 const* _data, uint8 const _length ); + void UpdateNodeInfo(uint8 const* _data, uint8 const _length); - bool ProtocolInfoReceived()const{ return m_protocolInfoReceived; } - bool NodeInfoReceived()const{ return m_nodeInfoReceived; } - bool IsNodeZWavePlus()const{ return m_nodePlusInfoReceived; } + bool ProtocolInfoReceived() const + { + return m_protocolInfoReceived; + } + bool NodeInfoReceived() const + { + return m_nodeInfoReceived; + } + bool IsNodeZWavePlus() const + { + return m_nodePlusInfoReceived; + } - bool AllQueriesCompleted()const{ return( QueryStage_Complete == m_queryStage ); } + bool AllQueriesCompleted() const + { + return (QueryStage_Complete == m_queryStage); + } - void SetNodePlusInfoReceived(const bool _received){ m_nodePlusInfoReceived = _received; } + void SetNodePlusInfoReceived(const bool _received) + { + m_nodePlusInfoReceived = _received; + } /** * Handle dead node detection tracking. * Use this routine to set state of nodes. * Tracks state as well as send notifications. */ - void SetNodeAlive( bool const _isAlive ); + void SetNodeAlive(bool const _isAlive); private: void SetStaticRequests(); - QueryStage m_queryStage; - bool m_queryPending; - bool m_queryConfiguration; - uint8 m_queryRetries; - bool m_protocolInfoReceived; - bool m_basicprotocolInfoReceived; - bool m_nodeInfoReceived; - bool m_nodePlusInfoReceived; - bool m_manufacturerSpecificClassReceived; - bool m_nodeInfoSupported; - bool m_refreshonNodeInfoFrame; - bool m_nodeAlive; + QueryStage m_queryStage; + bool m_queryPending; + bool m_queryConfiguration; + uint8 m_queryRetries; + bool m_protocolInfoReceived; + bool m_basicprotocolInfoReceived; + bool m_nodeInfoReceived; + bool m_nodePlusInfoReceived; + bool m_manufacturerSpecificClassReceived; + bool m_nodeInfoSupported; + bool m_refreshonNodeInfoFrame; + bool m_nodeAlive; //----------------------------------------------------------------------------- // Capabilities @@ -284,14 +293,14 @@ namespace OpenZWave // Security flags enum { - SecurityFlag_Security = 0x01, - SecurityFlag_Controller = 0x02, - SecurityFlag_SpecificDevice = 0x04, - SecurityFlag_RoutingSlave = 0x08, - SecurityFlag_BeamCapability = 0x10, - SecurityFlag_Sensor250ms = 0x20, - SecurityFlag_Sensor1000ms = 0x40, - SecurityFlag_OptionalFunctionality = 0x80 + SecurityFlag_Security = 0x01, + SecurityFlag_Controller = 0x02, + SecurityFlag_SpecificDevice = 0x04, + SecurityFlag_RoutingSlave = 0x08, + SecurityFlag_BeamCapability = 0x10, + SecurityFlag_Sensor250ms = 0x20, + SecurityFlag_Sensor1000ms = 0x40, + SecurityFlag_OptionalFunctionality = 0x80 }; // Node Ids @@ -300,46 +309,96 @@ namespace OpenZWave NodeBroadcast = 0xff }; - bool IsListeningDevice()const{ return m_listening; } - bool IsFrequentListeningDevice()const{ return m_frequentListening; } - bool IsBeamingDevice()const{ return m_beaming; } - bool IsRoutingDevice()const{ return m_routing; } - bool IsSecurityDevice()const{ return m_security; } - uint32 GetMaxBaudRate()const{ return m_maxBaudRate; } - uint8 GetVersion()const{ return m_version; } - uint8 GetSecurity()const{ return m_security; } - - uint8 GetNodeId()const{ return m_nodeId; } - - uint8 GetBasic()const{ return m_basic; } - uint8 GetGeneric()const{ return m_generic; } - uint8 GetSpecific()const{ return m_specific; } - string const& GetType()const{ return m_type; } - uint32 GetNeighbors( uint8** o_associations ); - bool IsController()const{ return ( m_basic == 0x01 || m_basic == 0x02 ) && ( m_generic == 0x01 || m_generic == 0x02 ); } - bool IsAddingNode() const { return m_addingNode; } /* These three *AddingNode functions are used to tell if we this node is just being discovered. Currently used by the Security CC to initiate the Network Key Exchange */ - void SetAddingNode() { m_addingNode = true; } - void ClearAddingNode() { m_addingNode = false; } + bool IsListeningDevice() const + { + return m_listening; + } + bool IsFrequentListeningDevice() const + { + return m_frequentListening; + } + bool IsBeamingDevice() const + { + return m_beaming; + } + bool IsRoutingDevice() const + { + return m_routing; + } + bool IsSecurityDevice() const + { + return m_security; + } + uint32 GetMaxBaudRate() const + { + return m_maxBaudRate; + } + uint8 GetVersion() const + { + return m_version; + } + uint8 GetSecurity() const + { + return m_security; + } + + uint8 GetNodeId() const + { + return m_nodeId; + } + + uint8 GetBasic() const + { + return m_basic; + } + string GetBasicString(); + uint8 GetGeneric(uint8 const _instance) const; + string GetGenericString(uint8 const _instance); + uint8 GetSpecific(uint8 const _instance) const; + string GetSpecificString(uint8 const _instance); + string GetEndPointDeviceClassLabel(uint8 const _generic, uint8 const _specific); + + string const& GetType() const + { + return m_type; + } + uint32 GetNeighbors(uint8** o_neighbors); + bool IsController() const + { + return (m_basic == 0x01 || m_basic == 0x02) && (m_generic == 0x01 || m_generic == 0x02); + } + bool IsAddingNode() const + { + return m_addingNode; + } /* These three *AddingNode functions are used to tell if we this node is just being discovered. Currently used by the Security CC to initiate the Network Key Exchange */ + void SetAddingNode() + { + m_addingNode = true; + } + void ClearAddingNode() + { + m_addingNode = false; + } bool IsNodeReset(); private: - bool m_listening; - bool m_frequentListening; - bool m_beaming; - bool m_routing; - uint32 m_maxBaudRate; - uint8 m_version; - bool m_security; - uint32 m_homeId; - uint8 m_nodeId; - uint8 m_basic; //*< Basic device class (0x01-Controller, 0x02-Static Controller, 0x03-Slave, 0x04-Routing Slave - uint8 m_generic; - uint8 m_specific; - string m_type; // Label representing the specific/generic/basic value - uint8 m_neighbors[29]; // Bitmask containing the neighboring nodes - uint8 m_numRouteNodes; // number of node routes - uint8 m_routeNodes[5]; // nodes to route to - map m_buttonMap; // Map button IDs into virtual node numbers - bool m_addingNode; + bool m_listening; + bool m_frequentListening; + bool m_beaming; + bool m_routing; + uint32 m_maxBaudRate; + uint8 m_version; + bool m_security; + uint32 m_homeId; + uint8 m_nodeId; + uint8 m_basic; //*< Basic device class (0x01-Controller, 0x02-Static Controller, 0x03-Slave, 0x04-Routing Slave + uint8 m_generic; + uint8 m_specific; + string m_type; // Label representing the specific/generic/basic value + uint8 m_neighbors[29]; // Bitmask containing the neighboring nodes + uint8 m_numRouteNodes; // number of node routes + uint8 m_routeNodes[5]; // nodes to route to + map m_buttonMap; // Map button IDs into virtual node numbers + bool m_addingNode; //----------------------------------------------------------------------------- // Device Naming @@ -347,42 +406,87 @@ namespace OpenZWave private: // Manufacturer, Product and Name are stored here so they can be set by the // user even if the device does not support the relevant command classes. - string GetManufacturerName()const{ return m_manufacturerName; } - string GetProductName()const{ return m_productName; } - string GetNodeName()const{ return m_nodeName; } - string GetLocation()const{ return m_location; } + string GetManufacturerName() const + { + return m_manufacturerName; + } + string GetProductName() const + { + return m_productName; + } + string GetNodeName() const + { + return m_nodeName; + } + string GetLocation() const + { + return m_location; + } // string GetManufacturerId()const{ return std::to_string(m_manufacturerId); } - uint16 GetManufacturerId()const{ return m_manufacturerId; } + uint16 GetManufacturerId() const + { + return m_manufacturerId; + } // string GetProductType()const{ return string(m_productType); } - uint16 GetProductType()const{ return m_productType; } + uint16 GetProductType() const + { + return m_productType; + } // string GetProductId()const{ return string(m_productId); } - uint16 GetProductId()const{ return m_productId; } + uint16 GetProductId() const + { + return m_productId; + } - void SetManufacturerName( string const& _manufacturerName ){ m_manufacturerName = _manufacturerName; } - void SetProductName( string const& _productName ){ m_productName = _productName; } - void SetNodeName( string const& _nodeName ); - void SetLocation( string const& _location ); + void SetManufacturerName(string const& _manufacturerName) + { + m_manufacturerName = _manufacturerName; + } + void SetProductName(string const& _productName) + { + m_productName = _productName; + } + void SetNodeName(string const& _nodeName); + void SetLocation(string const& _location); - void SetManufacturerId( uint16 const& _manufacturerId ){ m_manufacturerId = _manufacturerId; } - void SetProductType( uint16 const& _productType ){ m_productType = _productType; } - void SetProductId( uint16 const& _productId ){ m_productId = _productId; } + void SetManufacturerId(uint16 const& _manufacturerId) + { + m_manufacturerId = _manufacturerId; + } + void SetProductType(uint16 const& _productType) + { + m_productType = _productType; + } + void SetProductId(uint16 const& _productId) + { + m_productId = _productId; + } - string m_manufacturerName; - string m_productName; - string m_nodeName; - string m_location; + string m_manufacturerName; + string m_productName; + string m_nodeName; + string m_location; - uint16 m_manufacturerId; - uint16 m_productType; - uint16 m_productId; + uint16 m_manufacturerId; + uint16 m_productType; + uint16 m_productId; // zwave+ info - uint16 GetDeviceType() const { return m_deviceType; } + uint16 GetDeviceType() const + { + return m_deviceType; + } string GetDeviceTypeString(); - uint8 GetRoleType() const { return m_role; } + uint8 GetRoleType() const + { + return m_role; + } string GetRoleTypeString(); - uint8 GetNodeType() const { return m_nodeType; } + uint8 GetNodeType() const + { + return m_nodeType; + } string GetNodeTypeString(); uint16 m_deviceType; @@ -399,8 +503,8 @@ namespace OpenZWave * \return Pointer to the requested CommandClass object if supported, otherwise NULL. * \see CommandClass, m_commandClassMap */ - CommandClass* GetCommandClass( uint8 const _commandClassId, bool advertised = false )const; - void ApplicationCommandHandler( uint8 const* _data, bool encrypted ); + Internal::CC::CommandClass* GetCommandClass(uint8 const _commandClassId) const; + void ApplicationCommandHandler(uint8 const* _data, bool encrypted); /** * This function sets up Secured Command Classes. It iterates over the existing command classes marking them @@ -409,7 +513,7 @@ namespace OpenZWave * @param _length the length of the _data string * @param _instance the instance of the Class thats Secured. */ - void SetSecuredClasses( uint8 const* _data, uint8 const _length, uint32 const _instance = 1); + void SetSecuredClasses(uint8 const* _data, uint8 const _length, uint32 const _instance = 1); void SetSecured(bool secure); bool IsSecured(); /** @@ -426,39 +530,40 @@ namespace OpenZWave * */ uint8 GetNumInstances(uint8 const _ccid); + private: /** * Creates the specified command class object and adds it to the node (via the * m_commandClassMap) if it doesn't exist. * No new object is created if it already exists for this node. * \param _commandClassId Class ID (a single byte value) identifying the command class requested. - * \param advertised if the CommandClass is Advertised by this node * \return Pointer to the CommandClass object just added to the map (NULL if the object * was already there or if the CommandClass object creation failed). * \see CommandClass, CommandClasses::CreateCommandClass, m_commandClassMap */ - CommandClass* AddCommandClass( uint8 const _commandClassId, bool advertised = false); + Internal::CC::CommandClass* AddCommandClass(uint8 const _commandClassId); /** * Removes a command class object from the node (via the m_commandClassMap). Before removing the * object, this function also removes any values stored in the object's ValueStore. * \param _commandClassId Class ID (a single byte value) identifying the command class to be removed. * \see m_commandClassMap, ValueStore, GetValueStore, ValueStore::RemoveCommandClassValues */ - void RemoveCommandClass( uint8 const _commandClassId ); - void ReadXML( TiXmlElement const* _nodeElement ); - void ReadDeviceProtocolXML( TiXmlElement const* _ccsElement ); - void ReadCommandClassesXML( TiXmlElement const* _ccsElement ); - void WriteXML( TiXmlElement* _nodeElement ); + void RemoveCommandClass(uint8 const _commandClassId); + void ReadXML(TiXmlElement const* _nodeElement); + void ReadDeviceProtocolXML(TiXmlElement const* _ccsElement); + void ReadCommandClassesXML(TiXmlElement const* _ccsElement); + void WriteXML(TiXmlElement* _nodeElement); + + map m_commandClassMap; /**< Map of command class ids and pointers to associated command class objects */ + bool m_secured; /**< Is this Node added Securely */ + map m_globalInstanceLabel; /** < The Global Labels for Instances for CC that dont define their own labels */ - map m_commandClassMap; /**< Map of command class ids and pointers to associated command class objects */ - map m_advertisedCommandClassMap; /**< Map of Command Class Id's and Pointers to the Class for Advertised CommandClasses */ - bool m_secured; /**< Is this Node added Securely */ - map m_globalInstanceLabel; /** < The Global Labels for Instances for CC that dont define their own labels */ + TiXmlNode *m_nodeCache; //----------------------------------------------------------------------------- // Configuration Revision Related Classes //----------------------------------------------------------------------------- public: - void SetProductDetails(ProductDescriptor *product); + void SetProductDetails(std::shared_ptr product); /** Get a path to the config file for this device * * @return a path relative to the config directory for the config file. returns a empty string if a config file is not present. @@ -468,17 +573,29 @@ namespace OpenZWave * * @return a revision number */ - uint32 getFileConfigRevision() { return m_fileConfigRevision; }; + uint32 getFileConfigRevision() + { + return m_fileConfigRevision; + } + ; /** Get the Revision number of the config that is laoded for this Node * * @return the revision number currently loaded. */ - uint32 getLoadedConfigRevision() { return m_loadedConfigRevision; }; + uint32 getLoadedConfigRevision() + { + return m_loadedConfigRevision; + } + ; /** Get the Latest Config File revision available at openzwave.com * * @return The latest revision number available */ - uint32 getLatestConfigRevision() { return m_latestConfigRevision; }; + uint32 getLatestConfigRevision() + { + return m_latestConfigRevision; + } + ; /** Set the revision number of the Config File for this device * * @param rev the revision number @@ -497,13 +614,11 @@ namespace OpenZWave /** Check the latest available revision number for this device. * */ - void checkLatestConfigRevision( ); + void checkLatestConfigRevision(); private: - - ProductDescriptor *m_Product; - + std::shared_ptr m_Product; uint32 m_fileConfigRevision; uint32 m_loadedConfigRevision; @@ -512,7 +627,7 @@ namespace OpenZWave // Basic commands (helpers that go through the basic command class) //----------------------------------------------------------------------------- public: - void SetLevel( uint8 const _level ); + void SetLevel(uint8 const _level); //----------------------------------------------------------------------------- // On/Off commands (helpers that go through the basic or switchall command class) @@ -525,43 +640,46 @@ namespace OpenZWave // Values (handled by the command classes) //----------------------------------------------------------------------------- public: - ValueID CreateValueID( ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, ValueID::ValueType const _type ); + ValueID CreateValueID(ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, ValueID::ValueType const _type); - Value* GetValue( ValueID const& _id ); - Value* GetValue( uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex ); - bool RemoveValue( uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex ); + Internal::VC::Value* GetValue(ValueID const& _id); + Internal::VC::Value* GetValue(uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex); + bool RemoveValue(uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex); // Helpers for creating values - bool CreateValueBitSet( ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, int32 const _default, uint8 const _pollIntensity ); - bool CreateValueBool( ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, bool const _default, uint8 const _pollIntensity ); - bool CreateValueButton( ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, uint8 const _pollIntensity ); - bool CreateValueByte( ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, uint8 const _default, uint8 const _pollIntensity ); - bool CreateValueDecimal( ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, string const& _default, uint8 const _pollIntensity ); - bool CreateValueInt( ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, int32 const _default, uint8 const _pollIntensity ); - bool CreateValueList( ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, uint8 const _size, vector const& _items, int32 const _default, uint8 const _pollIntensity ); - bool CreateValueRaw( ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, uint8 const* _default, uint8 const _length, uint8 const _pollIntensity ); - bool CreateValueSchedule( ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, uint8 const _pollIntensity ); - bool CreateValueShort( ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, int16 const _default, uint8 const _pollIntensity ); - bool CreateValueString( ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, string const& _default, uint8 const _pollIntensity ); + bool CreateValueBitSet(ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, int32 const _default, uint8 const _pollIntensity); + bool CreateValueBool(ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, bool const _default, uint8 const _pollIntensity); + bool CreateValueButton(ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, uint8 const _pollIntensity); + bool CreateValueByte(ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, uint8 const _default, uint8 const _pollIntensity); + bool CreateValueDecimal(ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, string const& _default, uint8 const _pollIntensity); + bool CreateValueInt(ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, int32 const _default, uint8 const _pollIntensity); + bool CreateValueList(ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, uint8 const _size, vector const& _items, int32 const _default, uint8 const _pollIntensity); + bool CreateValueRaw(ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, uint8 const* _default, uint8 const _length, uint8 const _pollIntensity); + bool CreateValueSchedule(ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, uint8 const _pollIntensity); + bool CreateValueShort(ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, int16 const _default, uint8 const _pollIntensity); + bool CreateValueString(ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, string const& _default, uint8 const _pollIntensity); // helpers for removing values - void RemoveValueList( ValueList* _value ); + void RemoveValueList(Internal::VC::ValueList* _value); - void ReadValueFromXML( uint8 const _commandClassId, TiXmlElement const* _valueElement ); - bool CreateValueFromXML( uint8 const _commandClassId, TiXmlElement const* _valueElement ); + void ReadValueFromXML(uint8 const _commandClassId, TiXmlElement const* _valueElement); + bool CreateValueFromXML(uint8 const _commandClassId, TiXmlElement const* _valueElement); private: - ValueStore* GetValueStore()const{ return m_values; } + Internal::VC::ValueStore* GetValueStore() const + { + return m_values; + } - ValueStore* m_values; // Values reported via command classes + Internal::VC::ValueStore* m_values; // Values reported via command classes //----------------------------------------------------------------------------- // Configuration Parameters (handled by the Configuration command class) //----------------------------------------------------------------------------- private: - bool SetConfigParam( uint8 const _param, int32 _value, uint8 const _size ); - void RequestConfigParam( uint8 const _param ); - bool RequestAllConfigParams( uint32 const _requestFlags ); + bool SetConfigParam(uint8 const _param, int32 _value, uint8 const _size); + void RequestConfigParam(uint8 const _param); + bool RequestAllConfigParams(uint32 const _requestFlags); //----------------------------------------------------------------------------- // Dynamic Values (used by query and other command classes for updating) @@ -579,21 +697,21 @@ namespace OpenZWave private: // The public interface is provided via the wrappers in the Manager class uint8 GetNumGroups(); - uint32 GetAssociations( uint8 const _groupIdx, uint8** o_associations ); - uint32 GetAssociations( uint8 const _groupIdx, InstanceAssociation** o_associations ); - uint8 GetMaxAssociations( uint8 const _groupIdx ); - bool IsMultiInstance( uint8 const _groupIdx ); - string GetGroupLabel( uint8 const _groupIdx ); - void AddAssociation( uint8 const _groupIdx, uint8 const _targetNodeId, uint8 const _instance = 0x00 ); - void RemoveAssociation( uint8 const _groupIdx, uint8 const _targetNodeId, uint8 const _instance = 0x00 ); + uint32 GetAssociations(uint8 const _groupIdx, uint8** o_associations); + uint32 GetAssociations(uint8 const _groupIdx, InstanceAssociation** o_associations); + uint8 GetMaxAssociations(uint8 const _groupIdx); + bool IsMultiInstance(uint8 const _groupIdx); + string GetGroupLabel(uint8 const _groupIdx); + void AddAssociation(uint8 const _groupIdx, uint8 const _targetNodeId, uint8 const _instance = 0x00); + void RemoveAssociation(uint8 const _groupIdx, uint8 const _targetNodeId, uint8 const _instance = 0x00); void AutoAssociate(); // The following methods are not exposed - Group* GetGroup( uint8 const _groupIdx ); // Get a pointer to a Group object. This must only be called while holding the node Lock. - void AddGroup( Group* _group ); // The groups are fixed properties of a device, so there is no need for a matching RemoveGroup. - void WriteGroups( TiXmlElement* _associationsElement ); // Write the group data out to XNL + Group* GetGroup(uint8 const _groupIdx); // Get a pointer to a Group object. This must only be called while holding the node Lock. + void AddGroup(Group* _group); // The groups are fixed properties of a device, so there is no need for a matching RemoveGroup. + void WriteGroups(TiXmlElement* _associationsElement); // Write the group data out to XNL - map m_groups; // Maps group indices to Group objects. + map m_groups; // Maps group indices to Group objects. //----------------------------------------------------------------------------- // Device Classes (static data read from the device_classes.xml file) @@ -603,56 +721,65 @@ namespace OpenZWave class DeviceClass { public: - DeviceClass( TiXmlElement const* _el ); - ~DeviceClass(){ delete [] m_mandatoryCommandClasses; } - - uint8 const* GetMandatoryCommandClasses(){ return m_mandatoryCommandClasses; } - uint8 GetBasicMapping(){ return m_basicMapping; } - string const& GetLabel(){ return m_label; } + DeviceClass(TiXmlElement const* _el); + ~DeviceClass() + { + delete[] m_mandatoryCommandClasses; + } + + uint8 const* GetMandatoryCommandClasses() + { + return m_mandatoryCommandClasses; + } + uint8 GetBasicMapping() + { + return m_basicMapping; + } + string const& GetLabel() + { + return m_label; + } private: - uint8* m_mandatoryCommandClasses; // Zero terminated array of mandatory command classes for this device type. - uint8 m_basicMapping; // Command class that COMMAND_CLASS_BASIC maps on to, or zero if there is no mapping. - string m_label; // Descriptive label for the device. + uint8* m_mandatoryCommandClasses; // Zero terminated array of mandatory command classes for this device type. + uint8 m_basicMapping; // Command class that COMMAND_CLASS_BASIC maps on to, or zero if there is no mapping. + string m_label; // Descriptive label for the device. }; // Container for generic device class info - class GenericDeviceClass : public DeviceClass + class GenericDeviceClass: public DeviceClass { public: - GenericDeviceClass( TiXmlElement const* _el ); + GenericDeviceClass(TiXmlElement const* _el); ~GenericDeviceClass(); - DeviceClass* GetSpecificDeviceClass( uint8 const& _specific ); + DeviceClass* GetSpecificDeviceClass(uint8 const& _specific); private: - map m_specificDeviceClasses; + map m_specificDeviceClasses; }; - - bool SetDeviceClasses( uint8 const _basic, uint8 const _generic, uint8 const _specific ); // Set the device class data for the node - bool SetPlusDeviceClasses( uint8 const _role, uint8 const _nodeType, uint16 const _deviceType ); // Set the device class data for the node based on the Zwave+ info report - bool AddMandatoryCommandClasses( uint8 const* _commandClasses ); // Add mandatory command classes as specified in the device_classes.xml to the node. + bool SetDeviceClasses(uint8 const _basic, uint8 const _generic, uint8 const _specific); // Set the device class data for the node + bool SetPlusDeviceClasses(uint8 const _role, uint8 const _nodeType, uint16 const _deviceType); // Set the device class data for the node based on the Zwave+ info report + bool AddMandatoryCommandClasses(uint8 const* _commandClasses); // Add mandatory command classes as specified in the device_classes.xml to the node. void ReadDeviceClasses(); // Read the static device class data from the device_classes.xml file - string GetEndPointDeviceClassLabel( uint8 const _generic, uint8 const _specific ); - - static bool s_deviceClassesLoaded; // True if the xml file has already been loaded - static map s_basicDeviceClasses; // Map of basic device classes. - static map s_genericDeviceClasses; // Map of generic device classes. - static map s_roleDeviceClasses; // Map of Zwave+ role device classes. - static map s_deviceTypeClasses; // Map of Zwave+ device type device classes. - static map s_nodeTypes; // Map of ZWave+ Node Types + static bool s_deviceClassesLoaded; // True if the xml file has already been loaded + static map s_basicDeviceClasses; // Map of basic device classes. + static map s_genericDeviceClasses; // Map of generic device classes. + static map s_roleDeviceClasses; // Map of Zwave+ role device classes. + static map s_deviceTypeClasses; // Map of Zwave+ device type device classes. + static map s_nodeTypes; // Map of ZWave+ Node Types //----------------------------------------------------------------------------- // Statistics //----------------------------------------------------------------------------- - public: + public: struct CommandClassData { - uint8 m_commandClassId; - uint32 m_sentCnt; - uint32 m_receivedCnt; + uint8 m_commandClassId; + uint32 m_sentCnt; + uint32 m_receivedCnt; }; struct NodeData @@ -690,8 +817,8 @@ namespace OpenZWave uint8 m_lastFailedLinkTo; }; - private: - void GetNodeStatistics( NodeData* _data ); + private: + void GetNodeStatistics(NodeData* _data); uint32 m_sentCnt; // Number of messages sent from this node. uint32 m_sentFailed; // Number of sent messages failed @@ -701,8 +828,8 @@ namespace OpenZWave uint32 m_receivedUnsolicited; // Number of messages received unsolicited uint32 m_lastRequestRTT; // Last message request RTT uint32 m_lastResponseRTT; // Last message response RTT - TimeStamp m_sentTS; // Last message sent time - TimeStamp m_receivedTS; // Last message received time + Internal::Platform::TimeStamp m_sentTS; // Last message sent time + Internal::Platform::TimeStamp m_receivedTS; // Last message received time uint32 m_averageRequestRTT; // Average Request round trip time. uint32 m_averageResponseRTT; // Average Response round trip time. uint8 m_quality; // Node quality measure @@ -725,16 +852,15 @@ namespace OpenZWave uint8 m_lastFailedLinkFrom; // The last failed link from uint8 m_lastFailedLinkTo; // The last failed link to - //----------------------------------------------------------------------------- // Encryption Related //----------------------------------------------------------------------------- - public: + public: uint8 *GenerateNonceKey(); uint8 *GetNonceKey(uint32 nonceid); - private: + private: uint8 m_lastnonce; uint8 m_nonces[8][8]; @@ -742,7 +868,7 @@ namespace OpenZWave // MetaData Related //----------------------------------------------------------------------------- - public: + public: /** * MetaData Fields. * Available Fields that contain metadata about a device. @@ -768,26 +894,25 @@ namespace OpenZWave MetaData_Invalid = 255 }; - struct ChangeLogEntry { - string author; - string date; - int revision; - string description; + struct ChangeLogEntry + { + string author; + string date; + int revision; + string description; }; string const GetMetaData(MetaDataFields); - MetaDataFields const GetMetaDataId(string); + MetaDataFields GetMetaDataId(string); string const GetMetaDataString(MetaDataFields); ChangeLogEntry const GetChangeLog(uint32_t); - - private: + private: void ReadMetaDataFromXML(TiXmlElement const* _valueElement); void WriteMetaDataXML(TiXmlElement*); map m_metadata; map m_changeLog; }; - } //namespace OpenZWave #endif //_Node_H diff --git a/cpp/src/Notification.cpp b/cpp/src/Notification.cpp index 63f9641cae..cc07e29919 100644 --- a/cpp/src/Notification.cpp +++ b/cpp/src/Notification.cpp @@ -31,16 +31,17 @@ using namespace OpenZWave; - //----------------------------------------------------------------------------- // // Return a string representation of OZW //----------------------------------------------------------------------------- -string Notification::GetAsString() const { +string Notification::GetAsString() const +{ string str; string command; - switch (m_type) { + switch (m_type) + { case Type_ValueAdded: str = "ValueAdded"; break; @@ -120,7 +121,8 @@ string Notification::GetAsString() const { str = "AllNodesQueried"; break; case Type_Notification: - switch (m_byte) { + switch (m_byte) + { case Code_MsgComplete: str = "Notification - MsgComplete"; break; @@ -148,58 +150,59 @@ string Notification::GetAsString() const { str = "DriverRemoved"; break; case Type_ControllerCommand: - switch ( m_command ) - { - case Driver::ControllerCommand_AddDevice: - command = "AddDevice "; - break; - case Driver::ControllerCommand_AssignReturnRoute: - command = "AssignReturnRoute "; - break; - case Driver::ControllerCommand_CreateButton: - command = "CreateButton "; - break; - case Driver::ControllerCommand_CreateNewPrimary: - command = "CreateNewPrimary "; - break; - case Driver::ControllerCommand_DeleteAllReturnRoutes: - command = "DeleteAllReturnRoutes "; - break; - case Driver::ControllerCommand_DeleteButton: - command = "DeleteButton "; - break; - case Driver::ControllerCommand_HasNodeFailed: - command = "HasNodeFailed "; - break; - case Driver::ControllerCommand_ReceiveConfiguration: - command = "ReceiveConfiguration "; - break; - case Driver::ControllerCommand_RemoveDevice: - command = "RemoveDevice "; - break; - case Driver::ControllerCommand_RemoveFailedNode: - command = "RemoveFailedNode "; - break; - case Driver::ControllerCommand_ReplaceFailedNode: - command = "ReplaceFailedNode "; - break; - case Driver::ControllerCommand_ReplicationSend: - command = "ReplicationSend "; - break; - case Driver::ControllerCommand_RequestNetworkUpdate: - command = "RequestNetworkUpdate "; - break; - case Driver::ControllerCommand_RequestNodeNeighborUpdate: - command = "RequestNodeNeighborUpdate "; - break; - case Driver::ControllerCommand_SendNodeInformation: - command = "SendNodeInformation "; - break; - case Driver::ControllerCommand_TransferPrimaryRole: - command = "TransferPrimaryRole "; - break; - } - switch (m_event) { + switch (m_command) + { + case Driver::ControllerCommand_AddDevice: + command = "AddDevice "; + break; + case Driver::ControllerCommand_AssignReturnRoute: + command = "AssignReturnRoute "; + break; + case Driver::ControllerCommand_CreateButton: + command = "CreateButton "; + break; + case Driver::ControllerCommand_CreateNewPrimary: + command = "CreateNewPrimary "; + break; + case Driver::ControllerCommand_DeleteAllReturnRoutes: + command = "DeleteAllReturnRoutes "; + break; + case Driver::ControllerCommand_DeleteButton: + command = "DeleteButton "; + break; + case Driver::ControllerCommand_HasNodeFailed: + command = "HasNodeFailed "; + break; + case Driver::ControllerCommand_ReceiveConfiguration: + command = "ReceiveConfiguration "; + break; + case Driver::ControllerCommand_RemoveDevice: + command = "RemoveDevice "; + break; + case Driver::ControllerCommand_RemoveFailedNode: + command = "RemoveFailedNode "; + break; + case Driver::ControllerCommand_ReplaceFailedNode: + command = "ReplaceFailedNode "; + break; + case Driver::ControllerCommand_ReplicationSend: + command = "ReplicationSend "; + break; + case Driver::ControllerCommand_RequestNetworkUpdate: + command = "RequestNetworkUpdate "; + break; + case Driver::ControllerCommand_RequestNodeNeighborUpdate: + command = "RequestNodeNeighborUpdate "; + break; + case Driver::ControllerCommand_SendNodeInformation: + command = "SendNodeInformation "; + break; + case Driver::ControllerCommand_TransferPrimaryRole: + command = "TransferPrimaryRole "; + break; + } + switch (m_event) + { case Driver::ControllerState_Normal: str = command + "ControllerCommand - Normal"; break; @@ -210,7 +213,8 @@ string Notification::GetAsString() const { str = command + "ControllerCommand - Canceled"; break; case Driver::ControllerState_Error: - switch (m_byte) { + switch (m_byte) + { case Driver::ControllerError_None: str = "ControllerCommand - Error - None"; break; @@ -275,61 +279,61 @@ string Notification::GetAsString() const { break; } break; - case Type_NodeReset: - str = "Node Reset"; - break; - case Type_UserAlerts: - switch (m_useralerttype) { - case Alert_None: - str = "User Alert - No Alert"; - break; - case Alert_ConfigOutOfDate: - str = "User Alert - Config File out of Date"; - break; - case Alert_MFSOutOfDate: - str = "User Alert - Manufacturer_specific.xml out of Date"; - break; - case Alert_ConfigFileDownloadFailed: - str = "A Config File Failed to download"; - break; - case Alert_DNSError: - str = "A DNS Error Occurred"; - break; - case Alert_NodeReloadReqired: - str = "Node Reload Is Required due to new Config File"; - break; - case Alert_UnsupportedController: - str = "Controller Library is not a type we support"; - break; - case Alert_ApplicationStatus_Retry: - str = "Application Status: Retry Later"; - break; - case Alert_ApplicationStatus_Queued: - str = "Application Status: Command has been queued for execution later"; - break; - case Alert_ApplicationStatus_Rejected: - str = "Application Status: Command Rejected"; - } - break; - case Type_ManufacturerSpecificDBReady: - str = "ManufacturerSpecificDB Ready"; - break; + case Type_NodeReset: + str = "Node Reset"; + break; + case Type_UserAlerts: + switch (m_useralerttype) + { + case Alert_None: + str = "User Alert - No Alert"; + break; + case Alert_ConfigOutOfDate: + str = "User Alert - Config File out of Date"; + break; + case Alert_MFSOutOfDate: + str = "User Alert - Manufacturer_specific.xml out of Date"; + break; + case Alert_ConfigFileDownloadFailed: + str = "A Config File Failed to download"; + break; + case Alert_DNSError: + str = "A DNS Error Occurred"; + break; + case Alert_NodeReloadRequired: + str = "Node Reload Is Required due to new Config File"; + break; + case Alert_UnsupportedController: + str = "Controller Library is not a type we support"; + break; + case Alert_ApplicationStatus_Retry: + str = "Application Status: Retry Later"; + break; + case Alert_ApplicationStatus_Queued: + str = "Application Status: Command has been queued for execution later"; + break; + case Alert_ApplicationStatus_Rejected: + str = "Application Status: Command Rejected"; + } + break; + case Type_ManufacturerSpecificDBReady: + str = "ManufacturerSpecificDB Ready"; + break; } return str; } - std::ostream& operator<<(std::ostream &os, const Notification &dt) { - os << dt.GetAsString(); - return os; + os << dt.GetAsString(); + return os; } std::ostream& operator<<(std::ostream &os, const Notification *dt) { - os << dt->GetAsString(); - return os; + os << dt->GetAsString(); + return os; } diff --git a/cpp/src/Notification.h b/cpp/src/Notification.h index affefb6d12..455d536491 100644 --- a/cpp/src/Notification.h +++ b/cpp/src/Notification.h @@ -35,6 +35,24 @@ namespace OpenZWave { + namespace Internal + { + namespace CC + { + class ApplicationStatus; + class Basic; + class ManufacturerSpecific; + class NodeNaming; + class SceneActivation; + class WakeUp; + } + namespace VC + { + class Value; + class ValueStore; + } + class ManufacturerSpecificDB; + } /** \brief Provides a container for data sent via the notification callback * handler installed by a call to Manager::AddWatcher. * @@ -43,220 +61,319 @@ namespace OpenZWave */ class OPENZWAVE_EXPORT Notification { - friend class Manager; - friend class Driver; - friend class Node; - friend class Group; - friend class Value; - friend class ValueStore; - friend class Basic; - friend class ManufacturerSpecific; - friend class NodeNaming; - friend class NoOperation; - friend class SceneActivation; - friend class WakeUp; - friend class ApplicationStatus; - friend class ManufacturerSpecificDB; - /* allow us to Stream a Notification */ - //friend std::ostream &operator<<(std::ostream &os, const Notification &dt); + friend class Manager; + friend class Driver; + friend class Node; + friend class Group; + friend class Internal::VC::Value; + friend class Internal::VC::ValueStore; + friend class Internal::CC::Basic; + friend class Internal::CC::ManufacturerSpecific; + friend class Internal::CC::NodeNaming; + friend class Internal::CC::SceneActivation; + friend class Internal::CC::WakeUp; + friend class Internal::CC::ApplicationStatus; + friend class Internal::ManufacturerSpecificDB; + /* allow us to Stream a Notification */ + //friend std::ostream &operator<<(std::ostream &os, const Notification &dt); + public: + /** + * Notification types. + * Notifications of various Z-Wave events sent to the watchers + * registered with the Manager::AddWatcher method. + * \see Manager::AddWatcher + * \see Manager::BeginControllerCommand + */ + enum NotificationType + { + Type_ValueAdded = 0, /**< A new node value has been added to OpenZWave's list. These notifications occur after a node has been discovered, and details of its command classes have been received. Each command class may generate one or more values depending on the complexity of the item being represented. */ + Type_ValueRemoved, /**< A node value has been removed from OpenZWave's list. This only occurs when a node is removed. */ + Type_ValueChanged, /**< A node value has been updated from the Z-Wave network and it is different from the previous value. */ + Type_ValueRefreshed, /**< A node value has been updated from the Z-Wave network. */ + Type_Group, /**< The associations for the node have changed. The application should rebuild any group information it holds about the node. */ + Type_NodeNew, /**< A new node has been found (not already stored in zwcfg*.xml file) */ + Type_NodeAdded, /**< A new node has been added to OpenZWave's list. This may be due to a device being added to the Z-Wave network, or because the application is initializing itself. */ + Type_NodeRemoved, /**< A node has been removed from OpenZWave's list. This may be due to a device being removed from the Z-Wave network, or because the application is closing. */ + Type_NodeProtocolInfo, /**< Basic node information has been received, such as whether the node is a listening device, a routing device and its baud rate and basic, generic and specific types. It is after this notification that you can call Manager::GetNodeType to obtain a label containing the device description. */ + Type_NodeNaming, /**< One of the node names has changed (name, manufacturer, product). */ + Type_NodeEvent, /**< A node has triggered an event. This is commonly caused when a node sends a Basic_Set command to the controller. The event value is stored in the notification. */ + Type_PollingDisabled, /**< Polling of a node has been successfully turned off by a call to Manager::DisablePoll */ + Type_PollingEnabled, /**< Polling of a node has been successfully turned on by a call to Manager::EnablePoll */ + Type_SceneEvent, /**< Scene Activation Set received (Depreciated in 1.8) */ + Type_CreateButton, /**< Handheld controller button event created */ + Type_DeleteButton, /**< Handheld controller button event deleted */ + Type_ButtonOn, /**< Handheld controller button on pressed event */ + Type_ButtonOff, /**< Handheld controller button off pressed event */ + Type_DriverReady, /**< A driver for a PC Z-Wave controller has been added and is ready to use. The notification will contain the controller's Home ID, which is needed to call most of the Manager methods. */ + Type_DriverFailed, /**< Driver failed to load */ + Type_DriverReset, /**< All nodes and values for this driver have been removed. This is sent instead of potentially hundreds of individual node and value notifications. */ + Type_EssentialNodeQueriesComplete, /**< The queries on a node that are essential to its operation have been completed. The node can now handle incoming messages. */ + Type_NodeQueriesComplete, /**< All the initialization queries on a node have been completed. */ + Type_AwakeNodesQueried, /**< All awake nodes have been queried, so client application can expected complete data for these nodes. */ + Type_AllNodesQueriedSomeDead, /**< All nodes have been queried but some dead nodes found. */ + Type_AllNodesQueried, /**< All nodes have been queried, so client application can expected complete data. */ + Type_Notification, /**< An error has occurred that we need to report. */ + Type_DriverRemoved, /**< The Driver is being removed. (either due to Error or by request) Do Not Call Any Driver Related Methods after receiving this call */ + Type_ControllerCommand, /**< When Controller Commands are executed, Notifications of Success/Failure etc are communicated via this Notification + * Notification::GetEvent returns Driver::ControllerCommand and Notification::GetNotification returns Driver::ControllerState */ + Type_NodeReset, /**< The Device has been reset and thus removed from the NodeList in OZW */ + Type_UserAlerts, /**< Warnings and Notifications Generated by the library that should be displayed to the user (eg, out of date config files) */ + Type_ManufacturerSpecificDBReady /**< The ManufacturerSpecific Database Is Ready */ + }; - public: - /** - * Notification types. - * Notifications of various Z-Wave events sent to the watchers - * registered with the Manager::AddWatcher method. - * \see Manager::AddWatcher - * \see Manager::BeginControllerCommand - */ - enum NotificationType - { - Type_ValueAdded = 0, /**< A new node value has been added to OpenZWave's list. These notifications occur after a node has been discovered, and details of its command classes have been received. Each command class may generate one or more values depending on the complexity of the item being represented. */ - Type_ValueRemoved, /**< A node value has been removed from OpenZWave's list. This only occurs when a node is removed. */ - Type_ValueChanged, /**< A node value has been updated from the Z-Wave network and it is different from the previous value. */ - Type_ValueRefreshed, /**< A node value has been updated from the Z-Wave network. */ - Type_Group, /**< The associations for the node have changed. The application should rebuild any group information it holds about the node. */ - Type_NodeNew, /**< A new node has been found (not already stored in zwcfg*.xml file) */ - Type_NodeAdded, /**< A new node has been added to OpenZWave's list. This may be due to a device being added to the Z-Wave network, or because the application is initializing itself. */ - Type_NodeRemoved, /**< A node has been removed from OpenZWave's list. This may be due to a device being removed from the Z-Wave network, or because the application is closing. */ - Type_NodeProtocolInfo, /**< Basic node information has been received, such as whether the node is a listening device, a routing device and its baud rate and basic, generic and specific types. It is after this notification that you can call Manager::GetNodeType to obtain a label containing the device description. */ - Type_NodeNaming, /**< One of the node names has changed (name, manufacturer, product). */ - Type_NodeEvent, /**< A node has triggered an event. This is commonly caused when a node sends a Basic_Set command to the controller. The event value is stored in the notification. */ - Type_PollingDisabled, /**< Polling of a node has been successfully turned off by a call to Manager::DisablePoll */ - Type_PollingEnabled, /**< Polling of a node has been successfully turned on by a call to Manager::EnablePoll */ - Type_SceneEvent, /**< Scene Activation Set received (Depreciated in 1.8) */ - Type_CreateButton, /**< Handheld controller button event created */ - Type_DeleteButton, /**< Handheld controller button event deleted */ - Type_ButtonOn, /**< Handheld controller button on pressed event */ - Type_ButtonOff, /**< Handheld controller button off pressed event */ - Type_DriverReady, /**< A driver for a PC Z-Wave controller has been added and is ready to use. The notification will contain the controller's Home ID, which is needed to call most of the Manager methods. */ - Type_DriverFailed, /**< Driver failed to load */ - Type_DriverReset, /**< All nodes and values for this driver have been removed. This is sent instead of potentially hundreds of individual node and value notifications. */ - Type_EssentialNodeQueriesComplete, /**< The queries on a node that are essential to its operation have been completed. The node can now handle incoming messages. */ - Type_NodeQueriesComplete, /**< All the initialization queries on a node have been completed. */ - Type_AwakeNodesQueried, /**< All awake nodes have been queried, so client application can expected complete data for these nodes. */ - Type_AllNodesQueriedSomeDead, /**< All nodes have been queried but some dead nodes found. */ - Type_AllNodesQueried, /**< All nodes have been queried, so client application can expected complete data. */ - Type_Notification, /**< An error has occurred that we need to report. */ - Type_DriverRemoved, /**< The Driver is being removed. (either due to Error or by request) Do Not Call Any Driver Related Methods after receiving this call */ - Type_ControllerCommand, /**< When Controller Commands are executed, Notifications of Success/Failure etc are communicated via this Notification - * Notification::GetEvent returns Driver::ControllerCommand and Notification::GetNotification returns Driver::ControllerState */ - Type_NodeReset, /**< The Device has been reset and thus removed from the NodeList in OZW */ - Type_UserAlerts, /**< Warnings and Notifications Generated by the library that should be displayed to the user (eg, out of date config files) */ - Type_ManufacturerSpecificDBReady /**< The ManufacturerSpecific Database Is Ready */ - }; + /** + * Notification codes. + * Notifications of the type Type_Notification convey some + * extra information defined here. + */ + enum NotificationCode + { + Code_MsgComplete = 0, /**< Completed messages */ + Code_Timeout, /**< Messages that timeout will send a Notification with this code. */ + Code_NoOperation, /**< Report on NoOperation message sent completion */ + Code_Awake, /**< Report when a sleeping node wakes up */ + Code_Sleep, /**< Report when a node goes to sleep */ + Code_Dead, /**< Report when a node is presumed dead */ + Code_Alive /**< Report when a node is revived */ + }; - /** - * Notification codes. - * Notifications of the type Type_Notification convey some - * extra information defined here. - */ - enum NotificationCode - { - Code_MsgComplete = 0, /**< Completed messages */ - Code_Timeout, /**< Messages that timeout will send a Notification with this code. */ - Code_NoOperation, /**< Report on NoOperation message sent completion */ - Code_Awake, /**< Report when a sleeping node wakes up */ - Code_Sleep, /**< Report when a node goes to sleep */ - Code_Dead, /**< Report when a node is presumed dead */ - Code_Alive /**< Report when a node is revived */ - }; + /** + * User Alert Types - These are messages that should be displayed to users to inform them of + * potential issues such as Out of Date configuration files etc + */ + enum UserAlertNotification + { + Alert_None, /**< No Alert Currently Present */ + Alert_ConfigOutOfDate, /**< One of the Config Files is out of date. Use GetNodeId to determine which node is effected. */ + Alert_MFSOutOfDate, /**< the manufacturer_specific.xml file is out of date. */ + Alert_ConfigFileDownloadFailed, /**< A Config File failed to download */ + Alert_DNSError, /**< A error occurred performing a DNS Lookup */ + Alert_NodeReloadRequired, /**< A new Config file has been discovered for this node, and its pending a Reload to Take affect */ + Alert_UnsupportedController, /**< The Controller is not running a Firmware Library we support */ + Alert_ApplicationStatus_Retry, /**< Application Status CC returned a Retry Later Message */ + Alert_ApplicationStatus_Queued, /**< Command Has been Queued for later execution */ + Alert_ApplicationStatus_Rejected, /**< Command has been rejected */ + }; - /** - * User Alert Types - These are messages that should be displayed to users to inform them of - * potential issues such as Out of Date configuration files etc - */ - enum UserAlertNotification - { - Alert_None, /**< No Alert Currently Present */ - Alert_ConfigOutOfDate, /**< One of the Config Files is out of date. Use GetNodeId to determine which node is affected. */ - Alert_MFSOutOfDate, /**< the manufacturer_specific.xml file is out of date. */ - Alert_ConfigFileDownloadFailed, /**< A Config File failed to download */ - Alert_DNSError, /**< A error occurred performing a DNS Lookup */ - Alert_NodeReloadReqired, /**< A new Config file has been discovered for this node, and its pending a Reload to Take Effect */ - Alert_UnsupportedController, /**< The Controller is not running a Firmware Library we support */ - Alert_ApplicationStatus_Retry, /**< Application Status CC returned a Retry Later Message */ - Alert_ApplicationStatus_Queued, /**< Command Has been Queued for execution later */ - Alert_ApplicationStatus_Rejected, /**< Command has been rejected */ - }; + /** + * Get the type of this notification. + * \return the notification type. + * \see NotificationType + */ + NotificationType GetType() const + { + return m_type; + } - /** - * Get the type of this notification. - * \return the notification type. - * \see NotificationType - */ - NotificationType GetType()const{ return m_type; } + /** + * Get the Home ID of the driver sending this notification. + * \return the driver Home ID + */ + uint32 GetHomeId() const + { + return m_valueId.GetHomeId(); + } - /** - * Get the Home ID of the driver sending this notification. - * \return the driver Home ID - */ - uint32 GetHomeId()const{ return m_valueId.GetHomeId(); } + /** + * Get the ID of any node involved in this notification. + * \return the node's ID + */ + uint8 GetNodeId() const + { + return m_valueId.GetNodeId(); + } - /** - * Get the ID of any node involved in this notification. - * \return the node's ID - */ - uint8 GetNodeId()const{ return m_valueId.GetNodeId(); } + /** + * Get the unique ValueID of any value involved in this notification. + * \return the value's ValueID + */ + ValueID const& GetValueID() const + { + return m_valueId; + } - /** - * Get the unique ValueID of any value involved in this notification. - * \return the value's ValueID - */ - ValueID const& GetValueID()const{ return m_valueId; } + /** + * Get the index of the association group that has been changed. Only valid in Notification::Type_Group notifications. + * \return the group index. + */ + uint8 GetGroupIdx() const + { + assert(Type_Group == m_type); + return m_byte; + } - /** - * Get the index of the association group that has been changed. Only valid in Notification::Type_Group notifications. - * \return the group index. - */ - uint8 GetGroupIdx()const{ assert(Type_Group==m_type); return m_byte; } + /** + * Get the event value of a notification. Only valid in Notification::Type_NodeEvent and Notification::Type_ControllerCommand notifications. + * \return the event value. + */ + uint8 GetEvent() const + { + assert((Type_NodeEvent == m_type) || (Type_ControllerCommand == m_type)); + return m_event; + } - /** - * Get the event value of a notification. Only valid in Notification::Type_NodeEvent and Notification::Type_ControllerCommand notifications. - * \return the event value. - */ - uint8 GetEvent()const{ assert((Type_NodeEvent==m_type) || (Type_ControllerCommand == m_type)); return m_event; } + /** + * Get the button id of a notification. Only valid in Notification::Type_CreateButton, Notification::Type_DeleteButton, + * Notification::Type_ButtonOn and Notification::Type_ButtonOff notifications. + * \return the button id. + */ + uint8 GetButtonId() const + { + assert(Type_CreateButton == m_type || Type_DeleteButton == m_type || Type_ButtonOn == m_type || Type_ButtonOff == m_type); + return m_byte; + } - /** - * Get the button id of a notification. Only valid in Notification::Type_CreateButton, Notification::Type_DeleteButton, - * Notification::Type_ButtonOn and Notification::Type_ButtonOff notifications. - * \return the button id. - */ - uint8 GetButtonId()const{ assert(Type_CreateButton==m_type || Type_DeleteButton==m_type || Type_ButtonOn==m_type || Type_ButtonOff==m_type); return m_byte; } + /** + * Get the scene Id of a notification. Only valid in Notification::Type_SceneEvent notifications. + * The SceneActivation CC now exposes ValueID's that convey this information + * \return the event value. + */ + DEPRECATED uint8 GetSceneId() const + { + assert(Type_SceneEvent == m_type); + return m_byte; + } - /** - * Get the scene Id of a notification. Only valid in Notification::Type_SceneEvent notifications. - * The SceneActivation CC now exposes ValueID's that convey this information - * \return the event value. - */ - DEPRECATED uint8 GetSceneId()const{ assert(Type_SceneEvent==m_type); return m_byte; } + /** + * Get the notification code from a notification. Only valid for Notification::Type_Notification or Notification::Type_ControllerCommand notifications. + * \return the notification code. + */ + uint8 GetNotification() const + { + assert((Type_Notification == m_type) || (Type_ControllerCommand == m_type)); + return m_byte; + } - /** - * Get the notification code from a notification. Only valid for Notification::Type_Notification or Notification::Type_ControllerCommand notifications. - * \return the notification code. - */ - uint8 GetNotification()const{ assert((Type_Notification==m_type) || (Type_ControllerCommand == m_type)); return m_byte; } + /** + * Get the (controller) command from a notification. Only valid for Notification::Type_ControllerCommand notifications. + * \return the (controller) command code. + */ + uint8 GetCommand() const + { + assert(Type_ControllerCommand == m_type); + return m_command; + } - /** - * Get the (controller) command from a notification. Only valid for Notification::Type_ControllerCommand notifications. - * \return the (controller) command code. - */ - uint8 GetCommand()const{ assert(Type_ControllerCommand == m_type); return m_command; } - - /** - * Helper function to simplify wrapping the notification class. Should not normally need to be called. - * \return the internal byte value of the notification. - */ - uint8 GetByte()const{ return m_byte; } + /** + * Helper function to simplify wrapping the notification class. Should not normally need to be called. + * \return the internal byte value of the notification. + */ + uint8 GetByte() const + { + return m_byte; + } - /** - * Helper function to return the Timeout to wait for. Only valid for Notification::Type_UserAlerts - Notification::Alert_ApplicationStatus_Retry - * \return The time to wait before retrying - */ - uint8 GetRetry()const{ assert((Type_UserAlerts == m_type) && (Alert_ApplicationStatus_Retry == m_useralerttype)); return m_byte; } + /** + * Helper function to return the Timeout to wait for. Only valid for Notification::Type_UserAlerts - Notification::Alert_ApplicationStatus_Retry + * \return The time to wait before retrying + */ + uint8 GetRetry() const + { + assert((Type_UserAlerts == m_type) && (Alert_ApplicationStatus_Retry == m_useralerttype)); + return m_byte; + } - /** - * Helper Function to return the Notification as a String - * \return A string representation of this Notification - */ - string GetAsString()const; + /** + * Helper Function to return the Notification as a String + * \return A string representation of this Notification + */ + string GetAsString() const; - /** - * Retrieve the User Alert Type Enum to determine what this message is about - * \return UserAlertNotification Enum describing the Alert Type - */ - UserAlertNotification GetUserAlertType()const {return m_useralerttype;}; + /** + * Retrieve the User Alert Type Enum to determine what this message is about + * \return UserAlertNotification Enum describing the Alert Type + */ + UserAlertNotification GetUserAlertType() const + { + return m_useralerttype; + } + ; - /** - * Return the Comport associated with the DriverFailed Message - * \return a string representing the Comport - */ - string GetComPort()const { return m_comport; }; + /** + * Return the Comport associated with the DriverFailed Message + * \return a string representing the Comport + */ + string GetComPort() const + { + return m_comport; + } + ; - private: - Notification( NotificationType _type ): m_type( _type ), m_byte(0), m_event(0), m_command(0), m_useralerttype(Alert_None) {} - ~Notification(){} + private: + Notification(NotificationType _type) : + m_type(_type), m_byte(0), m_event(0), m_command(0), m_useralerttype(Alert_None) + { + } + ~Notification() + { + } - void SetHomeAndNodeIds( uint32 const _homeId, uint8 const _nodeId ){ m_valueId = ValueID( _homeId, _nodeId ); } - void SetHomeNodeIdAndInstance ( uint32 const _homeId, uint8 const _nodeId, uint32 const _instance ){ m_valueId = ValueID( _homeId, _nodeId, _instance ); } - void SetValueId( ValueID const& _valueId ){ m_valueId = _valueId; } - void SetGroupIdx( uint8 const _groupIdx ){ assert(Type_Group==m_type); m_byte = _groupIdx; } - void SetEvent( uint8 const _event ){ assert(Type_NodeEvent==m_type || Type_ControllerCommand == m_type); m_event = _event; } - void SetSceneId( uint8 const _sceneId ){ assert(Type_SceneEvent==m_type); m_byte = _sceneId; } - void SetButtonId( uint8 const _buttonId ){ assert(Type_CreateButton==m_type||Type_DeleteButton==m_type||Type_ButtonOn==m_type||Type_ButtonOff==m_type); m_byte = _buttonId; } - void SetNotification( uint8 const _noteId ){ assert((Type_Notification==m_type) || (Type_ControllerCommand == m_type)); m_byte = _noteId; } - void SetUserAlertNotification(UserAlertNotification const alerttype){ assert(Type_UserAlerts==m_type); m_useralerttype = alerttype; } - void SetCommand( uint8 const _command ){ assert(Type_ControllerCommand == m_type); m_command = _command; } - void SetComPort( string comport) { assert(Type_DriverFailed == m_type); m_comport = comport; } - void SetRetry (uint8 const timeout) { assert(Type_UserAlerts == m_type); m_byte = timeout; } + void SetHomeAndNodeIds(uint32 const _homeId, uint8 const _nodeId) + { + m_valueId = ValueID(_homeId, _nodeId); + } + void SetHomeNodeIdAndInstance(uint32 const _homeId, uint8 const _nodeId, uint32 const _instance) + { + m_valueId = ValueID(_homeId, _nodeId, _instance); + } + void SetValueId(ValueID const& _valueId) + { + m_valueId = _valueId; + } + void SetGroupIdx(uint8 const _groupIdx) + { + assert(Type_Group == m_type); + m_byte = _groupIdx; + } + void SetEvent(uint8 const _event) + { + assert(Type_NodeEvent == m_type || Type_ControllerCommand == m_type); + m_event = _event; + } + void SetSceneId(uint8 const _sceneId) + { + assert(Type_SceneEvent == m_type); + m_byte = _sceneId; + } + void SetButtonId(uint8 const _buttonId) + { + assert(Type_CreateButton == m_type || Type_DeleteButton == m_type || Type_ButtonOn == m_type || Type_ButtonOff == m_type); + m_byte = _buttonId; + } + void SetNotification(uint8 const _noteId) + { + assert((Type_Notification == m_type) || (Type_ControllerCommand == m_type)); + m_byte = _noteId; + } + void SetUserAlertNotification(UserAlertNotification const alerttype) + { + assert(Type_UserAlerts == m_type); + m_useralerttype = alerttype; + } + void SetCommand(uint8 const _command) + { + assert(Type_ControllerCommand == m_type); + m_command = _command; + } + void SetComPort(string comport) + { + assert(Type_DriverFailed == m_type); + m_comport = comport; + } + void SetRetry(uint8 const timeout) + { + assert(Type_UserAlerts == m_type); + m_byte = timeout; + } - NotificationType m_type; - ValueID m_valueId; - uint8 m_byte; - uint8 m_event; - uint8 m_command; - UserAlertNotification m_useralerttype; - string m_comport; + NotificationType m_type; + ValueID m_valueId; + uint8 m_byte; + uint8 m_event; + uint8 m_command; + UserAlertNotification m_useralerttype; + string m_comport; }; } //namespace OpenZWave diff --git a/cpp/src/NotificationCCTypes.cpp b/cpp/src/NotificationCCTypes.cpp index 291b279f94..94c9807bef 100755 --- a/cpp/src/NotificationCCTypes.cpp +++ b/cpp/src/NotificationCCTypes.cpp @@ -30,355 +30,366 @@ #include "tinyxml.h" #include "Options.h" +#include "Utils.h" #include "platform/Log.h" -using namespace OpenZWave; - -NotificationCCTypes *NotificationCCTypes::m_instance = NULL; -std::map NotificationCCTypes::Notifications; -uint32 NotificationCCTypes::m_revision(0); - -NotificationCCTypes::NotificationCCTypes() -{ -} - -void NotificationCCTypes::ReadXML -( -) +namespace OpenZWave { - // Parse the Z-Wave manufacturer and product XML file. - string configPath; - Options::Get()->GetOptionAsString( "ConfigPath", &configPath ); - - string path = configPath + "NotificationCCTypes.xml"; - TiXmlDocument* pDoc = new TiXmlDocument(); - if( !pDoc->LoadFile( path.c_str(), TIXML_ENCODING_UTF8 ) ) + namespace Internal { - delete pDoc; - Log::Write( LogLevel_Warning, "Unable to load NotificationCCTypes file %s", path.c_str()); - return; - } - pDoc->SetUserData((void*)path.c_str()); - Log::Write( LogLevel_Info, "Loading NotificationCCTypes File %s", path.c_str() ); - TiXmlElement const* root = pDoc->RootElement(); - char const *str = root->Value(); - if( str && !strcmp( str, "NotificationTypes" ) ) - { - // Read in the revision attributes - str = root->Attribute( "Revision" ); - if( !str ) + NotificationCCTypes *NotificationCCTypes::m_instance = NULL; + std::map > NotificationCCTypes::Notifications; + uint32 NotificationCCTypes::m_revision(0); + + NotificationCCTypes::NotificationCCTypes() { - Log::Write( LogLevel_Info, "Error in Product Config file at line %d - missing Revision attribute", root->Row() ); - delete pDoc; - return; } - m_revision = atol(str); - } - TiXmlElement const* AlarmTypeElement = root->FirstChildElement(); - while( AlarmTypeElement ) - { - char const* str = AlarmTypeElement->Value(); - char* pStopChar; - if( str && !strcmp( str, "AlarmType" ) ) + + void NotificationCCTypes::ReadXML() { - NotificationTypes *nt = new NotificationTypes; + // Parse the Z-Wave manufacturer and product XML file. + string configPath; + Options::Get()->GetOptionAsString("ConfigPath", &configPath); - str = AlarmTypeElement->Attribute( "id" ); - if( !str ) + string path = configPath + "NotificationCCTypes.xml"; + TiXmlDocument* pDoc = new TiXmlDocument(); + if (!pDoc->LoadFile(path.c_str(), TIXML_ENCODING_UTF8)) { - Log::Write( LogLevel_Warning, "NotificationCCTypes::ReadXML: Error in %s at line %d - missing AlarmType ID attribute", AlarmTypeElement->GetDocument()->GetUserData(), AlarmTypeElement->Row() ); - AlarmTypeElement = AlarmTypeElement->NextSiblingElement(); - delete nt; - continue; + delete pDoc; + Log::Write(LogLevel_Warning, "Unable to load NotificationCCTypes file %s", path.c_str()); + return; } - nt->id = (uint32)strtol( str, &pStopChar, 10 ); - str = AlarmTypeElement->Attribute( "name" ); - if ( !str ) + pDoc->SetUserData((void*) path.c_str()); + Log::Write(LogLevel_Info, "Loading NotificationCCTypes File %s", path.c_str()); + + TiXmlElement const* root = pDoc->RootElement(); + char const *str = root->Value(); + if (str && !strcmp(str, "NotificationTypes")) { - Log::Write( LogLevel_Warning, "NotificationCCTypes::ReadXML: Error in %s at line %d - missing AlarmType name attribute", AlarmTypeElement->GetDocument()->GetUserData(), AlarmTypeElement->Row() ); - AlarmTypeElement = AlarmTypeElement->NextSiblingElement(); - delete nt; - continue; + // Read in the revision attributes + str = root->Attribute("Revision"); + if (!str) + { + Log::Write(LogLevel_Info, "Error in Product Config file at line %d - missing Revision attribute", root->Row()); + delete pDoc; + return; + } + m_revision = atol(str); } - nt->name = str; - TiXmlElement const* AlarmEventElement = AlarmTypeElement->FirstChildElement(); - while (AlarmEventElement) { - str = AlarmEventElement->Value(); - if (str && !strcmp( str, "AlarmEvent" ) ) + TiXmlElement const* AlarmTypeElement = root->FirstChildElement(); + while (AlarmTypeElement) + { + char const* str = AlarmTypeElement->Value(); + char* pStopChar; + if (str && !strcmp(str, "AlarmType")) { - NotificationEvents *ne = new NotificationEvents; - str = AlarmEventElement->Attribute( "id" ); - if ( !str ) + NotificationTypes *nt = new NotificationTypes; + + str = AlarmTypeElement->Attribute("id"); + if (!str) { - Log::Write( LogLevel_Warning, "NotificationCCTypes::ReadXML: Error in %s at line %d - missing AlarmEventParam id attribute", AlarmEventElement->GetDocument()->GetUserData(), AlarmEventElement->Row() ); - AlarmEventElement = AlarmEventElement->NextSiblingElement(); - delete ne; + Log::Write(LogLevel_Warning, "NotificationCCTypes::ReadXML: Error in %s at line %d - missing AlarmType ID attribute", AlarmTypeElement->GetDocument()->GetUserData(), AlarmTypeElement->Row()); + AlarmTypeElement = AlarmTypeElement->NextSiblingElement(); + delete nt; continue; } - - ne->id = (uint32)strtol( str, &pStopChar, 10 ); - - str = AlarmEventElement->Attribute( "name" ); - if ( !str ) + nt->id = (uint32) strtol(str, &pStopChar, 10); + str = AlarmTypeElement->Attribute("name"); + if (!str) { - Log::Write( LogLevel_Warning, "NotificationCCTypes::ReadXML: Error in %s at line %d - missing AlarmEventParam name attribute", AlarmEventElement->GetDocument()->GetUserData(), AlarmEventElement->Row() ); - AlarmEventElement = AlarmEventElement->NextSiblingElement(); - delete ne; + Log::Write(LogLevel_Warning, "NotificationCCTypes::ReadXML: Error in %s at line %d - missing AlarmType name attribute", AlarmTypeElement->GetDocument()->GetUserData(), AlarmTypeElement->Row()); + AlarmTypeElement = AlarmTypeElement->NextSiblingElement(); + delete nt; continue; } - ne->name = str; - - TiXmlElement const* nextElement = AlarmEventElement->FirstChildElement(); - while (nextElement) { - str = nextElement->Value(); - if (str && !strcmp( str, "AlarmEventParam" ) ) + nt->name = str; + trim(nt->name); + TiXmlElement const* AlarmEventElement = AlarmTypeElement->FirstChildElement(); + while (AlarmEventElement) + { + str = AlarmEventElement->Value(); + if (str && !strcmp(str, "AlarmEvent")) { - NotificationEventParams *aep = new NotificationEventParams; - str = nextElement->Attribute( "id" ); - if ( !str ) + NotificationEvents *ne = new NotificationEvents; + str = AlarmEventElement->Attribute("id"); + if (!str) { - Log::Write( LogLevel_Warning, "NotificationCCTypes::ReadXML: Error in %s at line %d - missing AlarmEventParam id attribute", nextElement->GetDocument()->GetUserData(), nextElement->Row() ); - nextElement = nextElement->NextSiblingElement(); - delete aep; + Log::Write(LogLevel_Warning, "NotificationCCTypes::ReadXML: Error in %s at line %d - missing AlarmEventParam id attribute", AlarmEventElement->GetDocument()->GetUserData(), AlarmEventElement->Row()); + AlarmEventElement = AlarmEventElement->NextSiblingElement(); + delete ne; continue; } - aep->id = (uint32)strtol( str, &pStopChar, 10 ); - str = nextElement->Attribute( "type" ); - if ( !str ) + ne->id = (uint32) strtol(str, &pStopChar, 10); + + str = AlarmEventElement->Attribute("name"); + if (!str) { - Log::Write( LogLevel_Warning, "NotificationCCTypes::ReadXML: Error in %s at line %d - missing AlarmEventParam id attribute", nextElement->GetDocument()->GetUserData(), nextElement->Row() ); - nextElement = nextElement->NextSiblingElement(); - delete aep; + Log::Write(LogLevel_Warning, "NotificationCCTypes::ReadXML: Error in %s at line %d - missing AlarmEventParam name attribute", AlarmEventElement->GetDocument()->GetUserData(), AlarmEventElement->Row()); + AlarmEventElement = AlarmEventElement->NextSiblingElement(); + delete ne; continue; } + ne->name = str; + trim(ne->name); + TiXmlElement const* nextElement = AlarmEventElement->FirstChildElement(); + while (nextElement) + { + str = nextElement->Value(); + if (str && !strcmp(str, "AlarmEventParam")) + { + NotificationEventParams *aep = new NotificationEventParams; + str = nextElement->Attribute("id"); + if (!str) + { + Log::Write(LogLevel_Warning, "NotificationCCTypes::ReadXML: Error in %s at line %d - missing AlarmEventParam id attribute", nextElement->GetDocument()->GetUserData(), nextElement->Row()); + nextElement = nextElement->NextSiblingElement(); + delete aep; + continue; + } + aep->id = (uint32) strtol(str, &pStopChar, 10); - if (!strcasecmp(str, "location")) { - aep->type = NotificationCCTypes::NEPT_Location; - } else if (!strcasecmp(str, "list")) { - aep->type = NotificationCCTypes::NEPT_List; - TiXmlElement const* listElement = nextElement->FirstChildElement(); - while (listElement) { - str = listElement->Value(); - if (str && !strcmp( str, "Item" ) ) + str = nextElement->Attribute("type"); + if (!str) { - str = listElement->Attribute( "id" ); - if ( !str ) - { - Log::Write( LogLevel_Warning, "NotificationCCTypes::ReadXML: Error in %s at line %d - missing Item id attribute", listElement->GetDocument()->GetUserData(), nextElement->Row() ); - listElement = listElement->NextSiblingElement(); - continue; - } - uint32 listID = (uint32)strtol( str, &pStopChar, 10 ); - str = listElement->Attribute( "label" ); - if ( !str ) + Log::Write(LogLevel_Warning, "NotificationCCTypes::ReadXML: Error in %s at line %d - missing AlarmEventParam id attribute", nextElement->GetDocument()->GetUserData(), nextElement->Row()); + nextElement = nextElement->NextSiblingElement(); + delete aep; + continue; + } + + if (!strcasecmp(str, "location")) + { + aep->type = NotificationCCTypes::NEPT_Location; + } + else if (!strcasecmp(str, "list")) + { + aep->type = NotificationCCTypes::NEPT_List; + TiXmlElement const* listElement = nextElement->FirstChildElement(); + while (listElement) { - Log::Write( LogLevel_Warning, "NotificationCCTypes::ReadXML: Error in %s at line %d - missing Item name attribute", listElement->GetDocument()->GetUserData(), nextElement->Row() ); + str = listElement->Value(); + if (str && !strcmp(str, "Item")) + { + str = listElement->Attribute("id"); + if (!str) + { + Log::Write(LogLevel_Warning, "NotificationCCTypes::ReadXML: Error in %s at line %d - missing Item id attribute", listElement->GetDocument()->GetUserData(), nextElement->Row()); + listElement = listElement->NextSiblingElement(); + continue; + } + uint32 listID = (uint32) strtol(str, &pStopChar, 10); + str = listElement->Attribute("label"); + if (!str) + { + Log::Write(LogLevel_Warning, "NotificationCCTypes::ReadXML: Error in %s at line %d - missing Item name attribute", listElement->GetDocument()->GetUserData(), nextElement->Row()); + listElement = listElement->NextSiblingElement(); + continue; + } + if (aep->ListItems.find(listID) == aep->ListItems.end()) + { + aep->ListItems.insert(std::pair(listID, str)); + } + else + { + Log::Write(LogLevel_Warning, "NotificationCCTypes::ReadXML: Error in %s - A AlarmEventElement with id %d already exists. Skipping ", listElement->GetDocument()->GetUserData(), ne->id); + } + } listElement = listElement->NextSiblingElement(); - continue; - } - if (aep->ListItems.find(listID) == aep->ListItems.end()) { - aep->ListItems.insert(std::pair(listID, str)); - } else { - Log::Write( LogLevel_Warning, "NotificationCCTypes::ReadXML: Error in %s - A AlarmEventElement with id %d already exists. Skipping ", listElement->GetDocument()->GetUserData(), ne->id); } } - listElement = listElement->NextSiblingElement(); + else if (!strcasecmp(str, "usercodereport")) + { + aep->type = NotificationCCTypes::NEPT_UserCodeReport; + } + else if (!strcasecmp(str, "byte")) + { + aep->type = NotificationCCTypes::NEPT_Byte; + } + else if (!strcasecmp(str, "string")) + { + aep->type = NotificationCCTypes::NEPT_String; + } + else if (!strcasecmp(str, "duration")) + { + aep->type = NotificationCCTypes::NEPT_Time; + } + else + { + Log::Write(LogLevel_Warning, "NotificationCCTypes::ReadXML: Error in %s at line %d - unknown AlarmEventParam type attribute (%s)", nextElement->GetDocument()->GetUserData(), nextElement->Row(), str); + nextElement = nextElement->NextSiblingElement(); + continue; + } + + str = nextElement->Attribute("name"); + if (!str) + { + Log::Write(LogLevel_Warning, "NotificationCCTypes::ReadXML: Error in %s at line %d - missing AlarmEventParam name attribute", nextElement->GetDocument()->GetUserData(), nextElement->Row()); + nextElement = nextElement->NextSiblingElement(); + continue; + } + aep->name = str; + trim(aep->name); + if (ne->EventParams.find(aep->id) == ne->EventParams.end()) + ne->EventParams[aep->id] = std::shared_ptr(aep); + else + { + Log::Write(LogLevel_Warning, "NotificationCCTypes::ReadXML: Error in %s - A AlarmEventParam with id %d already exists. Skipping ", nextElement->GetDocument()->GetUserData(), aep->id); + delete aep; + } } - } else if (!strcasecmp(str, "usercodereport")) { - aep->type = NotificationCCTypes::NEPT_UserCodeReport; - } else if (!strcasecmp(str, "byte")) { - aep->type = NotificationCCTypes::NEPT_Byte; - } else if (!strcasecmp(str, "string")) { - aep->type = NotificationCCTypes::NEPT_String; - } else if (!strcasecmp(str, "duration")) { - aep->type = NotificationCCTypes::NEPT_Time; - } else { - Log::Write( LogLevel_Warning, "NotificationCCTypes::ReadXML: Error in %s at line %d - unknown AlarmEventParam type attribute (%s)", nextElement->GetDocument()->GetUserData(), nextElement->Row(), str ); nextElement = nextElement->NextSiblingElement(); - continue; } - - str = nextElement->Attribute( "name" ); - if ( !str ) + if (nt->Events.find(ne->id) == nt->Events.end()) + nt->Events[ne->id] = std::shared_ptr(ne); + else { - Log::Write( LogLevel_Warning, "NotificationCCTypes::ReadXML: Error in %s at line %d - missing AlarmEventParam name attribute", nextElement->GetDocument()->GetUserData(), nextElement->Row() ); - nextElement = nextElement->NextSiblingElement(); - continue; - } - aep->name = str; - - if (ne->EventParams.find(aep->id) == ne->EventParams.end()) - ne->EventParams[aep->id] = aep; - else { - Log::Write( LogLevel_Warning, "NotificationCCTypes::ReadXML: Error in %s - A AlarmEventParam with id %d already exists. Skipping ", nextElement->GetDocument()->GetUserData(), aep->id); - delete aep; + Log::Write(LogLevel_Warning, "NotificationCCTypes::ReadXML: Error in %s - A AlarmEventElement with id %d already exists. Skipping ", AlarmEventElement->GetDocument()->GetUserData(), ne->id); + delete ne; } } - nextElement = nextElement->NextSiblingElement(); + AlarmEventElement = AlarmEventElement->NextSiblingElement(); } - if (nt->Events.find(ne->id) == nt->Events.end()) - nt->Events[ne->id] = ne; - else { - Log::Write( LogLevel_Warning, "NotificationCCTypes::ReadXML: Error in %s - A AlarmEventElement with id %d already exists. Skipping ", AlarmEventElement->GetDocument()->GetUserData(), ne->id); - delete ne; + if (Notifications.find(nt->id) == Notifications.end()) + Notifications[nt->id] = std::shared_ptr(nt); + else + { + Log::Write(LogLevel_Warning, "NotificationCCTypes::ReadXML: Error in %s - A AlarmTypeElement with id %d already exists. Skipping ", AlarmTypeElement->GetDocument()->GetUserData(), nt->id); + delete nt; } } - AlarmEventElement = AlarmEventElement->NextSiblingElement(); - } - if (Notifications.find(nt->id) == Notifications.end()) - Notifications[nt->id] = nt; - else { - Log::Write( LogLevel_Warning, "NotificationCCTypes::ReadXML: Error in %s - A AlarmTypeElement with id %d already exists. Skipping ", AlarmTypeElement->GetDocument()->GetUserData(), nt->id); - delete nt; + AlarmTypeElement = AlarmTypeElement->NextSiblingElement(); } - } - AlarmTypeElement = AlarmTypeElement->NextSiblingElement(); - } - Log::Write(LogLevel_Info, "Loaded %s With Revision %d", pDoc->GetUserData(), m_revision); + Log::Write(LogLevel_Info, "Loaded %s With Revision %d", pDoc->GetUserData(), m_revision); #if 0 - std::cout << "NotificationCCTypes" << std::endl; - for (std::map::iterator it = Notifications.begin(); it != Notifications.end(); it++) { - std::cout << "\tAlarmType:" << it->first << " Name: " << it->second->name << std::endl; - for (std::map::iterator it2 = it->second->Events.begin(); it2 != it->second->Events.end(); it2++) { - std::cout << "\t\tAlarmEvents: " << it2->first << " Name: " << it2->second->name << std::endl; - for (std::map::iterator it3 = it2->second->EventParams.begin(); it3 != it2->second->EventParams.end(); it3++) { - std::cout << "\t\t\tEventParams: " << it3->first << " Name: " << it3->second->name << " Type: " << GetEventParamNames(it3->second->type) << std::endl; - for (std::map::iterator it4 = it3->second->ListItems.begin(); it4 != it3->second->ListItems.end(); it4++) { - std::cout << "\t\t\t\tEventParamsList: " << it4->first << " Name: " << it4->second << std::endl; + std::cout << "NotificationCCTypes" << std::endl; + for (std::map::iterator it = Notifications.begin(); it != Notifications.end(); it++) + { + std::cout << "\tAlarmType:" << it->first << " Name: " << it->second->name << std::endl; + for (std::map::iterator it2 = it->second->Events.begin(); it2 != it->second->Events.end(); it2++) + { + std::cout << "\t\tAlarmEvents: " << it2->first << " Name: " << it2->second->name << std::endl; + for (std::map::iterator it3 = it2->second->EventParams.begin(); it3 != it2->second->EventParams.end(); it3++) + { + std::cout << "\t\t\tEventParams: " << it3->first << " Name: " << it3->second->name << " Type: " << GetEventParamNames(it3->second->type) << std::endl; + for (std::map::iterator it4 = it3->second->ListItems.begin(); it4 != it3->second->ListItems.end(); it4++) + { + std::cout << "\t\t\t\tEventParamsList: " << it4->first << " Name: " << it4->second << std::endl; + } + } } } - } - } + exit(0); #endif + delete pDoc; + } -} - -string NotificationCCTypes::GetEventParamNames -( - NotificationEventParamTypes type -) -{ - switch (type) { - case NEPT_Location: - return "Location"; - break; - case NEPT_List: - return "List"; - break; - case NEPT_UserCodeReport: - return "UserCodeReport"; - break; - case NEPT_Byte: - return "Byte"; - break; - case NEPT_String: - return "String"; - break; - case NEPT_Time: - return "Duration"; - break; - }; - return "Unknown"; -} - -string NotificationCCTypes::GetAlarmType -( - uint32 type -) -{ - if (Notifications.find(type) != Notifications.end()) { - return Notifications.at(type)->name; - } - Log::Write( LogLevel_Warning, "NotificationCCTypes::GetAlarmType - Unknown AlarmType %d", type); - return "Unknown"; -} - -string NotificationCCTypes::GetEventForAlarmType -( - uint32 type, - uint32 event -) -{ - if ( const NotificationCCTypes::NotificationEvents *ne = NotificationCCTypes::GetAlarmNotificationEvents(type, event)) { - return ne->name; - } - Log::Write( LogLevel_Warning, "NotificationCCTypes::GetEventForAlarmType - Unknown AlarmType/Event %d/d", type, event); - return "Unknown"; -} - - + std::string NotificationCCTypes::GetEventParamNames(NotificationEventParamTypes type) + { + switch (type) + { + case NEPT_Location: + return "Location"; + break; + case NEPT_List: + return "List"; + break; + case NEPT_UserCodeReport: + return "UserCodeReport"; + break; + case NEPT_Byte: + return "Byte"; + break; + case NEPT_String: + return "String"; + break; + case NEPT_Time: + return "Duration"; + break; + }; + return "Unknown"; + } -const NotificationCCTypes::NotificationTypes* NotificationCCTypes::GetAlarmNotificationTypes -( - uint32 type -) -{ - if (Notifications.find(type) != Notifications.end()) { - return Notifications.at(type); - } - else - { - Log::Write( LogLevel_Warning, "NotificationCCTypes::GetAlarmNotificationTypes - Unknown Alarm Type %d", type); - } - return NULL; -} + std::string NotificationCCTypes::GetAlarmType(uint32 type) + { + if (Notifications.find(type) != Notifications.end()) + { + return Notifications.at(type)->name; + } + Log::Write(LogLevel_Warning, "NotificationCCTypes::GetAlarmType - Unknown AlarmType %d", type); + return "Unknown"; + } -const NotificationCCTypes::NotificationEvents* NotificationCCTypes::GetAlarmNotificationEvents -( - uint32 type, - uint32 event -) -{ - if (const NotificationCCTypes::NotificationTypes *nt = GetAlarmNotificationTypes(type)) { - if (nt->Events.find(event) != nt->Events.end()) { - return nt->Events.at(event); + std::string NotificationCCTypes::GetEventForAlarmType(uint32 type, uint32 event) + { + if (const std::shared_ptr ne = NotificationCCTypes::GetAlarmNotificationEvents(type, event)) + { + return ne->name; + } + Log::Write(LogLevel_Warning, "NotificationCCTypes::GetEventForAlarmType - Unknown AlarmType/Event %d/d", type, event); + return "Unknown"; } - Log::Write( LogLevel_Warning, "NotificationCCTypes::GetAlarmNotificationEvents - Unknown Alarm Event %d for Alarm Type %s (%d)", event, GetAlarmType(type).c_str(), type); - } - return NULL; -} -const std::map NotificationCCTypes::GetAlarmNotificationEventParams -( - uint32 type, - uint32 event -) -{ - if (const NotificationCCTypes::NotificationTypes *nt = GetAlarmNotificationTypes(type)) { - if (nt->Events.find(event) != nt->Events.end()) { - return nt->Events.at(event)->EventParams; + const std::shared_ptr NotificationCCTypes::GetAlarmNotificationTypes(uint32 type) + { + if (Notifications.find(type) != Notifications.end()) + { + return Notifications.at(type); + } + else + { + Log::Write(LogLevel_Warning, "NotificationCCTypes::GetAlarmNotificationTypes - Unknown Alarm Type %d", type); + } + return NULL; } - Log::Write( LogLevel_Warning, "NotificationCCTypes::GetAlarmNotificationEventParams - Unknown Alarm Event %d for Alarm Type %s (%d)", event, GetAlarmType(type).c_str(), type); - } - return std::map(); -} -bool NotificationCCTypes::Create -( -) -{ - if (m_instance != NULL) - { - return true; - } - m_instance = new NotificationCCTypes(); - ReadXML(); - return true; -} + const std::shared_ptr NotificationCCTypes::GetAlarmNotificationEvents(uint32 type, uint32 event) + { + if (const std::shared_ptr nt = GetAlarmNotificationTypes(type)) + { + if (nt->Events.find(event) != nt->Events.end()) + { + return nt->Events.at(event); + } + Log::Write(LogLevel_Warning, "NotificationCCTypes::GetAlarmNotificationEvents - Unknown Alarm Event %d for Alarm Type %s (%d)", event, GetAlarmType(type).c_str(), type); + } + return NULL; + } + const std::map > NotificationCCTypes::GetAlarmNotificationEventParams(uint32 type, uint32 event) + { + if (const std::shared_ptr nt = GetAlarmNotificationTypes(type)) + { + if (nt->Events.find(event) != nt->Events.end()) + { + return nt->Events.at(event)->EventParams; + } + Log::Write(LogLevel_Warning, "NotificationCCTypes::GetAlarmNotificationEventParams - Unknown Alarm Event %d for Alarm Type %s (%d)", event, GetAlarmType(type).c_str(), type); + } + return std::map >(); + } + bool NotificationCCTypes::Create() + { + if (m_instance != NULL) + { + return true; + } + m_instance = new NotificationCCTypes(); + ReadXML(); + return true; + } -NotificationCCTypes *NotificationCCTypes::Get -( -) -{ - if ( m_instance != NULL ) - { - return m_instance; - } - m_instance = new NotificationCCTypes(); - ReadXML(); - return m_instance; -} + NotificationCCTypes *NotificationCCTypes::Get() + { + if (m_instance != NULL) + { + return m_instance; + } + m_instance = new NotificationCCTypes(); + ReadXML(); + return m_instance; + } + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/NotificationCCTypes.h b/cpp/src/NotificationCCTypes.h index 77c2ea3a7e..5df7874c24 100755 --- a/cpp/src/NotificationCCTypes.h +++ b/cpp/src/NotificationCCTypes.h @@ -37,65 +37,70 @@ namespace OpenZWave { + namespace Internal + { -class NotificationCCTypes -{ -public: - enum NotificationEventParamTypes { - NEPT_Location = 0x01, - NEPT_List, - NEPT_UserCodeReport, - NEPT_Byte, - NEPT_String, - NEPT_Time - }; - - class NotificationEventParams { - public: - uint32 id; - string name; - NotificationEventParamTypes type; - std::map ListItems; - }; - class NotificationEvents { - public: - uint32 id; - string name; - std::map EventParams; - }; - class NotificationTypes { - public: - uint32 id; - string name; - std::map Events; - }; - + class NotificationCCTypes + { + public: + enum NotificationEventParamTypes + { + NEPT_Location = 0x01, + NEPT_List, + NEPT_UserCodeReport, + NEPT_Byte, + NEPT_String, + NEPT_Time + }; - //----------------------------------------------------------------------------- - // Construction - //----------------------------------------------------------------------------- -private: - NotificationCCTypes(); - ~NotificationCCTypes(); - static void ReadXML(); -public: - static NotificationCCTypes* Get(); - static bool Create(); - static string GetEventParamNames(NotificationEventParamTypes); - string GetAlarmType(uint32); - string GetEventForAlarmType(uint32, uint32); - const NotificationTypes *GetAlarmNotificationTypes(uint32); - const NotificationEvents *GetAlarmNotificationEvents(uint32, uint32); - const std::map GetAlarmNotificationEventParams(uint32, uint32); + class NotificationEventParams + { + public: + uint32 id; + string name; + NotificationEventParamTypes type; + std::map ListItems; + }; + class NotificationEvents + { + public: + uint32 id; + string name; + std::map > EventParams; + }; + class NotificationTypes + { + public: + uint32 id; + string name; + std::map > Events; + }; - //----------------------------------------------------------------------------- - // Instance Functions - //----------------------------------------------------------------------------- -private: - static NotificationCCTypes* m_instance; - static std::map Notifications; - static uint32 m_revision; -}; + //----------------------------------------------------------------------------- + // Construction + //----------------------------------------------------------------------------- + private: + NotificationCCTypes(); + ~NotificationCCTypes(); + static void ReadXML(); + public: + static NotificationCCTypes* Get(); + static bool Create(); + static string GetEventParamNames(NotificationEventParamTypes); + string GetAlarmType(uint32); + string GetEventForAlarmType(uint32, uint32); + const std::shared_ptr GetAlarmNotificationTypes(uint32); + const std::shared_ptr GetAlarmNotificationEvents(uint32, uint32); + const std::map> GetAlarmNotificationEventParams(uint32, uint32); -}; -#endif // VALUEHELP_H + //----------------------------------------------------------------------------- + // Instance Functions + //----------------------------------------------------------------------------- + private: + static NotificationCCTypes* m_instance; + static std::map > Notifications; + static uint32 m_revision; + }; + } // namespace Internal +} // namespace OpenZWave +#endif // NOTIFICATIONCCTYPES_H diff --git a/cpp/src/OZWException.h b/cpp/src/OZWException.h index 94b994d736..42a51142d3 100644 --- a/cpp/src/OZWException.h +++ b/cpp/src/OZWException.h @@ -33,95 +33,96 @@ #include #include - - namespace OpenZWave { - /** \brief Exception Handling Interface. - * - * This class is for exporting errors etc when using the OpenZWave API. It can report incorrect API usage - * (such as passing incorrect ValueID's to the Manager::SetValue methods) or - */ +/** \brief Exception Handling Interface. + * + * This class is for exporting errors etc when using the OpenZWave API. It can report incorrect API usage + * (such as passing incorrect ValueID's to the Manager::SetValue methods) or + */ -OPENZWAVE_EXPORT_WARNINGS_OFF - class OPENZWAVE_EXPORT OZWException : public std::runtime_error +class OPENZWAVE_EXPORT OZWException : public std::runtime_error +{ + public: + enum ExceptionType { - public: - enum ExceptionType { - OZWEXCEPTION_OPTIONS, - OZWEXCEPTION_CONFIG, - OZWEXCEPTION_INVALID_HOMEID = 100, - OZWEXCEPTION_INVALID_VALUEID, - OZWEXCEPTION_CANNOT_CONVERT_VALUEID, - OZWEXCEPTION_SECURITY_FAILED, - OZWEXCEPTION_INVALID_NODEID - }; - - //----------------------------------------------------------------------------- - // Construction - //----------------------------------------------------------------------------- - OZWException(std::string file, int line, ExceptionType exitCode, std::string msg) : - std::runtime_error(OZWException::GetExceptionText(file, line, exitCode, msg)), - m_exitCode(exitCode), - m_file(file), - m_line(line), - m_msg(msg) - { - } + OZWEXCEPTION_OPTIONS, + OZWEXCEPTION_CONFIG, + OZWEXCEPTION_INVALID_HOMEID = 100, + OZWEXCEPTION_INVALID_VALUEID, + OZWEXCEPTION_CANNOT_CONVERT_VALUEID, + OZWEXCEPTION_SECURITY_FAILED, + OZWEXCEPTION_INVALID_NODEID + }; - ~OZWException() throw() - { - } + //----------------------------------------------------------------------------- + // Construction + //----------------------------------------------------------------------------- + OZWException(std::string file, int line, ExceptionType exitCode, std::string msg) : + std::runtime_error(OZWException::GetExceptionText(file, line, exitCode, msg)), + m_exitCode(exitCode), + m_file(file), + m_line(line), + m_msg(msg) + { + } - //----------------------------------------------------------------------------- - // Accessor methods - //----------------------------------------------------------------------------- - ExceptionType GetType() { return m_exitCode; } - std::string GetFile() { return m_file; } - uint32 GetLine() { return m_line; } - std::string GetMsg() { return m_msg; } + ~OZWException() throw() + { + } + //----------------------------------------------------------------------------- + // Accessor methods + //----------------------------------------------------------------------------- + ExceptionType GetType() + { return m_exitCode;} + std::string GetFile() + { return m_file;} + uint32 GetLine() + { return m_line;} + std::string GetMsg() + { return m_msg;} - private: - static std::string GetExceptionText(std::string file, int line, ExceptionType exitCode, std::string msg) - { - std::stringstream ss; - ss << file.substr(file.find_last_of("/\\") + 1) << ":" << line; - switch (exitCode) { - case OZWEXCEPTION_OPTIONS: - ss << " - OptionsError (" << exitCode << ") Msg: " << msg; - break; - case OZWEXCEPTION_CONFIG: - ss << " - ConfigError (" << exitCode << ") Msg: " << msg; - break; - case OZWEXCEPTION_INVALID_HOMEID: - ss << " - InvalidHomeIDError (" << exitCode << ") Msg: " << msg; - break; - case OZWEXCEPTION_INVALID_VALUEID: - ss << " - InvalidValueIDError (" << exitCode << ") Msg: " << msg; - break; - case OZWEXCEPTION_CANNOT_CONVERT_VALUEID: - ss << " - CannotConvertValueIDError (" << exitCode << ") Msg: " << msg; - break; - case OZWEXCEPTION_SECURITY_FAILED: - ss << " - Security Initialization Failed (" << exitCode << ") Msg: " << msg; - break; - case OZWEXCEPTION_INVALID_NODEID: - ss << " - InvalidNodeIDError (" << exitCode << ") Msg: " << msg; - break; - } - return ss.str(); - } + private: + static std::string GetExceptionText(std::string file, int line, ExceptionType exitCode, std::string msg) + { + std::stringstream ss; + ss << file.substr(file.find_last_of("/\\") + 1) << ":" << line; + switch (exitCode) + { + case OZWEXCEPTION_OPTIONS: + ss << " - OptionsError (" << exitCode << ") Msg: " << msg; + break; + case OZWEXCEPTION_CONFIG: + ss << " - ConfigError (" << exitCode << ") Msg: " << msg; + break; + case OZWEXCEPTION_INVALID_HOMEID: + ss << " - InvalidHomeIDError (" << exitCode << ") Msg: " << msg; + break; + case OZWEXCEPTION_INVALID_VALUEID: + ss << " - InvalidValueIDError (" << exitCode << ") Msg: " << msg; + break; + case OZWEXCEPTION_CANNOT_CONVERT_VALUEID: + ss << " - CannotConvertValueIDError (" << exitCode << ") Msg: " << msg; + break; + case OZWEXCEPTION_SECURITY_FAILED: + ss << " - Security Initialization Failed (" << exitCode << ") Msg: " << msg; + break; + case OZWEXCEPTION_INVALID_NODEID: + ss << " - InvalidNodeIDError (" << exitCode << ") Msg: " << msg; + break; + } + return ss.str(); + } - //----------------------------------------------------------------------------- - // Member variables - //----------------------------------------------------------------------------- - ExceptionType m_exitCode; - std::string m_file; - uint32 m_line; - std::string m_msg; - }; -OPENZWAVE_EXPORT_WARNINGS_ON + //----------------------------------------------------------------------------- + // Member variables + //----------------------------------------------------------------------------- + ExceptionType m_exitCode; + std::string m_file; + uint32 m_line; + std::string m_msg; +}; } #endif // _FatalErrorException_H diff --git a/cpp/src/Options.cpp b/cpp/src/Options.cpp index f42421acde..9137f0e7cc 100644 --- a/cpp/src/Options.cpp +++ b/cpp/src/Options.cpp @@ -44,97 +44,96 @@ Options* Options::s_instance = NULL; // // Static method to create an Options object //----------------------------------------------------------------------------- -Options* Options::Create -( - string const& _configPath, - string const& _userPath, - string const& _commandLine -) +Options* Options::Create(string const& _configPath, string const& _userPath, string const& _commandLine) { - if( s_instance == NULL ) + if (s_instance == NULL) { string configPath = _configPath; string userPath = _userPath; // Make sure a trailing path delimiter is present - if( configPath.size() > 0 && configPath[configPath.size() - 1] != '/' ) + if (configPath.size() > 0 && configPath[configPath.size() - 1] != '/') { configPath += "/"; } - if( userPath.size() > 0 && userPath[userPath.size() - 1] != '/' ) + if (userPath.size() > 0 && userPath[userPath.size() - 1] != '/') { userPath += "/"; } - FileOps::Create(); - if( !FileOps::FolderExists( configPath ) ) + Internal::Platform::FileOps::Create(); + if (!Internal::Platform::FileOps::FolderExists(configPath)) { - Log::Create( "", false, true, LogLevel_Debug, LogLevel_Debug, LogLevel_None ); + Log::Create("", false, true, LogLevel_Debug, LogLevel_Debug, LogLevel_None); /* Try some default directories */ - if ( FileOps::FolderExists( "config/" ) ) + if (Internal::Platform::FileOps::FolderExists("config/")) { - Log::Write( LogLevel_Error, "Cannot find a path to the configuration files at %s, Using config/ instead...", configPath.c_str() ); + Log::Write(LogLevel_Error, "Cannot find a path to the configuration files at %s, Using config/ instead...", configPath.c_str()); configPath = "config/"; - } else if (FileOps::FolderExists("/etc/openzwave/" ) ) + } + else if (Internal::Platform::FileOps::FolderExists("/etc/openzwave/")) { - Log::Write( LogLevel_Error, "Cannot find a path to the configuration files at %s, Using /etc/openzwave/ instead...", configPath.c_str() ); + Log::Write(LogLevel_Error, "Cannot find a path to the configuration files at %s, Using /etc/openzwave/ instead...", configPath.c_str()); configPath = "/etc/openzwave/"; #ifdef SYSCONFDIR - } else if ( FileOps::FolderExists(SYSCONFDIR ) ) + } + else if ( Internal::Platform::FileOps::FolderExists(SYSCONFDIR ) ) { Log::Write( LogLevel_Error, "Cannot find a path to the configuration files at %s, Using %s instead...", configPath.c_str(), SYSCONFDIR); configPath = SYSCONFDIR; #endif - } else { - Log::Write( LogLevel_Error, "Cannot find a path to the configuration files at %s. Exiting...", configPath.c_str() ); + } + else + { + Log::Write(LogLevel_Error, "Cannot find a path to the configuration files at %s. Exiting...", configPath.c_str()); OZW_FATAL_ERROR(OZWException::OZWEXCEPTION_CONFIG, "Cannot Find Configuration Files"); return NULL; } } - FileOps::Destroy(); - s_instance = new Options( configPath, userPath, _commandLine ); + Internal::Platform::FileOps::Destroy(); + s_instance = new Options(configPath, userPath, _commandLine); // Add the default options - s_instance->AddOptionString( "ConfigPath", configPath, false ); // Path to the OpenZWave config folder. - s_instance->AddOptionString( "UserPath", userPath, false ); // Path to the user's data folder. - - s_instance->AddOptionBool( "Logging", true ); // Enable logging of library activity. - s_instance->AddOptionString( "LogFileName", "OZW_Log.txt", false ); // Name of the log file (can be changed via Log::SetLogFileName) - s_instance->AddOptionBool( "AppendLogFile", false ); // Append new session logs to existing log file (false = overwrite) - s_instance->AddOptionBool( "ConsoleOutput", true ); // Display log information on console (as well as save to disk) - s_instance->AddOptionInt( "SaveLogLevel", LogLevel_Detail ); // Save (to file) log messages equal to or above LogLevel_Detail - s_instance->AddOptionInt( "QueueLogLevel", LogLevel_Debug ); // Save (in RAM) log messages equal to or above LogLevel_Debug - s_instance->AddOptionInt( "DumpTriggerLevel", LogLevel_None ); // Default is to never dump RAM-stored log messages - - s_instance->AddOptionBool( "Associate", true ); // Enable automatic association of the controller with group one of every device. - s_instance->AddOptionString( "Exclude", string(""), true ); // Remove support for the listed command classes. - s_instance->AddOptionString( "Include", string(""), true ); // Only handle the specified command classes. The Exclude option is ignored if anything is listed here. - s_instance->AddOptionBool( "NotifyTransactions", false ); // Notifications when transaction complete is reported. - s_instance->AddOptionString( "Interface", string(""), true ); // Identify the serial port to be accessed (TODO: change the code so more than one serial port can be specified and HID) - s_instance->AddOptionBool( "SaveConfiguration", true ); // Save the XML configuration upon driver close. - s_instance->AddOptionInt( "DriverMaxAttempts", 0); - - s_instance->AddOptionInt( "PollInterval", 30000); // 30 seconds (can easily poll 30 values in this time; ~120 values is the effective limit for 30 seconds) - s_instance->AddOptionBool( "IntervalBetweenPolls", false ); // if false, try to execute the entire poll list within the PollInterval time frame - // if true, wait for PollInterval milliseconds between polls - s_instance->AddOptionBool( "SuppressValueRefresh", false ); // if true, notifications for refreshed (but unchanged) values will not be sent - s_instance->AddOptionBool( "PerformReturnRoutes", false ); // if true, return routes will be updated - s_instance->AddOptionString( "NetworkKey", string(""), false); - s_instance->AddOptionBool( "RefreshAllUserCodes", false ); // if true, during startup, we refresh all the UserCodes the device reports it supports. If False, we stop after we get the first "Available" slot (Some devices have 250+ usercode slots! - That makes our Session Stage Very Long ) - s_instance->AddOptionInt( "RetryTimeout", RETRY_TIMEOUT); // How long do we wait to timeout messages sent - s_instance->AddOptionBool( "EnableSIS", true); // Automatically become a SUC if there is no SUC on the network. - s_instance->AddOptionBool( "AssumeAwake", true); // Assume Devices that Support the Wakeup CC are awake when we first query them.... - s_instance->AddOptionBool( "NotifyOnDriverUnload", false); // Should we send the Node/Value Notifications on Driver Unloading - Read comments in Driver::~Driver() method about possible race conditions - s_instance->AddOptionString( "SecurityStrategy", "SUPPORTED", false); // Should we encrypt CC's that are available via both clear text and Security CC? - s_instance->AddOptionString( "CustomSecuredCC", "0x62,0x4c,0x63", false); // What List of Custom CC should we always encrypt if SecurityStrategy is CUSTOM - s_instance->AddOptionBool( "EnforceSecureReception", true); // if we recieve a clear text message for a CC that is Secured, should we drop the message - s_instance->AddOptionBool( "AutoUpdateConfigFile", true); // if we should automatically update config files for devices if they are out of date - s_instance->AddOptionString( "ReloadAfterUpdate", "AWAKE", false); // Should we automatically Reload Nodes after a update - s_instance->AddOptionString( "Language", "", false); // Language we should use - s_instance->AddOptionBool( "IncludeInstanceLabel", true); // Should we include the Instance Label in Value Labels on MultiInstance Devices + s_instance->AddOptionString("ConfigPath", configPath, false); // Path to the OpenZWave config folder. + s_instance->AddOptionString("UserPath", userPath, false); // Path to the user's data folder. + + s_instance->AddOptionBool("Logging", true); // Enable logging of library activity. + s_instance->AddOptionString("LogFileName", "OZW_Log.txt", false); // Name of the log file (can be changed via Log::SetLogFileName) + s_instance->AddOptionBool("AppendLogFile", false); // Append new session logs to existing log file (false = overwrite) + s_instance->AddOptionBool("ConsoleOutput", true); // Display log information on console (as well as save to disk) + s_instance->AddOptionInt("SaveLogLevel", LogLevel_Detail); // Save (to file) log messages equal to or above LogLevel_Detail + s_instance->AddOptionInt("QueueLogLevel", LogLevel_Debug); // Save (in RAM) log messages equal to or above LogLevel_Debug + s_instance->AddOptionInt("DumpTriggerLevel", LogLevel_None); // Default is to never dump RAM-stored log messages + + s_instance->AddOptionBool("Associate", true); // Enable automatic association of the controller with group one of every device. + s_instance->AddOptionString("Exclude", string(""), true); // Remove support for the listed command classes. + s_instance->AddOptionString("Include", string(""), true); // Only handle the specified command classes. The Exclude option is ignored if anything is listed here. + s_instance->AddOptionBool("NotifyTransactions", false); // Notifications when transaction complete is reported. + s_instance->AddOptionString("Interface", string(""), true); // Identify the serial port to be accessed (TODO: change the code so more than one serial port can be specified and HID) + s_instance->AddOptionBool("SaveConfiguration", true); // Save the XML configuration upon driver close. + s_instance->AddOptionInt("DriverMaxAttempts", 0); + + s_instance->AddOptionInt("PollInterval", 30000); // 30 seconds (can easily poll 30 values in this time; ~120 values is the effective limit for 30 seconds) + s_instance->AddOptionBool("IntervalBetweenPolls", false); // if false, try to execute the entire poll list within the PollInterval time frame + // if true, wait for PollInterval milliseconds between polls + s_instance->AddOptionBool("SuppressValueRefresh", false); // if true, notifications for refreshed (but unchanged) values will not be sent + s_instance->AddOptionBool("PerformReturnRoutes", false); // if true, return routes will be updated + s_instance->AddOptionString("NetworkKey", string(""), false); + s_instance->AddOptionBool("RefreshAllUserCodes", false); // if true, during startup, we refresh all the UserCodes the device reports it supports. If False, we stop after we get the first "Available" slot (Some devices have 250+ usercode slots! - That makes our Session Stage Very Long ) + s_instance->AddOptionInt("RetryTimeout", RETRY_TIMEOUT); // How long do we wait to timeout messages sent + s_instance->AddOptionBool("EnableSIS", true); // Automatically become a SUC if there is no SUC on the network. + s_instance->AddOptionBool("AssumeAwake", true); // Assume Devices that Support the Wakeup CC are awake when we first query them.... + s_instance->AddOptionBool("NotifyOnDriverUnload", false); // Should we send the Node/Value Notifications on Driver Unloading - Read comments in Driver::~Driver() method about possible race conditions + s_instance->AddOptionString("SecurityStrategy", "SUPPORTED", false); // Should we encrypt CC's that are available via both clear text and Security CC? + s_instance->AddOptionString("CustomSecuredCC", "0x62,0x4c,0x63", false); // What List of Custom CC should we always encrypt if SecurityStrategy is CUSTOM + s_instance->AddOptionBool("EnforceSecureReception", true); // if we recieve a clear text message for a CC that is Secured, should we drop the message + s_instance->AddOptionBool("AutoUpdateConfigFile", true); // if we should automatically update config files for devices if they are out of date + s_instance->AddOptionString("ReloadAfterUpdate", "AWAKE", false); // Should we automatically Reload Nodes after a update + s_instance->AddOptionString("Language", "", false); // Language we should use + s_instance->AddOptionBool("IncludeInstanceLabel", true); // Should we include the Instance Label in Value Labels on MultiInstance Devices #if defined WINRT - s_instance->AddOptionInt( "ThreadTerminateTimeout", -1); // Since threads cannot be terminated in WinRT, Thread::Terminate will simply wait for them to exit on there own + s_instance->AddOptionInt( "ThreadTerminateTimeout", -1); // Since threads cannot be terminated in WinRT, Thread::Terminate will simply wait for them to exit on there own #endif } @@ -145,11 +144,9 @@ Options* Options::Create // // Static method to destroy an Options object //----------------------------------------------------------------------------- -bool Options::Destroy -( -) +bool Options::Destroy() { - if( Manager::Get() ) + if (Manager::Get()) { // Cannot delete Options because Manager object still exists OZW_ERROR(OZWException::OZWEXCEPTION_OPTIONS, "Cannot Delete Options Class as Manager Class is still around"); @@ -162,21 +159,22 @@ bool Options::Destroy return true; } +//----------------------------------------------------------------------------- +// +// Static method to Get an Options object +//----------------------------------------------------------------------------- + +Options* Options::Get() +{ + return s_instance; +} + //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -Options::Options -( - string const& _configPath, - string const& _userPath, - string const& _commandLine -): - m_xml ("options.xml"), - m_commandLine( _commandLine ), - m_SystemPath (_configPath), - m_LocalPath (_userPath), - m_locked( false ) +Options::Options(string const& _configPath, string const& _userPath, string const& _commandLine) : + m_xml("options.xml"), m_commandLine(_commandLine), m_SystemPath(_configPath), m_LocalPath(_userPath), m_locked(false) { } @@ -184,16 +182,14 @@ Options::Options // // Destructor //----------------------------------------------------------------------------- -Options::~Options -( -) +Options::~Options() { // Clear the options map - while( !m_options.empty() ) + while (!m_options.empty()) { - map::iterator it = m_options.begin(); + map::iterator it = m_options.begin(); delete it->second; - m_options.erase( it ); + m_options.erase(it); } } @@ -201,23 +197,20 @@ Options::~Options // // Add a boolean option. //----------------------------------------------------------------------------- -bool Options::AddOptionBool -( - string const& _name, - bool const _value -) +bool Options::AddOptionBool(string const& _name, bool const _value) { // get (or create) option - Option* option = AddOption( _name ); + Option* option = AddOption(_name); - if (option == NULL) return false; + if (option == NULL) + return false; // set unique option members option->m_type = Options::OptionType_Bool; option->m_valueBool = _value; // save in m_options map - string lowerName = ToLower( _name ); + string lowerName = Internal::ToLower(_name); m_options[lowerName] = option; return true; } @@ -226,23 +219,20 @@ bool Options::AddOptionBool // // Add an integer option. //----------------------------------------------------------------------------- -bool Options::AddOptionInt -( - string const& _name, - int32 const _value -) +bool Options::AddOptionInt(string const& _name, int32 const _value) { // get (or create) option - Option* option = AddOption( _name ); + Option* option = AddOption(_name); - if (option == NULL) return false; + if (option == NULL) + return false; // set unique option members option->m_type = Options::OptionType_Int; option->m_valueInt = _value; // save in m_options map - string lowerName = ToLower( _name ); + string lowerName = Internal::ToLower(_name); m_options[lowerName] = option; return true; } @@ -251,17 +241,13 @@ bool Options::AddOptionInt // // Add a string option. //----------------------------------------------------------------------------- -bool Options::AddOptionString -( - string const& _name, - string const& _value, - bool const _append -) +bool Options::AddOptionString(string const& _name, string const& _value, bool const _append) { // get (or create) option - Option* option = AddOption( _name ); + Option* option = AddOption(_name); - if (option == NULL) return false; + if (option == NULL) + return false; // set unique option members option->m_type = Options::OptionType_String; @@ -269,7 +255,7 @@ bool Options::AddOptionString option->m_append = _append; // save in m_options map - string lowerName = ToLower( _name ); + string lowerName = Internal::ToLower(_name); m_options[lowerName] = option; return true; } @@ -278,20 +264,16 @@ bool Options::AddOptionString // // Get the value of a boolean option. //----------------------------------------------------------------------------- -bool Options::GetOptionAsBool -( - string const& _name, - bool* o_value -) +bool Options::GetOptionAsBool(string const& _name, bool* o_value) { - Option* option = Find( _name ); - if( o_value && option && ( OptionType_Bool == option->m_type ) ) + Option* option = Find(_name); + if (o_value && option && (OptionType_Bool == option->m_type)) { *o_value = option->m_valueBool; return true; } - Log::Write( LogLevel_Warning, "Specified option [%s] was not found.", _name.c_str() ); + Log::Write(LogLevel_Warning, "Specified option [%s] was not found.", _name.c_str()); return false; } @@ -299,20 +281,16 @@ bool Options::GetOptionAsBool // // Get the value of an integer option. //----------------------------------------------------------------------------- -bool Options::GetOptionAsInt -( - string const& _name, - int32* o_value -) +bool Options::GetOptionAsInt(string const& _name, int32* o_value) { - Option* option = Find( _name ); - if( o_value && option && ( OptionType_Int == option->m_type ) ) + Option* option = Find(_name); + if (o_value && option && (OptionType_Int == option->m_type)) { *o_value = option->m_valueInt; return true; } - Log::Write( LogLevel_Warning, "Specified option [%s] was not found.", _name.c_str() ); + Log::Write(LogLevel_Warning, "Specified option [%s] was not found.", _name.c_str()); return false; } @@ -320,20 +298,16 @@ bool Options::GetOptionAsInt // // Get the value of a string option. //----------------------------------------------------------------------------- -bool Options::GetOptionAsString -( - string const& _name, - string* o_value -) +bool Options::GetOptionAsString(string const& _name, string* o_value) { - Option* option = Find( _name ); - if( o_value && option && ( OptionType_String == option->m_type ) ) + Option* option = Find(_name); + if (o_value && option && (OptionType_String == option->m_type)) { *o_value = option->m_valueString; return true; } - Log::Write( LogLevel_Warning, "Specified option [%s] was not found.", _name.c_str() ); + Log::Write(LogLevel_Warning, "Specified option [%s] was not found.", _name.c_str()); return false; } @@ -341,19 +315,16 @@ bool Options::GetOptionAsString // // Get the type of value stored in an option. //----------------------------------------------------------------------------- -Options::OptionType Options::GetOptionType -( - string const& _name -) +Options::OptionType Options::GetOptionType(string const& _name) { - Option* option = Find( _name ); - if( option ) + Option* option = Find(_name); + if (option) { return option->m_type; } // Option not found - Log::Write( LogLevel_Warning, "Specified option [%s] was not found.", _name.c_str() ); + Log::Write(LogLevel_Warning, "Specified option [%s] was not found.", _name.c_str()); return OptionType_Invalid; } @@ -361,41 +332,41 @@ Options::OptionType Options::GetOptionType // // Read all the option XMLs and Command Lines, and lock their values. //----------------------------------------------------------------------------- -bool Options::Lock -( -) +bool Options::Lock() { - if( m_locked ) + if (m_locked) { - Log::Write( LogLevel_Error, "Options are already final (locked)." ); + Log::Write(LogLevel_Error, "Options are already final (locked)."); return false; } - ParseOptionsXML( m_SystemPath + m_xml ); - ParseOptionsXML( m_LocalPath + m_xml); - ParseOptionsString( m_commandLine ); + ParseOptionsXML(m_SystemPath + m_xml); + ParseOptionsXML(m_LocalPath + m_xml); + ParseOptionsString(m_commandLine); m_locked = true; /* Log our Configured Options */ - map::iterator it; - Log::Write( LogLevel_Info, "Options:"); - for (it = m_options.begin(); it != m_options.end(); it++) { + map::iterator it; + Log::Write(LogLevel_Info, "Options:"); + for (it = m_options.begin(); it != m_options.end(); it++) + { Option *opt = it->second; - switch (opt->m_type) { + switch (opt->m_type) + { case OptionType_Bool: - Log::Write( LogLevel_Info, "\t%s: %s", it->first.c_str(), opt->m_valueBool == true ? "true" : "false"); + Log::Write(LogLevel_Info, "\t%s: %s", it->first.c_str(), opt->m_valueBool == true ? "true" : "false"); break; case OptionType_Int: - Log::Write( LogLevel_Info, "\t%s: %d", it->first.c_str(), opt->m_valueInt); + Log::Write(LogLevel_Info, "\t%s: %d", it->first.c_str(), opt->m_valueInt); break; case OptionType_String: - Log::Write( LogLevel_Info, "\t%s: %s", it->first.c_str(), opt->m_valueString.c_str()); + Log::Write(LogLevel_Info, "\t%s: %s", it->first.c_str(), opt->m_valueString.c_str()); break; case OptionType_Invalid: - Log::Write( LogLevel_Info, "\t%s: Invalid Type"); + Log::Write(LogLevel_Info, "\t%s: Invalid Type"); break; } - } + } return true; } @@ -403,20 +374,17 @@ bool Options::Lock // // Parse a string containing program options, such as a command line //----------------------------------------------------------------------------- -bool Options::ParseOptionsString -( - string const& _commandLine -) +bool Options::ParseOptionsString(string const& _commandLine) { bool res = true; size_t pos = 0; size_t start = 0; - while( 1 ) + while (1) { // find start of first option name - pos = _commandLine.find_first_of( "--", start ); - if( string::npos == pos ) + pos = _commandLine.find_first_of("--", start); + if (string::npos == pos) { break; } @@ -424,51 +392,51 @@ bool Options::ParseOptionsString // found an option. Get the name. string optionName; - pos = _commandLine.find( " ", start ); - if( string::npos == pos ) + pos = _commandLine.find(" ", start); + if (string::npos == pos) { - optionName = _commandLine.substr( start ); + optionName = _commandLine.substr(start); start = pos; } else { - optionName = _commandLine.substr( start, pos-start ); + optionName = _commandLine.substr(start, pos - start); start = pos + 1; } // Find the matching option object - Option* option = Find( optionName ); - if( option ) + Option* option = Find(optionName); + if (option) { // Read the values int numValues = 0; bool parsing = true; - while( parsing ) + while (parsing) { string value; size_t back = start; - pos = _commandLine.find( " ", start ); - if( string::npos == pos ) + pos = _commandLine.find(" ", start); + if (string::npos == pos) { // Last value in string - value = _commandLine.substr( start ); + value = _commandLine.substr(start); parsing = false; start = pos; } else { - value = _commandLine.substr( start, pos-start ); - start = pos+1; + value = _commandLine.substr(start, pos - start); + start = pos + 1; } - if( !value.compare( 0, 2, "--" ) ) + if (!value.compare(0, 2, "--")) { // Value is actually the next option. - if( !numValues ) + if (!numValues) { // No values were read for this option // This is ok only for bool options, where we assume no value means "true". - if( OptionType_Bool == option->m_type ) + if (OptionType_Bool == option->m_type) { option->m_valueBool = true; } @@ -480,10 +448,10 @@ bool Options::ParseOptionsString start = back; // back up to the beginning of the next option break; } - else if( value.size() > 0 ) + else if (value.size() > 0) { // Set the value - option->SetValueFromString( value ); + option->SetValueFromString(value); numValues++; } } @@ -497,40 +465,37 @@ bool Options::ParseOptionsString // // Parse an XML file containing program options //----------------------------------------------------------------------------- -bool Options::ParseOptionsXML -( - string const& _filename -) +bool Options::ParseOptionsXML(string const& _filename) { TiXmlDocument doc; - if( !doc.LoadFile( _filename.c_str(), TIXML_ENCODING_UTF8 ) ) + if (!doc.LoadFile(_filename.c_str(), TIXML_ENCODING_UTF8)) { Log::Write(LogLevel_Warning, "Failed to Parse %s: %s", _filename.c_str(), doc.ErrorDesc()); return false; } - doc.SetUserData((void *)_filename.c_str()); + doc.SetUserData((void *) _filename.c_str()); Log::Write(LogLevel_Info, "Reading %s for Options", _filename.c_str()); TiXmlElement const* optionsElement = doc.RootElement(); // Read the options TiXmlElement const* optionElement = optionsElement->FirstChildElement(); - while( optionElement ) + while (optionElement) { char const* str = optionElement->Value(); - if( str && !strcmp( str, "Option" ) ) + if (str && !strcmp(str, "Option")) { - char const* name = optionElement->Attribute( "name" ); - if( name ) + char const* name = optionElement->Attribute("name"); + if (name) { - Option* option = Find( name ); - if( option ) + Option* option = Find(name); + if (option) { - char const* value = optionElement->Attribute( "value" ); - if( value ) + char const* value = optionElement->Attribute("value"); + if (value) { // Set the value - option->SetValueFromString( value ); + option->SetValueFromString(value); } } } @@ -546,22 +511,19 @@ bool Options::ParseOptionsXML // // General setup for adding a specific option //----------------------------------------------------------------------------- -Options::Option* Options::AddOption -( - string const& _name -) +Options::Option* Options::AddOption(string const& _name) { - if( m_locked ) + if (m_locked) { - Log::Write( LogLevel_Error, "Options have been locked. No more may be added." ); + Log::Write(LogLevel_Error, "Options have been locked. No more may be added."); return NULL; } // get a pointer to the option (and create a new Option if it doesn't already exist) - Option* option = Find( _name ); - if( option == NULL ) + Option* option = Find(_name); + if (option == NULL) { - option = new Option( _name ); + option = new Option(_name); } return option; @@ -571,14 +533,11 @@ Options::Option* Options::AddOption // // Find an option by name //----------------------------------------------------------------------------- -Options::Option* Options::Find -( - string const& _name -) +Options::Option* Options::Find(string const& _name) { - string lowername = ToLower( _name ); - map::iterator it = m_options.find( lowername ); - if( it != m_options.end() ) + string lowername = Internal::ToLower(_name); + map::iterator it = m_options.find(lowername); + if (it != m_options.end()) { return it->second; } @@ -590,21 +549,18 @@ Options::Option* Options::Find // // Find an option by name //----------------------------------------------------------------------------- -bool Options::Option::SetValueFromString -( - string const& _value -) +bool Options::Option::SetValueFromString(string const& _value) { - if( OptionType_Bool == m_type ) + if (OptionType_Bool == m_type) { - string lowerValue = ToLower( _value ); - if( ( lowerValue == "true" ) || ( lowerValue == "1" ) ) + string lowerValue = Internal::ToLower(_value); + if ((lowerValue == "true") || (lowerValue == "1")) { m_valueBool = true; return true; } - if( ( lowerValue == "false" ) || ( lowerValue == "0" ) ) + if ((lowerValue == "false") || (lowerValue == "0")) { m_valueBool = false; return true; @@ -613,17 +569,17 @@ bool Options::Option::SetValueFromString return false; } - if( OptionType_Int == m_type ) + if (OptionType_Int == m_type) { - m_valueInt = (int32)atol( _value.c_str() ); + m_valueInt = (int32) atol(_value.c_str()); return true; } - if( OptionType_String == m_type ) + if (OptionType_String == m_type) { - if( m_append && ( m_valueString.size() > 0 ) ) + if (m_append && (m_valueString.size() > 0)) { - m_valueString += ( string(",") + _value ); + m_valueString += (string(",") + _value); } else { diff --git a/cpp/src/Options.h b/cpp/src/Options.h index ffa02e6851..4ceae15fdf 100644 --- a/cpp/src/Options.h +++ b/cpp/src/Options.h @@ -65,189 +65,192 @@ namespace OpenZWave */ class OPENZWAVE_EXPORT Options { - public: - enum OptionType - { - OptionType_Invalid = 0, - OptionType_Bool, - OptionType_Int, - OptionType_String - }; - - /** - * Creates an object to manage the program options. - * \param _configPath a string containing the path to the OpenZWave library config - * folder, which contains XML descriptions of Z-Wave manufacturers and products. - * \param _userPath a string containing the path to the application's user data - * folder where the OpenZWave should store the Z-Wave network configuration and state. - * The _userPath is also the folder where OpenZWave will look for the file Options.xml - * which contains program option values. The file should be in the form outlined below, - * with one or more Option elements containing a name and value attribute. Multiple - * values with the same option name should be listed separately. Note that option names - * are case insensitive. - * \code - * - * - * - * \endcode - * \param _commandLine a string containing the program's command line options. - * Command line options are parsed after the options.xml file, and so take precedence. - * Options are identified by a leading -- (two minus signs). The following items - * in the string are treated as values for this option, until the next -- is - * reached. For boolean options only, it is possible to omit the value, in which case - * the value is assumed to be "true". Note that option names are case insensitive, and - * that option values should be separated by a space. - * \return Pointer to the newly created Options object. - * \see Get, Destroy, AddOption, GetOptionAs, Lock - */ - static Options* Create( string const& _configPath, string const& _userPath, string const& _commandLine ); - - /** - * Deletes the Options and cleans up any associated objects. - * The application is responsible for destroying the Options object, - * but this must not be done until after the Manager object has been - * destroyed. - * \param _options Pointer to the Options object to be destroyed. - * \return true if the Options object was destroyed. If the manager - * object still exists, this call will return false. - * \see Create, Get - */ - static bool Destroy(); - - /** - * Gets a pointer to the Options singleton object. - * \return a pointer to the Options singleton object. - * \see Create, Destroy - */ - static Options* Get(){ return s_instance; } - - /** - * Locks the options. - * Reads in option values from the XML options file and command line string and - * marks the options as locked. Once locked, no more calls to AddOption - * can be made. - * The options must be locked before the Manager::Create method is called. - * \see AddOption - */ - bool Lock(); - - /** - * Add a boolean option to the program. - * Adds an option to the program whose value can then be read from a file or command line. - * All calls to AddOptionInt must be made before Lock. - * \param _name the name of the option. Option names are case insensitive and must be unique. - * \param _default the default value for this option. - * \see GetOptionAsBool - */ - bool AddOptionBool( string const& _name, bool const _default ); - - /** - * Add an integer option to the program. - * Adds an option to the program whose value can then be read from a file or command line. - * All calls to AddOptionInt must be made before Lock. - * \param _name the name of the option. Option names are case insensitive and must be unique. - * \param _default the default value for this option. - * \see GetOptionAsInt - */ - bool AddOptionInt( string const& _name, int32 const _default ); - - /** - * Add a string option to the program. - * Adds an option to the program whose value can then be read from a file or command line. - * All calls to AddOptionString must be made before Lock. - * \param _name the name of the option. Option names are case insensitive and must be unique. - * \param _default the default value for this option. - * \param _append Setting append to true will cause values read from the command line - * or XML file to be concatenated into a comma delimited list. If _append is false, - * newer values will overwrite older ones. - * \see GetOptionAsString - */ - bool AddOptionString( string const& _name, string const& _default, bool const _append ); - - /** - * Get the value of a boolean option. - * \param _name the name of the option. Option names are case insensitive. - * \param o_value a pointer to the item that will be filled with the option value. - * \return true if the option value was fetched successfully, false if the - * option does not exist, or does not contain a boolean value - * \see AddOptionBool, GetOptionType - */ - bool GetOptionAsBool( string const& _name, bool* o_value ); - - /** - * Get the value of an integer option. - * \param _name the name of the option. Option names are case insensitive. - * \param o_value a pointer to the item that will be filled with the option value. - * \return true if the option value was fetched successfully, false if the - * option does not exist, or does not contain an integer value - * \see AddOptionInt, GetOptionType - */ - bool GetOptionAsInt( string const& _name, int32* o_value ); - - /** - * Get the value of a string option. - * \param _name the name of the option. Option names are case insensitive. - * \param o_value a pointer to the item that will be filled with the option value. - * \return true if the option value was fetched successfully, false if the - * option does not exist, or does not contain a string value - * \see AddOptionString, GetOptionType - */ - bool GetOptionAsString( string const& _name, string* o_value ); - - /** - * Get the type of value stored in an option. - * \param _name the name of the option. Option names are case insensitive. - * \return An enum value representing the type of the option value. If the - * option does not exist, OptionType_Invalid is returned. - * \see GetOptionAsBool, GetOptionAsInt, GetOptionAsString - */ - OptionType GetOptionType( string const& _name ); - - /** - * Test whether the options have been locked. - * \return true if the options have been locked. - * \see Lock - */ - bool AreLocked()const{ return m_locked; } - - - private: - class Option - { - friend class Options; - public: - Option( string const& _name ): m_name( _name ), m_append( false ){} - bool SetValueFromString( string const& _value ); - - Options::OptionType m_type; - string m_name; - bool m_valueBool; - int32 m_valueInt; - string m_valueString; - bool m_append; - }; - - Options( string const& _configPath, string const& _userPath, string const& _commandLine ); // Constructor, to be called only via the static Create method. - ~Options(); // Destructor, to be called only via the static Destroy method. - - bool ParseOptionsString( string const& _options ); // Parse a string containing program options, such as a command line. - bool ParseOptionsXML( string const& _filename ); // Parse an XML file containing program options. - Option* AddOption( string const& _name ); // check lock and create (or open existing) option - Option* Find( string const& _name ); - -OPENZWAVE_EXPORT_WARNINGS_OFF - map m_options; // Map of option names to values. -OPENZWAVE_EXPORT_WARNINGS_ON - string m_xml; // Path to XML options file. - string m_commandLine; // String containing command line options. - string m_SystemPath; - string m_LocalPath; - bool m_locked; // If true, the options are final and AddOption can no longer be called. - static Options* s_instance; + enum OptionType + { + OptionType_Invalid = 0, + OptionType_Bool, + OptionType_Int, + OptionType_String + }; + + /** + * Creates an object to manage the program options. + * \param _configPath a string containing the path to the OpenZWave library config + * folder, which contains XML descriptions of Z-Wave manufacturers and products. + * \param _userPath a string containing the path to the application's user data + * folder where the OpenZWave should store the Z-Wave network configuration and state. + * The _userPath is also the folder where OpenZWave will look for the file Options.xml + * which contains program option values. The file should be in the form outlined below, + * with one or more Option elements containing a name and value attribute. Multiple + * values with the same option name should be listed separately. Note that option names + * are case insensitive. + * \code + * + * + * + * \endcode + * \param _commandLine a string containing the program's command line options. + * Command line options are parsed after the options.xml file, and so take precedence. + * Options are identified by a leading -- (two minus signs). The following items + * in the string are treated as values for this option, until the next -- is + * reached. For boolean options only, it is possible to omit the value, in which case + * the value is assumed to be "true". Note that option names are case insensitive, and + * that option values should be separated by a space. + * \return Pointer to the newly created Options object. + * \see Get, Destroy, AddOption, GetOptionAs, Lock + */ + static Options* Create(string const& _configPath, string const& _userPath, string const& _commandLine); + + /** + * Deletes the Options and cleans up any associated objects. + * The application is responsible for destroying the Options object, + * but this must not be done until after the Manager object has been + * destroyed. + * \param _options Pointer to the Options object to be destroyed. + * \return true if the Options object was destroyed. If the manager + * object still exists, this call will return false. + * \see Create, Get + */ + static bool Destroy(); + + /** + * Gets a pointer to the Options singleton object. + * \return a pointer to the Options singleton object. + * \see Create, Destroy + */ + static Options* Get(); + + /** + * Locks the options. + * Reads in option values from the XML options file and command line string and + * marks the options as locked. Once locked, no more calls to AddOption + * can be made. + * The options must be locked before the Manager::Create method is called. + * \see AddOption + */ + bool Lock(); + + /** + * Add a boolean option to the program. + * Adds an option to the program whose value can then be read from a file or command line. + * All calls to AddOptionInt must be made before Lock. + * \param _name the name of the option. Option names are case insensitive and must be unique. + * \param _default the default value for this option. + * \see GetOptionAsBool + */ + bool AddOptionBool(string const& _name, bool const _default); + + /** + * Add an integer option to the program. + * Adds an option to the program whose value can then be read from a file or command line. + * All calls to AddOptionInt must be made before Lock. + * \param _name the name of the option. Option names are case insensitive and must be unique. + * \param _default the default value for this option. + * \see GetOptionAsInt + */ + bool AddOptionInt(string const& _name, int32 const _default); + + /** + * Add a string option to the program. + * Adds an option to the program whose value can then be read from a file or command line. + * All calls to AddOptionString must be made before Lock. + * \param _name the name of the option. Option names are case insensitive and must be unique. + * \param _default the default value for this option. + * \param _append Setting append to true will cause values read from the command line + * or XML file to be concatenated into a comma delimited list. If _append is false, + * newer values will overwrite older ones. + * \see GetOptionAsString + */ + bool AddOptionString(string const& _name, string const& _default, bool const _append); + + /** + * Get the value of a boolean option. + * \param _name the name of the option. Option names are case insensitive. + * \param o_value a pointer to the item that will be filled with the option value. + * \return true if the option value was fetched successfully, false if the + * option does not exist, or does not contain a boolean value + * \see AddOptionBool, GetOptionType + */ + bool GetOptionAsBool(string const& _name, bool* o_value); + + /** + * Get the value of an integer option. + * \param _name the name of the option. Option names are case insensitive. + * \param o_value a pointer to the item that will be filled with the option value. + * \return true if the option value was fetched successfully, false if the + * option does not exist, or does not contain an integer value + * \see AddOptionInt, GetOptionType + */ + bool GetOptionAsInt(string const& _name, int32* o_value); + + /** + * Get the value of a string option. + * \param _name the name of the option. Option names are case insensitive. + * \param o_value a pointer to the item that will be filled with the option value. + * \return true if the option value was fetched successfully, false if the + * option does not exist, or does not contain a string value + * \see AddOptionString, GetOptionType + */ + bool GetOptionAsString(string const& _name, string* o_value); + + /** + * Get the type of value stored in an option. + * \param _name the name of the option. Option names are case insensitive. + * \return An enum value representing the type of the option value. If the + * option does not exist, OptionType_Invalid is returned. + * \see GetOptionAsBool, GetOptionAsInt, GetOptionAsString + */ + OptionType GetOptionType(string const& _name); + + /** + * Test whether the options have been locked. + * \return true if the options have been locked. + * \see Lock + */ + bool AreLocked() const + { + return m_locked; + } + + private: + class Option + { + friend class Options; + + public: + Option(string const& _name) : + m_name(_name), m_append(false) + { + } + bool SetValueFromString(string const& _value); + + Options::OptionType m_type; + string m_name; + bool m_valueBool; + int32 m_valueInt; + string m_valueString; + bool m_append; + }; + + Options(string const& _configPath, string const& _userPath, string const& _commandLine); // Constructor, to be called only via the static Create method. + ~Options(); // Destructor, to be called only via the static Destroy method. + + bool ParseOptionsString(string const& _options); // Parse a string containing program options, such as a command line. + bool ParseOptionsXML(string const& _filename); // Parse an XML file containing program options. + Option* AddOption(string const& _name); // check lock and create (or open existing) option + Option* Find(string const& _name); + + map m_options; // Map of option names to values. + string m_xml; // Path to XML options file. + string m_commandLine; // String containing command line options. + string m_SystemPath; + string m_LocalPath; + bool m_locked; // If true, the options are final and AddOption can no longer be called. + static Options* s_instance; }; } // namespace OpenZWave diff --git a/cpp/src/Scene.cpp b/cpp/src/Scene.cpp index e828edebf7..96197a5775 100644 --- a/cpp/src/Scene.cpp +++ b/cpp/src/Scene.cpp @@ -35,447 +35,407 @@ #include "tinyxml.h" -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { -uint32 const c_sceneVersion = 1; + uint32 const c_sceneVersion = 1; //----------------------------------------------------------------------------- // Statics //----------------------------------------------------------------------------- -uint8 Scene::s_sceneCnt = 0; -Scene* Scene::s_scenes[256] = { 0 }; + uint8 Scene::s_sceneCnt = 0; + Scene* Scene::s_scenes[256] = + { 0 }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -Scene::Scene -( - uint8 const _sceneId -): - m_sceneId( _sceneId ), - m_label( "" ) -{ - s_scenes[_sceneId] = this; - s_sceneCnt++; -} + Scene::Scene(uint8 const _sceneId) : + m_sceneId(_sceneId), m_label("") + { + s_scenes[_sceneId] = this; + s_sceneCnt++; + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -Scene::~Scene -( -) -{ - while( !m_values.empty() ) - { - SceneStorage* ss = m_values.back(); - m_values.pop_back(); - delete ss; - } + Scene::~Scene() + { + while (!m_values.empty()) + { + SceneStorage* ss = m_values.back(); + m_values.pop_back(); + delete ss; + } - s_sceneCnt--; - s_scenes[m_sceneId] = NULL; -} + s_sceneCnt--; + s_scenes[m_sceneId] = NULL; + } //----------------------------------------------------------------------------- // // Write ourselves to an XML document //----------------------------------------------------------------------------- -void Scene::WriteXML -( - string const& _name -) -{ - char str[16]; + void Scene::WriteXML(string const& _name) + { + char str[16]; - // Create a new XML document to contain the driver configuration - TiXmlDocument doc; - TiXmlDeclaration* decl = new TiXmlDeclaration( "1.0", "utf-8", "" ); - TiXmlElement* scenesElement = new TiXmlElement( "Scenes" ); - doc.LinkEndChild( decl ); - doc.LinkEndChild( scenesElement ); + // Create a new XML document to contain the driver configuration + TiXmlDocument doc; + TiXmlDeclaration* decl = new TiXmlDeclaration("1.0", "utf-8", ""); + TiXmlElement* scenesElement = new TiXmlElement("Scenes"); + doc.LinkEndChild(decl); + doc.LinkEndChild(scenesElement); - scenesElement->SetAttribute( "xmlns", "http://code.google.com/p/open-zwave/" ); + scenesElement->SetAttribute("xmlns", "http://code.google.com/p/open-zwave/"); - snprintf( str, sizeof(str), "%d", c_sceneVersion ); - scenesElement->SetAttribute( "version", str); + snprintf(str, sizeof(str), "%d", c_sceneVersion); + scenesElement->SetAttribute("version", str); - for( int i = 1; i < 256; i++ ) - { - if( s_scenes[i] == NULL ) - { - continue; - } + for (int i = 1; i < 256; i++) + { + if (s_scenes[i] == NULL) + { + continue; + } - TiXmlElement* sceneElement = new TiXmlElement( "Scene" ); + TiXmlElement* sceneElement = new TiXmlElement("Scene"); - snprintf( str, sizeof(str), "%d", i ); - sceneElement->SetAttribute( "id", str ); - sceneElement->SetAttribute( "label", s_scenes[i]->m_label.c_str() ); + snprintf(str, sizeof(str), "%d", i); + sceneElement->SetAttribute("id", str); + sceneElement->SetAttribute("label", s_scenes[i]->m_label.c_str()); - for( vector::iterator vt = s_scenes[i]->m_values.begin(); vt != s_scenes[i]->m_values.end(); ++vt ) - { - TiXmlElement* valueElement = new TiXmlElement( "Value" ); + for (vector::iterator vt = s_scenes[i]->m_values.begin(); vt != s_scenes[i]->m_values.end(); ++vt) + { + TiXmlElement* valueElement = new TiXmlElement("Value"); - snprintf( str, sizeof(str), "0x%.8x", (*vt)->m_id.GetHomeId() ); - valueElement->SetAttribute( "homeId", str ); + snprintf(str, sizeof(str), "0x%.8x", (*vt)->m_id.GetHomeId()); + valueElement->SetAttribute("homeId", str); - snprintf( str, sizeof(str), "%d", (*vt)->m_id.GetNodeId() ); - valueElement->SetAttribute( "nodeId", str ); + snprintf(str, sizeof(str), "%d", (*vt)->m_id.GetNodeId()); + valueElement->SetAttribute("nodeId", str); - valueElement->SetAttribute( "genre", Value::GetGenreNameFromEnum((*vt)->m_id.GetGenre()) ); + valueElement->SetAttribute("genre", Internal::VC::Value::GetGenreNameFromEnum((*vt)->m_id.GetGenre())); - snprintf( str, sizeof(str), "%d", (*vt)->m_id.GetCommandClassId() ); - valueElement->SetAttribute( "commandClassId", str ); + snprintf(str, sizeof(str), "%d", (*vt)->m_id.GetCommandClassId()); + valueElement->SetAttribute("commandClassId", str); - snprintf( str, sizeof(str), "%d", (*vt)->m_id.GetInstance() ); - valueElement->SetAttribute( "instance", str ); + snprintf(str, sizeof(str), "%d", (*vt)->m_id.GetInstance()); + valueElement->SetAttribute("instance", str); - snprintf( str, sizeof(str), "%d", (*vt)->m_id.GetIndex() ); - valueElement->SetAttribute( "index", str ); + snprintf(str, sizeof(str), "%d", (*vt)->m_id.GetIndex()); + valueElement->SetAttribute("index", str); - valueElement->SetAttribute( "type", Value::GetTypeNameFromEnum((*vt)->m_id.GetType()) ); + valueElement->SetAttribute("type", Internal::VC::Value::GetTypeNameFromEnum((*vt)->m_id.GetType())); - TiXmlText* textElement = new TiXmlText( (*vt)->m_value.c_str() ); - valueElement->LinkEndChild( textElement ); + TiXmlText* textElement = new TiXmlText((*vt)->m_value.c_str()); + valueElement->LinkEndChild(textElement); - sceneElement->LinkEndChild( valueElement ); - } + sceneElement->LinkEndChild(valueElement); + } - scenesElement->LinkEndChild( sceneElement ); - } + scenesElement->LinkEndChild(sceneElement); + } - string userPath; - Options::Get()->GetOptionAsString( "UserPath", &userPath ); + string userPath; + Options::Get()->GetOptionAsString("UserPath", &userPath); - string filename = userPath + _name; + string filename = userPath + _name; - doc.SaveFile( filename.c_str() ); -} + doc.SaveFile(filename.c_str()); + } //----------------------------------------------------------------------------- // // Read scene configuration from an XML document //----------------------------------------------------------------------------- -bool Scene::ReadScenes -( -) -{ - int32 intVal; - char const* str; - - // Load the XML document that contains the driver configuration - string userPath; - Options::Get()->GetOptionAsString( "UserPath", &userPath ); - - string filename = userPath + "zwscene.xml"; - - TiXmlDocument doc; - if( !doc.LoadFile( filename.c_str(), TIXML_ENCODING_UTF8 ) ) - { - return false; - } - - TiXmlElement const* scenesElement = doc.RootElement(); - - // Version - if( TIXML_SUCCESS == scenesElement->QueryIntAttribute( "version", &intVal ) ) - { - if( (uint32)intVal != c_sceneVersion ) + bool Scene::ReadScenes() { - Log::Write( LogLevel_Alert, "Driver::ReadScenes - %s is from an older version of OpenZWave and cannot be loaded.", filename.c_str() ); - return false; - } - } - else - { - Log::Write( LogLevel_Alert, "Driver::ReadScenes - %s is from an older version of OpenZWave and cannot be loaded.", filename.c_str() ); - return false; - } + int32 intVal; + char const* str; - TiXmlElement const* sceneElement = scenesElement->FirstChildElement(); - while( sceneElement ) - { - Scene* scene = NULL; + // Load the XML document that contains the driver configuration + string userPath; + Options::Get()->GetOptionAsString("UserPath", &userPath); - if( TIXML_SUCCESS == sceneElement->QueryIntAttribute( "id", &intVal ) ) - { - scene = new Scene( (uint8)intVal ); - } + string filename = userPath + "zwscene.xml"; - if( scene == NULL ) - { - continue; - } + TiXmlDocument doc; + if (!doc.LoadFile(filename.c_str(), TIXML_ENCODING_UTF8)) + { + return false; + } - str = sceneElement->Attribute( "label" ); - if( str ) - { - scene->m_label = str; - } + TiXmlElement const* scenesElement = doc.RootElement(); - // Read the ValueId for this scene - TiXmlElement const* valueElement = sceneElement->FirstChildElement(); - while( valueElement ) - { - char const* elementName = valueElement->Value(); - if( elementName && !strcmp( elementName, "Value" ) ) + // Version + if (TIXML_SUCCESS == scenesElement->QueryIntAttribute("version", &intVal)) { - uint32 homeId = 0; - str = valueElement->Attribute( "homeId" ); - if( str ) + if ((uint32) intVal != c_sceneVersion) { - char *p; - homeId = (uint32)strtol( str, &p, 0 ); + Log::Write(LogLevel_Alert, "Driver::ReadScenes - %s is from an older version of OpenZWave and cannot be loaded.", filename.c_str()); + return false; } - uint8 nodeId = 0; - if (TIXML_SUCCESS == valueElement->QueryIntAttribute( "nodeId", &intVal ) ) + } + else + { + Log::Write(LogLevel_Alert, "Driver::ReadScenes - %s is from an older version of OpenZWave and cannot be loaded.", filename.c_str()); + return false; + } + + TiXmlElement const* sceneElement = scenesElement->FirstChildElement(); + while (sceneElement) + { + Scene* scene = NULL; + + if (TIXML_SUCCESS == sceneElement->QueryIntAttribute("id", &intVal)) { - nodeId = intVal; + scene = new Scene((uint8) intVal); } - ValueID::ValueGenre genre = Value::GetGenreEnumFromName( valueElement->Attribute( "genre" ) ); - uint8 commandClassId = 0; - if (TIXML_SUCCESS == valueElement->QueryIntAttribute( "commandClassId", &intVal ) ) + + if (scene == NULL) { - commandClassId = intVal; + continue; } - uint8 instance = 0; - if (TIXML_SUCCESS == valueElement->QueryIntAttribute( "instance", &intVal ) ) + + str = sceneElement->Attribute("label"); + if (str) { - instance = intVal; + scene->m_label = str; } - uint8 index = 0; - if (TIXML_SUCCESS == valueElement->QueryIntAttribute( "index", &intVal ) ) + + // Read the ValueId for this scene + TiXmlElement const* valueElement = sceneElement->FirstChildElement(); + while (valueElement) { - index = intVal; + char const* elementName = valueElement->Value(); + if (elementName && !strcmp(elementName, "Value")) + { + uint32 homeId = 0; + str = valueElement->Attribute("homeId"); + if (str) + { + char *p; + homeId = (uint32) strtol(str, &p, 0); + } + uint8 nodeId = 0; + if (TIXML_SUCCESS == valueElement->QueryIntAttribute("nodeId", &intVal)) + { + nodeId = intVal; + } + ValueID::ValueGenre genre = Internal::VC::Value::GetGenreEnumFromName(valueElement->Attribute("genre")); + uint8 commandClassId = 0; + if (TIXML_SUCCESS == valueElement->QueryIntAttribute("commandClassId", &intVal)) + { + commandClassId = intVal; + } + uint8 instance = 0; + if (TIXML_SUCCESS == valueElement->QueryIntAttribute("instance", &intVal)) + { + instance = intVal; + } + uint8 index = 0; + if (TIXML_SUCCESS == valueElement->QueryIntAttribute("index", &intVal)) + { + index = intVal; + } + ValueID::ValueType type = Internal::VC::Value::GetTypeEnumFromName(valueElement->Attribute("type")); + char const* data = valueElement->GetText(); + + scene->m_values.push_back(new SceneStorage(ValueID(homeId, nodeId, genre, commandClassId, instance, index, type), data)); + } + + valueElement = valueElement->NextSiblingElement(); } - ValueID::ValueType type = Value::GetTypeEnumFromName( valueElement->Attribute( "type" ) ); - char const* data = valueElement->GetText(); - - scene->m_values.push_back( new SceneStorage( ValueID(homeId, nodeId, genre, commandClassId, instance, index, type), data ) ); + sceneElement = sceneElement->NextSiblingElement(); } - - valueElement = valueElement->NextSiblingElement(); + return true; } - sceneElement = sceneElement->NextSiblingElement(); - } - return true; -} //----------------------------------------------------------------------------- // // Return the Scene object given the Scene Id //----------------------------------------------------------------------------- -Scene* Scene::Get -( - uint8 const _sceneId -) -{ - if ( s_scenes[_sceneId] != NULL ) - { - return s_scenes[_sceneId]; - } - return NULL; -} + Scene* Scene::Get(uint8 const _sceneId) + { + if (s_scenes[_sceneId] != NULL) + { + return s_scenes[_sceneId]; + } + return NULL; + } //----------------------------------------------------------------------------- // // Return an array of uint8 of used Scene IDs and the count //----------------------------------------------------------------------------- -uint8 Scene::GetAllScenes -( - uint8** _sceneIds -) -{ - if( s_sceneCnt > 0 ) - { - *_sceneIds = new uint8[s_sceneCnt]; - int j = 0; - for( int i = 1; i < 256; i++ ) + uint8 Scene::GetAllScenes(uint8** _sceneIds) { - if (s_scenes[i] != NULL) + if (s_sceneCnt > 0) { - (*_sceneIds)[j++] = s_scenes[i]->m_sceneId; + *_sceneIds = new uint8[s_sceneCnt]; + int j = 0; + for (int i = 1; i < 256; i++) + { + if (s_scenes[i] != NULL) + { + (*_sceneIds)[j++] = s_scenes[i]->m_sceneId; + } + } } + return s_sceneCnt; } - } - return s_sceneCnt; -} //----------------------------------------------------------------------------- // // Add a ValueID and a string to the scene. //----------------------------------------------------------------------------- -bool Scene::AddValue -( - ValueID const& _valueId, - string const& _value -) -{ - m_values.push_back( new SceneStorage( _valueId, _value ) ); - return true; -} + bool Scene::AddValue(ValueID const& _valueId, string const& _value) + { + m_values.push_back(new SceneStorage(_valueId, _value)); + return true; + } //----------------------------------------------------------------------------- // // Remove the first ValueID found //----------------------------------------------------------------------------- -bool Scene::RemoveValue -( - ValueID const& _valueId -) -{ - for( vector::iterator it = m_values.begin(); it != m_values.end(); ++it ) - { - if( (*it)->m_id == _valueId ) + bool Scene::RemoveValue(ValueID const& _valueId) { - delete *it; - m_values.erase( it ); - return true; + for (vector::iterator it = m_values.begin(); it != m_values.end(); ++it) + { + if ((*it)->m_id == _valueId) + { + delete *it; + m_values.erase(it); + return true; + } + } + return false; } - } - return false; -} //----------------------------------------------------------------------------- // // Remove all ValueIDs from given Home ID //----------------------------------------------------------------------------- -void Scene::RemoveValues -( - uint32 const _homeId -) -{ - again: - for( vector::iterator it = m_values.begin(); it != m_values.end(); ++it ) - { - if( (*it)->m_id.GetHomeId() == _homeId ) + void Scene::RemoveValues(uint32 const _homeId) { - delete *it; - m_values.erase( it ); - goto again; + again: for (vector::iterator it = m_values.begin(); it != m_values.end(); ++it) + { + if ((*it)->m_id.GetHomeId() == _homeId) + { + delete *it; + m_values.erase(it); + goto again; + } + } + // If the scene is now empty, delete it. + if (m_values.empty()) + { + delete this; + } } - } - // If the scene is now empty, delete it. - if( m_values.empty() ) - { - delete this; - } -} //----------------------------------------------------------------------------- // // Remove all ValueIDs from given Home ID and node ID //----------------------------------------------------------------------------- -void Scene::RemoveValues -( - uint32 const _homeId, - uint8 const _nodeId -) -{ - for( int i = 1; i < 256; i++ ) - { - Scene *scene = Scene::Get( i ); - if( scene != NULL ) + void Scene::RemoveValues(uint32 const _homeId, uint8 const _nodeId) { - again: - for( vector::iterator it = scene->m_values.begin(); it != scene->m_values.end(); ++it ) + for (int i = 1; i < 256; i++) { - if( (*it)->m_id.GetHomeId() == _homeId && (*it)->m_id.GetNodeId() == _nodeId ) + Scene *scene = Scene::Get(i); + if (scene != NULL) { - delete *it; - scene->m_values.erase( it ); - goto again; + again: for (vector::iterator it = scene->m_values.begin(); it != scene->m_values.end(); ++it) + { + if ((*it)->m_id.GetHomeId() == _homeId && (*it)->m_id.GetNodeId() == _nodeId) + { + delete *it; + scene->m_values.erase(it); + goto again; + } + } + // If the scene is now empty, delete it. + if (scene->m_values.empty()) + { + delete scene; + } } } - // If the scene is now empty, delete it. - if( scene->m_values.empty() ) - { - delete scene; - } } - } -} //----------------------------------------------------------------------------- // // Return all ValueIDs for the given scene. //----------------------------------------------------------------------------- -int Scene::GetValues -( - vector* o_value -) -{ - int size = (int) m_values.size(); - if( size > 0 ) - { - for( vector::iterator it = m_values.begin(); it != m_values.end(); ++it ) + int Scene::GetValues(vector* o_value) { - o_value->push_back( (*it)->m_id ); + int size = (int) m_values.size(); + if (size > 0) + { + for (vector::iterator it = m_values.begin(); it != m_values.end(); ++it) + { + o_value->push_back((*it)->m_id); + } + } + return size; } - } - return size; -} //----------------------------------------------------------------------------- // // Return a ValueID's value as string //----------------------------------------------------------------------------- -bool Scene::GetValue -( - ValueID const& _valueId, - string* o_value -) -{ - for( vector::iterator it = m_values.begin(); it != m_values.end(); ++it ) - { - if( (*it)->m_id == _valueId ) + bool Scene::GetValue(ValueID const& _valueId, string* o_value) { - *o_value = (*it)->m_value; - return true; - } - } - return false; -} + for (vector::iterator it = m_values.begin(); it != m_values.end(); ++it) + { + if ((*it)->m_id == _valueId) + { + *o_value = (*it)->m_value; + return true; + } + } + return false; + } //----------------------------------------------------------------------------- // // Set a ValueID's value as string //----------------------------------------------------------------------------- -bool Scene::SetValue -( - ValueID const& _valueId, - string const& _value -) -{ - for( vector::iterator it = m_values.begin(); it != m_values.end(); ++it ) - { - if( (*it)->m_id == _valueId ) + bool Scene::SetValue(ValueID const& _valueId, string const& _value) { - (*it)->m_value = _value; - return true; - } - } - return false; -} + for (vector::iterator it = m_values.begin(); it != m_values.end(); ++it) + { + if ((*it)->m_id == _valueId) + { + (*it)->m_value = _value; + return true; + } + } + return false; + } //----------------------------------------------------------------------------- // // Execute scene activation by running each ValueId/value //----------------------------------------------------------------------------- -bool Scene::Activate -( -) -{ - bool res = true; - for( vector::iterator it = m_values.begin(); it != m_values.end(); ++it ) - { - if ( !Manager::Get()->SetValue( (*it)->m_id, (*it)->m_value ) ) + bool Scene::Activate() { - res = false; + bool res = true; + for (vector::iterator it = m_values.begin(); it != m_values.end(); ++it) + { + if (!Manager::Get()->SetValue((*it)->m_id, (*it)->m_value)) + { + res = false; + } + } + return res; } - } - return res; -} + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/Scene.h b/cpp/src/Scene.h index 3af3e67468..a9bb7ea749 100644 --- a/cpp/src/Scene.h +++ b/cpp/src/Scene.h @@ -37,69 +37,83 @@ class TiXmlElement; namespace OpenZWave { - class ValueID; - - /** \brief Collection of ValueIDs to be treated as a unit. - */ - class Scene + namespace Internal { - friend class Manager; - friend class Driver; - friend class Node; - //----------------------------------------------------------------------------- - // Construction - //----------------------------------------------------------------------------- - private: - Scene( uint8 const _sceneId ); - ~Scene(); + /** \brief Collection of ValueIDs to be treated as a unit. + */ + class Scene + { + friend class OpenZWave::Manager; + friend class OpenZWave::Driver; + friend class OpenZWave::Node; - static void WriteXML( string const& _name ); - static bool ReadScenes(); - - //----------------------------------------------------------------------------- - // Scene functions - //----------------------------------------------------------------------------- - private: - static Scene* Get( uint8 const _sceneId ); - static uint8 GetAllScenes( uint8** _sceneIds ); + //----------------------------------------------------------------------------- + // Construction + //----------------------------------------------------------------------------- + private: + Scene(uint8 const _sceneId); + ~Scene(); - string const& GetLabel()const{ return m_label; } - void SetLabel( string const &_label ){ m_label = _label; } + static void WriteXML(string const& _name); + static bool ReadScenes(); - bool AddValue( ValueID const& _valueId, string const& _value ); - bool RemoveValue( ValueID const& _valueId ); - void RemoveValues( uint32 const _homeId ); - static void RemoveValues( uint32 const _homeId, uint8 const _nodeId ); - int GetValues( vector* o_value ); - bool GetValue( ValueID const& _valueId, string* o_value ); - bool SetValue( ValueID const& _valueId, string const& _value ); - bool Activate(); + //----------------------------------------------------------------------------- + // Scene functions + //----------------------------------------------------------------------------- + private: + static Scene* Get(uint8 const _sceneId); + static uint8 GetAllScenes(uint8** _sceneIds); - //----------------------------------------------------------------------------- - // ValueID/value storage - //----------------------------------------------------------------------------- - private: - class SceneStorage - { - public: - SceneStorage( ValueID const& _id, string const& _value ): m_id( _id ), m_value( _value ) {}; - ~SceneStorage() {}; + string const& GetLabel() const + { + return m_label; + } + void SetLabel(string const &_label) + { + m_label = _label; + } - ValueID const m_id; - string m_value; - }; - //----------------------------------------------------------------------------- - // Member variables - //----------------------------------------------------------------------------- - private: - uint8 m_sceneId; - string m_label; - vector m_values; - static uint8 s_sceneCnt; - static Scene* s_scenes[256]; - }; + bool AddValue(ValueID const& _valueId, string const& _value); + bool RemoveValue(ValueID const& _valueId); + void RemoveValues(uint32 const _homeId); + static void RemoveValues(uint32 const _homeId, uint8 const _nodeId); + int GetValues(vector* o_value); + bool GetValue(ValueID const& _valueId, string* o_value); + bool SetValue(ValueID const& _valueId, string const& _value); + bool Activate(); + + //----------------------------------------------------------------------------- + // ValueID/value storage + //----------------------------------------------------------------------------- + private: + class SceneStorage + { + public: + SceneStorage(ValueID const& _id, string const& _value) : + m_id(_id), m_value(_value) + { + } + ; + ~SceneStorage() + { + } + ; + ValueID const m_id; + string m_value; + }; + //----------------------------------------------------------------------------- + // Member variables + //----------------------------------------------------------------------------- + private: + uint8 m_sceneId; + string m_label; + vector m_values; + static uint8 s_sceneCnt; + static Scene* s_scenes[256]; + }; + } // namespace Internal } //namespace OpenZWave #endif //_Scene_H diff --git a/cpp/src/SensorMultiLevelCCTypes.cpp b/cpp/src/SensorMultiLevelCCTypes.cpp new file mode 100755 index 0000000000..b533ca60cc --- /dev/null +++ b/cpp/src/SensorMultiLevelCCTypes.cpp @@ -0,0 +1,257 @@ +//----------------------------------------------------------------------------- +// +// SensorMultiLevelCCTypes.cpp +// +// SensorMultiLevelCCTypes for SensorMultiLevel Command Class +// +// Copyright (c) 2019 Justin Hammond +// +// SOFTWARE NOTICE AND LICENSE +// +// This file is part of OpenZWave. +// +// OpenZWave is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, either version 3 of the License, +// or (at your option) any later version. +// +// OpenZWave is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with OpenZWave. If not, see . +// +//----------------------------------------------------------------------------- +#include "SensorMultiLevelCCTypes.h" + +#include + +#include "tinyxml.h" +#include "Options.h" +#include "Utils.h" +#include "platform/Log.h" + +namespace OpenZWave +{ + namespace Internal + { + + SensorMultiLevelCCTypes *SensorMultiLevelCCTypes::m_instance = NULL; + std::map > SensorMultiLevelCCTypes::SensorTypes; + uint32 SensorMultiLevelCCTypes::m_revision(0); + + SensorMultiLevelCCTypes::SensorMultiLevelCCTypes() + { + } + + void SensorMultiLevelCCTypes::ReadXML() + { + // Parse the Z-Wave manufacturer and product XML file. + string configPath; + Options::Get()->GetOptionAsString("ConfigPath", &configPath); + + string path = configPath + "SensorMultiLevelCCTypes.xml"; + TiXmlDocument* pDoc = new TiXmlDocument(); + if (!pDoc->LoadFile(path.c_str(), TIXML_ENCODING_UTF8)) + { + delete pDoc; + Log::Write(LogLevel_Warning, "Unable to load SensorMultiLevelCCTypes file %s", path.c_str()); + return; + } + pDoc->SetUserData((void*) path.c_str()); + Log::Write(LogLevel_Info, "Loading SensorMultiLevelCCTypes File %s", path.c_str()); + + TiXmlElement const* root = pDoc->RootElement(); + char const *str = root->Value(); + if (str && !strcmp(str, "SensorTypes")) + { + // Read in the revision attributes + str = root->Attribute("Revision"); + if (!str) + { + Log::Write(LogLevel_Info, "Error in SensorMultiLevel Config file at line %d - missing Revision attribute", root->Row()); + delete pDoc; + return; + } + m_revision = atol(str); + } + TiXmlElement const* SensorTypeElement = root->FirstChildElement(); + while (SensorTypeElement) + { + char const* str = SensorTypeElement->Value(); + char* pStopChar; + if (str && !strcmp(str, "SensorType")) + { + SensorMultiLevelTypes *st = new SensorMultiLevelTypes; + + str = SensorTypeElement->Attribute("id"); + if (!str) + { + Log::Write(LogLevel_Warning, "SensorMultiLevelCCTypes::ReadXML: Error in %s at line %d - missing SensorType ID attribute", SensorTypeElement->GetDocument()->GetUserData(), SensorTypeElement->Row()); + SensorTypeElement = SensorTypeElement->NextSiblingElement(); + delete st; + continue; + } + st->id = (uint32) strtol(str, &pStopChar, 10); + str = SensorTypeElement->Attribute("name"); + if (!str) + { + Log::Write(LogLevel_Warning, "SensorMultiLevelCCTypes::ReadXML: Error in %s at line %d - missing SensorType name attribute", SensorTypeElement->GetDocument()->GetUserData(), SensorTypeElement->Row()); + SensorTypeElement = SensorTypeElement->NextSiblingElement(); + delete st; + continue; + } + st->name = str; + trim(st->name); + TiXmlElement const* SensorScaleElement = SensorTypeElement->FirstChildElement(); + while (SensorScaleElement) + { + str = SensorScaleElement->Value(); + if (str && !strcmp(str, "SensorScale")) + { + SensorMultiLevelScales *ss = new SensorMultiLevelScales; + str = SensorScaleElement->Attribute("id"); + if (!str) + { + Log::Write(LogLevel_Warning, "SensorMultiLevelCCTypes::ReadXML: Error in %s at line %d - missing SensorScale id attribute", SensorScaleElement->GetDocument()->GetUserData(), SensorScaleElement->Row()); + SensorScaleElement = SensorScaleElement->NextSiblingElement(); + delete ss; + continue; + } + + ss->id = (uint32) strtol(str, &pStopChar, 10); + + str = SensorScaleElement->Attribute("name"); + if (!str) + { + Log::Write(LogLevel_Warning, "SensorMultiLevelCCTypes::ReadXML: Error in %s at line %d - missing SensorScale name attribute", SensorScaleElement->GetDocument()->GetUserData(), SensorScaleElement->Row()); + SensorScaleElement = SensorScaleElement->NextSiblingElement(); + delete ss; + continue; + } + ss->name = str; + trim(ss->name); + + str = SensorScaleElement->GetText(); + if (str) { + ss->unit = str; + trim(ss->unit); + } + + if (st->allSensorScales.find(ss->id) == st->allSensorScales.end()) + st->allSensorScales[ss->id] = std::shared_ptr(ss); + else + { + Log::Write(LogLevel_Warning, "SensorMultiLevelCCTypes::ReadXML: Error in %s at line %d - A SensorScale with id %d already exists. Skipping ", SensorScaleElement->GetDocument()->GetUserData(), SensorScaleElement->Row(), ss->id); + delete ss; + } + } + SensorScaleElement = SensorScaleElement->NextSiblingElement(); + } + if (SensorTypes.find(st->id) == SensorTypes.end()) + SensorTypes[st->id] = std::shared_ptr(st); + else + { + Log::Write(LogLevel_Warning, "SensorMultiLevelCCTypes::ReadXML: Error in %s at line %d - A SensorTypeElement with id %d already exists. Skipping ", SensorTypeElement->GetDocument()->GetUserData(), SensorTypeElement->Row(), st->id); + delete st; + } + } + SensorTypeElement = SensorTypeElement->NextSiblingElement(); + } + Log::Write(LogLevel_Info, "Loaded %s With Revision %d", pDoc->GetUserData(), m_revision); +#if 0 + std::cout << "SensorMultiLevelCCTypes" << std::endl; + for (std::map::iterator it = SensorTypes.begin(); it != SensorTypes.end(); it++) + { + std::cout << "\tSensorTypes:" << (uint32)it->first << " Name: " << it->second->name << std::endl; + for (std::map::iterator it2 = it->second->allSensorScales.begin(); it2 != it->second->allSensorScales.end(); it2++) + { + std::cout << "\t\tSensorScales: " << (uint32)it2->first << " Name: " << it2->second->name << std::endl; + } + } + exit(0); +#endif + delete pDoc; + } + + std::string SensorMultiLevelCCTypes::GetSensorName(uint32 type) + { + if (SensorTypes.find(type) != SensorTypes.end()) + { + return SensorTypes.at(type)->name; + } + Log::Write(LogLevel_Warning, "SensorMultiLevelCCTypes::GetSensorName - Unknown SensorType %d", type); + return "Unknown"; + } + + std::string SensorMultiLevelCCTypes::GetSensorUnit(uint32 type, uint8 scale) + { + if (SensorTypes.find(type) == SensorTypes.end()) + { + Log::Write(LogLevel_Warning, "SensorMultiLevelCCTypes::GetSensorUnit - Unknown SensorType %d", type); + return ""; + } + SensorScales ss = SensorTypes.at(type)->allSensorScales; + if (ss.find(scale) == ss.end()) + { + Log::Write(LogLevel_Warning, "SensorMultiLevelCCTypes::GetSensorUnit - Unknown SensorScale %d", scale); + return ""; + + } + return ss.at(scale)->unit; + } + + std::string SensorMultiLevelCCTypes::GetSensorUnitName(uint32 type, uint8 scale) { + if (SensorTypes.find(type) == SensorTypes.end()) + { + Log::Write(LogLevel_Warning, "SensorMultiLevelCCTypes::GetSensorUnit - Unknown SensorType %d", type); + return ""; + } + SensorScales ss = SensorTypes.at(type)->allSensorScales; + if (ss.find(scale) == ss.end()) + { + Log::Write(LogLevel_Warning, "SensorMultiLevelCCTypes::GetSensorUnit - Unknown SensorScale %d", scale); + return ""; + + } + return ss.at(scale)->name; + + } + + + const SensorMultiLevelCCTypes::SensorScales SensorMultiLevelCCTypes::GetSensorScales(uint32 type) + { + if (SensorTypes.find(type) == SensorTypes.end()) + { + Log::Write(LogLevel_Warning, "SensorMultiLevelCCTypes::GetSensorUnit - Unknown SensorType %d", type); + return SensorScales(); + } + return SensorTypes.at(type)->allSensorScales; + } + + + bool SensorMultiLevelCCTypes::Create() + { + if (m_instance != NULL) + { + return true; + } + m_instance = new SensorMultiLevelCCTypes(); + ReadXML(); + return true; + } + + SensorMultiLevelCCTypes *SensorMultiLevelCCTypes::Get() + { + if (m_instance != NULL) + { + return m_instance; + } + m_instance = new SensorMultiLevelCCTypes(); + ReadXML(); + return m_instance; + } + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/SensorMultiLevelCCTypes.h b/cpp/src/SensorMultiLevelCCTypes.h new file mode 100755 index 0000000000..3e4bafe938 --- /dev/null +++ b/cpp/src/SensorMultiLevelCCTypes.h @@ -0,0 +1,87 @@ +//----------------------------------------------------------------------------- +// +// SensorMultiLevelCCTypes.h +// +// SensorMultiLevelCCTypes for SensorMultiLevel Command Class +// +// Copyright (c) 2019 Justin Hammond +// +// SOFTWARE NOTICE AND LICENSE +// +// This file is part of OpenZWave. +// +// OpenZWave is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, either version 3 of the License, +// or (at your option) any later version. +// +// OpenZWave is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with OpenZWave. If not, see . +// +//----------------------------------------------------------------------------- + +#ifndef SENSORMULTILEVELCCTYPES_H +#define SENSORMULTILEVELCCTYPES_H + +#include +#include +#include +#include "Defs.h" +#include "Driver.h" +#include "command_classes/CommandClass.h" + +namespace OpenZWave +{ + namespace Internal + { + + class SensorMultiLevelCCTypes + { + public: + class SensorMultiLevelScales + { + public: + uint8 id; + string name; + string unit; + }; + typedef std::map > SensorScales; + class SensorMultiLevelTypes + { + public: + uint32 id; + string name; + SensorScales allSensorScales; + }; + + //----------------------------------------------------------------------------- + // Construction + //----------------------------------------------------------------------------- + private: + SensorMultiLevelCCTypes(); + ~SensorMultiLevelCCTypes(); + static void ReadXML(); + public: + static SensorMultiLevelCCTypes* Get(); + static bool Create(); + string GetSensorName(uint32); + string GetSensorUnit(uint32, uint8); + string GetSensorUnitName(uint32, uint8); + const SensorScales GetSensorScales(uint32); + + //----------------------------------------------------------------------------- + // Instance Functions + //----------------------------------------------------------------------------- + private: + static SensorMultiLevelCCTypes* m_instance; + static std::map > SensorTypes; + static uint32 m_revision; + }; + } // namespace Internal +} // namespace OpenZWave +#endif // SENSORMULTILEVELCCTYPES_H diff --git a/cpp/src/TimerThread.cpp b/cpp/src/TimerThread.cpp index b21d74a302..52761e6324 100644 --- a/cpp/src/TimerThread.cpp +++ b/cpp/src/TimerThread.cpp @@ -30,307 +30,292 @@ #include "platform/Log.h" #include "Driver.h" -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { //----------------------------------------------------------------------------- // // Main entry point for the timer thread. //----------------------------------------------------------------------------- -void TimerThread::TimerThreadEntryPoint -( - Event* _exitEvent, - void* _context -) -{ - TimerThread* timer = (TimerThread*)_context; - if( timer ) - { - timer->TimerThreadProc( _exitEvent ); - } -} + void TimerThread::TimerThreadEntryPoint(Internal::Platform::Event* _exitEvent, void* _context) + { + TimerThread* timer = (TimerThread*) _context; + if (timer) + { + timer->TimerThreadProc(_exitEvent); + } + } //----------------------------------------------------------------------------- // // Constructor. //----------------------------------------------------------------------------- -TimerThread::TimerThread -( - Driver *_driver -): + TimerThread::TimerThread(Driver *_driver) : //m_driver( _driver ), -m_timerEvent( new Event() ), -m_timerMutex( new Mutex() ), -m_timerTimeout( Wait::Timeout_Infinite ) -{ -} + m_timerEvent(new Internal::Platform::Event()), m_timerMutex(new Internal::Platform::Mutex()), m_timerTimeout(Internal::Platform::Wait::Timeout_Infinite) + { + } //----------------------------------------------------------------------------- // // Destructor. //----------------------------------------------------------------------------- -TimerThread::~TimerThread -( -) -{ - { - LockGuard LG(m_timerMutex); - for ( list::iterator it = m_timerEventList.begin(); it != m_timerEventList.end(); ++it ) { - delete (*it); + TimerThread::~TimerThread() + { + { + LockGuard LG(m_timerMutex); + for (list::iterator it = m_timerEventList.begin(); it != m_timerEventList.end(); ++it) + { + delete (*it); + } + } + m_timerMutex->Release(); + m_timerEvent->Release(); } - } - m_timerMutex->Release(); - m_timerEvent->Release(); -} - //----------------------------------------------------------------------------- // // Thread for timer based actions //----------------------------------------------------------------------------- -void TimerThread::TimerThreadProc -( - Event* _exitEvent -) -{ - Log::Write( LogLevel_Info, "Timer: thread starting" ); + void TimerThread::TimerThreadProc(Internal::Platform::Event* _exitEvent) + { + Log::Write(LogLevel_Info, "Timer: thread starting"); - Wait* waitObjects[2]; - waitObjects[0] = _exitEvent; - waitObjects[1] = m_timerEvent; - uint32 count = 2; + Internal::Platform::Wait* waitObjects[2]; + waitObjects[0] = _exitEvent; + waitObjects[1] = m_timerEvent; + uint32 count = 2; - // Initially no timer events so infinite timeout. - m_timerTimeout = Wait::Timeout_Infinite; + // Initially no timer events so infinite timeout. + m_timerTimeout = Internal::Platform::Wait::Timeout_Infinite; - while( 1 ) - { - Log::Write( LogLevel_Detail, "Timer: waiting with timeout %d ms", m_timerTimeout ); - int32 res = Wait::Multiple( waitObjects, count, m_timerTimeout ); + while (1) + { + Log::Write(LogLevel_Detail, "Timer: waiting with timeout %d ms", m_timerTimeout); + int32 res = Internal::Platform::Wait::Multiple(waitObjects, count, m_timerTimeout); - if (res == 0) - { - // Exit has been signalled - return; + if (res == 0) + { + // Exit has been signalled + return; - } else { - // Timeout or new entry to timer list. - m_timerTimeout = Wait::Timeout_Infinite; + } + else + { + // Timeout or new entry to timer list. + m_timerTimeout = Internal::Platform::Wait::Timeout_Infinite; - // Go through all waiting actions, and see if any need to be performed. - LockGuard LG(m_timerMutex); - list::iterator it = m_timerEventList.begin(); - while( it != m_timerEventList.end() ) { - int32 tr = (*it)->timestamp.TimeRemaining(); - if (tr <= 0) { - // Expired so perform action and remove from list. - Log::Write( LogLevel_Info, "Timer: delayed event" ); - TimerEventEntry *te = *(it++); - te->instance->TimerFireEvent(te); - } else { - // Time remaining. - m_timerTimeout = (m_timerTimeout == Wait::Timeout_Infinite) ? tr : std::min(m_timerTimeout, tr); - ++it; + // Go through all waiting actions, and see if any need to be performed. + LockGuard LG(m_timerMutex); + list::iterator it = m_timerEventList.begin(); + while (it != m_timerEventList.end()) + { + int32 tr = (*it)->timestamp.TimeRemaining(); + if (tr <= 0) + { + // Expired so perform action and remove from list. + Log::Write(LogLevel_Info, "Timer: delayed event"); + TimerEventEntry *te = *(it++); + te->instance->TimerFireEvent(te); + } + else + { + // Time remaining. + m_timerTimeout = (m_timerTimeout == Internal::Platform::Wait::Timeout_Infinite) ? tr : std::min(m_timerTimeout, tr); + ++it; + } + } + m_timerEvent->Reset(); } - } - m_timerEvent->Reset(); + } // while( 1 ) } - } // while( 1 ) -} //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- -TimerThread::TimerEventEntry* TimerThread::TimerSetEvent -( - int32 _milliseconds, - TimerCallback _callback, - Timer *_instance, - uint32 id -) -{ - Log::Write( LogLevel_Info, "Timer: adding event in %d ms", _milliseconds ); - TimerEventEntry *te = new TimerEventEntry(); - te->timestamp.SetTime(_milliseconds); - te->callback = _callback; - te->instance = _instance; - te->id = id; - // Don't want driver thread and timer thread accessing list at the same time. - LockGuard LG(m_timerMutex); - m_timerEventList.push_back(te); - m_timerEvent->Set(); - return te; -} + TimerThread::TimerEventEntry* TimerThread::TimerSetEvent(int32 _milliseconds, TimerCallback _callback, Timer *_instance, uint32 id) + { + Log::Write(LogLevel_Info, "Timer: adding event in %d ms", _milliseconds); + TimerEventEntry *te = new TimerEventEntry(); + te->timestamp.SetTime(_milliseconds); + te->callback = _callback; + te->instance = _instance; + te->id = id; + // Don't want driver thread and timer thread accessing list at the same time. + LockGuard LG(m_timerMutex); + m_timerEventList.push_back(te); + m_timerEvent->Set(); + return te; + } //----------------------------------------------------------------------------- // // Delete the Specific Timer //----------------------------------------------------------------------------- -void TimerThread::TimerDelEvent -( - TimerEventEntry *te -) -{ - LockGuard LG(m_timerMutex); - list::iterator it = find(m_timerEventList.begin(),m_timerEventList.end(), te); - if (it != m_timerEventList.end()) { - delete ((*it)); - m_timerEventList.erase(it); - } else { - Log::Write(LogLevel_Warning, "Cant Find TimerEvent to Delete in TimerDelEvent"); - } -} + void TimerThread::TimerDelEvent(TimerEventEntry *te) + { + LockGuard LG(m_timerMutex); + list::iterator it = find(m_timerEventList.begin(), m_timerEventList.end(), te); + if (it != m_timerEventList.end()) + { + delete ((*it)); + m_timerEventList.erase(it); + } + else + { + Log::Write(LogLevel_Warning, "Cant Find TimerEvent to Delete in TimerDelEvent"); + } + } //----------------------------------------------------------------------------- // // Constuctor for Timer SubClass with Driver passed in //----------------------------------------------------------------------------- -Timer::Timer -( - Driver *_driver -): -m_driver(_driver) -{ -}; + Timer::Timer(Driver *_driver) : + m_driver(_driver) + { + } + ; //----------------------------------------------------------------------------- // // Default Constuctor for Timer SubClass //----------------------------------------------------------------------------- -Timer::Timer -( -): -m_driver(NULL) -{ + Timer::Timer() : + m_driver(NULL) + { -}; + } + ; //----------------------------------------------------------------------------- // // Deconstuctor for Timer SubClass //----------------------------------------------------------------------------- -Timer::~Timer -( -) -{ - TimerDelEvents(); -} + Timer::~Timer() + { + TimerDelEvents(); + } //----------------------------------------------------------------------------- // // Create a new TimerCallback //----------------------------------------------------------------------------- -TimerThread::TimerEventEntry* Timer::TimerSetEvent -( - int32 _milliseconds, - TimerThread::TimerCallback _callback, - uint32 id -) -{ - if (m_driver) { - TimerThread::TimerEventEntry *te = m_driver->GetTimer()->TimerSetEvent(_milliseconds, _callback, this, id); - if (te) { - m_timerEventList.push_back(te); - return te; + TimerThread::TimerEventEntry* Timer::TimerSetEvent(int32 _milliseconds, TimerThread::TimerCallback _callback, uint32 id) + { + if (m_driver) + { + TimerThread::TimerEventEntry *te = m_driver->GetTimer()->TimerSetEvent(_milliseconds, _callback, this, id); + if (te) + { + m_timerEventList.push_back(te); + return te; + } + Log::Write(LogLevel_Warning, "Could Not Register Timer Callback"); + return NULL; + } + else + { + Log::Write(LogLevel_Warning, "Driver Not Set for TimerThread"); + return NULL; + } } - Log::Write(LogLevel_Warning, "Could Not Register Timer Callback"); - return NULL; - } else { - Log::Write(LogLevel_Warning, "Driver Not Set for TimerThread"); - return NULL; - } -} //----------------------------------------------------------------------------- // // Delete all TimerEvents associated with this instance //----------------------------------------------------------------------------- -void Timer::TimerDelEvents -( -) -{ - if (m_driver) { - list::iterator it = m_timerEventList.begin(); - while( it != m_timerEventList.end() ) { - m_driver->GetTimer()->TimerDelEvent((*it)); - it = m_timerEventList.erase(it); - } - } else { - Log::Write(LogLevel_Warning, "Driver Not Set for Timer"); - } + void Timer::TimerDelEvents() + { + if (m_driver) + { + list::iterator it = m_timerEventList.begin(); + while (it != m_timerEventList.end()) + { + m_driver->GetTimer()->TimerDelEvent((*it)); + it = m_timerEventList.erase(it); + } + } + else + { + Log::Write(LogLevel_Warning, "Driver Not Set for Timer"); + } -} + } //----------------------------------------------------------------------------- // // Associate this instance with a Driver //----------------------------------------------------------------------------- -void Timer::SetDriver -( - Driver *_driver -) -{ - m_driver = _driver; -} + void Timer::SetDriver(Driver *_driver) + { + m_driver = _driver; + } //----------------------------------------------------------------------------- // // Delete a specific TimerEvent //----------------------------------------------------------------------------- -void Timer::TimerDelEvent -( - TimerThread::TimerEventEntry *te -) -{ - if (m_driver) { - list::iterator it = find(m_timerEventList.begin(),m_timerEventList.end(), te); - if (it != m_timerEventList.end()) { - m_driver->GetTimer()->TimerDelEvent((*it)); - m_timerEventList.erase(it); - } else { - Log::Write(LogLevel_Warning, "Cant Find TimerEvent to Delete in TimerDelEvent"); - } - } else { - Log::Write(LogLevel_Warning, "Driver Not Set for Timer"); - return; - } + void Timer::TimerDelEvent(TimerThread::TimerEventEntry *te) + { + if (m_driver) + { + list::iterator it = find(m_timerEventList.begin(), m_timerEventList.end(), te); + if (it != m_timerEventList.end()) + { + m_driver->GetTimer()->TimerDelEvent((*it)); + m_timerEventList.erase(it); + } + else + { + Log::Write(LogLevel_Warning, "Cant Find TimerEvent to Delete in TimerDelEvent"); + } + } + else + { + Log::Write(LogLevel_Warning, "Driver Not Set for Timer"); + return; + } -} + } //----------------------------------------------------------------------------- // // Delete a specific TimerEvent //----------------------------------------------------------------------------- -void Timer::TimerDelEvent -( - uint32 id -) -{ - if (m_driver) { - for (list::iterator it = m_timerEventList.begin(); it != m_timerEventList.end(); it++ ) { - if ((*it)->id == id) { - m_driver->GetTimer()->TimerDelEvent((*it)); - m_timerEventList.erase(it); + void Timer::TimerDelEvent(uint32 id) + { + if (m_driver) + { + for (list::iterator it = m_timerEventList.begin(); it != m_timerEventList.end(); it++) + { + if ((*it)->id == id) + { + m_driver->GetTimer()->TimerDelEvent((*it)); + m_timerEventList.erase(it); + return; + } + } + Log::Write(LogLevel_Warning, "Cant Find TimerEvent %d to Delete in TimerDelEvent", id); + return; + } + else + { + Log::Write(LogLevel_Warning, "Driver Not Set for TimerThread"); return; } - } - Log::Write(LogLevel_Warning, "Cant Find TimerEvent %d to Delete in TimerDelEvent", id); - return; - } else { - Log::Write(LogLevel_Warning, "Driver Not Set for TimerThread"); - return; - } -} + } //----------------------------------------------------------------------------- // // Execute a Callback //----------------------------------------------------------------------------- -void Timer::TimerFireEvent -( - TimerThread::TimerEventEntry *te -) -{ - te->callback(te->id); - TimerDelEvent(te); -} - + void Timer::TimerFireEvent(TimerThread::TimerEventEntry *te) + { + te->callback(te->id); + TimerDelEvent(te); + } + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/TimerThread.h b/cpp/src/TimerThread.h index 4c9e2b3d7b..a0960b369a 100644 --- a/cpp/src/TimerThread.h +++ b/cpp/src/TimerThread.h @@ -46,140 +46,139 @@ using std::tr1::function; namespace OpenZWave { class Driver; - class Thread; - class Timer; - - /** \brief The TimerThread class makes it possible to schedule events to happen - * at a certain time in the future. - */ - class OPENZWAVE_EXPORT TimerThread + namespace Internal { - friend class Timer; - //----------------------------------------------------------------------------- - // Timer based actions - //----------------------------------------------------------------------------- - public: - /** A timer callback function. */ - typedef function TimerCallback; - - /** - * Constructor. - */ - TimerThread( Driver *_driver ); - - /** - * Destructor. + class Timer; + /** \brief The TimerThread class makes it possible to schedule events to happen + * at a certain time in the future. */ - ~TimerThread(); - - struct TimerEventEntry + class OPENZWAVE_EXPORT TimerThread { - Timer *instance; - TimeStamp timestamp; - TimerCallback callback; - uint32 id; + friend class Timer; + //----------------------------------------------------------------------------- + // Timer based actions + //----------------------------------------------------------------------------- + public: + /** A timer callback function. */ + typedef function TimerCallback; + + /** + * Constructor. + */ + TimerThread(Driver *_driver); + + /** + * Destructor. + */ + ~TimerThread(); + + struct TimerEventEntry + { + Timer *instance; + Internal::Platform::TimeStamp timestamp; + TimerCallback callback; + uint32 id; + }; + + /** + * Main entry point for the timer thread. Wrapper around TimerThreadProc. + * \param _exitEvent Exit event indicating the thread should exit + * \param _context A TimerThread object + */ + static void TimerThreadEntryPoint(Internal::Platform::Event* _exitEvent, void* _context); + + private: + //Driver* m_driver; + + /** + * Schedule an event. + * \param _milliseconds The number of milliseconds before the event should happen + * \param _callback The function to be called when the time is reached + * \param _instance The Timer SubClass where this Event should be executed from + */ + TimerEventEntry* TimerSetEvent(int32 _milliseconds, TimerCallback _callback, Timer *_instance, uint32 id); + + /** + * Remove a Event + * + */ + void TimerDelEvent(TimerEventEntry *); + + /** + * Main class entry point for the timer thread. Contains the main timer loop. + * \param _exitEvent Exit event indicating the thread should exit + */ + void TimerThreadProc(Internal::Platform::Event* _exitEvent); + + /** A list of upcoming timer events */ + list m_timerEventList; + + Internal::Platform::Event* m_timerEvent; // Event to signal new timed action requested + Internal::Platform::Mutex* m_timerMutex; // Serialize access to class members + int32 m_timerTimeout; // Time in milliseconds to wait until next event }; /** - * Main entry point for the timer thread. Wrapper around TimerThreadProc. - * \param _exitEvent Exit event indicating the thread should exit - * \param _context A TimerThread object - */ - static void TimerThreadEntryPoint( Event* _exitEvent, void* _context ); - - private: - //Driver* m_driver; - - /** - * Schedule an event. - * \param _milliseconds The number of milliseconds before the event should happen - * \param _callback The function to be called when the time is reached - * \param _instance The Timer SubClass where this Event should be executed from - */ - TimerEventEntry* TimerSetEvent( int32 _milliseconds, TimerCallback _callback, Timer *_instance, uint32 id ); - - /** - * Remove a Event + * \brief Timer SubClass for automatically registering/unregistering Timer Callbacks + * if the instance goes out of scope * */ - void TimerDelEvent(TimerEventEntry *); - - /** - * Main class entry point for the timer thread. Contains the main timer loop. - * \param _exitEvent Exit event indicating the thread should exit - */ - void TimerThreadProc( Event* _exitEvent ); - - - /** A list of upcoming timer events */ - list m_timerEventList; - - Event* m_timerEvent; // Event to signal new timed action requested - Mutex* m_timerMutex; // Serialize access to class members - int32 m_timerTimeout; // Time in milliseconds to wait until next event - }; - - /** - * \brief Timer SubClass for automatically registering/unregistering Timer Callbacks - * if the instance goes out of scope - * - */ - - class OPENZWAVE_EXPORT Timer - { - public: - /** - * \brief Constructor with the _driver this instance is associated with - * \param _driver The Driver that this instance is associated with - */ - Timer( Driver *_driver ); - /** - * \brief Default Constructor - */ - - Timer(); - /** - * \brief Destructor - */ - ~Timer(); - /** - * \brief Schedule an event. - * \param _milliseconds The number of milliseconds before the event should happen - * \param _callback The function to be called when the time is reached - * \param _id The ID of the Timer - */ - TimerThread::TimerEventEntry* TimerSetEvent( int32 _milliseconds, TimerThread::TimerCallback _callback, uint32 id ); - /** - * \brief Delete All Events registered to this instance - */ - void TimerDelEvents(); - /** - * \brief Delete a Specific Event Registered to this instance - * \param te The TimerEventEntry Struct that was returned when Setting a Event - */ - void TimerDelEvent(TimerThread::TimerEventEntry *te); - /** - * \brief Delete a Specific Event Registered to this instance - * \param id The ID of the Timer To Delete - */ - void TimerDelEvent(uint32 id); - - /** - * \brief Register the Driver Associated with this Instance - * \param _driver The Driver - */ - void SetDriver(Driver *_driver); - /** - * \brief Called From the TimerThread Class to execute a callback - * \param te The TimerEventEntry structure for the callback to execute - */ - void TimerFireEvent(TimerThread::TimerEventEntry *te); - private: - Driver* m_driver; - list m_timerEventList; + class OPENZWAVE_EXPORT Timer + { + public: + /** + * \brief Constructor with the _driver this instance is associated with + * \param _driver The Driver that this instance is associated with + */ + Timer(Driver *_driver); + /** + * \brief Default Constructor + */ + + Timer(); + /** + * \brief Destructor + */ + ~Timer(); + /** + * \brief Schedule an event. + * \param _milliseconds The number of milliseconds before the event should happen + * \param _callback The function to be called when the time is reached + * \param _id The ID of the Timer + */ + TimerThread::TimerEventEntry* TimerSetEvent(int32 _milliseconds, TimerThread::TimerCallback _callback, uint32 id); + /** + * \brief Delete All Events registered to this instance + */ + void TimerDelEvents(); + /** + * \brief Delete a Specific Event Registered to this instance + * \param te The TimerEventEntry Struct that was returned when Setting a Event + */ + void TimerDelEvent(TimerThread::TimerEventEntry *te); + /** + * \brief Delete a Specific Event Registered to this instance + * \param id The ID of the Timer To Delete + */ + void TimerDelEvent(uint32 id); + + /** + * \brief Register the Driver Associated with this Instance + * \param _driver The Driver + */ + void SetDriver(Driver *_driver); + /** + * \brief Called From the TimerThread Class to execute a callback + * \param te The TimerEventEntry structure for the callback to execute + */ + void TimerFireEvent(TimerThread::TimerEventEntry *te); + private: + Driver* m_driver; + list m_timerEventList; - }; + }; + } // namespace Internal } // namespace OpenZWave #endif // _TIMERTHREAD_H_ diff --git a/cpp/src/Utils.cpp b/cpp/src/Utils.cpp index 8e564bad25..ed229685e5 100644 --- a/cpp/src/Utils.cpp +++ b/cpp/src/Utils.cpp @@ -25,178 +25,195 @@ // //----------------------------------------------------------------------------- - #include "Defs.h" #include "Utils.h" +#include -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { //----------------------------------------------------------------------------- // // Convert a string to all upper-case. //----------------------------------------------------------------------------- -string OpenZWave::ToUpper -( - string const& _str -) -{ - string upper = _str; - transform( upper.begin(), upper.end(), upper.begin(), ::toupper ); - return upper; -} + std::string ToUpper(std::string const& _str) + { + std::string upper = _str; + transform(upper.begin(), upper.end(), upper.begin(), ::toupper); + return upper; + } //----------------------------------------------------------------------------- // // Convert a string to all lower-case. //----------------------------------------------------------------------------- -string OpenZWave::ToLower -( - string const& _str -) -{ - string lower = _str; - transform( lower.begin(), lower.end(), lower.begin(), ::tolower ); - return lower; -} + std::string ToLower(std::string const& _str) + { + std::string lower = _str; + transform(lower.begin(), lower.end(), lower.begin(), ::tolower); + return lower; + } //----------------------------------------------------------------------------- // // Remove WhiteSpaces from the begining and end of a string //----------------------------------------------------------------------------- -std::string &OpenZWave::trim -( - std::string &s -) -{ - if(s.size() == 0) - { - return s; - } + std::string &removewhitespace(std::string &s) + { + if (s.size() == 0) + { + return s; + } - int val = 0; - for (size_t cur = 0; cur < s.size(); cur++) - { - if(s[cur] != ' ' && isalnum(s[cur])) + int val = 0; + for (size_t cur = 0; cur < s.size(); cur++) + { + if (s[cur] != ' ' && isalnum(s[cur])) + { + s[val] = s[cur]; + val++; + } + } + s.resize(val); + return s; + } + + std::string& ltrim(std::string& s) { - s[val] = s[cur]; - val++; + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char c) + { return isgraph(c);})); + return s; + } + + std::string& rtrim(std::string& s) + { + s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char c) + { return isgraph(c);}).base(), s.end()); + return s; } - } - s.resize(val); - return s; -} + std::string& trim(std::string& s) + { + return Internal::ltrim(Internal::rtrim(s)); + } //----------------------------------------------------------------------------- // // Split a String into a vector, seperated by anything specified in seperators. //----------------------------------------------------------------------------- -void OpenZWave::split -( - std::vector& lst, - const std::string& input, - const std::string& separators, - bool remove_empty -) -{ - std::ostringstream word; - for (size_t n = 0; n < input.size(); ++n) - { - if (std::string::npos == separators.find(input[n])) - word << input[n]; - else + void split(std::vector& lst, const std::string& input, const std::string& separators, bool remove_empty) { + std::ostringstream word; + for (size_t n = 0; n < input.size(); ++n) + { + if (std::string::npos == separators.find(input[n])) + word << input[n]; + else + { + if (!word.str().empty() || !remove_empty) + lst.push_back(word.str()); + word.str(""); + } + } if (!word.str().empty() || !remove_empty) lst.push_back(word.str()); - word.str(""); } - } - if (!word.str().empty() || !remove_empty) - lst.push_back(word.str()); -} -void OpenZWave::PrintHex(std::string prefix, uint8_t const *data, uint32 const length) { - Log::Write(LogLevel_Info, "%s: %s", prefix.c_str(), PktToString(data, length).c_str()); -} - -string OpenZWave::PktToString(uint8 const *data, uint32 const length) { - char byteStr[5]; - std::string str; - for( uint32 i=0; i( ( std::ostringstream() << std::dec << x ) ).str(); + return static_cast< std::ostringstream & >( ( std::ostringstream() << std::dec << x ) ).str(); #endif -} + } -const char* OpenZWave::rssi_to_string(uint8 _data) { - static char buf[8]; + const char* rssi_to_string(uint8 _data) + { + static char buf[8]; - switch (_data) { - case 127: { - return "---"; - break; - } - case 126: { - return "MAX"; - break; - } - case 125: { - return "MIN"; - break; - } - default: - if (_data >= 11 && _data <= 124) - { - return "UNK"; - } - else + switch (_data) { - snprintf(buf, 5, "%4d", (unsigned int)_data - 256); - return buf; + case 127: + { + return "---"; + break; + } + case 126: + { + return "MAX"; + break; + } + case 125: + { + return "MIN"; + break; + } + default: + if (_data >= 11 && _data <= 124) + { + return "UNK"; + } + else + { + snprintf(buf, 5, "%4d", (unsigned int) _data - 256); + return buf; + } } - } -} + } + } // namespace Internal +} // namespace OpenZWave + #if (defined _WINDOWS || defined WIN32 || defined _MSC_VER) && (!defined MINGW && !defined __MINGW32__ && !defined __MINGW64__) /* Windows doesn't have localtime_r - use the "secure" version instead */ -struct tm *localtime_r(time_t *_clock, struct tm *_result) +struct tm *localtime_r(const time_t *_clock, struct tm *_result) { _localtime64_s(_result, _clock); return _result; } -#endif \ No newline at end of file +#endif + diff --git a/cpp/src/Utils.h b/cpp/src/Utils.h index fb89c7144b..33977eb3d9 100644 --- a/cpp/src/Utils.h +++ b/cpp/src/Utils.h @@ -36,92 +36,233 @@ #include #include #include +#ifndef WIN32 +#ifndef WINRT +#ifdef DEBUG +#include +#include +#endif +#endif +#endif namespace OpenZWave { - /** - * Convert a string to all upper-case. - * \param _str the string to be converted. - * \return the upper-case string. - * \see ToLower, Trim - */ - string ToUpper( string const& _str ); - - /** - * Convert a string to all lower-case. - * \param _str the string to be converted. - * \return the lower-case string. - * \see ToUpper, Trim - */ - string ToLower( string const& _str ); - - /** - * Split a String into a Vector, separated by separators - * \param lst the vector to store the results in - * \param input the input string to split - * \param separators a string containing a list of valid separators - * \param remove_empty if after splitting a string, the any of the results are a empty string, should we preserve them or not - */ - void split (std::vector& lst, const std::string& input, const std::string& separators, bool remove_empty = true); - - /** - * Trim Whitespace from the start and end of a string. - * \param s the string to trim - * \return the trimmed string - */ - std::string &trim ( std::string &s ); - - - void PrintHex(std::string prefix, uint8_t const *data, uint32 const length); - string PktToString(uint8 const *data, uint32 const length); - - struct LockGuard + namespace Internal { - LockGuard(Mutex* mutex) : _ref(mutex) - { - //std::cout << "Locking" << std::endl; - _ref->Lock(); - }; - - ~LockGuard() - { + /** + * Convert a string to all upper-case. + * \param _str the string to be converted. + * \return the upper-case string. + * \see ToLower, Trim + */ + std::string ToUpper(string const& _str); + + /** + * Convert a string to all lower-case. + * \param _str the string to be converted. + * \return the lower-case string. + * \see ToUpper, Trim + */ + std::string ToLower(string const& _str); + + /** + * Split a String into a Vector, separated by separators + * \param lst the vector to store the results in + * \param input the input string to split + * \param separators a string containing a list of valid separators + * \param remove_empty if after splitting a string, the any of the results are a empty string, should we preserve them or not + */ + void split(std::vector& lst, const std::string& input, const std::string& separators, bool remove_empty = true); + + /** + * remove all Whitespace from of a string. + * \param s the string to trim + * \return the trimmed string + */ + std::string &removewhitespace(std::string &s); + + /** + * @brief Left Trim + * + * Trims whitespace from the left end of the provided std::string + * + * @param[out] s The std::string to trim + * + * @return The modified std::string& + */ + std::string& ltrim(std::string& s); + + /** + * @brief Right Trim + * + * Trims whitespace from the right end of the provided std::string + * + * @param[out] s The std::string to trim + * + * @return The modified std::string& + */ + std::string& rtrim(std::string& s); + + /** + * @brief Trim + * + * Trims whitespace from both ends of the provided std::string + * + * @param[out] s The std::string to trim + * + * @return The modified std::string& + */ + std::string& trim(std::string& s); + + void PrintHex(std::string prefix, uint8_t const *data, uint32 const length); + string PktToString(uint8 const *data, uint32 const length); + + struct LockGuard + { + LockGuard(Internal::Platform::Mutex* mutex) : + _ref(mutex) + { + //std::cout << "Locking" << std::endl; + _ref->Lock(); + } + ; + + ~LockGuard() + { #if 0 - if (_ref->IsSignalled()) + if (_ref->IsSignalled()) std::cout << "Already Unlocked" << std::endl; - else + else std::cout << "Unlocking" << std::endl; #endif - if (!_ref->IsSignalled()) - _ref->Unlock(); - } - void Unlock() - { + if (!_ref->IsSignalled()) + _ref->Unlock(); + } + void Unlock() + { // std::cout << "Unlocking" << std::endl; - _ref->Unlock(); - } + _ref->Unlock(); + } + private: + LockGuard(const LockGuard&); + LockGuard& operator =(LockGuard const&); + + Internal::Platform::Mutex* _ref; + }; + + string ozwdirname(string); + + string intToString(int x); + + const char* rssi_to_string(uint8 _data); + +#ifndef WIN32 +#ifndef WINRT +#ifdef DEBUG + class StackTraceGenerator + { private: - LockGuard(const LockGuard&); - LockGuard& operator = ( LockGuard const& ); + // this is a pure utils class + // cannot be instantiated + // + StackTraceGenerator() = delete; + StackTraceGenerator(const StackTraceGenerator&) = delete; + StackTraceGenerator& operator=(const StackTraceGenerator&) = delete; + ~StackTraceGenerator() = delete; + + public: + + static std::vector GetTrace() + { + // record stack trace upto 128 frames + int callstack[128] = {}; + + // collect stack frames + int frames = backtrace((void**) callstack, 5); + + // get the human-readable symbols (mangled) + char** strs = backtrace_symbols((void**) callstack, frames); + + std::vector stackFrames; + stackFrames.reserve(frames); + + for (int i = 2; i < frames; ++i) + { + char functionSymbol[1024] = {}; + char moduleName[1024] = {}; + int offset = 0; + char addr[48] = {}; + + /* + + Typically this is how the backtrace looks like: - Mutex* _ref; - }; + 0 0x0000000100000e98 _Z5tracev + 72 + 1 0x00000001000015c1 _ZNK7functorclEv + 17 + 2 0x0000000100000f71 _Z3fn0v + 17 + 3 0x0000000100000f89 _Z3fn1v + 9 + 4 0x0000000100000f99 _Z3fn2v + 9 + 5 0x0000000100000fa9 _Z3fn3v + 9 + 6 0x0000000100000fb9 _Z3fn4v + 9 + 7 0x0000000100000fc9 _Z3fn5v + 9 + 8 0x0000000100000fd9 _Z3fn6v + 9 + 9 0x0000000100001018 main + 56 + 10 libdyld.dylib 0x00007fff91b647e1 start + 0 - string ozwdirname(string); + */ - string intToString( int x ); + // split the string, take out chunks out of stack trace + // we are primarily interested in module, function and address + sscanf(strs[i], "%*s %s %s %s %*s %d", + moduleName, addr, functionSymbol, &offset); - const char* rssi_to_string(uint8 _data); + int validCppName = 0; + // if this is a C++ library, symbol will be demangled + // on success function returns 0 + // + char* functionName = abi::__cxa_demangle(functionSymbol, + NULL, 0, &validCppName); + + char stackFrame[4096] = {}; + if (validCppName == 0) // success + { + sprintf(stackFrame, "(%s)\t0x%s — %s + %d", + moduleName, addr, functionName, offset); + } + else + { + // in the above traceback (in comments) last entry is not + // from C++ binary, last frame, libdyld.dylib, is printed + // from here + sprintf(stackFrame, "(%s)\t0x%s — %s + %d", + moduleName, addr, functionName, offset); + } + + if (functionName) + { + free(functionName); + } + Log::Write(LogLevel_Warning, "Stack: %s", stackFrame); + std::string frameStr(stackFrame); + stackFrames.push_back(frameStr); + } + free(strs); + + return stackFrames; + } + }; +#endif +#endif +#endif + } // namespace Internal } // namespace OpenZWave /* keep this outside of the namespace */ #if (defined _WINDOWS || defined WIN32 || defined _MSC_VER) && (!defined MINGW && !defined __MINGW32__ && !defined __MINGW64__) #include - struct tm *localtime_r(time_t *_clock, struct tm *_result); +struct tm *localtime_r(const time_t *_clock, struct tm *_result); #endif - #endif - - diff --git a/cpp/src/ValueIDIndexes.h b/cpp/src/ValueIDIndexes.h new file mode 100644 index 0000000000..0535cff89a --- /dev/null +++ b/cpp/src/ValueIDIndexes.h @@ -0,0 +1,49 @@ +//----------------------------------------------------------------------------- +// +// ValueIDIndexes.h +// +// List of all Possible ValueID Indexes in OZW +// +// Copyright (c) 2010 Mal Lansell +// +// SOFTWARE NOTICE AND LICENSE +// +// This file is part of OpenZWave. +// +// OpenZWave is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, either version 3 of the License, +// or (at your option) any later version. +// +// OpenZWave is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with OpenZWave. If not, see . +// +//----------------------------------------------------------------------------- + +/* This file is includes the pre-processed ValueIDIndexesDefines.h to avoid problems + * with MSVC not supporting enough arguments with Macro's. + * If you are adding a ValueID, you should add its index ENUM to ValuIDIndexDefines.def and the run + * 'make updateIndexDefines' to regenerate the the ValueIDIndexDefines.h file + */ + +#include + +#ifndef _ValueIDIndexes_H +#define _ValueIDIndexes_H +namespace OpenZWave +{ + +#ifdef _MSC_VER +#define strncpy(x, y, z) strncpy_s(x, sizeof(x), y, sizeof(x)-1) +#endif + +#include "ValueIDIndexesDefines.h" + +} + +#endif diff --git a/cpp/src/ValueIDIndexesDefines.def b/cpp/src/ValueIDIndexesDefines.def new file mode 100644 index 0000000000..dc099f05fd --- /dev/null +++ b/cpp/src/ValueIDIndexesDefines.def @@ -0,0 +1,3369 @@ +//----------------------------------------------------------------------------- +// +// ValueIDIndexes.h +// +// List of all Possible ValueID Indexes in OZW +// +// Copyright (c) 2010 Mal Lansell +// +// SOFTWARE NOTICE AND LICENSE +// +// This file is part of OpenZWave. +// +// OpenZWave is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, either version 3 of the License, +// or (at your option) any later version. +// +// OpenZWave is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with OpenZWave. If not, see . +// +//----------------------------------------------------------------------------- + + + +/* This file is run through the preprocessor and output to ValueIDIndexesDefines.h to avoid problems + * with MSVC not supporting enough arguments with Macro's. + * If you are adding a ValueID, you should add its index ENUM to ValuIDIndexDefines.def and the run + * 'make updateIndexDefines' to regenerate the the ValueIDIndexDefines.h file + * Obviously the regeneration will not work on MSVC, so you need clang or gnugcc to do the preprocessing + * how to do that is left to the reader to figure out on Windows. On Unix and Mac, as long as the compiler + * supports more than 512 Macro arguements, all should be good. + * + * This also has the nice side benefit in that we only have to do the pre-processing once, and the output is + * included into all the files that include ValueIDIndexes.h without having to process it again + */ + + + +#ifndef _ValueIDIndexesDefines_H +#define _ValueIDIndexesDefines_H + + + +/* this is good for upto 768 entries per ENUM. I shall predict that 768 entries shall be enough for any CommandClass :) */ + +#define MAP(macro, ...) \ + IDENTITY( \ + APPLY(CHOOSE_MAP_START, COUNT(__VA_ARGS__)) \ + (macro, __VA_ARGS__)) + +#define CHOOSE_MAP_START(count) MAP ## count + +#define APPLY(macro, ...) IDENTITY(macro(__VA_ARGS__)) + +// Needed to expand __VA_ARGS__ "eagerly" on the MSVC preprocessor. +#define IDENTITY(x) x + +#define MAP1(m, x) m(x) +#define MAP2(m, x, ...) m(x) IDENTITY(MAP1(m, __VA_ARGS__)) +#define MAP3(m, x, ...) m(x) IDENTITY(MAP2(m, __VA_ARGS__)) +#define MAP4(m, x, ...) m(x) IDENTITY(MAP3(m, __VA_ARGS__)) +#define MAP5(m, x, ...) m(x) IDENTITY(MAP4(m, __VA_ARGS__)) +#define MAP6(m, x, ...) m(x) IDENTITY(MAP5(m, __VA_ARGS__)) +#define MAP7(m, x, ...) m(x) IDENTITY(MAP6(m, __VA_ARGS__)) +#define MAP8(m, x, ...) m(x) IDENTITY(MAP7(m, __VA_ARGS__)) +#define MAP9(m, x, ...) m(x) IDENTITY(MAP8(m, __VA_ARGS__)) +#define MAP10(m, x, ...) m(x) IDENTITY(MAP9(m, __VA_ARGS__)) +#define MAP11(m, x, ...) m(x) IDENTITY(MAP10(m, __VA_ARGS__)) +#define MAP12(m, x, ...) m(x) IDENTITY(MAP11(m, __VA_ARGS__)) +#define MAP13(m, x, ...) m(x) IDENTITY(MAP12(m, __VA_ARGS__)) +#define MAP14(m, x, ...) m(x) IDENTITY(MAP13(m, __VA_ARGS__)) +#define MAP15(m, x, ...) m(x) IDENTITY(MAP14(m, __VA_ARGS__)) +#define MAP16(m, x, ...) m(x) IDENTITY(MAP15(m, __VA_ARGS__)) +#define MAP17(m, x, ...) m(x) IDENTITY(MAP16(m, __VA_ARGS__)) +#define MAP18(m, x, ...) m(x) IDENTITY(MAP17(m, __VA_ARGS__)) +#define MAP19(m, x, ...) m(x) IDENTITY(MAP18(m, __VA_ARGS__)) +#define MAP20(m, x, ...) m(x) IDENTITY(MAP19(m, __VA_ARGS__)) +#define MAP21(m, x, ...) m(x) IDENTITY(MAP20(m, __VA_ARGS__)) +#define MAP22(m, x, ...) m(x) IDENTITY(MAP21(m, __VA_ARGS__)) +#define MAP23(m, x, ...) m(x) IDENTITY(MAP22(m, __VA_ARGS__)) +#define MAP24(m, x, ...) m(x) IDENTITY(MAP23(m, __VA_ARGS__)) +#define MAP25(m, x, ...) m(x) IDENTITY(MAP24(m, __VA_ARGS__)) +#define MAP26(m, x, ...) m(x) IDENTITY(MAP25(m, __VA_ARGS__)) +#define MAP27(m, x, ...) m(x) IDENTITY(MAP26(m, __VA_ARGS__)) +#define MAP28(m, x, ...) m(x) IDENTITY(MAP27(m, __VA_ARGS__)) +#define MAP29(m, x, ...) m(x) IDENTITY(MAP28(m, __VA_ARGS__)) +#define MAP30(m, x, ...) m(x) IDENTITY(MAP29(m, __VA_ARGS__)) +#define MAP31(m, x, ...) m(x) IDENTITY(MAP30(m, __VA_ARGS__)) +#define MAP32(m, x, ...) m(x) IDENTITY(MAP31(m, __VA_ARGS__)) +#define MAP33(m, x, ...) m(x) IDENTITY(MAP32(m, __VA_ARGS__)) +#define MAP34(m, x, ...) m(x) IDENTITY(MAP33(m, __VA_ARGS__)) +#define MAP35(m, x, ...) m(x) IDENTITY(MAP34(m, __VA_ARGS__)) +#define MAP36(m, x, ...) m(x) IDENTITY(MAP35(m, __VA_ARGS__)) +#define MAP37(m, x, ...) m(x) IDENTITY(MAP36(m, __VA_ARGS__)) +#define MAP38(m, x, ...) m(x) IDENTITY(MAP37(m, __VA_ARGS__)) +#define MAP39(m, x, ...) m(x) IDENTITY(MAP38(m, __VA_ARGS__)) +#define MAP40(m, x, ...) m(x) IDENTITY(MAP39(m, __VA_ARGS__)) +#define MAP41(m, x, ...) m(x) IDENTITY(MAP40(m, __VA_ARGS__)) +#define MAP42(m, x, ...) m(x) IDENTITY(MAP41(m, __VA_ARGS__)) +#define MAP43(m, x, ...) m(x) IDENTITY(MAP42(m, __VA_ARGS__)) +#define MAP44(m, x, ...) m(x) IDENTITY(MAP43(m, __VA_ARGS__)) +#define MAP45(m, x, ...) m(x) IDENTITY(MAP44(m, __VA_ARGS__)) +#define MAP46(m, x, ...) m(x) IDENTITY(MAP45(m, __VA_ARGS__)) +#define MAP47(m, x, ...) m(x) IDENTITY(MAP46(m, __VA_ARGS__)) +#define MAP48(m, x, ...) m(x) IDENTITY(MAP47(m, __VA_ARGS__)) +#define MAP49(m, x, ...) m(x) IDENTITY(MAP48(m, __VA_ARGS__)) +#define MAP50(m, x, ...) m(x) IDENTITY(MAP49(m, __VA_ARGS__)) +#define MAP51(m, x, ...) m(x) IDENTITY(MAP50(m, __VA_ARGS__)) +#define MAP52(m, x, ...) m(x) IDENTITY(MAP51(m, __VA_ARGS__)) +#define MAP53(m, x, ...) m(x) IDENTITY(MAP52(m, __VA_ARGS__)) +#define MAP54(m, x, ...) m(x) IDENTITY(MAP53(m, __VA_ARGS__)) +#define MAP55(m, x, ...) m(x) IDENTITY(MAP54(m, __VA_ARGS__)) +#define MAP56(m, x, ...) m(x) IDENTITY(MAP55(m, __VA_ARGS__)) +#define MAP57(m, x, ...) m(x) IDENTITY(MAP56(m, __VA_ARGS__)) +#define MAP58(m, x, ...) m(x) IDENTITY(MAP57(m, __VA_ARGS__)) +#define MAP59(m, x, ...) m(x) IDENTITY(MAP58(m, __VA_ARGS__)) +#define MAP60(m, x, ...) m(x) IDENTITY(MAP59(m, __VA_ARGS__)) +#define MAP61(m, x, ...) m(x) IDENTITY(MAP60(m, __VA_ARGS__)) +#define MAP62(m, x, ...) m(x) IDENTITY(MAP61(m, __VA_ARGS__)) +#define MAP63(m, x, ...) m(x) IDENTITY(MAP62(m, __VA_ARGS__)) +#define MAP64(m, x, ...) m(x) IDENTITY(MAP63(m, __VA_ARGS__)) +#define MAP65(m, x, ...) m(x) IDENTITY(MAP64(m, __VA_ARGS__)) +#define MAP66(m, x, ...) m(x) IDENTITY(MAP65(m, __VA_ARGS__)) +#define MAP67(m, x, ...) m(x) IDENTITY(MAP66(m, __VA_ARGS__)) +#define MAP68(m, x, ...) m(x) IDENTITY(MAP67(m, __VA_ARGS__)) +#define MAP69(m, x, ...) m(x) IDENTITY(MAP68(m, __VA_ARGS__)) +#define MAP70(m, x, ...) m(x) IDENTITY(MAP69(m, __VA_ARGS__)) +#define MAP71(m, x, ...) m(x) IDENTITY(MAP70(m, __VA_ARGS__)) +#define MAP72(m, x, ...) m(x) IDENTITY(MAP71(m, __VA_ARGS__)) +#define MAP73(m, x, ...) m(x) IDENTITY(MAP72(m, __VA_ARGS__)) +#define MAP74(m, x, ...) m(x) IDENTITY(MAP73(m, __VA_ARGS__)) +#define MAP75(m, x, ...) m(x) IDENTITY(MAP74(m, __VA_ARGS__)) +#define MAP76(m, x, ...) m(x) IDENTITY(MAP75(m, __VA_ARGS__)) +#define MAP77(m, x, ...) m(x) IDENTITY(MAP76(m, __VA_ARGS__)) +#define MAP78(m, x, ...) m(x) IDENTITY(MAP77(m, __VA_ARGS__)) +#define MAP79(m, x, ...) m(x) IDENTITY(MAP78(m, __VA_ARGS__)) +#define MAP80(m, x, ...) m(x) IDENTITY(MAP79(m, __VA_ARGS__)) +#define MAP81(m, x, ...) m(x) IDENTITY(MAP80(m, __VA_ARGS__)) +#define MAP82(m, x, ...) m(x) IDENTITY(MAP81(m, __VA_ARGS__)) +#define MAP83(m, x, ...) m(x) IDENTITY(MAP82(m, __VA_ARGS__)) +#define MAP84(m, x, ...) m(x) IDENTITY(MAP83(m, __VA_ARGS__)) +#define MAP85(m, x, ...) m(x) IDENTITY(MAP84(m, __VA_ARGS__)) +#define MAP86(m, x, ...) m(x) IDENTITY(MAP85(m, __VA_ARGS__)) +#define MAP87(m, x, ...) m(x) IDENTITY(MAP86(m, __VA_ARGS__)) +#define MAP88(m, x, ...) m(x) IDENTITY(MAP87(m, __VA_ARGS__)) +#define MAP89(m, x, ...) m(x) IDENTITY(MAP88(m, __VA_ARGS__)) +#define MAP90(m, x, ...) m(x) IDENTITY(MAP89(m, __VA_ARGS__)) +#define MAP91(m, x, ...) m(x) IDENTITY(MAP90(m, __VA_ARGS__)) +#define MAP92(m, x, ...) m(x) IDENTITY(MAP91(m, __VA_ARGS__)) +#define MAP93(m, x, ...) m(x) IDENTITY(MAP92(m, __VA_ARGS__)) +#define MAP94(m, x, ...) m(x) IDENTITY(MAP93(m, __VA_ARGS__)) +#define MAP95(m, x, ...) m(x) IDENTITY(MAP94(m, __VA_ARGS__)) +#define MAP96(m, x, ...) m(x) IDENTITY(MAP95(m, __VA_ARGS__)) +#define MAP97(m, x, ...) m(x) IDENTITY(MAP96(m, __VA_ARGS__)) +#define MAP98(m, x, ...) m(x) IDENTITY(MAP97(m, __VA_ARGS__)) +#define MAP99(m, x, ...) m(x) IDENTITY(MAP98(m, __VA_ARGS__)) +#define MAP100(m, x, ...) m(x) IDENTITY(MAP99(m, __VA_ARGS__)) +#define MAP101(m, x, ...) m(x) IDENTITY(MAP100(m, __VA_ARGS__)) +#define MAP102(m, x, ...) m(x) IDENTITY(MAP101(m, __VA_ARGS__)) +#define MAP103(m, x, ...) m(x) IDENTITY(MAP102(m, __VA_ARGS__)) +#define MAP104(m, x, ...) m(x) IDENTITY(MAP103(m, __VA_ARGS__)) +#define MAP105(m, x, ...) m(x) IDENTITY(MAP104(m, __VA_ARGS__)) +#define MAP106(m, x, ...) m(x) IDENTITY(MAP105(m, __VA_ARGS__)) +#define MAP107(m, x, ...) m(x) IDENTITY(MAP106(m, __VA_ARGS__)) +#define MAP108(m, x, ...) m(x) IDENTITY(MAP107(m, __VA_ARGS__)) +#define MAP109(m, x, ...) m(x) IDENTITY(MAP108(m, __VA_ARGS__)) +#define MAP110(m, x, ...) m(x) IDENTITY(MAP109(m, __VA_ARGS__)) +#define MAP111(m, x, ...) m(x) IDENTITY(MAP110(m, __VA_ARGS__)) +#define MAP112(m, x, ...) m(x) IDENTITY(MAP111(m, __VA_ARGS__)) +#define MAP113(m, x, ...) m(x) IDENTITY(MAP112(m, __VA_ARGS__)) +#define MAP114(m, x, ...) m(x) IDENTITY(MAP113(m, __VA_ARGS__)) +#define MAP115(m, x, ...) m(x) IDENTITY(MAP114(m, __VA_ARGS__)) +#define MAP116(m, x, ...) m(x) IDENTITY(MAP115(m, __VA_ARGS__)) +#define MAP117(m, x, ...) m(x) IDENTITY(MAP116(m, __VA_ARGS__)) +#define MAP118(m, x, ...) m(x) IDENTITY(MAP117(m, __VA_ARGS__)) +#define MAP119(m, x, ...) m(x) IDENTITY(MAP118(m, __VA_ARGS__)) +#define MAP120(m, x, ...) m(x) IDENTITY(MAP119(m, __VA_ARGS__)) +#define MAP121(m, x, ...) m(x) IDENTITY(MAP120(m, __VA_ARGS__)) +#define MAP122(m, x, ...) m(x) IDENTITY(MAP121(m, __VA_ARGS__)) +#define MAP123(m, x, ...) m(x) IDENTITY(MAP122(m, __VA_ARGS__)) +#define MAP124(m, x, ...) m(x) IDENTITY(MAP123(m, __VA_ARGS__)) +#define MAP125(m, x, ...) m(x) IDENTITY(MAP124(m, __VA_ARGS__)) +#define MAP126(m, x, ...) m(x) IDENTITY(MAP125(m, __VA_ARGS__)) +#define MAP127(m, x, ...) m(x) IDENTITY(MAP126(m, __VA_ARGS__)) +#define MAP128(m, x, ...) m(x) IDENTITY(MAP127(m, __VA_ARGS__)) +#define MAP129(m, x, ...) m(x) IDENTITY(MAP128(m, __VA_ARGS__)) +#define MAP130(m, x, ...) m(x) IDENTITY(MAP129(m, __VA_ARGS__)) +#define MAP131(m, x, ...) m(x) IDENTITY(MAP130(m, __VA_ARGS__)) +#define MAP132(m, x, ...) m(x) IDENTITY(MAP131(m, __VA_ARGS__)) +#define MAP133(m, x, ...) m(x) IDENTITY(MAP132(m, __VA_ARGS__)) +#define MAP134(m, x, ...) m(x) IDENTITY(MAP133(m, __VA_ARGS__)) +#define MAP135(m, x, ...) m(x) IDENTITY(MAP134(m, __VA_ARGS__)) +#define MAP136(m, x, ...) m(x) IDENTITY(MAP135(m, __VA_ARGS__)) +#define MAP137(m, x, ...) m(x) IDENTITY(MAP136(m, __VA_ARGS__)) +#define MAP138(m, x, ...) m(x) IDENTITY(MAP137(m, __VA_ARGS__)) +#define MAP139(m, x, ...) m(x) IDENTITY(MAP138(m, __VA_ARGS__)) +#define MAP140(m, x, ...) m(x) IDENTITY(MAP139(m, __VA_ARGS__)) +#define MAP141(m, x, ...) m(x) IDENTITY(MAP140(m, __VA_ARGS__)) +#define MAP142(m, x, ...) m(x) IDENTITY(MAP141(m, __VA_ARGS__)) +#define MAP143(m, x, ...) m(x) IDENTITY(MAP142(m, __VA_ARGS__)) +#define MAP144(m, x, ...) m(x) IDENTITY(MAP143(m, __VA_ARGS__)) +#define MAP145(m, x, ...) m(x) IDENTITY(MAP144(m, __VA_ARGS__)) +#define MAP146(m, x, ...) m(x) IDENTITY(MAP145(m, __VA_ARGS__)) +#define MAP147(m, x, ...) m(x) IDENTITY(MAP146(m, __VA_ARGS__)) +#define MAP148(m, x, ...) m(x) IDENTITY(MAP147(m, __VA_ARGS__)) +#define MAP149(m, x, ...) m(x) IDENTITY(MAP148(m, __VA_ARGS__)) +#define MAP150(m, x, ...) m(x) IDENTITY(MAP149(m, __VA_ARGS__)) +#define MAP151(m, x, ...) m(x) IDENTITY(MAP150(m, __VA_ARGS__)) +#define MAP152(m, x, ...) m(x) IDENTITY(MAP151(m, __VA_ARGS__)) +#define MAP153(m, x, ...) m(x) IDENTITY(MAP152(m, __VA_ARGS__)) +#define MAP154(m, x, ...) m(x) IDENTITY(MAP153(m, __VA_ARGS__)) +#define MAP155(m, x, ...) m(x) IDENTITY(MAP154(m, __VA_ARGS__)) +#define MAP156(m, x, ...) m(x) IDENTITY(MAP155(m, __VA_ARGS__)) +#define MAP157(m, x, ...) m(x) IDENTITY(MAP156(m, __VA_ARGS__)) +#define MAP158(m, x, ...) m(x) IDENTITY(MAP157(m, __VA_ARGS__)) +#define MAP159(m, x, ...) m(x) IDENTITY(MAP158(m, __VA_ARGS__)) +#define MAP160(m, x, ...) m(x) IDENTITY(MAP159(m, __VA_ARGS__)) +#define MAP161(m, x, ...) m(x) IDENTITY(MAP160(m, __VA_ARGS__)) +#define MAP162(m, x, ...) m(x) IDENTITY(MAP161(m, __VA_ARGS__)) +#define MAP163(m, x, ...) m(x) IDENTITY(MAP162(m, __VA_ARGS__)) +#define MAP164(m, x, ...) m(x) IDENTITY(MAP163(m, __VA_ARGS__)) +#define MAP165(m, x, ...) m(x) IDENTITY(MAP164(m, __VA_ARGS__)) +#define MAP166(m, x, ...) m(x) IDENTITY(MAP165(m, __VA_ARGS__)) +#define MAP167(m, x, ...) m(x) IDENTITY(MAP166(m, __VA_ARGS__)) +#define MAP168(m, x, ...) m(x) IDENTITY(MAP167(m, __VA_ARGS__)) +#define MAP169(m, x, ...) m(x) IDENTITY(MAP168(m, __VA_ARGS__)) +#define MAP170(m, x, ...) m(x) IDENTITY(MAP169(m, __VA_ARGS__)) +#define MAP171(m, x, ...) m(x) IDENTITY(MAP170(m, __VA_ARGS__)) +#define MAP172(m, x, ...) m(x) IDENTITY(MAP171(m, __VA_ARGS__)) +#define MAP173(m, x, ...) m(x) IDENTITY(MAP172(m, __VA_ARGS__)) +#define MAP174(m, x, ...) m(x) IDENTITY(MAP173(m, __VA_ARGS__)) +#define MAP175(m, x, ...) m(x) IDENTITY(MAP174(m, __VA_ARGS__)) +#define MAP176(m, x, ...) m(x) IDENTITY(MAP175(m, __VA_ARGS__)) +#define MAP177(m, x, ...) m(x) IDENTITY(MAP176(m, __VA_ARGS__)) +#define MAP178(m, x, ...) m(x) IDENTITY(MAP177(m, __VA_ARGS__)) +#define MAP179(m, x, ...) m(x) IDENTITY(MAP178(m, __VA_ARGS__)) +#define MAP180(m, x, ...) m(x) IDENTITY(MAP179(m, __VA_ARGS__)) +#define MAP181(m, x, ...) m(x) IDENTITY(MAP180(m, __VA_ARGS__)) +#define MAP182(m, x, ...) m(x) IDENTITY(MAP181(m, __VA_ARGS__)) +#define MAP183(m, x, ...) m(x) IDENTITY(MAP182(m, __VA_ARGS__)) +#define MAP184(m, x, ...) m(x) IDENTITY(MAP183(m, __VA_ARGS__)) +#define MAP185(m, x, ...) m(x) IDENTITY(MAP184(m, __VA_ARGS__)) +#define MAP186(m, x, ...) m(x) IDENTITY(MAP185(m, __VA_ARGS__)) +#define MAP187(m, x, ...) m(x) IDENTITY(MAP186(m, __VA_ARGS__)) +#define MAP188(m, x, ...) m(x) IDENTITY(MAP187(m, __VA_ARGS__)) +#define MAP189(m, x, ...) m(x) IDENTITY(MAP188(m, __VA_ARGS__)) +#define MAP190(m, x, ...) m(x) IDENTITY(MAP189(m, __VA_ARGS__)) +#define MAP191(m, x, ...) m(x) IDENTITY(MAP190(m, __VA_ARGS__)) +#define MAP192(m, x, ...) m(x) IDENTITY(MAP191(m, __VA_ARGS__)) +#define MAP193(m, x, ...) m(x) IDENTITY(MAP192(m, __VA_ARGS__)) +#define MAP194(m, x, ...) m(x) IDENTITY(MAP193(m, __VA_ARGS__)) +#define MAP195(m, x, ...) m(x) IDENTITY(MAP194(m, __VA_ARGS__)) +#define MAP196(m, x, ...) m(x) IDENTITY(MAP195(m, __VA_ARGS__)) +#define MAP197(m, x, ...) m(x) IDENTITY(MAP196(m, __VA_ARGS__)) +#define MAP198(m, x, ...) m(x) IDENTITY(MAP197(m, __VA_ARGS__)) +#define MAP199(m, x, ...) m(x) IDENTITY(MAP198(m, __VA_ARGS__)) +#define MAP200(m, x, ...) m(x) IDENTITY(MAP199(m, __VA_ARGS__)) +#define MAP201(m, x, ...) m(x) IDENTITY(MAP200(m, __VA_ARGS__)) +#define MAP202(m, x, ...) m(x) IDENTITY(MAP201(m, __VA_ARGS__)) +#define MAP203(m, x, ...) m(x) IDENTITY(MAP202(m, __VA_ARGS__)) +#define MAP204(m, x, ...) m(x) IDENTITY(MAP203(m, __VA_ARGS__)) +#define MAP205(m, x, ...) m(x) IDENTITY(MAP204(m, __VA_ARGS__)) +#define MAP206(m, x, ...) m(x) IDENTITY(MAP205(m, __VA_ARGS__)) +#define MAP207(m, x, ...) m(x) IDENTITY(MAP206(m, __VA_ARGS__)) +#define MAP208(m, x, ...) m(x) IDENTITY(MAP207(m, __VA_ARGS__)) +#define MAP209(m, x, ...) m(x) IDENTITY(MAP208(m, __VA_ARGS__)) +#define MAP210(m, x, ...) m(x) IDENTITY(MAP209(m, __VA_ARGS__)) +#define MAP211(m, x, ...) m(x) IDENTITY(MAP210(m, __VA_ARGS__)) +#define MAP212(m, x, ...) m(x) IDENTITY(MAP211(m, __VA_ARGS__)) +#define MAP213(m, x, ...) m(x) IDENTITY(MAP212(m, __VA_ARGS__)) +#define MAP214(m, x, ...) m(x) IDENTITY(MAP213(m, __VA_ARGS__)) +#define MAP215(m, x, ...) m(x) IDENTITY(MAP214(m, __VA_ARGS__)) +#define MAP216(m, x, ...) m(x) IDENTITY(MAP215(m, __VA_ARGS__)) +#define MAP217(m, x, ...) m(x) IDENTITY(MAP216(m, __VA_ARGS__)) +#define MAP218(m, x, ...) m(x) IDENTITY(MAP217(m, __VA_ARGS__)) +#define MAP219(m, x, ...) m(x) IDENTITY(MAP218(m, __VA_ARGS__)) +#define MAP220(m, x, ...) m(x) IDENTITY(MAP219(m, __VA_ARGS__)) +#define MAP221(m, x, ...) m(x) IDENTITY(MAP220(m, __VA_ARGS__)) +#define MAP222(m, x, ...) m(x) IDENTITY(MAP221(m, __VA_ARGS__)) +#define MAP223(m, x, ...) m(x) IDENTITY(MAP222(m, __VA_ARGS__)) +#define MAP224(m, x, ...) m(x) IDENTITY(MAP223(m, __VA_ARGS__)) +#define MAP225(m, x, ...) m(x) IDENTITY(MAP224(m, __VA_ARGS__)) +#define MAP226(m, x, ...) m(x) IDENTITY(MAP225(m, __VA_ARGS__)) +#define MAP227(m, x, ...) m(x) IDENTITY(MAP226(m, __VA_ARGS__)) +#define MAP228(m, x, ...) m(x) IDENTITY(MAP227(m, __VA_ARGS__)) +#define MAP229(m, x, ...) m(x) IDENTITY(MAP228(m, __VA_ARGS__)) +#define MAP230(m, x, ...) m(x) IDENTITY(MAP229(m, __VA_ARGS__)) +#define MAP231(m, x, ...) m(x) IDENTITY(MAP230(m, __VA_ARGS__)) +#define MAP232(m, x, ...) m(x) IDENTITY(MAP231(m, __VA_ARGS__)) +#define MAP233(m, x, ...) m(x) IDENTITY(MAP232(m, __VA_ARGS__)) +#define MAP234(m, x, ...) m(x) IDENTITY(MAP233(m, __VA_ARGS__)) +#define MAP235(m, x, ...) m(x) IDENTITY(MAP234(m, __VA_ARGS__)) +#define MAP236(m, x, ...) m(x) IDENTITY(MAP235(m, __VA_ARGS__)) +#define MAP237(m, x, ...) m(x) IDENTITY(MAP236(m, __VA_ARGS__)) +#define MAP238(m, x, ...) m(x) IDENTITY(MAP237(m, __VA_ARGS__)) +#define MAP239(m, x, ...) m(x) IDENTITY(MAP238(m, __VA_ARGS__)) +#define MAP240(m, x, ...) m(x) IDENTITY(MAP239(m, __VA_ARGS__)) +#define MAP241(m, x, ...) m(x) IDENTITY(MAP240(m, __VA_ARGS__)) +#define MAP242(m, x, ...) m(x) IDENTITY(MAP241(m, __VA_ARGS__)) +#define MAP243(m, x, ...) m(x) IDENTITY(MAP242(m, __VA_ARGS__)) +#define MAP244(m, x, ...) m(x) IDENTITY(MAP243(m, __VA_ARGS__)) +#define MAP245(m, x, ...) m(x) IDENTITY(MAP244(m, __VA_ARGS__)) +#define MAP246(m, x, ...) m(x) IDENTITY(MAP245(m, __VA_ARGS__)) +#define MAP247(m, x, ...) m(x) IDENTITY(MAP246(m, __VA_ARGS__)) +#define MAP248(m, x, ...) m(x) IDENTITY(MAP247(m, __VA_ARGS__)) +#define MAP249(m, x, ...) m(x) IDENTITY(MAP248(m, __VA_ARGS__)) +#define MAP250(m, x, ...) m(x) IDENTITY(MAP249(m, __VA_ARGS__)) +#define MAP251(m, x, ...) m(x) IDENTITY(MAP250(m, __VA_ARGS__)) +#define MAP252(m, x, ...) m(x) IDENTITY(MAP251(m, __VA_ARGS__)) +#define MAP253(m, x, ...) m(x) IDENTITY(MAP252(m, __VA_ARGS__)) +#define MAP254(m, x, ...) m(x) IDENTITY(MAP253(m, __VA_ARGS__)) +#define MAP255(m, x, ...) m(x) IDENTITY(MAP254(m, __VA_ARGS__)) +#define MAP256(m, x, ...) m(x) IDENTITY(MAP255(m, __VA_ARGS__)) +#define MAP257(m, x, ...) m(x) IDENTITY(MAP256(m, __VA_ARGS__)) +#define MAP258(m, x, ...) m(x) IDENTITY(MAP257(m, __VA_ARGS__)) +#define MAP259(m, x, ...) m(x) IDENTITY(MAP258(m, __VA_ARGS__)) +#define MAP260(m, x, ...) m(x) IDENTITY(MAP259(m, __VA_ARGS__)) +#define MAP261(m, x, ...) m(x) IDENTITY(MAP260(m, __VA_ARGS__)) +#define MAP262(m, x, ...) m(x) IDENTITY(MAP261(m, __VA_ARGS__)) +#define MAP263(m, x, ...) m(x) IDENTITY(MAP262(m, __VA_ARGS__)) +#define MAP264(m, x, ...) m(x) IDENTITY(MAP263(m, __VA_ARGS__)) +#define MAP265(m, x, ...) m(x) IDENTITY(MAP264(m, __VA_ARGS__)) +#define MAP266(m, x, ...) m(x) IDENTITY(MAP265(m, __VA_ARGS__)) +#define MAP267(m, x, ...) m(x) IDENTITY(MAP266(m, __VA_ARGS__)) +#define MAP268(m, x, ...) m(x) IDENTITY(MAP267(m, __VA_ARGS__)) +#define MAP269(m, x, ...) m(x) IDENTITY(MAP268(m, __VA_ARGS__)) +#define MAP270(m, x, ...) m(x) IDENTITY(MAP269(m, __VA_ARGS__)) +#define MAP271(m, x, ...) m(x) IDENTITY(MAP270(m, __VA_ARGS__)) +#define MAP272(m, x, ...) m(x) IDENTITY(MAP271(m, __VA_ARGS__)) +#define MAP273(m, x, ...) m(x) IDENTITY(MAP272(m, __VA_ARGS__)) +#define MAP274(m, x, ...) m(x) IDENTITY(MAP273(m, __VA_ARGS__)) +#define MAP275(m, x, ...) m(x) IDENTITY(MAP274(m, __VA_ARGS__)) +#define MAP276(m, x, ...) m(x) IDENTITY(MAP275(m, __VA_ARGS__)) +#define MAP277(m, x, ...) m(x) IDENTITY(MAP276(m, __VA_ARGS__)) +#define MAP278(m, x, ...) m(x) IDENTITY(MAP277(m, __VA_ARGS__)) +#define MAP279(m, x, ...) m(x) IDENTITY(MAP278(m, __VA_ARGS__)) +#define MAP280(m, x, ...) m(x) IDENTITY(MAP279(m, __VA_ARGS__)) +#define MAP281(m, x, ...) m(x) IDENTITY(MAP280(m, __VA_ARGS__)) +#define MAP282(m, x, ...) m(x) IDENTITY(MAP281(m, __VA_ARGS__)) +#define MAP283(m, x, ...) m(x) IDENTITY(MAP282(m, __VA_ARGS__)) +#define MAP284(m, x, ...) m(x) IDENTITY(MAP283(m, __VA_ARGS__)) +#define MAP285(m, x, ...) m(x) IDENTITY(MAP284(m, __VA_ARGS__)) +#define MAP286(m, x, ...) m(x) IDENTITY(MAP285(m, __VA_ARGS__)) +#define MAP287(m, x, ...) m(x) IDENTITY(MAP286(m, __VA_ARGS__)) +#define MAP288(m, x, ...) m(x) IDENTITY(MAP287(m, __VA_ARGS__)) +#define MAP289(m, x, ...) m(x) IDENTITY(MAP288(m, __VA_ARGS__)) +#define MAP290(m, x, ...) m(x) IDENTITY(MAP289(m, __VA_ARGS__)) +#define MAP291(m, x, ...) m(x) IDENTITY(MAP290(m, __VA_ARGS__)) +#define MAP292(m, x, ...) m(x) IDENTITY(MAP291(m, __VA_ARGS__)) +#define MAP293(m, x, ...) m(x) IDENTITY(MAP292(m, __VA_ARGS__)) +#define MAP294(m, x, ...) m(x) IDENTITY(MAP293(m, __VA_ARGS__)) +#define MAP295(m, x, ...) m(x) IDENTITY(MAP294(m, __VA_ARGS__)) +#define MAP296(m, x, ...) m(x) IDENTITY(MAP295(m, __VA_ARGS__)) +#define MAP297(m, x, ...) m(x) IDENTITY(MAP296(m, __VA_ARGS__)) +#define MAP298(m, x, ...) m(x) IDENTITY(MAP297(m, __VA_ARGS__)) +#define MAP299(m, x, ...) m(x) IDENTITY(MAP298(m, __VA_ARGS__)) +#define MAP300(m, x, ...) m(x) IDENTITY(MAP299(m, __VA_ARGS__)) +#define MAP301(m, x, ...) m(x) IDENTITY(MAP300(m, __VA_ARGS__)) +#define MAP302(m, x, ...) m(x) IDENTITY(MAP301(m, __VA_ARGS__)) +#define MAP303(m, x, ...) m(x) IDENTITY(MAP302(m, __VA_ARGS__)) +#define MAP304(m, x, ...) m(x) IDENTITY(MAP303(m, __VA_ARGS__)) +#define MAP305(m, x, ...) m(x) IDENTITY(MAP304(m, __VA_ARGS__)) +#define MAP306(m, x, ...) m(x) IDENTITY(MAP305(m, __VA_ARGS__)) +#define MAP307(m, x, ...) m(x) IDENTITY(MAP306(m, __VA_ARGS__)) +#define MAP308(m, x, ...) m(x) IDENTITY(MAP307(m, __VA_ARGS__)) +#define MAP309(m, x, ...) m(x) IDENTITY(MAP308(m, __VA_ARGS__)) +#define MAP310(m, x, ...) m(x) IDENTITY(MAP309(m, __VA_ARGS__)) +#define MAP311(m, x, ...) m(x) IDENTITY(MAP310(m, __VA_ARGS__)) +#define MAP312(m, x, ...) m(x) IDENTITY(MAP311(m, __VA_ARGS__)) +#define MAP313(m, x, ...) m(x) IDENTITY(MAP312(m, __VA_ARGS__)) +#define MAP314(m, x, ...) m(x) IDENTITY(MAP313(m, __VA_ARGS__)) +#define MAP315(m, x, ...) m(x) IDENTITY(MAP314(m, __VA_ARGS__)) +#define MAP316(m, x, ...) m(x) IDENTITY(MAP315(m, __VA_ARGS__)) +#define MAP317(m, x, ...) m(x) IDENTITY(MAP316(m, __VA_ARGS__)) +#define MAP318(m, x, ...) m(x) IDENTITY(MAP317(m, __VA_ARGS__)) +#define MAP319(m, x, ...) m(x) IDENTITY(MAP318(m, __VA_ARGS__)) +#define MAP320(m, x, ...) m(x) IDENTITY(MAP319(m, __VA_ARGS__)) +#define MAP321(m, x, ...) m(x) IDENTITY(MAP320(m, __VA_ARGS__)) +#define MAP322(m, x, ...) m(x) IDENTITY(MAP321(m, __VA_ARGS__)) +#define MAP323(m, x, ...) m(x) IDENTITY(MAP322(m, __VA_ARGS__)) +#define MAP324(m, x, ...) m(x) IDENTITY(MAP323(m, __VA_ARGS__)) +#define MAP325(m, x, ...) m(x) IDENTITY(MAP324(m, __VA_ARGS__)) +#define MAP326(m, x, ...) m(x) IDENTITY(MAP325(m, __VA_ARGS__)) +#define MAP327(m, x, ...) m(x) IDENTITY(MAP326(m, __VA_ARGS__)) +#define MAP328(m, x, ...) m(x) IDENTITY(MAP327(m, __VA_ARGS__)) +#define MAP329(m, x, ...) m(x) IDENTITY(MAP328(m, __VA_ARGS__)) +#define MAP330(m, x, ...) m(x) IDENTITY(MAP329(m, __VA_ARGS__)) +#define MAP331(m, x, ...) m(x) IDENTITY(MAP330(m, __VA_ARGS__)) +#define MAP332(m, x, ...) m(x) IDENTITY(MAP331(m, __VA_ARGS__)) +#define MAP333(m, x, ...) m(x) IDENTITY(MAP332(m, __VA_ARGS__)) +#define MAP334(m, x, ...) m(x) IDENTITY(MAP333(m, __VA_ARGS__)) +#define MAP335(m, x, ...) m(x) IDENTITY(MAP334(m, __VA_ARGS__)) +#define MAP336(m, x, ...) m(x) IDENTITY(MAP335(m, __VA_ARGS__)) +#define MAP337(m, x, ...) m(x) IDENTITY(MAP336(m, __VA_ARGS__)) +#define MAP338(m, x, ...) m(x) IDENTITY(MAP337(m, __VA_ARGS__)) +#define MAP339(m, x, ...) m(x) IDENTITY(MAP338(m, __VA_ARGS__)) +#define MAP340(m, x, ...) m(x) IDENTITY(MAP339(m, __VA_ARGS__)) +#define MAP341(m, x, ...) m(x) IDENTITY(MAP340(m, __VA_ARGS__)) +#define MAP342(m, x, ...) m(x) IDENTITY(MAP341(m, __VA_ARGS__)) +#define MAP343(m, x, ...) m(x) IDENTITY(MAP342(m, __VA_ARGS__)) +#define MAP344(m, x, ...) m(x) IDENTITY(MAP343(m, __VA_ARGS__)) +#define MAP345(m, x, ...) m(x) IDENTITY(MAP344(m, __VA_ARGS__)) +#define MAP346(m, x, ...) m(x) IDENTITY(MAP345(m, __VA_ARGS__)) +#define MAP347(m, x, ...) m(x) IDENTITY(MAP346(m, __VA_ARGS__)) +#define MAP348(m, x, ...) m(x) IDENTITY(MAP347(m, __VA_ARGS__)) +#define MAP349(m, x, ...) m(x) IDENTITY(MAP348(m, __VA_ARGS__)) +#define MAP350(m, x, ...) m(x) IDENTITY(MAP349(m, __VA_ARGS__)) +#define MAP351(m, x, ...) m(x) IDENTITY(MAP350(m, __VA_ARGS__)) +#define MAP352(m, x, ...) m(x) IDENTITY(MAP351(m, __VA_ARGS__)) +#define MAP353(m, x, ...) m(x) IDENTITY(MAP352(m, __VA_ARGS__)) +#define MAP354(m, x, ...) m(x) IDENTITY(MAP353(m, __VA_ARGS__)) +#define MAP355(m, x, ...) m(x) IDENTITY(MAP354(m, __VA_ARGS__)) +#define MAP356(m, x, ...) m(x) IDENTITY(MAP355(m, __VA_ARGS__)) +#define MAP357(m, x, ...) m(x) IDENTITY(MAP356(m, __VA_ARGS__)) +#define MAP358(m, x, ...) m(x) IDENTITY(MAP357(m, __VA_ARGS__)) +#define MAP359(m, x, ...) m(x) IDENTITY(MAP358(m, __VA_ARGS__)) +#define MAP360(m, x, ...) m(x) IDENTITY(MAP359(m, __VA_ARGS__)) +#define MAP361(m, x, ...) m(x) IDENTITY(MAP360(m, __VA_ARGS__)) +#define MAP362(m, x, ...) m(x) IDENTITY(MAP361(m, __VA_ARGS__)) +#define MAP363(m, x, ...) m(x) IDENTITY(MAP362(m, __VA_ARGS__)) +#define MAP364(m, x, ...) m(x) IDENTITY(MAP363(m, __VA_ARGS__)) +#define MAP365(m, x, ...) m(x) IDENTITY(MAP364(m, __VA_ARGS__)) +#define MAP366(m, x, ...) m(x) IDENTITY(MAP365(m, __VA_ARGS__)) +#define MAP367(m, x, ...) m(x) IDENTITY(MAP366(m, __VA_ARGS__)) +#define MAP368(m, x, ...) m(x) IDENTITY(MAP367(m, __VA_ARGS__)) +#define MAP369(m, x, ...) m(x) IDENTITY(MAP368(m, __VA_ARGS__)) +#define MAP370(m, x, ...) m(x) IDENTITY(MAP369(m, __VA_ARGS__)) +#define MAP371(m, x, ...) m(x) IDENTITY(MAP370(m, __VA_ARGS__)) +#define MAP372(m, x, ...) m(x) IDENTITY(MAP371(m, __VA_ARGS__)) +#define MAP373(m, x, ...) m(x) IDENTITY(MAP372(m, __VA_ARGS__)) +#define MAP374(m, x, ...) m(x) IDENTITY(MAP373(m, __VA_ARGS__)) +#define MAP375(m, x, ...) m(x) IDENTITY(MAP374(m, __VA_ARGS__)) +#define MAP376(m, x, ...) m(x) IDENTITY(MAP375(m, __VA_ARGS__)) +#define MAP377(m, x, ...) m(x) IDENTITY(MAP376(m, __VA_ARGS__)) +#define MAP378(m, x, ...) m(x) IDENTITY(MAP377(m, __VA_ARGS__)) +#define MAP379(m, x, ...) m(x) IDENTITY(MAP378(m, __VA_ARGS__)) +#define MAP380(m, x, ...) m(x) IDENTITY(MAP379(m, __VA_ARGS__)) +#define MAP381(m, x, ...) m(x) IDENTITY(MAP380(m, __VA_ARGS__)) +#define MAP382(m, x, ...) m(x) IDENTITY(MAP381(m, __VA_ARGS__)) +#define MAP383(m, x, ...) m(x) IDENTITY(MAP382(m, __VA_ARGS__)) +#define MAP384(m, x, ...) m(x) IDENTITY(MAP383(m, __VA_ARGS__)) +#define MAP385(m, x, ...) m(x) IDENTITY(MAP384(m, __VA_ARGS__)) +#define MAP386(m, x, ...) m(x) IDENTITY(MAP385(m, __VA_ARGS__)) +#define MAP387(m, x, ...) m(x) IDENTITY(MAP386(m, __VA_ARGS__)) +#define MAP388(m, x, ...) m(x) IDENTITY(MAP387(m, __VA_ARGS__)) +#define MAP389(m, x, ...) m(x) IDENTITY(MAP388(m, __VA_ARGS__)) +#define MAP390(m, x, ...) m(x) IDENTITY(MAP389(m, __VA_ARGS__)) +#define MAP391(m, x, ...) m(x) IDENTITY(MAP390(m, __VA_ARGS__)) +#define MAP392(m, x, ...) m(x) IDENTITY(MAP391(m, __VA_ARGS__)) +#define MAP393(m, x, ...) m(x) IDENTITY(MAP392(m, __VA_ARGS__)) +#define MAP394(m, x, ...) m(x) IDENTITY(MAP393(m, __VA_ARGS__)) +#define MAP395(m, x, ...) m(x) IDENTITY(MAP394(m, __VA_ARGS__)) +#define MAP396(m, x, ...) m(x) IDENTITY(MAP395(m, __VA_ARGS__)) +#define MAP397(m, x, ...) m(x) IDENTITY(MAP396(m, __VA_ARGS__)) +#define MAP398(m, x, ...) m(x) IDENTITY(MAP397(m, __VA_ARGS__)) +#define MAP399(m, x, ...) m(x) IDENTITY(MAP398(m, __VA_ARGS__)) +#define MAP400(m, x, ...) m(x) IDENTITY(MAP399(m, __VA_ARGS__)) +#define MAP401(m, x, ...) m(x) IDENTITY(MAP400(m, __VA_ARGS__)) +#define MAP402(m, x, ...) m(x) IDENTITY(MAP401(m, __VA_ARGS__)) +#define MAP403(m, x, ...) m(x) IDENTITY(MAP402(m, __VA_ARGS__)) +#define MAP404(m, x, ...) m(x) IDENTITY(MAP403(m, __VA_ARGS__)) +#define MAP405(m, x, ...) m(x) IDENTITY(MAP404(m, __VA_ARGS__)) +#define MAP406(m, x, ...) m(x) IDENTITY(MAP405(m, __VA_ARGS__)) +#define MAP407(m, x, ...) m(x) IDENTITY(MAP406(m, __VA_ARGS__)) +#define MAP408(m, x, ...) m(x) IDENTITY(MAP407(m, __VA_ARGS__)) +#define MAP409(m, x, ...) m(x) IDENTITY(MAP408(m, __VA_ARGS__)) +#define MAP410(m, x, ...) m(x) IDENTITY(MAP409(m, __VA_ARGS__)) +#define MAP411(m, x, ...) m(x) IDENTITY(MAP410(m, __VA_ARGS__)) +#define MAP412(m, x, ...) m(x) IDENTITY(MAP411(m, __VA_ARGS__)) +#define MAP413(m, x, ...) m(x) IDENTITY(MAP412(m, __VA_ARGS__)) +#define MAP414(m, x, ...) m(x) IDENTITY(MAP413(m, __VA_ARGS__)) +#define MAP415(m, x, ...) m(x) IDENTITY(MAP414(m, __VA_ARGS__)) +#define MAP416(m, x, ...) m(x) IDENTITY(MAP415(m, __VA_ARGS__)) +#define MAP417(m, x, ...) m(x) IDENTITY(MAP416(m, __VA_ARGS__)) +#define MAP418(m, x, ...) m(x) IDENTITY(MAP417(m, __VA_ARGS__)) +#define MAP419(m, x, ...) m(x) IDENTITY(MAP418(m, __VA_ARGS__)) +#define MAP420(m, x, ...) m(x) IDENTITY(MAP419(m, __VA_ARGS__)) +#define MAP421(m, x, ...) m(x) IDENTITY(MAP420(m, __VA_ARGS__)) +#define MAP422(m, x, ...) m(x) IDENTITY(MAP421(m, __VA_ARGS__)) +#define MAP423(m, x, ...) m(x) IDENTITY(MAP422(m, __VA_ARGS__)) +#define MAP424(m, x, ...) m(x) IDENTITY(MAP423(m, __VA_ARGS__)) +#define MAP425(m, x, ...) m(x) IDENTITY(MAP424(m, __VA_ARGS__)) +#define MAP426(m, x, ...) m(x) IDENTITY(MAP425(m, __VA_ARGS__)) +#define MAP427(m, x, ...) m(x) IDENTITY(MAP426(m, __VA_ARGS__)) +#define MAP428(m, x, ...) m(x) IDENTITY(MAP427(m, __VA_ARGS__)) +#define MAP429(m, x, ...) m(x) IDENTITY(MAP428(m, __VA_ARGS__)) +#define MAP430(m, x, ...) m(x) IDENTITY(MAP429(m, __VA_ARGS__)) +#define MAP431(m, x, ...) m(x) IDENTITY(MAP430(m, __VA_ARGS__)) +#define MAP432(m, x, ...) m(x) IDENTITY(MAP431(m, __VA_ARGS__)) +#define MAP433(m, x, ...) m(x) IDENTITY(MAP432(m, __VA_ARGS__)) +#define MAP434(m, x, ...) m(x) IDENTITY(MAP433(m, __VA_ARGS__)) +#define MAP435(m, x, ...) m(x) IDENTITY(MAP434(m, __VA_ARGS__)) +#define MAP436(m, x, ...) m(x) IDENTITY(MAP435(m, __VA_ARGS__)) +#define MAP437(m, x, ...) m(x) IDENTITY(MAP436(m, __VA_ARGS__)) +#define MAP438(m, x, ...) m(x) IDENTITY(MAP437(m, __VA_ARGS__)) +#define MAP439(m, x, ...) m(x) IDENTITY(MAP438(m, __VA_ARGS__)) +#define MAP440(m, x, ...) m(x) IDENTITY(MAP439(m, __VA_ARGS__)) +#define MAP441(m, x, ...) m(x) IDENTITY(MAP440(m, __VA_ARGS__)) +#define MAP442(m, x, ...) m(x) IDENTITY(MAP441(m, __VA_ARGS__)) +#define MAP443(m, x, ...) m(x) IDENTITY(MAP442(m, __VA_ARGS__)) +#define MAP444(m, x, ...) m(x) IDENTITY(MAP443(m, __VA_ARGS__)) +#define MAP445(m, x, ...) m(x) IDENTITY(MAP444(m, __VA_ARGS__)) +#define MAP446(m, x, ...) m(x) IDENTITY(MAP445(m, __VA_ARGS__)) +#define MAP447(m, x, ...) m(x) IDENTITY(MAP446(m, __VA_ARGS__)) +#define MAP448(m, x, ...) m(x) IDENTITY(MAP447(m, __VA_ARGS__)) +#define MAP449(m, x, ...) m(x) IDENTITY(MAP448(m, __VA_ARGS__)) +#define MAP450(m, x, ...) m(x) IDENTITY(MAP449(m, __VA_ARGS__)) +#define MAP451(m, x, ...) m(x) IDENTITY(MAP450(m, __VA_ARGS__)) +#define MAP452(m, x, ...) m(x) IDENTITY(MAP451(m, __VA_ARGS__)) +#define MAP453(m, x, ...) m(x) IDENTITY(MAP452(m, __VA_ARGS__)) +#define MAP454(m, x, ...) m(x) IDENTITY(MAP453(m, __VA_ARGS__)) +#define MAP455(m, x, ...) m(x) IDENTITY(MAP454(m, __VA_ARGS__)) +#define MAP456(m, x, ...) m(x) IDENTITY(MAP455(m, __VA_ARGS__)) +#define MAP457(m, x, ...) m(x) IDENTITY(MAP456(m, __VA_ARGS__)) +#define MAP458(m, x, ...) m(x) IDENTITY(MAP457(m, __VA_ARGS__)) +#define MAP459(m, x, ...) m(x) IDENTITY(MAP458(m, __VA_ARGS__)) +#define MAP460(m, x, ...) m(x) IDENTITY(MAP459(m, __VA_ARGS__)) +#define MAP461(m, x, ...) m(x) IDENTITY(MAP460(m, __VA_ARGS__)) +#define MAP462(m, x, ...) m(x) IDENTITY(MAP461(m, __VA_ARGS__)) +#define MAP463(m, x, ...) m(x) IDENTITY(MAP462(m, __VA_ARGS__)) +#define MAP464(m, x, ...) m(x) IDENTITY(MAP463(m, __VA_ARGS__)) +#define MAP465(m, x, ...) m(x) IDENTITY(MAP464(m, __VA_ARGS__)) +#define MAP466(m, x, ...) m(x) IDENTITY(MAP465(m, __VA_ARGS__)) +#define MAP467(m, x, ...) m(x) IDENTITY(MAP466(m, __VA_ARGS__)) +#define MAP468(m, x, ...) m(x) IDENTITY(MAP467(m, __VA_ARGS__)) +#define MAP469(m, x, ...) m(x) IDENTITY(MAP468(m, __VA_ARGS__)) +#define MAP470(m, x, ...) m(x) IDENTITY(MAP469(m, __VA_ARGS__)) +#define MAP471(m, x, ...) m(x) IDENTITY(MAP470(m, __VA_ARGS__)) +#define MAP472(m, x, ...) m(x) IDENTITY(MAP471(m, __VA_ARGS__)) +#define MAP473(m, x, ...) m(x) IDENTITY(MAP472(m, __VA_ARGS__)) +#define MAP474(m, x, ...) m(x) IDENTITY(MAP473(m, __VA_ARGS__)) +#define MAP475(m, x, ...) m(x) IDENTITY(MAP474(m, __VA_ARGS__)) +#define MAP476(m, x, ...) m(x) IDENTITY(MAP475(m, __VA_ARGS__)) +#define MAP477(m, x, ...) m(x) IDENTITY(MAP476(m, __VA_ARGS__)) +#define MAP478(m, x, ...) m(x) IDENTITY(MAP477(m, __VA_ARGS__)) +#define MAP479(m, x, ...) m(x) IDENTITY(MAP478(m, __VA_ARGS__)) +#define MAP480(m, x, ...) m(x) IDENTITY(MAP479(m, __VA_ARGS__)) +#define MAP481(m, x, ...) m(x) IDENTITY(MAP480(m, __VA_ARGS__)) +#define MAP482(m, x, ...) m(x) IDENTITY(MAP481(m, __VA_ARGS__)) +#define MAP483(m, x, ...) m(x) IDENTITY(MAP482(m, __VA_ARGS__)) +#define MAP484(m, x, ...) m(x) IDENTITY(MAP483(m, __VA_ARGS__)) +#define MAP485(m, x, ...) m(x) IDENTITY(MAP484(m, __VA_ARGS__)) +#define MAP486(m, x, ...) m(x) IDENTITY(MAP485(m, __VA_ARGS__)) +#define MAP487(m, x, ...) m(x) IDENTITY(MAP486(m, __VA_ARGS__)) +#define MAP488(m, x, ...) m(x) IDENTITY(MAP487(m, __VA_ARGS__)) +#define MAP489(m, x, ...) m(x) IDENTITY(MAP488(m, __VA_ARGS__)) +#define MAP490(m, x, ...) m(x) IDENTITY(MAP489(m, __VA_ARGS__)) +#define MAP491(m, x, ...) m(x) IDENTITY(MAP490(m, __VA_ARGS__)) +#define MAP492(m, x, ...) m(x) IDENTITY(MAP491(m, __VA_ARGS__)) +#define MAP493(m, x, ...) m(x) IDENTITY(MAP492(m, __VA_ARGS__)) +#define MAP494(m, x, ...) m(x) IDENTITY(MAP493(m, __VA_ARGS__)) +#define MAP495(m, x, ...) m(x) IDENTITY(MAP494(m, __VA_ARGS__)) +#define MAP496(m, x, ...) m(x) IDENTITY(MAP495(m, __VA_ARGS__)) +#define MAP497(m, x, ...) m(x) IDENTITY(MAP496(m, __VA_ARGS__)) +#define MAP498(m, x, ...) m(x) IDENTITY(MAP497(m, __VA_ARGS__)) +#define MAP499(m, x, ...) m(x) IDENTITY(MAP498(m, __VA_ARGS__)) +#define MAP500(m, x, ...) m(x) IDENTITY(MAP499(m, __VA_ARGS__)) +#define MAP501(m, x, ...) m(x) IDENTITY(MAP500(m, __VA_ARGS__)) +#define MAP502(m, x, ...) m(x) IDENTITY(MAP501(m, __VA_ARGS__)) +#define MAP503(m, x, ...) m(x) IDENTITY(MAP502(m, __VA_ARGS__)) +#define MAP504(m, x, ...) m(x) IDENTITY(MAP503(m, __VA_ARGS__)) +#define MAP505(m, x, ...) m(x) IDENTITY(MAP504(m, __VA_ARGS__)) +#define MAP506(m, x, ...) m(x) IDENTITY(MAP505(m, __VA_ARGS__)) +#define MAP507(m, x, ...) m(x) IDENTITY(MAP506(m, __VA_ARGS__)) +#define MAP508(m, x, ...) m(x) IDENTITY(MAP507(m, __VA_ARGS__)) +#define MAP509(m, x, ...) m(x) IDENTITY(MAP508(m, __VA_ARGS__)) +#define MAP510(m, x, ...) m(x) IDENTITY(MAP509(m, __VA_ARGS__)) +#define MAP511(m, x, ...) m(x) IDENTITY(MAP510(m, __VA_ARGS__)) +#define MAP512(m, x, ...) m(x) IDENTITY(MAP511(m, __VA_ARGS__)) +#define MAP513(m, x, ...) m(x) IDENTITY(MAP512(m, __VA_ARGS__)) +#define MAP514(m, x, ...) m(x) IDENTITY(MAP513(m, __VA_ARGS__)) +#define MAP515(m, x, ...) m(x) IDENTITY(MAP514(m, __VA_ARGS__)) +#define MAP516(m, x, ...) m(x) IDENTITY(MAP515(m, __VA_ARGS__)) +#define MAP517(m, x, ...) m(x) IDENTITY(MAP516(m, __VA_ARGS__)) +#define MAP518(m, x, ...) m(x) IDENTITY(MAP517(m, __VA_ARGS__)) +#define MAP519(m, x, ...) m(x) IDENTITY(MAP518(m, __VA_ARGS__)) +#define MAP520(m, x, ...) m(x) IDENTITY(MAP519(m, __VA_ARGS__)) +#define MAP521(m, x, ...) m(x) IDENTITY(MAP520(m, __VA_ARGS__)) +#define MAP522(m, x, ...) m(x) IDENTITY(MAP521(m, __VA_ARGS__)) +#define MAP523(m, x, ...) m(x) IDENTITY(MAP522(m, __VA_ARGS__)) +#define MAP524(m, x, ...) m(x) IDENTITY(MAP523(m, __VA_ARGS__)) +#define MAP525(m, x, ...) m(x) IDENTITY(MAP524(m, __VA_ARGS__)) +#define MAP526(m, x, ...) m(x) IDENTITY(MAP525(m, __VA_ARGS__)) +#define MAP527(m, x, ...) m(x) IDENTITY(MAP526(m, __VA_ARGS__)) +#define MAP528(m, x, ...) m(x) IDENTITY(MAP527(m, __VA_ARGS__)) +#define MAP529(m, x, ...) m(x) IDENTITY(MAP528(m, __VA_ARGS__)) +#define MAP530(m, x, ...) m(x) IDENTITY(MAP529(m, __VA_ARGS__)) +#define MAP531(m, x, ...) m(x) IDENTITY(MAP530(m, __VA_ARGS__)) +#define MAP532(m, x, ...) m(x) IDENTITY(MAP531(m, __VA_ARGS__)) +#define MAP533(m, x, ...) m(x) IDENTITY(MAP532(m, __VA_ARGS__)) +#define MAP534(m, x, ...) m(x) IDENTITY(MAP533(m, __VA_ARGS__)) +#define MAP535(m, x, ...) m(x) IDENTITY(MAP534(m, __VA_ARGS__)) +#define MAP536(m, x, ...) m(x) IDENTITY(MAP535(m, __VA_ARGS__)) +#define MAP537(m, x, ...) m(x) IDENTITY(MAP536(m, __VA_ARGS__)) +#define MAP538(m, x, ...) m(x) IDENTITY(MAP537(m, __VA_ARGS__)) +#define MAP539(m, x, ...) m(x) IDENTITY(MAP538(m, __VA_ARGS__)) +#define MAP540(m, x, ...) m(x) IDENTITY(MAP539(m, __VA_ARGS__)) +#define MAP541(m, x, ...) m(x) IDENTITY(MAP540(m, __VA_ARGS__)) +#define MAP542(m, x, ...) m(x) IDENTITY(MAP541(m, __VA_ARGS__)) +#define MAP543(m, x, ...) m(x) IDENTITY(MAP542(m, __VA_ARGS__)) +#define MAP544(m, x, ...) m(x) IDENTITY(MAP543(m, __VA_ARGS__)) +#define MAP545(m, x, ...) m(x) IDENTITY(MAP544(m, __VA_ARGS__)) +#define MAP546(m, x, ...) m(x) IDENTITY(MAP545(m, __VA_ARGS__)) +#define MAP547(m, x, ...) m(x) IDENTITY(MAP546(m, __VA_ARGS__)) +#define MAP548(m, x, ...) m(x) IDENTITY(MAP547(m, __VA_ARGS__)) +#define MAP549(m, x, ...) m(x) IDENTITY(MAP548(m, __VA_ARGS__)) +#define MAP550(m, x, ...) m(x) IDENTITY(MAP549(m, __VA_ARGS__)) +#define MAP551(m, x, ...) m(x) IDENTITY(MAP550(m, __VA_ARGS__)) +#define MAP552(m, x, ...) m(x) IDENTITY(MAP551(m, __VA_ARGS__)) +#define MAP553(m, x, ...) m(x) IDENTITY(MAP552(m, __VA_ARGS__)) +#define MAP554(m, x, ...) m(x) IDENTITY(MAP553(m, __VA_ARGS__)) +#define MAP555(m, x, ...) m(x) IDENTITY(MAP554(m, __VA_ARGS__)) +#define MAP556(m, x, ...) m(x) IDENTITY(MAP555(m, __VA_ARGS__)) +#define MAP557(m, x, ...) m(x) IDENTITY(MAP556(m, __VA_ARGS__)) +#define MAP558(m, x, ...) m(x) IDENTITY(MAP557(m, __VA_ARGS__)) +#define MAP559(m, x, ...) m(x) IDENTITY(MAP558(m, __VA_ARGS__)) +#define MAP560(m, x, ...) m(x) IDENTITY(MAP559(m, __VA_ARGS__)) +#define MAP561(m, x, ...) m(x) IDENTITY(MAP560(m, __VA_ARGS__)) +#define MAP562(m, x, ...) m(x) IDENTITY(MAP561(m, __VA_ARGS__)) +#define MAP563(m, x, ...) m(x) IDENTITY(MAP562(m, __VA_ARGS__)) +#define MAP564(m, x, ...) m(x) IDENTITY(MAP563(m, __VA_ARGS__)) +#define MAP565(m, x, ...) m(x) IDENTITY(MAP564(m, __VA_ARGS__)) +#define MAP566(m, x, ...) m(x) IDENTITY(MAP565(m, __VA_ARGS__)) +#define MAP567(m, x, ...) m(x) IDENTITY(MAP566(m, __VA_ARGS__)) +#define MAP568(m, x, ...) m(x) IDENTITY(MAP567(m, __VA_ARGS__)) +#define MAP569(m, x, ...) m(x) IDENTITY(MAP568(m, __VA_ARGS__)) +#define MAP570(m, x, ...) m(x) IDENTITY(MAP569(m, __VA_ARGS__)) +#define MAP571(m, x, ...) m(x) IDENTITY(MAP570(m, __VA_ARGS__)) +#define MAP572(m, x, ...) m(x) IDENTITY(MAP571(m, __VA_ARGS__)) +#define MAP573(m, x, ...) m(x) IDENTITY(MAP572(m, __VA_ARGS__)) +#define MAP574(m, x, ...) m(x) IDENTITY(MAP573(m, __VA_ARGS__)) +#define MAP575(m, x, ...) m(x) IDENTITY(MAP574(m, __VA_ARGS__)) +#define MAP576(m, x, ...) m(x) IDENTITY(MAP575(m, __VA_ARGS__)) +#define MAP577(m, x, ...) m(x) IDENTITY(MAP576(m, __VA_ARGS__)) +#define MAP578(m, x, ...) m(x) IDENTITY(MAP577(m, __VA_ARGS__)) +#define MAP579(m, x, ...) m(x) IDENTITY(MAP578(m, __VA_ARGS__)) +#define MAP580(m, x, ...) m(x) IDENTITY(MAP579(m, __VA_ARGS__)) +#define MAP581(m, x, ...) m(x) IDENTITY(MAP580(m, __VA_ARGS__)) +#define MAP582(m, x, ...) m(x) IDENTITY(MAP581(m, __VA_ARGS__)) +#define MAP583(m, x, ...) m(x) IDENTITY(MAP582(m, __VA_ARGS__)) +#define MAP584(m, x, ...) m(x) IDENTITY(MAP583(m, __VA_ARGS__)) +#define MAP585(m, x, ...) m(x) IDENTITY(MAP584(m, __VA_ARGS__)) +#define MAP586(m, x, ...) m(x) IDENTITY(MAP585(m, __VA_ARGS__)) +#define MAP587(m, x, ...) m(x) IDENTITY(MAP586(m, __VA_ARGS__)) +#define MAP588(m, x, ...) m(x) IDENTITY(MAP587(m, __VA_ARGS__)) +#define MAP589(m, x, ...) m(x) IDENTITY(MAP588(m, __VA_ARGS__)) +#define MAP590(m, x, ...) m(x) IDENTITY(MAP589(m, __VA_ARGS__)) +#define MAP591(m, x, ...) m(x) IDENTITY(MAP590(m, __VA_ARGS__)) +#define MAP592(m, x, ...) m(x) IDENTITY(MAP591(m, __VA_ARGS__)) +#define MAP593(m, x, ...) m(x) IDENTITY(MAP592(m, __VA_ARGS__)) +#define MAP594(m, x, ...) m(x) IDENTITY(MAP593(m, __VA_ARGS__)) +#define MAP595(m, x, ...) m(x) IDENTITY(MAP594(m, __VA_ARGS__)) +#define MAP596(m, x, ...) m(x) IDENTITY(MAP595(m, __VA_ARGS__)) +#define MAP597(m, x, ...) m(x) IDENTITY(MAP596(m, __VA_ARGS__)) +#define MAP598(m, x, ...) m(x) IDENTITY(MAP597(m, __VA_ARGS__)) +#define MAP599(m, x, ...) m(x) IDENTITY(MAP598(m, __VA_ARGS__)) +#define MAP600(m, x, ...) m(x) IDENTITY(MAP499(m, __VA_ARGS__)) +#define MAP601(m, x, ...) m(x) IDENTITY(MAP600(m, __VA_ARGS__)) +#define MAP602(m, x, ...) m(x) IDENTITY(MAP601(m, __VA_ARGS__)) +#define MAP603(m, x, ...) m(x) IDENTITY(MAP602(m, __VA_ARGS__)) +#define MAP604(m, x, ...) m(x) IDENTITY(MAP603(m, __VA_ARGS__)) +#define MAP605(m, x, ...) m(x) IDENTITY(MAP604(m, __VA_ARGS__)) +#define MAP606(m, x, ...) m(x) IDENTITY(MAP605(m, __VA_ARGS__)) +#define MAP607(m, x, ...) m(x) IDENTITY(MAP606(m, __VA_ARGS__)) +#define MAP608(m, x, ...) m(x) IDENTITY(MAP607(m, __VA_ARGS__)) +#define MAP609(m, x, ...) m(x) IDENTITY(MAP608(m, __VA_ARGS__)) +#define MAP610(m, x, ...) m(x) IDENTITY(MAP609(m, __VA_ARGS__)) +#define MAP611(m, x, ...) m(x) IDENTITY(MAP610(m, __VA_ARGS__)) +#define MAP612(m, x, ...) m(x) IDENTITY(MAP611(m, __VA_ARGS__)) +#define MAP613(m, x, ...) m(x) IDENTITY(MAP612(m, __VA_ARGS__)) +#define MAP614(m, x, ...) m(x) IDENTITY(MAP613(m, __VA_ARGS__)) +#define MAP615(m, x, ...) m(x) IDENTITY(MAP614(m, __VA_ARGS__)) +#define MAP616(m, x, ...) m(x) IDENTITY(MAP615(m, __VA_ARGS__)) +#define MAP617(m, x, ...) m(x) IDENTITY(MAP616(m, __VA_ARGS__)) +#define MAP618(m, x, ...) m(x) IDENTITY(MAP617(m, __VA_ARGS__)) +#define MAP619(m, x, ...) m(x) IDENTITY(MAP618(m, __VA_ARGS__)) +#define MAP620(m, x, ...) m(x) IDENTITY(MAP619(m, __VA_ARGS__)) +#define MAP621(m, x, ...) m(x) IDENTITY(MAP620(m, __VA_ARGS__)) +#define MAP622(m, x, ...) m(x) IDENTITY(MAP621(m, __VA_ARGS__)) +#define MAP623(m, x, ...) m(x) IDENTITY(MAP622(m, __VA_ARGS__)) +#define MAP624(m, x, ...) m(x) IDENTITY(MAP623(m, __VA_ARGS__)) +#define MAP625(m, x, ...) m(x) IDENTITY(MAP624(m, __VA_ARGS__)) +#define MAP626(m, x, ...) m(x) IDENTITY(MAP625(m, __VA_ARGS__)) +#define MAP627(m, x, ...) m(x) IDENTITY(MAP626(m, __VA_ARGS__)) +#define MAP628(m, x, ...) m(x) IDENTITY(MAP627(m, __VA_ARGS__)) +#define MAP629(m, x, ...) m(x) IDENTITY(MAP628(m, __VA_ARGS__)) +#define MAP630(m, x, ...) m(x) IDENTITY(MAP629(m, __VA_ARGS__)) +#define MAP631(m, x, ...) m(x) IDENTITY(MAP630(m, __VA_ARGS__)) +#define MAP632(m, x, ...) m(x) IDENTITY(MAP631(m, __VA_ARGS__)) +#define MAP633(m, x, ...) m(x) IDENTITY(MAP632(m, __VA_ARGS__)) +#define MAP634(m, x, ...) m(x) IDENTITY(MAP633(m, __VA_ARGS__)) +#define MAP635(m, x, ...) m(x) IDENTITY(MAP634(m, __VA_ARGS__)) +#define MAP636(m, x, ...) m(x) IDENTITY(MAP635(m, __VA_ARGS__)) +#define MAP637(m, x, ...) m(x) IDENTITY(MAP636(m, __VA_ARGS__)) +#define MAP638(m, x, ...) m(x) IDENTITY(MAP637(m, __VA_ARGS__)) +#define MAP639(m, x, ...) m(x) IDENTITY(MAP638(m, __VA_ARGS__)) +#define MAP640(m, x, ...) m(x) IDENTITY(MAP639(m, __VA_ARGS__)) +#define MAP641(m, x, ...) m(x) IDENTITY(MAP640(m, __VA_ARGS__)) +#define MAP642(m, x, ...) m(x) IDENTITY(MAP641(m, __VA_ARGS__)) +#define MAP643(m, x, ...) m(x) IDENTITY(MAP642(m, __VA_ARGS__)) +#define MAP644(m, x, ...) m(x) IDENTITY(MAP643(m, __VA_ARGS__)) +#define MAP645(m, x, ...) m(x) IDENTITY(MAP644(m, __VA_ARGS__)) +#define MAP646(m, x, ...) m(x) IDENTITY(MAP645(m, __VA_ARGS__)) +#define MAP647(m, x, ...) m(x) IDENTITY(MAP646(m, __VA_ARGS__)) +#define MAP648(m, x, ...) m(x) IDENTITY(MAP647(m, __VA_ARGS__)) +#define MAP649(m, x, ...) m(x) IDENTITY(MAP648(m, __VA_ARGS__)) +#define MAP650(m, x, ...) m(x) IDENTITY(MAP649(m, __VA_ARGS__)) +#define MAP651(m, x, ...) m(x) IDENTITY(MAP650(m, __VA_ARGS__)) +#define MAP652(m, x, ...) m(x) IDENTITY(MAP651(m, __VA_ARGS__)) +#define MAP653(m, x, ...) m(x) IDENTITY(MAP652(m, __VA_ARGS__)) +#define MAP654(m, x, ...) m(x) IDENTITY(MAP653(m, __VA_ARGS__)) +#define MAP655(m, x, ...) m(x) IDENTITY(MAP654(m, __VA_ARGS__)) +#define MAP656(m, x, ...) m(x) IDENTITY(MAP655(m, __VA_ARGS__)) +#define MAP657(m, x, ...) m(x) IDENTITY(MAP656(m, __VA_ARGS__)) +#define MAP658(m, x, ...) m(x) IDENTITY(MAP657(m, __VA_ARGS__)) +#define MAP659(m, x, ...) m(x) IDENTITY(MAP658(m, __VA_ARGS__)) +#define MAP660(m, x, ...) m(x) IDENTITY(MAP659(m, __VA_ARGS__)) +#define MAP661(m, x, ...) m(x) IDENTITY(MAP660(m, __VA_ARGS__)) +#define MAP662(m, x, ...) m(x) IDENTITY(MAP661(m, __VA_ARGS__)) +#define MAP663(m, x, ...) m(x) IDENTITY(MAP662(m, __VA_ARGS__)) +#define MAP664(m, x, ...) m(x) IDENTITY(MAP663(m, __VA_ARGS__)) +#define MAP665(m, x, ...) m(x) IDENTITY(MAP664(m, __VA_ARGS__)) +#define MAP666(m, x, ...) m(x) IDENTITY(MAP665(m, __VA_ARGS__)) +#define MAP667(m, x, ...) m(x) IDENTITY(MAP666(m, __VA_ARGS__)) +#define MAP668(m, x, ...) m(x) IDENTITY(MAP667(m, __VA_ARGS__)) +#define MAP669(m, x, ...) m(x) IDENTITY(MAP668(m, __VA_ARGS__)) +#define MAP670(m, x, ...) m(x) IDENTITY(MAP669(m, __VA_ARGS__)) +#define MAP671(m, x, ...) m(x) IDENTITY(MAP670(m, __VA_ARGS__)) +#define MAP672(m, x, ...) m(x) IDENTITY(MAP671(m, __VA_ARGS__)) +#define MAP673(m, x, ...) m(x) IDENTITY(MAP672(m, __VA_ARGS__)) +#define MAP674(m, x, ...) m(x) IDENTITY(MAP673(m, __VA_ARGS__)) +#define MAP675(m, x, ...) m(x) IDENTITY(MAP674(m, __VA_ARGS__)) +#define MAP676(m, x, ...) m(x) IDENTITY(MAP675(m, __VA_ARGS__)) +#define MAP677(m, x, ...) m(x) IDENTITY(MAP676(m, __VA_ARGS__)) +#define MAP678(m, x, ...) m(x) IDENTITY(MAP677(m, __VA_ARGS__)) +#define MAP679(m, x, ...) m(x) IDENTITY(MAP678(m, __VA_ARGS__)) +#define MAP680(m, x, ...) m(x) IDENTITY(MAP679(m, __VA_ARGS__)) +#define MAP681(m, x, ...) m(x) IDENTITY(MAP680(m, __VA_ARGS__)) +#define MAP682(m, x, ...) m(x) IDENTITY(MAP681(m, __VA_ARGS__)) +#define MAP683(m, x, ...) m(x) IDENTITY(MAP682(m, __VA_ARGS__)) +#define MAP684(m, x, ...) m(x) IDENTITY(MAP683(m, __VA_ARGS__)) +#define MAP685(m, x, ...) m(x) IDENTITY(MAP684(m, __VA_ARGS__)) +#define MAP686(m, x, ...) m(x) IDENTITY(MAP685(m, __VA_ARGS__)) +#define MAP687(m, x, ...) m(x) IDENTITY(MAP686(m, __VA_ARGS__)) +#define MAP688(m, x, ...) m(x) IDENTITY(MAP687(m, __VA_ARGS__)) +#define MAP689(m, x, ...) m(x) IDENTITY(MAP688(m, __VA_ARGS__)) +#define MAP690(m, x, ...) m(x) IDENTITY(MAP689(m, __VA_ARGS__)) +#define MAP691(m, x, ...) m(x) IDENTITY(MAP690(m, __VA_ARGS__)) +#define MAP692(m, x, ...) m(x) IDENTITY(MAP691(m, __VA_ARGS__)) +#define MAP693(m, x, ...) m(x) IDENTITY(MAP692(m, __VA_ARGS__)) +#define MAP694(m, x, ...) m(x) IDENTITY(MAP693(m, __VA_ARGS__)) +#define MAP695(m, x, ...) m(x) IDENTITY(MAP694(m, __VA_ARGS__)) +#define MAP696(m, x, ...) m(x) IDENTITY(MAP695(m, __VA_ARGS__)) +#define MAP697(m, x, ...) m(x) IDENTITY(MAP696(m, __VA_ARGS__)) +#define MAP698(m, x, ...) m(x) IDENTITY(MAP697(m, __VA_ARGS__)) +#define MAP699(m, x, ...) m(x) IDENTITY(MAP698(m, __VA_ARGS__)) +#define MAP700(m, x, ...) m(x) IDENTITY(MAP499(m, __VA_ARGS__)) +#define MAP701(m, x, ...) m(x) IDENTITY(MAP700(m, __VA_ARGS__)) +#define MAP702(m, x, ...) m(x) IDENTITY(MAP701(m, __VA_ARGS__)) +#define MAP703(m, x, ...) m(x) IDENTITY(MAP702(m, __VA_ARGS__)) +#define MAP704(m, x, ...) m(x) IDENTITY(MAP703(m, __VA_ARGS__)) +#define MAP705(m, x, ...) m(x) IDENTITY(MAP704(m, __VA_ARGS__)) +#define MAP706(m, x, ...) m(x) IDENTITY(MAP705(m, __VA_ARGS__)) +#define MAP707(m, x, ...) m(x) IDENTITY(MAP706(m, __VA_ARGS__)) +#define MAP708(m, x, ...) m(x) IDENTITY(MAP707(m, __VA_ARGS__)) +#define MAP709(m, x, ...) m(x) IDENTITY(MAP708(m, __VA_ARGS__)) +#define MAP710(m, x, ...) m(x) IDENTITY(MAP709(m, __VA_ARGS__)) +#define MAP711(m, x, ...) m(x) IDENTITY(MAP710(m, __VA_ARGS__)) +#define MAP712(m, x, ...) m(x) IDENTITY(MAP711(m, __VA_ARGS__)) +#define MAP713(m, x, ...) m(x) IDENTITY(MAP712(m, __VA_ARGS__)) +#define MAP714(m, x, ...) m(x) IDENTITY(MAP713(m, __VA_ARGS__)) +#define MAP715(m, x, ...) m(x) IDENTITY(MAP714(m, __VA_ARGS__)) +#define MAP716(m, x, ...) m(x) IDENTITY(MAP715(m, __VA_ARGS__)) +#define MAP717(m, x, ...) m(x) IDENTITY(MAP716(m, __VA_ARGS__)) +#define MAP718(m, x, ...) m(x) IDENTITY(MAP717(m, __VA_ARGS__)) +#define MAP719(m, x, ...) m(x) IDENTITY(MAP718(m, __VA_ARGS__)) +#define MAP720(m, x, ...) m(x) IDENTITY(MAP719(m, __VA_ARGS__)) +#define MAP721(m, x, ...) m(x) IDENTITY(MAP720(m, __VA_ARGS__)) +#define MAP722(m, x, ...) m(x) IDENTITY(MAP721(m, __VA_ARGS__)) +#define MAP723(m, x, ...) m(x) IDENTITY(MAP722(m, __VA_ARGS__)) +#define MAP724(m, x, ...) m(x) IDENTITY(MAP723(m, __VA_ARGS__)) +#define MAP725(m, x, ...) m(x) IDENTITY(MAP724(m, __VA_ARGS__)) +#define MAP726(m, x, ...) m(x) IDENTITY(MAP725(m, __VA_ARGS__)) +#define MAP727(m, x, ...) m(x) IDENTITY(MAP726(m, __VA_ARGS__)) +#define MAP728(m, x, ...) m(x) IDENTITY(MAP727(m, __VA_ARGS__)) +#define MAP729(m, x, ...) m(x) IDENTITY(MAP728(m, __VA_ARGS__)) +#define MAP730(m, x, ...) m(x) IDENTITY(MAP729(m, __VA_ARGS__)) +#define MAP731(m, x, ...) m(x) IDENTITY(MAP730(m, __VA_ARGS__)) +#define MAP732(m, x, ...) m(x) IDENTITY(MAP731(m, __VA_ARGS__)) +#define MAP733(m, x, ...) m(x) IDENTITY(MAP732(m, __VA_ARGS__)) +#define MAP734(m, x, ...) m(x) IDENTITY(MAP733(m, __VA_ARGS__)) +#define MAP735(m, x, ...) m(x) IDENTITY(MAP734(m, __VA_ARGS__)) +#define MAP736(m, x, ...) m(x) IDENTITY(MAP735(m, __VA_ARGS__)) +#define MAP737(m, x, ...) m(x) IDENTITY(MAP736(m, __VA_ARGS__)) +#define MAP738(m, x, ...) m(x) IDENTITY(MAP737(m, __VA_ARGS__)) +#define MAP739(m, x, ...) m(x) IDENTITY(MAP738(m, __VA_ARGS__)) +#define MAP740(m, x, ...) m(x) IDENTITY(MAP739(m, __VA_ARGS__)) +#define MAP741(m, x, ...) m(x) IDENTITY(MAP740(m, __VA_ARGS__)) +#define MAP742(m, x, ...) m(x) IDENTITY(MAP741(m, __VA_ARGS__)) +#define MAP743(m, x, ...) m(x) IDENTITY(MAP742(m, __VA_ARGS__)) +#define MAP744(m, x, ...) m(x) IDENTITY(MAP743(m, __VA_ARGS__)) +#define MAP745(m, x, ...) m(x) IDENTITY(MAP744(m, __VA_ARGS__)) +#define MAP746(m, x, ...) m(x) IDENTITY(MAP745(m, __VA_ARGS__)) +#define MAP747(m, x, ...) m(x) IDENTITY(MAP746(m, __VA_ARGS__)) +#define MAP748(m, x, ...) m(x) IDENTITY(MAP747(m, __VA_ARGS__)) +#define MAP749(m, x, ...) m(x) IDENTITY(MAP748(m, __VA_ARGS__)) +#define MAP750(m, x, ...) m(x) IDENTITY(MAP749(m, __VA_ARGS__)) +#define MAP751(m, x, ...) m(x) IDENTITY(MAP750(m, __VA_ARGS__)) +#define MAP752(m, x, ...) m(x) IDENTITY(MAP751(m, __VA_ARGS__)) +#define MAP753(m, x, ...) m(x) IDENTITY(MAP752(m, __VA_ARGS__)) +#define MAP754(m, x, ...) m(x) IDENTITY(MAP753(m, __VA_ARGS__)) +#define MAP755(m, x, ...) m(x) IDENTITY(MAP754(m, __VA_ARGS__)) +#define MAP756(m, x, ...) m(x) IDENTITY(MAP755(m, __VA_ARGS__)) +#define MAP757(m, x, ...) m(x) IDENTITY(MAP756(m, __VA_ARGS__)) +#define MAP758(m, x, ...) m(x) IDENTITY(MAP757(m, __VA_ARGS__)) +#define MAP759(m, x, ...) m(x) IDENTITY(MAP758(m, __VA_ARGS__)) +#define MAP760(m, x, ...) m(x) IDENTITY(MAP759(m, __VA_ARGS__)) +#define MAP761(m, x, ...) m(x) IDENTITY(MAP760(m, __VA_ARGS__)) +#define MAP762(m, x, ...) m(x) IDENTITY(MAP761(m, __VA_ARGS__)) +#define MAP763(m, x, ...) m(x) IDENTITY(MAP762(m, __VA_ARGS__)) +#define MAP764(m, x, ...) m(x) IDENTITY(MAP763(m, __VA_ARGS__)) +#define MAP765(m, x, ...) m(x) IDENTITY(MAP764(m, __VA_ARGS__)) +#define MAP766(m, x, ...) m(x) IDENTITY(MAP765(m, __VA_ARGS__)) +#define MAP767(m, x, ...) m(x) IDENTITY(MAP766(m, __VA_ARGS__)) +#define MAP768(m, x, ...) m(x) IDENTITY(MAP767(m, __VA_ARGS__)) + + +#define EVALUATE_COUNT(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \ + _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \ + _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \ + _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \ + _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \ + _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \ + _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, \ + _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, \ + _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, \ + _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, \ + _101, _102, _103, _104, _105, _106, _107, _108, _109, _110, \ + _111, _112, _113, _114, _115, _116, _117, _118, _119, _120, \ + _121, _122, _123, _124, _125, _126, _127, _128, _129, _130, \ + _131, _132, _133, _134, _135, _136, _137, _138, _139, _140, \ + _141, _142, _143, _144, _145, _146, _147, _148, _149, _150, \ + _151, _152, _153, _154, _155, _156, _157, _158, _159, _160, \ + _161, _162, _163, _164, _165, _166, _167, _168, _169, _170, \ + _171, _172, _173, _174, _175, _176, _177, _178, _179, _180, \ + _181, _182, _183, _184, _185, _186, _187, _188, _189, _190, \ + _191, _192, _193, _194, _195, _196, _197, _198, _199, _200, \ + _201, _202, _203, _204, _205, _206, _207, _208, _209, _210, \ + _211, _212, _213, _214, _215, _216, _217, _218, _219, _220, \ + _221, _222, _223, _224, _225, _226, _227, _228, _229, _230, \ + _231, _232, _233, _234, _235, _236, _237, _238, _239, _240, \ + _241, _242, _243, _244, _245, _246, _247, _248, _249, _250, \ + _251, _252, _253, _254, _255, _256, _257, _258, _259, _260, \ + _261, _262, _263, _264, _265, _266, _267, _268, _269, _270, \ + _271, _272, _273, _274, _275, _276, _277, _278, _279, _280, \ + _281, _282, _283, _284, _285, _286, _287, _288, _289, _290, \ + _291, _292, _293, _294, _295, _296, _297, _298, _299, _300, \ + _301, _302, _303, _304, _305, _306, _307, _308, _309, _310, \ + _311, _312, _313, _314, _315, _316, _317, _318, _319, _320, \ + _321, _322, _323, _324, _325, _326, _327, _328, _329, _330, \ + _331, _332, _333, _334, _335, _336, _337, _338, _339, _340, \ + _341, _342, _343, _344, _345, _346, _347, _348, _349, _350, \ + _351, _352, _353, _354, _355, _356, _357, _358, _359, _360, \ + _361, _362, _363, _364, _365, _366, _367, _368, _369, _370, \ + _371, _372, _373, _374, _375, _376, _377, _378, _379, _380, \ + _381, _382, _383, _384, _385, _386, _387, _388, _389, _390, \ + _391, _392, _393, _394, _395, _396, _397, _398, _399, _400, \ + _401, _402, _403, _404, _405, _406, _407, _408, _409, _410, \ + _411, _412, _413, _414, _415, _416, _417, _418, _419, _420, \ + _421, _422, _423, _424, _425, _426, _427, _428, _429, _430, \ + _431, _432, _433, _434, _435, _436, _437, _438, _439, _440, \ + _441, _442, _443, _444, _445, _446, _447, _448, _449, _450, \ + _451, _452, _453, _454, _455, _456, _457, _458, _459, _460, \ + _461, _462, _463, _464, _465, _466, _467, _468, _469, _470, \ + _471, _472, _473, _474, _475, _476, _477, _478, _479, _480, \ + _481, _482, _483, _484, _485, _486, _487, _488, _489, _490, \ + _491, _492, _493, _494, _495, _496, _497, _498, _499, _500, \ + _501, _502, _503, _504, _505, _506, _507, _508, _509, _510, \ + _511, _512, _513, _514, _515, _516, _517, _518, _519, _520, \ + _521, _522, _523, _524, _525, _526, _527, _528, _529, _530, \ + _531, _532, _533, _534, _535, _536, _537, _538, _539, _540, \ + _541, _542, _543, _544, _545, _546, _547, _548, _549, _550, \ + _551, _552, _553, _554, _555, _556, _557, _558, _559, _560, \ + _561, _562, _563, _564, _565, _566, _567, _568, _569, _570, \ + _571, _572, _573, _574, _575, _576, _577, _578, _579, _580, \ + _581, _582, _583, _584, _585, _586, _587, _588, _589, _590, \ + _591, _592, _593, _594, _595, _596, _597, _598, _599, _600, \ + _601, _602, _603, _604, _605, _606, _607, _608, _609, _610, \ + _611, _612, _613, _614, _615, _616, _617, _618, _619, _620, \ + _621, _622, _623, _624, _625, _626, _627, _628, _629, _630, \ + _631, _632, _633, _634, _635, _636, _637, _638, _639, _640, \ + _641, _642, _643, _644, _645, _646, _647, _648, _649, _650, \ + _651, _652, _653, _654, _655, _656, _657, _658, _659, _660, \ + _661, _662, _663, _664, _665, _666, _667, _668, _669, _670, \ + _671, _672, _673, _674, _675, _676, _677, _678, _679, _680, \ + _681, _682, _683, _684, _685, _686, _687, _688, _689, _690, \ + _691, _692, _693, _694, _695, _696, _697, _698, _699, _700, \ + _701, _702, _703, _704, _705, _706, _707, _708, _709, _710, \ + _711, _712, _713, _714, _715, _716, _717, _718, _719, _720, \ + _721, _722, _723, _724, _725, _726, _727, _728, _729, _730, \ + _731, _732, _733, _734, _735, _736, _737, _738, _739, _740, \ + _741, _742, _743, _744, _745, _746, _747, _748, _749, _750, \ + _751, _752, _753, _754, _755, _756, _757, _758, _759, _760, \ + _761, _762, _763, _764, _765, _766, _767, _768, \ + count, ...) count + +#define COUNT(...) \ + IDENTITY(EVALUATE_COUNT(__VA_ARGS__, 768, 767, 766, 765, 764, 763, 762, 761, \ + 760, 759, 758, 757, 756, 755, 754, 753, 752, 751, \ + 750, 749, 748, 747, 746, 745, 744, 743, 742, 741, \ + 740, 739, 738, 737, 736, 735, 734, 733, 732, 731, \ + 730, 729, 728, 727, 726, 725, 724, 723, 722, 721, \ + 720, 719, 718, 717, 716, 715, 714, 713, 712, 711, \ + 710, 709, 708, 707, 706, 705, 704, 703, 702, 701, \ + 700, 699, 698, 697, 696, 695, 694, 693, 692, 691, \ + 690, 689, 688, 687, 686, 685, 684, 683, 682, 681, \ + 680, 679, 678, 677, 676, 675, 674, 673, 672, 671, \ + 670, 669, 668, 667, 666, 665, 664, 663, 662, 661, \ + 660, 659, 658, 657, 656, 655, 654, 653, 652, 651, \ + 650, 649, 648, 647, 646, 645, 644, 643, 642, 641, \ + 640, 639, 638, 637, 636, 635, 634, 633, 632, 631, \ + 630, 629, 628, 627, 626, 625, 624, 623, 622, 621, \ + 620, 619, 618, 617, 616, 615, 614, 613, 612, 611, \ + 610, 609, 608, 607, 606, 605, 604, 603, 602, 601, \ + 600, 599, 598, 597, 596, 595, 594, 593, 592, 591, \ + 590, 589, 588, 587, 586, 585, 584, 583, 582, 581, \ + 580, 579, 578, 577, 576, 575, 574, 573, 572, 571, \ + 570, 569, 568, 567, 566, 565, 564, 563, 562, 561, \ + 560, 559, 558, 557, 556, 555, 554, 553, 552, 551, \ + 550, 549, 548, 547, 546, 545, 544, 543, 542, 541, \ + 540, 539, 538, 537, 536, 535, 534, 533, 532, 531, \ + 530, 529, 528, 527, 526, 525, 524, 523, 522, 521, \ + 520, 519, 518, 517, 516, 515, 514, 513, 512, 511, \ + 510, 509, 508, 507, 506, 505, 504, 503, 502, 501, \ + 500, 499, 498, 497, 496, 495, 494, 493, 492, 491, \ + 490, 489, 488, 487, 486, 485, 484, 483, 482, 481, \ + 480, 479, 478, 477, 476, 475, 474, 473, 472, 471, \ + 470, 469, 468, 467, 466, 465, 464, 463, 462, 461, \ + 460, 459, 458, 457, 456, 455, 454, 453, 452, 451, \ + 450, 449, 448, 447, 446, 445, 444, 443, 442, 441, \ + 440, 439, 438, 437, 436, 435, 434, 433, 432, 431, \ + 430, 429, 428, 427, 426, 425, 424, 423, 422, 421, \ + 420, 419, 418, 417, 416, 415, 414, 413, 412, 411, \ + 410, 409, 408, 407, 406, 405, 404, 403, 402, 401, \ + 400, 399, 398, 397, 396, 395, 394, 393, 392, 391, \ + 390, 389, 388, 387, 386, 385, 384, 383, 382, 381, \ + 380, 379, 378, 377, 376, 375, 374, 373, 372, 371, \ + 370, 369, 368, 367, 366, 365, 364, 363, 362, 361, \ + 360, 359, 358, 357, 356, 355, 354, 353, 352, 351, \ + 350, 349, 348, 347, 346, 345, 344, 343, 342, 341, \ + 340, 339, 338, 337, 336, 335, 334, 333, 332, 331, \ + 330, 329, 328, 327, 326, 325, 324, 323, 322, 321, \ + 320, 319, 318, 317, 316, 315, 314, 313, 312, 311, \ + 310, 309, 308, 307, 306, 305, 304, 303, 302, 301, \ + 300, 299, 298, 297, 296, 295, 294, 293, 292, 291, \ + 290, 289, 288, 287, 286, 285, 284, 283, 282, 281, \ + 280, 279, 278, 277, 276, 275, 274, 273, 272, 271, \ + 270, 269, 268, 267, 266, 265, 264, 263, 262, 261, \ + 260, 259, 258, 257, 256, 255, 254, 253, 252, 251, \ + 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, \ + 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, \ + 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, \ + 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, \ + 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, \ + 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, \ + 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, \ + 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, \ + 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, \ + 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, \ + 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, \ + 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, \ + 130, 129, 128, 127, 126, 125, 124, 123, 122, 121, \ + 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, \ + 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, \ + 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, \ + 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, \ + 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, \ + 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, \ + 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, \ + 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, \ + 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, \ + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, \ + 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, \ + 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)) + + +struct ignore_assign { + ignore_assign(int value) : _value(value) { } + operator int() const { return _value; } + + const ignore_assign& operator =(int dummy) { (void)dummy; return *this; } + + int _value; +}; + +#define IGNORE_ASSIGN_SINGLE(expression) (ignore_assign)expression, +#define IGNORE_ASSIGN(...) IDENTITY(MAP(IGNORE_ASSIGN_SINGLE, __VA_ARGS__)) + +#define STRINGIZE_SINGLE(expression) #expression, +#define STRINGIZE(...) IDENTITY(MAP(STRINGIZE_SINGLE, __VA_ARGS__)) + + + +#define ENUM(EnumName, ...) \ +struct EnumName { \ + enum _enumerated { __VA_ARGS__ }; \ + \ + _enumerated _value; \ + \ + EnumName(_enumerated value) : _value(value) { } \ + operator _enumerated() const { return _value; } \ + \ + const char* _to_string() const \ + { \ + for (size_t index = 0; index < _count; ++index) { \ + if (_values()[index] == _value) \ + return _names()[index]; \ + } \ + \ + return NULL; \ + } \ + \ + static const size_t _count = IDENTITY(COUNT(__VA_ARGS__)); \ + \ + static const int* _values() \ + { \ + static const int values[] = \ + { IDENTITY(IGNORE_ASSIGN(__VA_ARGS__)) }; \ + return values; \ + } \ + \ + static const char* const* _names() \ + { \ + static const char* const raw_names[] = \ + { IDENTITY(STRINGIZE(__VA_ARGS__)) }; \ + \ + static char* processed_names[_count]; \ + static bool initialized = false; \ + \ + if (!initialized) { \ + for (size_t index = 0; index < _count; ++index) { \ + size_t length = \ + std::strcspn(raw_names[index], " =\t\n\r"); \ + \ + processed_names[index] = new char[length + 1]; \ + \ + strncpy( \ + processed_names[index], raw_names[index], length); \ + processed_names[index][length] = '\0'; \ + } \ + } \ + \ + return processed_names; \ + } \ +}; + + +/* !!! If you are adding new Enums for Events or Params + * Please keep the existing Type_Event_XXX definition (and assign it a value) + * and add your new definition such like Type_NewNotification = XX + */ + +ENUM(ValueID_Index_Alarm, + Type_Start = 0, + Type_Smoke_Alarm = 1, + Type_Carbon_Monoxide = 2, + Type_Carbon_Dioxide = 3, + Type_Heat = 4, + Type_Water = 5, + Type_Access_Control = 6, + Type_Home_Security = 7, + Type_Power_Management = 8, + Type_System = 9, + Type_Emergency = 10, + Type_Clock = 11, + Type_Appliance = 12, + Type_Home_Health = 13, + Type_Siren = 14, + Type_Water_Valve = 15, + Type_Weather = 16, + Type_Irrigation = 17, + Type_Gas = 18, + Type_Event_19, + Type_Event_20, + Type_Event_21, + Type_Event_22, + Type_Event_23, + Type_Event_24, + Type_Event_25, + Type_Event_26, + Type_Event_27, + Type_Event_28, + Type_Event_29, + Type_Event_30, + Type_Event_31, + Type_Event_32, + Type_Event_33, + Type_Event_34, + Type_Event_35, + Type_Event_36, + Type_Event_37, + Type_Event_38, + Type_Event_39, + Type_Event_40, + Type_Event_41, + Type_Event_42, + Type_Event_43, + Type_Event_44, + Type_Event_45, + Type_Event_46, + Type_Event_47, + Type_Event_48, + Type_Event_49, + Type_Event_50, + Type_Event_51, + Type_Event_52, + Type_Event_53, + Type_Event_54, + Type_Event_55, + Type_Event_56, + Type_Event_57, + Type_Event_58, + Type_Event_59, + Type_Event_60, + Type_Event_61, + Type_Event_62, + Type_Event_63, + Type_Event_64, + Type_Event_65, + Type_Event_66, + Type_Event_67, + Type_Event_68, + Type_Event_69, + Type_Event_70, + Type_Event_71, + Type_Event_72, + Type_Event_73, + Type_Event_74, + Type_Event_75, + Type_Event_76, + Type_Event_77, + Type_Event_78, + Type_Event_79, + Type_Event_80, + Type_Event_81, + Type_Event_82, + Type_Event_83, + Type_Event_84, + Type_Event_85, + Type_Event_86, + Type_Event_87, + Type_Event_88, + Type_Event_89, + Type_Event_90, + Type_Event_91, + Type_Event_92, + Type_Event_93, + Type_Event_94, + Type_Event_95, + Type_Event_96, + Type_Event_97, + Type_Event_98, + Type_Event_99, + Type_Event_100, + Type_Event_101, + Type_Event_102, + Type_Event_103, + Type_Event_104, + Type_Event_105, + Type_Event_106, + Type_Event_107, + Type_Event_108, + Type_Event_109, + Type_Event_110, + Type_Event_111, + Type_Event_112, + Type_Event_113, + Type_Event_114, + Type_Event_115, + Type_Event_116, + Type_Event_117, + Type_Event_118, + Type_Event_119, + Type_Event_120, + Type_Event_121, + Type_Event_122, + Type_Event_123, + Type_Event_124, + Type_Event_125, + Type_Event_126, + Type_Event_127, + Type_Event_128, + Type_Event_129, + Type_Event_130, + Type_Event_131, + Type_Event_132, + Type_Event_133, + Type_Event_134, + Type_Event_135, + Type_Event_136, + Type_Event_137, + Type_Event_138, + Type_Event_139, + Type_Event_140, + Type_Event_141, + Type_Event_142, + Type_Event_143, + Type_Event_144, + Type_Event_145, + Type_Event_146, + Type_Event_147, + Type_Event_148, + Type_Event_149, + Type_Event_150, + Type_Event_151, + Type_Event_152, + Type_Event_153, + Type_Event_154, + Type_Event_155, + Type_Event_156, + Type_Event_157, + Type_Event_158, + Type_Event_159, + Type_Event_160, + Type_Event_161, + Type_Event_162, + Type_Event_163, + Type_Event_164, + Type_Event_165, + Type_Event_166, + Type_Event_167, + Type_Event_168, + Type_Event_169, + Type_Event_170, + Type_Event_171, + Type_Event_172, + Type_Event_173, + Type_Event_174, + Type_Event_175, + Type_Event_176, + Type_Event_177, + Type_Event_178, + Type_Event_179, + Type_Event_180, + Type_Event_181, + Type_Event_182, + Type_Event_183, + Type_Event_184, + Type_Event_185, + Type_Event_186, + Type_Event_187, + Type_Event_188, + Type_Event_189, + Type_Event_190, + Type_Event_191, + Type_Event_192, + Type_Event_193, + Type_Event_194, + Type_Event_195, + Type_Event_196, + Type_Event_197, + Type_Event_198, + Type_Event_199, + Type_Event_200, + Type_Event_201, + Type_Event_202, + Type_Event_203, + Type_Event_204, + Type_Event_205, + Type_Event_206, + Type_Event_207, + Type_Event_208, + Type_Event_209, + Type_Event_210, + Type_Event_211, + Type_Event_212, + Type_Event_213, + Type_Event_214, + Type_Event_215, + Type_Event_216, + Type_Event_217, + Type_Event_218, + Type_Event_219, + Type_Event_220, + Type_Event_221, + Type_Event_222, + Type_Event_223, + Type_Event_224, + Type_Event_225, + Type_Event_226, + Type_Event_227, + Type_Event_228, + Type_Event_229, + Type_Event_230, + Type_Event_231, + Type_Event_232, + Type_Event_233, + Type_Event_234, + Type_Event_235, + Type_Event_236, + Type_Event_237, + Type_Event_238, + Type_Event_239, + Type_Event_240, + Type_Event_241, + Type_Event_242, + Type_Event_243, + Type_Event_244, + Type_Event_245, + Type_Event_246, + Type_Event_247, + Type_Event_248, + Type_Event_249, + Type_Event_250, + Type_Event_251, + Type_Event_252, + Type_Event_253, + Type_Event_254, + Type_Event_255, + Type_Event_Param_Previous_Event = 256, + Type_Event_Param_Location = 257, + Type_Event_Param_Result = 258, + Type_Event_Param_Threshold = 259, + Type_Event_Param_UserCode = 260, + Type_Event_Param_261 = 261, + Type_Event_Param_Progress = 262, + Type_Event_Param_Mode = 263, + Type_Event_Param_Obstruction = 264, + Type_Event_Param_Sensor_ID = 265, + Type_Event_Param_Error_Code = 266, + Type_Event_Param_Duration = 267, + Type_Event_Param_Pollution_Level = 268, + Type_Event_Param_Status = 269, + Type_Event_Param_Schedule_ID = 270, + Type_Event_Param_Valve_Table_ID = 271, + Type_Event_Param_272, + Type_Event_Param_273, + Type_Event_Param_274, + Type_Event_Param_275, + Type_Event_Param_276, + Type_Event_Param_277, + Type_Event_Param_278, + Type_Event_Param_279, + Type_Event_Param_280, + Type_Event_Param_281, + Type_Event_Param_282, + Type_Event_Param_283, + Type_Event_Param_284, + Type_Event_Param_285, + Type_Event_Param_286, + Type_Event_Param_287, + Type_Event_Param_288, + Type_Event_Param_289, + Type_Event_Param_290, + Type_Event_Param_291, + Type_Event_Param_292, + Type_Event_Param_293, + Type_Event_Param_294, + Type_Event_Param_295, + Type_Event_Param_296, + Type_Event_Param_297, + Type_Event_Param_298, + Type_Event_Param_299, + Type_Event_Param_300, + Type_Event_Param_301, + Type_Event_Param_302, + Type_Event_Param_303, + Type_Event_Param_304, + Type_Event_Param_305, + Type_Event_Param_306, + Type_Event_Param_307, + Type_Event_Param_308, + Type_Event_Param_309, + Type_Event_Param_310, + Type_Event_Param_311, + Type_Event_Param_312, + Type_Event_Param_313, + Type_Event_Param_314, + Type_Event_Param_315, + Type_Event_Param_316, + Type_Event_Param_317, + Type_Event_Param_318, + Type_Event_Param_319, + Type_Event_Param_320, + Type_Event_Param_321, + Type_Event_Param_322, + Type_Event_Param_323, + Type_Event_Param_324, + Type_Event_Param_325, + Type_Event_Param_326, + Type_Event_Param_327, + Type_Event_Param_328, + Type_Event_Param_329, + Type_Event_Param_330, + Type_Event_Param_331, + Type_Event_Param_332, + Type_Event_Param_333, + Type_Event_Param_334, + Type_Event_Param_335, + Type_Event_Param_336, + Type_Event_Param_337, + Type_Event_Param_338, + Type_Event_Param_339, + Type_Event_Param_340, + Type_Event_Param_341, + Type_Event_Param_342, + Type_Event_Param_343, + Type_Event_Param_344, + Type_Event_Param_345, + Type_Event_Param_346, + Type_Event_Param_347, + Type_Event_Param_348, + Type_Event_Param_349, + Type_Event_Param_350, + Type_Event_Param_351, + Type_Event_Param_352, + Type_Event_Param_353, + Type_Event_Param_354, + Type_Event_Param_355, + Type_Event_Param_356, + Type_Event_Param_357, + Type_Event_Param_358, + Type_Event_Param_359, + Type_Event_Param_360, + Type_Event_Param_361, + Type_Event_Param_362, + Type_Event_Param_363, + Type_Event_Param_364, + Type_Event_Param_365, + Type_Event_Param_366, + Type_Event_Param_367, + Type_Event_Param_368, + Type_Event_Param_369, + Type_Event_Param_370, + Type_Event_Param_371, + Type_Event_Param_372, + Type_Event_Param_373, + Type_Event_Param_374, + Type_Event_Param_375, + Type_Event_Param_376, + Type_Event_Param_377, + Type_Event_Param_378, + Type_Event_Param_379, + Type_Event_Param_380, + Type_Event_Param_381, + Type_Event_Param_382, + Type_Event_Param_383, + Type_Event_Param_384, + Type_Event_Param_385, + Type_Event_Param_386, + Type_Event_Param_387, + Type_Event_Param_388, + Type_Event_Param_389, + Type_Event_Param_390, + Type_Event_Param_391, + Type_Event_Param_392, + Type_Event_Param_393, + Type_Event_Param_394, + Type_Event_Param_395, + Type_Event_Param_396, + Type_Event_Param_397, + Type_Event_Param_398, + Type_Event_Param_399, + Type_Event_Param_400, + Type_Event_Param_401, + Type_Event_Param_402, + Type_Event_Param_403, + Type_Event_Param_404, + Type_Event_Param_405, + Type_Event_Param_406, + Type_Event_Param_407, + Type_Event_Param_408, + Type_Event_Param_409, + Type_Event_Param_410, + Type_Event_Param_411, + Type_Event_Param_412, + Type_Event_Param_413, + Type_Event_Param_414, + Type_Event_Param_415, + Type_Event_Param_416, + Type_Event_Param_417, + Type_Event_Param_418, + Type_Event_Param_419, + Type_Event_Param_420, + Type_Event_Param_421, + Type_Event_Param_422, + Type_Event_Param_423, + Type_Event_Param_424, + Type_Event_Param_425, + Type_Event_Param_426, + Type_Event_Param_427, + Type_Event_Param_428, + Type_Event_Param_429, + Type_Event_Param_430, + Type_Event_Param_431, + Type_Event_Param_432, + Type_Event_Param_433, + Type_Event_Param_434, + Type_Event_Param_435, + Type_Event_Param_436, + Type_Event_Param_437, + Type_Event_Param_438, + Type_Event_Param_439, + Type_Event_Param_440, + Type_Event_Param_441, + Type_Event_Param_442, + Type_Event_Param_443, + Type_Event_Param_444, + Type_Event_Param_445, + Type_Event_Param_446, + Type_Event_Param_447, + Type_Event_Param_448, + Type_Event_Param_449, + Type_Event_Param_450, + Type_Event_Param_451, + Type_Event_Param_452, + Type_Event_Param_453, + Type_Event_Param_454, + Type_Event_Param_455, + Type_Event_Param_456, + Type_Event_Param_457, + Type_Event_Param_458, + Type_Event_Param_459, + Type_Event_Param_460, + Type_Event_Param_461, + Type_Event_Param_462, + Type_Event_Param_463, + Type_Event_Param_464, + Type_Event_Param_465, + Type_Event_Param_466, + Type_Event_Param_467, + Type_Event_Param_468, + Type_Event_Param_469, + Type_Event_Param_470, + Type_Event_Param_471, + Type_Event_Param_472, + Type_Event_Param_473, + Type_Event_Param_474, + Type_Event_Param_475, + Type_Event_Param_476, + Type_Event_Param_477, + Type_Event_Param_478, + Type_Event_Param_479, + Type_Event_Param_480, + Type_Event_Param_481, + Type_Event_Param_482, + Type_Event_Param_483, + Type_Event_Param_484, + Type_Event_Param_485, + Type_Event_Param_486, + Type_Event_Param_487, + Type_Event_Param_488, + Type_Event_Param_489, + Type_Event_Param_490, + Type_Event_Param_491, + Type_Event_Param_492, + Type_Event_Param_493, + Type_Event_Param_494, + Type_Event_Param_495, + Type_Event_Param_496, + Type_Event_Param_497, + Type_Event_Param_498, + Type_Event_Param_499, + Type_Event_Param_500, + Type_Event_Param_501, + Type_Event_Param_502, + Type_Event_Param_503, + Type_Event_Param_504, + Type_Event_Param_505, + Type_Event_Param_506, + Type_Event_Param_507, + Type_Event_Param_508, + Type_Event_Param_509, + Type_Event_Param_510, + Type_Event_Param_511, + Type_v1 = 512, + Level_v1 = 513, + AutoClearEvents = 514 + ); +ENUM(ValueID_Index_AssociationCommandConfiguration, + MaxCommandLength = 0, + CommandsAreValues = 1, + CommandsAreConfigurable = 2, + NumFreeCommands = 3, + MaxCommands = 4 + ); +ENUM(ValueID_Index_BarrierOperator, + Command = 0, + Label = 1, + SupportedSignals = 2, + Audible = 3, + Visual = 4 + ); +ENUM(ValueID_Index_Basic, + Set = 0 + ); +ENUM(ValueID_Index_BasicWindowCovering, + Open = 0, + Close = 1 + ); +ENUM(ValueID_Index_Battery, + Level = 0 + ); +ENUM(ValueID_Index_CentralScene, + Scene_1 = 1, + Scene_2, + Scene_3, + Scene_4, + Scene_5, + Scene_6, + Scene_7, + Scene_8, + Scene_9, + Scene_10, + Scene_11, + Scene_12, + Scene_13, + Scene_14, + Scene_15, + Scene_16, + Scene_17, + Scene_18, + Scene_19, + Scene_20, + Scene_21, + Scene_22, + Scene_23, + Scene_24, + Scene_25, + Scene_26, + Scene_27, + Scene_28, + Scene_29, + Scene_30, + Scene_31, + Scene_32, + Scene_33, + Scene_34, + Scene_35, + Scene_36, + Scene_37, + Scene_38, + Scene_39, + Scene_40, + Scene_41, + Scene_42, + Scene_43, + Scene_44, + Scene_45, + Scene_46, + Scene_47, + Scene_48, + Scene_49, + Scene_50, + Scene_51, + Scene_52, + Scene_53, + Scene_54, + Scene_55, + Scene_56, + Scene_57, + Scene_58, + Scene_59, + Scene_60, + Scene_61, + Scene_62, + Scene_63, + Scene_64, + Scene_65, + Scene_66, + Scene_67, + Scene_68, + Scene_69, + Scene_70, + Scene_71, + Scene_72, + Scene_73, + Scene_74, + Scene_75, + Scene_76, + Scene_77, + Scene_78, + Scene_79, + Scene_80, + Scene_81, + Scene_82, + Scene_83, + Scene_84, + Scene_85, + Scene_86, + Scene_87, + Scene_88, + Scene_89, + Scene_90, + Scene_91, + Scene_92, + Scene_93, + Scene_94, + Scene_95, + Scene_96, + Scene_97, + Scene_98, + Scene_99, + Scene_100, + Scene_101, + Scene_102, + Scene_103, + Scene_104, + Scene_105, + Scene_106, + Scene_107, + Scene_108, + Scene_109, + Scene_110, + Scene_111, + Scene_112, + Scene_113, + Scene_114, + Scene_115, + Scene_116, + Scene_117, + Scene_118, + Scene_119, + Scene_120, + Scene_121, + Scene_122, + Scene_123, + Scene_124, + Scene_125, + Scene_126, + Scene_127, + Scene_128, + Scene_129, + Scene_130, + Scene_131, + Scene_132, + Scene_133, + Scene_134, + Scene_135, + Scene_136, + Scene_137, + Scene_138, + Scene_139, + Scene_140, + Scene_141, + Scene_142, + Scene_143, + Scene_144, + Scene_145, + Scene_146, + Scene_147, + Scene_148, + Scene_149, + Scene_150, + Scene_151, + Scene_152, + Scene_153, + Scene_154, + Scene_155, + Scene_156, + Scene_157, + Scene_158, + Scene_159, + Scene_160, + Scene_161, + Scene_162, + Scene_163, + Scene_164, + Scene_165, + Scene_166, + Scene_167, + Scene_168, + Scene_169, + Scene_170, + Scene_171, + Scene_172, + Scene_173, + Scene_174, + Scene_175, + Scene_176, + Scene_177, + Scene_178, + Scene_179, + Scene_180, + Scene_181, + Scene_182, + Scene_183, + Scene_184, + Scene_185, + Scene_186, + Scene_187, + Scene_188, + Scene_189, + Scene_190, + Scene_191, + Scene_192, + Scene_193, + Scene_194, + Scene_195, + Scene_196, + Scene_197, + Scene_198, + Scene_199, + Scene_200, + Scene_201, + Scene_202, + Scene_203, + Scene_204, + Scene_205, + Scene_206, + Scene_207, + Scene_208, + Scene_209, + Scene_210, + Scene_211, + Scene_212, + Scene_213, + Scene_214, + Scene_215, + Scene_216, + Scene_217, + Scene_218, + Scene_219, + Scene_220, + Scene_221, + Scene_222, + Scene_223, + Scene_224, + Scene_225, + Scene_226, + Scene_227, + Scene_228, + Scene_229, + Scene_230, + Scene_231, + Scene_232, + Scene_233, + Scene_234, + Scene_235, + Scene_236, + Scene_237, + Scene_238, + Scene_239, + Scene_240, + Scene_241, + Scene_242, + Scene_243, + Scene_244, + Scene_245, + Scene_246, + Scene_247, + Scene_248, + Scene_249, + Scene_250, + Scene_251, + Scene_252, + Scene_253, + Scene_254, + Scene_255, + SceneCount = 256, + ClearSceneTimeout = 257 + ); +ENUM(ValueID_Index_ClimateControlSchedule, + DOW_Monday = 1, + DOW_Tuesday = 2, + DOW_Wednesday = 3, + DOW_Thursday = 4, + DOW_Friday = 5, + DOW_Saturday = 6, + DOW_Sunday = 7, + OverrideState = 8, + OverrideSetback = 9 + ); +ENUM(ValueID_Index_Clock, + Day = 0, + Hour = 1, + Minute = 2 + ); +ENUM(ValueID_Index_Color, + Color = 0, + Index = 1, + Channels_Capabilities = 2, + Duration = 4 + ); +ENUM(ValueID_Index_Configuration, + Parameter_1 = 1, + Parameter_2, + Parameter_3, + Parameter_4, + Parameter_5, + Parameter_6, + Parameter_7, + Parameter_8, + Parameter_9, + Parameter_10, + Parameter_11, + Parameter_12, + Parameter_13, + Parameter_14, + Parameter_15, + Parameter_16, + Parameter_17, + Parameter_18, + Parameter_19, + Parameter_20, + Parameter_21, + Parameter_22, + Parameter_23, + Parameter_24, + Parameter_25, + Parameter_26, + Parameter_27, + Parameter_28, + Parameter_29, + Parameter_30, + Parameter_31, + Parameter_32, + Parameter_33, + Parameter_34, + Parameter_35, + Parameter_36, + Parameter_37, + Parameter_38, + Parameter_39, + Parameter_40, + Parameter_41, + Parameter_42, + Parameter_43, + Parameter_44, + Parameter_45, + Parameter_46, + Parameter_47, + Parameter_48, + Parameter_49, + Parameter_50, + Parameter_51, + Parameter_52, + Parameter_53, + Parameter_54, + Parameter_55, + Parameter_56, + Parameter_57, + Parameter_58, + Parameter_59, + Parameter_60, + Parameter_61, + Parameter_62, + Parameter_63, + Parameter_64, + Parameter_65, + Parameter_66, + Parameter_67, + Parameter_68, + Parameter_69, + Parameter_70, + Parameter_71, + Parameter_72, + Parameter_73, + Parameter_74, + Parameter_75, + Parameter_76, + Parameter_77, + Parameter_78, + Parameter_79, + Parameter_80, + Parameter_81, + Parameter_82, + Parameter_83, + Parameter_84, + Parameter_85, + Parameter_86, + Parameter_87, + Parameter_88, + Parameter_89, + Parameter_90, + Parameter_91, + Parameter_92, + Parameter_93, + Parameter_94, + Parameter_95, + Parameter_96, + Parameter_97, + Parameter_98, + Parameter_99, + Parameter_100, + Parameter_101, + Parameter_102, + Parameter_103, + Parameter_104, + Parameter_105, + Parameter_106, + Parameter_107, + Parameter_108, + Parameter_109, + Parameter_110, + Parameter_111, + Parameter_112, + Parameter_113, + Parameter_114, + Parameter_115, + Parameter_116, + Parameter_117, + Parameter_118, + Parameter_119, + Parameter_120, + Parameter_121, + Parameter_122, + Parameter_123, + Parameter_124, + Parameter_125, + Parameter_126, + Parameter_127, + Parameter_128, + Parameter_129, + Parameter_130, + Parameter_131, + Parameter_132, + Parameter_133, + Parameter_134, + Parameter_135, + Parameter_136, + Parameter_137, + Parameter_138, + Parameter_139, + Parameter_140, + Parameter_141, + Parameter_142, + Parameter_143, + Parameter_144, + Parameter_145, + Parameter_146, + Parameter_147, + Parameter_148, + Parameter_149, + Parameter_150, + Parameter_151, + Parameter_152, + Parameter_153, + Parameter_154, + Parameter_155, + Parameter_156, + Parameter_157, + Parameter_158, + Parameter_159, + Parameter_160, + Parameter_161, + Parameter_162, + Parameter_163, + Parameter_164, + Parameter_165, + Parameter_166, + Parameter_167, + Parameter_168, + Parameter_169, + Parameter_170, + Parameter_171, + Parameter_172, + Parameter_173, + Parameter_174, + Parameter_175, + Parameter_176, + Parameter_177, + Parameter_178, + Parameter_179, + Parameter_180, + Parameter_181, + Parameter_182, + Parameter_183, + Parameter_184, + Parameter_185, + Parameter_186, + Parameter_187, + Parameter_188, + Parameter_189, + Parameter_190, + Parameter_191, + Parameter_192, + Parameter_193, + Parameter_194, + Parameter_195, + Parameter_196, + Parameter_197, + Parameter_198, + Parameter_199, + Parameter_200, + Parameter_201, + Parameter_202, + Parameter_203, + Parameter_204, + Parameter_205, + Parameter_206, + Parameter_207, + Parameter_208, + Parameter_209, + Parameter_210, + Parameter_211, + Parameter_212, + Parameter_213, + Parameter_214, + Parameter_215, + Parameter_216, + Parameter_217, + Parameter_218, + Parameter_219, + Parameter_220, + Parameter_221, + Parameter_222, + Parameter_223, + Parameter_224, + Parameter_225, + Parameter_226, + Parameter_227, + Parameter_228, + Parameter_229, + Parameter_230, + Parameter_231, + Parameter_232, + Parameter_233, + Parameter_234, + Parameter_235, + Parameter_236, + Parameter_237, + Parameter_238, + Parameter_239, + Parameter_240, + Parameter_241, + Parameter_242, + Parameter_243, + Parameter_244, + Parameter_245, + Parameter_246, + Parameter_247, + Parameter_248, + Parameter_249, + Parameter_250, + Parameter_251, + Parameter_252, + Parameter_253, + Parameter_254, + Parameter_255 + ); +ENUM(ValueID_Index_ControllerReplication, + NodeId = 0, + Function = 1, + Replicate = 2 + ); +ENUM(ValueID_Index_DoorLock, + Lock = 0, + Lock_Mode = 1, + System_Config_Mode = 2, + System_Config_Minutes = 3, + System_Config_Seconds = 4, + System_Config_OutsideHandles = 5, + System_Config_InsideHandles = 6 + ); +ENUM(ValueID_Index_DoorLockLogging, + System_Config_MaxRecords = 0, + GetRecordNo = 1, + LogRecord = 2 + ); +ENUM(ValueID_Index_EnergyProduction, + Instant = 0, + Total = 1, + Today = 2, + Time = 3 + ); +ENUM(ValueID_Index_Indicator, + Indicator = 0 + ); +ENUM(ValueID_Index_Language, + Language = 0, + Country = 1 + ); +ENUM(ValueID_Index_Lock, + Locked = 0 + ); +ENUM(ValueID_Index_ManufacturerProprietary, + FibaroVenetianBlinds_Blinds = 0, + FibaroVenetianBlinds_Tilt = 1 + ); +ENUM(ValueID_Index_ManufacturerSpecific, + LoadedConfig = 0, + LocalConfig = 1, + LatestConfig = 2, + DeviceID = 3, + SerialNumber = 4 + ); +ENUM(ValueID_Index_Meter, + Electric_kWh = 0, + Electric_kVah, + Electric_W, + Electric_Pulse, + Electric_V, + Electric_A, + Electric_PowerFactor, + Electric_Unknown_1, + Electric_kVar, + Electric_kVarh, + Electric_Unknown_2, + Electric_Unknown_3, + Electric_Unknown_4, + Electric_Unknown_5, + Electric_Unknown_6, + Electric_Unknown_7, + Gas_Cubic_Meters, + Gas_Cubic_Feet, + Gas_Unknown_1, + Gas_Pulse, + Gas_Unknown_2, + Gas_Unknown_3, + Gas_Unknown_4, + Gas_Unknown_5, + Gas_Unknown_6, + Gas_Unknown_7, + Gas_Unknown_8, + Gas_Unknown_9, + Gas_Unknown_10, + Gas_Unknown_11, + Gas_Unknown_12, + Gas_Unknown_13, + Water_Cubic_Meters, + Water_Cubic_Feet, + Water_Cubic_US_Gallons, + Water_Cubic_Pulse, + Water_Unknown_1, + Water_Unknown_2, + Water_Unknown_3, + Water_Unknown_4, + Water_Unknown_5, + Water_Unknown_6, + Water_Unknown_7, + Water_Unknown_8, + Water_Unknown_9, + Water_Unknown_10, + Water_Unknown_11, + Water_Unknown_12, + Heating_kWh, + Heating_Unknown_1, + Heating_Unknown_2, + Heating_Unknown_3, + Heating_Unknown_4, + Heating_Unknown_5, + Heating_Unknown_6, + Heating_Unknown_7, + Heating_Unknown_8, + Heating_Unknown_9, + Heating_Unknown_10, + Heating_Unknown_11, + Heating_Unknown_12, + Heating_Unknown_13, + Heating_Unknown_14, + Heating_Unknown_15, + Cooling_kWh, + Cooling_Unknown_1, + Cooling_Unknown_2, + Cooling_Unknown_3, + Cooling_Unknown_4, + Cooling_Unknown_5, + Cooling_Unknown_6, + Cooling_Unknown_7, + Cooling_Unknown_8, + Cooling_Unknown_9, + Cooling_Unknown_10, + Cooling_Unknown_11, + Cooling_Unknown_12, + Cooling_Unknown_13, + Cooling_Unknown_14, + Cooling_Unknown_15, + Exporting = 256, + Reset = 257 + ); +ENUM(ValueID_Index_MeterPulse, + Count = 0 + ); +ENUM(ValueID_Index_PowerLevel, + Powerlevel = 0, + Timeout = 1, + Set = 2, + TestNode = 3, + TestPowerlevel = 4, + TestFrames = 5, + Test = 6, + Report = 7, + TestStatus = 8, + TestAckFrames = 9 + ); +ENUM(ValueID_Index_Protection, + Protection = 0 + ); +ENUM(ValueID_Index_SceneActivation, + SceneID = 0, + Duration = 1 + ); +ENUM(ValueID_Index_Security, + Secured = 0 + ); +ENUM(ValueID_Index_SensorAlarm, + Sensor_1, + Sensor_2, + Sensor_3, + Sensor_4, + Sensor_5, + Sensor_6, + Sensor_7, + Sensor_8, + Sensor_9, + Sensor_10, + Sensor_11, + Sensor_12, + Sensor_13, + Sensor_14, + Sensor_15, + Sensor_16, + Sensor_17, + Sensor_18, + Sensor_19, + Sensor_20, + Sensor_21, + Sensor_22, + Sensor_23, + Sensor_24, + Sensor_25, + Sensor_26, + Sensor_27, + Sensor_28, + Sensor_29, + Sensor_30, + Sensor_31, + Sensor_32, + Sensor_33, + Sensor_34, + Sensor_35, + Sensor_36, + Sensor_37, + Sensor_38, + Sensor_39, + Sensor_40, + Sensor_41, + Sensor_42, + Sensor_43, + Sensor_44, + Sensor_45, + Sensor_46, + Sensor_47, + Sensor_48, + Sensor_49, + Sensor_50, + Sensor_51, + Sensor_52, + Sensor_53, + Sensor_54, + Sensor_55, + Sensor_56, + Sensor_57, + Sensor_58, + Sensor_59, + Sensor_60, + Sensor_61, + Sensor_62, + Sensor_63, + Sensor_64, + Sensor_65, + Sensor_66, + Sensor_67, + Sensor_68, + Sensor_69, + Sensor_70, + Sensor_71, + Sensor_72, + Sensor_73, + Sensor_74, + Sensor_75, + Sensor_76, + Sensor_77, + Sensor_78, + Sensor_79, + Sensor_80, + Sensor_81, + Sensor_82, + Sensor_83, + Sensor_84, + Sensor_85, + Sensor_86, + Sensor_87, + Sensor_88, + Sensor_89, + Sensor_90, + Sensor_91, + Sensor_92, + Sensor_93, + Sensor_94, + Sensor_95, + Sensor_96, + Sensor_97, + Sensor_98, + Sensor_99, + Sensor_100, + Sensor_101, + Sensor_102, + Sensor_103, + Sensor_104, + Sensor_105, + Sensor_106, + Sensor_107, + Sensor_108, + Sensor_109, + Sensor_110, + Sensor_111, + Sensor_112, + Sensor_113, + Sensor_114, + Sensor_115, + Sensor_116, + Sensor_117, + Sensor_118, + Sensor_119, + Sensor_120, + Sensor_121, + Sensor_122, + Sensor_123, + Sensor_124, + Sensor_125, + Sensor_126, + Sensor_127, + Sensor_128, + Sensor_129, + Sensor_130, + Sensor_131, + Sensor_132, + Sensor_133, + Sensor_134, + Sensor_135, + Sensor_136, + Sensor_137, + Sensor_138, + Sensor_139, + Sensor_140, + Sensor_141, + Sensor_142, + Sensor_143, + Sensor_144, + Sensor_145, + Sensor_146, + Sensor_147, + Sensor_148, + Sensor_149, + Sensor_150, + Sensor_151, + Sensor_152, + Sensor_153, + Sensor_154, + Sensor_155, + Sensor_156, + Sensor_157, + Sensor_158, + Sensor_159, + Sensor_160, + Sensor_161, + Sensor_162, + Sensor_163, + Sensor_164, + Sensor_165, + Sensor_166, + Sensor_167, + Sensor_168, + Sensor_169, + Sensor_170, + Sensor_171, + Sensor_172, + Sensor_173, + Sensor_174, + Sensor_175, + Sensor_176, + Sensor_177, + Sensor_178, + Sensor_179, + Sensor_180, + Sensor_181, + Sensor_182, + Sensor_183, + Sensor_184, + Sensor_185, + Sensor_186, + Sensor_187, + Sensor_188, + Sensor_189, + Sensor_190, + Sensor_191, + Sensor_192, + Sensor_193, + Sensor_194, + Sensor_195, + Sensor_196, + Sensor_197, + Sensor_198, + Sensor_199, + Sensor_200, + Sensor_201, + Sensor_202, + Sensor_203, + Sensor_204, + Sensor_205, + Sensor_206, + Sensor_207, + Sensor_208, + Sensor_209, + Sensor_210, + Sensor_211, + Sensor_212, + Sensor_213, + Sensor_214, + Sensor_215, + Sensor_216, + Sensor_217, + Sensor_218, + Sensor_219, + Sensor_220, + Sensor_221, + Sensor_222, + Sensor_223, + Sensor_224, + Sensor_225, + Sensor_226, + Sensor_227, + Sensor_228, + Sensor_229, + Sensor_230, + Sensor_231, + Sensor_232, + Sensor_233, + Sensor_234, + Sensor_235, + Sensor_236, + Sensor_237, + Sensor_238, + Sensor_239, + Sensor_240, + Sensor_241, + Sensor_242, + Sensor_243, + Sensor_244, + Sensor_245, + Sensor_246, + Sensor_247, + Sensor_248, + Sensor_249, + Sensor_250, + Sensor_251, + Sensor_252, + Sensor_253, + Sensor_254, + Sensor_255 + ); +ENUM(ValueID_Index_SensorBinary, + Sensor_1, + Sensor_2, + Sensor_3, + Sensor_4, + Sensor_5, + Sensor_6, + Sensor_7, + Sensor_8, + Sensor_9, + Sensor_10, + Sensor_11, + Sensor_12, + Sensor_13, + Sensor_14, + Sensor_15, + Sensor_16, + Sensor_17, + Sensor_18, + Sensor_19, + Sensor_20, + Sensor_21, + Sensor_22, + Sensor_23, + Sensor_24, + Sensor_25, + Sensor_26, + Sensor_27, + Sensor_28, + Sensor_29, + Sensor_30, + Sensor_31, + Sensor_32, + Sensor_33, + Sensor_34, + Sensor_35, + Sensor_36, + Sensor_37, + Sensor_38, + Sensor_39, + Sensor_40, + Sensor_41, + Sensor_42, + Sensor_43, + Sensor_44, + Sensor_45, + Sensor_46, + Sensor_47, + Sensor_48, + Sensor_49, + Sensor_50, + Sensor_51, + Sensor_52, + Sensor_53, + Sensor_54, + Sensor_55, + Sensor_56, + Sensor_57, + Sensor_58, + Sensor_59, + Sensor_60, + Sensor_61, + Sensor_62, + Sensor_63, + Sensor_64, + Sensor_65, + Sensor_66, + Sensor_67, + Sensor_68, + Sensor_69, + Sensor_70, + Sensor_71, + Sensor_72, + Sensor_73, + Sensor_74, + Sensor_75, + Sensor_76, + Sensor_77, + Sensor_78, + Sensor_79, + Sensor_80, + Sensor_81, + Sensor_82, + Sensor_83, + Sensor_84, + Sensor_85, + Sensor_86, + Sensor_87, + Sensor_88, + Sensor_89, + Sensor_90, + Sensor_91, + Sensor_92, + Sensor_93, + Sensor_94, + Sensor_95, + Sensor_96, + Sensor_97, + Sensor_98, + Sensor_99, + Sensor_100, + Sensor_101, + Sensor_102, + Sensor_103, + Sensor_104, + Sensor_105, + Sensor_106, + Sensor_107, + Sensor_108, + Sensor_109, + Sensor_110, + Sensor_111, + Sensor_112, + Sensor_113, + Sensor_114, + Sensor_115, + Sensor_116, + Sensor_117, + Sensor_118, + Sensor_119, + Sensor_120, + Sensor_121, + Sensor_122, + Sensor_123, + Sensor_124, + Sensor_125, + Sensor_126, + Sensor_127, + Sensor_128, + Sensor_129, + Sensor_130, + Sensor_131, + Sensor_132, + Sensor_133, + Sensor_134, + Sensor_135, + Sensor_136, + Sensor_137, + Sensor_138, + Sensor_139, + Sensor_140, + Sensor_141, + Sensor_142, + Sensor_143, + Sensor_144, + Sensor_145, + Sensor_146, + Sensor_147, + Sensor_148, + Sensor_149, + Sensor_150, + Sensor_151, + Sensor_152, + Sensor_153, + Sensor_154, + Sensor_155, + Sensor_156, + Sensor_157, + Sensor_158, + Sensor_159, + Sensor_160, + Sensor_161, + Sensor_162, + Sensor_163, + Sensor_164, + Sensor_165, + Sensor_166, + Sensor_167, + Sensor_168, + Sensor_169, + Sensor_170, + Sensor_171, + Sensor_172, + Sensor_173, + Sensor_174, + Sensor_175, + Sensor_176, + Sensor_177, + Sensor_178, + Sensor_179, + Sensor_180, + Sensor_181, + Sensor_182, + Sensor_183, + Sensor_184, + Sensor_185, + Sensor_186, + Sensor_187, + Sensor_188, + Sensor_189, + Sensor_190, + Sensor_191, + Sensor_192, + Sensor_193, + Sensor_194, + Sensor_195, + Sensor_196, + Sensor_197, + Sensor_198, + Sensor_199, + Sensor_200, + Sensor_201, + Sensor_202, + Sensor_203, + Sensor_204, + Sensor_205, + Sensor_206, + Sensor_207, + Sensor_208, + Sensor_209, + Sensor_210, + Sensor_211, + Sensor_212, + Sensor_213, + Sensor_214, + Sensor_215, + Sensor_216, + Sensor_217, + Sensor_218, + Sensor_219, + Sensor_220, + Sensor_221, + Sensor_222, + Sensor_223, + Sensor_224, + Sensor_225, + Sensor_226, + Sensor_227, + Sensor_228, + Sensor_229, + Sensor_230, + Sensor_231, + Sensor_232, + Sensor_233, + Sensor_234, + Sensor_235, + Sensor_236, + Sensor_237, + Sensor_238, + Sensor_239, + Sensor_240, + Sensor_241, + Sensor_242, + Sensor_243, + Sensor_244, + Sensor_245, + Sensor_246, + Sensor_247, + Sensor_248, + Sensor_249, + Sensor_250, + Sensor_251, + Sensor_252, + Sensor_253, + Sensor_254, + Sensor_255 + ); +ENUM(ValueID_Index_SensorMultiLevel, + Air_Temperature = 1, + General_Purpose, + Luminance, + Power, + Humidity, + Velocity, + Direction, + Atmospheric_Pressure, + Barometric_Pressure, + Solar_Radiation, + Dew_Point, + Rain_Rate, + Tide_Level, + Weight, + Voltage, + Current, + Carbon_Dioxide, + Air_Flow, + Tank_Capacity, + Distance, + Angle_Position, + Rotation, + Water_Temperature, + Soil_Temperature, + Seismic_Intensity, + Seismic_Magnitude, + Ultraviolet, + Electrical_Resistivity, + Electrical_Conductivity, + Loudness, + Moisture, + Frequency, + Time, + Target_Temperature, + Particulate_Mater_2_5, + Formaldehyde_CH20_Level, + Radon_Concentration, + Methane_Density, + Volatile_Organic_Compound, + Carbon_Monoxide, + Soil_Humidity, + Soil_Reactivity, + Soil_Salinity, + Heart_Beat, + Blood_Pressure, + Muscle_Mass, + Fat_Mass, + Bone_Mass, + Total_Body_Water, + Basic_Metabolic_Rate, + Body_Mass_Index, + X_Axis_Acceleration, + Y_Axis_Acceleration, + Z_Axis_Acceleration, + Smoke_Density, + Water_Flow, + Water_Pressure, + RF_Signal_Strength, + Particulate_Matter, + Respiratory_Rate, + Relative_Modulation, + Boiler_Water_Temperature, + Domestic_Hot_Water_Temperature, + Outside_Temperature, + Exhaust_Temperature, + Water_Chlorine, + Water_Acidity, + Water_Oxidation_Reduction_Potential, + Heart_Rate_LF_HF_Ratio, + Motion_Direction, + Applied_Force, + Return_Air_Temperature, + Supply_Air_Temperature, + Condenser_Coil_Temperature, + Evaporator_Coil_Temperature, + Liquid_Line_Temperature, + Discharge_Line_Temperature, + Suction, + Discharge, + Defrost_Temperature, + Ozone, + Sulfur_Dioxide, + Nitrogen_Dioxide, + Ammonia, + Lead, + Particulate_Matter_v2, + Air_Temperature_Units = 256, + General_Purpose_Units, + Luminance_Units, + Power_Units, + Humidity_Units, + Velocity_Units, + Direction_Units, + Atmospheric_Pressure_Units, + Barometric_Pressure_Units, + Solar_Radiation_Units, + Dew_Point_Units, + Rain_Rate_Units, + Tide_Level_Units, + Weight_Units, + Voltage_Units, + Current_Units, + Carbon_Dioxide_Units, + Air_Flow_Units, + Tank_Capacity_Units, + Distance_Units, + Angle_Position_Units, + Rotation_Units, + Water_Temperature_Units, + Soil_Temperature_Units, + Seismic_Intensity_Units, + Seismic_Magnitude_Units, + Ultraviolet_Units, + Electrical_Resistivity_Units, + Electrical_Conductivity_Units, + Loudness_Units, + Moisture_Units, + Frequency_Units, + Time_Units, + Target_Temperature_Units, + Particulate_Mater_2_5_Units, + Formaldehyde_CH20_Level_Units, + Radon_Concentration_Units, + Methane_Density_Units, + Volatile_Organic_Compound_Units, + Carbon_Monoxide_Units, + Soil_Humidity_Units, + Soil_Reactivity_Units, + Soil_Salinity_Units, + Heart_Beat_Units, + Blood_Pressure_Units, + Muscle_Mass_Units, + Fat_Mass_Units, + Bone_Mass_Units, + Total_Body_Water_Units, + Basic_Metabolic_Rate_Units, + Body_Mass_Index_Units, + X_Axis_Acceleration_Units, + Y_Axis_Acceleration_Units, + Z_Axis_Acceleration_Units, + Smoke_Density_Units, + Water_Flow_Units, + Water_Pressure_Units, + RF_Signal_Strength_Units, + Particulate_Matter_Units, + Respiratory_Rate_Units, + Relative_Modulation_Units, + Boiler_Water_Temperature_Units, + Domestic_Hot_Water_Temperature_Units, + Outside_Temperature_Units, + Exhaust_Temperature_Units, + Water_Chlorine_Units, + Water_Acidity_Units, + Water_Oxidation_Reduction_Potential_Units, + Heart_Rate_LF_HF_Ratio_Units, + Motion_Direction_Units, + Applied_Force_Units, + Return_Air_Temperature_Units, + Supply_Air_Temperature_Units, + Condenser_Coil_Temperature_Units, + Evaporator_Coil_Temperature_Units, + Liquid_Line_Temperature_Units, + Discharge_Line_Temperature_Units, + Suction_Units, + Discharge_Units, + Defrost_Temperature_Units, + Ozone_Units, + Sulfur_Dioxide_Units, + Nitrogen_Dioxide_Units, + Ammonia_Units, + Lead_Units, + Particulate_Matter_v2_Units + + ); +ENUM(ValueID_Index_SimpleAV, + Command = 0 + ); +ENUM(ValueID_Index_SoundSwitch, + Tone_Count = 0, + Tones = 1, + Volume = 2, + Default_Tone = 3 + ); +ENUM(ValueID_Index_SwitchAll, + SwitchAll = 0 + ); +ENUM(ValueID_Index_SwitchBinary, + Level = 0, + TargetState = 1, + Duration = 2 + ); +ENUM(ValueID_Index_SwitchMultiLevel, + Level = 0, + Bright = 1, + Dim = 2, + IgnoreStartLevel = 3, + StartLevel = 4, + Duration = 5, + Step = 6, + Inc = 7, + Dec = 8, + TargetValue = 9 + ); +ENUM(ValueID_Index_SwitchToggleBinary, + ToggleSwitch = 0 + ); +ENUM(ValueID_Index_SwitchToggleMultilevel, + Level = 0 + ); +ENUM(ValueID_Index_ThermostatFanMode, + FanMode = 0 + ); +ENUM(ValueID_Index_ThermostatFanState, + FanState = 0 + ); +ENUM(ValueID_Index_ThermostatMode, + Mode = 0 + ); +ENUM(ValueID_Index_ThermostatOperatingState, + OperatingState = 0 + ); +ENUM(ValueID_Index_ThermostatSetpoint, + Unused_0 = 0, + Heating, + Cooling, + Unused_3, + Unused_4, + Unused_5, + Unused_6, + Furnace, + DryAir, + MoistAir, + AutoChangeover, + HeatingEcon, + CoolingEcon, + AwayHeating, + CoolingHeating, + Unused_0_Minimum = 100, + Heating_Minimum, + Cooling_Minimum, + Unused_3_Minimum, + Unused_4_Minimum, + Unused_5_Minimum, + Unused_6_Minimum, + Furnace_Minimum, + DryAir_Minimum, + MoistAir_Minimum, + AutoChangeOver_Minimum, + Heating_Econ_Minimum, + Cooling_Econ_Minimum, + Away_Heating_Minimum, + Cooling_Heating_Minimum, + Unused_0_Maximum = 200, + Heating_Maximum, + Cooling_Maximum, + Unused_3_Maximum, + Unused_4_Maximum, + Unused_5_Maximum, + Unused_6_Maximum, + Furnace_Maximum, + DryAir_Maximum, + MoistAir_Maximum, + AutoChangeOver_Maximum, + Heating_Econ_Maximum, + Cooling_Econ_Maximum, + Away_Heating_Maximum, + Cooling_Heating_Maximum + ); +ENUM(ValueID_Index_TimeParameters, + Date = 0, + Time = 1, + Set = 2, + Refresh = 3 + ); +ENUM(ValueID_Index_UserCode, + Enrollment_Code = 0, + Code_1, + Code_2, + Code_3, + Code_4, + Code_5, + Code_6, + Code_7, + Code_8, + Code_9, + Code_10, + Code_11, + Code_12, + Code_13, + Code_14, + Code_15, + Code_16, + Code_17, + Code_18, + Code_19, + Code_20, + Code_21, + Code_22, + Code_23, + Code_24, + Code_25, + Code_26, + Code_27, + Code_28, + Code_29, + Code_30, + Code_31, + Code_32, + Code_33, + Code_34, + Code_35, + Code_36, + Code_37, + Code_38, + Code_39, + Code_40, + Code_41, + Code_42, + Code_43, + Code_44, + Code_45, + Code_46, + Code_47, + Code_48, + Code_49, + Code_50, + Code_51, + Code_52, + Code_53, + Code_54, + Code_55, + Code_56, + Code_57, + Code_58, + Code_59, + Code_60, + Code_61, + Code_62, + Code_63, + Code_64, + Code_65, + Code_66, + Code_67, + Code_68, + Code_69, + Code_70, + Code_71, + Code_72, + Code_73, + Code_74, + Code_75, + Code_76, + Code_77, + Code_78, + Code_79, + Code_80, + Code_81, + Code_82, + Code_83, + Code_84, + Code_85, + Code_86, + Code_87, + Code_88, + Code_89, + Code_90, + Code_91, + Code_92, + Code_93, + Code_94, + Code_95, + Code_96, + Code_97, + Code_98, + Code_99, + Code_100, + Code_101, + Code_102, + Code_103, + Code_104, + Code_105, + Code_106, + Code_107, + Code_108, + Code_109, + Code_110, + Code_111, + Code_112, + Code_113, + Code_114, + Code_115, + Code_116, + Code_117, + Code_118, + Code_119, + Code_120, + Code_121, + Code_122, + Code_123, + Code_124, + Code_125, + Code_126, + Code_127, + Code_128, + Code_129, + Code_130, + Code_131, + Code_132, + Code_133, + Code_134, + Code_135, + Code_136, + Code_137, + Code_138, + Code_139, + Code_140, + Code_141, + Code_142, + Code_143, + Code_144, + Code_145, + Code_146, + Code_147, + Code_148, + Code_149, + Code_150, + Code_151, + Code_152, + Code_153, + Code_154, + Code_155, + Code_156, + Code_157, + Code_158, + Code_159, + Code_160, + Code_161, + Code_162, + Code_163, + Code_164, + Code_165, + Code_166, + Code_167, + Code_168, + Code_169, + Code_170, + Code_171, + Code_172, + Code_173, + Code_174, + Code_175, + Code_176, + Code_177, + Code_178, + Code_179, + Code_180, + Code_181, + Code_182, + Code_183, + Code_184, + Code_185, + Code_186, + Code_187, + Code_188, + Code_189, + Code_190, + Code_191, + Code_192, + Code_193, + Code_194, + Code_195, + Code_196, + Code_197, + Code_198, + Code_199, + Code_200, + Code_201, + Code_202, + Code_203, + Code_204, + Code_205, + Code_206, + Code_207, + Code_208, + Code_209, + Code_210, + Code_211, + Code_212, + Code_213, + Code_214, + Code_215, + Code_216, + Code_217, + Code_218, + Code_219, + Code_220, + Code_221, + Code_222, + Code_223, + Code_224, + Code_225, + Code_226, + Code_227, + Code_228, + Code_229, + Code_230, + Code_231, + Code_232, + Code_233, + Code_234, + Code_235, + Code_236, + Code_237, + Code_238, + Code_239, + Code_240, + Code_241, + Code_242, + Code_243, + Code_244, + Code_245, + Code_246, + Code_247, + Code_248, + Code_249, + Code_250, + Code_251, + Code_252, + Code_253, + Refresh = 255, + RemoveCode = 256, + Count = 257, + RawValue = 258, + RawValueIndex = 259 + ); +ENUM(ValueID_Index_Version, + Library = 0, + Protocol = 1, + Application = 2 + ); +ENUM(ValueID_Index_WakeUp, + Interval = 0, + Min_Interval = 1, + Max_Interval = 2, + Default_Interval = 3, + Interval_Step = 4 + ); +ENUM(ValueID_Index_ZWavePlusInfo, + Version = 0, + InstallerIcon = 1, + UserIcon = 2 + ); +#endif diff --git a/cpp/src/ValueIDIndexesDefines.h b/cpp/src/ValueIDIndexesDefines.h new file mode 100644 index 0000000000..48053dcc20 --- /dev/null +++ b/cpp/src/ValueIDIndexesDefines.h @@ -0,0 +1,160 @@ +struct ignore_assign { + ignore_assign(int value) : _value(value) { } + operator int() const { return _value; } + + const ignore_assign& operator =(int dummy) { (void)dummy; return *this; } + + int _value; +}; +struct ValueID_Index_Alarm { enum _enumerated { Type_Start = 0, Type_Smoke_Alarm = 1, Type_Carbon_Monoxide = 2, Type_Carbon_Dioxide = 3, Type_Heat = 4, Type_Water = 5, Type_Access_Control = 6, Type_Home_Security = 7, Type_Power_Management = 8, Type_System = 9, Type_Emergency = 10, Type_Clock = 11, Type_Appliance = 12, Type_Home_Health = 13, Type_Siren = 14, Type_Water_Valve = 15, Type_Weather = 16, Type_Irrigation = 17, Type_Gas = 18, Type_Event_19, Type_Event_20, Type_Event_21, Type_Event_22, Type_Event_23, Type_Event_24, Type_Event_25, Type_Event_26, Type_Event_27, Type_Event_28, Type_Event_29, Type_Event_30, Type_Event_31, Type_Event_32, Type_Event_33, Type_Event_34, Type_Event_35, Type_Event_36, Type_Event_37, Type_Event_38, Type_Event_39, Type_Event_40, Type_Event_41, Type_Event_42, Type_Event_43, Type_Event_44, Type_Event_45, Type_Event_46, Type_Event_47, Type_Event_48, Type_Event_49, Type_Event_50, Type_Event_51, Type_Event_52, Type_Event_53, Type_Event_54, Type_Event_55, Type_Event_56, Type_Event_57, Type_Event_58, Type_Event_59, Type_Event_60, Type_Event_61, Type_Event_62, Type_Event_63, Type_Event_64, Type_Event_65, Type_Event_66, Type_Event_67, Type_Event_68, Type_Event_69, Type_Event_70, Type_Event_71, Type_Event_72, Type_Event_73, Type_Event_74, Type_Event_75, Type_Event_76, Type_Event_77, Type_Event_78, Type_Event_79, Type_Event_80, Type_Event_81, Type_Event_82, Type_Event_83, Type_Event_84, Type_Event_85, Type_Event_86, Type_Event_87, Type_Event_88, Type_Event_89, Type_Event_90, Type_Event_91, Type_Event_92, Type_Event_93, Type_Event_94, Type_Event_95, Type_Event_96, Type_Event_97, Type_Event_98, Type_Event_99, Type_Event_100, Type_Event_101, Type_Event_102, Type_Event_103, Type_Event_104, Type_Event_105, Type_Event_106, Type_Event_107, Type_Event_108, Type_Event_109, Type_Event_110, Type_Event_111, Type_Event_112, Type_Event_113, Type_Event_114, Type_Event_115, Type_Event_116, Type_Event_117, Type_Event_118, Type_Event_119, Type_Event_120, Type_Event_121, Type_Event_122, Type_Event_123, Type_Event_124, Type_Event_125, Type_Event_126, Type_Event_127, Type_Event_128, Type_Event_129, Type_Event_130, Type_Event_131, Type_Event_132, Type_Event_133, Type_Event_134, Type_Event_135, Type_Event_136, Type_Event_137, Type_Event_138, Type_Event_139, Type_Event_140, Type_Event_141, Type_Event_142, Type_Event_143, Type_Event_144, Type_Event_145, Type_Event_146, Type_Event_147, Type_Event_148, Type_Event_149, Type_Event_150, Type_Event_151, Type_Event_152, Type_Event_153, Type_Event_154, Type_Event_155, Type_Event_156, Type_Event_157, Type_Event_158, Type_Event_159, Type_Event_160, Type_Event_161, Type_Event_162, Type_Event_163, Type_Event_164, Type_Event_165, Type_Event_166, Type_Event_167, Type_Event_168, Type_Event_169, Type_Event_170, Type_Event_171, Type_Event_172, Type_Event_173, Type_Event_174, Type_Event_175, Type_Event_176, Type_Event_177, Type_Event_178, Type_Event_179, Type_Event_180, Type_Event_181, Type_Event_182, Type_Event_183, Type_Event_184, Type_Event_185, Type_Event_186, Type_Event_187, Type_Event_188, Type_Event_189, Type_Event_190, Type_Event_191, Type_Event_192, Type_Event_193, Type_Event_194, Type_Event_195, Type_Event_196, Type_Event_197, Type_Event_198, Type_Event_199, Type_Event_200, Type_Event_201, Type_Event_202, Type_Event_203, Type_Event_204, Type_Event_205, Type_Event_206, Type_Event_207, Type_Event_208, Type_Event_209, Type_Event_210, Type_Event_211, Type_Event_212, Type_Event_213, Type_Event_214, Type_Event_215, Type_Event_216, Type_Event_217, Type_Event_218, Type_Event_219, Type_Event_220, Type_Event_221, Type_Event_222, Type_Event_223, Type_Event_224, Type_Event_225, Type_Event_226, Type_Event_227, Type_Event_228, Type_Event_229, Type_Event_230, Type_Event_231, Type_Event_232, Type_Event_233, Type_Event_234, Type_Event_235, Type_Event_236, Type_Event_237, Type_Event_238, Type_Event_239, Type_Event_240, Type_Event_241, Type_Event_242, Type_Event_243, Type_Event_244, Type_Event_245, Type_Event_246, Type_Event_247, Type_Event_248, Type_Event_249, Type_Event_250, Type_Event_251, Type_Event_252, Type_Event_253, Type_Event_254, Type_Event_255, Type_Event_Param_Previous_Event = 256, Type_Event_Param_Location = 257, Type_Event_Param_Result = 258, Type_Event_Param_Threshold = 259, Type_Event_Param_UserCode = 260, Type_Event_Param_261 = 261, Type_Event_Param_Progress = 262, Type_Event_Param_Mode = 263, Type_Event_Param_Obstruction = 264, Type_Event_Param_Sensor_ID = 265, Type_Event_Param_Error_Code = 266, Type_Event_Param_Duration = 267, Type_Event_Param_Pollution_Level = 268, Type_Event_Param_Status = 269, Type_Event_Param_Schedule_ID = 270, Type_Event_Param_Valve_Table_ID = 271, Type_Event_Param_272, Type_Event_Param_273, Type_Event_Param_274, Type_Event_Param_275, Type_Event_Param_276, Type_Event_Param_277, Type_Event_Param_278, Type_Event_Param_279, Type_Event_Param_280, Type_Event_Param_281, Type_Event_Param_282, Type_Event_Param_283, Type_Event_Param_284, Type_Event_Param_285, Type_Event_Param_286, Type_Event_Param_287, Type_Event_Param_288, Type_Event_Param_289, Type_Event_Param_290, Type_Event_Param_291, Type_Event_Param_292, Type_Event_Param_293, Type_Event_Param_294, Type_Event_Param_295, Type_Event_Param_296, Type_Event_Param_297, Type_Event_Param_298, Type_Event_Param_299, Type_Event_Param_300, Type_Event_Param_301, Type_Event_Param_302, Type_Event_Param_303, Type_Event_Param_304, Type_Event_Param_305, Type_Event_Param_306, Type_Event_Param_307, Type_Event_Param_308, Type_Event_Param_309, Type_Event_Param_310, Type_Event_Param_311, Type_Event_Param_312, Type_Event_Param_313, Type_Event_Param_314, Type_Event_Param_315, Type_Event_Param_316, Type_Event_Param_317, Type_Event_Param_318, Type_Event_Param_319, Type_Event_Param_320, Type_Event_Param_321, Type_Event_Param_322, Type_Event_Param_323, Type_Event_Param_324, Type_Event_Param_325, Type_Event_Param_326, Type_Event_Param_327, Type_Event_Param_328, Type_Event_Param_329, Type_Event_Param_330, Type_Event_Param_331, Type_Event_Param_332, Type_Event_Param_333, Type_Event_Param_334, Type_Event_Param_335, Type_Event_Param_336, Type_Event_Param_337, Type_Event_Param_338, Type_Event_Param_339, Type_Event_Param_340, Type_Event_Param_341, Type_Event_Param_342, Type_Event_Param_343, Type_Event_Param_344, Type_Event_Param_345, Type_Event_Param_346, Type_Event_Param_347, Type_Event_Param_348, Type_Event_Param_349, Type_Event_Param_350, Type_Event_Param_351, Type_Event_Param_352, Type_Event_Param_353, Type_Event_Param_354, Type_Event_Param_355, Type_Event_Param_356, Type_Event_Param_357, Type_Event_Param_358, Type_Event_Param_359, Type_Event_Param_360, Type_Event_Param_361, Type_Event_Param_362, Type_Event_Param_363, Type_Event_Param_364, Type_Event_Param_365, Type_Event_Param_366, Type_Event_Param_367, Type_Event_Param_368, Type_Event_Param_369, Type_Event_Param_370, Type_Event_Param_371, Type_Event_Param_372, Type_Event_Param_373, Type_Event_Param_374, Type_Event_Param_375, Type_Event_Param_376, Type_Event_Param_377, Type_Event_Param_378, Type_Event_Param_379, Type_Event_Param_380, Type_Event_Param_381, Type_Event_Param_382, Type_Event_Param_383, Type_Event_Param_384, Type_Event_Param_385, Type_Event_Param_386, Type_Event_Param_387, Type_Event_Param_388, Type_Event_Param_389, Type_Event_Param_390, Type_Event_Param_391, Type_Event_Param_392, Type_Event_Param_393, Type_Event_Param_394, Type_Event_Param_395, Type_Event_Param_396, Type_Event_Param_397, Type_Event_Param_398, Type_Event_Param_399, Type_Event_Param_400, Type_Event_Param_401, Type_Event_Param_402, Type_Event_Param_403, Type_Event_Param_404, Type_Event_Param_405, Type_Event_Param_406, Type_Event_Param_407, Type_Event_Param_408, Type_Event_Param_409, Type_Event_Param_410, Type_Event_Param_411, Type_Event_Param_412, Type_Event_Param_413, Type_Event_Param_414, Type_Event_Param_415, Type_Event_Param_416, Type_Event_Param_417, Type_Event_Param_418, Type_Event_Param_419, Type_Event_Param_420, Type_Event_Param_421, Type_Event_Param_422, Type_Event_Param_423, Type_Event_Param_424, Type_Event_Param_425, Type_Event_Param_426, Type_Event_Param_427, Type_Event_Param_428, Type_Event_Param_429, Type_Event_Param_430, Type_Event_Param_431, Type_Event_Param_432, Type_Event_Param_433, Type_Event_Param_434, Type_Event_Param_435, Type_Event_Param_436, Type_Event_Param_437, Type_Event_Param_438, Type_Event_Param_439, Type_Event_Param_440, Type_Event_Param_441, Type_Event_Param_442, Type_Event_Param_443, Type_Event_Param_444, Type_Event_Param_445, Type_Event_Param_446, Type_Event_Param_447, Type_Event_Param_448, Type_Event_Param_449, Type_Event_Param_450, Type_Event_Param_451, Type_Event_Param_452, Type_Event_Param_453, Type_Event_Param_454, Type_Event_Param_455, Type_Event_Param_456, Type_Event_Param_457, Type_Event_Param_458, Type_Event_Param_459, Type_Event_Param_460, Type_Event_Param_461, Type_Event_Param_462, Type_Event_Param_463, Type_Event_Param_464, Type_Event_Param_465, Type_Event_Param_466, Type_Event_Param_467, Type_Event_Param_468, Type_Event_Param_469, Type_Event_Param_470, Type_Event_Param_471, Type_Event_Param_472, Type_Event_Param_473, Type_Event_Param_474, Type_Event_Param_475, Type_Event_Param_476, Type_Event_Param_477, Type_Event_Param_478, Type_Event_Param_479, Type_Event_Param_480, Type_Event_Param_481, Type_Event_Param_482, Type_Event_Param_483, Type_Event_Param_484, Type_Event_Param_485, Type_Event_Param_486, Type_Event_Param_487, Type_Event_Param_488, Type_Event_Param_489, Type_Event_Param_490, Type_Event_Param_491, Type_Event_Param_492, Type_Event_Param_493, Type_Event_Param_494, Type_Event_Param_495, Type_Event_Param_496, Type_Event_Param_497, Type_Event_Param_498, Type_Event_Param_499, Type_Event_Param_500, Type_Event_Param_501, Type_Event_Param_502, Type_Event_Param_503, Type_Event_Param_504, Type_Event_Param_505, Type_Event_Param_506, Type_Event_Param_507, Type_Event_Param_508, Type_Event_Param_509, Type_Event_Param_510, Type_Event_Param_511, Type_v1 = 512, Level_v1 = 513, AutoClearEvents = 514 }; _enumerated _value; ValueID_Index_Alarm(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 515; static const int* _values() { static const int values[] = { (ignore_assign)Type_Start = 0, (ignore_assign)Type_Smoke_Alarm = 1, (ignore_assign)Type_Carbon_Monoxide = 2, (ignore_assign)Type_Carbon_Dioxide = 3, (ignore_assign)Type_Heat = 4, (ignore_assign)Type_Water = 5, (ignore_assign)Type_Access_Control = 6, (ignore_assign)Type_Home_Security = 7, (ignore_assign)Type_Power_Management = 8, (ignore_assign)Type_System = 9, (ignore_assign)Type_Emergency = 10, (ignore_assign)Type_Clock = 11, (ignore_assign)Type_Appliance = 12, (ignore_assign)Type_Home_Health = 13, (ignore_assign)Type_Siren = 14, (ignore_assign)Type_Water_Valve = 15, (ignore_assign)Type_Weather = 16, (ignore_assign)Type_Irrigation = 17, (ignore_assign)Type_Gas = 18, (ignore_assign)Type_Event_19, (ignore_assign)Type_Event_20, (ignore_assign)Type_Event_21, (ignore_assign)Type_Event_22, (ignore_assign)Type_Event_23, (ignore_assign)Type_Event_24, (ignore_assign)Type_Event_25, (ignore_assign)Type_Event_26, (ignore_assign)Type_Event_27, (ignore_assign)Type_Event_28, (ignore_assign)Type_Event_29, (ignore_assign)Type_Event_30, (ignore_assign)Type_Event_31, (ignore_assign)Type_Event_32, (ignore_assign)Type_Event_33, (ignore_assign)Type_Event_34, (ignore_assign)Type_Event_35, (ignore_assign)Type_Event_36, (ignore_assign)Type_Event_37, (ignore_assign)Type_Event_38, (ignore_assign)Type_Event_39, (ignore_assign)Type_Event_40, (ignore_assign)Type_Event_41, (ignore_assign)Type_Event_42, (ignore_assign)Type_Event_43, (ignore_assign)Type_Event_44, (ignore_assign)Type_Event_45, (ignore_assign)Type_Event_46, (ignore_assign)Type_Event_47, (ignore_assign)Type_Event_48, (ignore_assign)Type_Event_49, (ignore_assign)Type_Event_50, (ignore_assign)Type_Event_51, (ignore_assign)Type_Event_52, (ignore_assign)Type_Event_53, (ignore_assign)Type_Event_54, (ignore_assign)Type_Event_55, (ignore_assign)Type_Event_56, (ignore_assign)Type_Event_57, (ignore_assign)Type_Event_58, (ignore_assign)Type_Event_59, (ignore_assign)Type_Event_60, (ignore_assign)Type_Event_61, (ignore_assign)Type_Event_62, (ignore_assign)Type_Event_63, (ignore_assign)Type_Event_64, (ignore_assign)Type_Event_65, (ignore_assign)Type_Event_66, (ignore_assign)Type_Event_67, (ignore_assign)Type_Event_68, (ignore_assign)Type_Event_69, (ignore_assign)Type_Event_70, (ignore_assign)Type_Event_71, (ignore_assign)Type_Event_72, (ignore_assign)Type_Event_73, (ignore_assign)Type_Event_74, (ignore_assign)Type_Event_75, (ignore_assign)Type_Event_76, (ignore_assign)Type_Event_77, (ignore_assign)Type_Event_78, (ignore_assign)Type_Event_79, (ignore_assign)Type_Event_80, (ignore_assign)Type_Event_81, (ignore_assign)Type_Event_82, (ignore_assign)Type_Event_83, (ignore_assign)Type_Event_84, (ignore_assign)Type_Event_85, (ignore_assign)Type_Event_86, (ignore_assign)Type_Event_87, (ignore_assign)Type_Event_88, (ignore_assign)Type_Event_89, (ignore_assign)Type_Event_90, (ignore_assign)Type_Event_91, (ignore_assign)Type_Event_92, (ignore_assign)Type_Event_93, (ignore_assign)Type_Event_94, (ignore_assign)Type_Event_95, (ignore_assign)Type_Event_96, (ignore_assign)Type_Event_97, (ignore_assign)Type_Event_98, (ignore_assign)Type_Event_99, (ignore_assign)Type_Event_100, (ignore_assign)Type_Event_101, (ignore_assign)Type_Event_102, (ignore_assign)Type_Event_103, (ignore_assign)Type_Event_104, (ignore_assign)Type_Event_105, (ignore_assign)Type_Event_106, (ignore_assign)Type_Event_107, (ignore_assign)Type_Event_108, (ignore_assign)Type_Event_109, (ignore_assign)Type_Event_110, (ignore_assign)Type_Event_111, (ignore_assign)Type_Event_112, (ignore_assign)Type_Event_113, (ignore_assign)Type_Event_114, (ignore_assign)Type_Event_115, (ignore_assign)Type_Event_116, (ignore_assign)Type_Event_117, (ignore_assign)Type_Event_118, (ignore_assign)Type_Event_119, (ignore_assign)Type_Event_120, (ignore_assign)Type_Event_121, (ignore_assign)Type_Event_122, (ignore_assign)Type_Event_123, (ignore_assign)Type_Event_124, (ignore_assign)Type_Event_125, (ignore_assign)Type_Event_126, (ignore_assign)Type_Event_127, (ignore_assign)Type_Event_128, (ignore_assign)Type_Event_129, (ignore_assign)Type_Event_130, (ignore_assign)Type_Event_131, (ignore_assign)Type_Event_132, (ignore_assign)Type_Event_133, (ignore_assign)Type_Event_134, (ignore_assign)Type_Event_135, (ignore_assign)Type_Event_136, (ignore_assign)Type_Event_137, (ignore_assign)Type_Event_138, (ignore_assign)Type_Event_139, (ignore_assign)Type_Event_140, (ignore_assign)Type_Event_141, (ignore_assign)Type_Event_142, (ignore_assign)Type_Event_143, (ignore_assign)Type_Event_144, (ignore_assign)Type_Event_145, (ignore_assign)Type_Event_146, (ignore_assign)Type_Event_147, (ignore_assign)Type_Event_148, (ignore_assign)Type_Event_149, (ignore_assign)Type_Event_150, (ignore_assign)Type_Event_151, (ignore_assign)Type_Event_152, (ignore_assign)Type_Event_153, (ignore_assign)Type_Event_154, (ignore_assign)Type_Event_155, (ignore_assign)Type_Event_156, (ignore_assign)Type_Event_157, (ignore_assign)Type_Event_158, (ignore_assign)Type_Event_159, (ignore_assign)Type_Event_160, (ignore_assign)Type_Event_161, (ignore_assign)Type_Event_162, (ignore_assign)Type_Event_163, (ignore_assign)Type_Event_164, (ignore_assign)Type_Event_165, (ignore_assign)Type_Event_166, (ignore_assign)Type_Event_167, (ignore_assign)Type_Event_168, (ignore_assign)Type_Event_169, (ignore_assign)Type_Event_170, (ignore_assign)Type_Event_171, (ignore_assign)Type_Event_172, (ignore_assign)Type_Event_173, (ignore_assign)Type_Event_174, (ignore_assign)Type_Event_175, (ignore_assign)Type_Event_176, (ignore_assign)Type_Event_177, (ignore_assign)Type_Event_178, (ignore_assign)Type_Event_179, (ignore_assign)Type_Event_180, (ignore_assign)Type_Event_181, (ignore_assign)Type_Event_182, (ignore_assign)Type_Event_183, (ignore_assign)Type_Event_184, (ignore_assign)Type_Event_185, (ignore_assign)Type_Event_186, (ignore_assign)Type_Event_187, (ignore_assign)Type_Event_188, (ignore_assign)Type_Event_189, (ignore_assign)Type_Event_190, (ignore_assign)Type_Event_191, (ignore_assign)Type_Event_192, (ignore_assign)Type_Event_193, (ignore_assign)Type_Event_194, (ignore_assign)Type_Event_195, (ignore_assign)Type_Event_196, (ignore_assign)Type_Event_197, (ignore_assign)Type_Event_198, (ignore_assign)Type_Event_199, (ignore_assign)Type_Event_200, (ignore_assign)Type_Event_201, (ignore_assign)Type_Event_202, (ignore_assign)Type_Event_203, (ignore_assign)Type_Event_204, (ignore_assign)Type_Event_205, (ignore_assign)Type_Event_206, (ignore_assign)Type_Event_207, (ignore_assign)Type_Event_208, (ignore_assign)Type_Event_209, (ignore_assign)Type_Event_210, (ignore_assign)Type_Event_211, (ignore_assign)Type_Event_212, (ignore_assign)Type_Event_213, (ignore_assign)Type_Event_214, (ignore_assign)Type_Event_215, (ignore_assign)Type_Event_216, (ignore_assign)Type_Event_217, (ignore_assign)Type_Event_218, (ignore_assign)Type_Event_219, (ignore_assign)Type_Event_220, (ignore_assign)Type_Event_221, (ignore_assign)Type_Event_222, (ignore_assign)Type_Event_223, (ignore_assign)Type_Event_224, (ignore_assign)Type_Event_225, (ignore_assign)Type_Event_226, (ignore_assign)Type_Event_227, (ignore_assign)Type_Event_228, (ignore_assign)Type_Event_229, (ignore_assign)Type_Event_230, (ignore_assign)Type_Event_231, (ignore_assign)Type_Event_232, (ignore_assign)Type_Event_233, (ignore_assign)Type_Event_234, (ignore_assign)Type_Event_235, (ignore_assign)Type_Event_236, (ignore_assign)Type_Event_237, (ignore_assign)Type_Event_238, (ignore_assign)Type_Event_239, (ignore_assign)Type_Event_240, (ignore_assign)Type_Event_241, (ignore_assign)Type_Event_242, (ignore_assign)Type_Event_243, (ignore_assign)Type_Event_244, (ignore_assign)Type_Event_245, (ignore_assign)Type_Event_246, (ignore_assign)Type_Event_247, (ignore_assign)Type_Event_248, (ignore_assign)Type_Event_249, (ignore_assign)Type_Event_250, (ignore_assign)Type_Event_251, (ignore_assign)Type_Event_252, (ignore_assign)Type_Event_253, (ignore_assign)Type_Event_254, (ignore_assign)Type_Event_255, (ignore_assign)Type_Event_Param_Previous_Event = 256, (ignore_assign)Type_Event_Param_Location = 257, (ignore_assign)Type_Event_Param_Result = 258, (ignore_assign)Type_Event_Param_Threshold = 259, (ignore_assign)Type_Event_Param_UserCode = 260, (ignore_assign)Type_Event_Param_261 = 261, (ignore_assign)Type_Event_Param_Progress = 262, (ignore_assign)Type_Event_Param_Mode = 263, (ignore_assign)Type_Event_Param_Obstruction = 264, (ignore_assign)Type_Event_Param_Sensor_ID = 265, (ignore_assign)Type_Event_Param_Error_Code = 266, (ignore_assign)Type_Event_Param_Duration = 267, (ignore_assign)Type_Event_Param_Pollution_Level = 268, (ignore_assign)Type_Event_Param_Status = 269, (ignore_assign)Type_Event_Param_Schedule_ID = 270, (ignore_assign)Type_Event_Param_Valve_Table_ID = 271, (ignore_assign)Type_Event_Param_272, (ignore_assign)Type_Event_Param_273, (ignore_assign)Type_Event_Param_274, (ignore_assign)Type_Event_Param_275, (ignore_assign)Type_Event_Param_276, (ignore_assign)Type_Event_Param_277, (ignore_assign)Type_Event_Param_278, (ignore_assign)Type_Event_Param_279, (ignore_assign)Type_Event_Param_280, (ignore_assign)Type_Event_Param_281, (ignore_assign)Type_Event_Param_282, (ignore_assign)Type_Event_Param_283, (ignore_assign)Type_Event_Param_284, (ignore_assign)Type_Event_Param_285, (ignore_assign)Type_Event_Param_286, (ignore_assign)Type_Event_Param_287, (ignore_assign)Type_Event_Param_288, (ignore_assign)Type_Event_Param_289, (ignore_assign)Type_Event_Param_290, (ignore_assign)Type_Event_Param_291, (ignore_assign)Type_Event_Param_292, (ignore_assign)Type_Event_Param_293, (ignore_assign)Type_Event_Param_294, (ignore_assign)Type_Event_Param_295, (ignore_assign)Type_Event_Param_296, (ignore_assign)Type_Event_Param_297, (ignore_assign)Type_Event_Param_298, (ignore_assign)Type_Event_Param_299, (ignore_assign)Type_Event_Param_300, (ignore_assign)Type_Event_Param_301, (ignore_assign)Type_Event_Param_302, (ignore_assign)Type_Event_Param_303, (ignore_assign)Type_Event_Param_304, (ignore_assign)Type_Event_Param_305, (ignore_assign)Type_Event_Param_306, (ignore_assign)Type_Event_Param_307, (ignore_assign)Type_Event_Param_308, (ignore_assign)Type_Event_Param_309, (ignore_assign)Type_Event_Param_310, (ignore_assign)Type_Event_Param_311, (ignore_assign)Type_Event_Param_312, (ignore_assign)Type_Event_Param_313, (ignore_assign)Type_Event_Param_314, (ignore_assign)Type_Event_Param_315, (ignore_assign)Type_Event_Param_316, (ignore_assign)Type_Event_Param_317, (ignore_assign)Type_Event_Param_318, (ignore_assign)Type_Event_Param_319, (ignore_assign)Type_Event_Param_320, (ignore_assign)Type_Event_Param_321, (ignore_assign)Type_Event_Param_322, (ignore_assign)Type_Event_Param_323, (ignore_assign)Type_Event_Param_324, (ignore_assign)Type_Event_Param_325, (ignore_assign)Type_Event_Param_326, (ignore_assign)Type_Event_Param_327, (ignore_assign)Type_Event_Param_328, (ignore_assign)Type_Event_Param_329, (ignore_assign)Type_Event_Param_330, (ignore_assign)Type_Event_Param_331, (ignore_assign)Type_Event_Param_332, (ignore_assign)Type_Event_Param_333, (ignore_assign)Type_Event_Param_334, (ignore_assign)Type_Event_Param_335, (ignore_assign)Type_Event_Param_336, (ignore_assign)Type_Event_Param_337, (ignore_assign)Type_Event_Param_338, (ignore_assign)Type_Event_Param_339, (ignore_assign)Type_Event_Param_340, (ignore_assign)Type_Event_Param_341, (ignore_assign)Type_Event_Param_342, (ignore_assign)Type_Event_Param_343, (ignore_assign)Type_Event_Param_344, (ignore_assign)Type_Event_Param_345, (ignore_assign)Type_Event_Param_346, (ignore_assign)Type_Event_Param_347, (ignore_assign)Type_Event_Param_348, (ignore_assign)Type_Event_Param_349, (ignore_assign)Type_Event_Param_350, (ignore_assign)Type_Event_Param_351, (ignore_assign)Type_Event_Param_352, (ignore_assign)Type_Event_Param_353, (ignore_assign)Type_Event_Param_354, (ignore_assign)Type_Event_Param_355, (ignore_assign)Type_Event_Param_356, (ignore_assign)Type_Event_Param_357, (ignore_assign)Type_Event_Param_358, (ignore_assign)Type_Event_Param_359, (ignore_assign)Type_Event_Param_360, (ignore_assign)Type_Event_Param_361, (ignore_assign)Type_Event_Param_362, (ignore_assign)Type_Event_Param_363, (ignore_assign)Type_Event_Param_364, (ignore_assign)Type_Event_Param_365, (ignore_assign)Type_Event_Param_366, (ignore_assign)Type_Event_Param_367, (ignore_assign)Type_Event_Param_368, (ignore_assign)Type_Event_Param_369, (ignore_assign)Type_Event_Param_370, (ignore_assign)Type_Event_Param_371, (ignore_assign)Type_Event_Param_372, (ignore_assign)Type_Event_Param_373, (ignore_assign)Type_Event_Param_374, (ignore_assign)Type_Event_Param_375, (ignore_assign)Type_Event_Param_376, (ignore_assign)Type_Event_Param_377, (ignore_assign)Type_Event_Param_378, (ignore_assign)Type_Event_Param_379, (ignore_assign)Type_Event_Param_380, (ignore_assign)Type_Event_Param_381, (ignore_assign)Type_Event_Param_382, (ignore_assign)Type_Event_Param_383, (ignore_assign)Type_Event_Param_384, (ignore_assign)Type_Event_Param_385, (ignore_assign)Type_Event_Param_386, (ignore_assign)Type_Event_Param_387, (ignore_assign)Type_Event_Param_388, (ignore_assign)Type_Event_Param_389, (ignore_assign)Type_Event_Param_390, (ignore_assign)Type_Event_Param_391, (ignore_assign)Type_Event_Param_392, (ignore_assign)Type_Event_Param_393, (ignore_assign)Type_Event_Param_394, (ignore_assign)Type_Event_Param_395, (ignore_assign)Type_Event_Param_396, (ignore_assign)Type_Event_Param_397, (ignore_assign)Type_Event_Param_398, (ignore_assign)Type_Event_Param_399, (ignore_assign)Type_Event_Param_400, (ignore_assign)Type_Event_Param_401, (ignore_assign)Type_Event_Param_402, (ignore_assign)Type_Event_Param_403, (ignore_assign)Type_Event_Param_404, (ignore_assign)Type_Event_Param_405, (ignore_assign)Type_Event_Param_406, (ignore_assign)Type_Event_Param_407, (ignore_assign)Type_Event_Param_408, (ignore_assign)Type_Event_Param_409, (ignore_assign)Type_Event_Param_410, (ignore_assign)Type_Event_Param_411, (ignore_assign)Type_Event_Param_412, (ignore_assign)Type_Event_Param_413, (ignore_assign)Type_Event_Param_414, (ignore_assign)Type_Event_Param_415, (ignore_assign)Type_Event_Param_416, (ignore_assign)Type_Event_Param_417, (ignore_assign)Type_Event_Param_418, (ignore_assign)Type_Event_Param_419, (ignore_assign)Type_Event_Param_420, (ignore_assign)Type_Event_Param_421, (ignore_assign)Type_Event_Param_422, (ignore_assign)Type_Event_Param_423, (ignore_assign)Type_Event_Param_424, (ignore_assign)Type_Event_Param_425, (ignore_assign)Type_Event_Param_426, (ignore_assign)Type_Event_Param_427, (ignore_assign)Type_Event_Param_428, (ignore_assign)Type_Event_Param_429, (ignore_assign)Type_Event_Param_430, (ignore_assign)Type_Event_Param_431, (ignore_assign)Type_Event_Param_432, (ignore_assign)Type_Event_Param_433, (ignore_assign)Type_Event_Param_434, (ignore_assign)Type_Event_Param_435, (ignore_assign)Type_Event_Param_436, (ignore_assign)Type_Event_Param_437, (ignore_assign)Type_Event_Param_438, (ignore_assign)Type_Event_Param_439, (ignore_assign)Type_Event_Param_440, (ignore_assign)Type_Event_Param_441, (ignore_assign)Type_Event_Param_442, (ignore_assign)Type_Event_Param_443, (ignore_assign)Type_Event_Param_444, (ignore_assign)Type_Event_Param_445, (ignore_assign)Type_Event_Param_446, (ignore_assign)Type_Event_Param_447, (ignore_assign)Type_Event_Param_448, (ignore_assign)Type_Event_Param_449, (ignore_assign)Type_Event_Param_450, (ignore_assign)Type_Event_Param_451, (ignore_assign)Type_Event_Param_452, (ignore_assign)Type_Event_Param_453, (ignore_assign)Type_Event_Param_454, (ignore_assign)Type_Event_Param_455, (ignore_assign)Type_Event_Param_456, (ignore_assign)Type_Event_Param_457, (ignore_assign)Type_Event_Param_458, (ignore_assign)Type_Event_Param_459, (ignore_assign)Type_Event_Param_460, (ignore_assign)Type_Event_Param_461, (ignore_assign)Type_Event_Param_462, (ignore_assign)Type_Event_Param_463, (ignore_assign)Type_Event_Param_464, (ignore_assign)Type_Event_Param_465, (ignore_assign)Type_Event_Param_466, (ignore_assign)Type_Event_Param_467, (ignore_assign)Type_Event_Param_468, (ignore_assign)Type_Event_Param_469, (ignore_assign)Type_Event_Param_470, (ignore_assign)Type_Event_Param_471, (ignore_assign)Type_Event_Param_472, (ignore_assign)Type_Event_Param_473, (ignore_assign)Type_Event_Param_474, (ignore_assign)Type_Event_Param_475, (ignore_assign)Type_Event_Param_476, (ignore_assign)Type_Event_Param_477, (ignore_assign)Type_Event_Param_478, (ignore_assign)Type_Event_Param_479, (ignore_assign)Type_Event_Param_480, (ignore_assign)Type_Event_Param_481, (ignore_assign)Type_Event_Param_482, (ignore_assign)Type_Event_Param_483, (ignore_assign)Type_Event_Param_484, (ignore_assign)Type_Event_Param_485, (ignore_assign)Type_Event_Param_486, (ignore_assign)Type_Event_Param_487, (ignore_assign)Type_Event_Param_488, (ignore_assign)Type_Event_Param_489, (ignore_assign)Type_Event_Param_490, (ignore_assign)Type_Event_Param_491, (ignore_assign)Type_Event_Param_492, (ignore_assign)Type_Event_Param_493, (ignore_assign)Type_Event_Param_494, (ignore_assign)Type_Event_Param_495, (ignore_assign)Type_Event_Param_496, (ignore_assign)Type_Event_Param_497, (ignore_assign)Type_Event_Param_498, (ignore_assign)Type_Event_Param_499, (ignore_assign)Type_Event_Param_500, (ignore_assign)Type_Event_Param_501, (ignore_assign)Type_Event_Param_502, (ignore_assign)Type_Event_Param_503, (ignore_assign)Type_Event_Param_504, (ignore_assign)Type_Event_Param_505, (ignore_assign)Type_Event_Param_506, (ignore_assign)Type_Event_Param_507, (ignore_assign)Type_Event_Param_508, (ignore_assign)Type_Event_Param_509, (ignore_assign)Type_Event_Param_510, (ignore_assign)Type_Event_Param_511, (ignore_assign)Type_v1 = 512, (ignore_assign)Level_v1 = 513, (ignore_assign)AutoClearEvents = 514, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Type_Start = 0", "Type_Smoke_Alarm = 1", "Type_Carbon_Monoxide = 2", "Type_Carbon_Dioxide = 3", "Type_Heat = 4", "Type_Water = 5", "Type_Access_Control = 6", "Type_Home_Security = 7", "Type_Power_Management = 8", "Type_System = 9", "Type_Emergency = 10", "Type_Clock = 11", "Type_Appliance = 12", "Type_Home_Health = 13", "Type_Siren = 14", "Type_Water_Valve = 15", "Type_Weather = 16", "Type_Irrigation = 17", "Type_Gas = 18", "Type_Event_19", "Type_Event_20", "Type_Event_21", "Type_Event_22", "Type_Event_23", "Type_Event_24", "Type_Event_25", "Type_Event_26", "Type_Event_27", "Type_Event_28", "Type_Event_29", "Type_Event_30", "Type_Event_31", "Type_Event_32", "Type_Event_33", "Type_Event_34", "Type_Event_35", "Type_Event_36", "Type_Event_37", "Type_Event_38", "Type_Event_39", "Type_Event_40", "Type_Event_41", "Type_Event_42", "Type_Event_43", "Type_Event_44", "Type_Event_45", "Type_Event_46", "Type_Event_47", "Type_Event_48", "Type_Event_49", "Type_Event_50", "Type_Event_51", "Type_Event_52", "Type_Event_53", "Type_Event_54", "Type_Event_55", "Type_Event_56", "Type_Event_57", "Type_Event_58", "Type_Event_59", "Type_Event_60", "Type_Event_61", "Type_Event_62", "Type_Event_63", "Type_Event_64", "Type_Event_65", "Type_Event_66", "Type_Event_67", "Type_Event_68", "Type_Event_69", "Type_Event_70", "Type_Event_71", "Type_Event_72", "Type_Event_73", "Type_Event_74", "Type_Event_75", "Type_Event_76", "Type_Event_77", "Type_Event_78", "Type_Event_79", "Type_Event_80", "Type_Event_81", "Type_Event_82", "Type_Event_83", "Type_Event_84", "Type_Event_85", "Type_Event_86", "Type_Event_87", "Type_Event_88", "Type_Event_89", "Type_Event_90", "Type_Event_91", "Type_Event_92", "Type_Event_93", "Type_Event_94", "Type_Event_95", "Type_Event_96", "Type_Event_97", "Type_Event_98", "Type_Event_99", "Type_Event_100", "Type_Event_101", "Type_Event_102", "Type_Event_103", "Type_Event_104", "Type_Event_105", "Type_Event_106", "Type_Event_107", "Type_Event_108", "Type_Event_109", "Type_Event_110", "Type_Event_111", "Type_Event_112", "Type_Event_113", "Type_Event_114", "Type_Event_115", "Type_Event_116", "Type_Event_117", "Type_Event_118", "Type_Event_119", "Type_Event_120", "Type_Event_121", "Type_Event_122", "Type_Event_123", "Type_Event_124", "Type_Event_125", "Type_Event_126", "Type_Event_127", "Type_Event_128", "Type_Event_129", "Type_Event_130", "Type_Event_131", "Type_Event_132", "Type_Event_133", "Type_Event_134", "Type_Event_135", "Type_Event_136", "Type_Event_137", "Type_Event_138", "Type_Event_139", "Type_Event_140", "Type_Event_141", "Type_Event_142", "Type_Event_143", "Type_Event_144", "Type_Event_145", "Type_Event_146", "Type_Event_147", "Type_Event_148", "Type_Event_149", "Type_Event_150", "Type_Event_151", "Type_Event_152", "Type_Event_153", "Type_Event_154", "Type_Event_155", "Type_Event_156", "Type_Event_157", "Type_Event_158", "Type_Event_159", "Type_Event_160", "Type_Event_161", "Type_Event_162", "Type_Event_163", "Type_Event_164", "Type_Event_165", "Type_Event_166", "Type_Event_167", "Type_Event_168", "Type_Event_169", "Type_Event_170", "Type_Event_171", "Type_Event_172", "Type_Event_173", "Type_Event_174", "Type_Event_175", "Type_Event_176", "Type_Event_177", "Type_Event_178", "Type_Event_179", "Type_Event_180", "Type_Event_181", "Type_Event_182", "Type_Event_183", "Type_Event_184", "Type_Event_185", "Type_Event_186", "Type_Event_187", "Type_Event_188", "Type_Event_189", "Type_Event_190", "Type_Event_191", "Type_Event_192", "Type_Event_193", "Type_Event_194", "Type_Event_195", "Type_Event_196", "Type_Event_197", "Type_Event_198", "Type_Event_199", "Type_Event_200", "Type_Event_201", "Type_Event_202", "Type_Event_203", "Type_Event_204", "Type_Event_205", "Type_Event_206", "Type_Event_207", "Type_Event_208", "Type_Event_209", "Type_Event_210", "Type_Event_211", "Type_Event_212", "Type_Event_213", "Type_Event_214", "Type_Event_215", "Type_Event_216", "Type_Event_217", "Type_Event_218", "Type_Event_219", "Type_Event_220", "Type_Event_221", "Type_Event_222", "Type_Event_223", "Type_Event_224", "Type_Event_225", "Type_Event_226", "Type_Event_227", "Type_Event_228", "Type_Event_229", "Type_Event_230", "Type_Event_231", "Type_Event_232", "Type_Event_233", "Type_Event_234", "Type_Event_235", "Type_Event_236", "Type_Event_237", "Type_Event_238", "Type_Event_239", "Type_Event_240", "Type_Event_241", "Type_Event_242", "Type_Event_243", "Type_Event_244", "Type_Event_245", "Type_Event_246", "Type_Event_247", "Type_Event_248", "Type_Event_249", "Type_Event_250", "Type_Event_251", "Type_Event_252", "Type_Event_253", "Type_Event_254", "Type_Event_255", "Type_Event_Param_Previous_Event = 256", "Type_Event_Param_Location = 257", "Type_Event_Param_Result = 258", "Type_Event_Param_Threshold = 259", "Type_Event_Param_UserCode = 260", "Type_Event_Param_261 = 261", "Type_Event_Param_Progress = 262", "Type_Event_Param_Mode = 263", "Type_Event_Param_Obstruction = 264", "Type_Event_Param_Sensor_ID = 265", "Type_Event_Param_Error_Code = 266", "Type_Event_Param_Duration = 267", "Type_Event_Param_Pollution_Level = 268", "Type_Event_Param_Status = 269", "Type_Event_Param_Schedule_ID = 270", "Type_Event_Param_Valve_Table_ID = 271", "Type_Event_Param_272", "Type_Event_Param_273", "Type_Event_Param_274", "Type_Event_Param_275", "Type_Event_Param_276", "Type_Event_Param_277", "Type_Event_Param_278", "Type_Event_Param_279", "Type_Event_Param_280", "Type_Event_Param_281", "Type_Event_Param_282", "Type_Event_Param_283", "Type_Event_Param_284", "Type_Event_Param_285", "Type_Event_Param_286", "Type_Event_Param_287", "Type_Event_Param_288", "Type_Event_Param_289", "Type_Event_Param_290", "Type_Event_Param_291", "Type_Event_Param_292", "Type_Event_Param_293", "Type_Event_Param_294", "Type_Event_Param_295", "Type_Event_Param_296", "Type_Event_Param_297", "Type_Event_Param_298", "Type_Event_Param_299", "Type_Event_Param_300", "Type_Event_Param_301", "Type_Event_Param_302", "Type_Event_Param_303", "Type_Event_Param_304", "Type_Event_Param_305", "Type_Event_Param_306", "Type_Event_Param_307", "Type_Event_Param_308", "Type_Event_Param_309", "Type_Event_Param_310", "Type_Event_Param_311", "Type_Event_Param_312", "Type_Event_Param_313", "Type_Event_Param_314", "Type_Event_Param_315", "Type_Event_Param_316", "Type_Event_Param_317", "Type_Event_Param_318", "Type_Event_Param_319", "Type_Event_Param_320", "Type_Event_Param_321", "Type_Event_Param_322", "Type_Event_Param_323", "Type_Event_Param_324", "Type_Event_Param_325", "Type_Event_Param_326", "Type_Event_Param_327", "Type_Event_Param_328", "Type_Event_Param_329", "Type_Event_Param_330", "Type_Event_Param_331", "Type_Event_Param_332", "Type_Event_Param_333", "Type_Event_Param_334", "Type_Event_Param_335", "Type_Event_Param_336", "Type_Event_Param_337", "Type_Event_Param_338", "Type_Event_Param_339", "Type_Event_Param_340", "Type_Event_Param_341", "Type_Event_Param_342", "Type_Event_Param_343", "Type_Event_Param_344", "Type_Event_Param_345", "Type_Event_Param_346", "Type_Event_Param_347", "Type_Event_Param_348", "Type_Event_Param_349", "Type_Event_Param_350", "Type_Event_Param_351", "Type_Event_Param_352", "Type_Event_Param_353", "Type_Event_Param_354", "Type_Event_Param_355", "Type_Event_Param_356", "Type_Event_Param_357", "Type_Event_Param_358", "Type_Event_Param_359", "Type_Event_Param_360", "Type_Event_Param_361", "Type_Event_Param_362", "Type_Event_Param_363", "Type_Event_Param_364", "Type_Event_Param_365", "Type_Event_Param_366", "Type_Event_Param_367", "Type_Event_Param_368", "Type_Event_Param_369", "Type_Event_Param_370", "Type_Event_Param_371", "Type_Event_Param_372", "Type_Event_Param_373", "Type_Event_Param_374", "Type_Event_Param_375", "Type_Event_Param_376", "Type_Event_Param_377", "Type_Event_Param_378", "Type_Event_Param_379", "Type_Event_Param_380", "Type_Event_Param_381", "Type_Event_Param_382", "Type_Event_Param_383", "Type_Event_Param_384", "Type_Event_Param_385", "Type_Event_Param_386", "Type_Event_Param_387", "Type_Event_Param_388", "Type_Event_Param_389", "Type_Event_Param_390", "Type_Event_Param_391", "Type_Event_Param_392", "Type_Event_Param_393", "Type_Event_Param_394", "Type_Event_Param_395", "Type_Event_Param_396", "Type_Event_Param_397", "Type_Event_Param_398", "Type_Event_Param_399", "Type_Event_Param_400", "Type_Event_Param_401", "Type_Event_Param_402", "Type_Event_Param_403", "Type_Event_Param_404", "Type_Event_Param_405", "Type_Event_Param_406", "Type_Event_Param_407", "Type_Event_Param_408", "Type_Event_Param_409", "Type_Event_Param_410", "Type_Event_Param_411", "Type_Event_Param_412", "Type_Event_Param_413", "Type_Event_Param_414", "Type_Event_Param_415", "Type_Event_Param_416", "Type_Event_Param_417", "Type_Event_Param_418", "Type_Event_Param_419", "Type_Event_Param_420", "Type_Event_Param_421", "Type_Event_Param_422", "Type_Event_Param_423", "Type_Event_Param_424", "Type_Event_Param_425", "Type_Event_Param_426", "Type_Event_Param_427", "Type_Event_Param_428", "Type_Event_Param_429", "Type_Event_Param_430", "Type_Event_Param_431", "Type_Event_Param_432", "Type_Event_Param_433", "Type_Event_Param_434", "Type_Event_Param_435", "Type_Event_Param_436", "Type_Event_Param_437", "Type_Event_Param_438", "Type_Event_Param_439", "Type_Event_Param_440", "Type_Event_Param_441", "Type_Event_Param_442", "Type_Event_Param_443", "Type_Event_Param_444", "Type_Event_Param_445", "Type_Event_Param_446", "Type_Event_Param_447", "Type_Event_Param_448", "Type_Event_Param_449", "Type_Event_Param_450", "Type_Event_Param_451", "Type_Event_Param_452", "Type_Event_Param_453", "Type_Event_Param_454", "Type_Event_Param_455", "Type_Event_Param_456", "Type_Event_Param_457", "Type_Event_Param_458", "Type_Event_Param_459", "Type_Event_Param_460", "Type_Event_Param_461", "Type_Event_Param_462", "Type_Event_Param_463", "Type_Event_Param_464", "Type_Event_Param_465", "Type_Event_Param_466", "Type_Event_Param_467", "Type_Event_Param_468", "Type_Event_Param_469", "Type_Event_Param_470", "Type_Event_Param_471", "Type_Event_Param_472", "Type_Event_Param_473", "Type_Event_Param_474", "Type_Event_Param_475", "Type_Event_Param_476", "Type_Event_Param_477", "Type_Event_Param_478", "Type_Event_Param_479", "Type_Event_Param_480", "Type_Event_Param_481", "Type_Event_Param_482", "Type_Event_Param_483", "Type_Event_Param_484", "Type_Event_Param_485", "Type_Event_Param_486", "Type_Event_Param_487", "Type_Event_Param_488", "Type_Event_Param_489", "Type_Event_Param_490", "Type_Event_Param_491", "Type_Event_Param_492", "Type_Event_Param_493", "Type_Event_Param_494", "Type_Event_Param_495", "Type_Event_Param_496", "Type_Event_Param_497", "Type_Event_Param_498", "Type_Event_Param_499", "Type_Event_Param_500", "Type_Event_Param_501", "Type_Event_Param_502", "Type_Event_Param_503", "Type_Event_Param_504", "Type_Event_Param_505", "Type_Event_Param_506", "Type_Event_Param_507", "Type_Event_Param_508", "Type_Event_Param_509", "Type_Event_Param_510", "Type_Event_Param_511", "Type_v1 = 512", "Level_v1 = 513", "AutoClearEvents = 514", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; +struct ValueID_Index_AssociationCommandConfiguration { enum _enumerated { MaxCommandLength = 0, CommandsAreValues = 1, CommandsAreConfigurable = 2, NumFreeCommands = 3, MaxCommands = 4 }; _enumerated _value; ValueID_Index_AssociationCommandConfiguration(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 5; static const int* _values() { static const int values[] = { (ignore_assign)MaxCommandLength = 0, (ignore_assign)CommandsAreValues = 1, (ignore_assign)CommandsAreConfigurable = 2, (ignore_assign)NumFreeCommands = 3, (ignore_assign)MaxCommands = 4, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "MaxCommandLength = 0", "CommandsAreValues = 1", "CommandsAreConfigurable = 2", "NumFreeCommands = 3", "MaxCommands = 4", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + + + + + +struct ValueID_Index_BarrierOperator { enum _enumerated { Command = 0, Label = 1, SupportedSignals = 2, Audible = 3, Visual = 4 }; _enumerated _value; ValueID_Index_BarrierOperator(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 5; static const int* _values() { static const int values[] = { (ignore_assign)Command = 0, (ignore_assign)Label = 1, (ignore_assign)SupportedSignals = 2, (ignore_assign)Audible = 3, (ignore_assign)Visual = 4, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Command = 0", "Label = 1", "SupportedSignals = 2", "Audible = 3", "Visual = 4", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + + + + + +struct ValueID_Index_Basic { enum _enumerated { Set = 0 }; _enumerated _value; ValueID_Index_Basic(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 1; static const int* _values() { static const int values[] = { (ignore_assign)Set = 0, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Set = 0", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + +struct ValueID_Index_BasicWindowCovering { enum _enumerated { Open = 0, Close = 1 }; _enumerated _value; ValueID_Index_BasicWindowCovering(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 2; static const int* _values() { static const int values[] = { (ignore_assign)Open = 0, (ignore_assign)Close = 1, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Open = 0", "Close = 1", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + + +struct ValueID_Index_Battery { enum _enumerated { Level = 0 }; _enumerated _value; ValueID_Index_Battery(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 1; static const int* _values() { static const int values[] = { (ignore_assign)Level = 0, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Level = 0", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + +struct ValueID_Index_CentralScene { enum _enumerated { Scene_1 = 1, Scene_2, Scene_3, Scene_4, Scene_5, Scene_6, Scene_7, Scene_8, Scene_9, Scene_10, Scene_11, Scene_12, Scene_13, Scene_14, Scene_15, Scene_16, Scene_17, Scene_18, Scene_19, Scene_20, Scene_21, Scene_22, Scene_23, Scene_24, Scene_25, Scene_26, Scene_27, Scene_28, Scene_29, Scene_30, Scene_31, Scene_32, Scene_33, Scene_34, Scene_35, Scene_36, Scene_37, Scene_38, Scene_39, Scene_40, Scene_41, Scene_42, Scene_43, Scene_44, Scene_45, Scene_46, Scene_47, Scene_48, Scene_49, Scene_50, Scene_51, Scene_52, Scene_53, Scene_54, Scene_55, Scene_56, Scene_57, Scene_58, Scene_59, Scene_60, Scene_61, Scene_62, Scene_63, Scene_64, Scene_65, Scene_66, Scene_67, Scene_68, Scene_69, Scene_70, Scene_71, Scene_72, Scene_73, Scene_74, Scene_75, Scene_76, Scene_77, Scene_78, Scene_79, Scene_80, Scene_81, Scene_82, Scene_83, Scene_84, Scene_85, Scene_86, Scene_87, Scene_88, Scene_89, Scene_90, Scene_91, Scene_92, Scene_93, Scene_94, Scene_95, Scene_96, Scene_97, Scene_98, Scene_99, Scene_100, Scene_101, Scene_102, Scene_103, Scene_104, Scene_105, Scene_106, Scene_107, Scene_108, Scene_109, Scene_110, Scene_111, Scene_112, Scene_113, Scene_114, Scene_115, Scene_116, Scene_117, Scene_118, Scene_119, Scene_120, Scene_121, Scene_122, Scene_123, Scene_124, Scene_125, Scene_126, Scene_127, Scene_128, Scene_129, Scene_130, Scene_131, Scene_132, Scene_133, Scene_134, Scene_135, Scene_136, Scene_137, Scene_138, Scene_139, Scene_140, Scene_141, Scene_142, Scene_143, Scene_144, Scene_145, Scene_146, Scene_147, Scene_148, Scene_149, Scene_150, Scene_151, Scene_152, Scene_153, Scene_154, Scene_155, Scene_156, Scene_157, Scene_158, Scene_159, Scene_160, Scene_161, Scene_162, Scene_163, Scene_164, Scene_165, Scene_166, Scene_167, Scene_168, Scene_169, Scene_170, Scene_171, Scene_172, Scene_173, Scene_174, Scene_175, Scene_176, Scene_177, Scene_178, Scene_179, Scene_180, Scene_181, Scene_182, Scene_183, Scene_184, Scene_185, Scene_186, Scene_187, Scene_188, Scene_189, Scene_190, Scene_191, Scene_192, Scene_193, Scene_194, Scene_195, Scene_196, Scene_197, Scene_198, Scene_199, Scene_200, Scene_201, Scene_202, Scene_203, Scene_204, Scene_205, Scene_206, Scene_207, Scene_208, Scene_209, Scene_210, Scene_211, Scene_212, Scene_213, Scene_214, Scene_215, Scene_216, Scene_217, Scene_218, Scene_219, Scene_220, Scene_221, Scene_222, Scene_223, Scene_224, Scene_225, Scene_226, Scene_227, Scene_228, Scene_229, Scene_230, Scene_231, Scene_232, Scene_233, Scene_234, Scene_235, Scene_236, Scene_237, Scene_238, Scene_239, Scene_240, Scene_241, Scene_242, Scene_243, Scene_244, Scene_245, Scene_246, Scene_247, Scene_248, Scene_249, Scene_250, Scene_251, Scene_252, Scene_253, Scene_254, Scene_255, SceneCount = 256, ClearSceneTimeout = 257 }; _enumerated _value; ValueID_Index_CentralScene(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 257; static const int* _values() { static const int values[] = { (ignore_assign)Scene_1 = 1, (ignore_assign)Scene_2, (ignore_assign)Scene_3, (ignore_assign)Scene_4, (ignore_assign)Scene_5, (ignore_assign)Scene_6, (ignore_assign)Scene_7, (ignore_assign)Scene_8, (ignore_assign)Scene_9, (ignore_assign)Scene_10, (ignore_assign)Scene_11, (ignore_assign)Scene_12, (ignore_assign)Scene_13, (ignore_assign)Scene_14, (ignore_assign)Scene_15, (ignore_assign)Scene_16, (ignore_assign)Scene_17, (ignore_assign)Scene_18, (ignore_assign)Scene_19, (ignore_assign)Scene_20, (ignore_assign)Scene_21, (ignore_assign)Scene_22, (ignore_assign)Scene_23, (ignore_assign)Scene_24, (ignore_assign)Scene_25, (ignore_assign)Scene_26, (ignore_assign)Scene_27, (ignore_assign)Scene_28, (ignore_assign)Scene_29, (ignore_assign)Scene_30, (ignore_assign)Scene_31, (ignore_assign)Scene_32, (ignore_assign)Scene_33, (ignore_assign)Scene_34, (ignore_assign)Scene_35, (ignore_assign)Scene_36, (ignore_assign)Scene_37, (ignore_assign)Scene_38, (ignore_assign)Scene_39, (ignore_assign)Scene_40, (ignore_assign)Scene_41, (ignore_assign)Scene_42, (ignore_assign)Scene_43, (ignore_assign)Scene_44, (ignore_assign)Scene_45, (ignore_assign)Scene_46, (ignore_assign)Scene_47, (ignore_assign)Scene_48, (ignore_assign)Scene_49, (ignore_assign)Scene_50, (ignore_assign)Scene_51, (ignore_assign)Scene_52, (ignore_assign)Scene_53, (ignore_assign)Scene_54, (ignore_assign)Scene_55, (ignore_assign)Scene_56, (ignore_assign)Scene_57, (ignore_assign)Scene_58, (ignore_assign)Scene_59, (ignore_assign)Scene_60, (ignore_assign)Scene_61, (ignore_assign)Scene_62, (ignore_assign)Scene_63, (ignore_assign)Scene_64, (ignore_assign)Scene_65, (ignore_assign)Scene_66, (ignore_assign)Scene_67, (ignore_assign)Scene_68, (ignore_assign)Scene_69, (ignore_assign)Scene_70, (ignore_assign)Scene_71, (ignore_assign)Scene_72, (ignore_assign)Scene_73, (ignore_assign)Scene_74, (ignore_assign)Scene_75, (ignore_assign)Scene_76, (ignore_assign)Scene_77, (ignore_assign)Scene_78, (ignore_assign)Scene_79, (ignore_assign)Scene_80, (ignore_assign)Scene_81, (ignore_assign)Scene_82, (ignore_assign)Scene_83, (ignore_assign)Scene_84, (ignore_assign)Scene_85, (ignore_assign)Scene_86, (ignore_assign)Scene_87, (ignore_assign)Scene_88, (ignore_assign)Scene_89, (ignore_assign)Scene_90, (ignore_assign)Scene_91, (ignore_assign)Scene_92, (ignore_assign)Scene_93, (ignore_assign)Scene_94, (ignore_assign)Scene_95, (ignore_assign)Scene_96, (ignore_assign)Scene_97, (ignore_assign)Scene_98, (ignore_assign)Scene_99, (ignore_assign)Scene_100, (ignore_assign)Scene_101, (ignore_assign)Scene_102, (ignore_assign)Scene_103, (ignore_assign)Scene_104, (ignore_assign)Scene_105, (ignore_assign)Scene_106, (ignore_assign)Scene_107, (ignore_assign)Scene_108, (ignore_assign)Scene_109, (ignore_assign)Scene_110, (ignore_assign)Scene_111, (ignore_assign)Scene_112, (ignore_assign)Scene_113, (ignore_assign)Scene_114, (ignore_assign)Scene_115, (ignore_assign)Scene_116, (ignore_assign)Scene_117, (ignore_assign)Scene_118, (ignore_assign)Scene_119, (ignore_assign)Scene_120, (ignore_assign)Scene_121, (ignore_assign)Scene_122, (ignore_assign)Scene_123, (ignore_assign)Scene_124, (ignore_assign)Scene_125, (ignore_assign)Scene_126, (ignore_assign)Scene_127, (ignore_assign)Scene_128, (ignore_assign)Scene_129, (ignore_assign)Scene_130, (ignore_assign)Scene_131, (ignore_assign)Scene_132, (ignore_assign)Scene_133, (ignore_assign)Scene_134, (ignore_assign)Scene_135, (ignore_assign)Scene_136, (ignore_assign)Scene_137, (ignore_assign)Scene_138, (ignore_assign)Scene_139, (ignore_assign)Scene_140, (ignore_assign)Scene_141, (ignore_assign)Scene_142, (ignore_assign)Scene_143, (ignore_assign)Scene_144, (ignore_assign)Scene_145, (ignore_assign)Scene_146, (ignore_assign)Scene_147, (ignore_assign)Scene_148, (ignore_assign)Scene_149, (ignore_assign)Scene_150, (ignore_assign)Scene_151, (ignore_assign)Scene_152, (ignore_assign)Scene_153, (ignore_assign)Scene_154, (ignore_assign)Scene_155, (ignore_assign)Scene_156, (ignore_assign)Scene_157, (ignore_assign)Scene_158, (ignore_assign)Scene_159, (ignore_assign)Scene_160, (ignore_assign)Scene_161, (ignore_assign)Scene_162, (ignore_assign)Scene_163, (ignore_assign)Scene_164, (ignore_assign)Scene_165, (ignore_assign)Scene_166, (ignore_assign)Scene_167, (ignore_assign)Scene_168, (ignore_assign)Scene_169, (ignore_assign)Scene_170, (ignore_assign)Scene_171, (ignore_assign)Scene_172, (ignore_assign)Scene_173, (ignore_assign)Scene_174, (ignore_assign)Scene_175, (ignore_assign)Scene_176, (ignore_assign)Scene_177, (ignore_assign)Scene_178, (ignore_assign)Scene_179, (ignore_assign)Scene_180, (ignore_assign)Scene_181, (ignore_assign)Scene_182, (ignore_assign)Scene_183, (ignore_assign)Scene_184, (ignore_assign)Scene_185, (ignore_assign)Scene_186, (ignore_assign)Scene_187, (ignore_assign)Scene_188, (ignore_assign)Scene_189, (ignore_assign)Scene_190, (ignore_assign)Scene_191, (ignore_assign)Scene_192, (ignore_assign)Scene_193, (ignore_assign)Scene_194, (ignore_assign)Scene_195, (ignore_assign)Scene_196, (ignore_assign)Scene_197, (ignore_assign)Scene_198, (ignore_assign)Scene_199, (ignore_assign)Scene_200, (ignore_assign)Scene_201, (ignore_assign)Scene_202, (ignore_assign)Scene_203, (ignore_assign)Scene_204, (ignore_assign)Scene_205, (ignore_assign)Scene_206, (ignore_assign)Scene_207, (ignore_assign)Scene_208, (ignore_assign)Scene_209, (ignore_assign)Scene_210, (ignore_assign)Scene_211, (ignore_assign)Scene_212, (ignore_assign)Scene_213, (ignore_assign)Scene_214, (ignore_assign)Scene_215, (ignore_assign)Scene_216, (ignore_assign)Scene_217, (ignore_assign)Scene_218, (ignore_assign)Scene_219, (ignore_assign)Scene_220, (ignore_assign)Scene_221, (ignore_assign)Scene_222, (ignore_assign)Scene_223, (ignore_assign)Scene_224, (ignore_assign)Scene_225, (ignore_assign)Scene_226, (ignore_assign)Scene_227, (ignore_assign)Scene_228, (ignore_assign)Scene_229, (ignore_assign)Scene_230, (ignore_assign)Scene_231, (ignore_assign)Scene_232, (ignore_assign)Scene_233, (ignore_assign)Scene_234, (ignore_assign)Scene_235, (ignore_assign)Scene_236, (ignore_assign)Scene_237, (ignore_assign)Scene_238, (ignore_assign)Scene_239, (ignore_assign)Scene_240, (ignore_assign)Scene_241, (ignore_assign)Scene_242, (ignore_assign)Scene_243, (ignore_assign)Scene_244, (ignore_assign)Scene_245, (ignore_assign)Scene_246, (ignore_assign)Scene_247, (ignore_assign)Scene_248, (ignore_assign)Scene_249, (ignore_assign)Scene_250, (ignore_assign)Scene_251, (ignore_assign)Scene_252, (ignore_assign)Scene_253, (ignore_assign)Scene_254, (ignore_assign)Scene_255, (ignore_assign)SceneCount = 256, (ignore_assign)ClearSceneTimeout = 257, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Scene_1 = 1", "Scene_2", "Scene_3", "Scene_4", "Scene_5", "Scene_6", "Scene_7", "Scene_8", "Scene_9", "Scene_10", "Scene_11", "Scene_12", "Scene_13", "Scene_14", "Scene_15", "Scene_16", "Scene_17", "Scene_18", "Scene_19", "Scene_20", "Scene_21", "Scene_22", "Scene_23", "Scene_24", "Scene_25", "Scene_26", "Scene_27", "Scene_28", "Scene_29", "Scene_30", "Scene_31", "Scene_32", "Scene_33", "Scene_34", "Scene_35", "Scene_36", "Scene_37", "Scene_38", "Scene_39", "Scene_40", "Scene_41", "Scene_42", "Scene_43", "Scene_44", "Scene_45", "Scene_46", "Scene_47", "Scene_48", "Scene_49", "Scene_50", "Scene_51", "Scene_52", "Scene_53", "Scene_54", "Scene_55", "Scene_56", "Scene_57", "Scene_58", "Scene_59", "Scene_60", "Scene_61", "Scene_62", "Scene_63", "Scene_64", "Scene_65", "Scene_66", "Scene_67", "Scene_68", "Scene_69", "Scene_70", "Scene_71", "Scene_72", "Scene_73", "Scene_74", "Scene_75", "Scene_76", "Scene_77", "Scene_78", "Scene_79", "Scene_80", "Scene_81", "Scene_82", "Scene_83", "Scene_84", "Scene_85", "Scene_86", "Scene_87", "Scene_88", "Scene_89", "Scene_90", "Scene_91", "Scene_92", "Scene_93", "Scene_94", "Scene_95", "Scene_96", "Scene_97", "Scene_98", "Scene_99", "Scene_100", "Scene_101", "Scene_102", "Scene_103", "Scene_104", "Scene_105", "Scene_106", "Scene_107", "Scene_108", "Scene_109", "Scene_110", "Scene_111", "Scene_112", "Scene_113", "Scene_114", "Scene_115", "Scene_116", "Scene_117", "Scene_118", "Scene_119", "Scene_120", "Scene_121", "Scene_122", "Scene_123", "Scene_124", "Scene_125", "Scene_126", "Scene_127", "Scene_128", "Scene_129", "Scene_130", "Scene_131", "Scene_132", "Scene_133", "Scene_134", "Scene_135", "Scene_136", "Scene_137", "Scene_138", "Scene_139", "Scene_140", "Scene_141", "Scene_142", "Scene_143", "Scene_144", "Scene_145", "Scene_146", "Scene_147", "Scene_148", "Scene_149", "Scene_150", "Scene_151", "Scene_152", "Scene_153", "Scene_154", "Scene_155", "Scene_156", "Scene_157", "Scene_158", "Scene_159", "Scene_160", "Scene_161", "Scene_162", "Scene_163", "Scene_164", "Scene_165", "Scene_166", "Scene_167", "Scene_168", "Scene_169", "Scene_170", "Scene_171", "Scene_172", "Scene_173", "Scene_174", "Scene_175", "Scene_176", "Scene_177", "Scene_178", "Scene_179", "Scene_180", "Scene_181", "Scene_182", "Scene_183", "Scene_184", "Scene_185", "Scene_186", "Scene_187", "Scene_188", "Scene_189", "Scene_190", "Scene_191", "Scene_192", "Scene_193", "Scene_194", "Scene_195", "Scene_196", "Scene_197", "Scene_198", "Scene_199", "Scene_200", "Scene_201", "Scene_202", "Scene_203", "Scene_204", "Scene_205", "Scene_206", "Scene_207", "Scene_208", "Scene_209", "Scene_210", "Scene_211", "Scene_212", "Scene_213", "Scene_214", "Scene_215", "Scene_216", "Scene_217", "Scene_218", "Scene_219", "Scene_220", "Scene_221", "Scene_222", "Scene_223", "Scene_224", "Scene_225", "Scene_226", "Scene_227", "Scene_228", "Scene_229", "Scene_230", "Scene_231", "Scene_232", "Scene_233", "Scene_234", "Scene_235", "Scene_236", "Scene_237", "Scene_238", "Scene_239", "Scene_240", "Scene_241", "Scene_242", "Scene_243", "Scene_244", "Scene_245", "Scene_246", "Scene_247", "Scene_248", "Scene_249", "Scene_250", "Scene_251", "Scene_252", "Scene_253", "Scene_254", "Scene_255", "SceneCount = 256", "ClearSceneTimeout = 257", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; +struct ValueID_Index_ClimateControlSchedule { enum _enumerated { DOW_Monday = 1, DOW_Tuesday = 2, DOW_Wednesday = 3, DOW_Thursday = 4, DOW_Friday = 5, DOW_Saturday = 6, DOW_Sunday = 7, OverrideState = 8, OverrideSetback = 9 }; _enumerated _value; ValueID_Index_ClimateControlSchedule(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 9; static const int* _values() { static const int values[] = { (ignore_assign)DOW_Monday = 1, (ignore_assign)DOW_Tuesday = 2, (ignore_assign)DOW_Wednesday = 3, (ignore_assign)DOW_Thursday = 4, (ignore_assign)DOW_Friday = 5, (ignore_assign)DOW_Saturday = 6, (ignore_assign)DOW_Sunday = 7, (ignore_assign)OverrideState = 8, (ignore_assign)OverrideSetback = 9, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "DOW_Monday = 1", "DOW_Tuesday = 2", "DOW_Wednesday = 3", "DOW_Thursday = 4", "DOW_Friday = 5", "DOW_Saturday = 6", "DOW_Sunday = 7", "OverrideState = 8", "OverrideSetback = 9", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; +struct ValueID_Index_Clock { enum _enumerated { Day = 0, Hour = 1, Minute = 2 }; _enumerated _value; ValueID_Index_Clock(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 3; static const int* _values() { static const int values[] = { (ignore_assign)Day = 0, (ignore_assign)Hour = 1, (ignore_assign)Minute = 2, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Day = 0", "Hour = 1", "Minute = 2", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + + + +struct ValueID_Index_Color { enum _enumerated { Color = 0, Index = 1, Channels_Capabilities = 2, Duration = 4 }; _enumerated _value; ValueID_Index_Color(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 4; static const int* _values() { static const int values[] = { (ignore_assign)Color = 0, (ignore_assign)Index = 1, (ignore_assign)Channels_Capabilities = 2, (ignore_assign)Duration = 4, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Color = 0", "Index = 1", "Channels_Capabilities = 2", "Duration = 4", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + + + + +struct ValueID_Index_Configuration { enum _enumerated { Parameter_1 = 1, Parameter_2, Parameter_3, Parameter_4, Parameter_5, Parameter_6, Parameter_7, Parameter_8, Parameter_9, Parameter_10, Parameter_11, Parameter_12, Parameter_13, Parameter_14, Parameter_15, Parameter_16, Parameter_17, Parameter_18, Parameter_19, Parameter_20, Parameter_21, Parameter_22, Parameter_23, Parameter_24, Parameter_25, Parameter_26, Parameter_27, Parameter_28, Parameter_29, Parameter_30, Parameter_31, Parameter_32, Parameter_33, Parameter_34, Parameter_35, Parameter_36, Parameter_37, Parameter_38, Parameter_39, Parameter_40, Parameter_41, Parameter_42, Parameter_43, Parameter_44, Parameter_45, Parameter_46, Parameter_47, Parameter_48, Parameter_49, Parameter_50, Parameter_51, Parameter_52, Parameter_53, Parameter_54, Parameter_55, Parameter_56, Parameter_57, Parameter_58, Parameter_59, Parameter_60, Parameter_61, Parameter_62, Parameter_63, Parameter_64, Parameter_65, Parameter_66, Parameter_67, Parameter_68, Parameter_69, Parameter_70, Parameter_71, Parameter_72, Parameter_73, Parameter_74, Parameter_75, Parameter_76, Parameter_77, Parameter_78, Parameter_79, Parameter_80, Parameter_81, Parameter_82, Parameter_83, Parameter_84, Parameter_85, Parameter_86, Parameter_87, Parameter_88, Parameter_89, Parameter_90, Parameter_91, Parameter_92, Parameter_93, Parameter_94, Parameter_95, Parameter_96, Parameter_97, Parameter_98, Parameter_99, Parameter_100, Parameter_101, Parameter_102, Parameter_103, Parameter_104, Parameter_105, Parameter_106, Parameter_107, Parameter_108, Parameter_109, Parameter_110, Parameter_111, Parameter_112, Parameter_113, Parameter_114, Parameter_115, Parameter_116, Parameter_117, Parameter_118, Parameter_119, Parameter_120, Parameter_121, Parameter_122, Parameter_123, Parameter_124, Parameter_125, Parameter_126, Parameter_127, Parameter_128, Parameter_129, Parameter_130, Parameter_131, Parameter_132, Parameter_133, Parameter_134, Parameter_135, Parameter_136, Parameter_137, Parameter_138, Parameter_139, Parameter_140, Parameter_141, Parameter_142, Parameter_143, Parameter_144, Parameter_145, Parameter_146, Parameter_147, Parameter_148, Parameter_149, Parameter_150, Parameter_151, Parameter_152, Parameter_153, Parameter_154, Parameter_155, Parameter_156, Parameter_157, Parameter_158, Parameter_159, Parameter_160, Parameter_161, Parameter_162, Parameter_163, Parameter_164, Parameter_165, Parameter_166, Parameter_167, Parameter_168, Parameter_169, Parameter_170, Parameter_171, Parameter_172, Parameter_173, Parameter_174, Parameter_175, Parameter_176, Parameter_177, Parameter_178, Parameter_179, Parameter_180, Parameter_181, Parameter_182, Parameter_183, Parameter_184, Parameter_185, Parameter_186, Parameter_187, Parameter_188, Parameter_189, Parameter_190, Parameter_191, Parameter_192, Parameter_193, Parameter_194, Parameter_195, Parameter_196, Parameter_197, Parameter_198, Parameter_199, Parameter_200, Parameter_201, Parameter_202, Parameter_203, Parameter_204, Parameter_205, Parameter_206, Parameter_207, Parameter_208, Parameter_209, Parameter_210, Parameter_211, Parameter_212, Parameter_213, Parameter_214, Parameter_215, Parameter_216, Parameter_217, Parameter_218, Parameter_219, Parameter_220, Parameter_221, Parameter_222, Parameter_223, Parameter_224, Parameter_225, Parameter_226, Parameter_227, Parameter_228, Parameter_229, Parameter_230, Parameter_231, Parameter_232, Parameter_233, Parameter_234, Parameter_235, Parameter_236, Parameter_237, Parameter_238, Parameter_239, Parameter_240, Parameter_241, Parameter_242, Parameter_243, Parameter_244, Parameter_245, Parameter_246, Parameter_247, Parameter_248, Parameter_249, Parameter_250, Parameter_251, Parameter_252, Parameter_253, Parameter_254, Parameter_255 }; _enumerated _value; ValueID_Index_Configuration(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 255; static const int* _values() { static const int values[] = { (ignore_assign)Parameter_1 = 1, (ignore_assign)Parameter_2, (ignore_assign)Parameter_3, (ignore_assign)Parameter_4, (ignore_assign)Parameter_5, (ignore_assign)Parameter_6, (ignore_assign)Parameter_7, (ignore_assign)Parameter_8, (ignore_assign)Parameter_9, (ignore_assign)Parameter_10, (ignore_assign)Parameter_11, (ignore_assign)Parameter_12, (ignore_assign)Parameter_13, (ignore_assign)Parameter_14, (ignore_assign)Parameter_15, (ignore_assign)Parameter_16, (ignore_assign)Parameter_17, (ignore_assign)Parameter_18, (ignore_assign)Parameter_19, (ignore_assign)Parameter_20, (ignore_assign)Parameter_21, (ignore_assign)Parameter_22, (ignore_assign)Parameter_23, (ignore_assign)Parameter_24, (ignore_assign)Parameter_25, (ignore_assign)Parameter_26, (ignore_assign)Parameter_27, (ignore_assign)Parameter_28, (ignore_assign)Parameter_29, (ignore_assign)Parameter_30, (ignore_assign)Parameter_31, (ignore_assign)Parameter_32, (ignore_assign)Parameter_33, (ignore_assign)Parameter_34, (ignore_assign)Parameter_35, (ignore_assign)Parameter_36, (ignore_assign)Parameter_37, (ignore_assign)Parameter_38, (ignore_assign)Parameter_39, (ignore_assign)Parameter_40, (ignore_assign)Parameter_41, (ignore_assign)Parameter_42, (ignore_assign)Parameter_43, (ignore_assign)Parameter_44, (ignore_assign)Parameter_45, (ignore_assign)Parameter_46, (ignore_assign)Parameter_47, (ignore_assign)Parameter_48, (ignore_assign)Parameter_49, (ignore_assign)Parameter_50, (ignore_assign)Parameter_51, (ignore_assign)Parameter_52, (ignore_assign)Parameter_53, (ignore_assign)Parameter_54, (ignore_assign)Parameter_55, (ignore_assign)Parameter_56, (ignore_assign)Parameter_57, (ignore_assign)Parameter_58, (ignore_assign)Parameter_59, (ignore_assign)Parameter_60, (ignore_assign)Parameter_61, (ignore_assign)Parameter_62, (ignore_assign)Parameter_63, (ignore_assign)Parameter_64, (ignore_assign)Parameter_65, (ignore_assign)Parameter_66, (ignore_assign)Parameter_67, (ignore_assign)Parameter_68, (ignore_assign)Parameter_69, (ignore_assign)Parameter_70, (ignore_assign)Parameter_71, (ignore_assign)Parameter_72, (ignore_assign)Parameter_73, (ignore_assign)Parameter_74, (ignore_assign)Parameter_75, (ignore_assign)Parameter_76, (ignore_assign)Parameter_77, (ignore_assign)Parameter_78, (ignore_assign)Parameter_79, (ignore_assign)Parameter_80, (ignore_assign)Parameter_81, (ignore_assign)Parameter_82, (ignore_assign)Parameter_83, (ignore_assign)Parameter_84, (ignore_assign)Parameter_85, (ignore_assign)Parameter_86, (ignore_assign)Parameter_87, (ignore_assign)Parameter_88, (ignore_assign)Parameter_89, (ignore_assign)Parameter_90, (ignore_assign)Parameter_91, (ignore_assign)Parameter_92, (ignore_assign)Parameter_93, (ignore_assign)Parameter_94, (ignore_assign)Parameter_95, (ignore_assign)Parameter_96, (ignore_assign)Parameter_97, (ignore_assign)Parameter_98, (ignore_assign)Parameter_99, (ignore_assign)Parameter_100, (ignore_assign)Parameter_101, (ignore_assign)Parameter_102, (ignore_assign)Parameter_103, (ignore_assign)Parameter_104, (ignore_assign)Parameter_105, (ignore_assign)Parameter_106, (ignore_assign)Parameter_107, (ignore_assign)Parameter_108, (ignore_assign)Parameter_109, (ignore_assign)Parameter_110, (ignore_assign)Parameter_111, (ignore_assign)Parameter_112, (ignore_assign)Parameter_113, (ignore_assign)Parameter_114, (ignore_assign)Parameter_115, (ignore_assign)Parameter_116, (ignore_assign)Parameter_117, (ignore_assign)Parameter_118, (ignore_assign)Parameter_119, (ignore_assign)Parameter_120, (ignore_assign)Parameter_121, (ignore_assign)Parameter_122, (ignore_assign)Parameter_123, (ignore_assign)Parameter_124, (ignore_assign)Parameter_125, (ignore_assign)Parameter_126, (ignore_assign)Parameter_127, (ignore_assign)Parameter_128, (ignore_assign)Parameter_129, (ignore_assign)Parameter_130, (ignore_assign)Parameter_131, (ignore_assign)Parameter_132, (ignore_assign)Parameter_133, (ignore_assign)Parameter_134, (ignore_assign)Parameter_135, (ignore_assign)Parameter_136, (ignore_assign)Parameter_137, (ignore_assign)Parameter_138, (ignore_assign)Parameter_139, (ignore_assign)Parameter_140, (ignore_assign)Parameter_141, (ignore_assign)Parameter_142, (ignore_assign)Parameter_143, (ignore_assign)Parameter_144, (ignore_assign)Parameter_145, (ignore_assign)Parameter_146, (ignore_assign)Parameter_147, (ignore_assign)Parameter_148, (ignore_assign)Parameter_149, (ignore_assign)Parameter_150, (ignore_assign)Parameter_151, (ignore_assign)Parameter_152, (ignore_assign)Parameter_153, (ignore_assign)Parameter_154, (ignore_assign)Parameter_155, (ignore_assign)Parameter_156, (ignore_assign)Parameter_157, (ignore_assign)Parameter_158, (ignore_assign)Parameter_159, (ignore_assign)Parameter_160, (ignore_assign)Parameter_161, (ignore_assign)Parameter_162, (ignore_assign)Parameter_163, (ignore_assign)Parameter_164, (ignore_assign)Parameter_165, (ignore_assign)Parameter_166, (ignore_assign)Parameter_167, (ignore_assign)Parameter_168, (ignore_assign)Parameter_169, (ignore_assign)Parameter_170, (ignore_assign)Parameter_171, (ignore_assign)Parameter_172, (ignore_assign)Parameter_173, (ignore_assign)Parameter_174, (ignore_assign)Parameter_175, (ignore_assign)Parameter_176, (ignore_assign)Parameter_177, (ignore_assign)Parameter_178, (ignore_assign)Parameter_179, (ignore_assign)Parameter_180, (ignore_assign)Parameter_181, (ignore_assign)Parameter_182, (ignore_assign)Parameter_183, (ignore_assign)Parameter_184, (ignore_assign)Parameter_185, (ignore_assign)Parameter_186, (ignore_assign)Parameter_187, (ignore_assign)Parameter_188, (ignore_assign)Parameter_189, (ignore_assign)Parameter_190, (ignore_assign)Parameter_191, (ignore_assign)Parameter_192, (ignore_assign)Parameter_193, (ignore_assign)Parameter_194, (ignore_assign)Parameter_195, (ignore_assign)Parameter_196, (ignore_assign)Parameter_197, (ignore_assign)Parameter_198, (ignore_assign)Parameter_199, (ignore_assign)Parameter_200, (ignore_assign)Parameter_201, (ignore_assign)Parameter_202, (ignore_assign)Parameter_203, (ignore_assign)Parameter_204, (ignore_assign)Parameter_205, (ignore_assign)Parameter_206, (ignore_assign)Parameter_207, (ignore_assign)Parameter_208, (ignore_assign)Parameter_209, (ignore_assign)Parameter_210, (ignore_assign)Parameter_211, (ignore_assign)Parameter_212, (ignore_assign)Parameter_213, (ignore_assign)Parameter_214, (ignore_assign)Parameter_215, (ignore_assign)Parameter_216, (ignore_assign)Parameter_217, (ignore_assign)Parameter_218, (ignore_assign)Parameter_219, (ignore_assign)Parameter_220, (ignore_assign)Parameter_221, (ignore_assign)Parameter_222, (ignore_assign)Parameter_223, (ignore_assign)Parameter_224, (ignore_assign)Parameter_225, (ignore_assign)Parameter_226, (ignore_assign)Parameter_227, (ignore_assign)Parameter_228, (ignore_assign)Parameter_229, (ignore_assign)Parameter_230, (ignore_assign)Parameter_231, (ignore_assign)Parameter_232, (ignore_assign)Parameter_233, (ignore_assign)Parameter_234, (ignore_assign)Parameter_235, (ignore_assign)Parameter_236, (ignore_assign)Parameter_237, (ignore_assign)Parameter_238, (ignore_assign)Parameter_239, (ignore_assign)Parameter_240, (ignore_assign)Parameter_241, (ignore_assign)Parameter_242, (ignore_assign)Parameter_243, (ignore_assign)Parameter_244, (ignore_assign)Parameter_245, (ignore_assign)Parameter_246, (ignore_assign)Parameter_247, (ignore_assign)Parameter_248, (ignore_assign)Parameter_249, (ignore_assign)Parameter_250, (ignore_assign)Parameter_251, (ignore_assign)Parameter_252, (ignore_assign)Parameter_253, (ignore_assign)Parameter_254, (ignore_assign)Parameter_255, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Parameter_1 = 1", "Parameter_2", "Parameter_3", "Parameter_4", "Parameter_5", "Parameter_6", "Parameter_7", "Parameter_8", "Parameter_9", "Parameter_10", "Parameter_11", "Parameter_12", "Parameter_13", "Parameter_14", "Parameter_15", "Parameter_16", "Parameter_17", "Parameter_18", "Parameter_19", "Parameter_20", "Parameter_21", "Parameter_22", "Parameter_23", "Parameter_24", "Parameter_25", "Parameter_26", "Parameter_27", "Parameter_28", "Parameter_29", "Parameter_30", "Parameter_31", "Parameter_32", "Parameter_33", "Parameter_34", "Parameter_35", "Parameter_36", "Parameter_37", "Parameter_38", "Parameter_39", "Parameter_40", "Parameter_41", "Parameter_42", "Parameter_43", "Parameter_44", "Parameter_45", "Parameter_46", "Parameter_47", "Parameter_48", "Parameter_49", "Parameter_50", "Parameter_51", "Parameter_52", "Parameter_53", "Parameter_54", "Parameter_55", "Parameter_56", "Parameter_57", "Parameter_58", "Parameter_59", "Parameter_60", "Parameter_61", "Parameter_62", "Parameter_63", "Parameter_64", "Parameter_65", "Parameter_66", "Parameter_67", "Parameter_68", "Parameter_69", "Parameter_70", "Parameter_71", "Parameter_72", "Parameter_73", "Parameter_74", "Parameter_75", "Parameter_76", "Parameter_77", "Parameter_78", "Parameter_79", "Parameter_80", "Parameter_81", "Parameter_82", "Parameter_83", "Parameter_84", "Parameter_85", "Parameter_86", "Parameter_87", "Parameter_88", "Parameter_89", "Parameter_90", "Parameter_91", "Parameter_92", "Parameter_93", "Parameter_94", "Parameter_95", "Parameter_96", "Parameter_97", "Parameter_98", "Parameter_99", "Parameter_100", "Parameter_101", "Parameter_102", "Parameter_103", "Parameter_104", "Parameter_105", "Parameter_106", "Parameter_107", "Parameter_108", "Parameter_109", "Parameter_110", "Parameter_111", "Parameter_112", "Parameter_113", "Parameter_114", "Parameter_115", "Parameter_116", "Parameter_117", "Parameter_118", "Parameter_119", "Parameter_120", "Parameter_121", "Parameter_122", "Parameter_123", "Parameter_124", "Parameter_125", "Parameter_126", "Parameter_127", "Parameter_128", "Parameter_129", "Parameter_130", "Parameter_131", "Parameter_132", "Parameter_133", "Parameter_134", "Parameter_135", "Parameter_136", "Parameter_137", "Parameter_138", "Parameter_139", "Parameter_140", "Parameter_141", "Parameter_142", "Parameter_143", "Parameter_144", "Parameter_145", "Parameter_146", "Parameter_147", "Parameter_148", "Parameter_149", "Parameter_150", "Parameter_151", "Parameter_152", "Parameter_153", "Parameter_154", "Parameter_155", "Parameter_156", "Parameter_157", "Parameter_158", "Parameter_159", "Parameter_160", "Parameter_161", "Parameter_162", "Parameter_163", "Parameter_164", "Parameter_165", "Parameter_166", "Parameter_167", "Parameter_168", "Parameter_169", "Parameter_170", "Parameter_171", "Parameter_172", "Parameter_173", "Parameter_174", "Parameter_175", "Parameter_176", "Parameter_177", "Parameter_178", "Parameter_179", "Parameter_180", "Parameter_181", "Parameter_182", "Parameter_183", "Parameter_184", "Parameter_185", "Parameter_186", "Parameter_187", "Parameter_188", "Parameter_189", "Parameter_190", "Parameter_191", "Parameter_192", "Parameter_193", "Parameter_194", "Parameter_195", "Parameter_196", "Parameter_197", "Parameter_198", "Parameter_199", "Parameter_200", "Parameter_201", "Parameter_202", "Parameter_203", "Parameter_204", "Parameter_205", "Parameter_206", "Parameter_207", "Parameter_208", "Parameter_209", "Parameter_210", "Parameter_211", "Parameter_212", "Parameter_213", "Parameter_214", "Parameter_215", "Parameter_216", "Parameter_217", "Parameter_218", "Parameter_219", "Parameter_220", "Parameter_221", "Parameter_222", "Parameter_223", "Parameter_224", "Parameter_225", "Parameter_226", "Parameter_227", "Parameter_228", "Parameter_229", "Parameter_230", "Parameter_231", "Parameter_232", "Parameter_233", "Parameter_234", "Parameter_235", "Parameter_236", "Parameter_237", "Parameter_238", "Parameter_239", "Parameter_240", "Parameter_241", "Parameter_242", "Parameter_243", "Parameter_244", "Parameter_245", "Parameter_246", "Parameter_247", "Parameter_248", "Parameter_249", "Parameter_250", "Parameter_251", "Parameter_252", "Parameter_253", "Parameter_254", "Parameter_255", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; +struct ValueID_Index_ControllerReplication { enum _enumerated { NodeId = 0, Function = 1, Replicate = 2 }; _enumerated _value; ValueID_Index_ControllerReplication(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 3; static const int* _values() { static const int values[] = { (ignore_assign)NodeId = 0, (ignore_assign)Function = 1, (ignore_assign)Replicate = 2, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "NodeId = 0", "Function = 1", "Replicate = 2", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + + + +struct ValueID_Index_DoorLock { enum _enumerated { Lock = 0, Lock_Mode = 1, System_Config_Mode = 2, System_Config_Minutes = 3, System_Config_Seconds = 4, System_Config_OutsideHandles = 5, System_Config_InsideHandles = 6 }; _enumerated _value; ValueID_Index_DoorLock(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 7; static const int* _values() { static const int values[] = { (ignore_assign)Lock = 0, (ignore_assign)Lock_Mode = 1, (ignore_assign)System_Config_Mode = 2, (ignore_assign)System_Config_Minutes = 3, (ignore_assign)System_Config_Seconds = 4, (ignore_assign)System_Config_OutsideHandles = 5, (ignore_assign)System_Config_InsideHandles = 6, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Lock = 0", "Lock_Mode = 1", "System_Config_Mode = 2", "System_Config_Minutes = 3", "System_Config_Seconds = 4", "System_Config_OutsideHandles = 5", "System_Config_InsideHandles = 6", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; +struct ValueID_Index_DoorLockLogging { enum _enumerated { System_Config_MaxRecords = 0, GetRecordNo = 1, LogRecord = 2 }; _enumerated _value; ValueID_Index_DoorLockLogging(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 3; static const int* _values() { static const int values[] = { (ignore_assign)System_Config_MaxRecords = 0, (ignore_assign)GetRecordNo = 1, (ignore_assign)LogRecord = 2, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "System_Config_MaxRecords = 0", "GetRecordNo = 1", "LogRecord = 2", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + + + +struct ValueID_Index_EnergyProduction { enum _enumerated { Instant = 0, Total = 1, Today = 2, Time = 3 }; _enumerated _value; ValueID_Index_EnergyProduction(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 4; static const int* _values() { static const int values[] = { (ignore_assign)Instant = 0, (ignore_assign)Total = 1, (ignore_assign)Today = 2, (ignore_assign)Time = 3, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Instant = 0", "Total = 1", "Today = 2", "Time = 3", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + + + + +struct ValueID_Index_Indicator { enum _enumerated { Indicator = 0 }; _enumerated _value; ValueID_Index_Indicator(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 1; static const int* _values() { static const int values[] = { (ignore_assign)Indicator = 0, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Indicator = 0", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + +struct ValueID_Index_Language { enum _enumerated { Language = 0, Country = 1 }; _enumerated _value; ValueID_Index_Language(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 2; static const int* _values() { static const int values[] = { (ignore_assign)Language = 0, (ignore_assign)Country = 1, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Language = 0", "Country = 1", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + + +struct ValueID_Index_Lock { enum _enumerated { Locked = 0 }; _enumerated _value; ValueID_Index_Lock(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 1; static const int* _values() { static const int values[] = { (ignore_assign)Locked = 0, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Locked = 0", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + +struct ValueID_Index_ManufacturerProprietary { enum _enumerated { FibaroVenetianBlinds_Blinds = 0, FibaroVenetianBlinds_Tilt = 1 }; _enumerated _value; ValueID_Index_ManufacturerProprietary(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 2; static const int* _values() { static const int values[] = { (ignore_assign)FibaroVenetianBlinds_Blinds = 0, (ignore_assign)FibaroVenetianBlinds_Tilt = 1, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "FibaroVenetianBlinds_Blinds = 0", "FibaroVenetianBlinds_Tilt = 1", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + + +struct ValueID_Index_ManufacturerSpecific { enum _enumerated { LoadedConfig = 0, LocalConfig = 1, LatestConfig = 2, DeviceID = 3, SerialNumber = 4 }; _enumerated _value; ValueID_Index_ManufacturerSpecific(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 5; static const int* _values() { static const int values[] = { (ignore_assign)LoadedConfig = 0, (ignore_assign)LocalConfig = 1, (ignore_assign)LatestConfig = 2, (ignore_assign)DeviceID = 3, (ignore_assign)SerialNumber = 4, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "LoadedConfig = 0", "LocalConfig = 1", "LatestConfig = 2", "DeviceID = 3", "SerialNumber = 4", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + + + + + +struct ValueID_Index_Meter { enum _enumerated { Electric_kWh = 0, Electric_kVah, Electric_W, Electric_Pulse, Electric_V, Electric_A, Electric_PowerFactor, Electric_Unknown_1, Electric_kVar, Electric_kVarh, Electric_Unknown_2, Electric_Unknown_3, Electric_Unknown_4, Electric_Unknown_5, Electric_Unknown_6, Electric_Unknown_7, Gas_Cubic_Meters, Gas_Cubic_Feet, Gas_Unknown_1, Gas_Pulse, Gas_Unknown_2, Gas_Unknown_3, Gas_Unknown_4, Gas_Unknown_5, Gas_Unknown_6, Gas_Unknown_7, Gas_Unknown_8, Gas_Unknown_9, Gas_Unknown_10, Gas_Unknown_11, Gas_Unknown_12, Gas_Unknown_13, Water_Cubic_Meters, Water_Cubic_Feet, Water_Cubic_US_Gallons, Water_Cubic_Pulse, Water_Unknown_1, Water_Unknown_2, Water_Unknown_3, Water_Unknown_4, Water_Unknown_5, Water_Unknown_6, Water_Unknown_7, Water_Unknown_8, Water_Unknown_9, Water_Unknown_10, Water_Unknown_11, Water_Unknown_12, Heating_kWh, Heating_Unknown_1, Heating_Unknown_2, Heating_Unknown_3, Heating_Unknown_4, Heating_Unknown_5, Heating_Unknown_6, Heating_Unknown_7, Heating_Unknown_8, Heating_Unknown_9, Heating_Unknown_10, Heating_Unknown_11, Heating_Unknown_12, Heating_Unknown_13, Heating_Unknown_14, Heating_Unknown_15, Cooling_kWh, Cooling_Unknown_1, Cooling_Unknown_2, Cooling_Unknown_3, Cooling_Unknown_4, Cooling_Unknown_5, Cooling_Unknown_6, Cooling_Unknown_7, Cooling_Unknown_8, Cooling_Unknown_9, Cooling_Unknown_10, Cooling_Unknown_11, Cooling_Unknown_12, Cooling_Unknown_13, Cooling_Unknown_14, Cooling_Unknown_15, Exporting = 256, Reset = 257 }; _enumerated _value; ValueID_Index_Meter(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 82; static const int* _values() { static const int values[] = { (ignore_assign)Electric_kWh = 0, (ignore_assign)Electric_kVah, (ignore_assign)Electric_W, (ignore_assign)Electric_Pulse, (ignore_assign)Electric_V, (ignore_assign)Electric_A, (ignore_assign)Electric_PowerFactor, (ignore_assign)Electric_Unknown_1, (ignore_assign)Electric_kVar, (ignore_assign)Electric_kVarh, (ignore_assign)Electric_Unknown_2, (ignore_assign)Electric_Unknown_3, (ignore_assign)Electric_Unknown_4, (ignore_assign)Electric_Unknown_5, (ignore_assign)Electric_Unknown_6, (ignore_assign)Electric_Unknown_7, (ignore_assign)Gas_Cubic_Meters, (ignore_assign)Gas_Cubic_Feet, (ignore_assign)Gas_Unknown_1, (ignore_assign)Gas_Pulse, (ignore_assign)Gas_Unknown_2, (ignore_assign)Gas_Unknown_3, (ignore_assign)Gas_Unknown_4, (ignore_assign)Gas_Unknown_5, (ignore_assign)Gas_Unknown_6, (ignore_assign)Gas_Unknown_7, (ignore_assign)Gas_Unknown_8, (ignore_assign)Gas_Unknown_9, (ignore_assign)Gas_Unknown_10, (ignore_assign)Gas_Unknown_11, (ignore_assign)Gas_Unknown_12, (ignore_assign)Gas_Unknown_13, (ignore_assign)Water_Cubic_Meters, (ignore_assign)Water_Cubic_Feet, (ignore_assign)Water_Cubic_US_Gallons, (ignore_assign)Water_Cubic_Pulse, (ignore_assign)Water_Unknown_1, (ignore_assign)Water_Unknown_2, (ignore_assign)Water_Unknown_3, (ignore_assign)Water_Unknown_4, (ignore_assign)Water_Unknown_5, (ignore_assign)Water_Unknown_6, (ignore_assign)Water_Unknown_7, (ignore_assign)Water_Unknown_8, (ignore_assign)Water_Unknown_9, (ignore_assign)Water_Unknown_10, (ignore_assign)Water_Unknown_11, (ignore_assign)Water_Unknown_12, (ignore_assign)Heating_kWh, (ignore_assign)Heating_Unknown_1, (ignore_assign)Heating_Unknown_2, (ignore_assign)Heating_Unknown_3, (ignore_assign)Heating_Unknown_4, (ignore_assign)Heating_Unknown_5, (ignore_assign)Heating_Unknown_6, (ignore_assign)Heating_Unknown_7, (ignore_assign)Heating_Unknown_8, (ignore_assign)Heating_Unknown_9, (ignore_assign)Heating_Unknown_10, (ignore_assign)Heating_Unknown_11, (ignore_assign)Heating_Unknown_12, (ignore_assign)Heating_Unknown_13, (ignore_assign)Heating_Unknown_14, (ignore_assign)Heating_Unknown_15, (ignore_assign)Cooling_kWh, (ignore_assign)Cooling_Unknown_1, (ignore_assign)Cooling_Unknown_2, (ignore_assign)Cooling_Unknown_3, (ignore_assign)Cooling_Unknown_4, (ignore_assign)Cooling_Unknown_5, (ignore_assign)Cooling_Unknown_6, (ignore_assign)Cooling_Unknown_7, (ignore_assign)Cooling_Unknown_8, (ignore_assign)Cooling_Unknown_9, (ignore_assign)Cooling_Unknown_10, (ignore_assign)Cooling_Unknown_11, (ignore_assign)Cooling_Unknown_12, (ignore_assign)Cooling_Unknown_13, (ignore_assign)Cooling_Unknown_14, (ignore_assign)Cooling_Unknown_15, (ignore_assign)Exporting = 256, (ignore_assign)Reset = 257, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Electric_kWh = 0", "Electric_kVah", "Electric_W", "Electric_Pulse", "Electric_V", "Electric_A", "Electric_PowerFactor", "Electric_Unknown_1", "Electric_kVar", "Electric_kVarh", "Electric_Unknown_2", "Electric_Unknown_3", "Electric_Unknown_4", "Electric_Unknown_5", "Electric_Unknown_6", "Electric_Unknown_7", "Gas_Cubic_Meters", "Gas_Cubic_Feet", "Gas_Unknown_1", "Gas_Pulse", "Gas_Unknown_2", "Gas_Unknown_3", "Gas_Unknown_4", "Gas_Unknown_5", "Gas_Unknown_6", "Gas_Unknown_7", "Gas_Unknown_8", "Gas_Unknown_9", "Gas_Unknown_10", "Gas_Unknown_11", "Gas_Unknown_12", "Gas_Unknown_13", "Water_Cubic_Meters", "Water_Cubic_Feet", "Water_Cubic_US_Gallons", "Water_Cubic_Pulse", "Water_Unknown_1", "Water_Unknown_2", "Water_Unknown_3", "Water_Unknown_4", "Water_Unknown_5", "Water_Unknown_6", "Water_Unknown_7", "Water_Unknown_8", "Water_Unknown_9", "Water_Unknown_10", "Water_Unknown_11", "Water_Unknown_12", "Heating_kWh", "Heating_Unknown_1", "Heating_Unknown_2", "Heating_Unknown_3", "Heating_Unknown_4", "Heating_Unknown_5", "Heating_Unknown_6", "Heating_Unknown_7", "Heating_Unknown_8", "Heating_Unknown_9", "Heating_Unknown_10", "Heating_Unknown_11", "Heating_Unknown_12", "Heating_Unknown_13", "Heating_Unknown_14", "Heating_Unknown_15", "Cooling_kWh", "Cooling_Unknown_1", "Cooling_Unknown_2", "Cooling_Unknown_3", "Cooling_Unknown_4", "Cooling_Unknown_5", "Cooling_Unknown_6", "Cooling_Unknown_7", "Cooling_Unknown_8", "Cooling_Unknown_9", "Cooling_Unknown_10", "Cooling_Unknown_11", "Cooling_Unknown_12", "Cooling_Unknown_13", "Cooling_Unknown_14", "Cooling_Unknown_15", "Exporting = 256", "Reset = 257", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; +struct ValueID_Index_MeterPulse { enum _enumerated { Count = 0 }; _enumerated _value; ValueID_Index_MeterPulse(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 1; static const int* _values() { static const int values[] = { (ignore_assign)Count = 0, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Count = 0", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + +struct ValueID_Index_PowerLevel { enum _enumerated { Powerlevel = 0, Timeout = 1, Set = 2, TestNode = 3, TestPowerlevel = 4, TestFrames = 5, Test = 6, Report = 7, TestStatus = 8, TestAckFrames = 9 }; _enumerated _value; ValueID_Index_PowerLevel(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 10; static const int* _values() { static const int values[] = { (ignore_assign)Powerlevel = 0, (ignore_assign)Timeout = 1, (ignore_assign)Set = 2, (ignore_assign)TestNode = 3, (ignore_assign)TestPowerlevel = 4, (ignore_assign)TestFrames = 5, (ignore_assign)Test = 6, (ignore_assign)Report = 7, (ignore_assign)TestStatus = 8, (ignore_assign)TestAckFrames = 9, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Powerlevel = 0", "Timeout = 1", "Set = 2", "TestNode = 3", "TestPowerlevel = 4", "TestFrames = 5", "Test = 6", "Report = 7", "TestStatus = 8", "TestAckFrames = 9", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; +struct ValueID_Index_Protection { enum _enumerated { Protection = 0 }; _enumerated _value; ValueID_Index_Protection(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 1; static const int* _values() { static const int values[] = { (ignore_assign)Protection = 0, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Protection = 0", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + +struct ValueID_Index_SceneActivation { enum _enumerated { SceneID = 0, Duration = 1 }; _enumerated _value; ValueID_Index_SceneActivation(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 2; static const int* _values() { static const int values[] = { (ignore_assign)SceneID = 0, (ignore_assign)Duration = 1, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "SceneID = 0", "Duration = 1", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + + +struct ValueID_Index_Security { enum _enumerated { Secured = 0 }; _enumerated _value; ValueID_Index_Security(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 1; static const int* _values() { static const int values[] = { (ignore_assign)Secured = 0, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Secured = 0", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + +struct ValueID_Index_SensorAlarm { enum _enumerated { Sensor_1, Sensor_2, Sensor_3, Sensor_4, Sensor_5, Sensor_6, Sensor_7, Sensor_8, Sensor_9, Sensor_10, Sensor_11, Sensor_12, Sensor_13, Sensor_14, Sensor_15, Sensor_16, Sensor_17, Sensor_18, Sensor_19, Sensor_20, Sensor_21, Sensor_22, Sensor_23, Sensor_24, Sensor_25, Sensor_26, Sensor_27, Sensor_28, Sensor_29, Sensor_30, Sensor_31, Sensor_32, Sensor_33, Sensor_34, Sensor_35, Sensor_36, Sensor_37, Sensor_38, Sensor_39, Sensor_40, Sensor_41, Sensor_42, Sensor_43, Sensor_44, Sensor_45, Sensor_46, Sensor_47, Sensor_48, Sensor_49, Sensor_50, Sensor_51, Sensor_52, Sensor_53, Sensor_54, Sensor_55, Sensor_56, Sensor_57, Sensor_58, Sensor_59, Sensor_60, Sensor_61, Sensor_62, Sensor_63, Sensor_64, Sensor_65, Sensor_66, Sensor_67, Sensor_68, Sensor_69, Sensor_70, Sensor_71, Sensor_72, Sensor_73, Sensor_74, Sensor_75, Sensor_76, Sensor_77, Sensor_78, Sensor_79, Sensor_80, Sensor_81, Sensor_82, Sensor_83, Sensor_84, Sensor_85, Sensor_86, Sensor_87, Sensor_88, Sensor_89, Sensor_90, Sensor_91, Sensor_92, Sensor_93, Sensor_94, Sensor_95, Sensor_96, Sensor_97, Sensor_98, Sensor_99, Sensor_100, Sensor_101, Sensor_102, Sensor_103, Sensor_104, Sensor_105, Sensor_106, Sensor_107, Sensor_108, Sensor_109, Sensor_110, Sensor_111, Sensor_112, Sensor_113, Sensor_114, Sensor_115, Sensor_116, Sensor_117, Sensor_118, Sensor_119, Sensor_120, Sensor_121, Sensor_122, Sensor_123, Sensor_124, Sensor_125, Sensor_126, Sensor_127, Sensor_128, Sensor_129, Sensor_130, Sensor_131, Sensor_132, Sensor_133, Sensor_134, Sensor_135, Sensor_136, Sensor_137, Sensor_138, Sensor_139, Sensor_140, Sensor_141, Sensor_142, Sensor_143, Sensor_144, Sensor_145, Sensor_146, Sensor_147, Sensor_148, Sensor_149, Sensor_150, Sensor_151, Sensor_152, Sensor_153, Sensor_154, Sensor_155, Sensor_156, Sensor_157, Sensor_158, Sensor_159, Sensor_160, Sensor_161, Sensor_162, Sensor_163, Sensor_164, Sensor_165, Sensor_166, Sensor_167, Sensor_168, Sensor_169, Sensor_170, Sensor_171, Sensor_172, Sensor_173, Sensor_174, Sensor_175, Sensor_176, Sensor_177, Sensor_178, Sensor_179, Sensor_180, Sensor_181, Sensor_182, Sensor_183, Sensor_184, Sensor_185, Sensor_186, Sensor_187, Sensor_188, Sensor_189, Sensor_190, Sensor_191, Sensor_192, Sensor_193, Sensor_194, Sensor_195, Sensor_196, Sensor_197, Sensor_198, Sensor_199, Sensor_200, Sensor_201, Sensor_202, Sensor_203, Sensor_204, Sensor_205, Sensor_206, Sensor_207, Sensor_208, Sensor_209, Sensor_210, Sensor_211, Sensor_212, Sensor_213, Sensor_214, Sensor_215, Sensor_216, Sensor_217, Sensor_218, Sensor_219, Sensor_220, Sensor_221, Sensor_222, Sensor_223, Sensor_224, Sensor_225, Sensor_226, Sensor_227, Sensor_228, Sensor_229, Sensor_230, Sensor_231, Sensor_232, Sensor_233, Sensor_234, Sensor_235, Sensor_236, Sensor_237, Sensor_238, Sensor_239, Sensor_240, Sensor_241, Sensor_242, Sensor_243, Sensor_244, Sensor_245, Sensor_246, Sensor_247, Sensor_248, Sensor_249, Sensor_250, Sensor_251, Sensor_252, Sensor_253, Sensor_254, Sensor_255 }; _enumerated _value; ValueID_Index_SensorAlarm(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 255; static const int* _values() { static const int values[] = { (ignore_assign)Sensor_1, (ignore_assign)Sensor_2, (ignore_assign)Sensor_3, (ignore_assign)Sensor_4, (ignore_assign)Sensor_5, (ignore_assign)Sensor_6, (ignore_assign)Sensor_7, (ignore_assign)Sensor_8, (ignore_assign)Sensor_9, (ignore_assign)Sensor_10, (ignore_assign)Sensor_11, (ignore_assign)Sensor_12, (ignore_assign)Sensor_13, (ignore_assign)Sensor_14, (ignore_assign)Sensor_15, (ignore_assign)Sensor_16, (ignore_assign)Sensor_17, (ignore_assign)Sensor_18, (ignore_assign)Sensor_19, (ignore_assign)Sensor_20, (ignore_assign)Sensor_21, (ignore_assign)Sensor_22, (ignore_assign)Sensor_23, (ignore_assign)Sensor_24, (ignore_assign)Sensor_25, (ignore_assign)Sensor_26, (ignore_assign)Sensor_27, (ignore_assign)Sensor_28, (ignore_assign)Sensor_29, (ignore_assign)Sensor_30, (ignore_assign)Sensor_31, (ignore_assign)Sensor_32, (ignore_assign)Sensor_33, (ignore_assign)Sensor_34, (ignore_assign)Sensor_35, (ignore_assign)Sensor_36, (ignore_assign)Sensor_37, (ignore_assign)Sensor_38, (ignore_assign)Sensor_39, (ignore_assign)Sensor_40, (ignore_assign)Sensor_41, (ignore_assign)Sensor_42, (ignore_assign)Sensor_43, (ignore_assign)Sensor_44, (ignore_assign)Sensor_45, (ignore_assign)Sensor_46, (ignore_assign)Sensor_47, (ignore_assign)Sensor_48, (ignore_assign)Sensor_49, (ignore_assign)Sensor_50, (ignore_assign)Sensor_51, (ignore_assign)Sensor_52, (ignore_assign)Sensor_53, (ignore_assign)Sensor_54, (ignore_assign)Sensor_55, (ignore_assign)Sensor_56, (ignore_assign)Sensor_57, (ignore_assign)Sensor_58, (ignore_assign)Sensor_59, (ignore_assign)Sensor_60, (ignore_assign)Sensor_61, (ignore_assign)Sensor_62, (ignore_assign)Sensor_63, (ignore_assign)Sensor_64, (ignore_assign)Sensor_65, (ignore_assign)Sensor_66, (ignore_assign)Sensor_67, (ignore_assign)Sensor_68, (ignore_assign)Sensor_69, (ignore_assign)Sensor_70, (ignore_assign)Sensor_71, (ignore_assign)Sensor_72, (ignore_assign)Sensor_73, (ignore_assign)Sensor_74, (ignore_assign)Sensor_75, (ignore_assign)Sensor_76, (ignore_assign)Sensor_77, (ignore_assign)Sensor_78, (ignore_assign)Sensor_79, (ignore_assign)Sensor_80, (ignore_assign)Sensor_81, (ignore_assign)Sensor_82, (ignore_assign)Sensor_83, (ignore_assign)Sensor_84, (ignore_assign)Sensor_85, (ignore_assign)Sensor_86, (ignore_assign)Sensor_87, (ignore_assign)Sensor_88, (ignore_assign)Sensor_89, (ignore_assign)Sensor_90, (ignore_assign)Sensor_91, (ignore_assign)Sensor_92, (ignore_assign)Sensor_93, (ignore_assign)Sensor_94, (ignore_assign)Sensor_95, (ignore_assign)Sensor_96, (ignore_assign)Sensor_97, (ignore_assign)Sensor_98, (ignore_assign)Sensor_99, (ignore_assign)Sensor_100, (ignore_assign)Sensor_101, (ignore_assign)Sensor_102, (ignore_assign)Sensor_103, (ignore_assign)Sensor_104, (ignore_assign)Sensor_105, (ignore_assign)Sensor_106, (ignore_assign)Sensor_107, (ignore_assign)Sensor_108, (ignore_assign)Sensor_109, (ignore_assign)Sensor_110, (ignore_assign)Sensor_111, (ignore_assign)Sensor_112, (ignore_assign)Sensor_113, (ignore_assign)Sensor_114, (ignore_assign)Sensor_115, (ignore_assign)Sensor_116, (ignore_assign)Sensor_117, (ignore_assign)Sensor_118, (ignore_assign)Sensor_119, (ignore_assign)Sensor_120, (ignore_assign)Sensor_121, (ignore_assign)Sensor_122, (ignore_assign)Sensor_123, (ignore_assign)Sensor_124, (ignore_assign)Sensor_125, (ignore_assign)Sensor_126, (ignore_assign)Sensor_127, (ignore_assign)Sensor_128, (ignore_assign)Sensor_129, (ignore_assign)Sensor_130, (ignore_assign)Sensor_131, (ignore_assign)Sensor_132, (ignore_assign)Sensor_133, (ignore_assign)Sensor_134, (ignore_assign)Sensor_135, (ignore_assign)Sensor_136, (ignore_assign)Sensor_137, (ignore_assign)Sensor_138, (ignore_assign)Sensor_139, (ignore_assign)Sensor_140, (ignore_assign)Sensor_141, (ignore_assign)Sensor_142, (ignore_assign)Sensor_143, (ignore_assign)Sensor_144, (ignore_assign)Sensor_145, (ignore_assign)Sensor_146, (ignore_assign)Sensor_147, (ignore_assign)Sensor_148, (ignore_assign)Sensor_149, (ignore_assign)Sensor_150, (ignore_assign)Sensor_151, (ignore_assign)Sensor_152, (ignore_assign)Sensor_153, (ignore_assign)Sensor_154, (ignore_assign)Sensor_155, (ignore_assign)Sensor_156, (ignore_assign)Sensor_157, (ignore_assign)Sensor_158, (ignore_assign)Sensor_159, (ignore_assign)Sensor_160, (ignore_assign)Sensor_161, (ignore_assign)Sensor_162, (ignore_assign)Sensor_163, (ignore_assign)Sensor_164, (ignore_assign)Sensor_165, (ignore_assign)Sensor_166, (ignore_assign)Sensor_167, (ignore_assign)Sensor_168, (ignore_assign)Sensor_169, (ignore_assign)Sensor_170, (ignore_assign)Sensor_171, (ignore_assign)Sensor_172, (ignore_assign)Sensor_173, (ignore_assign)Sensor_174, (ignore_assign)Sensor_175, (ignore_assign)Sensor_176, (ignore_assign)Sensor_177, (ignore_assign)Sensor_178, (ignore_assign)Sensor_179, (ignore_assign)Sensor_180, (ignore_assign)Sensor_181, (ignore_assign)Sensor_182, (ignore_assign)Sensor_183, (ignore_assign)Sensor_184, (ignore_assign)Sensor_185, (ignore_assign)Sensor_186, (ignore_assign)Sensor_187, (ignore_assign)Sensor_188, (ignore_assign)Sensor_189, (ignore_assign)Sensor_190, (ignore_assign)Sensor_191, (ignore_assign)Sensor_192, (ignore_assign)Sensor_193, (ignore_assign)Sensor_194, (ignore_assign)Sensor_195, (ignore_assign)Sensor_196, (ignore_assign)Sensor_197, (ignore_assign)Sensor_198, (ignore_assign)Sensor_199, (ignore_assign)Sensor_200, (ignore_assign)Sensor_201, (ignore_assign)Sensor_202, (ignore_assign)Sensor_203, (ignore_assign)Sensor_204, (ignore_assign)Sensor_205, (ignore_assign)Sensor_206, (ignore_assign)Sensor_207, (ignore_assign)Sensor_208, (ignore_assign)Sensor_209, (ignore_assign)Sensor_210, (ignore_assign)Sensor_211, (ignore_assign)Sensor_212, (ignore_assign)Sensor_213, (ignore_assign)Sensor_214, (ignore_assign)Sensor_215, (ignore_assign)Sensor_216, (ignore_assign)Sensor_217, (ignore_assign)Sensor_218, (ignore_assign)Sensor_219, (ignore_assign)Sensor_220, (ignore_assign)Sensor_221, (ignore_assign)Sensor_222, (ignore_assign)Sensor_223, (ignore_assign)Sensor_224, (ignore_assign)Sensor_225, (ignore_assign)Sensor_226, (ignore_assign)Sensor_227, (ignore_assign)Sensor_228, (ignore_assign)Sensor_229, (ignore_assign)Sensor_230, (ignore_assign)Sensor_231, (ignore_assign)Sensor_232, (ignore_assign)Sensor_233, (ignore_assign)Sensor_234, (ignore_assign)Sensor_235, (ignore_assign)Sensor_236, (ignore_assign)Sensor_237, (ignore_assign)Sensor_238, (ignore_assign)Sensor_239, (ignore_assign)Sensor_240, (ignore_assign)Sensor_241, (ignore_assign)Sensor_242, (ignore_assign)Sensor_243, (ignore_assign)Sensor_244, (ignore_assign)Sensor_245, (ignore_assign)Sensor_246, (ignore_assign)Sensor_247, (ignore_assign)Sensor_248, (ignore_assign)Sensor_249, (ignore_assign)Sensor_250, (ignore_assign)Sensor_251, (ignore_assign)Sensor_252, (ignore_assign)Sensor_253, (ignore_assign)Sensor_254, (ignore_assign)Sensor_255, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Sensor_1", "Sensor_2", "Sensor_3", "Sensor_4", "Sensor_5", "Sensor_6", "Sensor_7", "Sensor_8", "Sensor_9", "Sensor_10", "Sensor_11", "Sensor_12", "Sensor_13", "Sensor_14", "Sensor_15", "Sensor_16", "Sensor_17", "Sensor_18", "Sensor_19", "Sensor_20", "Sensor_21", "Sensor_22", "Sensor_23", "Sensor_24", "Sensor_25", "Sensor_26", "Sensor_27", "Sensor_28", "Sensor_29", "Sensor_30", "Sensor_31", "Sensor_32", "Sensor_33", "Sensor_34", "Sensor_35", "Sensor_36", "Sensor_37", "Sensor_38", "Sensor_39", "Sensor_40", "Sensor_41", "Sensor_42", "Sensor_43", "Sensor_44", "Sensor_45", "Sensor_46", "Sensor_47", "Sensor_48", "Sensor_49", "Sensor_50", "Sensor_51", "Sensor_52", "Sensor_53", "Sensor_54", "Sensor_55", "Sensor_56", "Sensor_57", "Sensor_58", "Sensor_59", "Sensor_60", "Sensor_61", "Sensor_62", "Sensor_63", "Sensor_64", "Sensor_65", "Sensor_66", "Sensor_67", "Sensor_68", "Sensor_69", "Sensor_70", "Sensor_71", "Sensor_72", "Sensor_73", "Sensor_74", "Sensor_75", "Sensor_76", "Sensor_77", "Sensor_78", "Sensor_79", "Sensor_80", "Sensor_81", "Sensor_82", "Sensor_83", "Sensor_84", "Sensor_85", "Sensor_86", "Sensor_87", "Sensor_88", "Sensor_89", "Sensor_90", "Sensor_91", "Sensor_92", "Sensor_93", "Sensor_94", "Sensor_95", "Sensor_96", "Sensor_97", "Sensor_98", "Sensor_99", "Sensor_100", "Sensor_101", "Sensor_102", "Sensor_103", "Sensor_104", "Sensor_105", "Sensor_106", "Sensor_107", "Sensor_108", "Sensor_109", "Sensor_110", "Sensor_111", "Sensor_112", "Sensor_113", "Sensor_114", "Sensor_115", "Sensor_116", "Sensor_117", "Sensor_118", "Sensor_119", "Sensor_120", "Sensor_121", "Sensor_122", "Sensor_123", "Sensor_124", "Sensor_125", "Sensor_126", "Sensor_127", "Sensor_128", "Sensor_129", "Sensor_130", "Sensor_131", "Sensor_132", "Sensor_133", "Sensor_134", "Sensor_135", "Sensor_136", "Sensor_137", "Sensor_138", "Sensor_139", "Sensor_140", "Sensor_141", "Sensor_142", "Sensor_143", "Sensor_144", "Sensor_145", "Sensor_146", "Sensor_147", "Sensor_148", "Sensor_149", "Sensor_150", "Sensor_151", "Sensor_152", "Sensor_153", "Sensor_154", "Sensor_155", "Sensor_156", "Sensor_157", "Sensor_158", "Sensor_159", "Sensor_160", "Sensor_161", "Sensor_162", "Sensor_163", "Sensor_164", "Sensor_165", "Sensor_166", "Sensor_167", "Sensor_168", "Sensor_169", "Sensor_170", "Sensor_171", "Sensor_172", "Sensor_173", "Sensor_174", "Sensor_175", "Sensor_176", "Sensor_177", "Sensor_178", "Sensor_179", "Sensor_180", "Sensor_181", "Sensor_182", "Sensor_183", "Sensor_184", "Sensor_185", "Sensor_186", "Sensor_187", "Sensor_188", "Sensor_189", "Sensor_190", "Sensor_191", "Sensor_192", "Sensor_193", "Sensor_194", "Sensor_195", "Sensor_196", "Sensor_197", "Sensor_198", "Sensor_199", "Sensor_200", "Sensor_201", "Sensor_202", "Sensor_203", "Sensor_204", "Sensor_205", "Sensor_206", "Sensor_207", "Sensor_208", "Sensor_209", "Sensor_210", "Sensor_211", "Sensor_212", "Sensor_213", "Sensor_214", "Sensor_215", "Sensor_216", "Sensor_217", "Sensor_218", "Sensor_219", "Sensor_220", "Sensor_221", "Sensor_222", "Sensor_223", "Sensor_224", "Sensor_225", "Sensor_226", "Sensor_227", "Sensor_228", "Sensor_229", "Sensor_230", "Sensor_231", "Sensor_232", "Sensor_233", "Sensor_234", "Sensor_235", "Sensor_236", "Sensor_237", "Sensor_238", "Sensor_239", "Sensor_240", "Sensor_241", "Sensor_242", "Sensor_243", "Sensor_244", "Sensor_245", "Sensor_246", "Sensor_247", "Sensor_248", "Sensor_249", "Sensor_250", "Sensor_251", "Sensor_252", "Sensor_253", "Sensor_254", "Sensor_255", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; +struct ValueID_Index_SensorBinary { enum _enumerated { Sensor_1, Sensor_2, Sensor_3, Sensor_4, Sensor_5, Sensor_6, Sensor_7, Sensor_8, Sensor_9, Sensor_10, Sensor_11, Sensor_12, Sensor_13, Sensor_14, Sensor_15, Sensor_16, Sensor_17, Sensor_18, Sensor_19, Sensor_20, Sensor_21, Sensor_22, Sensor_23, Sensor_24, Sensor_25, Sensor_26, Sensor_27, Sensor_28, Sensor_29, Sensor_30, Sensor_31, Sensor_32, Sensor_33, Sensor_34, Sensor_35, Sensor_36, Sensor_37, Sensor_38, Sensor_39, Sensor_40, Sensor_41, Sensor_42, Sensor_43, Sensor_44, Sensor_45, Sensor_46, Sensor_47, Sensor_48, Sensor_49, Sensor_50, Sensor_51, Sensor_52, Sensor_53, Sensor_54, Sensor_55, Sensor_56, Sensor_57, Sensor_58, Sensor_59, Sensor_60, Sensor_61, Sensor_62, Sensor_63, Sensor_64, Sensor_65, Sensor_66, Sensor_67, Sensor_68, Sensor_69, Sensor_70, Sensor_71, Sensor_72, Sensor_73, Sensor_74, Sensor_75, Sensor_76, Sensor_77, Sensor_78, Sensor_79, Sensor_80, Sensor_81, Sensor_82, Sensor_83, Sensor_84, Sensor_85, Sensor_86, Sensor_87, Sensor_88, Sensor_89, Sensor_90, Sensor_91, Sensor_92, Sensor_93, Sensor_94, Sensor_95, Sensor_96, Sensor_97, Sensor_98, Sensor_99, Sensor_100, Sensor_101, Sensor_102, Sensor_103, Sensor_104, Sensor_105, Sensor_106, Sensor_107, Sensor_108, Sensor_109, Sensor_110, Sensor_111, Sensor_112, Sensor_113, Sensor_114, Sensor_115, Sensor_116, Sensor_117, Sensor_118, Sensor_119, Sensor_120, Sensor_121, Sensor_122, Sensor_123, Sensor_124, Sensor_125, Sensor_126, Sensor_127, Sensor_128, Sensor_129, Sensor_130, Sensor_131, Sensor_132, Sensor_133, Sensor_134, Sensor_135, Sensor_136, Sensor_137, Sensor_138, Sensor_139, Sensor_140, Sensor_141, Sensor_142, Sensor_143, Sensor_144, Sensor_145, Sensor_146, Sensor_147, Sensor_148, Sensor_149, Sensor_150, Sensor_151, Sensor_152, Sensor_153, Sensor_154, Sensor_155, Sensor_156, Sensor_157, Sensor_158, Sensor_159, Sensor_160, Sensor_161, Sensor_162, Sensor_163, Sensor_164, Sensor_165, Sensor_166, Sensor_167, Sensor_168, Sensor_169, Sensor_170, Sensor_171, Sensor_172, Sensor_173, Sensor_174, Sensor_175, Sensor_176, Sensor_177, Sensor_178, Sensor_179, Sensor_180, Sensor_181, Sensor_182, Sensor_183, Sensor_184, Sensor_185, Sensor_186, Sensor_187, Sensor_188, Sensor_189, Sensor_190, Sensor_191, Sensor_192, Sensor_193, Sensor_194, Sensor_195, Sensor_196, Sensor_197, Sensor_198, Sensor_199, Sensor_200, Sensor_201, Sensor_202, Sensor_203, Sensor_204, Sensor_205, Sensor_206, Sensor_207, Sensor_208, Sensor_209, Sensor_210, Sensor_211, Sensor_212, Sensor_213, Sensor_214, Sensor_215, Sensor_216, Sensor_217, Sensor_218, Sensor_219, Sensor_220, Sensor_221, Sensor_222, Sensor_223, Sensor_224, Sensor_225, Sensor_226, Sensor_227, Sensor_228, Sensor_229, Sensor_230, Sensor_231, Sensor_232, Sensor_233, Sensor_234, Sensor_235, Sensor_236, Sensor_237, Sensor_238, Sensor_239, Sensor_240, Sensor_241, Sensor_242, Sensor_243, Sensor_244, Sensor_245, Sensor_246, Sensor_247, Sensor_248, Sensor_249, Sensor_250, Sensor_251, Sensor_252, Sensor_253, Sensor_254, Sensor_255 }; _enumerated _value; ValueID_Index_SensorBinary(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 255; static const int* _values() { static const int values[] = { (ignore_assign)Sensor_1, (ignore_assign)Sensor_2, (ignore_assign)Sensor_3, (ignore_assign)Sensor_4, (ignore_assign)Sensor_5, (ignore_assign)Sensor_6, (ignore_assign)Sensor_7, (ignore_assign)Sensor_8, (ignore_assign)Sensor_9, (ignore_assign)Sensor_10, (ignore_assign)Sensor_11, (ignore_assign)Sensor_12, (ignore_assign)Sensor_13, (ignore_assign)Sensor_14, (ignore_assign)Sensor_15, (ignore_assign)Sensor_16, (ignore_assign)Sensor_17, (ignore_assign)Sensor_18, (ignore_assign)Sensor_19, (ignore_assign)Sensor_20, (ignore_assign)Sensor_21, (ignore_assign)Sensor_22, (ignore_assign)Sensor_23, (ignore_assign)Sensor_24, (ignore_assign)Sensor_25, (ignore_assign)Sensor_26, (ignore_assign)Sensor_27, (ignore_assign)Sensor_28, (ignore_assign)Sensor_29, (ignore_assign)Sensor_30, (ignore_assign)Sensor_31, (ignore_assign)Sensor_32, (ignore_assign)Sensor_33, (ignore_assign)Sensor_34, (ignore_assign)Sensor_35, (ignore_assign)Sensor_36, (ignore_assign)Sensor_37, (ignore_assign)Sensor_38, (ignore_assign)Sensor_39, (ignore_assign)Sensor_40, (ignore_assign)Sensor_41, (ignore_assign)Sensor_42, (ignore_assign)Sensor_43, (ignore_assign)Sensor_44, (ignore_assign)Sensor_45, (ignore_assign)Sensor_46, (ignore_assign)Sensor_47, (ignore_assign)Sensor_48, (ignore_assign)Sensor_49, (ignore_assign)Sensor_50, (ignore_assign)Sensor_51, (ignore_assign)Sensor_52, (ignore_assign)Sensor_53, (ignore_assign)Sensor_54, (ignore_assign)Sensor_55, (ignore_assign)Sensor_56, (ignore_assign)Sensor_57, (ignore_assign)Sensor_58, (ignore_assign)Sensor_59, (ignore_assign)Sensor_60, (ignore_assign)Sensor_61, (ignore_assign)Sensor_62, (ignore_assign)Sensor_63, (ignore_assign)Sensor_64, (ignore_assign)Sensor_65, (ignore_assign)Sensor_66, (ignore_assign)Sensor_67, (ignore_assign)Sensor_68, (ignore_assign)Sensor_69, (ignore_assign)Sensor_70, (ignore_assign)Sensor_71, (ignore_assign)Sensor_72, (ignore_assign)Sensor_73, (ignore_assign)Sensor_74, (ignore_assign)Sensor_75, (ignore_assign)Sensor_76, (ignore_assign)Sensor_77, (ignore_assign)Sensor_78, (ignore_assign)Sensor_79, (ignore_assign)Sensor_80, (ignore_assign)Sensor_81, (ignore_assign)Sensor_82, (ignore_assign)Sensor_83, (ignore_assign)Sensor_84, (ignore_assign)Sensor_85, (ignore_assign)Sensor_86, (ignore_assign)Sensor_87, (ignore_assign)Sensor_88, (ignore_assign)Sensor_89, (ignore_assign)Sensor_90, (ignore_assign)Sensor_91, (ignore_assign)Sensor_92, (ignore_assign)Sensor_93, (ignore_assign)Sensor_94, (ignore_assign)Sensor_95, (ignore_assign)Sensor_96, (ignore_assign)Sensor_97, (ignore_assign)Sensor_98, (ignore_assign)Sensor_99, (ignore_assign)Sensor_100, (ignore_assign)Sensor_101, (ignore_assign)Sensor_102, (ignore_assign)Sensor_103, (ignore_assign)Sensor_104, (ignore_assign)Sensor_105, (ignore_assign)Sensor_106, (ignore_assign)Sensor_107, (ignore_assign)Sensor_108, (ignore_assign)Sensor_109, (ignore_assign)Sensor_110, (ignore_assign)Sensor_111, (ignore_assign)Sensor_112, (ignore_assign)Sensor_113, (ignore_assign)Sensor_114, (ignore_assign)Sensor_115, (ignore_assign)Sensor_116, (ignore_assign)Sensor_117, (ignore_assign)Sensor_118, (ignore_assign)Sensor_119, (ignore_assign)Sensor_120, (ignore_assign)Sensor_121, (ignore_assign)Sensor_122, (ignore_assign)Sensor_123, (ignore_assign)Sensor_124, (ignore_assign)Sensor_125, (ignore_assign)Sensor_126, (ignore_assign)Sensor_127, (ignore_assign)Sensor_128, (ignore_assign)Sensor_129, (ignore_assign)Sensor_130, (ignore_assign)Sensor_131, (ignore_assign)Sensor_132, (ignore_assign)Sensor_133, (ignore_assign)Sensor_134, (ignore_assign)Sensor_135, (ignore_assign)Sensor_136, (ignore_assign)Sensor_137, (ignore_assign)Sensor_138, (ignore_assign)Sensor_139, (ignore_assign)Sensor_140, (ignore_assign)Sensor_141, (ignore_assign)Sensor_142, (ignore_assign)Sensor_143, (ignore_assign)Sensor_144, (ignore_assign)Sensor_145, (ignore_assign)Sensor_146, (ignore_assign)Sensor_147, (ignore_assign)Sensor_148, (ignore_assign)Sensor_149, (ignore_assign)Sensor_150, (ignore_assign)Sensor_151, (ignore_assign)Sensor_152, (ignore_assign)Sensor_153, (ignore_assign)Sensor_154, (ignore_assign)Sensor_155, (ignore_assign)Sensor_156, (ignore_assign)Sensor_157, (ignore_assign)Sensor_158, (ignore_assign)Sensor_159, (ignore_assign)Sensor_160, (ignore_assign)Sensor_161, (ignore_assign)Sensor_162, (ignore_assign)Sensor_163, (ignore_assign)Sensor_164, (ignore_assign)Sensor_165, (ignore_assign)Sensor_166, (ignore_assign)Sensor_167, (ignore_assign)Sensor_168, (ignore_assign)Sensor_169, (ignore_assign)Sensor_170, (ignore_assign)Sensor_171, (ignore_assign)Sensor_172, (ignore_assign)Sensor_173, (ignore_assign)Sensor_174, (ignore_assign)Sensor_175, (ignore_assign)Sensor_176, (ignore_assign)Sensor_177, (ignore_assign)Sensor_178, (ignore_assign)Sensor_179, (ignore_assign)Sensor_180, (ignore_assign)Sensor_181, (ignore_assign)Sensor_182, (ignore_assign)Sensor_183, (ignore_assign)Sensor_184, (ignore_assign)Sensor_185, (ignore_assign)Sensor_186, (ignore_assign)Sensor_187, (ignore_assign)Sensor_188, (ignore_assign)Sensor_189, (ignore_assign)Sensor_190, (ignore_assign)Sensor_191, (ignore_assign)Sensor_192, (ignore_assign)Sensor_193, (ignore_assign)Sensor_194, (ignore_assign)Sensor_195, (ignore_assign)Sensor_196, (ignore_assign)Sensor_197, (ignore_assign)Sensor_198, (ignore_assign)Sensor_199, (ignore_assign)Sensor_200, (ignore_assign)Sensor_201, (ignore_assign)Sensor_202, (ignore_assign)Sensor_203, (ignore_assign)Sensor_204, (ignore_assign)Sensor_205, (ignore_assign)Sensor_206, (ignore_assign)Sensor_207, (ignore_assign)Sensor_208, (ignore_assign)Sensor_209, (ignore_assign)Sensor_210, (ignore_assign)Sensor_211, (ignore_assign)Sensor_212, (ignore_assign)Sensor_213, (ignore_assign)Sensor_214, (ignore_assign)Sensor_215, (ignore_assign)Sensor_216, (ignore_assign)Sensor_217, (ignore_assign)Sensor_218, (ignore_assign)Sensor_219, (ignore_assign)Sensor_220, (ignore_assign)Sensor_221, (ignore_assign)Sensor_222, (ignore_assign)Sensor_223, (ignore_assign)Sensor_224, (ignore_assign)Sensor_225, (ignore_assign)Sensor_226, (ignore_assign)Sensor_227, (ignore_assign)Sensor_228, (ignore_assign)Sensor_229, (ignore_assign)Sensor_230, (ignore_assign)Sensor_231, (ignore_assign)Sensor_232, (ignore_assign)Sensor_233, (ignore_assign)Sensor_234, (ignore_assign)Sensor_235, (ignore_assign)Sensor_236, (ignore_assign)Sensor_237, (ignore_assign)Sensor_238, (ignore_assign)Sensor_239, (ignore_assign)Sensor_240, (ignore_assign)Sensor_241, (ignore_assign)Sensor_242, (ignore_assign)Sensor_243, (ignore_assign)Sensor_244, (ignore_assign)Sensor_245, (ignore_assign)Sensor_246, (ignore_assign)Sensor_247, (ignore_assign)Sensor_248, (ignore_assign)Sensor_249, (ignore_assign)Sensor_250, (ignore_assign)Sensor_251, (ignore_assign)Sensor_252, (ignore_assign)Sensor_253, (ignore_assign)Sensor_254, (ignore_assign)Sensor_255, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Sensor_1", "Sensor_2", "Sensor_3", "Sensor_4", "Sensor_5", "Sensor_6", "Sensor_7", "Sensor_8", "Sensor_9", "Sensor_10", "Sensor_11", "Sensor_12", "Sensor_13", "Sensor_14", "Sensor_15", "Sensor_16", "Sensor_17", "Sensor_18", "Sensor_19", "Sensor_20", "Sensor_21", "Sensor_22", "Sensor_23", "Sensor_24", "Sensor_25", "Sensor_26", "Sensor_27", "Sensor_28", "Sensor_29", "Sensor_30", "Sensor_31", "Sensor_32", "Sensor_33", "Sensor_34", "Sensor_35", "Sensor_36", "Sensor_37", "Sensor_38", "Sensor_39", "Sensor_40", "Sensor_41", "Sensor_42", "Sensor_43", "Sensor_44", "Sensor_45", "Sensor_46", "Sensor_47", "Sensor_48", "Sensor_49", "Sensor_50", "Sensor_51", "Sensor_52", "Sensor_53", "Sensor_54", "Sensor_55", "Sensor_56", "Sensor_57", "Sensor_58", "Sensor_59", "Sensor_60", "Sensor_61", "Sensor_62", "Sensor_63", "Sensor_64", "Sensor_65", "Sensor_66", "Sensor_67", "Sensor_68", "Sensor_69", "Sensor_70", "Sensor_71", "Sensor_72", "Sensor_73", "Sensor_74", "Sensor_75", "Sensor_76", "Sensor_77", "Sensor_78", "Sensor_79", "Sensor_80", "Sensor_81", "Sensor_82", "Sensor_83", "Sensor_84", "Sensor_85", "Sensor_86", "Sensor_87", "Sensor_88", "Sensor_89", "Sensor_90", "Sensor_91", "Sensor_92", "Sensor_93", "Sensor_94", "Sensor_95", "Sensor_96", "Sensor_97", "Sensor_98", "Sensor_99", "Sensor_100", "Sensor_101", "Sensor_102", "Sensor_103", "Sensor_104", "Sensor_105", "Sensor_106", "Sensor_107", "Sensor_108", "Sensor_109", "Sensor_110", "Sensor_111", "Sensor_112", "Sensor_113", "Sensor_114", "Sensor_115", "Sensor_116", "Sensor_117", "Sensor_118", "Sensor_119", "Sensor_120", "Sensor_121", "Sensor_122", "Sensor_123", "Sensor_124", "Sensor_125", "Sensor_126", "Sensor_127", "Sensor_128", "Sensor_129", "Sensor_130", "Sensor_131", "Sensor_132", "Sensor_133", "Sensor_134", "Sensor_135", "Sensor_136", "Sensor_137", "Sensor_138", "Sensor_139", "Sensor_140", "Sensor_141", "Sensor_142", "Sensor_143", "Sensor_144", "Sensor_145", "Sensor_146", "Sensor_147", "Sensor_148", "Sensor_149", "Sensor_150", "Sensor_151", "Sensor_152", "Sensor_153", "Sensor_154", "Sensor_155", "Sensor_156", "Sensor_157", "Sensor_158", "Sensor_159", "Sensor_160", "Sensor_161", "Sensor_162", "Sensor_163", "Sensor_164", "Sensor_165", "Sensor_166", "Sensor_167", "Sensor_168", "Sensor_169", "Sensor_170", "Sensor_171", "Sensor_172", "Sensor_173", "Sensor_174", "Sensor_175", "Sensor_176", "Sensor_177", "Sensor_178", "Sensor_179", "Sensor_180", "Sensor_181", "Sensor_182", "Sensor_183", "Sensor_184", "Sensor_185", "Sensor_186", "Sensor_187", "Sensor_188", "Sensor_189", "Sensor_190", "Sensor_191", "Sensor_192", "Sensor_193", "Sensor_194", "Sensor_195", "Sensor_196", "Sensor_197", "Sensor_198", "Sensor_199", "Sensor_200", "Sensor_201", "Sensor_202", "Sensor_203", "Sensor_204", "Sensor_205", "Sensor_206", "Sensor_207", "Sensor_208", "Sensor_209", "Sensor_210", "Sensor_211", "Sensor_212", "Sensor_213", "Sensor_214", "Sensor_215", "Sensor_216", "Sensor_217", "Sensor_218", "Sensor_219", "Sensor_220", "Sensor_221", "Sensor_222", "Sensor_223", "Sensor_224", "Sensor_225", "Sensor_226", "Sensor_227", "Sensor_228", "Sensor_229", "Sensor_230", "Sensor_231", "Sensor_232", "Sensor_233", "Sensor_234", "Sensor_235", "Sensor_236", "Sensor_237", "Sensor_238", "Sensor_239", "Sensor_240", "Sensor_241", "Sensor_242", "Sensor_243", "Sensor_244", "Sensor_245", "Sensor_246", "Sensor_247", "Sensor_248", "Sensor_249", "Sensor_250", "Sensor_251", "Sensor_252", "Sensor_253", "Sensor_254", "Sensor_255", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; +struct ValueID_Index_SensorMultiLevel { enum _enumerated { Air_Temperature = 1, General_Purpose, Luminance, Power, Humidity, Velocity, Direction, Atmospheric_Pressure, Barometric_Pressure, Solar_Radiation, Dew_Point, Rain_Rate, Tide_Level, Weight, Voltage, Current, Carbon_Dioxide, Air_Flow, Tank_Capacity, Distance, Angle_Position, Rotation, Water_Temperature, Soil_Temperature, Seismic_Intensity, Seismic_Magnitude, Ultraviolet, Electrical_Resistivity, Electrical_Conductivity, Loudness, Moisture, Frequency, Time, Target_Temperature, Particulate_Mater_2_5, Formaldehyde_CH20_Level, Radon_Concentration, Methane_Density, Volatile_Organic_Compound, Carbon_Monoxide, Soil_Humidity, Soil_Reactivity, Soil_Salinity, Heart_Beat, Blood_Pressure, Muscle_Mass, Fat_Mass, Bone_Mass, Total_Body_Water, Basic_Metabolic_Rate, Body_Mass_Index, X_Axis_Acceleration, Y_Axis_Acceleration, Z_Axis_Acceleration, Smoke_Density, Water_Flow, Water_Pressure, RF_Signal_Strength, Particulate_Matter, Respiratory_Rate, Relative_Modulation, Boiler_Water_Temperature, Domestic_Hot_Water_Temperature, Outside_Temperature, Exhaust_Temperature, Water_Chlorine, Water_Acidity, Water_Oxidation_Reduction_Potential, Heart_Rate_LF_HF_Ratio, Motion_Direction, Applied_Force, Return_Air_Temperature, Supply_Air_Temperature, Condenser_Coil_Temperature, Evaporator_Coil_Temperature, Liquid_Line_Temperature, Discharge_Line_Temperature, Suction, Discharge, Defrost_Temperature, Ozone, Sulfur_Dioxide, Nitrogen_Dioxide, Ammonia, Lead, Particulate_Matter_v2, Air_Temperature_Units = 256, General_Purpose_Units, Luminance_Units, Power_Units, Humidity_Units, Velocity_Units, Direction_Units, Atmospheric_Pressure_Units, Barometric_Pressure_Units, Solar_Radiation_Units, Dew_Point_Units, Rain_Rate_Units, Tide_Level_Units, Weight_Units, Voltage_Units, Current_Units, Carbon_Dioxide_Units, Air_Flow_Units, Tank_Capacity_Units, Distance_Units, Angle_Position_Units, Rotation_Units, Water_Temperature_Units, Soil_Temperature_Units, Seismic_Intensity_Units, Seismic_Magnitude_Units, Ultraviolet_Units, Electrical_Resistivity_Units, Electrical_Conductivity_Units, Loudness_Units, Moisture_Units, Frequency_Units, Time_Units, Target_Temperature_Units, Particulate_Mater_2_5_Units, Formaldehyde_CH20_Level_Units, Radon_Concentration_Units, Methane_Density_Units, Volatile_Organic_Compound_Units, Carbon_Monoxide_Units, Soil_Humidity_Units, Soil_Reactivity_Units, Soil_Salinity_Units, Heart_Beat_Units, Blood_Pressure_Units, Muscle_Mass_Units, Fat_Mass_Units, Bone_Mass_Units, Total_Body_Water_Units, Basic_Metabolic_Rate_Units, Body_Mass_Index_Units, X_Axis_Acceleration_Units, Y_Axis_Acceleration_Units, Z_Axis_Acceleration_Units, Smoke_Density_Units, Water_Flow_Units, Water_Pressure_Units, RF_Signal_Strength_Units, Particulate_Matter_Units, Respiratory_Rate_Units, Relative_Modulation_Units, Boiler_Water_Temperature_Units, Domestic_Hot_Water_Temperature_Units, Outside_Temperature_Units, Exhaust_Temperature_Units, Water_Chlorine_Units, Water_Acidity_Units, Water_Oxidation_Reduction_Potential_Units, Heart_Rate_LF_HF_Ratio_Units, Motion_Direction_Units, Applied_Force_Units, Return_Air_Temperature_Units, Supply_Air_Temperature_Units, Condenser_Coil_Temperature_Units, Evaporator_Coil_Temperature_Units, Liquid_Line_Temperature_Units, Discharge_Line_Temperature_Units, Suction_Units, Discharge_Units, Defrost_Temperature_Units, Ozone_Units, Sulfur_Dioxide_Units, Nitrogen_Dioxide_Units, Ammonia_Units, Lead_Units, Particulate_Matter_v2_Units }; _enumerated _value; ValueID_Index_SensorMultiLevel(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 172; static const int* _values() { static const int values[] = { (ignore_assign)Air_Temperature = 1, (ignore_assign)General_Purpose, (ignore_assign)Luminance, (ignore_assign)Power, (ignore_assign)Humidity, (ignore_assign)Velocity, (ignore_assign)Direction, (ignore_assign)Atmospheric_Pressure, (ignore_assign)Barometric_Pressure, (ignore_assign)Solar_Radiation, (ignore_assign)Dew_Point, (ignore_assign)Rain_Rate, (ignore_assign)Tide_Level, (ignore_assign)Weight, (ignore_assign)Voltage, (ignore_assign)Current, (ignore_assign)Carbon_Dioxide, (ignore_assign)Air_Flow, (ignore_assign)Tank_Capacity, (ignore_assign)Distance, (ignore_assign)Angle_Position, (ignore_assign)Rotation, (ignore_assign)Water_Temperature, (ignore_assign)Soil_Temperature, (ignore_assign)Seismic_Intensity, (ignore_assign)Seismic_Magnitude, (ignore_assign)Ultraviolet, (ignore_assign)Electrical_Resistivity, (ignore_assign)Electrical_Conductivity, (ignore_assign)Loudness, (ignore_assign)Moisture, (ignore_assign)Frequency, (ignore_assign)Time, (ignore_assign)Target_Temperature, (ignore_assign)Particulate_Mater_2_5, (ignore_assign)Formaldehyde_CH20_Level, (ignore_assign)Radon_Concentration, (ignore_assign)Methane_Density, (ignore_assign)Volatile_Organic_Compound, (ignore_assign)Carbon_Monoxide, (ignore_assign)Soil_Humidity, (ignore_assign)Soil_Reactivity, (ignore_assign)Soil_Salinity, (ignore_assign)Heart_Beat, (ignore_assign)Blood_Pressure, (ignore_assign)Muscle_Mass, (ignore_assign)Fat_Mass, (ignore_assign)Bone_Mass, (ignore_assign)Total_Body_Water, (ignore_assign)Basic_Metabolic_Rate, (ignore_assign)Body_Mass_Index, (ignore_assign)X_Axis_Acceleration, (ignore_assign)Y_Axis_Acceleration, (ignore_assign)Z_Axis_Acceleration, (ignore_assign)Smoke_Density, (ignore_assign)Water_Flow, (ignore_assign)Water_Pressure, (ignore_assign)RF_Signal_Strength, (ignore_assign)Particulate_Matter, (ignore_assign)Respiratory_Rate, (ignore_assign)Relative_Modulation, (ignore_assign)Boiler_Water_Temperature, (ignore_assign)Domestic_Hot_Water_Temperature, (ignore_assign)Outside_Temperature, (ignore_assign)Exhaust_Temperature, (ignore_assign)Water_Chlorine, (ignore_assign)Water_Acidity, (ignore_assign)Water_Oxidation_Reduction_Potential, (ignore_assign)Heart_Rate_LF_HF_Ratio, (ignore_assign)Motion_Direction, (ignore_assign)Applied_Force, (ignore_assign)Return_Air_Temperature, (ignore_assign)Supply_Air_Temperature, (ignore_assign)Condenser_Coil_Temperature, (ignore_assign)Evaporator_Coil_Temperature, (ignore_assign)Liquid_Line_Temperature, (ignore_assign)Discharge_Line_Temperature, (ignore_assign)Suction, (ignore_assign)Discharge, (ignore_assign)Defrost_Temperature, (ignore_assign)Ozone, (ignore_assign)Sulfur_Dioxide, (ignore_assign)Nitrogen_Dioxide, (ignore_assign)Ammonia, (ignore_assign)Lead, (ignore_assign)Particulate_Matter_v2, (ignore_assign)Air_Temperature_Units = 256, (ignore_assign)General_Purpose_Units, (ignore_assign)Luminance_Units, (ignore_assign)Power_Units, (ignore_assign)Humidity_Units, (ignore_assign)Velocity_Units, (ignore_assign)Direction_Units, (ignore_assign)Atmospheric_Pressure_Units, (ignore_assign)Barometric_Pressure_Units, (ignore_assign)Solar_Radiation_Units, (ignore_assign)Dew_Point_Units, (ignore_assign)Rain_Rate_Units, (ignore_assign)Tide_Level_Units, (ignore_assign)Weight_Units, (ignore_assign)Voltage_Units, (ignore_assign)Current_Units, (ignore_assign)Carbon_Dioxide_Units, (ignore_assign)Air_Flow_Units, (ignore_assign)Tank_Capacity_Units, (ignore_assign)Distance_Units, (ignore_assign)Angle_Position_Units, (ignore_assign)Rotation_Units, (ignore_assign)Water_Temperature_Units, (ignore_assign)Soil_Temperature_Units, (ignore_assign)Seismic_Intensity_Units, (ignore_assign)Seismic_Magnitude_Units, (ignore_assign)Ultraviolet_Units, (ignore_assign)Electrical_Resistivity_Units, (ignore_assign)Electrical_Conductivity_Units, (ignore_assign)Loudness_Units, (ignore_assign)Moisture_Units, (ignore_assign)Frequency_Units, (ignore_assign)Time_Units, (ignore_assign)Target_Temperature_Units, (ignore_assign)Particulate_Mater_2_5_Units, (ignore_assign)Formaldehyde_CH20_Level_Units, (ignore_assign)Radon_Concentration_Units, (ignore_assign)Methane_Density_Units, (ignore_assign)Volatile_Organic_Compound_Units, (ignore_assign)Carbon_Monoxide_Units, (ignore_assign)Soil_Humidity_Units, (ignore_assign)Soil_Reactivity_Units, (ignore_assign)Soil_Salinity_Units, (ignore_assign)Heart_Beat_Units, (ignore_assign)Blood_Pressure_Units, (ignore_assign)Muscle_Mass_Units, (ignore_assign)Fat_Mass_Units, (ignore_assign)Bone_Mass_Units, (ignore_assign)Total_Body_Water_Units, (ignore_assign)Basic_Metabolic_Rate_Units, (ignore_assign)Body_Mass_Index_Units, (ignore_assign)X_Axis_Acceleration_Units, (ignore_assign)Y_Axis_Acceleration_Units, (ignore_assign)Z_Axis_Acceleration_Units, (ignore_assign)Smoke_Density_Units, (ignore_assign)Water_Flow_Units, (ignore_assign)Water_Pressure_Units, (ignore_assign)RF_Signal_Strength_Units, (ignore_assign)Particulate_Matter_Units, (ignore_assign)Respiratory_Rate_Units, (ignore_assign)Relative_Modulation_Units, (ignore_assign)Boiler_Water_Temperature_Units, (ignore_assign)Domestic_Hot_Water_Temperature_Units, (ignore_assign)Outside_Temperature_Units, (ignore_assign)Exhaust_Temperature_Units, (ignore_assign)Water_Chlorine_Units, (ignore_assign)Water_Acidity_Units, (ignore_assign)Water_Oxidation_Reduction_Potential_Units, (ignore_assign)Heart_Rate_LF_HF_Ratio_Units, (ignore_assign)Motion_Direction_Units, (ignore_assign)Applied_Force_Units, (ignore_assign)Return_Air_Temperature_Units, (ignore_assign)Supply_Air_Temperature_Units, (ignore_assign)Condenser_Coil_Temperature_Units, (ignore_assign)Evaporator_Coil_Temperature_Units, (ignore_assign)Liquid_Line_Temperature_Units, (ignore_assign)Discharge_Line_Temperature_Units, (ignore_assign)Suction_Units, (ignore_assign)Discharge_Units, (ignore_assign)Defrost_Temperature_Units, (ignore_assign)Ozone_Units, (ignore_assign)Sulfur_Dioxide_Units, (ignore_assign)Nitrogen_Dioxide_Units, (ignore_assign)Ammonia_Units, (ignore_assign)Lead_Units, (ignore_assign)Particulate_Matter_v2_Units, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Air_Temperature = 1", "General_Purpose", "Luminance", "Power", "Humidity", "Velocity", "Direction", "Atmospheric_Pressure", "Barometric_Pressure", "Solar_Radiation", "Dew_Point", "Rain_Rate", "Tide_Level", "Weight", "Voltage", "Current", "Carbon_Dioxide", "Air_Flow", "Tank_Capacity", "Distance", "Angle_Position", "Rotation", "Water_Temperature", "Soil_Temperature", "Seismic_Intensity", "Seismic_Magnitude", "Ultraviolet", "Electrical_Resistivity", "Electrical_Conductivity", "Loudness", "Moisture", "Frequency", "Time", "Target_Temperature", "Particulate_Mater_2_5", "Formaldehyde_CH20_Level", "Radon_Concentration", "Methane_Density", "Volatile_Organic_Compound", "Carbon_Monoxide", "Soil_Humidity", "Soil_Reactivity", "Soil_Salinity", "Heart_Beat", "Blood_Pressure", "Muscle_Mass", "Fat_Mass", "Bone_Mass", "Total_Body_Water", "Basic_Metabolic_Rate", "Body_Mass_Index", "X_Axis_Acceleration", "Y_Axis_Acceleration", "Z_Axis_Acceleration", "Smoke_Density", "Water_Flow", "Water_Pressure", "RF_Signal_Strength", "Particulate_Matter", "Respiratory_Rate", "Relative_Modulation", "Boiler_Water_Temperature", "Domestic_Hot_Water_Temperature", "Outside_Temperature", "Exhaust_Temperature", "Water_Chlorine", "Water_Acidity", "Water_Oxidation_Reduction_Potential", "Heart_Rate_LF_HF_Ratio", "Motion_Direction", "Applied_Force", "Return_Air_Temperature", "Supply_Air_Temperature", "Condenser_Coil_Temperature", "Evaporator_Coil_Temperature", "Liquid_Line_Temperature", "Discharge_Line_Temperature", "Suction", "Discharge", "Defrost_Temperature", "Ozone", "Sulfur_Dioxide", "Nitrogen_Dioxide", "Ammonia", "Lead", "Particulate_Matter_v2", "Air_Temperature_Units = 256", "General_Purpose_Units", "Luminance_Units", "Power_Units", "Humidity_Units", "Velocity_Units", "Direction_Units", "Atmospheric_Pressure_Units", "Barometric_Pressure_Units", "Solar_Radiation_Units", "Dew_Point_Units", "Rain_Rate_Units", "Tide_Level_Units", "Weight_Units", "Voltage_Units", "Current_Units", "Carbon_Dioxide_Units", "Air_Flow_Units", "Tank_Capacity_Units", "Distance_Units", "Angle_Position_Units", "Rotation_Units", "Water_Temperature_Units", "Soil_Temperature_Units", "Seismic_Intensity_Units", "Seismic_Magnitude_Units", "Ultraviolet_Units", "Electrical_Resistivity_Units", "Electrical_Conductivity_Units", "Loudness_Units", "Moisture_Units", "Frequency_Units", "Time_Units", "Target_Temperature_Units", "Particulate_Mater_2_5_Units", "Formaldehyde_CH20_Level_Units", "Radon_Concentration_Units", "Methane_Density_Units", "Volatile_Organic_Compound_Units", "Carbon_Monoxide_Units", "Soil_Humidity_Units", "Soil_Reactivity_Units", "Soil_Salinity_Units", "Heart_Beat_Units", "Blood_Pressure_Units", "Muscle_Mass_Units", "Fat_Mass_Units", "Bone_Mass_Units", "Total_Body_Water_Units", "Basic_Metabolic_Rate_Units", "Body_Mass_Index_Units", "X_Axis_Acceleration_Units", "Y_Axis_Acceleration_Units", "Z_Axis_Acceleration_Units", "Smoke_Density_Units", "Water_Flow_Units", "Water_Pressure_Units", "RF_Signal_Strength_Units", "Particulate_Matter_Units", "Respiratory_Rate_Units", "Relative_Modulation_Units", "Boiler_Water_Temperature_Units", "Domestic_Hot_Water_Temperature_Units", "Outside_Temperature_Units", "Exhaust_Temperature_Units", "Water_Chlorine_Units", "Water_Acidity_Units", "Water_Oxidation_Reduction_Potential_Units", "Heart_Rate_LF_HF_Ratio_Units", "Motion_Direction_Units", "Applied_Force_Units", "Return_Air_Temperature_Units", "Supply_Air_Temperature_Units", "Condenser_Coil_Temperature_Units", "Evaporator_Coil_Temperature_Units", "Liquid_Line_Temperature_Units", "Discharge_Line_Temperature_Units", "Suction_Units", "Discharge_Units", "Defrost_Temperature_Units", "Ozone_Units", "Sulfur_Dioxide_Units", "Nitrogen_Dioxide_Units", "Ammonia_Units", "Lead_Units", "Particulate_Matter_v2_Units", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; +struct ValueID_Index_SimpleAV { enum _enumerated { Command = 0 }; _enumerated _value; ValueID_Index_SimpleAV(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 1; static const int* _values() { static const int values[] = { (ignore_assign)Command = 0, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Command = 0", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + +struct ValueID_Index_SoundSwitch { enum _enumerated { Tone_Count = 0, Tones = 1, Volume = 2, Default_Tone = 3 }; _enumerated _value; ValueID_Index_SoundSwitch(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 4; static const int* _values() { static const int values[] = { (ignore_assign)Tone_Count = 0, (ignore_assign)Tones = 1, (ignore_assign)Volume = 2, (ignore_assign)Default_Tone = 3, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Tone_Count = 0", "Tones = 1", "Volume = 2", "Default_Tone = 3", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + + + + +struct ValueID_Index_SwitchAll { enum _enumerated { SwitchAll = 0 }; _enumerated _value; ValueID_Index_SwitchAll(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 1; static const int* _values() { static const int values[] = { (ignore_assign)SwitchAll = 0, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "SwitchAll = 0", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + +struct ValueID_Index_SwitchBinary { enum _enumerated { Level = 0, TargetState = 1, Duration = 2 }; _enumerated _value; ValueID_Index_SwitchBinary(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 3; static const int* _values() { static const int values[] = { (ignore_assign)Level = 0, (ignore_assign)TargetState = 1, (ignore_assign)Duration = 2, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Level = 0", "TargetState = 1", "Duration = 2", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + + + +struct ValueID_Index_SwitchMultiLevel { enum _enumerated { Level = 0, Bright = 1, Dim = 2, IgnoreStartLevel = 3, StartLevel = 4, Duration = 5, Step = 6, Inc = 7, Dec = 8, TargetValue = 9 }; _enumerated _value; ValueID_Index_SwitchMultiLevel(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 10; static const int* _values() { static const int values[] = { (ignore_assign)Level = 0, (ignore_assign)Bright = 1, (ignore_assign)Dim = 2, (ignore_assign)IgnoreStartLevel = 3, (ignore_assign)StartLevel = 4, (ignore_assign)Duration = 5, (ignore_assign)Step = 6, (ignore_assign)Inc = 7, (ignore_assign)Dec = 8, (ignore_assign)TargetValue = 9, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Level = 0", "Bright = 1", "Dim = 2", "IgnoreStartLevel = 3", "StartLevel = 4", "Duration = 5", "Step = 6", "Inc = 7", "Dec = 8", "TargetValue = 9", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; +struct ValueID_Index_SwitchToggleBinary { enum _enumerated { ToggleSwitch = 0 }; _enumerated _value; ValueID_Index_SwitchToggleBinary(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 1; static const int* _values() { static const int values[] = { (ignore_assign)ToggleSwitch = 0, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "ToggleSwitch = 0", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + +struct ValueID_Index_SwitchToggleMultilevel { enum _enumerated { Level = 0 }; _enumerated _value; ValueID_Index_SwitchToggleMultilevel(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 1; static const int* _values() { static const int values[] = { (ignore_assign)Level = 0, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Level = 0", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + +struct ValueID_Index_ThermostatFanMode { enum _enumerated { FanMode = 0 }; _enumerated _value; ValueID_Index_ThermostatFanMode(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 1; static const int* _values() { static const int values[] = { (ignore_assign)FanMode = 0, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "FanMode = 0", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + +struct ValueID_Index_ThermostatFanState { enum _enumerated { FanState = 0 }; _enumerated _value; ValueID_Index_ThermostatFanState(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 1; static const int* _values() { static const int values[] = { (ignore_assign)FanState = 0, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "FanState = 0", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + +struct ValueID_Index_ThermostatMode { enum _enumerated { Mode = 0 }; _enumerated _value; ValueID_Index_ThermostatMode(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 1; static const int* _values() { static const int values[] = { (ignore_assign)Mode = 0, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Mode = 0", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + +struct ValueID_Index_ThermostatOperatingState { enum _enumerated { OperatingState = 0 }; _enumerated _value; ValueID_Index_ThermostatOperatingState(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 1; static const int* _values() { static const int values[] = { (ignore_assign)OperatingState = 0, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "OperatingState = 0", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + +struct ValueID_Index_ThermostatSetpoint { enum _enumerated { Unused_0 = 0, Heating, Cooling, Unused_3, Unused_4, Unused_5, Unused_6, Furnace, DryAir, MoistAir, AutoChangeover, HeatingEcon, CoolingEcon, AwayHeating, CoolingHeating, Unused_0_Minimum = 100, Heating_Minimum, Cooling_Minimum, Unused_3_Minimum, Unused_4_Minimum, Unused_5_Minimum, Unused_6_Minimum, Furnace_Minimum, DryAir_Minimum, MoistAir_Minimum, AutoChangeOver_Minimum, Heating_Econ_Minimum, Cooling_Econ_Minimum, Away_Heating_Minimum, Cooling_Heating_Minimum, Unused_0_Maximum = 200, Heating_Maximum, Cooling_Maximum, Unused_3_Maximum, Unused_4_Maximum, Unused_5_Maximum, Unused_6_Maximum, Furnace_Maximum, DryAir_Maximum, MoistAir_Maximum, AutoChangeOver_Maximum, Heating_Econ_Maximum, Cooling_Econ_Maximum, Away_Heating_Maximum, Cooling_Heating_Maximum }; _enumerated _value; ValueID_Index_ThermostatSetpoint(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 45; static const int* _values() { static const int values[] = { (ignore_assign)Unused_0 = 0, (ignore_assign)Heating, (ignore_assign)Cooling, (ignore_assign)Unused_3, (ignore_assign)Unused_4, (ignore_assign)Unused_5, (ignore_assign)Unused_6, (ignore_assign)Furnace, (ignore_assign)DryAir, (ignore_assign)MoistAir, (ignore_assign)AutoChangeover, (ignore_assign)HeatingEcon, (ignore_assign)CoolingEcon, (ignore_assign)AwayHeating, (ignore_assign)CoolingHeating, (ignore_assign)Unused_0_Minimum = 100, (ignore_assign)Heating_Minimum, (ignore_assign)Cooling_Minimum, (ignore_assign)Unused_3_Minimum, (ignore_assign)Unused_4_Minimum, (ignore_assign)Unused_5_Minimum, (ignore_assign)Unused_6_Minimum, (ignore_assign)Furnace_Minimum, (ignore_assign)DryAir_Minimum, (ignore_assign)MoistAir_Minimum, (ignore_assign)AutoChangeOver_Minimum, (ignore_assign)Heating_Econ_Minimum, (ignore_assign)Cooling_Econ_Minimum, (ignore_assign)Away_Heating_Minimum, (ignore_assign)Cooling_Heating_Minimum, (ignore_assign)Unused_0_Maximum = 200, (ignore_assign)Heating_Maximum, (ignore_assign)Cooling_Maximum, (ignore_assign)Unused_3_Maximum, (ignore_assign)Unused_4_Maximum, (ignore_assign)Unused_5_Maximum, (ignore_assign)Unused_6_Maximum, (ignore_assign)Furnace_Maximum, (ignore_assign)DryAir_Maximum, (ignore_assign)MoistAir_Maximum, (ignore_assign)AutoChangeOver_Maximum, (ignore_assign)Heating_Econ_Maximum, (ignore_assign)Cooling_Econ_Maximum, (ignore_assign)Away_Heating_Maximum, (ignore_assign)Cooling_Heating_Maximum, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Unused_0 = 0", "Heating", "Cooling", "Unused_3", "Unused_4", "Unused_5", "Unused_6", "Furnace", "DryAir", "MoistAir", "AutoChangeover", "HeatingEcon", "CoolingEcon", "AwayHeating", "CoolingHeating", "Unused_0_Minimum = 100", "Heating_Minimum", "Cooling_Minimum", "Unused_3_Minimum", "Unused_4_Minimum", "Unused_5_Minimum", "Unused_6_Minimum", "Furnace_Minimum", "DryAir_Minimum", "MoistAir_Minimum", "AutoChangeOver_Minimum", "Heating_Econ_Minimum", "Cooling_Econ_Minimum", "Away_Heating_Minimum", "Cooling_Heating_Minimum", "Unused_0_Maximum = 200", "Heating_Maximum", "Cooling_Maximum", "Unused_3_Maximum", "Unused_4_Maximum", "Unused_5_Maximum", "Unused_6_Maximum", "Furnace_Maximum", "DryAir_Maximum", "MoistAir_Maximum", "AutoChangeOver_Maximum", "Heating_Econ_Maximum", "Cooling_Econ_Maximum", "Away_Heating_Maximum", "Cooling_Heating_Maximum", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; +struct ValueID_Index_TimeParameters { enum _enumerated { Date = 0, Time = 1, Set = 2, Refresh = 3 }; _enumerated _value; ValueID_Index_TimeParameters(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 4; static const int* _values() { static const int values[] = { (ignore_assign)Date = 0, (ignore_assign)Time = 1, (ignore_assign)Set = 2, (ignore_assign)Refresh = 3, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Date = 0", "Time = 1", "Set = 2", "Refresh = 3", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + + + + +struct ValueID_Index_UserCode { enum _enumerated { Enrollment_Code = 0, Code_1, Code_2, Code_3, Code_4, Code_5, Code_6, Code_7, Code_8, Code_9, Code_10, Code_11, Code_12, Code_13, Code_14, Code_15, Code_16, Code_17, Code_18, Code_19, Code_20, Code_21, Code_22, Code_23, Code_24, Code_25, Code_26, Code_27, Code_28, Code_29, Code_30, Code_31, Code_32, Code_33, Code_34, Code_35, Code_36, Code_37, Code_38, Code_39, Code_40, Code_41, Code_42, Code_43, Code_44, Code_45, Code_46, Code_47, Code_48, Code_49, Code_50, Code_51, Code_52, Code_53, Code_54, Code_55, Code_56, Code_57, Code_58, Code_59, Code_60, Code_61, Code_62, Code_63, Code_64, Code_65, Code_66, Code_67, Code_68, Code_69, Code_70, Code_71, Code_72, Code_73, Code_74, Code_75, Code_76, Code_77, Code_78, Code_79, Code_80, Code_81, Code_82, Code_83, Code_84, Code_85, Code_86, Code_87, Code_88, Code_89, Code_90, Code_91, Code_92, Code_93, Code_94, Code_95, Code_96, Code_97, Code_98, Code_99, Code_100, Code_101, Code_102, Code_103, Code_104, Code_105, Code_106, Code_107, Code_108, Code_109, Code_110, Code_111, Code_112, Code_113, Code_114, Code_115, Code_116, Code_117, Code_118, Code_119, Code_120, Code_121, Code_122, Code_123, Code_124, Code_125, Code_126, Code_127, Code_128, Code_129, Code_130, Code_131, Code_132, Code_133, Code_134, Code_135, Code_136, Code_137, Code_138, Code_139, Code_140, Code_141, Code_142, Code_143, Code_144, Code_145, Code_146, Code_147, Code_148, Code_149, Code_150, Code_151, Code_152, Code_153, Code_154, Code_155, Code_156, Code_157, Code_158, Code_159, Code_160, Code_161, Code_162, Code_163, Code_164, Code_165, Code_166, Code_167, Code_168, Code_169, Code_170, Code_171, Code_172, Code_173, Code_174, Code_175, Code_176, Code_177, Code_178, Code_179, Code_180, Code_181, Code_182, Code_183, Code_184, Code_185, Code_186, Code_187, Code_188, Code_189, Code_190, Code_191, Code_192, Code_193, Code_194, Code_195, Code_196, Code_197, Code_198, Code_199, Code_200, Code_201, Code_202, Code_203, Code_204, Code_205, Code_206, Code_207, Code_208, Code_209, Code_210, Code_211, Code_212, Code_213, Code_214, Code_215, Code_216, Code_217, Code_218, Code_219, Code_220, Code_221, Code_222, Code_223, Code_224, Code_225, Code_226, Code_227, Code_228, Code_229, Code_230, Code_231, Code_232, Code_233, Code_234, Code_235, Code_236, Code_237, Code_238, Code_239, Code_240, Code_241, Code_242, Code_243, Code_244, Code_245, Code_246, Code_247, Code_248, Code_249, Code_250, Code_251, Code_252, Code_253, Refresh = 255, RemoveCode = 256, Count = 257, RawValue = 258, RawValueIndex = 259 }; _enumerated _value; ValueID_Index_UserCode(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 259; static const int* _values() { static const int values[] = { (ignore_assign)Enrollment_Code = 0, (ignore_assign)Code_1, (ignore_assign)Code_2, (ignore_assign)Code_3, (ignore_assign)Code_4, (ignore_assign)Code_5, (ignore_assign)Code_6, (ignore_assign)Code_7, (ignore_assign)Code_8, (ignore_assign)Code_9, (ignore_assign)Code_10, (ignore_assign)Code_11, (ignore_assign)Code_12, (ignore_assign)Code_13, (ignore_assign)Code_14, (ignore_assign)Code_15, (ignore_assign)Code_16, (ignore_assign)Code_17, (ignore_assign)Code_18, (ignore_assign)Code_19, (ignore_assign)Code_20, (ignore_assign)Code_21, (ignore_assign)Code_22, (ignore_assign)Code_23, (ignore_assign)Code_24, (ignore_assign)Code_25, (ignore_assign)Code_26, (ignore_assign)Code_27, (ignore_assign)Code_28, (ignore_assign)Code_29, (ignore_assign)Code_30, (ignore_assign)Code_31, (ignore_assign)Code_32, (ignore_assign)Code_33, (ignore_assign)Code_34, (ignore_assign)Code_35, (ignore_assign)Code_36, (ignore_assign)Code_37, (ignore_assign)Code_38, (ignore_assign)Code_39, (ignore_assign)Code_40, (ignore_assign)Code_41, (ignore_assign)Code_42, (ignore_assign)Code_43, (ignore_assign)Code_44, (ignore_assign)Code_45, (ignore_assign)Code_46, (ignore_assign)Code_47, (ignore_assign)Code_48, (ignore_assign)Code_49, (ignore_assign)Code_50, (ignore_assign)Code_51, (ignore_assign)Code_52, (ignore_assign)Code_53, (ignore_assign)Code_54, (ignore_assign)Code_55, (ignore_assign)Code_56, (ignore_assign)Code_57, (ignore_assign)Code_58, (ignore_assign)Code_59, (ignore_assign)Code_60, (ignore_assign)Code_61, (ignore_assign)Code_62, (ignore_assign)Code_63, (ignore_assign)Code_64, (ignore_assign)Code_65, (ignore_assign)Code_66, (ignore_assign)Code_67, (ignore_assign)Code_68, (ignore_assign)Code_69, (ignore_assign)Code_70, (ignore_assign)Code_71, (ignore_assign)Code_72, (ignore_assign)Code_73, (ignore_assign)Code_74, (ignore_assign)Code_75, (ignore_assign)Code_76, (ignore_assign)Code_77, (ignore_assign)Code_78, (ignore_assign)Code_79, (ignore_assign)Code_80, (ignore_assign)Code_81, (ignore_assign)Code_82, (ignore_assign)Code_83, (ignore_assign)Code_84, (ignore_assign)Code_85, (ignore_assign)Code_86, (ignore_assign)Code_87, (ignore_assign)Code_88, (ignore_assign)Code_89, (ignore_assign)Code_90, (ignore_assign)Code_91, (ignore_assign)Code_92, (ignore_assign)Code_93, (ignore_assign)Code_94, (ignore_assign)Code_95, (ignore_assign)Code_96, (ignore_assign)Code_97, (ignore_assign)Code_98, (ignore_assign)Code_99, (ignore_assign)Code_100, (ignore_assign)Code_101, (ignore_assign)Code_102, (ignore_assign)Code_103, (ignore_assign)Code_104, (ignore_assign)Code_105, (ignore_assign)Code_106, (ignore_assign)Code_107, (ignore_assign)Code_108, (ignore_assign)Code_109, (ignore_assign)Code_110, (ignore_assign)Code_111, (ignore_assign)Code_112, (ignore_assign)Code_113, (ignore_assign)Code_114, (ignore_assign)Code_115, (ignore_assign)Code_116, (ignore_assign)Code_117, (ignore_assign)Code_118, (ignore_assign)Code_119, (ignore_assign)Code_120, (ignore_assign)Code_121, (ignore_assign)Code_122, (ignore_assign)Code_123, (ignore_assign)Code_124, (ignore_assign)Code_125, (ignore_assign)Code_126, (ignore_assign)Code_127, (ignore_assign)Code_128, (ignore_assign)Code_129, (ignore_assign)Code_130, (ignore_assign)Code_131, (ignore_assign)Code_132, (ignore_assign)Code_133, (ignore_assign)Code_134, (ignore_assign)Code_135, (ignore_assign)Code_136, (ignore_assign)Code_137, (ignore_assign)Code_138, (ignore_assign)Code_139, (ignore_assign)Code_140, (ignore_assign)Code_141, (ignore_assign)Code_142, (ignore_assign)Code_143, (ignore_assign)Code_144, (ignore_assign)Code_145, (ignore_assign)Code_146, (ignore_assign)Code_147, (ignore_assign)Code_148, (ignore_assign)Code_149, (ignore_assign)Code_150, (ignore_assign)Code_151, (ignore_assign)Code_152, (ignore_assign)Code_153, (ignore_assign)Code_154, (ignore_assign)Code_155, (ignore_assign)Code_156, (ignore_assign)Code_157, (ignore_assign)Code_158, (ignore_assign)Code_159, (ignore_assign)Code_160, (ignore_assign)Code_161, (ignore_assign)Code_162, (ignore_assign)Code_163, (ignore_assign)Code_164, (ignore_assign)Code_165, (ignore_assign)Code_166, (ignore_assign)Code_167, (ignore_assign)Code_168, (ignore_assign)Code_169, (ignore_assign)Code_170, (ignore_assign)Code_171, (ignore_assign)Code_172, (ignore_assign)Code_173, (ignore_assign)Code_174, (ignore_assign)Code_175, (ignore_assign)Code_176, (ignore_assign)Code_177, (ignore_assign)Code_178, (ignore_assign)Code_179, (ignore_assign)Code_180, (ignore_assign)Code_181, (ignore_assign)Code_182, (ignore_assign)Code_183, (ignore_assign)Code_184, (ignore_assign)Code_185, (ignore_assign)Code_186, (ignore_assign)Code_187, (ignore_assign)Code_188, (ignore_assign)Code_189, (ignore_assign)Code_190, (ignore_assign)Code_191, (ignore_assign)Code_192, (ignore_assign)Code_193, (ignore_assign)Code_194, (ignore_assign)Code_195, (ignore_assign)Code_196, (ignore_assign)Code_197, (ignore_assign)Code_198, (ignore_assign)Code_199, (ignore_assign)Code_200, (ignore_assign)Code_201, (ignore_assign)Code_202, (ignore_assign)Code_203, (ignore_assign)Code_204, (ignore_assign)Code_205, (ignore_assign)Code_206, (ignore_assign)Code_207, (ignore_assign)Code_208, (ignore_assign)Code_209, (ignore_assign)Code_210, (ignore_assign)Code_211, (ignore_assign)Code_212, (ignore_assign)Code_213, (ignore_assign)Code_214, (ignore_assign)Code_215, (ignore_assign)Code_216, (ignore_assign)Code_217, (ignore_assign)Code_218, (ignore_assign)Code_219, (ignore_assign)Code_220, (ignore_assign)Code_221, (ignore_assign)Code_222, (ignore_assign)Code_223, (ignore_assign)Code_224, (ignore_assign)Code_225, (ignore_assign)Code_226, (ignore_assign)Code_227, (ignore_assign)Code_228, (ignore_assign)Code_229, (ignore_assign)Code_230, (ignore_assign)Code_231, (ignore_assign)Code_232, (ignore_assign)Code_233, (ignore_assign)Code_234, (ignore_assign)Code_235, (ignore_assign)Code_236, (ignore_assign)Code_237, (ignore_assign)Code_238, (ignore_assign)Code_239, (ignore_assign)Code_240, (ignore_assign)Code_241, (ignore_assign)Code_242, (ignore_assign)Code_243, (ignore_assign)Code_244, (ignore_assign)Code_245, (ignore_assign)Code_246, (ignore_assign)Code_247, (ignore_assign)Code_248, (ignore_assign)Code_249, (ignore_assign)Code_250, (ignore_assign)Code_251, (ignore_assign)Code_252, (ignore_assign)Code_253, (ignore_assign)Refresh = 255, (ignore_assign)RemoveCode = 256, (ignore_assign)Count = 257, (ignore_assign)RawValue = 258, (ignore_assign)RawValueIndex = 259, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Enrollment_Code = 0", "Code_1", "Code_2", "Code_3", "Code_4", "Code_5", "Code_6", "Code_7", "Code_8", "Code_9", "Code_10", "Code_11", "Code_12", "Code_13", "Code_14", "Code_15", "Code_16", "Code_17", "Code_18", "Code_19", "Code_20", "Code_21", "Code_22", "Code_23", "Code_24", "Code_25", "Code_26", "Code_27", "Code_28", "Code_29", "Code_30", "Code_31", "Code_32", "Code_33", "Code_34", "Code_35", "Code_36", "Code_37", "Code_38", "Code_39", "Code_40", "Code_41", "Code_42", "Code_43", "Code_44", "Code_45", "Code_46", "Code_47", "Code_48", "Code_49", "Code_50", "Code_51", "Code_52", "Code_53", "Code_54", "Code_55", "Code_56", "Code_57", "Code_58", "Code_59", "Code_60", "Code_61", "Code_62", "Code_63", "Code_64", "Code_65", "Code_66", "Code_67", "Code_68", "Code_69", "Code_70", "Code_71", "Code_72", "Code_73", "Code_74", "Code_75", "Code_76", "Code_77", "Code_78", "Code_79", "Code_80", "Code_81", "Code_82", "Code_83", "Code_84", "Code_85", "Code_86", "Code_87", "Code_88", "Code_89", "Code_90", "Code_91", "Code_92", "Code_93", "Code_94", "Code_95", "Code_96", "Code_97", "Code_98", "Code_99", "Code_100", "Code_101", "Code_102", "Code_103", "Code_104", "Code_105", "Code_106", "Code_107", "Code_108", "Code_109", "Code_110", "Code_111", "Code_112", "Code_113", "Code_114", "Code_115", "Code_116", "Code_117", "Code_118", "Code_119", "Code_120", "Code_121", "Code_122", "Code_123", "Code_124", "Code_125", "Code_126", "Code_127", "Code_128", "Code_129", "Code_130", "Code_131", "Code_132", "Code_133", "Code_134", "Code_135", "Code_136", "Code_137", "Code_138", "Code_139", "Code_140", "Code_141", "Code_142", "Code_143", "Code_144", "Code_145", "Code_146", "Code_147", "Code_148", "Code_149", "Code_150", "Code_151", "Code_152", "Code_153", "Code_154", "Code_155", "Code_156", "Code_157", "Code_158", "Code_159", "Code_160", "Code_161", "Code_162", "Code_163", "Code_164", "Code_165", "Code_166", "Code_167", "Code_168", "Code_169", "Code_170", "Code_171", "Code_172", "Code_173", "Code_174", "Code_175", "Code_176", "Code_177", "Code_178", "Code_179", "Code_180", "Code_181", "Code_182", "Code_183", "Code_184", "Code_185", "Code_186", "Code_187", "Code_188", "Code_189", "Code_190", "Code_191", "Code_192", "Code_193", "Code_194", "Code_195", "Code_196", "Code_197", "Code_198", "Code_199", "Code_200", "Code_201", "Code_202", "Code_203", "Code_204", "Code_205", "Code_206", "Code_207", "Code_208", "Code_209", "Code_210", "Code_211", "Code_212", "Code_213", "Code_214", "Code_215", "Code_216", "Code_217", "Code_218", "Code_219", "Code_220", "Code_221", "Code_222", "Code_223", "Code_224", "Code_225", "Code_226", "Code_227", "Code_228", "Code_229", "Code_230", "Code_231", "Code_232", "Code_233", "Code_234", "Code_235", "Code_236", "Code_237", "Code_238", "Code_239", "Code_240", "Code_241", "Code_242", "Code_243", "Code_244", "Code_245", "Code_246", "Code_247", "Code_248", "Code_249", "Code_250", "Code_251", "Code_252", "Code_253", "Refresh = 255", "RemoveCode = 256", "Count = 257", "RawValue = 258", "RawValueIndex = 259", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; +struct ValueID_Index_Version { enum _enumerated { Library = 0, Protocol = 1, Application = 2 }; _enumerated _value; ValueID_Index_Version(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 3; static const int* _values() { static const int values[] = { (ignore_assign)Library = 0, (ignore_assign)Protocol = 1, (ignore_assign)Application = 2, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Library = 0", "Protocol = 1", "Application = 2", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + + + +struct ValueID_Index_WakeUp { enum _enumerated { Interval = 0, Min_Interval = 1, Max_Interval = 2, Default_Interval = 3, Interval_Step = 4 }; _enumerated _value; ValueID_Index_WakeUp(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 5; static const int* _values() { static const int values[] = { (ignore_assign)Interval = 0, (ignore_assign)Min_Interval = 1, (ignore_assign)Max_Interval = 2, (ignore_assign)Default_Interval = 3, (ignore_assign)Interval_Step = 4, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Interval = 0", "Min_Interval = 1", "Max_Interval = 2", "Default_Interval = 3", "Interval_Step = 4", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; + + + + + + +struct ValueID_Index_ZWavePlusInfo { enum _enumerated { Version = 0, InstallerIcon = 1, UserIcon = 2 }; _enumerated _value; ValueID_Index_ZWavePlusInfo(_enumerated value) : _value(value) { } operator _enumerated() const { return _value; } const char* _to_string() const { for (size_t index = 0; index < _count; ++index) { if (_values()[index] == _value) return _names()[index]; } return NULL; } static const size_t _count = 3; static const int* _values() { static const int values[] = { (ignore_assign)Version = 0, (ignore_assign)InstallerIcon = 1, (ignore_assign)UserIcon = 2, }; return values; } static const char* const* _names() { static const char* const raw_names[] = { "Version = 0", "InstallerIcon = 1", "UserIcon = 2", }; static char* processed_names[_count]; static bool initialized = false; if (!initialized) { for (size_t index = 0; index < _count; ++index) { size_t length = std::strcspn(raw_names[index], " =\t\n\r"); processed_names[index] = new char[length + 1]; strncpy( processed_names[index], raw_names[index], length); processed_names[index][length] = '\0'; } } return processed_names; } };; diff --git a/cpp/src/ZWSecurity.cpp b/cpp/src/ZWSecurity.cpp index 8180b95b67..8591cb61d3 100644 --- a/cpp/src/ZWSecurity.cpp +++ b/cpp/src/ZWSecurity.cpp @@ -37,348 +37,358 @@ #include "command_classes/Security.h" #include "aes/aescpp.h" -namespace OpenZWave { - //using namespace OpenZWave; - - //----------------------------------------------------------------------------- - // - // Generate authentication data from a security-encrypted message - //----------------------------------------------------------------------------- - bool GenerateAuthentication - ( - uint8 const* _data, // Starting from the command class command - uint32 const _length, - Driver *driver, - uint8 const _sendingNode, - uint8 const _receivingNode, - uint8 *iv, - uint8* _authentication // 8-byte buffer that will be filled with the authentication data - ) +namespace OpenZWave +{ + namespace Internal { - // Build a buffer containing a 4-byte header and the encrypted - // message data, padded with zeros to a 16-byte boundary. - uint8 buffer[256]; - uint8 tmpauth[16]; - memset(buffer, 0, 256); - memset(tmpauth, 0, 16); - buffer[0] = _data[0]; // Security command class command - buffer[1] = _sendingNode; - buffer[2] = _receivingNode; - buffer[3] = _length - 19; // Subtract 19 to account for the 9 security command class bytes that come before and after the encrypted data - memcpy( &buffer[4], &_data[9], _length-19 ); // Encrypted message - uint8 bufsize = _length - 19 + 4; /* the size of buffer */ + //----------------------------------------------------------------------------- + // + // Generate authentication data from a security-encrypted message + //----------------------------------------------------------------------------- + bool GenerateAuthentication(uint8 const* _data, // Starting from the command class command + uint32 const _length, Driver *driver, uint8 const _sendingNode, uint8 const _receivingNode, uint8 *iv, + uint8* _authentication // 8-byte buffer that will be filled with the authentication data + ) + { + // Build a buffer containing a 4-byte header and the encrypted + // message data, padded with zeros to a 16-byte boundary. + uint8 buffer[256]; + uint8 tmpauth[16]; + memset(buffer, 0, 256); + memset(tmpauth, 0, 16); + buffer[0] = _data[0]; // Security command class command + buffer[1] = _sendingNode; + buffer[2] = _receivingNode; + buffer[3] = _length - 19; // Subtract 19 to account for the 9 security command class bytes that come before and after the encrypted data + memcpy(&buffer[4], &_data[9], _length - 19); // Encrypted message + + uint8 bufsize = _length - 19 + 4; /* the size of buffer */ #ifdef DEBUG - PrintHex("Raw Auth (minus IV)", buffer, bufsize); - Log::Write(LogLevel_Debug, _receivingNode, "Raw Auth (Minus IV) Size: %d (%d)", bufsize, bufsize+16); + Internal::PrintHex("Raw Auth (minus IV)", buffer, bufsize); + Log::Write(LogLevel_Debug, _receivingNode, "Raw Auth (Minus IV) Size: %d (%d)", bufsize, bufsize+16); #endif - aes_mode_reset(driver->GetAuthKey()); - /* encrypt the IV with ecb */ - if (aes_ecb_encrypt(iv, tmpauth, 16, driver->GetAuthKey()) == EXIT_FAILURE) { - Log::Write(LogLevel_Warning, _receivingNode, "Failed Initial ECB Encrypt of Auth Packet"); - return false; - } + aes_mode_reset(driver->GetAuthKey()); + /* encrypt the IV with ecb */ + if (aes_ecb_encrypt(iv, tmpauth, 16, driver->GetAuthKey()) == EXIT_FAILURE) + { + Log::Write(LogLevel_Warning, _receivingNode, "Failed Initial ECB Encrypt of Auth Packet"); + return false; + } - /* our temporary holding var */ - uint8 encpck[16]; + /* our temporary holding var */ + uint8 encpck[16]; - int block = 0; - /* reset our encpck temp var */ - memset(encpck, 0, 16); - /* now xor the buffer with our encrypted IV */ - for (int i = 0; i < bufsize; i++) { - encpck[block] = buffer[i]; - block++; - /* if we hit a blocksize, then encrypt */ - if (block == 16) { - for (int j = 0; j < 16; j++) { - /* here we do our xor */ - tmpauth[j] = encpck[j] ^ tmpauth[j]; - /* and reset encpck for good measure */ - encpck[j] = 0; + int block = 0; + /* reset our encpck temp var */ + memset(encpck, 0, 16); + /* now xor the buffer with our encrypted IV */ + for (int i = 0; i < bufsize; i++) + { + encpck[block] = buffer[i]; + block++; + /* if we hit a blocksize, then encrypt */ + if (block == 16) + { + for (int j = 0; j < 16; j++) + { + /* here we do our xor */ + tmpauth[j] = encpck[j] ^ tmpauth[j]; + /* and reset encpck for good measure */ + encpck[j] = 0; + } + /* reset our block counter back to 0 */ + block = 0; + aes_mode_reset(driver->GetAuthKey()); + if (aes_ecb_encrypt(tmpauth, tmpauth, 16, driver->GetAuthKey()) == EXIT_FAILURE) + { + Log::Write(LogLevel_Warning, _receivingNode, "Failed Subsequent (%d) ECB Encrypt of Auth Packet", i); + return false; + } + } + } + /* any left over data that isn't a full block size*/ + if (block > 0) + { + for (int i = 0; i < 16; i++) + { + /* encpck from block to 16 is already guaranteed to be 0 + * so its safe to xor it with out tmpmac */ + tmpauth[i] = encpck[i] ^ tmpauth[i]; } - /* reset our block counter back to 0 */ - block = 0; aes_mode_reset(driver->GetAuthKey()); - if (aes_ecb_encrypt(tmpauth, tmpauth, 16, driver->GetAuthKey()) == EXIT_FAILURE) { - Log::Write(LogLevel_Warning, _receivingNode, "Failed Subsequent (%d) ECB Encrypt of Auth Packet", i); + if (aes_ecb_encrypt(tmpauth, tmpauth, 16, driver->GetAuthKey()) == EXIT_FAILURE) + { + Log::Write(LogLevel_Warning, _receivingNode, "Failed Final ECB Encrypt of Auth Packet"); return false; } } - } - /* any left over data that isn't a full block size*/ - if (block > 0) { - for (int i= 0; i < 16; i++) { - /* encpck from block to 16 is already gauranteed to be 0 - * so its safe to xor it with out tmpmac */ - tmpauth[i] = encpck[i] ^ tmpauth[i]; - } - aes_mode_reset(driver->GetAuthKey()); - if (aes_ecb_encrypt(tmpauth, tmpauth, 16, driver->GetAuthKey()) == EXIT_FAILURE) { - Log::Write(LogLevel_Warning, _receivingNode, "Failed Final ECB Encrypt of Auth Packet"); - return false; - } - } - /* we only care about the first 8 bytes of tmpauth as the mac */ + /* we only care about the first 8 bytes of tmpauth as the mac */ #ifdef DEBUG - PrintHex("Computed Auth", tmpauth, 8); + Internal::PrintHex("Computed Auth", tmpauth, 8); #endif - /* so only copy 8 bytes to the _authentication var */ - memcpy(_authentication, tmpauth, 8); - return true; - } + /* so only copy 8 bytes to the _authentication var */ + memcpy(_authentication, tmpauth, 8); + return true; + } - bool EncyrptBuffer( - uint8 *m_buffer, - uint8 m_length, - Driver *driver, - uint8 const _sendingNode, - uint8 const _receivingNode, - uint8 const m_nonce[8], - uint8* e_buffer - ) - { + bool EncryptBuffer(uint8 *m_buffer, uint8 m_length, Driver *driver, uint8 const _sendingNode, uint8 const _receivingNode, uint8 const m_nonce[8], uint8* e_buffer) + { #if 0 - m_nonce[0] = 0x09; - m_nonce[1] = 0x0d; - m_nonce[2] = 0x93; - m_nonce[3] = 0xd3; - m_nonce[4] = 0x61; - m_nonce[5] = 0x61; - m_nonce[6] = 0x1d; - m_nonce[7] = 0xd6; + m_nonce[0] = 0x09; + m_nonce[1] = 0x0d; + m_nonce[2] = 0x93; + m_nonce[3] = 0xd3; + m_nonce[4] = 0x61; + m_nonce[5] = 0x61; + m_nonce[6] = 0x1d; + m_nonce[7] = 0xd6; #endif - uint8 len = 0; - e_buffer[len++] = SOF; - e_buffer[len++] = m_length + 18; // length of full packet - e_buffer[len++] = REQUEST; - e_buffer[len++] = FUNC_ID_ZW_SEND_DATA; - e_buffer[len++] = _receivingNode; - e_buffer[len++] = m_length + 11; // Length of the payload - e_buffer[len++] = Security::StaticGetCommandClassId(); - e_buffer[len++] = SecurityCmd_MessageEncap; - - /* create our IV */ - uint8 initializationVector[16]; - /* the first 8 bytes of a outgoing IV are random - * and we add it also to the start of the payload - */ - for (int i = 0; i < 8; i++) { - initializationVector[i] = (uint8) (255.0 * rand() / (RAND_MAX + 1.0)); - e_buffer[len++] = initializationVector[i]; - } - /* the remaining 8 bytes are the NONCE we got from the device */ - for (int i = 0; i < 8; i++) { - initializationVector[8+i] = m_nonce[i]; - } - - /* we need a copy b/c aes_ofb_encrypt will overwrite it */ - uint8 iv_dup[16]; - for (int i = 0; i < 16; i++) { - iv_dup[i] = initializationVector[i]; - } + uint8 len = 0; + e_buffer[len++] = SOF; + e_buffer[len++] = m_length + 18; // length of full packet + e_buffer[len++] = REQUEST; + e_buffer[len++] = FUNC_ID_ZW_SEND_DATA; + e_buffer[len++] = _receivingNode; + e_buffer[len++] = m_length + 11; // Length of the payload + e_buffer[len++] = Internal::CC::Security::StaticGetCommandClassId(); + e_buffer[len++] = Internal::CC::SecurityCmd_MessageEncap; + + /* create our IV */ + uint8 initializationVector[16]; + /* the first 8 bytes of a outgoing IV are random + * and we add it also to the start of the payload + */ + for (int i = 0; i < 8; i++) + { + initializationVector[i] = (uint8) (255.0 * rand() / (RAND_MAX + 1.0)); + e_buffer[len++] = initializationVector[i]; + } + /* the remaining 8 bytes are the NONCE we got from the device */ + for (int i = 0; i < 8; i++) + { + initializationVector[8 + i] = m_nonce[i]; + } - uint8 plaintextmsg[32]; - /* add the Sequence Flag - * - Since we dont currently handle multipacket encryption - * just set this to 0 - */ - plaintextmsg[0] = 0; - /* now add the actual message to be encrypted */ - for (int i = 0; i < m_length-6-3; i++) - plaintextmsg[i+1] = m_buffer[6+i]; + /* we need a copy b/c aes_ofb_encrypt will overwrite it */ + uint8 iv_dup[16]; + for (int i = 0; i < 16; i++) + { + iv_dup[i] = initializationVector[i]; + } - /* now encrypt */ - uint8 encryptedpayload[30]; - aes_mode_reset(driver->GetEncKey()); + uint8 plaintextmsg[32]; + /* add the Sequence Flag + * - Since we don't currently handle multipacket encryption + * just set this to 0 + */ + plaintextmsg[0] = 0; + /* now add the actual message to be encrypted */ + for (int i = 0; i < m_length - 6 - 3; i++) + plaintextmsg[i + 1] = m_buffer[6 + i]; + + /* now encrypt */ + uint8 encryptedpayload[30]; + aes_mode_reset(driver->GetEncKey()); #ifdef DEBUG - PrintHex("Plain Text Packet:", plaintextmsg, m_length-5-3); + Internal::PrintHex("Plain Text Packet:", plaintextmsg, m_length-5-3); #endif - if (aes_ofb_encrypt(plaintextmsg, encryptedpayload, m_length-5-3, initializationVector, driver->GetEncKey()) == EXIT_FAILURE) { - Log::Write(LogLevel_Warning, _receivingNode, "Failed to Encrypt Packet"); - return false; - } + if (aes_ofb_encrypt(plaintextmsg, encryptedpayload, m_length - 5 - 3, initializationVector, driver->GetEncKey()) == EXIT_FAILURE) + { + Log::Write(LogLevel_Warning, _receivingNode, "Failed to Encrypt Packet"); + return false; + } #ifdef DEBUG - PrintHex("Encrypted Packet", encryptedpayload, m_length-5-3); + Internal::PrintHex("Encrypted Packet", encryptedpayload, m_length-5-3); #endif - /* now add the Encrypted output to the packet */ - for (int i = 0; i < m_length-5-3; i++) { - e_buffer[len++] = encryptedpayload[i]; - } - - // Append the nonce identifier :) - e_buffer[len++] = m_nonce[0]; + /* now add the Encrypted output to the packet */ + for (int i = 0; i < m_length - 5 - 3; i++) + { + e_buffer[len++] = encryptedpayload[i]; + } + // Append the nonce identifier :) + e_buffer[len++] = m_nonce[0]; - /* now calculate the MAC and append it */ - uint8 mac[8]; - GenerateAuthentication(&e_buffer[7], e_buffer[5], driver, _sendingNode, _receivingNode, iv_dup, mac); - for(int i=0; i<8; ++i ) - { - e_buffer[len++] = mac[i]; - } + /* now calculate the MAC and append it */ + uint8 mac[8]; + GenerateAuthentication(&e_buffer[7], e_buffer[5], driver, _sendingNode, _receivingNode, iv_dup, mac); + for (int i = 0; i < 8; ++i) + { + e_buffer[len++] = mac[i]; + } - e_buffer[len++] = driver->GetTransmitOptions(); - /* this is the same as the Actual Message */ - e_buffer[len++] = m_buffer[m_length-2]; - // Calculate the checksum - uint8 csum = 0xff; - for( int32 i=1; iGetTransmitOptions(); + /* this is the same as the Actual Message */ + e_buffer[len++] = m_buffer[m_length - 2]; + // Calculate the checksum + uint8 csum = 0xff; + for (int32 i = 1; i < len; ++i) + { + csum ^= e_buffer[i]; + } + e_buffer[len++] = csum; #ifdef DEBUG - PrintHex("Encrypted Packet", e_buffer, len); - Log::Write(LogLevel_Info, "Length: %d", len); + Internal::PrintHex("Encrypted Packet", e_buffer, len); + Log::Write(LogLevel_Info, "Length: %d", len); #endif - return true; - } - - bool createIVFromPacket_inbound(uint8 const* _data, uint8 const m_nonce[8], uint8 *iv) { - - for (int i = 0; i < 8; i++) { - iv[i] = _data[i]; + return true; } - for (int i = 0; i < 8; i++) { - iv[8+i] = m_nonce[i]; - } - return true; - } - - /* To Decrypt, we start the packet at the IV (right after the command) - * - * Encrypted Packet Size is Packet Lenght - Device Nonce(8) - Reciever Nonce ID (1) - Mac (8) - CommandClass - Command - * - * Reciever Nonce is at Position 14 + Encrypted Packet Size - * Mac is at Position 15 + Encrypted Packet Size - * 0 - Command Class - * 1 - Command - * 2 to 9 - Device Nonce - * 10 - Sequence (e) - * 11 - Command Class (e) - * 12 - Command (e) - * 13 to EncryptedPckSize - * ReciverNonceID (1 Byte) - * Mac (8 Bytes) - */ - - - bool DecryptBuffer - ( - uint8 *e_buffer, - uint8 e_length, - Driver *driver, - uint8 const _sendingNode, - uint8 const _receivingNode, - uint8 const m_nonce[8], - uint8* m_buffer - ) - { - PrintHex("Raw", e_buffer, e_length); + bool createIVFromPacket_inbound(uint8 const* _data, uint8 const m_nonce[8], uint8 *iv) + { - if (e_length < 19) { - Log::Write(LogLevel_Warning, _sendingNode, "Received a Encrypted Message that is too Short. Dropping it"); - return false; + for (int i = 0; i < 8; i++) + { + iv[i] = _data[i]; + } + for (int i = 0; i < 8; i++) + { + iv[8 + i] = m_nonce[i]; + } + return true; } - - uint8 iv[17]; - createIVFromPacket_inbound(&e_buffer[2], m_nonce, iv); /* first 8 bytes of Packet are the Random Value generated by the Device - * 2nd 8 bytes of the IV are our nonce we sent previously + /* To Decrypt, we start the packet at the IV (right after the command) + * + * Encrypted Packet Size is Packet Length - Device Nonce(8) - Receiver Nonce ID (1) - Mac (8) - CommandClass - Command + * + * Receiver Nonce is at Position 14 + Encrypted Packet Size + * Mac is at Position 15 + Encrypted Packet Size + * 0 - Command Class + * 1 - Command + * 2 to 9 - Device Nonce + * 10 - Sequence (e) + * 11 - Command Class (e) + * 12 - Command (e) + * 13 to EncryptedPckSize + * ReceiverNonceID (1 Byte) + * Mac (8 Bytes) */ - memset(&m_buffer[0], 0, 32); - uint32 encryptedpacketsize = e_length - 8 - 8 - 2 - 2; - /* if the Encrypted Packet Size is less than 3, there is probably a issue, drop it. */ - if (encryptedpacketsize < 3) { - Log::Write(LogLevel_Warning, _sendingNode, "Encrypted Packet Size is Less than 3 Bytes. Dropping"); - return false; - } + bool DecryptBuffer(uint8 *e_buffer, uint8 e_length, Driver *driver, uint8 const _sendingNode, uint8 const _receivingNode, uint8 const m_nonce[8], uint8* m_buffer) + { + Internal::PrintHex("Raw", e_buffer, e_length); + if (e_length < 19) + { + Log::Write(LogLevel_Warning, _sendingNode, "Received a Encrypted Message that is too Short. Dropping it"); + return false; + } - uint8 encyptedpacket[32]; + uint8 iv[17]; + createIVFromPacket_inbound(&e_buffer[2], m_nonce, iv); /* first 8 bytes of Packet are the Random Value generated by the Device + * 2nd 8 bytes of the IV are our nonce we sent previously + */ + memset(&m_buffer[0], 0, 32); + uint32 encryptedpacketsize = e_length - 8 - 8 - 2 - 2; - for (uint32 i = 0; i < 32; i++) { - if (i >= encryptedpacketsize) { - /* pad the remaining fields */ - encyptedpacket[i] = 0; - } else { - encyptedpacket[i] = e_buffer[10+i]; + /* if the Encrypted Packet Size is less than 3, there is probably a issue, drop it. */ + if (encryptedpacketsize < 3) + { + Log::Write(LogLevel_Warning, _sendingNode, "Encrypted Packet Size is Less than 3 Bytes. Dropping"); + return false; } - } + uint8 encyptedpacket[32]; + + for (uint32 i = 0; i < 32; i++) + { + if (i >= encryptedpacketsize) + { + /* pad the remaining fields */ + encyptedpacket[i] = 0; + } + else + { + encyptedpacket[i] = e_buffer[10 + i]; + } + } #ifdef DEBUG - Log::Write(LogLevel_Debug, _sendingNode, "Encrypted Packet Sizes: %d (Total) %d (Payload)", e_length, encryptedpacketsize); - PrintHex("IV", iv, 16); - PrintHex("Encrypted", encyptedpacket, 16); - /* Mac Starts after Encrypted Packet. */ - PrintHex("Auth", &e_buffer[11+encryptedpacketsize], 8); + Log::Write(LogLevel_Debug, _sendingNode, "Encrypted Packet Sizes: %u (Total) %u (Payload)", e_length, encryptedpacketsize); + Internal::PrintHex("IV", iv, 16); + Internal::PrintHex("Encrypted", encyptedpacket, 32); + /* Mac Starts after Encrypted Packet. */ + Internal::PrintHex("Auth", &e_buffer[11+encryptedpacketsize], 8); #endif - aes_mode_reset(driver->GetEncKey()); + aes_mode_reset(driver->GetEncKey()); #if 0 - uint8_t iv[16] = { 0x81, 0x42, 0xd1, 0x51, 0xf1, 0x59, 0x3d, 0x70, 0xd5, 0xe3, 0x6c, 0xcb, 0x02, 0xd0, 0x3f, 0x5c, /* */ }; - uint8_t pck[] = { 0x25, 0x68, 0x06, 0xc5, 0xb3, 0xee, 0x2c, 0x17, 0x26, 0x7e, 0xf0, 0x84, 0xd4, 0xc3, 0xba, 0xed, 0xe5, 0xb9, 0x55}; - if (aes_ofb_decrypt(pck, decryptpacket, 19, iv, this->EncryptKey) == EXIT_FAILURE) { - Log::Write(LogLevel_Warning, GetNodeId(), "Failed to Decrypt Packet"); - return false; - } - PrintHex("Pck", decryptpacket, 19); + uint8_t iv[16] = + { 0x81, 0x42, 0xd1, 0x51, 0xf1, 0x59, 0x3d, 0x70, 0xd5, 0xe3, 0x6c, 0xcb, 0x02, 0xd0, 0x3f, 0x5c, /* */}; + uint8_t pck[] = + { 0x25, 0x68, 0x06, 0xc5, 0xb3, 0xee, 0x2c, 0x17, 0x26, 0x7e, 0xf0, 0x84, 0xd4, 0xc3, 0xba, 0xed, 0xe5, 0xb9, 0x55}; + if (aes_ofb_decrypt(pck, decryptpacket, 19, iv, this->EncryptKey) == EXIT_FAILURE) + { + Log::Write(LogLevel_Warning, GetNodeId(), "Failed to Decrypt Packet"); + return false; + } + Internal::PrintHex("Pck", decryptpacket, 19); #else - if (aes_ofb_decrypt(encyptedpacket, m_buffer, encryptedpacketsize, iv, driver->GetEncKey()) == EXIT_FAILURE) { - Log::Write(LogLevel_Warning, _sendingNode, "Failed to Decrypt Packet"); - return false; - } - Log::Write(LogLevel_Detail, _sendingNode, "Decrypted Packet: %s", PktToString(m_buffer, encryptedpacketsize).c_str()); + if (aes_ofb_decrypt(encyptedpacket, m_buffer, encryptedpacketsize, iv, driver->GetEncKey()) == EXIT_FAILURE) + { + Log::Write(LogLevel_Warning, _sendingNode, "Failed to Decrypt Packet"); + return false; + } + Log::Write(LogLevel_Detail, _sendingNode, "Decrypted Packet: %s", Internal::PktToString(m_buffer, encryptedpacketsize).c_str()); #endif - uint8 mac[32]; - /* we have to regenerate the IV as the ofb decryption routine will alter it. */ - createIVFromPacket_inbound(&e_buffer[2], m_nonce, iv); + uint8 mac[32]; + /* we have to regenerate the IV as the ofb decryption routine will alter it. */ + createIVFromPacket_inbound(&e_buffer[2], m_nonce, iv); - GenerateAuthentication(&e_buffer[1], e_length-1, driver, _sendingNode, _receivingNode, iv, mac); - if (memcmp(&e_buffer[11+encryptedpacketsize], mac, 8) != 0) { - Log::Write(LogLevel_Warning, _sendingNode, "MAC Authentication of Packet Failed. Dropping"); - return false; + GenerateAuthentication(&e_buffer[1], e_length - 1, driver, _sendingNode, _receivingNode, iv, mac); + if (memcmp(&e_buffer[11 + encryptedpacketsize], mac, 8) != 0) + { + Log::Write(LogLevel_Warning, _sendingNode, "MAC Authentication of Packet Failed. Dropping"); + return false; + } + /* XXX TODO: Check the Sequence Header Frame to see if this is the first part of a + * message, or 2nd part, or a entire message. + * + * I haven't actually seen a Z-Wave Message thats too big to fit in a encrypted message + * yet, so we will look at this if such a message actually exists! + * + * 2019-08 such a message was found, PST02 produces long multi cmd, see + * https://github.com/OpenZWave/open-zwave/issues/1899 + */ + + return true; } - /* XXX TODO: Check the Sequence Header Frame to see if this is the first part of a - * message, or 2nd part, or a entire message. - * - * I havn't actually seen a Z-Wave Message thats too big to fit in a encrypted message - * yet, so we will look at this if such a message actually exists! - */ - - return true; - } - SecurityStrategy ShouldSecureCommandClass(uint8 CommandClass) { - string securestrategy; - Options::Get()->GetOptionAsString( "SecurityStrategy", &securestrategy ); - - if (ToUpper(securestrategy) == "ESSENTIAL") { - return SecurityStrategy_Essential; - } else if (ToUpper(securestrategy) == "SUPPORTED") { - return SecurityStrategy_Supported; - } else if (ToUpper(securestrategy) == "CUSTOM") { - string customsecurecc; - Options::Get()->GetOptionAsString( "CustomSecuredCC", &customsecurecc); + SecurityStrategy ShouldSecureCommandClass(uint8 CommandClass) + { + string securestrategy; + Options::Get()->GetOptionAsString("SecurityStrategy", &securestrategy); - char* pos = const_cast(customsecurecc.c_str()); - while( *pos ) + if (Internal::ToUpper(securestrategy) == "ESSENTIAL") { - if (CommandClass == (uint8)strtol( pos, &pos, 16 )) { - return SecurityStrategy_Supported; - } - if( (*pos) == ',' ) + return SecurityStrategy_Essential; + } + else if (Internal::ToUpper(securestrategy) == "SUPPORTED") + { + return SecurityStrategy_Supported; + } + else if (Internal::ToUpper(securestrategy) == "CUSTOM") + { + string customsecurecc; + Options::Get()->GetOptionAsString("CustomSecuredCC", &customsecurecc); + + char* pos = const_cast(customsecurecc.c_str()); + while (*pos) { - ++pos; + if (CommandClass == (uint8) strtol(pos, &pos, 16)) + { + return SecurityStrategy_Supported; + } + if ((*pos) == ',') + { + ++pos; + } } } + return SecurityStrategy_Essential; } - return SecurityStrategy_Essential; - } - -} + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/ZWSecurity.h b/cpp/src/ZWSecurity.h index 77f70a49e2..ca86dc362b 100644 --- a/cpp/src/ZWSecurity.h +++ b/cpp/src/ZWSecurity.h @@ -28,7 +28,6 @@ #ifndef SECURITY_H_ #define SECURITY_H_ - #include #include #include @@ -37,17 +36,19 @@ namespace OpenZWave { -bool EncyrptBuffer( uint8 *m_buffer, uint8 m_length, Driver *driver, uint8 const _sendingNode, uint8 const _receivingNode, uint8 const m_nonce[8], uint8* e_buffer); -bool DecryptBuffer( uint8 *e_buffer, uint8 e_length, Driver *driver, uint8 const _sendingNode, uint8 const _receivingNode, uint8 const m_nonce[8], uint8* m_buffer ); -bool GenerateAuthentication( uint8 const* _data, uint32 const _length, Driver *driver, uint8 const _sendingNode, uint8 const _receivingNode, uint8 *iv, uint8* _authentication); -enum SecurityStrategy -{ - SecurityStrategy_Essential = 0, - SecurityStrategy_Supported -}; -SecurityStrategy ShouldSecureCommandClass(uint8 CommandClass); - -} + namespace Internal + { + bool EncryptBuffer(uint8 *m_buffer, uint8 m_length, Driver *driver, uint8 const _sendingNode, uint8 const _receivingNode, uint8 const m_nonce[8], uint8* e_buffer); + bool DecryptBuffer(uint8 *e_buffer, uint8 e_length, Driver *driver, uint8 const _sendingNode, uint8 const _receivingNode, uint8 const m_nonce[8], uint8* m_buffer); + bool GenerateAuthentication(uint8 const* _data, uint32 const _length, Driver *driver, uint8 const _sendingNode, uint8 const _receivingNode, uint8 *iv, uint8* _authentication); + enum SecurityStrategy + { + SecurityStrategy_Essential = 0, + SecurityStrategy_Supported + }; + SecurityStrategy ShouldSecureCommandClass(uint8 CommandClass); + } // namespace Internal +} // namespace OpenZWave #endif /* SECURITY_H_ */ diff --git a/cpp/src/command_classes/Alarm.cpp b/cpp/src/command_classes/Alarm.cpp index 85e23e5c4c..cee454edac 100644 --- a/cpp/src/command_classes/Alarm.cpp +++ b/cpp/src/command_classes/Alarm.cpp @@ -29,8 +29,6 @@ // But we cannot rename the class names as we already have a Notification Class used // for signaling events to the application. - - #include "command_classes/CommandClasses.h" #include "command_classes/Alarm.h" #include "command_classes/NodeNaming.h" @@ -47,612 +45,669 @@ #include "value_classes/ValueList.h" #include "value_classes/ValueString.h" #include "value_classes/ValueInt.h" -using namespace OpenZWave; - -enum AlarmCmd -{ - AlarmCmd_Get = 0x04, - AlarmCmd_Report = 0x05, - AlarmCmd_Set = 0x06, - // Version 2 - AlarmCmd_SupportedGet = 0x07, - AlarmCmd_SupportedReport = 0x08, - // Version 3 - AlarmCmd_Event_Supported_Get = 0x01, - AlarmCmd_Event_Supported_Report = 0x02 -}; -enum +namespace OpenZWave { - AlarmIndex_Type_Start = 0, - AlarmIndex_Type_End = 255, - AlarmIndex_Type_ParamStart = 256, - AlarmIndex_Type_ParamEnd = 511, - AlarmIndex_Type = 512, - AlarmIndex_Level, - AlarmIndex_AutoClearEvents -}; - - + namespace Internal + { + namespace CC + { + enum AlarmCmd + { + AlarmCmd_Get = 0x04, + AlarmCmd_Report = 0x05, + AlarmCmd_Set = 0x06, + // Version 2 + AlarmCmd_SupportedGet = 0x07, + AlarmCmd_SupportedReport = 0x08, + // Version 3 + AlarmCmd_Event_Supported_Get = 0x01, + AlarmCmd_Event_Supported_Report = 0x02 + }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -Alarm::Alarm -( - uint32 const _homeId, - uint8 const _nodeId -): -CommandClass( _homeId, _nodeId ), -m_v1Params(false), -m_ClearTimeout ( 5000 ) -{ - Timer::SetDriver(GetDriver()); - SetStaticRequest( StaticRequest_Values ); -} - + Alarm::Alarm(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId), m_v1Params(false), m_ClearTimeout(5000) + { + Timer::SetDriver(GetDriver()); + m_com.EnableFlag(COMPAT_FLAG_NOT_ENABLECLEAR, true); + m_com.EnableFlag(COMPAT_FLAG_NOT_V1ALARMTYPES_ENABLED, false); + SetStaticRequest(StaticRequest_Values); + } //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool Alarm::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) ) - { - if( GetVersion() > 1 ) - { - // Request the supported alarm types - Msg* msg = new Msg( "AlarmCmd_SupportedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( AlarmCmd_SupportedGet ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - } - else - { - /* create version 1 ValueID's */ - if( Node* node = GetNodeUnsafe() ) + bool Alarm::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) { - m_v1Params = true; - node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, AlarmIndex_Type, "Alarm Type", "", true, false, 0, 0 ); - node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, AlarmIndex_Level, "Alarm Level", "", true, false, 0, 0 ); - } - } - if (GetVersion() < 4) { - if ( Node* node = GetNodeUnsafe() ) { - node->CreateValueInt( ValueID::ValueGenre_Config, GetCommandClassId(), _instance, AlarmIndex_AutoClearEvents, "Automatically Clear Events", "ms", false, false, m_ClearTimeout, 0); - } - } + if ((_requestFlags & RequestFlag_Static) && HasStaticRequest(StaticRequest_Values)) + { + if (GetVersion() > 1) + { + // Request the supported alarm types + Msg* msg = new Msg("AlarmCmd_SupportedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(AlarmCmd_SupportedGet); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + } + if (GetVersion() == 1 || m_com.GetFlagBool(COMPAT_FLAG_NOT_V1ALARMTYPES_ENABLED)) + { + /* create version 1 ValueID's */ + if (Node* node = GetNodeUnsafe()) + { + m_v1Params = true; + node->CreateValueByte(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_Alarm::Type_v1, "Alarm Type", "", true, false, 0, 0); + node->CreateValueByte(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_Alarm::Level_v1, "Alarm Level", "", true, false, 0, 0); + } + } + if (GetVersion() < 4 && m_com.GetFlagBool(COMPAT_FLAG_NOT_ENABLECLEAR) == true) + { + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueInt(ValueID::ValueGenre_Config, GetCommandClassId(), _instance, ValueID_Index_Alarm::AutoClearEvents, "Automatically Clear Events", "ms", false, false, m_ClearTimeout, 0); + } + } - } + } - if( _requestFlags & RequestFlag_Dynamic ) - { - return RequestValue( _requestFlags, 0, _instance, _queue ); - } + if (_requestFlags & RequestFlag_Dynamic) + { + return RequestValue(_requestFlags, 0, _instance, _queue); + } - return false; -} + return false; + } -bool Alarm::SetValue -( - Value const& _value -) -{ - if ((ValueID::ValueType_Int== _value.GetID().GetType()) && (_value.GetID().GetIndex() == AlarmIndex_AutoClearEvents)) { - ValueInt const *value = static_cast(&_value); - m_ClearTimeout = value->GetValue(); - return true; - } - return false; -} + bool Alarm::SetValue(Internal::VC::Value const& _value) + { + if ((ValueID::ValueType_Int == _value.GetID().GetType()) && (_value.GetID().GetIndex() == ValueID_Index_Alarm::AutoClearEvents)) + { + Internal::VC::ValueInt const *value = static_cast(&_value); + m_ClearTimeout = value->GetValue(); + return true; + } + return false; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool Alarm::RequestValue -( - uint32 const _requestFlags, - uint16 const _dummy1, // = 0 (not used) - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - if( GetVersion() == 1 ) - { - Msg* msg = new Msg( "AlarmCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( AlarmCmd_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } - else if (GetVersion() >= 3) - { - bool res = false; - Msg* msg = new Msg( "AlarmCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( GetVersion() == 2 ? 4 : 5); - msg->Append( GetCommandClassId() ); - msg->Append( AlarmCmd_Get ); - msg->Append( 0x00 ); /* we don't get Version 1/2 Alarm Types */ - msg->Append( 0xFF ); - if( GetVersion() > 2 ) - msg->Append(0x00); //get first event of type. - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - res = true; - return res; - } - } else { - Log::Write( LogLevel_Info, GetNodeId(), "AlarmCmd_Get Not Supported on this node"); - } - return false; -} + bool Alarm::RequestValue(uint32 const _requestFlags, uint16 const _dummy1, // = 0 (not used) + uint8 const _instance, Driver::MsgQueue const _queue) + { + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + if (GetVersion() <= 2) + { + Msg* msg = new Msg("AlarmCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(AlarmCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else if (GetVersion() >= 3) + { + bool res = false; + Msg* msg = new Msg("AlarmCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(GetVersion() == 2 ? 4 : 5); + msg->Append(GetCommandClassId()); + msg->Append(AlarmCmd_Get); + msg->Append(0x00); /* we don't get Version 1/2 Alarm Types */ + msg->Append(0xFF); + if (GetVersion() > 2) + msg->Append(0x00); //get first event of type. + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + res = true; + return res; + } + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "AlarmCmd_Get Not Supported on this node"); + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool Alarm::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if (AlarmCmd_Report == (AlarmCmd)_data[0]) - { - // We have received a report from the Z-Wave device - if( GetVersion() == 1) - { - Log::Write( LogLevel_Info, GetNodeId(), "Received Alarm report: type=%d, level=%d", _data[1], _data[2] ); - - if( ValueByte *value = static_cast( GetValue( _instance, AlarmIndex_Type ) ) ) + bool Alarm::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) { - value->OnValueRefreshed( _data[1] ); - value->Release(); - } - // For device on version 1 the level could have different value. This level value correspond to a list of alarm type. - if ( ValueByte* value = static_cast( GetValue( _instance, AlarmIndex_Level ) ) ) - { - value->OnValueRefreshed( _data[2] ); - value->Release(); - } - } - /* version 2 */ - else if(( GetVersion() > 1 ) && ( _length >= 7 )) - { - // With Version=2, the data has more detailed information about the alarm - if (m_v1Params) { + if (AlarmCmd_Report == (AlarmCmd) _data[0]) + { + // We have received a report from the Z-Wave device + if (GetVersion() == 1) + { + Log::Write(LogLevel_Info, GetNodeId(), "Received Alarm report: type=%d, level=%d", _data[1], _data[2]); - Log::Write( LogLevel_Info, GetNodeId(), "Received Notification report (v1): type:%d event:%d", - _data[1], _data[2] ); + if (Internal::VC::ValueByte *value = static_cast(GetValue(_instance, ValueID_Index_Alarm::Type_v1))) + { + value->OnValueRefreshed(_data[1]); + value->Release(); + } + // For device on version 1 the level could have different value. This level value correspond to a list of alarm type. + if (Internal::VC::ValueByte* value = static_cast(GetValue(_instance, ValueID_Index_Alarm::Level_v1))) + { + value->OnValueRefreshed(_data[2]); + value->Release(); + } + } + /* version 2 */ + else if ((GetVersion() > 1) && (_length >= 7)) + { + // With Version=2, the data has more detailed information about the alarm + if (m_v1Params) + { - if( ValueByte *value = static_cast( GetValue( _instance, AlarmIndex_Type ) ) ) - { - value->OnValueRefreshed( _data[1] ); - value->Release(); - } - // For device on version 1 the level could have different value. This level value correspond to a list of alarm type. - if ( ValueByte* value = static_cast( GetValue( _instance, AlarmIndex_Level ) ) ) - { - value->OnValueRefreshed( _data[2] ); - value->Release(); - } - } - /* ok. Its a AlarmCC/NotificationCC Version 2 or above. */ - bool NotificationStatus = false; - if (_data[4] == 0xFF) - NotificationStatus = true; + Log::Write(LogLevel_Info, GetNodeId(), "Received Notification report (v1): type:%d event:%d", _data[1], _data[2]); - uint8 NotificationType = _data[5]; - uint8 NotificationEvent = _data[6]; - bool NotificationSequencePresent = ((_data[7] & 0x80) == 1); - uint8 EventParamLength = (_data[7] & 0x1F); - uint8 NotificationSequence = 0; - if (NotificationSequencePresent) { - NotificationSequence = _data[7+EventParamLength]; - } - Log::Write( LogLevel_Info, GetNodeId(), "Received Notification report (>v1): Type: %s (%d) Event: %s (%d) Status: %s, Param Length: %d", NotificationCCTypes::Get()->GetAlarmType(NotificationType).c_str(), NotificationType, NotificationCCTypes::Get()->GetEventForAlarmType(NotificationType, NotificationEvent).c_str(), NotificationEvent, NotificationStatus ? "true" : "false", EventParamLength); - if (NotificationSequencePresent) - Log::Write ( LogLevel_Info, GetNodeId(), "\t Sequence Number: %d", NotificationSequence); + if (Internal::VC::ValueByte *value = static_cast(GetValue(_instance, ValueID_Index_Alarm::Type_v1))) + { + value->OnValueRefreshed(_data[1]); + value->Release(); + } + // For device on version 1 the level could have different value. This level value correspond to a list of alarm type. + if (Internal::VC::ValueByte* value = static_cast(GetValue(_instance, ValueID_Index_Alarm::Level_v1))) + { + value->OnValueRefreshed(_data[2]); + value->Release(); + } + } + /* ok. Its a AlarmCC/NotificationCC Version 2 or above. */ + bool NotificationStatus = false; + if (_data[4] == 0xFF) + NotificationStatus = true; + + uint8 NotificationType = _data[5]; + uint8 NotificationEvent = _data[6]; + bool NotificationSequencePresent = ((_data[7] & 0x80) == 1); + uint8 EventParamLength = (_data[7] & 0x1F); + uint8 NotificationSequence = 0; + if (NotificationSequencePresent) + { + NotificationSequence = _data[7 + EventParamLength]; + } + Log::Write(LogLevel_Info, GetNodeId(), "Received Notification report (>v1): Type: %s (%d) Event: %s (%d) Status: %s, Param Length: %d", NotificationCCTypes::Get()->GetAlarmType(NotificationType).c_str(), NotificationType, NotificationCCTypes::Get()->GetEventForAlarmType(NotificationType, NotificationEvent).c_str(), NotificationEvent, NotificationStatus ? "true" : "false", EventParamLength); + if (NotificationSequencePresent) + Log::Write(LogLevel_Info, GetNodeId(), "\t Sequence Number: %d", NotificationSequence); - ClearEventParams(_instance); + ClearEventParams(_instance); - m_ParamsSet.clear(); - /* do any Event Params that are sent over */ - if (EventParamLength > 0) { - const std::map nep = NotificationCCTypes::Get()->GetAlarmNotificationEventParams(NotificationType, NotificationEvent); - if (nep.size() > 0) { - for (std::map::const_iterator it = nep.begin(); it != nep.end(); it++) { - switch (it->second->type) { - case NotificationCCTypes::NEPT_Location: { - /* _data[8] should be COMMAND_CLASS_NODE_NAMING - * _data[9] should be NodeNamingCmd_Report (0x03) - */ - if ((_data[8] == NodeNaming::StaticGetCommandClassId()) && (_data[9] == 0x03) && EventParamLength > 2) { - if (ValueString *value = static_cast(GetValue(_instance, it->first))) + m_ParamsSet.clear(); + /* do any Event Params that are sent over */ + if (EventParamLength > 0) + { + const std::map > nep = NotificationCCTypes::Get()->GetAlarmNotificationEventParams(NotificationType, NotificationEvent); + if (nep.size() > 0) + { + for (std::map >::const_iterator it = nep.begin(); it != nep.end(); it++) { - value->OnValueRefreshed(ExtractString(&_data[10], EventParamLength-2)); - value->Release(); - m_ParamsSet.push_back(it->first); - } else { - Log::Write( LogLevel_Warning, GetNodeId(), "Couldn't Find AlarmIndex_Type_ParamLocation"); + switch (it->second->type) + { + case NotificationCCTypes::NEPT_Location: + { + /* _data[8] should be COMMAND_CLASS_NODE_NAMING + * _data[9] should be NodeNamingCmd_Report (0x03) + */ + if ((_data[8] == NodeNaming::StaticGetCommandClassId()) && (_data[9] == 0x03) && EventParamLength > 2) + { + if (Internal::VC::ValueString *value = static_cast(GetValue(_instance, it->first))) + { + value->OnValueRefreshed(ExtractString(&_data[10], EventParamLength - 2)); + value->Release(); + m_ParamsSet.push_back(it->first); + } + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "Couldn't Find ValueID_Index_Alarm::Type_ParamLocation"); + } + } + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "Location Param didn't have correct Header, or was too small"); + } + break; + } + case NotificationCCTypes::NEPT_List: + { + if (EventParamLength == 1) + { + if (Internal::VC::ValueList *value = static_cast(GetValue(_instance, it->first))) + { + value->OnValueRefreshed(_data[8]); + value->Release(); + m_ParamsSet.push_back(it->first); + } + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "Couldn't Find ValueID_Index_Alarm::Type_ParamList"); + } + } + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "List Param size was not equal to 1"); + } + break; + } + case NotificationCCTypes::NEPT_UserCodeReport: + { + /* _data[8] should be COMMAND_CLASS_USER_CODE + * _data[9] should be UserCodeCmd_Report (0x03) + * _data[10] is the UserID + * _data[11] is the UserID Status (Ignored) + * _data[12] onwards is the UserCode Entered (minimum 4 Bytes) + */ + if ((EventParamLength >= 8) && (_data[8] == UserCode::StaticGetCommandClassId()) && (_data[9] == 0x03)) + { + if (Internal::VC::ValueByte *value = static_cast(GetValue(_instance, it->first))) + { + value->OnValueRefreshed(_data[11]); + value->Release(); + m_ParamsSet.push_back(it->first); + } + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "Couldn't Find ValueID_Index_Alarm::Type_ParamUserCodeid"); + } + if (Internal::VC::ValueString *value = static_cast(GetValue(_instance, it->first))) + { + value->OnValueRefreshed(ExtractString(&_data[12], EventParamLength - 4)); + value->Release(); + m_ParamsSet.push_back(it->first); + } + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "Couldn't Find ValueID_Index_Alarm::Type_ParamUserCodeEntered"); + } + } + else if (EventParamLength == 1) + { + /* some devices (Like BeNext TagReader) don't send a Proper UserCodeCmd_Report Message, Just the Index of the Code that Triggered */ + if (Internal::VC::ValueByte *value = static_cast(GetValue(_instance, it->first))) + { + value->OnValueRefreshed(_data[8]); + value->Release(); + m_ParamsSet.push_back(it->first); + } + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "Couldn't Find ValueID_Index_Alarm::Type_ParamUserCodeid"); + } + } + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "UserCode Param didn't have correct Header, or was too small"); + } + break; + } + case NotificationCCTypes::NEPT_Byte: + { + if (EventParamLength == 1) + { + if (Internal::VC::ValueByte *value = static_cast(GetValue(_instance, it->first))) + { + value->OnValueRefreshed(_data[8]); + value->Release(); + m_ParamsSet.push_back(it->first); + } + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "Couldn't Find ValueID_Index_Alarm::Type_ParamByte"); + } + } + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "Byte Param size was not equal to 1"); + } + break; + } + case NotificationCCTypes::NEPT_String: + { + if (Internal::VC::ValueString *value = static_cast(GetValue(_instance, it->first))) + { + value->OnValueRefreshed(ExtractString(&_data[10], EventParamLength - 2)); + value->Release(); + m_ParamsSet.push_back(it->first); + } + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "Couldn't Find ValueID_Index_Alarm::Type_ParamString"); + } + break; + } + case NotificationCCTypes::NEPT_Time: + { + /* This is a Duration Entry, we will expose as seconds. Its 3 Bytes from the Event */ + if (EventParamLength == 3) + { + uint32 duration = (_data[10] * 3600) + (_data[11] * 60) + (_data[12]); + if (Internal::VC::ValueInt *value = static_cast(GetValue(_instance, it->first))) + { + value->OnValueRefreshed(duration); + value->Release(); + m_ParamsSet.push_back(it->first); + } + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "Couldn't Find ValueID_Index_Alarm::Type_Duration"); + } + } + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "Duration Param size was not equal to 3"); + } + break; + } + + } + } + } + } + + /* update the actual value only after we set the Params */ + if (Internal::VC::ValueList *value = static_cast(GetValue(_instance, NotificationType))) + { + value->OnValueRefreshed(NotificationEvent); + value->Release(); + } + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "Couldn't Find a ValueList for Notification Type %d (%d)", NotificationType, _instance); + } + + /* Any Version below 4 doesn't have a Clear Event, so we trigger a timer to manually clear it */ + if ((NotificationEvent != 0) && (GetVersion() < 4) && (m_ClearTimeout > 0) && (m_com.GetFlagBool(COMPAT_FLAG_NOT_ENABLECLEAR) == true)) + { + Log::Write(LogLevel_Info, GetNodeId(), "Automatically Clearing Alarm in %dms", m_ClearTimeout); + m_TimersToInstances.insert(std::pair(NotificationType, _instance)); + TimerThread::TimerCallback callback = bind(&Alarm::ClearAlarm, this, NotificationType); + TimerSetEvent(m_ClearTimeout, callback, 1); + } + + } + return true; + } + + if (AlarmCmd_SupportedReport == (AlarmCmd) _data[0]) + { + if (Node* node = GetNodeUnsafe()) + { + // We have received the supported alarm types from the Z-Wave device + Log::Write(LogLevel_Info, GetNodeId(), "Received supported alarm types"); + /* Device Only supports Version 1 of the Alarm CC */ + if ((GetVersion() > 2) && (_data[1] & 0x80)) + { + m_v1Params = true; + Log::Write(LogLevel_Info, GetNodeId(), "Notification::SupportedReport - Device Supports Alarm Version 1 Parameters"); + node->CreateValueByte(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_Alarm::Type_v1, "Alarm Type", "", true, false, 0, 0); + node->CreateValueByte(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_Alarm::Level_v1, "Alarm Level", "", true, false, 0, 0); + } + // Parse the data for the supported alarm types + uint8 numBytes = (_data[1] & 0x1F); + for (uint32 i = 0; i < numBytes; ++i) + { + for (int32 bit = 0; bit < 8; ++bit) + { + if ((_data[i + 2] & (1 << bit)) != 0) + { + int32 index = (int32) (i << 3) + bit; + Log::Write(LogLevel_Info, GetNodeId(), "\tAlarmType: %s", NotificationCCTypes::Get()->GetAlarmType(index).c_str()); + if (GetVersion() == 2) + { + /* EventSupported is only compatible in Version 3 and above */ + vector _items; + if (const std::shared_ptr nt = NotificationCCTypes::Get()->GetAlarmNotificationTypes(index)) + { + for (std::map >::const_iterator it = nt->Events.begin(); it != nt->Events.end(); it++) + { + /* Create it */ + SetupEvents(index, it->first, &_items, _instance); +#if 0 + Log::Write ( LogLevel_Info, GetNodeId(), "\t\tAll Events - Alarm CC Version 2 - %s", it->second->name); + ValueList::Item item; + item.m_value = it->first; + item.m_label = it->second->name; + _items.push_back( item ); +#endif + } + node->CreateValueList(ValueID::ValueGenre_User, GetCommandClassId(), _instance, index, NotificationCCTypes::Get()->GetAlarmType(index), "", true, false, (const uint8_t) (_items.size() & 0xFF), _items, 0, 0); + } + ClearStaticRequest(StaticRequest_Values); + } + else if (GetVersion() > 2) + { + /* These Devices have EVENT_SUPPORTED command */ + Msg* msg = new Msg("AlarmCmd_Event_Supported_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(AlarmCmd_Event_Supported_Get); + msg->Append(index); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + } } - } else { - Log::Write( LogLevel_Warning, GetNodeId(), "Location Param didn't have correct Header, or was too small"); } - break; } - case NotificationCCTypes::NEPT_List: { - if (EventParamLength == 1) { - if (ValueList *value = static_cast(GetValue(_instance, it->first))) + } + return true; + } + if (AlarmCmd_Event_Supported_Report == (AlarmCmd) _data[0]) + { + // if( Node* node = GetNodeUnsafe() ) + { + uint32 type = _data[1]; + // We have received the supported alarm Event types from the Z-Wave device + Log::Write(LogLevel_Info, GetNodeId(), "Received supported alarm Event types for AlarmType %s (%d)", NotificationCCTypes::Get()->GetAlarmType(type).c_str(), type); + // Parse the data for the supported Alarm Event types + uint8 numBytes = (_data[2] & 0x1F); + vector _items; + /* always Add the Clear Event Type */ + SetupEvents(type, 0, &_items, _instance); + + for (uint32 i = 0; i < numBytes; ++i) + { + for (int32 bit = 0; bit < 8; ++bit) + { + if ((_data[i + 3] & (1 << bit)) != 0) { - value->OnValueRefreshed(_data[8]); - value->Release(); - m_ParamsSet.push_back(it->first); - } else { - Log::Write( LogLevel_Warning, GetNodeId(), "Couldn't Find AlarmIndex_Type_ParamList"); + uint32 index = (int32) (i << 3) + bit; + SetupEvents(type, index, &_items, _instance); } - } else { - Log::Write( LogLevel_Warning, GetNodeId(), "List Param size was not equal to 1"); } - break; } - case NotificationCCTypes::NEPT_UserCodeReport: { - /* _data[8] should be COMMAND_CLASS_USER_CODE - * _data[9] should be UserCodeCmd_Report (0x03) - * _data[10] is the UserID - * _data[11] is the UserID Status (Ignored) - * _data[12] onwards is the UserCode Entered (minimum 4 Bytes) - */ - if ((EventParamLength >= 8 ) && (_data[8] == UserCode::StaticGetCommandClassId()) && (_data[9] == 0x03)) { - if (ValueByte *value = static_cast(GetValue(_instance, it->first))) + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueList(ValueID::ValueGenre_User, GetCommandClassId(), _instance, type, NotificationCCTypes::Get()->GetAlarmType(type), "", true, false, (uint8_t) (_items.size() & 0xFF), _items, 0, 0); + } + } + ClearStaticRequest(StaticRequest_Values); + return true; + } + + return false; + } + void Alarm::SetupEvents(uint32 type, uint32 index, vector *_items, uint32 const _instance) + { + if (const std::shared_ptr ne = NotificationCCTypes::Get()->GetAlarmNotificationEvents(type, index)) + { + Log::Write(LogLevel_Info, GetNodeId(), "\tEvent Type %d: %s ", ne->id, ne->name.c_str()); + Internal::VC::ValueList::Item item; + item.m_value = ne->id; + item.m_label = ne->name; + _items->push_back(item); + /* If there are Params - Lets create the correct types now */ + if (Node* node = GetNodeUnsafe()) + { + for (std::map >::const_iterator it = ne->EventParams.begin(); it != ne->EventParams.end(); it++) + { + switch (it->second->type) + { + case NotificationCCTypes::NEPT_Location: { - value->OnValueRefreshed(_data[11]); - value->Release(); - m_ParamsSet.push_back(it->first); - } else { - Log::Write( LogLevel_Warning, GetNodeId(), "Couldn't Find AlarmIndex_Type_ParamUserCodeid"); + node->CreateValueString(ValueID::ValueGenre_User, GetCommandClassId(), _instance, it->first, it->second->name, "", true, false, "", 0); + break; } - if (ValueString *value = static_cast(GetValue(_instance,it->first))) + case NotificationCCTypes::NEPT_List: { - value->OnValueRefreshed(ExtractString(&_data[12], EventParamLength-4)); - value->Release(); - m_ParamsSet.push_back(it->first); - } else { - Log::Write( LogLevel_Warning, GetNodeId(), "Couldn't Find AlarmIndex_Type_ParamUserCodeEntered"); + vector _Paramitems; + for (std::map::iterator it2 = it->second->ListItems.begin(); it2 != it->second->ListItems.end(); it2++) + { + Internal::VC::ValueList::Item Paramitem; + Paramitem.m_value = ne->id; + Paramitem.m_label = ne->name; + _Paramitems.push_back(Paramitem); + } + node->CreateValueList(ValueID::ValueGenre_User, GetCommandClassId(), _instance, it->first, it->second->name, "", true, false, (uint8_t) (_Paramitems.size() & 0xFF), _Paramitems, 0, 0); + break; } - } else if (EventParamLength == 1) { - /* some devices (Like BeNext TagReader) don't send a Proper UserCodeCmd_Report Message, Just the Index of the Code that Triggered */ - if (ValueByte *value = static_cast(GetValue(_instance, it->first))) + case NotificationCCTypes::NEPT_UserCodeReport: { - value->OnValueRefreshed(_data[11]); - value->Release(); - m_ParamsSet.push_back(it->first); - } else { - Log::Write( LogLevel_Warning, GetNodeId(), "Couldn't Find AlarmIndex_Type_ParamUserCodeid"); + node->CreateValueByte(ValueID::ValueGenre_User, GetCommandClassId(), _instance, it->first, it->second->name, "", true, false, 0, 0); + node->CreateValueString(ValueID::ValueGenre_User, GetCommandClassId(), _instance, it->first + 1, it->second->name, "", true, false, "", 0); + break; } - } else { - Log::Write( LogLevel_Warning, GetNodeId(), "UserCode Param didn't have correct Header, or was too small"); - } - break; - } - case NotificationCCTypes::NEPT_Byte: { - if (EventParamLength == 1) { - if (ValueByte *value = static_cast(GetValue(_instance, it->first))) + case NotificationCCTypes::NEPT_Byte: { - value->OnValueRefreshed(_data[8]); - value->Release(); - m_ParamsSet.push_back(it->first); - } else { - Log::Write( LogLevel_Warning, GetNodeId(), "Couldn't Find AlarmIndex_Type_ParamByte"); + node->CreateValueByte(ValueID::ValueGenre_User, GetCommandClassId(), _instance, it->first, it->second->name, "", true, false, 0, 0); + break; } - } else { - Log::Write( LogLevel_Warning, GetNodeId(), "Byte Param size was not equal to 1"); - } - break; - } - case NotificationCCTypes::NEPT_String: { - if (ValueString *value = static_cast(GetValue(_instance, it->first))) - { - value->OnValueRefreshed(ExtractString(&_data[10], EventParamLength-2)); - value->Release(); - m_ParamsSet.push_back(it->first); - } else { - Log::Write( LogLevel_Warning, GetNodeId(), "Couldn't Find AlarmIndex_Type_ParamString"); - } - break; - } - case NotificationCCTypes::NEPT_Time: { - /* This is a Duration Entry, we will expose as seconds. Its 3 Bytes from the Event */ - if (EventParamLength == 3) { - uint32 duration = (_data[10] * 3600) + (_data[11] * 60) + (_data[12]); - if (ValueInt *value = static_cast(GetValue(_instance, it->first))) + case NotificationCCTypes::NEPT_String: + { + node->CreateValueString(ValueID::ValueGenre_User, GetCommandClassId(), _instance, it->first, it->second->name, "", true, false, "", 0); + break; + } + case NotificationCCTypes::NEPT_Time: { - value->OnValueRefreshed(duration); - value->Release(); - m_ParamsSet.push_back(it->first); - } else { - Log::Write( LogLevel_Warning, GetNodeId(), "Couldn't Find AlarmIndex_Type_Duration"); + node->CreateValueInt(ValueID::ValueGenre_User, GetCommandClassId(), _instance, it->first, it->second->name, "", true, false, 0, 0); + break; } - } else { - Log::Write( LogLevel_Warning, GetNodeId(), "Duration Param size was not equal to 3"); } - break; - } - } } } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "\tEvent Type %d: Unknown", index); + Internal::VC::ValueList::Item item; + item.m_value = index; + item.m_label = string("Unknown"); + _items->push_back(item); + } } - /* update the actual value only after we set the Params */ - if ( ValueList *value = static_cast( GetValue( _instance, NotificationType ) ) ) + void Alarm::ClearEventParams(uint32 const _instance) { - value->OnValueRefreshed(NotificationEvent); - value->Release(); - } else { - Log::Write ( LogLevel_Warning, GetNodeId(), "Couldn't Find a ValueList for Notification Type %d (%d)", NotificationType, _instance); - } - - /* Any Version below 4 doesn't have a Clear Event, so we trigger a timer to manually clear it */ - if ((NotificationEvent != 0) && (GetVersion() < 4)) { - Log::Write( LogLevel_Info, GetNodeId(), "Automatically Clearing Alarm in %dms", m_ClearTimeout ); - m_TimersToInstances.insert(std::pair(NotificationType, _instance)); - TimerThread::TimerCallback callback = bind(&Alarm::ClearAlarm, this, NotificationType); - TimerSetEvent(m_ClearTimeout, callback, 1); - } + /* Reset Any of the Params that may have been previously set with another event */ + for (std::vector::iterator it = m_ParamsSet.begin(); it != m_ParamsSet.end(); it++) + { - } - return true; - } + Internal::VC::Value *value = GetValue(_instance, (*it)); - if( AlarmCmd_SupportedReport == (AlarmCmd)_data[0] ) - { - if( Node* node = GetNodeUnsafe() ) - { - // We have received the supported alarm types from the Z-Wave device - Log::Write( LogLevel_Info, GetNodeId(), "Received supported alarm types" ); - /* Device Only supports Version 1 of the Alarm CC */ - if ((GetVersion() > 2) && (_data[1] & 0x80)) { - m_v1Params = true; - Log::Write( LogLevel_Info, GetNodeId(), "Notification::SupportedReport - Device Supports Alarm Version 1 Parameters"); - node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, AlarmIndex_Type, "Alarm Type", "", true, false, 0, 0 ); - node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, AlarmIndex_Level, "Alarm Level", "", true, false, 0, 0 ); - } - // Parse the data for the supported alarm types - uint8 numBytes = (_data[1] & 0x1F); - for( uint32 i=0; iGetID().GetType()) { - int32 index = (int32)(i<<3) + bit; - Log::Write( LogLevel_Info, GetNodeId(), "\tAlarmType: %s", NotificationCCTypes::Get()->GetAlarmType(index).c_str()); - if (GetVersion() == 2) { - /* EventSupported is only compatible in Version 3 and above */ - vector _items; - if (const NotificationCCTypes::NotificationTypes *nt = NotificationCCTypes::Get()->GetAlarmNotificationTypes(index)) { - for (std::map::const_iterator it = nt->Events.begin(); it != nt->Events.end(); it++) { - /* Create it */ - SetupEvents(index, it->first, &_items, _instance); -#if 0 - Log::Write ( LogLevel_Info, GetNodeId(), "\t\tAll Events - Alarm CC Version 2 - %s", it->second->name); - ValueList::Item item; - item.m_value = it->first; - item.m_label = it->second->name; - _items.push_back( item ); -#endif - } - node->CreateValueList( ValueID::ValueGenre_User, GetCommandClassId(), _instance, index, NotificationCCTypes::Get()->GetAlarmType(index), "", true, false, (const uint8_t)(_items.size() & 0xFF), _items, 0, 0 ); + case ValueID::ValueType_Byte: + { + if (Internal::VC::ValueByte *value = static_cast(GetValue(_instance, (*it)))) + { + value->OnValueRefreshed(0); + value->Release(); + } + } + break; + case ValueID::ValueType_String: + { + if (Internal::VC::ValueString *value = static_cast(GetValue(_instance, (*it)))) + { + value->OnValueRefreshed(""); + value->Release(); } - ClearStaticRequest( StaticRequest_Values ); } - else if (GetVersion() > 2) + break; + case ValueID::ValueType_List: + { + if (Internal::VC::ValueList *value = static_cast(GetValue(_instance, (*it)))) + { + /* XXX TODO: Need to specify that the default is. Not all Lists have 0 index */ + value->OnValueRefreshed(0); + value->Release(); + } + } + break; + case ValueID::ValueType_Int: { - /* These Devices have EVENT_SUPPORTED command */ - Msg* msg = new Msg( "AlarmCmd_Event_Supported_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( AlarmCmd_Event_Supported_Get ); - msg->Append( index); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); + if (Internal::VC::ValueInt *value = static_cast(GetValue(_instance, (*it)))) + { + value->OnValueRefreshed(0); + value->Release(); + } } + break; + default: + Log::Write(LogLevel_Warning, GetNodeId(), "TODO: Clear Events for ValueType %d", value->GetID().GetType()); } } } - } - return true; - } - if( AlarmCmd_Event_Supported_Report == (AlarmCmd)_data[0] ) - { - // if( Node* node = GetNodeUnsafe() ) - { - uint32 type = _data[1]; - // We have received the supported alarm Event types from the Z-Wave device - Log::Write( LogLevel_Info, GetNodeId(), "Received supported alarm Event types for AlarmType %s (%d)", NotificationCCTypes::Get()->GetAlarmType(type).c_str(), type); - // Parse the data for the supported Alarm Event types - uint8 numBytes = (_data[2] & 0x1F); - vector _items; - /* always Add the Clear Event Type */ - SetupEvents(type, 0, &_items, _instance); - for( uint32 i=0; iCreateValueList( ValueID::ValueGenre_User, GetCommandClassId(), _instance, type, NotificationCCTypes::Get()->GetAlarmType(type), "", true, false, (uint8_t)(_items.size() & 0xFF), _items, 0, 0 ); - } - } - ClearStaticRequest( StaticRequest_Values ); - return true; - } - - return false; -} -void Alarm::SetupEvents -( - uint32 type, - uint32 index, - vector *_items, - uint32 const _instance -) -{ - if (const NotificationCCTypes::NotificationEvents *ne = NotificationCCTypes::Get()->GetAlarmNotificationEvents(type, index)) { - Log::Write( LogLevel_Info, GetNodeId(), "\tEvent Type %d: %s ", ne->id, ne->name.c_str()); - ValueList::Item item; - item.m_value = ne->id; - item.m_label = ne->name; - _items->push_back( item ); - /* If there are Params - Lets create the correct types now */ - if ( Node* node = GetNodeUnsafe() ) { - for (std::map::const_iterator it = ne->EventParams.begin(); it != ne->EventParams.end(); it++ ) { - switch (it->second->type) { - case NotificationCCTypes::NEPT_Location: { - node->CreateValueString( ValueID::ValueGenre_User, GetCommandClassId(), _instance, it->first, it->second->name, "", true, false, "", 0); - break; + _instance = m_TimersToInstances.at(type); + m_TimersToInstances.erase(type); } - case NotificationCCTypes::NEPT_List: { - vector _Paramitems; - for (std::map::iterator it2 = it->second->ListItems.begin(); it2 != it->second->ListItems.end(); it2++) { - ValueList::Item Paramitem; - Paramitem.m_value = ne->id; - Paramitem.m_label = ne->name; - _Paramitems.push_back( Paramitem ); - } - node->CreateValueList( ValueID::ValueGenre_User, GetCommandClassId(), _instance, it->first, it->second->name, "", true, false, (uint8_t)(_Paramitems.size() & 0xFF), _Paramitems, 0, 0 ); - break; - } - case NotificationCCTypes::NEPT_UserCodeReport: { - node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, it->first, it->second->name, "", true, false, 0, 0); - node->CreateValueString(ValueID::ValueGenre_User, GetCommandClassId(), _instance, it->first+1, it->second->name, "", true, false, "", 0); - break; - } - case NotificationCCTypes::NEPT_Byte: { - node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, it->first, it->second->name, "", true, false, 0, 0); - break; + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "Cant Find Notification Type %d in m_TimersToInstances", type); + return; } - case NotificationCCTypes::NEPT_String: { - node->CreateValueString( ValueID::ValueGenre_User, GetCommandClassId(), _instance, it->first, it->second->name, "", true, false, "", 0); - break; + ClearEventParams(_instance); + /* update the actual value only after we set the Params */ + if (Internal::VC::ValueList *value = static_cast(GetValue(_instance, type))) + { + value->OnValueRefreshed(0); + value->Release(); } - case NotificationCCTypes::NEPT_Time: { - node->CreateValueInt( ValueID::ValueGenre_User, GetCommandClassId(), _instance, it->first, it->second->name, "", true, false, 0, 0); - break; + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "Couldn't Find a ValueList to ClearAlarm for Notification Type %d (%d)", type, _instance); } + if (m_v1Params) + { + if (Internal::VC::ValueByte *value = static_cast(GetValue(_instance, ValueID_Index_Alarm::Type_v1))) + { + value->OnValueRefreshed(0); + value->Release(); + } + if (Internal::VC::ValueByte* value = static_cast(GetValue(_instance, ValueID_Index_Alarm::Level_v1))) + { + value->OnValueRefreshed(0); + value->Release(); + } } } - } - } else { - Log::Write (LogLevel_Info, GetNodeId(), "\tEvent Type %d: Unknown", index); - ValueList::Item item; - item.m_value = index; - item.m_label = string("Unknown"); - _items->push_back( item ); - } -} - -void Alarm::ClearEventParams -( - uint32 const _instance -) -{ - /* Reset Any of the Params that may have been previously set with another event */ - for (std::vector::iterator it = m_ParamsSet.begin(); it != m_ParamsSet.end(); it++) - { - - Value *value = GetValue(_instance, (*it)); - - switch (value->GetID().GetType()) { - case ValueID::ValueType_Byte: { - if (ValueByte *value = static_cast(GetValue(_instance, (*it)))) - { - value->OnValueRefreshed(0); - value->Release(); - } - } - break; - case ValueID::ValueType_String: { - if (ValueString *value = static_cast(GetValue(_instance, (*it)))) - { - value->OnValueRefreshed(""); - value->Release(); - } - } - break; - case ValueID::ValueType_List: { - if (ValueList *value = static_cast(GetValue(_instance, (*it)))) - { - /* XXX TODO: Need to specify that the default is. Not all Lists have 0 index */ - value->OnValueRefreshed(0); - value->Release(); - } - } - break; - case ValueID::ValueType_Int: { - if (ValueInt *value = static_cast(GetValue(_instance, (*it)))) - { - value->OnValueRefreshed(0); - value->Release(); - } - } - break; - default: - Log::Write(LogLevel_Warning, GetNodeId(), "TODO: Clear Events for ValueType %d", value->GetID().GetType()); - } - } -} - -void Alarm::ClearAlarm(uint32 type) { - uint32 _instance; - if (m_TimersToInstances.find(type) != m_TimersToInstances.end()) { - _instance = m_TimersToInstances.at(type); - m_TimersToInstances.erase(type); - } else { - Log::Write(LogLevel_Warning, GetNodeId(), "Cant Find Notification Type %d in m_TimersToInstances", type); - return; - } - ClearEventParams(_instance); - /* update the actual value only after we set the Params */ - if ( ValueList *value = static_cast( GetValue( _instance, type ) ) ) - { - value->OnValueRefreshed(0); - value->Release(); - } else { - Log::Write ( LogLevel_Warning, GetNodeId(), "Couldn't Find a ValueList to ClearAlarm for Notification Type %d (%d)", type, _instance); - } -} + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/Alarm.h b/cpp/src/command_classes/Alarm.h index f0ce6e6328..252c8f0bb0 100644 --- a/cpp/src/command_classes/Alarm.h +++ b/cpp/src/command_classes/Alarm.h @@ -34,46 +34,68 @@ namespace OpenZWave { class ValueByte; - - /** \brief Implements COMMAND_CLASS_NOTIFICATION (0x71), a Z-Wave device command class. - * \ingroup CommandClass - */ - class Alarm: public CommandClass, private Timer + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Alarm( _homeId, _nodeId ); } - virtual ~Alarm(){} - - /** \brief Get command class ID (1 byte) identifying this command class. */ - static uint8 const StaticGetCommandClassId(){ return 0x71; } - /** \brief Get a string containing the name of this command class. */ - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_NOTIFICATION"; } - - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - /** \brief Get command class ID (1 byte) identifying this command class. (Inherited from CommandClass) */ - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - /** \brief Get a string containing the name of this command class. (Inherited from CommandClass) */ - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - /** \brief Handle a response to a message associated with this command class. (Inherited from CommandClass) */ - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual uint8 GetMaxVersion(){ return 8; } - virtual bool SetValue( Value const& _value ); - + namespace CC + { + /** \brief Implements COMMAND_CLASS_NOTIFICATION (0x71), a Z-Wave device command class. + * \ingroup CommandClass + */ + class Alarm: public CommandClass, private Timer + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new Alarm(_homeId, _nodeId); + } + virtual ~Alarm() + { + } - private: - Alarm( uint32 const _homeId, uint8 const _nodeId ); - void SetupEvents(uint32 type, uint32 index, vector *_items, uint32 const _instance); - void ClearAlarm(uint32 type); - void ClearEventParams(uint32 const _instance); - bool m_v1Params; - std::vector m_ParamsSet; - uint32 m_ClearTimeout; - std::map m_TimersToInstances; + /** \brief Get command class ID (1 byte) identifying this command class. */ + static uint8 const StaticGetCommandClassId() + { + return 0x71; + } + /** \brief Get a string containing the name of this command class. */ + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_NOTIFICATION"; + } + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + /** \brief Get command class ID (1 byte) identifying this command class. (Inherited from CommandClass) */ + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + /** \brief Get a string containing the name of this command class. (Inherited from CommandClass) */ + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + /** \brief Handle a response to a message associated with this command class. (Inherited from CommandClass) */ + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual uint8 GetMaxVersion() override + { + return 8; + } + virtual bool SetValue(Internal::VC::Value const& _value) override; - }; + private: + Alarm(uint32 const _homeId, uint8 const _nodeId); + void SetupEvents(uint32 type, uint32 index, vector *_items, uint32 const _instance); + void ClearAlarm(uint32 type); + void ClearEventParams(uint32 const _instance); + bool m_v1Params; + std::vector m_ParamsSet; + uint32 m_ClearTimeout; + std::map m_TimersToInstances; + }; + } // namespace CommandClass + } // namespace Internal } // namespace OpenZWave diff --git a/cpp/src/command_classes/ApplicationStatus.cpp b/cpp/src/command_classes/ApplicationStatus.cpp index 01ce654ff4..0063ac289c 100644 --- a/cpp/src/command_classes/ApplicationStatus.cpp +++ b/cpp/src/command_classes/ApplicationStatus.cpp @@ -33,65 +33,67 @@ #include "Notification.h" #include "platform/Log.h" -using namespace OpenZWave; - -enum ApplicationStatusCmd +namespace OpenZWave { - ApplicationStatusCmd_Busy = 0x01, - ApplicationStatusCmd_RejectedRequest = 0x02 -}; + namespace Internal + { + namespace CC + { + enum ApplicationStatusCmd + { + ApplicationStatusCmd_Busy = 0x01, + ApplicationStatusCmd_RejectedRequest = 0x02 + }; //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool ApplicationStatus::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - Notification* notification = new Notification( Notification::Type_Notification ); - notification->SetHomeAndNodeIds( GetHomeId(), GetNodeId() ); - notification->SetNotification( Notification::Type_UserAlerts ); - if( ApplicationStatusCmd_Busy == (ApplicationStatusCmd)_data[0] ) - { - switch( _data[1] ) - { - case 0: - { - notification->SetUserAlertNotification(Notification::Alert_ApplicationStatus_Retry); - break; - } - case 1: - { - notification->SetUserAlertNotification(Notification::Alert_ApplicationStatus_Retry); - notification->SetRetry(_data[2]); - break; - } - case 2: - { - notification->SetUserAlertNotification(Notification::Alert_ApplicationStatus_Queued); - break; - } - default: + bool ApplicationStatus::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) { - // Invalid status - Log::Write( LogLevel_Warning, GetNodeId(), "Received a unknown Application Status Message %d - Assuming Rejected", _data[1]); - notification->SetUserAlertNotification(Notification::Alert_ApplicationStatus_Rejected); - } - } - } + Notification* notification = new Notification(Notification::Type_UserAlerts); + notification->SetHomeAndNodeIds(GetHomeId(), GetNodeId()); + if (ApplicationStatusCmd_Busy == (ApplicationStatusCmd) _data[0]) + { + switch (_data[1]) + { + case 0: + { + notification->SetUserAlertNotification(Notification::Alert_ApplicationStatus_Retry); + break; + } + case 1: + { + notification->SetUserAlertNotification(Notification::Alert_ApplicationStatus_Retry); + notification->SetRetry(_data[2]); + break; + } + case 2: + { + notification->SetUserAlertNotification(Notification::Alert_ApplicationStatus_Queued); + break; + } + default: + { + // Invalid status + Log::Write(LogLevel_Warning, GetNodeId(), "Received a unknown Application Status Message %d - Assuming Rejected", _data[1]); + notification->SetUserAlertNotification(Notification::Alert_ApplicationStatus_Rejected); + } + } + } - if( ApplicationStatusCmd_RejectedRequest == (ApplicationStatusCmd)_data[0] ) - { - notification->SetUserAlertNotification(Notification::Alert_ApplicationStatus_Rejected); - } + if (ApplicationStatusCmd_RejectedRequest == (ApplicationStatusCmd) _data[0]) + { + notification->SetUserAlertNotification(Notification::Alert_ApplicationStatus_Rejected); + } - GetDriver()->QueueNotification( notification ); + GetDriver()->QueueNotification(notification); - return true; -} + return true; + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/ApplicationStatus.h b/cpp/src/command_classes/ApplicationStatus.h index 5034e98408..8d87fdddcc 100644 --- a/cpp/src/command_classes/ApplicationStatus.h +++ b/cpp/src/command_classes/ApplicationStatus.h @@ -32,27 +32,52 @@ namespace OpenZWave { - /** \brief Implements COMMAND_CLASS_APPLICATION_STATUS (0x22), a Z-Wave device command class. - * \ingroup CommandClass - */ - class ApplicationStatus: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new ApplicationStatus( _homeId, _nodeId ); } - virtual ~ApplicationStatus(){} + namespace CC + { + /** \brief Implements COMMAND_CLASS_APPLICATION_STATUS (0x22), a Z-Wave device command class. + * \ingroup CommandClass + */ + class ApplicationStatus: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new ApplicationStatus(_homeId, _nodeId); + } + virtual ~ApplicationStatus() + { + } - static uint8 const StaticGetCommandClassId(){ return 0x22; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_APPLICATION_STATUS"; } + static uint8 const StaticGetCommandClassId() + { + return 0x22; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_APPLICATION_STATUS"; + } - // From CommandClass - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - - private: - ApplicationStatus( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} - }; + // From CommandClass + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + private: + ApplicationStatus(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + } + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/Association.cpp b/cpp/src/command_classes/Association.cpp index 2bdd375de3..5d84f00acc 100644 --- a/cpp/src/command_classes/Association.cpp +++ b/cpp/src/command_classes/Association.cpp @@ -35,356 +35,324 @@ #include "Group.h" #include "platform/Log.h" -using namespace OpenZWave; - -enum AssociationCmd +namespace OpenZWave { - AssociationCmd_Set = 0x01, - AssociationCmd_Get = 0x02, - AssociationCmd_Report = 0x03, - AssociationCmd_Remove = 0x04, - AssociationCmd_GroupingsGet = 0x05, - AssociationCmd_GroupingsReport = 0x06 -}; + namespace Internal + { + namespace CC + { + enum AssociationCmd + { + AssociationCmd_Set = 0x01, + AssociationCmd_Get = 0x02, + AssociationCmd_Report = 0x03, + AssociationCmd_Remove = 0x04, + AssociationCmd_GroupingsGet = 0x05, + AssociationCmd_GroupingsReport = 0x06 + }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -Association::Association -( - uint32 const _homeId, - uint8 const _nodeId -): - CommandClass( _homeId, _nodeId ), - m_queryAll(false), - m_numGroups(0) -{ - SetStaticRequest( StaticRequest_Values ); -} + Association::Association(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId), m_queryAll(false), m_numGroups(0) + { + SetStaticRequest(StaticRequest_Values); + } //----------------------------------------------------------------------------- // // Read the saved association data //----------------------------------------------------------------------------- -void Association::ReadXML -( - TiXmlElement const* _ccElement -) -{ - CommandClass::ReadXML( _ccElement ); - - TiXmlElement const* associationsElement = _ccElement->FirstChildElement(); - while( associationsElement ) - { - char const* str = associationsElement->Value(); - if( str && !strcmp( str, "Associations" ) ) - { - int intVal; - if( TIXML_SUCCESS == associationsElement->QueryIntAttribute( "num_groups", &intVal ) ) + void Association::ReadXML(TiXmlElement const* _ccElement) { - m_numGroups = (uint8)intVal; - } + CommandClass::ReadXML(_ccElement); - TiXmlElement const* groupElement = associationsElement->FirstChildElement(); - while( groupElement ) - { - if( Node* node = GetNodeUnsafe() ) + TiXmlElement const* associationsElement = _ccElement->FirstChildElement(); + while (associationsElement) { - Group* group = new Group( GetHomeId(), GetNodeId(), groupElement ); - node->AddGroup( group ); - } + char const* str = associationsElement->Value(); + if (str && !strcmp(str, "Associations")) + { + int intVal; + if (TIXML_SUCCESS == associationsElement->QueryIntAttribute("num_groups", &intVal)) + { + m_numGroups = (uint8) intVal; + } - groupElement = groupElement->NextSiblingElement(); - } + TiXmlElement const* groupElement = associationsElement->FirstChildElement(); + while (groupElement) + { + if (Node* node = GetNodeUnsafe()) + { + Group* group = new Group(GetHomeId(), GetNodeId(), groupElement); + node->AddGroup(group); + } - break; - } + groupElement = groupElement->NextSiblingElement(); + } - associationsElement = associationsElement->NextSiblingElement(); - } -} + break; + } + + associationsElement = associationsElement->NextSiblingElement(); + } + } //----------------------------------------------------------------------------- // // Save the association data //----------------------------------------------------------------------------- -void Association::WriteXML -( - TiXmlElement* _ccElement -) -{ - CommandClass::WriteXML( _ccElement ); + void Association::WriteXML(TiXmlElement* _ccElement) + { + CommandClass::WriteXML(_ccElement); - if( Node* node = GetNodeUnsafe() ) - { - TiXmlElement* associationsElement = new TiXmlElement( "Associations" ); + if (Node* node = GetNodeUnsafe()) + { + TiXmlElement* associationsElement = new TiXmlElement("Associations"); - char str[8]; - snprintf( str, 8, "%d", m_numGroups ); - associationsElement->SetAttribute( "num_groups", str ); + char str[8]; + snprintf(str, 8, "%d", m_numGroups); + associationsElement->SetAttribute("num_groups", str); - _ccElement->LinkEndChild( associationsElement ); - node->WriteGroups( associationsElement ); - } -} + _ccElement->LinkEndChild(associationsElement); + node->WriteGroups(associationsElement); + } + } //----------------------------------------------------------------------------- // // Nothing to do for Association //----------------------------------------------------------------------------- -bool Association::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) ) - { - // Request the supported group info - return RequestValue( _requestFlags, 0, _instance, _queue ); - } + bool Association::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + if ((_requestFlags & RequestFlag_Static) && HasStaticRequest(StaticRequest_Values)) + { + // Request the supported group info + return RequestValue(_requestFlags, 0, _instance, _queue); + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Nothing to do for Association //----------------------------------------------------------------------------- -bool Association::RequestValue -( - uint32 const _requestFlags, - uint16 const _dummy1, // = 0 (not used) - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _instance != 1 ) - { - // This command class doesn't work with multiple instances - return false; - } - // Request the supported group info - Msg* msg = new Msg( "AssociationCmd_GroupingsGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( AssociationCmd_GroupingsGet ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; -} + bool Association::RequestValue(uint32 const _requestFlags, uint16 const _dummy1, // = 0 (not used) + uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_instance != 1) + { + // This command class doesn't work with multiple instances + return false; + } + // Request the supported group info + Msg* msg = new Msg("AssociationCmd_GroupingsGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(AssociationCmd_GroupingsGet); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } //----------------------------------------------------------------------------- // // Request the contents of each group in turn //----------------------------------------------------------------------------- -void Association::RequestAllGroups -( - uint32 const _requestFlags -) -{ - m_queryAll = true; + void Association::RequestAllGroups(uint32 const _requestFlags) + { + m_queryAll = true; - // Request the contents of the individual groups in turn. - if( m_numGroups == 0xff ) - { - // We start with group 255, and will then move to group 1, 2 etc and stop when we find a group with a maxAssociations of zero. - Log::Write( LogLevel_Info, GetNodeId(), "Number of association groups reported for node %d is 255, which requires special case handling.", GetNodeId() ); - QueryGroup( 0xff, _requestFlags ); - } - else - { - // We start with group 1, and will then move to group 2, 3 etc and stop when the group index is greater than m_numGroups. - Log::Write( LogLevel_Info, GetNodeId(), "Number of association groups reported for node %d is %d.", GetNodeId(), m_numGroups ); - QueryGroup( 1, _requestFlags ); - } -} + // Request the contents of the individual groups in turn. + if (m_numGroups == 0xff) + { + // We start with group 255, and will then move to group 1, 2 etc and stop when we find a group with a maxAssociations of zero. + Log::Write(LogLevel_Info, GetNodeId(), "Number of association groups reported for node %d is 255, which requires special case handling.", GetNodeId()); + QueryGroup(0xff, _requestFlags); + } + else + { + // We start with group 1, and will then move to group 2, 3 etc and stop when the group index is greater than m_numGroups. + Log::Write(LogLevel_Info, GetNodeId(), "Number of association groups reported for node %d is %d.", GetNodeId(), m_numGroups); + QueryGroup(1, _requestFlags); + } + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool Association::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - bool handled = false; - uint32 i; - - if( Node* node = GetNodeUnsafe() ) - { - if( AssociationCmd_GroupingsReport == (AssociationCmd)_data[0] ) - { - // Retrieve the number of groups this device supports. - // The groups will be queried with the session data. - m_numGroups = _data[1]; - Log::Write( LogLevel_Info, GetNodeId(), "Received Association Groupings report from node %d. Number of groups is %d", GetNodeId(), m_numGroups ); - ClearStaticRequest( StaticRequest_Values ); - handled = true; - } - else if( AssociationCmd_Report == (AssociationCmd)_data[0] ) - { - // Get the group info - uint8 groupIdx = _data[1]; - uint8 maxAssociations = _data[2]; // If the maxAssociations is zero, this is not a supported group. - uint8 numReportsToFollow = _data[3]; // If a device supports a lot of associations, they may come in more than one message. - - if( maxAssociations ) + bool Association::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) { - if( _length >= 5 ) - { - uint8 numAssociations = _length - 5; + bool handled = false; + uint32 i; - Log::Write( LogLevel_Info, GetNodeId(), "Received Association report from node %d, group %d, containing %d associations", GetNodeId(), groupIdx, numAssociations ); - if( numAssociations ) + if (Node* node = GetNodeUnsafe()) + { + if (AssociationCmd_GroupingsReport == (AssociationCmd) _data[0]) + { + // Retrieve the number of groups this device supports. + // The groups will be queried with the session data. + m_numGroups = _data[1]; + Log::Write(LogLevel_Info, GetNodeId(), "Received Association Groupings report from node %d. Number of groups is %d", GetNodeId(), m_numGroups); + ClearStaticRequest(StaticRequest_Values); + handled = true; + } + else if (AssociationCmd_Report == (AssociationCmd) _data[0]) { - Log::Write( LogLevel_Info, GetNodeId(), " The group contains:" ); - for( i=0; i= 5) + { + uint8 numAssociations = _length - 5; + + Log::Write(LogLevel_Info, GetNodeId(), "Received Association report from node %d, group %d, containing %d associations", GetNodeId(), groupIdx, numAssociations); + if (numAssociations) + { + Log::Write(LogLevel_Info, GetNodeId(), " The group contains:"); + for (i = 0; i < numAssociations; ++i) + { + Log::Write(LogLevel_Info, GetNodeId(), " Node %d", _data[i + 4]); + m_pendingMembers.push_back(_data[i + 4]); + } + } + } + + if (numReportsToFollow) + { + // We're expecting more reports for this group + Log::Write(LogLevel_Info, GetNodeId(), "%d more association reports expected for node %d, group %d", numReportsToFollow, GetNodeId(), groupIdx); + return true; + } + else + { + // No more reports to come for this group, so we can apply the pending list + Group* group = node->GetGroup(groupIdx); + if ( NULL == group) + { + // Group has not been created yet + group = new Group(GetHomeId(), GetNodeId(), groupIdx, maxAssociations); + node->AddGroup(group); + } + + // Update the group with its new contents + group->OnGroupChanged(m_pendingMembers); + m_pendingMembers.clear(); + } + } + else + { + // maxAssociations is zero, so we've reached the end of the query process + Log::Write(LogLevel_Info, GetNodeId(), "Max associations for node %d, group %d is zero. Querying associations for this node is complete.", GetNodeId(), groupIdx); + node->AutoAssociate(); + m_queryAll = false; } - } - } - if( numReportsToFollow ) - { - // We're expecting more reports for this group - Log::Write( LogLevel_Info, GetNodeId(), "%d more association reports expected for node %d, group %d", numReportsToFollow, GetNodeId(), groupIdx ); - return true; - } - else - { - // No more reports to come for this group, so we can apply the pending list - Group* group = node->GetGroup( groupIdx ); - if( NULL == group ) - { - // Group has not been created yet - group = new Group( GetHomeId(), GetNodeId(), groupIdx, maxAssociations ); - node->AddGroup( group ); - } + if (m_queryAll) + { + // Work out which is the next group we will query. + // If we are currently on group 255, the next group will be 1. + uint8 nextGroup = groupIdx + 1; + if (!nextGroup) + { + nextGroup = 1; + } + + if (nextGroup <= m_numGroups) + { + // Query the next group + QueryGroup(nextGroup, 0); + } + else + { + // We're all done + Log::Write(LogLevel_Info, GetNodeId(), "Querying associations for node %d is complete.", GetNodeId()); + node->AutoAssociate(); + m_queryAll = false; + } + } - // Update the group with its new contents - group->OnGroupChanged( m_pendingMembers ); - m_pendingMembers.clear(); + handled = true; + } } - } - else - { - // maxAssociations is zero, so we've reached the end of the query process - Log::Write( LogLevel_Info, GetNodeId(), "Max associations for node %d, group %d is zero. Querying associations for this node is complete.", GetNodeId(), groupIdx ); - node->AutoAssociate(); - m_queryAll = false; + + return handled; } - if( m_queryAll ) +//----------------------------------------------------------------------------- +// +// Request details of an association group +//----------------------------------------------------------------------------- + void Association::QueryGroup(uint8 _groupIdx, uint32 const _requestFlags) { - // Work out which is the next group we will query. - // If we are currently on group 255, the next group will be 1. - uint8 nextGroup = groupIdx + 1; - if( !nextGroup ) + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) { - nextGroup = 1; - } - - if( nextGroup <= m_numGroups ) - { - // Query the next group - QueryGroup( nextGroup, 0 ); + Log::Write(LogLevel_Info, GetNodeId(), "Get Associations for group %d of node %d", _groupIdx, GetNodeId()); + Msg* msg = new Msg("AssociationCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(AssociationCmd_Get); + msg->Append(_groupIdx); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return; } else { - // We're all done - Log::Write( LogLevel_Info, GetNodeId(), "Querying associations for node %d is complete.", GetNodeId() ); - node->AutoAssociate(); - m_queryAll = false; + Log::Write(LogLevel_Info, GetNodeId(), "AssociationCmd_Get Not Supported on this node"); } + return; } - - handled = true; - } - } - - return handled; -} - -//----------------------------------------------------------------------------- -// -// Request details of an association group -//----------------------------------------------------------------------------- -void Association::QueryGroup -( - uint8 _groupIdx, - uint32 const _requestFlags -) -{ - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Log::Write( LogLevel_Info, GetNodeId(), "Get Associations for group %d of node %d", _groupIdx, GetNodeId() ); - Msg* msg = new Msg( "AssociationCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( AssociationCmd_Get ); - msg->Append( _groupIdx ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - return; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "AssociationCmd_Get Not Supported on this node"); - } - return; -} //----------------------------------------------------------------------------- // // Add an association between devices //----------------------------------------------------------------------------- -void Association::Set -( - uint8 _groupIdx, - uint8 _targetNodeId -) -{ - Log::Write( LogLevel_Info, GetNodeId(), "Association::Set - Adding node %d to group %d of node %d", _targetNodeId, _groupIdx, GetNodeId() ); - - Msg* msg = new Msg( "AssociationCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->Append( GetNodeId() ); - msg->Append( 4 ); - msg->Append( GetCommandClassId() ); - msg->Append( AssociationCmd_Set ); - msg->Append( _groupIdx ); - msg->Append( _targetNodeId ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); -} + void Association::Set(uint8 _groupIdx, uint8 _targetNodeId) + { + Log::Write(LogLevel_Info, GetNodeId(), "Association::Set - Adding node %d to group %d of node %d", _targetNodeId, _groupIdx, GetNodeId()); + + Msg* msg = new Msg("AssociationCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->Append(GetNodeId()); + msg->Append(4); + msg->Append(GetCommandClassId()); + msg->Append(AssociationCmd_Set); + msg->Append(_groupIdx); + msg->Append(_targetNodeId); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + } //----------------------------------------------------------------------------- // // Remove an association between devices //----------------------------------------------------------------------------- -void Association::Remove -( - uint8 _groupIdx, - uint8 _targetNodeId -) -{ - Log::Write( LogLevel_Info, GetNodeId(), "Association::Remove - Removing node %d from group %d of node %d", _targetNodeId, _groupIdx, GetNodeId() ); - - Msg* msg = new Msg( "AssociationCmd_Remove", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->Append( GetNodeId() ); - msg->Append( 4 ); - msg->Append( GetCommandClassId() ); - msg->Append( AssociationCmd_Remove ); - msg->Append( _groupIdx ); - msg->Append( _targetNodeId ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); -} + void Association::Remove(uint8 _groupIdx, uint8 _targetNodeId) + { + Log::Write(LogLevel_Info, GetNodeId(), "Association::Remove - Removing node %d from group %d of node %d", _targetNodeId, _groupIdx, GetNodeId()); + + Msg* msg = new Msg("AssociationCmd_Remove", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->Append(GetNodeId()); + msg->Append(4); + msg->Append(GetCommandClassId()); + msg->Append(AssociationCmd_Remove); + msg->Append(_groupIdx); + msg->Append(_targetNodeId); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/Association.h b/cpp/src/command_classes/Association.h index 746b0361d1..ea3dee3ff2 100644 --- a/cpp/src/command_classes/Association.h +++ b/cpp/src/command_classes/Association.h @@ -33,43 +33,65 @@ namespace OpenZWave { - /** \brief Implements COMMAND_CLASS_ASSOCIATION (0x85), a Z-Wave device command class. - *\ingroup CommandClass - */ - class Association: public CommandClass + namespace Internal { - friend class Group; + namespace CC + { + /** \brief Implements COMMAND_CLASS_ASSOCIATION (0x85), a Z-Wave device command class. + *\ingroup CommandClass + */ + class Association: public CommandClass + { + friend class OpenZWave::Group; - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Association( _homeId, _nodeId ); } - virtual ~Association(){} + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new Association(_homeId, _nodeId); + } + virtual ~Association() + { + } - static uint8 const StaticGetCommandClassId(){ return 0x85; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_ASSOCIATION"; } + static uint8 const StaticGetCommandClassId() + { + return 0x85; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_ASSOCIATION"; + } - // From CommandClass - virtual void ReadXML( TiXmlElement const* _ccElement ); - virtual void WriteXML( TiXmlElement* _ccElement ); - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); + // From CommandClass + virtual void ReadXML(TiXmlElement const* _ccElement) override; + virtual void WriteXML(TiXmlElement* _ccElement) override; + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; - void RequestAllGroups( uint32 const _requestFlags ); - void Set( uint8 const _group, uint8 const _nodeId ); - void Remove( uint8 const _group, uint8 const _nodeId ); + void RequestAllGroups(uint32 const _requestFlags); + void Set(uint8 const _group, uint8 const _nodeId); + void Remove(uint8 const _group, uint8 const _nodeId); - private: - Association( uint32 const _homeId, uint8 const _nodeId ); - void QueryGroup( uint8 _groupIdx, uint32 const _requestFlags ); - void AutoAssociate(); - - bool m_queryAll; // When true, once a group has been queried, we request the next one. - uint8 m_numGroups; // Number of groups supported by the device. 255 is reported by certain manufacturers and requires special handling. - vector m_pendingMembers; // Used to build a list of group members from multiple reports - }; + private: + Association(uint32 const _homeId, uint8 const _nodeId); + void QueryGroup(uint8 _groupIdx, uint32 const _requestFlags); + void AutoAssociate(); + bool m_queryAll; // When true, once a group has been queried, we request the next one. + uint8 m_numGroups; // Number of groups supported by the device. 255 is reported by certain manufacturers and requires special handling. + vector m_pendingMembers; // Used to build a list of group members from multiple reports + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/AssociationCommandConfiguration.cpp b/cpp/src/command_classes/AssociationCommandConfiguration.cpp index 0ac07f494c..576441250b 100644 --- a/cpp/src/command_classes/AssociationCommandConfiguration.cpp +++ b/cpp/src/command_classes/AssociationCommandConfiguration.cpp @@ -37,245 +37,216 @@ #include "value_classes/ValueByte.h" #include "value_classes/ValueShort.h" -using namespace OpenZWave; - -enum AssociationCommandConfigurationCmd -{ - AssociationCommandConfigurationCmd_SupportedRecordsGet = 0x01, - AssociationCommandConfigurationCmd_SupportedRecordsReport = 0x02, - AssociationCommandConfigurationCmd_Set = 0x03, - AssociationCommandConfigurationCmd_Get = 0x04, - AssociationCommandConfigurationCmd_Report = 0x05 -}; - -enum +namespace OpenZWave { - AssociationCommandConfigurationIndex_MaxCommandLength = 0, - AssociationCommandConfigurationIndex_CommandsAreValues, - AssociationCommandConfigurationIndex_CommandsAreConfigurable, - AssociationCommandConfigurationIndex_NumFreeCommands, - AssociationCommandConfigurationIndex_MaxCommands -}; + namespace Internal + { + namespace CC + { + enum AssociationCommandConfigurationCmd + { + AssociationCommandConfigurationCmd_SupportedRecordsGet = 0x01, + AssociationCommandConfigurationCmd_SupportedRecordsReport = 0x02, + AssociationCommandConfigurationCmd_Set = 0x03, + AssociationCommandConfigurationCmd_Get = 0x04, + AssociationCommandConfigurationCmd_Report = 0x05 + }; //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool AssociationCommandConfiguration::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _requestFlags & RequestFlag_Session ) - { - return RequestValue( _requestFlags, 0, _instance, _queue ); - } + bool AssociationCommandConfiguration::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_requestFlags & RequestFlag_Session) + { + return RequestValue(_requestFlags, 0, _instance, _queue); + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool AssociationCommandConfiguration::RequestValue -( - uint32 const _requestFlags, - uint16 const _dummy1, // = 0 (not used) - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _instance != 1 ) - { - // This command class doesn't work with multiple instances - return false; - } + bool AssociationCommandConfiguration::RequestValue(uint32 const _requestFlags, uint16 const _dummy1, // = 0 (not used) + uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_instance != 1) + { + // This command class doesn't work with multiple instances + return false; + } - Msg* msg = new Msg( "AssociationCommandConfigurationCmd_SupportedRecordsGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( AssociationCommandConfigurationCmd_SupportedRecordsGet ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; -} + Msg* msg = new Msg("AssociationCommandConfigurationCmd_SupportedRecordsGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(AssociationCommandConfigurationCmd_SupportedRecordsGet); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } //----------------------------------------------------------------------------- // // Request the command data //----------------------------------------------------------------------------- -void AssociationCommandConfiguration::RequestCommands -( - uint8 const _groupIdx, - uint8 const _nodeId -) -{ - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Msg* msg = new Msg( "AssociationCommandConfigurationCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( 4 ); - msg->Append( GetCommandClassId() ); - msg->Append( AssociationCommandConfigurationCmd_Get ); - msg->Append( _groupIdx ); - msg->Append( _nodeId ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - } else { - Log::Write( LogLevel_Info, GetNodeId(), "AssociationCommandConfigurationCmd_Get Not Supported on this node"); - } -} + void AssociationCommandConfiguration::RequestCommands(uint8 const _groupIdx, uint8 const _nodeId) + { + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Msg* msg = new Msg("AssociationCommandConfigurationCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(4); + msg->Append(GetCommandClassId()); + msg->Append(AssociationCommandConfigurationCmd_Get); + msg->Append(_groupIdx); + msg->Append(_nodeId); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "AssociationCommandConfigurationCmd_Get Not Supported on this node"); + } + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool AssociationCommandConfiguration::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if (AssociationCommandConfigurationCmd_SupportedRecordsReport == (AssociationCommandConfigurationCmd)_data[0]) - { - uint8 maxCommandLength = _data[1] >> 2; - bool commandsAreValues = ( (_data[1] & 0x02) != 0 ); - bool commandsAreConfigurable = ( (_data[1] & 0x01) != 0 ); - int16 numFreeCommands = (((int16)_data[2])<<16) | (int16)_data[3]; - int16 maxCommands = (((int16)_data[4])<<16) | (int16)_data[5]; - - Log::Write( LogLevel_Info, GetNodeId(), "Received AssociationCommandConfiguration Supported Records Report:" ); - Log::Write( LogLevel_Info, GetNodeId(), " Maximum command length = %d bytes", maxCommandLength ); - Log::Write( LogLevel_Info, GetNodeId(), " Maximum number of commands = %d", maxCommands ); - Log::Write( LogLevel_Info, GetNodeId(), " Number of free commands = %d", numFreeCommands ); - Log::Write( LogLevel_Info, GetNodeId(), " Commands are %s and are %s", commandsAreValues ? "values" : "not values", commandsAreConfigurable ? "configurable" : "not configurable" ); - - ValueBool* valueBool; - ValueByte* valueByte; - ValueShort* valueShort; - - if( (valueByte = static_cast( GetValue( _instance, AssociationCommandConfigurationIndex_MaxCommandLength ) )) ) - { - valueByte->OnValueRefreshed( maxCommandLength ); - valueByte->Release(); - } - - if( (valueBool = static_cast( GetValue( _instance, AssociationCommandConfigurationIndex_CommandsAreValues ) )) ) - { - valueBool->OnValueRefreshed( commandsAreValues ); - valueBool->Release(); - } - - if( (valueBool = static_cast( GetValue( _instance, AssociationCommandConfigurationIndex_CommandsAreConfigurable ) )) ) - { - valueBool->OnValueRefreshed( commandsAreConfigurable ); - valueBool->Release(); - } - - if( (valueShort = static_cast( GetValue( _instance, AssociationCommandConfigurationIndex_NumFreeCommands ) )) ) - { - valueShort->OnValueRefreshed( numFreeCommands ); - valueShort->Release(); - } - - if( (valueShort = static_cast( GetValue( _instance, AssociationCommandConfigurationIndex_MaxCommands ) )) ) - { - valueShort->OnValueRefreshed( maxCommands ); - valueShort->Release(); - } - return true; - } - - if (AssociationCommandConfigurationCmd_Report == (AssociationCommandConfigurationCmd)_data[0]) - { - uint8 groupIdx = _data[1]; - uint8 nodeIdx = _data[2]; - bool firstReports = ( ( _data[3] & 0x80 ) != 0 ); // True if this is the first message containing commands for this group and node. - uint8 numReports = _data[3] & 0x0f; - - Log::Write( LogLevel_Info, GetNodeId(), "Received AssociationCommandConfiguration Report from:" ); - Log::Write( LogLevel_Info, GetNodeId(), " Commands for node %d in group %d,", nodeIdx, groupIdx ); - - if( Node* node = GetNodeUnsafe() ) - { - Group* group = node->GetGroup( groupIdx ); - if( NULL == group ) + bool AssociationCommandConfiguration::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) { - if( firstReports ) + if (AssociationCommandConfigurationCmd_SupportedRecordsReport == (AssociationCommandConfigurationCmd) _data[0]) { - // This is the first report message, so we should clear any existing command data - group->ClearCommands( nodeIdx ); + uint8 maxCommandLength = _data[1] >> 2; + bool commandsAreValues = ((_data[1] & 0x02) != 0); + bool commandsAreConfigurable = ((_data[1] & 0x01) != 0); + int16 numFreeCommands = (((int16) _data[2]) << 16) | (int16) _data[3]; + int16 maxCommands = (((int16) _data[4]) << 16) | (int16) _data[5]; + + Log::Write(LogLevel_Info, GetNodeId(), "Received AssociationCommandConfiguration Supported Records Report:"); + Log::Write(LogLevel_Info, GetNodeId(), " Maximum command length = %d bytes", maxCommandLength); + Log::Write(LogLevel_Info, GetNodeId(), " Maximum number of commands = %d", maxCommands); + Log::Write(LogLevel_Info, GetNodeId(), " Number of free commands = %d", numFreeCommands); + Log::Write(LogLevel_Info, GetNodeId(), " Commands are %s and are %s", commandsAreValues ? "values" : "not values", commandsAreConfigurable ? "configurable" : "not configurable"); + + Internal::VC::ValueBool* valueBool; + Internal::VC::ValueByte* valueByte; + Internal::VC::ValueShort* valueShort; + + if ((valueByte = static_cast(GetValue(_instance, ValueID_Index_AssociationCommandConfiguration::MaxCommandLength)))) + { + valueByte->OnValueRefreshed(maxCommandLength); + valueByte->Release(); + } + + if ((valueBool = static_cast(GetValue(_instance, ValueID_Index_AssociationCommandConfiguration::CommandsAreValues)))) + { + valueBool->OnValueRefreshed(commandsAreValues); + valueBool->Release(); + } + + if ((valueBool = static_cast(GetValue(_instance, ValueID_Index_AssociationCommandConfiguration::CommandsAreConfigurable)))) + { + valueBool->OnValueRefreshed(commandsAreConfigurable); + valueBool->Release(); + } + + if ((valueShort = static_cast(GetValue(_instance, ValueID_Index_AssociationCommandConfiguration::NumFreeCommands)))) + { + valueShort->OnValueRefreshed(numFreeCommands); + valueShort->Release(); + } + + if ((valueShort = static_cast(GetValue(_instance, ValueID_Index_AssociationCommandConfiguration::MaxCommands)))) + { + valueShort->OnValueRefreshed(maxCommands); + valueShort->Release(); + } + return true; } - uint8 const* start = &_data[4]; - - for( uint8 i=0; iAddCommand( nodeIdx, length, start+1 ); - start += length; + uint8 groupIdx = _data[1]; + uint8 nodeIdx = _data[2]; + bool firstReports = ((_data[3] & 0x80) != 0); // True if this is the first message containing commands for this group and node. + uint8 numReports = _data[3] & 0x0f; + + Log::Write(LogLevel_Info, GetNodeId(), "Received AssociationCommandConfiguration Report from:"); + Log::Write(LogLevel_Info, GetNodeId(), " Commands for node %d in group %d,", nodeIdx, groupIdx); + + if (Node* node = GetNodeUnsafe()) + { + Group* group = node->GetGroup(groupIdx); + if ( NULL == group) + { + if (firstReports) + { + // This is the first report message, so we should clear any existing command data + group->ClearCommands(nodeIdx); + } + + uint8 const* start = &_data[4]; + + for (uint8 i = 0; i < numReports; ++i) + { + uint8 length = start[0]; + group->AddCommand(nodeIdx, length, start + 1); + start += length; + } + } + } + + return true; } + return false; } - } - - return true; - } - return false; -} //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void AssociationCommandConfiguration::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - node->CreateValueByte ( ValueID::ValueGenre_System, GetCommandClassId(), _instance, AssociationCommandConfigurationIndex_MaxCommandLength, "Max Command Length", "", true, false, 0, 0 ); - node->CreateValueBool ( ValueID::ValueGenre_System, GetCommandClassId(), _instance, AssociationCommandConfigurationIndex_CommandsAreValues, "Commands are Values", "", true, false, false, 0 ); - node->CreateValueBool ( ValueID::ValueGenre_System, GetCommandClassId(), _instance, AssociationCommandConfigurationIndex_CommandsAreConfigurable, "Commands are Configurable", "", true, false, false, 0 ); - node->CreateValueShort( ValueID::ValueGenre_System, GetCommandClassId(), _instance, AssociationCommandConfigurationIndex_NumFreeCommands, "Free Commands", "", true, false, 0, 0 ); - node->CreateValueShort( ValueID::ValueGenre_System, GetCommandClassId(), _instance, AssociationCommandConfigurationIndex_MaxCommands, "Max Commands", "", true, false, 0, 0 ); - } -} + void AssociationCommandConfiguration::CreateVars(uint8 const _instance) + { + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueByte(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_AssociationCommandConfiguration::MaxCommandLength, "Max Command Length", "", true, false, 0, 0); + node->CreateValueBool(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_AssociationCommandConfiguration::CommandsAreValues, "Commands are Values", "", true, false, false, 0); + node->CreateValueBool(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_AssociationCommandConfiguration::CommandsAreConfigurable, "Commands are Configurable", "", true, false, false, 0); + node->CreateValueShort(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_AssociationCommandConfiguration::NumFreeCommands, "Free Commands", "", true, false, 0, 0); + node->CreateValueShort(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_AssociationCommandConfiguration::MaxCommands, "Max Commands", "", true, false, 0, 0); + } + } //----------------------------------------------------------------------------- // // Set a command for the association //----------------------------------------------------------------------------- -void AssociationCommandConfiguration::SetCommand -( - uint8 const _groupIdx, - uint8 const _nodeId, - uint8 const _length, - uint8 const* _data -) -{ - Msg* msg = new Msg( "AssociationCommandConfigurationCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( _length + 5 ); - msg->Append( GetCommandClassId() ); - msg->Append( AssociationCommandConfigurationCmd_Set ); - msg->Append( _groupIdx ); - msg->Append( _nodeId ); - msg->Append( _length ); - - for( uint8 i=0; i<_length; ++i ) - { - msg->Append( _data[i] ); - } - - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); -} - + void AssociationCommandConfiguration::SetCommand(uint8 const _groupIdx, uint8 const _nodeId, uint8 const _length, uint8 const* _data) + { + Msg* msg = new Msg("AssociationCommandConfigurationCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(_length + 5); + msg->Append(GetCommandClassId()); + msg->Append(AssociationCommandConfigurationCmd_Set); + msg->Append(_groupIdx); + msg->Append(_nodeId); + msg->Append(_length); + + for (uint8 i = 0; i < _length; ++i) + { + msg->Append(_data[i]); + } + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/AssociationCommandConfiguration.h b/cpp/src/command_classes/AssociationCommandConfiguration.h index 1d0a72efff..900aff03b0 100644 --- a/cpp/src/command_classes/AssociationCommandConfiguration.h +++ b/cpp/src/command_classes/AssociationCommandConfiguration.h @@ -33,39 +33,63 @@ #include "value_classes/ValueByte.h" #include "value_classes/ValueShort.h" - namespace OpenZWave { - /** \brief Implements COMMAND_CLASS_ASSOCIATION_COMMAND_CONFIGURATION (0x9b), a Z-Wave device command class. - * \ingroup CommandClass - */ - - class AssociationCommandConfiguration: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new AssociationCommandConfiguration( _homeId, _nodeId ); } - virtual ~AssociationCommandConfiguration(){} + namespace CC + { + /** \brief Implements COMMAND_CLASS_ASSOCIATION_COMMAND_CONFIGURATION (0x9b), a Z-Wave device command class. + * \ingroup CommandClass + */ + + class AssociationCommandConfiguration: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new AssociationCommandConfiguration(_homeId, _nodeId); + } + virtual ~AssociationCommandConfiguration() + { + } - static uint8 const StaticGetCommandClassId(){ return 0x9b; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_ASSOCIATION_COMMAND_CONFIGURATION"; } - - void RequestCommands( uint8 const _groupIdx, uint8 const _nodeId ); - void SetCommand( uint8 const _groupIdx, uint8 const _nodeId, uint8 const _length, uint8 const* _data ); + static uint8 const StaticGetCommandClassId() + { + return 0x9b; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_ASSOCIATION_COMMAND_CONFIGURATION"; + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); + void RequestCommands(uint8 const _groupIdx, uint8 const _nodeId); + void SetCommand(uint8 const _groupIdx, uint8 const _nodeId, uint8 const _length, uint8 const* _data); - protected: - virtual void CreateVars( uint8 const _instance ); + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; - private: - AssociationCommandConfiguration( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} - }; + protected: + virtual void CreateVars(uint8 const _instance) override; + private: + AssociationCommandConfiguration(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + } + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/BarrierOperator.cpp b/cpp/src/command_classes/BarrierOperator.cpp index 92d291e822..6090c12870 100644 --- a/cpp/src/command_classes/BarrierOperator.cpp +++ b/cpp/src/command_classes/BarrierOperator.cpp @@ -36,410 +36,373 @@ #include "value_classes/ValueByte.h" #include "value_classes/ValueBool.h" -using namespace OpenZWave; - -enum BarrierOperatorCmd -{ - BarrierOperatorCmd_Set = 0x01, - BarrierOperatorCmd_Get = 0x02, - BarrierOperatorCmd_Report = 0x03, - BarrierOperatorCmd_SignalSupportedGet = 0x04, - BarrierOperatorCmd_SignalSupportedReport = 0x05, - BarrierOperatorCmd_SignalSet = 0x06, - BarrierOperatorCmd_SignalGet = 0x07, - BarrierOperatorCmd_SignalReport = 0x08 -}; - -enum BarrierOperatorState +namespace OpenZWave { - BarrierOperatorState_Closed = 0x00, - BarrierOperatorState_Closing = 0xFC, - BarrierOperatorState_Stopped = 0xFD, - BarrierOperatorState_Opening = 0xFE, - BarrierOperatorState_Open = 0xFF, -}; + namespace Internal + { + namespace CC + { -enum BarrierOperator_SignalAttributesMask -{ - BarrierOperatorSignalMask_Audible = 0x01, - BarrierOperatorSignalMask_Visual = 0x02, - BarrierOperatorSignalMask_All = 0x03 -}; + enum BarrierOperatorCmd + { + BarrierOperatorCmd_Set = 0x01, + BarrierOperatorCmd_Get = 0x02, + BarrierOperatorCmd_Report = 0x03, + BarrierOperatorCmd_SignalSupportedGet = 0x04, + BarrierOperatorCmd_SignalSupportedReport = 0x05, + BarrierOperatorCmd_SignalSet = 0x06, + BarrierOperatorCmd_SignalGet = 0x07, + BarrierOperatorCmd_SignalReport = 0x08 + }; -enum BarrierOperatorCmd_Indexes -{ - BarrierOperatorCmd_Index = 0x00, - BarrierOperatorLabel_Index = 0x01, - BarrierOperatorSupportedSignals_Index = 0x02, - BarrierOperatorAudible_Index = 0x03, - BarrierOperatorVisual_Index = 0x04, -}; + enum BarrierOperatorState + { + BarrierOperatorState_Closed = 0x00, + BarrierOperatorState_Closing = 0xFC, + BarrierOperatorState_Stopped = 0xFD, + BarrierOperatorState_Opening = 0xFE, + BarrierOperatorState_Open = 0xFF, + }; -static char const* c_BarrierOperator_States[] = -{ - "Closed", - "Closing", - "Stopped", - "Opening", - "Opened", - "Unknown" -}; + enum BarrierOperator_SignalAttributesMask + { + BarrierOperatorSignalMask_Audible = 0x01, + BarrierOperatorSignalMask_Visual = 0x02, + BarrierOperatorSignalMask_All = 0x03 + }; -static char const *c_BarrierOperator_Signals[] = -{ - "None", - "Audible", - "Visual", - "Both" -}; + static char const* c_BarrierOperator_States[] = + { "Closed", "Closing", "Stopped", "Opening", "Opened", "Unknown" }; -BarrierOperator::BarrierOperator -( - uint32 const _homeId, - uint8 const _nodeId -): -CommandClass( _homeId, _nodeId ) -{ + static char const *c_BarrierOperator_Signals[] = + { "None", "Audible", "Visual", "Both" }; -} + BarrierOperator::BarrierOperator(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + } //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool BarrierOperator::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - bool res = false; - if( _requestFlags & RequestFlag_Dynamic ) - { - res |= RequestValue( _requestFlags, BarrierOperatorCmd_Index, _instance, _queue ); - } - if ( _requestFlags & RequestFlag_Static ) - { - res |= RequestValue( _requestFlags, BarrierOperatorSupportedSignals_Index, _instance, _queue ); - } + bool BarrierOperator::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + bool res = false; + if (_requestFlags & RequestFlag_Dynamic) + { + res |= RequestValue(_requestFlags, ValueID_Index_BarrierOperator::Command, _instance, _queue); + } + if (_requestFlags & RequestFlag_Static) + { + res |= RequestValue(_requestFlags, ValueID_Index_BarrierOperator::SupportedSignals, _instance, _queue); + } - return res; -} + return res; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool BarrierOperator::RequestValue -( - uint32 const _requestFlags, - uint16 const _index, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if (_index == BarrierOperatorCmd_Index) - { - Msg* msg = new Msg("BarrierOperatorCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); - msg->SetInstance(this, _instance); - msg->Append(GetNodeId()); - msg->Append(2); - msg->Append(GetCommandClassId()); - msg->Append(BarrierOperatorCmd_Get); - msg->Append(GetDriver()->GetTransmitOptions()); - GetDriver()->SendMsg(msg, _queue); - return true; - } - else if ( _index == BarrierOperatorAudible_Index ) - { - Msg* msg = new Msg("BarrierOperatorCmd_SignalGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); - msg->SetInstance(this, _instance); - msg->Append(GetNodeId()); - msg->Append(3); - msg->Append(GetCommandClassId()); - msg->Append(BarrierOperatorCmd_SignalGet); - msg->Append(0x01); - msg->Append(GetDriver()->GetTransmitOptions()); - GetDriver()->SendMsg(msg, _queue); - return true; - } - else if (_index == BarrierOperatorVisual_Index) - { - Msg* msg = new Msg("BarrierOperatorCmd_SignalGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); - msg->SetInstance(this, _instance); - msg->Append(GetNodeId()); - msg->Append(3); - msg->Append(GetCommandClassId()); - msg->Append(BarrierOperatorCmd_SignalGet); - msg->Append(0x02); - msg->Append(GetDriver()->GetTransmitOptions()); - GetDriver()->SendMsg(msg, _queue); - return true; - } - else if (_index == BarrierOperatorSupportedSignals_Index) - { - Msg* msg = new Msg("BarrierOperatorCmd_SignalSupportedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); - msg->SetInstance(this, _instance); - msg->Append(GetNodeId()); - msg->Append(2); - msg->Append(GetCommandClassId()); - msg->Append(BarrierOperatorCmd_SignalSupportedGet); - msg->Append(GetDriver()->GetTransmitOptions()); - GetDriver()->SendMsg(msg, _queue); - return true; - } - return false; -} - + bool BarrierOperator::RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_index == ValueID_Index_BarrierOperator::Command) + { + Msg* msg = new Msg("BarrierOperatorCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(BarrierOperatorCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else if (_index == ValueID_Index_BarrierOperator::Audible) + { + Msg* msg = new Msg("BarrierOperatorCmd_SignalGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(BarrierOperatorCmd_SignalGet); + msg->Append(0x01); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else if (_index == ValueID_Index_BarrierOperator::Visual) + { + Msg* msg = new Msg("BarrierOperatorCmd_SignalGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(BarrierOperatorCmd_SignalGet); + msg->Append(0x02); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else if (_index == ValueID_Index_BarrierOperator::SupportedSignals) + { + Msg* msg = new Msg("BarrierOperatorCmd_SignalSupportedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(BarrierOperatorCmd_SignalSupportedGet); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool BarrierOperator::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if (BarrierOperatorCmd_Report == (BarrierOperatorCmd)_data[0]) - { - uint8 state_index = 5; - switch (_data[1]) - { - case BarrierOperatorState_Closed: - { - state_index = 0; - break; - } - case BarrierOperatorState_Closing: - { - state_index = 1; - break; - } - case BarrierOperatorState_Stopped: - { - state_index = 2; - break; - } - case BarrierOperatorState_Opening: - { - state_index = 3; - break; - } - case BarrierOperatorState_Open: - { - state_index = 4; - break; - } - default: + bool BarrierOperator::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) { - Log::Write(LogLevel_Warning, GetNodeId(), "Received Invalid BarrierOperatorState %d", _data[1]); - break; - } - } + if (BarrierOperatorCmd_Report == (BarrierOperatorCmd) _data[0]) + { + uint8 state_index = 5; + switch (_data[1]) + { + case BarrierOperatorState_Closed: + { + state_index = 0; + break; + } + case BarrierOperatorState_Closing: + { + state_index = 1; + break; + } + case BarrierOperatorState_Stopped: + { + state_index = 2; + break; + } + case BarrierOperatorState_Opening: + { + state_index = 3; + break; + } + case BarrierOperatorState_Open: + { + state_index = 4; + break; + } + default: + { + Log::Write(LogLevel_Warning, GetNodeId(), "Received Invalid BarrierOperatorState %d", _data[1]); + break; + } + } - if( ValueList* value = static_cast( GetValue( _instance, BarrierOperatorLabel_Index ) ) ) - { - value->OnValueRefreshed( state_index ); - value->Release(); - } else { - Log::Write( LogLevel_Warning, GetNodeId(), "No ValueID created for BarrierOperator state"); - return false; - } - return true; - } - if (BarrierOperatorCmd_SignalSupportedReport == (BarrierOperatorCmd)_data[0]) - { + if (Internal::VC::ValueList* value = static_cast(GetValue(_instance, ValueID_Index_BarrierOperator::Label))) + { + value->OnValueRefreshed(state_index); + value->Release(); + } + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "No ValueID created for BarrierOperator state"); + return false; + } + return true; + } + if (BarrierOperatorCmd_SignalSupportedReport == (BarrierOperatorCmd) _data[0]) + { - Log::Write(LogLevel_Info, GetNodeId(), "Received BarrierOperator Signal Support Report"); - uint8 state_index = 0; - uint8 data = _data[1]; + Log::Write(LogLevel_Info, GetNodeId(), "Received BarrierOperator Signal Support Report"); + uint8 state_index = 0; + uint8 data = _data[1]; - /* Aeotec GDC shifts the SupportedReport by one, so we have to shift back */ - if (data > 3) - { - Log::Write(LogLevel_Warning, GetNodeId(), "SignalSupportedReport is out of Range. Shifting Right"); - data = data >> 1; - } - switch (data) - { - case BarrierOperatorSignalMask_Audible: - { - state_index = 1; - RequestValue( 0, BarrierOperatorAudible_Index , _instance, Driver::MsgQueue_Send ); - break; - } - case BarrierOperatorSignalMask_Visual: - { - state_index = 2; - RequestValue( 0, BarrierOperatorVisual_Index , _instance, Driver::MsgQueue_Send ); - break; - } + /* Aeotec GDC shifts the SupportedReport by one, so we have to shift back */ + if (data > 3) + { + Log::Write(LogLevel_Warning, GetNodeId(), "SignalSupportedReport is out of Range. Shifting Right"); + data = data >> 1; + } + switch (data) + { + case BarrierOperatorSignalMask_Audible: + { + state_index = 1; + RequestValue(0, ValueID_Index_BarrierOperator::Audible, _instance, Driver::MsgQueue_Send); + break; + } + case BarrierOperatorSignalMask_Visual: + { + state_index = 2; + RequestValue(0, ValueID_Index_BarrierOperator::Visual, _instance, Driver::MsgQueue_Send); + break; + } - case BarrierOperatorSignalMask_All: - { - state_index = 3; - RequestValue( 0, BarrierOperatorAudible_Index , _instance, Driver::MsgQueue_Send ); - RequestValue( 0, BarrierOperatorVisual_Index , _instance, Driver::MsgQueue_Send ); - break; - } - default: - { - Log::Write(LogLevel_Warning, GetNodeId(), "Received Invalid SignalSupported Report: %d", _data[1]); - break; - } - } - if( ValueList* value = static_cast( GetValue( _instance, BarrierOperatorSupportedSignals_Index ) ) ) - { - value->OnValueRefreshed( state_index ); - value->Release(); + case BarrierOperatorSignalMask_All: + { + state_index = 3; + RequestValue(0, ValueID_Index_BarrierOperator::Audible, _instance, Driver::MsgQueue_Send); + RequestValue(0, ValueID_Index_BarrierOperator::Visual, _instance, Driver::MsgQueue_Send); + break; + } + default: + { + Log::Write(LogLevel_Warning, GetNodeId(), "Received Invalid SignalSupported Report: %d", _data[1]); + break; + } + } + if (Internal::VC::ValueList* value = static_cast(GetValue(_instance, ValueID_Index_BarrierOperator::SupportedSignals))) + { + value->OnValueRefreshed(state_index); + value->Release(); - } else { - Log::Write( LogLevel_Warning, GetNodeId(), "No ValueID created for BarrierOperator SupportedSignals"); - return false; - } - return true; - } - if (BarrierOperatorCmd_SignalReport == (BarrierOperatorCmd)_data[0]) - { - if (_data[1] & 0x01) - { - Log::Write(LogLevel_Info, GetNodeId(), "Received BarrierOperator Signal Report for Audible"); - if (ValueBool* value = static_cast(GetValue(_instance, 3))) - { - value->OnValueRefreshed(_data[2] == 0xFF ? true : false); - value->Release(); - } - } - if (_data[1] & 0x02) - { - Log::Write(LogLevel_Info, GetNodeId(), "Received BarrierOperator Signal Report for Visual"); - if (ValueBool* value = static_cast(GetValue(_instance, 4))) - { - value->OnValueRefreshed(_data[2] == 0xFF ? true : false ); - value->Release(); - } - } - return true; - } + } + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "No ValueID created for BarrierOperator SupportedSignals"); + return false; + } + return true; + } + if (BarrierOperatorCmd_SignalReport == (BarrierOperatorCmd) _data[0]) + { + if (_data[1] & 0x01) + { + Log::Write(LogLevel_Info, GetNodeId(), "Received BarrierOperator Signal Report for Audible"); + if (Internal::VC::ValueBool* value = static_cast(GetValue(_instance, ValueID_Index_BarrierOperator::Audible))) + { + value->OnValueRefreshed(_data[2] == 0xFF ? true : false); + value->Release(); + } + } + if (_data[1] & 0x02) + { + Log::Write(LogLevel_Info, GetNodeId(), "Received BarrierOperator Signal Report for Visual"); + if (Internal::VC::ValueBool* value = static_cast(GetValue(_instance, ValueID_Index_BarrierOperator::Visual))) + { + value->OnValueRefreshed(_data[2] == 0xFF ? true : false); + value->Release(); + } + } + return true; + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Set a value //----------------------------------------------------------------------------- -bool BarrierOperator::SetValue -( - Value const& _value - ) -{ - uint8 idx = (uint8_t)(_value.GetID().GetIndex() & 0xFF); - if (ValueID::ValueType_List == _value.GetID().GetType()) - { - if (idx == BarrierOperatorLabel_Index) - { - ValueList const* value = static_cast(&_value); - const ValueList::Item *item = value->GetItem(); - uint8 position = BarrierOperatorState_Closed; - if (item->m_value > 0) - position = BarrierOperatorState_Open; - Log::Write(LogLevel_Info, GetNodeId(), "BarrierOperator::Set - Requesting barrier to be %s", position > 0 ? "Open" : "Closed"); - Msg* msg = new Msg("BarrierOperatorCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); - msg->SetInstance(this, _value.GetID().GetInstance()); - msg->Append(GetNodeId()); - msg->Append(3); - msg->Append(GetCommandClassId()); - msg->Append(BarrierOperatorCmd_Set); - msg->Append(position); - msg->Append(GetDriver()->GetTransmitOptions()); - GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); - return true; - } - } - if (ValueID::ValueType_Bool == _value.GetID().GetType()) - { - if (idx == BarrierOperatorAudible_Index) - { - ValueBool const* value = static_cast(&_value); - Log::Write(LogLevel_Info, GetNodeId(), "BarrierOperatorSignal::Set - Requesting Audible to be %s", value->GetValue() ? "ON" : "OFF"); - Msg* msg = new Msg("BarrierOperatorSignalCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); - msg->SetInstance(this, _value.GetID().GetInstance()); - msg->Append(GetNodeId()); - msg->Append(4); - msg->Append(GetCommandClassId()); - msg->Append(BarrierOperatorCmd_SignalSet); - msg->Append(BarrierOperatorSignalMask_Audible); - msg->Append(value->GetValue() ? 0xFF : 0x00); - msg->Append(GetDriver()->GetTransmitOptions()); - GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); - return true; - } - else if (idx == BarrierOperatorVisual_Index) - { - ValueBool const* value = static_cast(&_value); - Log::Write(LogLevel_Info, GetNodeId(), "BarrierOperatorSignal::Set - Requesting Visual to be %s", value->GetValue() ? "ON" : "OFF"); - Msg* msg = new Msg("BarrierOperatorSignalCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); - msg->SetInstance(this, _value.GetID().GetInstance()); - msg->Append(GetNodeId()); - msg->Append(4); - msg->Append(GetCommandClassId()); - msg->Append(BarrierOperatorCmd_SignalSet); - msg->Append(BarrierOperatorSignalMask_Visual); - msg->Append(value->GetValue() ? 0xFF : 0x00); - msg->Append(GetDriver()->GetTransmitOptions()); - GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); - return true; - } - } - return false; -} + bool BarrierOperator::SetValue(Internal::VC::Value const& _value) + { + uint8 idx = (uint8_t) (_value.GetID().GetIndex() & 0xFF); + if (ValueID::ValueType_List == _value.GetID().GetType()) + { + if (idx == ValueID_Index_BarrierOperator::Label) + { + Internal::VC::ValueList const* value = static_cast(&_value); + const Internal::VC::ValueList::Item *item = value->GetItem(); + uint8 position = BarrierOperatorState_Closed; + if (item->m_value > 0) + position = BarrierOperatorState_Open; + Log::Write(LogLevel_Info, GetNodeId(), "BarrierOperator::Set - Requesting barrier to be %s", position > 0 ? "Open" : "Closed"); + Msg* msg = new Msg("BarrierOperatorCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->SetInstance(this, _value.GetID().GetInstance()); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(BarrierOperatorCmd_Set); + msg->Append(position); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return true; + } + } + if (ValueID::ValueType_Bool == _value.GetID().GetType()) + { + if (idx == ValueID_Index_BarrierOperator::Audible) + { + Internal::VC::ValueBool const* value = static_cast(&_value); + Log::Write(LogLevel_Info, GetNodeId(), "BarrierOperatorSignal::Set - Requesting Audible to be %s", value->GetValue() ? "ON" : "OFF"); + Msg* msg = new Msg("BarrierOperatorSignalCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->SetInstance(this, _value.GetID().GetInstance()); + msg->Append(GetNodeId()); + msg->Append(4); + msg->Append(GetCommandClassId()); + msg->Append(BarrierOperatorCmd_SignalSet); + msg->Append(BarrierOperatorSignalMask_Audible); + msg->Append(value->GetValue() ? 0xFF : 0x00); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return true; + } + else if (idx == ValueID_Index_BarrierOperator::Visual) + { + Internal::VC::ValueBool const* value = static_cast(&_value); + Log::Write(LogLevel_Info, GetNodeId(), "BarrierOperatorSignal::Set - Requesting Visual to be %s", value->GetValue() ? "ON" : "OFF"); + Msg* msg = new Msg("BarrierOperatorSignalCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->SetInstance(this, _value.GetID().GetInstance()); + msg->Append(GetNodeId()); + msg->Append(4); + msg->Append(GetCommandClassId()); + msg->Append(BarrierOperatorCmd_SignalSet); + msg->Append(BarrierOperatorSignalMask_Visual); + msg->Append(value->GetValue() ? 0xFF : 0x00); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return true; + } + } + return false; + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void BarrierOperator::CreateVars -( - uint8 const _instance -) -{ - if (Node* node = GetNodeUnsafe()) - { - { - vector items; - unsigned int size = (sizeof(c_BarrierOperator_States)/sizeof(c_BarrierOperator_States[0])); - for( unsigned int i=0; i < size; i++) - { - ValueList::Item item; - item.m_label = c_BarrierOperator_States[i]; - item.m_value = i; - items.push_back( item ); - } - node->CreateValueList( ValueID::ValueGenre_User, GetCommandClassId(), _instance, BarrierOperatorLabel_Index, "Barrier State", "", false, false, size, items, 0, 0 ); - } - { - vector items; - unsigned int size = (sizeof(c_BarrierOperator_Signals)/sizeof(c_BarrierOperator_Signals[0])); - for( unsigned int i=0; i < size; i++) + void BarrierOperator::CreateVars(uint8 const _instance) { - ValueList::Item item; - item.m_label = c_BarrierOperator_Signals[i]; - item.m_value = i; - items.push_back( item ); - } - node->CreateValueList( ValueID::ValueGenre_Config, GetCommandClassId(), _instance, BarrierOperatorSupportedSignals_Index, "Supported Signals", "", true, false, size, items, 0, 0 ); - } - node->CreateValueBool(ValueID::ValueGenre_Config, GetCommandClassId(), _instance, BarrierOperatorAudible_Index, "Audible Notification", "", false, false, false, 0); - node->CreateValueBool(ValueID::ValueGenre_Config, GetCommandClassId(), _instance, BarrierOperatorVisual_Index, "Visual Notification", "", false, false, false, 0); + if (Node* node = GetNodeUnsafe()) + { + { + std::vector items; + unsigned int size = (sizeof(c_BarrierOperator_States) / sizeof(c_BarrierOperator_States[0])); + for (unsigned int i = 0; i < size; i++) + { + Internal::VC::ValueList::Item item; + item.m_label = c_BarrierOperator_States[i]; + item.m_value = i; + items.push_back(item); + } + node->CreateValueList(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_BarrierOperator::Label, "Barrier State", "", false, false, size, items, 0, 0); + } + { + std::vector items; + unsigned int size = (sizeof(c_BarrierOperator_Signals) / sizeof(c_BarrierOperator_Signals[0])); + for (unsigned int i = 0; i < size; i++) + { + Internal::VC::ValueList::Item item; + item.m_label = c_BarrierOperator_Signals[i]; + item.m_value = i; + items.push_back(item); + } + node->CreateValueList(ValueID::ValueGenre_Config, GetCommandClassId(), _instance, ValueID_Index_BarrierOperator::SupportedSignals, "Supported Signals", "", true, false, size, items, 0, 0); + } + node->CreateValueBool(ValueID::ValueGenre_Config, GetCommandClassId(), _instance, ValueID_Index_BarrierOperator::Audible, "Audible Notification", "", false, false, false, 0); + node->CreateValueBool(ValueID::ValueGenre_Config, GetCommandClassId(), _instance, ValueID_Index_BarrierOperator::Visual, "Visual Notification", "", false, false, false, 0); - - } -} + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/BarrierOperator.h b/cpp/src/command_classes/BarrierOperator.h index 37ca3a2566..163e96cbda 100644 --- a/cpp/src/command_classes/BarrierOperator.h +++ b/cpp/src/command_classes/BarrierOperator.h @@ -32,39 +32,61 @@ namespace OpenZWave { - class ValueByte; - class ValueBool; - - /** \brief Implements COMMAND_CLASS_BARRIER_OPERATOR (0x66), a Z-Wave device command class. - * \ingroup CommandClass - */ - class BarrierOperator: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new BarrierOperator( _homeId, _nodeId ); } - virtual ~BarrierOperator(){} - - static uint8 const StaticGetCommandClassId(){ return 0x66; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_BARRIER_OPERATOR"; } + namespace CC + { + /** \brief Implements COMMAND_CLASS_BARRIER_OPERATOR (0x66), a Z-Wave device command class. + * \ingroup CommandClass + */ + class BarrierOperator: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new BarrierOperator(_homeId, _nodeId); + } + virtual ~BarrierOperator() + { + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - bool RequestSignalSupport( uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool SetValue(Value const& _value); + static uint8 const StaticGetCommandClassId() + { + return 0x66; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_BARRIER_OPERATOR"; + } - virtual uint8 GetMaxVersion(){ return 3; } + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + bool RequestSignalSupport(uint8 const _instance, Driver::MsgQueue const _queue); + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool SetValue(Internal::VC::Value const& _value) override; - protected: - virtual void CreateVars( uint8 const _instance ); + virtual uint8 GetMaxVersion() override + { + return 3; + } - private: - BarrierOperator( uint32 const _homeId, uint8 const _nodeId ); - }; + protected: + virtual void CreateVars(uint8 const _instance) override; + private: + BarrierOperator(uint32 const _homeId, uint8 const _nodeId); + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/Basic.cpp b/cpp/src/command_classes/Basic.cpp index 91daa8991c..188ed6dc6f 100644 --- a/cpp/src/command_classes/Basic.cpp +++ b/cpp/src/command_classes/Basic.cpp @@ -40,270 +40,257 @@ #include "tinyxml.h" -using namespace OpenZWave; - -enum BasicCmd +namespace OpenZWave { - BasicCmd_Set = 0x01, - BasicCmd_Get = 0x02, - BasicCmd_Report = 0x03 -}; + namespace Internal + { + namespace CC + { + + enum BasicCmd + { + BasicCmd_Set = 0x01, + BasicCmd_Get = 0x02, + BasicCmd_Report = 0x03 + }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -Basic::Basic -( - uint32 const _homeId, - uint8 const _nodeId -): - CommandClass( _homeId, _nodeId ) -{ - m_com.EnableFlag(COMPAT_FLAG_BASIC_IGNOREREMAPPING, false); - m_com.EnableFlag(COMPAT_FLAG_BASIC_MAPPING, 0); - m_com.EnableFlag(COMPAT_FLAG_BASIC_SETASREPORT, false); -} + Basic::Basic(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + m_com.EnableFlag(COMPAT_FLAG_BASIC_IGNOREREMAPPING, false); + m_com.EnableFlag(COMPAT_FLAG_BASIC_MAPPING, 0); + m_com.EnableFlag(COMPAT_FLAG_BASIC_SETASREPORT, false); + } //----------------------------------------------------------------------------- // // Read configuration. //----------------------------------------------------------------------------- -void Basic::ReadXML -( - TiXmlElement const* _ccElement -) -{ - CommandClass::ReadXML( _ccElement ); - SetMapping(m_com.GetFlagByte(COMPAT_FLAG_BASIC_MAPPING), false); -} - + void Basic::ReadXML(TiXmlElement const* _ccElement) + { + CommandClass::ReadXML(_ccElement); + SetMapping(m_com.GetFlagByte(COMPAT_FLAG_BASIC_MAPPING), false); + } //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool Basic::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if (IsAfterMark()) - { - Log::Write (LogLevel_Info, GetNodeId(), "Controlled Class"); - return false; - } - if( _requestFlags & RequestFlag_Dynamic ) - { - if ((m_com.GetFlagBool(COMPAT_FLAG_BASIC_IGNOREREMAPPING) || (!m_com.GetFlagBool(COMPAT_FLAG_BASIC_IGNOREREMAPPING) && m_com.GetFlagByte(COMPAT_FLAG_BASIC_MAPPING) == 0))) - return RequestValue( _requestFlags, 0, _instance, _queue ); - } - return false; -} + bool Basic::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (IsAfterMark()) + { + Log::Write(LogLevel_Info, GetNodeId(), "Controlled Class"); + return false; + } + if (_requestFlags & RequestFlag_Dynamic) + { + if ((m_com.GetFlagBool(COMPAT_FLAG_BASIC_IGNOREREMAPPING) || (!m_com.GetFlagBool(COMPAT_FLAG_BASIC_IGNOREREMAPPING) && m_com.GetFlagByte(COMPAT_FLAG_BASIC_MAPPING) == 0))) + return RequestValue(_requestFlags, ValueID_Index_Basic::Set, _instance, _queue); + } + return false; + } //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool Basic::RequestValue -( - uint32 const _requestFlags, - uint16 const _dummy1, // = 0 (not used) - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Msg* msg = new Msg( "BasicCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( BasicCmd_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "BasicCmd_Get Not Supported on this node"); - } - return false; -} + bool Basic::RequestValue(uint32 const _requestFlags, uint16 const _dummy1, // = 0 (not used) + uint8 const _instance, Driver::MsgQueue const _queue) + { + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Msg* msg = new Msg("BasicCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(BasicCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "BasicCmd_Get Not Supported on this node"); + } + return false; + } + + bool Basic::HandleIncomingMsg(uint8 const* _data, uint32 const _length, uint32 const _instance + ) + { + /* just redirect to the HandleMsg Method */ + return HandleMsg(_data, _length, _instance); + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool Basic::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if( BasicCmd_Report == (BasicCmd)_data[0] ) - { - // Level - Log::Write( LogLevel_Info, GetNodeId(), "Received Basic report from node %d: level=%d", GetNodeId(), _data[1] ); - if( !m_com.GetFlagBool(COMPAT_FLAG_BASIC_IGNOREREMAPPING) && m_com.GetFlagByte(COMPAT_FLAG_BASIC_MAPPING) != 0 ) - { - UpdateMappedClass( _instance, m_com.GetFlagByte(COMPAT_FLAG_BASIC_MAPPING), _data[1] ); - } - else if( ValueByte* value = static_cast( GetValue( _instance, 0 ) ) ) - { - value->OnValueRefreshed( _data[1] ); - value->Release(); - } else { - Log::Write(LogLevel_Warning, GetNodeId(), "No Valid Mapping for Basic Command Class and No ValueID Exported. Error?"); - } - return true; - } - - if( BasicCmd_Set == (BasicCmd)_data[0] ) - { - if( m_com.GetFlagBool(COMPAT_FLAG_BASIC_SETASREPORT) ) - { - Log::Write( LogLevel_Info, GetNodeId(), "Received Basic set from node %d: level=%d. Treating it as a Basic report.", GetNodeId(), _data[1] ); - if( !m_com.GetFlagBool(COMPAT_FLAG_BASIC_IGNOREREMAPPING) && m_com.GetFlagByte(COMPAT_FLAG_BASIC_MAPPING) != 0 ) + bool Basic::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) { - UpdateMappedClass( _instance, m_com.GetFlagByte(COMPAT_FLAG_BASIC_MAPPING), _data[1] ); - } - else if( ValueByte* value = static_cast( GetValue( _instance, 0 ) ) ) - { - value->OnValueRefreshed( _data[1] ); - value->Release(); - } - } - else - { - // Commmand received from the node. Handle as a notification event - Log::Write( LogLevel_Info, GetNodeId(), "Received Basic set from node %d: level=%d. Sending event notification.", GetNodeId(), _data[1] ); + if (BasicCmd_Report == (BasicCmd) _data[0]) + { + // Level + Log::Write(LogLevel_Info, GetNodeId(), "Received Basic report from node %d: level=%d", GetNodeId(), _data[1]); + if (!m_com.GetFlagBool(COMPAT_FLAG_BASIC_IGNOREREMAPPING) && m_com.GetFlagByte(COMPAT_FLAG_BASIC_MAPPING) != 0) + { + UpdateMappedClass(_instance, m_com.GetFlagByte(COMPAT_FLAG_BASIC_MAPPING), _data[1]); + } + else if (Internal::VC::ValueByte* value = static_cast(GetValue(_instance, ValueID_Index_Basic::Set))) + { + value->OnValueRefreshed(_data[1]); + value->Release(); + } + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "No Valid Mapping for Basic Command Class and No ValueID Exported. Error?"); + } + return true; + } - Notification* notification = new Notification( Notification::Type_NodeEvent ); - notification->SetHomeNodeIdAndInstance( GetHomeId(), GetNodeId(), _instance ); - notification->SetEvent( _data[1] ); - GetDriver()->QueueNotification( notification ); - } - return true; - } + if (BasicCmd_Set == (BasicCmd) _data[0]) + { + if (m_com.GetFlagBool(COMPAT_FLAG_BASIC_SETASREPORT)) + { + Log::Write(LogLevel_Info, GetNodeId(), "Received Basic set from node %d: level=%d. Treating it as a Basic report.", GetNodeId(), _data[1]); + if (!m_com.GetFlagBool(COMPAT_FLAG_BASIC_IGNOREREMAPPING) && m_com.GetFlagByte(COMPAT_FLAG_BASIC_MAPPING) != 0) + { + UpdateMappedClass(_instance, m_com.GetFlagByte(COMPAT_FLAG_BASIC_MAPPING), _data[1]); + } + else if (Internal::VC::ValueByte* value = static_cast(GetValue(_instance, ValueID_Index_Basic::Set))) + { + value->OnValueRefreshed(_data[1]); + value->Release(); + } + } + else + { + // Commmand received from the node. Handle as a notification event + Log::Write(LogLevel_Info, GetNodeId(), "Received Basic set from node %d: level=%d. Sending event notification.", GetNodeId(), _data[1]); - return false; -} + Notification* notification = new Notification(Notification::Type_NodeEvent); + notification->SetHomeNodeIdAndInstance(GetHomeId(), GetNodeId(), _instance); + notification->SetEvent(_data[1]); + GetDriver()->QueueNotification(notification); + } + return true; + } + + return false; + } //----------------------------------------------------------------------------- // // Set a value on the Z-Wave device //----------------------------------------------------------------------------- -bool Basic::SetValue -( - Value const& _value -) -{ - if( ValueID::ValueType_Byte == _value.GetID().GetType() ) - { - ValueByte const* value = static_cast(&_value); + bool Basic::SetValue(Internal::VC::Value const& _value) + { + if (ValueID::ValueType_Byte == _value.GetID().GetType()) + { + Internal::VC::ValueByte const* value = static_cast(&_value); - Log::Write( LogLevel_Info, GetNodeId(), "Basic::Set - Setting node %d to level %d", GetNodeId(), value->GetValue() ); - Msg* msg = new Msg( "BasicCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->SetInstance( this, _value.GetID().GetInstance() ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( BasicCmd_Set ); - msg->Append( value->GetValue() ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - return true; - } + Log::Write(LogLevel_Info, GetNodeId(), "Basic::Set - Setting node %d to level %d", GetNodeId(), value->GetValue()); + Msg* msg = new Msg("BasicCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->SetInstance(this, _value.GetID().GetInstance()); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(BasicCmd_Set); + msg->Append(value->GetValue()); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return true; + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void Basic::CreateVars -( - uint8 const _instance -) -{ - m_instances.push_back(_instance); -} + void Basic::CreateVars(uint8 const _instance) + { + m_instances.push_back(_instance); + } //----------------------------------------------------------------------------- // // Helper method to set the level //----------------------------------------------------------------------------- -void Basic::Set -( - uint8 const _level -) -{ - // This may look like a long winded way to do this, but - // it ensures that all the proper notifications get sent. - if( ValueByte* value = static_cast( GetValue( 1, 0 ) ) ) - { - value->Set( _level ); - value->Release(); - } -} + void Basic::Set(uint8 const _level) + { + // This may look like a long winded way to do this, but + // it ensures that all the proper notifications get sent. + if (Internal::VC::ValueByte* value = static_cast(GetValue(1, ValueID_Index_Basic::Set))) + { + value->Set(_level); + value->Release(); + } + } //----------------------------------------------------------------------------- // // Map COMMAND_CLASS_BASIC messages to another command class //----------------------------------------------------------------------------- -bool Basic::SetMapping -( - uint8 const _commandClassId, - bool const _doLog -) -{ - bool res = false; - - if( _commandClassId != NoOperation::StaticGetCommandClassId() ) - { - if( _doLog ) - { - char str[16]; - snprintf( str, sizeof(str), "0x%02x", _commandClassId ); - string ccstr = str; - if( Node const* node = GetNodeUnsafe() ) + bool Basic::SetMapping(uint8 const _commandClassId, bool const _doLog) { - if( CommandClass* cc = node->GetCommandClass( _commandClassId ) ) + bool res = false; + + if (_commandClassId != NoOperation::StaticGetCommandClassId()) { - ccstr = cc->GetCommandClassName(); + if (_doLog) + { + char str[16]; + snprintf(str, sizeof(str), "0x%02x", _commandClassId); + string ccstr = str; + if (Node const* node = GetNodeUnsafe()) + { + if (CommandClass* cc = node->GetCommandClass(_commandClassId)) + { + ccstr = cc->GetCommandClassName(); + } + } + if (m_com.GetFlagBool(COMPAT_FLAG_BASIC_IGNOREREMAPPING)) + { + Log::Write(LogLevel_Info, GetNodeId(), " COMMAND_CLASS_BASIC will not be mapped to %s (ignored)", ccstr.c_str()); + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), " COMMAND_CLASS_BASIC will be mapped to %s", ccstr.c_str()); + } + } + m_com.SetFlagByte(COMPAT_FLAG_BASIC_MAPPING, _commandClassId); + RemoveValue(1, ValueID_Index_Basic::Set); + res = true; } - } - if( m_com.GetFlagBool(COMPAT_FLAG_BASIC_IGNOREREMAPPING) ) - { - Log::Write( LogLevel_Info, GetNodeId(), " COMMAND_CLASS_BASIC will not be mapped to %s (ignored)", ccstr.c_str() ); - } - else - { - Log::Write( LogLevel_Info, GetNodeId(), " COMMAND_CLASS_BASIC will be mapped to %s", ccstr.c_str() ); - } - } - m_com.SetFlagByte(COMPAT_FLAG_BASIC_MAPPING, _commandClassId); - RemoveValue( 1, 0 ); - res = true; - } - if( m_com.GetFlagByte(COMPAT_FLAG_BASIC_MAPPING) == 0 ) - { - if (_doLog ) - Log::Write( LogLevel_Info, GetNodeId(), " COMMAND_CLASS_BASIC is not mapped" ); - if( Node* node = GetNodeUnsafe() ) - { - if (m_instances.size() > 0) { - for (unsigned int i = 0; i < m_instances.size(); i++) - node->CreateValueByte( ValueID::ValueGenre_Basic, GetCommandClassId(), m_instances[i], 0, "Basic", "", false, false, 0, 0 ); - } else { - node->CreateValueByte( ValueID::ValueGenre_Basic, GetCommandClassId(), 0, 0, "Basic", "", false, false, 0, 0 ); + if (m_com.GetFlagByte(COMPAT_FLAG_BASIC_MAPPING) == 0) + { + if (_doLog) + Log::Write(LogLevel_Info, GetNodeId(), " COMMAND_CLASS_BASIC is not mapped"); + if (Node* node = GetNodeUnsafe()) + { + if (m_instances.size() > 0) + { + for (unsigned int i = 0; i < m_instances.size(); i++) + node->CreateValueByte(ValueID::ValueGenre_Basic, GetCommandClassId(), m_instances[i], ValueID_Index_Basic::Set, "Basic", "", false, false, 0, 0); + } + else + { + node->CreateValueByte(ValueID::ValueGenre_Basic, GetCommandClassId(), 0, ValueID_Index_Basic::Set, "Basic", "", false, false, 0, 0); + } + } + } + return res; } - } - } - return res; -} + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/Basic.h b/cpp/src/command_classes/Basic.h index f896c4c099..874a5a0208 100644 --- a/cpp/src/command_classes/Basic.h +++ b/cpp/src/command_classes/Basic.h @@ -32,42 +32,67 @@ namespace OpenZWave { - class ValueByte; - - /** \brief Implements COMMAND_CLASS_BASIC (0x20), a Z-Wave device command class. - * \ingroup CommandClass - */ - class Basic: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Basic( _homeId, _nodeId ); } - virtual ~Basic(){} - - static uint8 const StaticGetCommandClassId(){ return 0x20; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_BASIC"; } + namespace CC + { + /** \brief Implements COMMAND_CLASS_BASIC (0x20), a Z-Wave device command class. + * \ingroup CommandClass + */ + class Basic: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new Basic(_homeId, _nodeId); + } + virtual ~Basic() + { + } - bool SetMapping( uint8 const _commandClassId, bool const _doLog = true ); // Map COMMAND_CLASS_BASIC messages to another command class - uint8_t GetMapping() { return m_com.GetFlagByte(COMPAT_FLAG_BASIC_MAPPING); }; - // From CommandClass - virtual void ReadXML( TiXmlElement const* _ccElement ); - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool SetValue( Value const& _value ); + static uint8 const StaticGetCommandClassId() + { + return 0x20; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_BASIC"; + } - void Set( uint8 const _level ); + bool SetMapping(uint8 const _commandClassId, bool const _doLog = true); // Map COMMAND_CLASS_BASIC messages to another command class + uint8_t GetMapping() + { + return m_com.GetFlagByte(COMPAT_FLAG_BASIC_MAPPING); + } + ; + // From CommandClass + virtual void ReadXML(TiXmlElement const* _ccElement) override; + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool HandleIncomingMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool SetValue(Internal::VC::Value const& _value) override; - protected: - virtual void CreateVars( uint8 const _instance ); + void Set(uint8 const _level); - private: - Basic( uint32 const _homeId, uint8 const _nodeId ); + protected: + virtual void CreateVars(uint8 const _instance) override; - std::vector m_instances; - }; + private: + Basic(uint32 const _homeId, uint8 const _nodeId); + std::vector m_instances; + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/BasicWindowCovering.cpp b/cpp/src/command_classes/BasicWindowCovering.cpp index 2fd9eadc1d..63731274dc 100644 --- a/cpp/src/command_classes/BasicWindowCovering.cpp +++ b/cpp/src/command_classes/BasicWindowCovering.cpp @@ -34,85 +34,81 @@ #include "platform/Log.h" #include "value_classes/ValueButton.h" -using namespace OpenZWave; - -enum BasicWindowCoveringCmd +namespace OpenZWave { - BasicWindowCoveringCmd_StartLevelChange = 0x01, - BasicWindowCoveringCmd_StopLevelChange = 0x02 -}; + namespace Internal + { + namespace CC + { -enum -{ - BasicWindowCoveringIndex_Open = 0, - BasicWindowCoveringIndex_Close -}; + enum BasicWindowCoveringCmd + { + BasicWindowCoveringCmd_StartLevelChange = 0x01, + BasicWindowCoveringCmd_StopLevelChange = 0x02 + }; //----------------------------------------------------------------------------- // // Set a value on the Z-Wave device //----------------------------------------------------------------------------- -bool BasicWindowCovering::SetValue -( - Value const& _value -) -{ - if( ValueID::ValueType_Button == _value.GetID().GetType() ) - { - ValueButton const* button = static_cast(&_value); + bool BasicWindowCovering::SetValue(Internal::VC::Value const& _value) + { + if (ValueID::ValueType_Button == _value.GetID().GetType()) + { + Internal::VC::ValueButton const* button = static_cast(&_value); - uint8 action = 0x40; - if( button->GetID().GetIndex() ) // Open is index zero, so non-zero is close. - { - // Close - action = 0; - } + uint8 action = 0x40; + if (button->GetID().GetIndex() == ValueID_Index_BasicWindowCovering::Close) // Open is index zero, so non-zero is close. + { + // Close + action = 0; + } - if( button && button->IsPressed() ) - { - Log::Write( LogLevel_Info, GetNodeId(), "BasicWindowCovering - Start Level Change (%s)", action ? "Open" : "Close" ); - Msg* msg = new Msg( "BasicWindowCoveringCmd_StartLevelChange", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->SetInstance( this, _value.GetID().GetInstance() ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( BasicWindowCoveringCmd_StartLevelChange ); - msg->Append( action ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - return true; - } - else - { - Log::Write( LogLevel_Info, GetNodeId(), "BasicWindowCovering - Stop Level Change" ); - Msg* msg = new Msg( "BasicWindowCoveringCmd_StopLevelChange", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->SetInstance( this, _value.GetID().GetInstance() ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( BasicWindowCoveringCmd_StopLevelChange ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - return true; - } - } + if (button && button->IsPressed()) + { + Log::Write(LogLevel_Info, GetNodeId(), "BasicWindowCovering - Start Level Change (%s)", action ? "Open" : "Close"); + Msg* msg = new Msg("BasicWindowCoveringCmd_StartLevelChange", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->SetInstance(this, _value.GetID().GetInstance()); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(BasicWindowCoveringCmd_StartLevelChange); + msg->Append(action); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "BasicWindowCovering - Stop Level Change"); + Msg* msg = new Msg("BasicWindowCoveringCmd_StopLevelChange", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->SetInstance(this, _value.GetID().GetInstance()); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(BasicWindowCoveringCmd_StopLevelChange); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return true; + } + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void BasicWindowCovering::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - node->CreateValueButton( ValueID::ValueGenre_User, GetCommandClassId(), _instance, BasicWindowCoveringIndex_Open, "Open", 0 ); - node->CreateValueButton( ValueID::ValueGenre_User, GetCommandClassId(), _instance, BasicWindowCoveringIndex_Close, "Close", 0 ); - } -} + void BasicWindowCovering::CreateVars(uint8 const _instance) + { + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueButton(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_BasicWindowCovering::Open, "Open", 0); + node->CreateValueButton(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_BasicWindowCovering::Close, "Close", 0); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/BasicWindowCovering.h b/cpp/src/command_classes/BasicWindowCovering.h index f80492d52b..8837b3d52f 100644 --- a/cpp/src/command_classes/BasicWindowCovering.h +++ b/cpp/src/command_classes/BasicWindowCovering.h @@ -32,33 +32,59 @@ namespace OpenZWave { - class ValueButton; - - /** \brief Implements COMMAND_CLASS_BASIC_WINDOW_COVERING (0x50), a Z-Wave device command class. - * \ingroup CommandClass - */ - class BasicWindowCovering: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new BasicWindowCovering( _homeId, _nodeId ); } - virtual ~BasicWindowCovering(){} - - static uint8 const StaticGetCommandClassId(){ return 0x50; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_BASIC_WINDOW_COVERING"; } + namespace CC + { + /** \brief Implements COMMAND_CLASS_BASIC_WINDOW_COVERING (0x50), a Z-Wave device command class. + * \ingroup CommandClass + */ + class BasicWindowCovering: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new BasicWindowCovering(_homeId, _nodeId); + } + virtual ~BasicWindowCovering() + { + } - // From CommandClass - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ){ return false; } - virtual bool SetValue( Value const& _value ); + static uint8 const StaticGetCommandClassId() + { + return 0x50; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_BASIC_WINDOW_COVERING"; + } - protected: - virtual void CreateVars( uint8 const _instance ); + // From CommandClass + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override + { + return false; + } + virtual bool SetValue(Internal::VC::Value const& _value) override; - private: - BasicWindowCovering( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} - }; + protected: + virtual void CreateVars(uint8 const _instance) override; + private: + BasicWindowCovering(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + } + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/Battery.cpp b/cpp/src/command_classes/Battery.cpp index 24c77f02d1..fc64858155 100644 --- a/cpp/src/command_classes/Battery.cpp +++ b/cpp/src/command_classes/Battery.cpp @@ -35,112 +35,104 @@ #include "value_classes/ValueByte.h" -using namespace OpenZWave; - -enum BatteryCmd +namespace OpenZWave { - BatteryCmd_Get = 0x02, - BatteryCmd_Report = 0x03 -}; + namespace Internal + { + namespace CC + { + + enum BatteryCmd + { + BatteryCmd_Get = 0x02, + BatteryCmd_Report = 0x03 + }; //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool Battery::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _requestFlags & RequestFlag_Dynamic ) - { - return RequestValue( _requestFlags, 0, _instance, _queue ); - } + bool Battery::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_requestFlags & RequestFlag_Dynamic) + { + return RequestValue(_requestFlags, ValueID_Index_Battery::Level, _instance, _queue); + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool Battery::RequestValue -( - uint32 const _requestFlags, - uint16 const _dummy1, // = 0 (not used) - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _instance != 1 ) - { - // This command class doesn't work with multiple instances - return false; - } - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Msg* msg = new Msg( "BatteryCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( BatteryCmd_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "BatteryCmd_Get Not Supported on this node"); - } - return false; -} + bool Battery::RequestValue(uint32 const _requestFlags, uint16 const _dummy1, // = 0 (not used) + uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_instance != 1) + { + // This command class doesn't work with multiple instances + return false; + } + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Msg* msg = new Msg("BatteryCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(BatteryCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "BatteryCmd_Get Not Supported on this node"); + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool Battery::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if (BatteryCmd_Report == (BatteryCmd)_data[0]) - { - // We have received a battery level report from the Z-Wave device. - // Devices send 0xff instead of zero for a low battery warning. - uint8 batteryLevel = _data[1]; - if( batteryLevel == 0xff ) - { - batteryLevel = 0; - } + bool Battery::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) + { + if (BatteryCmd_Report == (BatteryCmd) _data[0]) + { + // We have received a battery level report from the Z-Wave device. + // Devices send 0xff instead of zero for a low battery warning. + uint8 batteryLevel = _data[1]; + if (batteryLevel == 0xff) + { + batteryLevel = 0; + } - Log::Write( LogLevel_Info, GetNodeId(), "Received Battery report from node %d: level=%d", GetNodeId(), batteryLevel ); + Log::Write(LogLevel_Info, GetNodeId(), "Received Battery report from node %d: level=%d", GetNodeId(), batteryLevel); - if( ValueByte* value = static_cast( GetValue( _instance, 0 ) ) ) - { - value->OnValueRefreshed( batteryLevel ); - value->Release(); - } - return true; - } - return false; -} + if (Internal::VC::ValueByte* value = static_cast(GetValue(_instance, ValueID_Index_Battery::Level))) + { + value->OnValueRefreshed(batteryLevel); + value->Release(); + } + return true; + } + return false; + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void Battery::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, "Battery Level", "%", true, false, 100, 0 ); - } -} - + void Battery::CreateVars(uint8 const _instance) + { + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueByte(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_Battery::Level, "Battery Level", "%", true, false, 100, 0); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/Battery.h b/cpp/src/command_classes/Battery.h index 37753fa5e6..af11bb6cff 100644 --- a/cpp/src/command_classes/Battery.h +++ b/cpp/src/command_classes/Battery.h @@ -32,34 +32,57 @@ namespace OpenZWave { - class ValueByte; - - /** \brief Implements COMMAND_CLASS_BATTERY (0x80), a Z-Wave device command class. - * \ingroup CommandClass - */ - class Battery: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Battery( _homeId, _nodeId ); } - virtual ~Battery(){} - - static uint8 const StaticGetCommandClassId(){ return 0x80; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_BATTERY"; } + namespace CC + { + /** \brief Implements COMMAND_CLASS_BATTERY (0x80), a Z-Wave device command class. + * \ingroup CommandClass + */ + class Battery: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new Battery(_homeId, _nodeId); + } + virtual ~Battery() + { + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); + static uint8 const StaticGetCommandClassId() + { + return 0x80; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_BATTERY"; + } - protected: - virtual void CreateVars( uint8 const _instance ); + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; - private: - Battery( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} - }; + protected: + virtual void CreateVars(uint8 const _instance) override; + private: + Battery(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + } + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/CRC16Encap.cpp b/cpp/src/command_classes/CRC16Encap.cpp index 65dacf99da..9d3a4b936f 100644 --- a/cpp/src/command_classes/CRC16Encap.cpp +++ b/cpp/src/command_classes/CRC16Encap.cpp @@ -33,69 +33,77 @@ #include "Driver.h" #include "platform/Log.h" -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace CC + { // // CRC-CCITT (0x1D0F) // -uint16 crc16(uint8 const * data_p, uint32 const _length){ - uint8 x; - uint16 crc = 0xF6AF; // 0x1D0F with first byte 0x56; - uint32 length = _length; - - while (length--){ - x = crc >> 8 ^ *data_p++; - x ^= x>>4; - crc = (crc << 8) ^ ((uint16)(x << 12)) ^ ((uint16)(x <<5)) ^ ((uint16)x); - } - return crc; -} + uint16 crc16(uint8 const * data_p, uint32 const _length) + { + uint8 x; + uint16 crc = 0xF6AF; // 0x1D0F with first byte 0x56; + uint32 length = _length; -enum CRC16EncapCmd -{ - CRC16EncapCmd_Encap = 0x01 -}; + while (length--) + { + x = crc >> 8 ^ *data_p++; + x ^= x >> 4; + crc = (crc << 8) ^ ((uint16) (x << 12)) ^ ((uint16) (x << 5)) ^ ((uint16) x); + } + return crc; + } + enum CRC16EncapCmd + { + CRC16EncapCmd_Encap = 0x01 + }; //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool CRC16Encap::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if( CRC16EncapCmd_Encap == (CRC16EncapCmd)_data[0] ) - { - Log::Write( LogLevel_Info, GetNodeId(), "Received CRC16-command from node %d", GetNodeId()); + bool CRC16Encap::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) + { + if (CRC16EncapCmd_Encap == (CRC16EncapCmd) _data[0]) + { + Log::Write(LogLevel_Info, GetNodeId(), "Received CRC16-command from node %d", GetNodeId()); - uint16 crcM = (_data[_length - 3] << 8) + _data[_length - 2] ; // crc as reported in msg - uint16 crcC = crc16(&_data[0], _length - 3 ); // crc calculated + uint16 crcM = (_data[_length - 3] << 8) + _data[_length - 2]; // crc as reported in msg + uint16 crcC = crc16(&_data[0], _length - 3); // crc calculated - if ( crcM != crcC ) - { - Log::Write( LogLevel_Info, GetNodeId(), "CRC check failed, message contains 0x%.4x but should be 0x%.4x", crcM, crcC); - return false; - } + if (crcM != crcC) + { + Log::Write(LogLevel_Info, GetNodeId(), "CRC check failed, message contains 0x%.4x but should be 0x%.4x", crcM, crcC); + return false; + } - if( Node const* node = GetNodeUnsafe() ) - { - uint8 commandClassId = _data[1]; + if (Node const* node = GetNodeUnsafe()) + { + uint8 commandClassId = _data[1]; - if( CommandClass* pCommandClass = node->GetCommandClass( commandClassId, false ) ) - { - pCommandClass->HandleMsg( &_data[2], _length - 4 ); - } - if( CommandClass* pCommandClass = node->GetCommandClass( commandClassId, true ) ) - { - pCommandClass->HandleIncomingMsg( &_data[2], _length - 4 ); - } - } + if (CommandClass* pCommandClass = node->GetCommandClass(commandClassId)) + { + if (!pCommandClass->IsAfterMark()) + { + pCommandClass->HandleMsg(&_data[2], _length - 4); + } + else + { + pCommandClass->HandleIncomingMsg(&_data[2], _length - 4); + } + } + } - return true; - } - return false; -} + return true; + } + return false; + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/CRC16Encap.h b/cpp/src/command_classes/CRC16Encap.h index 3317510247..d574385748 100644 --- a/cpp/src/command_classes/CRC16Encap.h +++ b/cpp/src/command_classes/CRC16Encap.h @@ -32,27 +32,52 @@ namespace OpenZWave { - /** \brief Implements COMMAND_CLASS_CRC_16_ENCAP (0x56), a Z-Wave device command class. - * \ingroup CommandClass - */ - class CRC16Encap: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new CRC16Encap( _homeId, _nodeId ); } - virtual ~CRC16Encap(){} + namespace CC + { + /** \brief Implements COMMAND_CLASS_CRC_16_ENCAP (0x56), a Z-Wave device command class. + * \ingroup CommandClass + */ + class CRC16Encap: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new CRC16Encap(_homeId, _nodeId); + } + virtual ~CRC16Encap() + { + } - static uint8 const StaticGetCommandClassId(){ return 0x56; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_CRC_16_ENCAP"; } + static uint8 const StaticGetCommandClassId() + { + return 0x56; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_CRC_16_ENCAP"; + } - // From CommandClass - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - - private: - CRC16Encap( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} - }; + // From CommandClass + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + private: + CRC16Encap(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + } + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/CentralScene.cpp b/cpp/src/command_classes/CentralScene.cpp index a06466fe4e..330ff71ad7 100644 --- a/cpp/src/command_classes/CentralScene.cpp +++ b/cpp/src/command_classes/CentralScene.cpp @@ -38,613 +38,332 @@ #include "tinyxml.h" -using namespace OpenZWave; - -enum CentralSceneCmd +namespace OpenZWave { - CentralSceneCmd_Capability_Get = 0x01, - CentralSceneCmd_Capability_Report = 0x02, - CentralSceneCmd_Set = 0x03 -}; + namespace Internal + { + namespace CC + { + enum CentralSceneCmd + { + CentralSceneCmd_Capability_Get = 0x01, + CentralSceneCmd_Capability_Report = 0x02, + CentralSceneCmd_Set = 0x03 + }; -enum CentralScene_ValueID_Index -{ - CentralSceneIndex_SceneID_1 = 0x01, - CentralSceneIndex_SceneID_2, - CentralSceneIndex_SceneID_3, - CentralSceneIndex_SceneID_4, - CentralSceneIndex_SceneID_5, - CentralSceneIndex_SceneID_6, - CentralSceneIndex_SceneID_7, - CentralSceneIndex_SceneID_8, - CentralSceneIndex_SceneID_9, - CentralSceneIndex_SceneID_10, - CentralSceneIndex_SceneID_11, - CentralSceneIndex_SceneID_12, - CentralSceneIndex_SceneID_13, - CentralSceneIndex_SceneID_14, - CentralSceneIndex_SceneID_15, - CentralSceneIndex_SceneID_16, - CentralSceneIndex_SceneID_17, - CentralSceneIndex_SceneID_18, - CentralSceneIndex_SceneID_19, - CentralSceneIndex_SceneID_20, - CentralSceneIndex_SceneID_21, - CentralSceneIndex_SceneID_22, - CentralSceneIndex_SceneID_23, - CentralSceneIndex_SceneID_24, - CentralSceneIndex_SceneID_25, - CentralSceneIndex_SceneID_26, - CentralSceneIndex_SceneID_27, - CentralSceneIndex_SceneID_28, - CentralSceneIndex_SceneID_29, - CentralSceneIndex_SceneID_30, - CentralSceneIndex_SceneID_31, - CentralSceneIndex_SceneID_32, - CentralSceneIndex_SceneID_33, - CentralSceneIndex_SceneID_34, - CentralSceneIndex_SceneID_35, - CentralSceneIndex_SceneID_36, - CentralSceneIndex_SceneID_37, - CentralSceneIndex_SceneID_38, - CentralSceneIndex_SceneID_39, - CentralSceneIndex_SceneID_40, - CentralSceneIndex_SceneID_41, - CentralSceneIndex_SceneID_42, - CentralSceneIndex_SceneID_43, - CentralSceneIndex_SceneID_44, - CentralSceneIndex_SceneID_45, - CentralSceneIndex_SceneID_46, - CentralSceneIndex_SceneID_47, - CentralSceneIndex_SceneID_48, - CentralSceneIndex_SceneID_49, - CentralSceneIndex_SceneID_50, - CentralSceneIndex_SceneID_51, - CentralSceneIndex_SceneID_52, - CentralSceneIndex_SceneID_53, - CentralSceneIndex_SceneID_54, - CentralSceneIndex_SceneID_55, - CentralSceneIndex_SceneID_56, - CentralSceneIndex_SceneID_57, - CentralSceneIndex_SceneID_58, - CentralSceneIndex_SceneID_59, - CentralSceneIndex_SceneID_60, - CentralSceneIndex_SceneID_61, - CentralSceneIndex_SceneID_62, - CentralSceneIndex_SceneID_63, - CentralSceneIndex_SceneID_64, - CentralSceneIndex_SceneID_65, - CentralSceneIndex_SceneID_66, - CentralSceneIndex_SceneID_67, - CentralSceneIndex_SceneID_68, - CentralSceneIndex_SceneID_69, - CentralSceneIndex_SceneID_70, - CentralSceneIndex_SceneID_71, - CentralSceneIndex_SceneID_72, - CentralSceneIndex_SceneID_73, - CentralSceneIndex_SceneID_74, - CentralSceneIndex_SceneID_75, - CentralSceneIndex_SceneID_76, - CentralSceneIndex_SceneID_77, - CentralSceneIndex_SceneID_78, - CentralSceneIndex_SceneID_79, - CentralSceneIndex_SceneID_80, - CentralSceneIndex_SceneID_81, - CentralSceneIndex_SceneID_82, - CentralSceneIndex_SceneID_83, - CentralSceneIndex_SceneID_84, - CentralSceneIndex_SceneID_85, - CentralSceneIndex_SceneID_86, - CentralSceneIndex_SceneID_87, - CentralSceneIndex_SceneID_88, - CentralSceneIndex_SceneID_89, - CentralSceneIndex_SceneID_90, - CentralSceneIndex_SceneID_91, - CentralSceneIndex_SceneID_92, - CentralSceneIndex_SceneID_93, - CentralSceneIndex_SceneID_94, - CentralSceneIndex_SceneID_95, - CentralSceneIndex_SceneID_96, - CentralSceneIndex_SceneID_97, - CentralSceneIndex_SceneID_98, - CentralSceneIndex_SceneID_99, - CentralSceneIndex_SceneID_100, - CentralSceneIndex_SceneID_101, - CentralSceneIndex_SceneID_102, - CentralSceneIndex_SceneID_103, - CentralSceneIndex_SceneID_104, - CentralSceneIndex_SceneID_105, - CentralSceneIndex_SceneID_106, - CentralSceneIndex_SceneID_107, - CentralSceneIndex_SceneID_108, - CentralSceneIndex_SceneID_109, - CentralSceneIndex_SceneID_110, - CentralSceneIndex_SceneID_111, - CentralSceneIndex_SceneID_112, - CentralSceneIndex_SceneID_113, - CentralSceneIndex_SceneID_114, - CentralSceneIndex_SceneID_115, - CentralSceneIndex_SceneID_116, - CentralSceneIndex_SceneID_117, - CentralSceneIndex_SceneID_118, - CentralSceneIndex_SceneID_119, - CentralSceneIndex_SceneID_120, - CentralSceneIndex_SceneID_121, - CentralSceneIndex_SceneID_122, - CentralSceneIndex_SceneID_123, - CentralSceneIndex_SceneID_124, - CentralSceneIndex_SceneID_125, - CentralSceneIndex_SceneID_126, - CentralSceneIndex_SceneID_127, - CentralSceneIndex_SceneID_128, - CentralSceneIndex_SceneID_129, - CentralSceneIndex_SceneID_130, - CentralSceneIndex_SceneID_131, - CentralSceneIndex_SceneID_132, - CentralSceneIndex_SceneID_133, - CentralSceneIndex_SceneID_134, - CentralSceneIndex_SceneID_135, - CentralSceneIndex_SceneID_136, - CentralSceneIndex_SceneID_137, - CentralSceneIndex_SceneID_138, - CentralSceneIndex_SceneID_139, - CentralSceneIndex_SceneID_140, - CentralSceneIndex_SceneID_141, - CentralSceneIndex_SceneID_142, - CentralSceneIndex_SceneID_143, - CentralSceneIndex_SceneID_144, - CentralSceneIndex_SceneID_145, - CentralSceneIndex_SceneID_146, - CentralSceneIndex_SceneID_147, - CentralSceneIndex_SceneID_148, - CentralSceneIndex_SceneID_149, - CentralSceneIndex_SceneID_150, - CentralSceneIndex_SceneID_151, - CentralSceneIndex_SceneID_152, - CentralSceneIndex_SceneID_153, - CentralSceneIndex_SceneID_154, - CentralSceneIndex_SceneID_155, - CentralSceneIndex_SceneID_156, - CentralSceneIndex_SceneID_157, - CentralSceneIndex_SceneID_158, - CentralSceneIndex_SceneID_159, - CentralSceneIndex_SceneID_160, - CentralSceneIndex_SceneID_161, - CentralSceneIndex_SceneID_162, - CentralSceneIndex_SceneID_163, - CentralSceneIndex_SceneID_164, - CentralSceneIndex_SceneID_165, - CentralSceneIndex_SceneID_166, - CentralSceneIndex_SceneID_167, - CentralSceneIndex_SceneID_168, - CentralSceneIndex_SceneID_169, - CentralSceneIndex_SceneID_170, - CentralSceneIndex_SceneID_171, - CentralSceneIndex_SceneID_172, - CentralSceneIndex_SceneID_173, - CentralSceneIndex_SceneID_174, - CentralSceneIndex_SceneID_175, - CentralSceneIndex_SceneID_176, - CentralSceneIndex_SceneID_177, - CentralSceneIndex_SceneID_178, - CentralSceneIndex_SceneID_179, - CentralSceneIndex_SceneID_180, - CentralSceneIndex_SceneID_181, - CentralSceneIndex_SceneID_182, - CentralSceneIndex_SceneID_183, - CentralSceneIndex_SceneID_184, - CentralSceneIndex_SceneID_185, - CentralSceneIndex_SceneID_186, - CentralSceneIndex_SceneID_187, - CentralSceneIndex_SceneID_188, - CentralSceneIndex_SceneID_189, - CentralSceneIndex_SceneID_190, - CentralSceneIndex_SceneID_191, - CentralSceneIndex_SceneID_192, - CentralSceneIndex_SceneID_193, - CentralSceneIndex_SceneID_194, - CentralSceneIndex_SceneID_195, - CentralSceneIndex_SceneID_196, - CentralSceneIndex_SceneID_197, - CentralSceneIndex_SceneID_198, - CentralSceneIndex_SceneID_199, - CentralSceneIndex_SceneID_200, - CentralSceneIndex_SceneID_201, - CentralSceneIndex_SceneID_202, - CentralSceneIndex_SceneID_203, - CentralSceneIndex_SceneID_204, - CentralSceneIndex_SceneID_205, - CentralSceneIndex_SceneID_206, - CentralSceneIndex_SceneID_207, - CentralSceneIndex_SceneID_208, - CentralSceneIndex_SceneID_209, - CentralSceneIndex_SceneID_210, - CentralSceneIndex_SceneID_211, - CentralSceneIndex_SceneID_212, - CentralSceneIndex_SceneID_213, - CentralSceneIndex_SceneID_214, - CentralSceneIndex_SceneID_215, - CentralSceneIndex_SceneID_216, - CentralSceneIndex_SceneID_217, - CentralSceneIndex_SceneID_218, - CentralSceneIndex_SceneID_219, - CentralSceneIndex_SceneID_220, - CentralSceneIndex_SceneID_221, - CentralSceneIndex_SceneID_222, - CentralSceneIndex_SceneID_223, - CentralSceneIndex_SceneID_224, - CentralSceneIndex_SceneID_225, - CentralSceneIndex_SceneID_226, - CentralSceneIndex_SceneID_227, - CentralSceneIndex_SceneID_228, - CentralSceneIndex_SceneID_229, - CentralSceneIndex_SceneID_230, - CentralSceneIndex_SceneID_231, - CentralSceneIndex_SceneID_232, - CentralSceneIndex_SceneID_233, - CentralSceneIndex_SceneID_234, - CentralSceneIndex_SceneID_235, - CentralSceneIndex_SceneID_236, - CentralSceneIndex_SceneID_237, - CentralSceneIndex_SceneID_238, - CentralSceneIndex_SceneID_239, - CentralSceneIndex_SceneID_240, - CentralSceneIndex_SceneID_241, - CentralSceneIndex_SceneID_242, - CentralSceneIndex_SceneID_243, - CentralSceneIndex_SceneID_244, - CentralSceneIndex_SceneID_245, - CentralSceneIndex_SceneID_246, - CentralSceneIndex_SceneID_247, - CentralSceneIndex_SceneID_248, - CentralSceneIndex_SceneID_249, - CentralSceneIndex_SceneID_250, - CentralSceneIndex_SceneID_251, - CentralSceneIndex_SceneID_252, - CentralSceneIndex_SceneID_253, - CentralSceneIndex_SceneID_254, - CentralSceneIndex_SceneID_255, - CentralSceneIndex_SceneCount = 0x100, - CentralSceneIndex_ClearSceneTimeout -}; + enum CentralScene_ValueID_Index + { + }; -enum CentralScene_KeyAttributesMask -{ - CentralSceneMask_KeyPressed1time = 0x01, - CentralSceneMask_KeyReleased = 0x02, - CentralSceneMask_HeldDown = 0x04, - CentralSceneMask_KeyPressed2times = 0x08, - CentralSceneMask_KeyPressed3times = 0x10, - CentralSceneMask_KeyPressed4times = 0x20, - CentralSceneMask_KeyPressed5times = 0x40, - CentralSceneMask_reserved = 0x80, -}; + enum CentralScene_KeyAttributesMask + { + CentralSceneMask_KeyPressed1time = 0x01, + CentralSceneMask_KeyReleased = 0x02, + CentralSceneMask_HeldDown = 0x04, + CentralSceneMask_KeyPressed2times = 0x08, + CentralSceneMask_KeyPressed3times = 0x10, + CentralSceneMask_KeyPressed4times = 0x20, + CentralSceneMask_KeyPressed5times = 0x40, + CentralSceneMask_reserved = 0x80, + }; -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, -}; + 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, + }; -static char const* c_CentralScene_KeyAttributes[] = -{ - "Inactive", - "Pressed 1 Time", - "Key Released", - "Key Held down", - "Pressed 2 Times", - "Pressed 3 Times", - "Pressed 4 Times", - "Pressed 5 Times" -}; + static char const* c_CentralScene_KeyAttributes[] = + { "Inactive", "Pressed 1 Time", "Key Released", "Key Held down", "Pressed 2 Times", "Pressed 3 Times", "Pressed 4 Times", "Pressed 5 Times" }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -CentralScene::CentralScene -( - uint32 const _homeId, - uint8 const _nodeId -): -CommandClass( _homeId, _nodeId ), -m_slowrefresh( false ), -m_sequence( 0 ) -{ - m_dom.EnableFlag(STATE_FLAG_CS_SCENECOUNT, 0); - m_dom.EnableFlag(STATE_FLAG_CS_CLEARTIMEOUT, 1000); - Timer::SetDriver(GetDriver()); - SetStaticRequest( StaticRequest_Values ); -} - + CentralScene::CentralScene(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId), m_slowrefresh(false), m_sequence(0) + { + m_dom.EnableFlag(STATE_FLAG_CS_SCENECOUNT, 0); + m_dom.EnableFlag(STATE_FLAG_CS_CLEARTIMEOUT, 1000); + Timer::SetDriver(GetDriver()); + SetStaticRequest(StaticRequest_Values); + } //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool CentralScene::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - bool requests = false; - if( (_requestFlags & RequestFlag_Static) && HasStaticRequest( StaticRequest_Values ) ) - { - requests = RequestValue( _requestFlags, CentralSceneCmd_Capability_Get, _instance, _queue ); - } - return requests; -} + bool CentralScene::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + bool requests = false; + if ((_requestFlags & RequestFlag_Static) && HasStaticRequest(StaticRequest_Values)) + { + requests = RequestValue(_requestFlags, CentralSceneCmd_Capability_Get, _instance, _queue); + } + return requests; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool CentralScene::RequestValue -( - uint32 const _requestFlags, - uint16 const _what, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if (_what == CentralSceneCmd_Capability_Get) { - Msg* msg = new Msg( "CentralSceneCmd_Capability_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( CentralSceneCmd_Capability_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - } - return true; -} + bool CentralScene::RequestValue(uint32 const _requestFlags, uint16 const _what, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_what == CentralSceneCmd_Capability_Get) + { + Msg* msg = new Msg("CentralSceneCmd_Capability_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(CentralSceneCmd_Capability_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + } + return true; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool CentralScene::SetValue -( - Value const& _value -) -{ - if ((ValueID::ValueType_Int == _value.GetID().GetType()) && (_value.GetID().GetIndex() == CentralSceneIndex_ClearSceneTimeout)) { - ValueInt const *value = static_cast(&_value); - m_dom.SetFlagInt(STATE_FLAG_CS_CLEARTIMEOUT, value->GetValue()); - return true; - } - return false; -} + bool CentralScene::SetValue(Internal::VC::Value const& _value) + { + if ((ValueID::ValueType_Int == _value.GetID().GetType()) && (_value.GetID().GetIndex() == ValueID_Index_CentralScene::ClearSceneTimeout)) + { + Internal::VC::ValueInt const *value = static_cast(&_value); + m_dom.SetFlagInt(STATE_FLAG_CS_CLEARTIMEOUT, value->GetValue()); + return true; + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool CentralScene::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if( CentralSceneCmd_Set == (CentralSceneCmd)_data[0] ) - { - // Central Scene Set received so send notification - /* if the sequence number is the same as what we have recieved previously this is a retried packet */ - if (m_sequence == _data[1]) { - Log::Write( LogLevel_Warning, GetNodeId(), "Recieved Duplicated Scene Notification. Dropping..."); - return true; - } - m_sequence = _data[1]; - uint8 keyAttribute = (_data[2] & 0x07); - uint8 sceneID = _data[3]; - Log::Write( LogLevel_Info, GetNodeId(), "Received Central Scene set from node %d: scene id=%d with key Attribute %d. Sending event notification.", GetNodeId(), sceneID, keyAttribute); - - if( ValueList* value = static_cast( GetValue( _instance, sceneID ) ) ) - { - /* plus one, as we have our own "inactive" entry at index 0 */ - value->OnValueRefreshed( keyAttribute +1 ); - value->Release(); - /* Start up a Timer to set this back to Inactive */ - Log::Write( LogLevel_Info, GetNodeId(), "Automatically Clearing Scene %d in %dms", sceneID, m_dom.GetFlagInt(STATE_FLAG_CS_CLEARTIMEOUT) ); - if (m_TimersSet.find(sceneID) == m_TimersSet.end()) { - m_TimersSet.insert(std::pair(sceneID, _instance)); - } else { - /* clear the Old Timer */ - TimerDelEvent(sceneID); - /* no need to pop it off the list, as we will add it again below */ - } - TimerThread::TimerCallback callback = bind(&CentralScene::ClearScene, this, sceneID); - TimerSetEvent(m_dom.GetFlagInt(STATE_FLAG_CS_CLEARTIMEOUT), callback, sceneID); - } else { - Log::Write( LogLevel_Warning, GetNodeId(), "No ValueID created for Scene %d", sceneID); - return false; - } - return true; - } - else if (CentralSceneCmd_Capability_Report == (CentralSceneCmd)_data[0]) - { - /* Create a Number of ValueID's based on the STATE_FLAG_CS_SCENECOUNT variable - * We prefer what the Config File specifies rather than what is returned by - * the Device... - */ - int scenecount = _data[1]; - if (m_dom.GetFlagByte(STATE_FLAG_CS_SCENECOUNT) == 0) - { - m_dom.SetFlagByte(STATE_FLAG_CS_SCENECOUNT, scenecount); - } - bool identical = true; //version 1 does not know this, so set it to true. - if ( GetVersion() >= 2 ) - { - identical = _data[2] & 0x01; - Log::Write( LogLevel_Detail, GetNodeId(), "CentralScene: all scenes identical? %i",identical); - if ( GetVersion() >= 3 ) - m_slowrefresh = (_data[2] & 0x80) == 1 ? true : false; - } - - if ( ValueInt* value = static_cast( GetValue( _instance, CentralSceneIndex_SceneCount))) - { - value->OnValueRefreshed(m_dom.GetFlagByte(STATE_FLAG_CS_SCENECOUNT)); - value->Release(); - } else { - Log::Write( LogLevel_Warning, GetNodeId(), "Can't find ValueID for SceneCount"); - } - - for (int sceneID = 1; sceneID <= m_dom.GetFlagByte(STATE_FLAG_CS_SCENECOUNT) ; sceneID++) { - if ( GetVersion() == 1 ) + bool CentralScene::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) { - // version 1 does not tell us which keyAttributes are supported, but only single press, released and held down are supported, so add these 3 - if( Node* node = GetNodeUnsafe() ) + if (CentralSceneCmd_Set == (CentralSceneCmd) _data[0]) { - vector items; - for( unsigned int i=0; i < 4; i++) + // Central Scene Set received so send notification + /* if the sequence number is the same as what we have received previously this is a retried packet */ + if (m_sequence == _data[1]) { - ValueList::Item item; - item.m_label = c_CentralScene_KeyAttributes[i]; - item.m_value = i; - items.push_back( item ); + Log::Write(LogLevel_Warning, GetNodeId(), "Received Duplicated Scene Notification. Dropping..."); + return true; } - char lbl[64]; - snprintf(lbl, 64, "Scene %d", sceneID); - node->CreateValueList( ValueID::ValueGenre_User, GetCommandClassId(), _instance, sceneID, lbl, "", true, false, 3, items, 0, 0 ); - } - } - if ( GetVersion() >= 2 ) - { - if ( identical ) - { - int keyAttributes = _data[3]; - createSupportedKeyAttributesValues(keyAttributes,sceneID,_instance); + m_sequence = _data[1]; + uint8 keyAttribute = (_data[2] & 0x07); + uint8 sceneID = _data[3]; + Log::Write(LogLevel_Info, GetNodeId(), "Received Central Scene set from node %d: scene id=%d with key Attribute %d. Sending event notification.", GetNodeId(), sceneID, keyAttribute); + + if (Internal::VC::ValueList* value = static_cast(GetValue(_instance, sceneID))) + { + /* plus one, as we have our own "inactive" entry at index 0 */ + value->OnValueRefreshed(keyAttribute + 1); + value->Release(); + /* Start up a Timer to set this back to Inactive */ + Log::Write(LogLevel_Info, GetNodeId(), "Automatically Clearing Scene %d in %dms", sceneID, m_dom.GetFlagInt(STATE_FLAG_CS_CLEARTIMEOUT)); + if (m_TimersSet.find(sceneID) == m_TimersSet.end()) + { + m_TimersSet.insert(std::pair(sceneID, _instance)); + } + else + { + /* clear the Old Timer */ + TimerDelEvent(sceneID); + /* no need to pop it off the list, as we will add it again below */ + } + TimerThread::TimerCallback callback = bind(&CentralScene::ClearScene, this, sceneID); + TimerSetEvent(m_dom.GetFlagInt(STATE_FLAG_CS_CLEARTIMEOUT), callback, sceneID); + } + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "No ValueID created for Scene %d", sceneID); + return false; + } + return true; } - else + else if (CentralSceneCmd_Capability_Report == (CentralSceneCmd) _data[0]) { - int keyAttributes = _data[2 +sceneID]; - createSupportedKeyAttributesValues(keyAttributes, sceneID,_instance); + /* Create a Number of ValueID's based on the STATE_FLAG_CS_SCENECOUNT variable + * We prefer what the Config File specifies rather than what is returned by + * the Device... + */ + int scenecount = _data[1]; + if (m_dom.GetFlagByte(STATE_FLAG_CS_SCENECOUNT) == 0) + { + m_dom.SetFlagByte(STATE_FLAG_CS_SCENECOUNT, scenecount); + } + bool identical = true; //version 1 does not know this, so set it to true. + if (GetVersion() >= 2) + { + identical = _data[2] & 0x01; + Log::Write(LogLevel_Detail, GetNodeId(), "CentralScene: all scenes identical? %i", identical); + if (GetVersion() >= 3) + m_slowrefresh = (_data[2] & 0x80) == 1 ? true : false; + } + + if (Internal::VC::ValueInt* value = static_cast(GetValue(_instance, ValueID_Index_CentralScene::SceneCount))) + { + value->OnValueRefreshed(m_dom.GetFlagByte(STATE_FLAG_CS_SCENECOUNT)); + value->Release(); + } + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "Can't find ValueID for SceneCount"); + } + + for (int sceneID = 1; sceneID <= m_dom.GetFlagByte(STATE_FLAG_CS_SCENECOUNT); sceneID++) + { + if (GetVersion() == 1) + { + // version 1 does not tell us which keyAttributes are supported, but only single press, released and held down are supported, so add these 3 + if (Node* node = GetNodeUnsafe()) + { + vector items; + for (unsigned int i = 0; i < 4; i++) + { + Internal::VC::ValueList::Item item; + item.m_label = c_CentralScene_KeyAttributes[i]; + item.m_value = i; + items.push_back(item); + } + char lbl[64]; + snprintf(lbl, 64, "Scene %d", sceneID); + node->CreateValueList(ValueID::ValueGenre_User, GetCommandClassId(), _instance, sceneID, lbl, "", true, false, 3, items, 0, 0); + } + } + if (GetVersion() >= 2) + { + if (identical) + { + int keyAttributes = _data[3]; + createSupportedKeyAttributesValues(keyAttributes, sceneID, _instance); + } + else + { + int keyAttributes = _data[2 + sceneID]; + createSupportedKeyAttributesValues(keyAttributes, sceneID, _instance); + } + } + } } - } - } - } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void CentralScene::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - node->CreateValueInt( ValueID::ValueGenre_User, GetCommandClassId(), _instance, CentralSceneIndex_SceneCount, "Scene Count", "", true, false, 0, 0 ); - node->CreateValueInt( ValueID::ValueGenre_Config, GetCommandClassId(), _instance, CentralSceneIndex_ClearSceneTimeout, "Scene Reset Timeout", "", false, false, m_dom.GetFlagInt(STATE_FLAG_CS_CLEARTIMEOUT), 0); - } -} + void CentralScene::CreateVars(uint8 const _instance) + { + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueInt(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_CentralScene::SceneCount, "Scene Count", "", true, false, 0, 0); + node->CreateValueInt(ValueID::ValueGenre_Config, GetCommandClassId(), _instance, ValueID_Index_CentralScene::ClearSceneTimeout, "Scene Reset Timeout", "", false, false, m_dom.GetFlagInt(STATE_FLAG_CS_CLEARTIMEOUT), 0); + } + } -void CentralScene::createSupportedKeyAttributesValues -( - uint8 keyAttributes, - uint8 sceneNumber, - uint8 instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - vector items; - { - ValueList::Item item; - item.m_label = c_CentralScene_KeyAttributes[0]; - item.m_value = 0; - items.push_back( item ); - } + void CentralScene::createSupportedKeyAttributesValues(uint8 keyAttributes, uint8 sceneNumber, uint8 instance) + { + if (Node* node = GetNodeUnsafe()) + { + vector items; + { + Internal::VC::ValueList::Item item; + item.m_label = c_CentralScene_KeyAttributes[0]; + item.m_value = 0; + items.push_back(item); + } - if ( keyAttributes & CentralSceneMask_KeyPressed1time) - { - ValueList::Item item; - item.m_label = c_CentralScene_KeyAttributes[1]; - item.m_value = 1; - items.push_back( item ); - } - if ( keyAttributes & CentralSceneMask_KeyReleased) - { - ValueList::Item item; - item.m_label = c_CentralScene_KeyAttributes[2]; - item.m_value = 2; - items.push_back( item ); - } - if ( keyAttributes & CentralSceneMask_HeldDown) - { - ValueList::Item item; - item.m_label = c_CentralScene_KeyAttributes[3]; - item.m_value = 3; - items.push_back( item ); - } - if ( keyAttributes & CentralSceneMask_KeyPressed2times) - { - ValueList::Item item; - item.m_label = c_CentralScene_KeyAttributes[4]; - item.m_value = 4; - items.push_back( item ); - } - if ( keyAttributes & CentralSceneMask_KeyPressed3times) - { - ValueList::Item item; - item.m_label = c_CentralScene_KeyAttributes[5]; - item.m_value = 5; - items.push_back( item ); - } - if ( keyAttributes & CentralSceneMask_KeyPressed4times) - { - ValueList::Item item; - item.m_label = c_CentralScene_KeyAttributes[6]; - item.m_value = 6; - items.push_back( item ); - } - if ( keyAttributes & CentralSceneMask_KeyPressed5times) - { - ValueList::Item item; - item.m_label = c_CentralScene_KeyAttributes[7]; - item.m_value = 7; - items.push_back( item ); - } - char lbl[64]; - snprintf(lbl, 64, "Scene %d", sceneNumber); - node->CreateValueList( ValueID::ValueGenre_User, GetCommandClassId(), instance, sceneNumber, lbl, "", true, false, (uint8_t)(items.size() & 0xFF), items, 0, 0 ); - } -} + if (keyAttributes & CentralSceneMask_KeyPressed1time) + { + Internal::VC::ValueList::Item item; + item.m_label = c_CentralScene_KeyAttributes[1]; + item.m_value = 1; + items.push_back(item); + } + if (keyAttributes & CentralSceneMask_KeyReleased) + { + Internal::VC::ValueList::Item item; + item.m_label = c_CentralScene_KeyAttributes[2]; + item.m_value = 2; + items.push_back(item); + } + if (keyAttributes & CentralSceneMask_HeldDown) + { + Internal::VC::ValueList::Item item; + item.m_label = c_CentralScene_KeyAttributes[3]; + item.m_value = 3; + items.push_back(item); + } + if (keyAttributes & CentralSceneMask_KeyPressed2times) + { + Internal::VC::ValueList::Item item; + item.m_label = c_CentralScene_KeyAttributes[4]; + item.m_value = 4; + items.push_back(item); + } + if (keyAttributes & CentralSceneMask_KeyPressed3times) + { + Internal::VC::ValueList::Item item; + item.m_label = c_CentralScene_KeyAttributes[5]; + item.m_value = 5; + items.push_back(item); + } + if (keyAttributes & CentralSceneMask_KeyPressed4times) + { + Internal::VC::ValueList::Item item; + item.m_label = c_CentralScene_KeyAttributes[6]; + item.m_value = 6; + items.push_back(item); + } + if (keyAttributes & CentralSceneMask_KeyPressed5times) + { + Internal::VC::ValueList::Item item; + item.m_label = c_CentralScene_KeyAttributes[7]; + item.m_value = 7; + items.push_back(item); + } + char lbl[64]; + snprintf(lbl, 64, "Scene %d", sceneNumber); + node->CreateValueList(ValueID::ValueGenre_User, GetCommandClassId(), instance, sceneNumber, lbl, "", true, false, (uint8_t) (items.size() & 0xFF), items, 0, 0); + } + } -void CentralScene::ClearScene -( - uint32 sceneID -) -{ + void CentralScene::ClearScene(uint32 sceneID) + { - uint8 _instance; - if (m_TimersSet.find(sceneID) != m_TimersSet.end()) { - _instance = m_TimersSet.at(sceneID); - } else { - Log::Write( LogLevel_Warning, "Can't find Timer in TimerSet List"); - return; - } + uint8 _instance; + if (m_TimersSet.find(sceneID) != m_TimersSet.end()) + { + _instance = m_TimersSet.at(sceneID); + } + else + { + Log::Write(LogLevel_Warning, "Can't find Timer in TimerSet List"); + return; + } - if( ValueList* value = static_cast( GetValue( _instance, sceneID ) ) ) - { - /* plus one, as we have our own "inactive" entry at index 0 */ - value->OnValueRefreshed( 0 ); - value->Release(); - } - m_TimersSet.erase(sceneID); + if (Internal::VC::ValueList* value = static_cast(GetValue(_instance, sceneID))) + { + /* plus one, as we have our own "inactive" entry at index 0 */ + value->OnValueRefreshed(0); + value->Release(); + } + m_TimersSet.erase(sceneID); -} + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/CentralScene.h b/cpp/src/command_classes/CentralScene.h index c7ea4d5e75..4ee15d13d1 100644 --- a/cpp/src/command_classes/CentralScene.h +++ b/cpp/src/command_classes/CentralScene.h @@ -33,51 +33,77 @@ namespace OpenZWave { - class ValueByte; - - /** \brief Implements COMMAND_CLASS_CENTRAL_SCENE (0x5B), a Z-Wave device command class. - * \ingroup CommandClass - */ - class CentralScene: public CommandClass, private Timer + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new CentralScene( _homeId, _nodeId ); } - virtual ~CentralScene(){} + namespace CC + { + + /** \brief Implements COMMAND_CLASS_CENTRAL_SCENE (0x5B), a Z-Wave device command class. + * \ingroup CommandClass + */ + class CentralScene: public CommandClass, private Timer + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new CentralScene(_homeId, _nodeId); + } + virtual ~CentralScene() + { + } - /** \brief Get command class ID (1 byte) identifying this command class. */ - static uint8 const StaticGetCommandClassId(){ return 0x5B; } - /** \brief Get a string containing the name of this command class. */ - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_CENTRAL_SCENE"; } + /** \brief Get command class ID (1 byte) identifying this command class. */ + static uint8 const StaticGetCommandClassId() + { + return 0x5B; + } + /** \brief Get a string containing the name of this command class. */ + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_CENTRAL_SCENE"; + } - // From CommandClass - /** \brief Get command class ID (1 byte) identifying this command class. (Inherited from CommandClass) */ - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - /** \brief Get a string containing the name of this command class. (Inherited from CommandClass) */ - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual uint8 GetMaxVersion(){ return 3; } - /** \brief Handle a response to a message associated with this command class. (Inherited from CommandClass) */ - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - /** \brief Create Default Vars for this CC */ - void CreateVars( uint8 const _instance ); - bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - bool RequestValue( uint32 const _requestFlags, uint16 const _what, uint8 const _instance, Driver::MsgQueue const _queue ); - bool SetValue( Value const& _value); - private: - /** - * Creates the ValueIDs for the keyAttributes - * @param identical - * @param keyAttributes - * @param sceneNumber - * @return - */ - void createSupportedKeyAttributesValues(uint8 keyAttributes, uint8 sceneNumber, uint8 instance); - void ClearScene(uint32 sceneID); - CentralScene( uint32 const _homeId, uint8 const _nodeId ); - bool m_slowrefresh; - uint8 m_sequence; - std::map m_TimersSet; - }; + // From CommandClass + /** \brief Get command class ID (1 byte) identifying this command class. (Inherited from CommandClass) */ + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + /** \brief Get a string containing the name of this command class. (Inherited from CommandClass) */ + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual uint8 GetMaxVersion() override + { + return 3; + } + /** \brief Handle a response to a message associated with this command class. (Inherited from CommandClass) */ + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + bool RequestValue(uint32 const _requestFlags, uint16 const _what, uint8 const _instance, Driver::MsgQueue const _queue) override; + bool SetValue(Internal::VC::Value const& _value) override; + protected: + /** \brief Create Default Vars for this CC */ + void CreateVars(uint8 const _instance) override; + private: + /** + * Creates the ValueIDs for the keyAttributes + * @param identical + * @param keyAttributes + * @param sceneNumber + * @return + */ + void createSupportedKeyAttributesValues(uint8 keyAttributes, uint8 sceneNumber, uint8 instance); + void ClearScene(uint32 sceneID); + CentralScene(uint32 const _homeId, uint8 const _nodeId); + bool m_slowrefresh; + uint8 m_sequence; + std::map m_TimersSet; + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/ClimateControlSchedule.cpp b/cpp/src/command_classes/ClimateControlSchedule.cpp index cc731f1e03..876de075d4 100644 --- a/cpp/src/command_classes/ClimateControlSchedule.cpp +++ b/cpp/src/command_classes/ClimateControlSchedule.cpp @@ -38,370 +38,351 @@ #include "tinyxml.h" -using namespace OpenZWave; - -enum ClimateControlScheduleCmd -{ - ClimateControlScheduleCmd_Set = 0x01, - ClimateControlScheduleCmd_Get, - ClimateControlScheduleCmd_Report, - ClimateControlScheduleCmd_ChangedGet, - ClimateControlScheduleCmd_ChangedReport, - ClimateControlScheduleCmd_OverrideSet, - ClimateControlScheduleCmd_OverrideGet, - ClimateControlScheduleCmd_OverrideReport -}; - -enum +namespace OpenZWave { - ClimateControlScheduleIndex_OverrideState = 8, - ClimateControlScheduleIndex_OverrideSetback = 9 -}; + namespace Internal + { + namespace CC + { -static char const* c_dayNames[] = -{ - "Invalid", - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday", - "Sunday" -}; - -static char const* c_overrideStateNames[] = -{ - "None", - "Temporary", - "Permanent", - "Invalid" -}; + enum ClimateControlScheduleCmd + { + ClimateControlScheduleCmd_Set = 0x01, + ClimateControlScheduleCmd_Get, + ClimateControlScheduleCmd_Report, + ClimateControlScheduleCmd_ChangedGet, + ClimateControlScheduleCmd_ChangedReport, + ClimateControlScheduleCmd_OverrideSet, + ClimateControlScheduleCmd_OverrideGet, + ClimateControlScheduleCmd_OverrideReport + }; + + static char const* c_dayNames[] = + { "Invalid", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" }; + + static char const* c_overrideStateNames[] = + { "None", "Temporary", "Permanent", "Invalid" }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -ClimateControlSchedule::ClimateControlSchedule -( - uint32 const _homeId, - uint8 const _nodeId -): -CommandClass( _homeId, _nodeId ) -{ - m_dom.EnableFlag(STATE_FLAG_CCS_CHANGECOUNTER, 0); -} + ClimateControlSchedule::ClimateControlSchedule(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + m_dom.EnableFlag(STATE_FLAG_CCS_CHANGECOUNTER, 0); + } //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool ClimateControlSchedule::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _requestFlags & RequestFlag_Session ) - { - // See if the schedule has changed since last time - return RequestValue( _requestFlags, 0, _instance, _queue ); - } + bool ClimateControlSchedule::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_requestFlags & RequestFlag_Session) + { + // See if the schedule has changed since last time + return RequestValue(_requestFlags, 0, _instance, _queue); + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool ClimateControlSchedule::RequestValue -( - uint32 const _requestFlags, - uint16 const _dummy1, // = 0 (not used) - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - // See if the schedule has changed since last time - Msg* msg = new Msg( "ClimateControlScheduleCmd_ChangedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( ClimateControlScheduleCmd_ChangedGet ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; -} + bool ClimateControlSchedule::RequestValue(uint32 const _requestFlags, uint16 const _dummy1, // = 0 (not used) + uint8 const _instance, Driver::MsgQueue const _queue) + { + // See if the schedule has changed since last time + Msg* msg = new Msg("ClimateControlScheduleCmd_ChangedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(ClimateControlScheduleCmd_ChangedGet); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool ClimateControlSchedule::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if( ClimateControlScheduleCmd_Report == (ClimateControlScheduleCmd)_data[0] ) - { - uint8 day = _data[1] & 0x07; - - if (day > 7) /* size of c_dayNames */ - { - Log::Write (LogLevel_Warning, GetNodeId(), "Day Value was greater than range. Setting to Invalid"); - day = 0; - } - - Log::Write( LogLevel_Info, GetNodeId(), "Received climate control schedule report for %s", c_dayNames[day] ); - - if( ValueSchedule* value = static_cast( GetValue( _instance, day ) ) ) - { - // Remove any existing data - value->ClearSwitchPoints(); - - // Parse the switch point data - for( uint8 i=2; i<29; i+=3 ) + bool ClimateControlSchedule::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) { - uint8 setback = _data[i+2]; - if( setback == 0x7f ) + if (ClimateControlScheduleCmd_Report == (ClimateControlScheduleCmd) _data[0]) { - // Switch point is unused, so we stop parsing here - break; + uint8 day = _data[1] & 0x07; + + if (day > 7) /* size of c_dayNames */ + { + Log::Write(LogLevel_Warning, GetNodeId(), "Day Value was greater than range. Setting to Invalid"); + day = 0; + } + + Log::Write(LogLevel_Info, GetNodeId(), "Received climate control schedule report for %s", c_dayNames[day]); + + if (Internal::VC::ValueSchedule* value = static_cast(GetValue(_instance, day))) + { + // Remove any existing data + value->ClearSwitchPoints(); + + // Parse the switch point data + for (uint8 i = 2; i < 29; i += 3) + { + uint8 setback = _data[i + 2]; + if (setback == 0x7f) + { + // Switch point is unused, so we stop parsing here + break; + } + + uint8 hours = _data[i] & 0x1f; + uint8 minutes = _data[i + 1] & 0x3f; + + if (setback == 0x79) + { + Log::Write(LogLevel_Info, GetNodeId(), " Switch point at %02d:%02d, Frost Protection Mode", hours, minutes, c_dayNames[day]); + } + else if (setback == 0x7a) + { + Log::Write(LogLevel_Info, GetNodeId(), " Switch point at %02d:%02d, Energy Saving Mode", hours, minutes, c_dayNames[day]); + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), " Switch point at %02d:%02d, Setback %+.1fC", hours, minutes, ((float) setback) * 0.1f); + } + + value->SetSwitchPoint(hours, minutes, setback); + } + + if (!value->GetNumSwitchPoints()) + { + Log::Write(LogLevel_Info, GetNodeId(), " No Switch points have been set"); + } + + // Notify the user + value->OnValueRefreshed(); + value->Release(); + } + + return true; } - uint8 hours = _data[i] & 0x1f; - uint8 minutes = _data[i+1] & 0x3f; - - if( setback == 0x79 ) + if (ClimateControlScheduleCmd_ChangedReport == (ClimateControlScheduleCmd) _data[0]) { - Log::Write( LogLevel_Info, GetNodeId(), " Switch point at %02d:%02d, Frost Protection Mode", hours, minutes, c_dayNames[day] ); + Log::Write(LogLevel_Info, GetNodeId(), "Received climate control schedule changed report:"); + + if (_data[1]) + { + if (_data[1] != m_dom.GetFlagByte(STATE_FLAG_CCS_CHANGECOUNTER)) + { + m_dom.SetFlagByte(STATE_FLAG_CCS_CHANGECOUNTER, _data[1]); + + // The schedule has changed and is not in override mode, so request reports for each day + for (int i = 1; i <= 7; ++i) + { + Log::Write(LogLevel_Info, GetNodeId(), "Get climate control schedule for %s", c_dayNames[i]); + + Msg* msg = new Msg("ClimateControlScheduleCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(ClimateControlScheduleCmd_Get); + msg->Append(i); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + } + } + } + else + { + // Device is in override mode, so we request details of that instead + Msg* msg = new Msg("ClimateControlScheduleCmd_OverrideGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(ClimateControlScheduleCmd_OverrideGet); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + } + return true; } - else if( setback == 0x7a ) - { - Log::Write( LogLevel_Info, GetNodeId(), " Switch point at %02d:%02d, Energy Saving Mode", hours, minutes, c_dayNames[day] ); - } - else - { - Log::Write( LogLevel_Info, GetNodeId(), " Switch point at %02d:%02d, Setback %+.1fC", hours, minutes, ((float)setback)*0.1f ); - } - - value->SetSwitchPoint( hours, minutes, setback ); - } - - if( !value->GetNumSwitchPoints() ) - { - Log::Write( LogLevel_Info, GetNodeId(), " No Switch points have been set" ); - } - - // Notify the user - value->OnValueRefreshed(); - value->Release(); - } - - return true; - } - - if( ClimateControlScheduleCmd_ChangedReport == (ClimateControlScheduleCmd)_data[0] ) - { - Log::Write( LogLevel_Info, GetNodeId(), "Received climate control schedule changed report:" ); - - if( _data[1] ) - { - if( _data[1] != m_dom.GetFlagByte(STATE_FLAG_CCS_CHANGECOUNTER) ) - { - m_dom.SetFlagByte(STATE_FLAG_CCS_CHANGECOUNTER, _data[1]); - // The schedule has changed and is not in override mode, so request reports for each day - for( int i=1; i<=7; ++i ) + if (ClimateControlScheduleCmd_OverrideReport == (ClimateControlScheduleCmd) _data[0]) { - Log::Write(LogLevel_Info, GetNodeId(), "Get climate control schedule for %s", c_dayNames[i] ); - - Msg* msg = new Msg( "ClimateControlScheduleCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( ClimateControlScheduleCmd_Get ); - msg->Append( i ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); + uint8 overrideState = _data[1] & 0x03; + if (overrideState > 3) /* size of c_overrideStateNames */ + { + Log::Write(LogLevel_Warning, GetNodeId(), "overrideState Value was greater than range. Setting to Invalid"); + overrideState = 3; + } + + Log::Write(LogLevel_Info, GetNodeId(), "Received climate control schedule override report:"); + Log::Write(LogLevel_Info, GetNodeId(), " Override State: %s:", c_overrideStateNames[overrideState]); + + if (Internal::VC::ValueList* valueList = static_cast(GetValue(_instance, ValueID_Index_ClimateControlSchedule::OverrideState))) + { + valueList->OnValueRefreshed((int) overrideState); + valueList->Release(); + } + + uint8 setback = _data[2]; + if (overrideState) + { + if (setback == 0x79) + { + Log::Write(LogLevel_Info, GetNodeId(), " Override Setback: Frost Protection Mode"); + } + else if (setback == 0x7a) + { + Log::Write(LogLevel_Info, GetNodeId(), " Override Setback: Energy Saving Mode"); + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), " Override Setback: %+.1fC", ((float) setback) * 0.1f); + } + } + + if (Internal::VC::ValueByte* valueByte = static_cast(GetValue(_instance, ValueID_Index_ClimateControlSchedule::OverrideSetback))) + { + valueByte->OnValueRefreshed(setback); + valueByte->Release(); + } + + return true; } - } - } - else - { - // Device is in override mode, so we request details of that instead - Msg* msg = new Msg( "ClimateControlScheduleCmd_OverrideGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( ClimateControlScheduleCmd_OverrideGet ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - } - return true; - } - - if( ClimateControlScheduleCmd_OverrideReport == (ClimateControlScheduleCmd)_data[0] ) - { - uint8 overrideState = _data[1] & 0x03; - if (overrideState > 3) /* size of c_overrideStateNames */ - { - Log::Write (LogLevel_Warning, GetNodeId(), "overrideState Value was greater than range. Setting to Invalid"); - overrideState = 3; - } - - Log::Write( LogLevel_Info, GetNodeId(), "Received climate control schedule override report:" ); - Log::Write( LogLevel_Info, GetNodeId(), " Override State: %s:", c_overrideStateNames[overrideState] ); - - if( ValueList* valueList = static_cast( GetValue( _instance, ClimateControlScheduleIndex_OverrideState ) ) ) - { - valueList->OnValueRefreshed( (int)overrideState ); - valueList->Release(); - } - uint8 setback = _data[2]; - if( overrideState ) - { - if( setback == 0x79 ) - { - Log::Write( LogLevel_Info, GetNodeId(), " Override Setback: Frost Protection Mode" ); + return false; } - else if( setback == 0x7a ) - { - Log::Write( LogLevel_Info, GetNodeId(), " Override Setback: Energy Saving Mode" ); - } - else - { - Log::Write( LogLevel_Info, GetNodeId(), " Override Setback: %+.1fC", ((float)setback)*0.1f ); - } - } - - if( ValueByte* valueByte = static_cast( GetValue( _instance, ClimateControlScheduleIndex_OverrideSetback ) ) ) - { - valueByte->OnValueRefreshed( setback ); - valueByte->Release(); - } - - return true; - } - - return false; -} //----------------------------------------------------------------------------- // // Set a value in the device //----------------------------------------------------------------------------- -bool ClimateControlSchedule::SetValue -( - Value const& _value -) -{ + bool ClimateControlSchedule::SetValue(Internal::VC::Value const& _value) + { // bool res = false; - uint8_t instance = _value.GetID().GetInstance(); - uint8_t idx = (uint8_t)(_value.GetID().GetIndex() & 0xFF); - - if( idx < 8 ) - { - // Set a schedule - ValueSchedule const* value = static_cast(&_value); + uint8_t instance = _value.GetID().GetInstance(); + uint8_t idx = (uint8_t) (_value.GetID().GetIndex() & 0xFF); - Log::Write( LogLevel_Info, GetNodeId(), "Set the climate control schedule for %s", c_dayNames[idx]); - - Msg* msg = new Msg( "ClimateControlScheduleCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, instance ); - msg->Append( GetNodeId() ); - msg->Append( 30 ); - msg->Append( GetCommandClassId() ); - msg->Append( ClimateControlScheduleCmd_Set ); - msg->Append( idx ); // Day of week + if (idx < 8) + { + // Set a schedule + Internal::VC::ValueSchedule const* value = static_cast(&_value); + + Log::Write(LogLevel_Info, GetNodeId(), "Set the climate control schedule for %s", c_dayNames[idx]); + + Msg* msg = new Msg("ClimateControlScheduleCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, instance); + msg->Append(GetNodeId()); + msg->Append(30); + msg->Append(GetCommandClassId()); + msg->Append(ClimateControlScheduleCmd_Set); + msg->Append(idx); // Day of week + + for (uint8_t i = 0; i < 9; ++i) + { + uint8_t hours; + uint8_t minutes; + int8 setback; + if (value->GetSwitchPoint(i, &hours, &minutes, &setback)) + { + msg->Append(hours); + msg->Append(minutes); + msg->Append(setback); + } + else + { + // Unused switch point + msg->Append(0); + msg->Append(0); + msg->Append(0x7f); + } + } + + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + } + else + { + // Set an override + if (Internal::VC::ValueList* state = static_cast(GetValue(instance, ValueID_Index_ClimateControlSchedule::OverrideState))) + { + if (Internal::VC::ValueList::Item const* item = state->GetItem()) + { + if (Internal::VC::ValueByte* setback = static_cast(GetValue(instance, ValueID_Index_ClimateControlSchedule::OverrideSetback))) + { + Msg* msg = new Msg("ClimateControlScheduleCmd_OverrideSet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + // nullptr check after "new" is kind of placebo, but it makes for consistent code + // discussion: https://github.com/OpenZWave/open-zwave/pull/1985 + if (msg != nullptr) + { + msg->SetInstance(this, instance); + msg->Append(GetNodeId()); + msg->Append(4); + msg->Append(GetCommandClassId()); + msg->Append(ClimateControlScheduleCmd_OverrideSet); + msg->Append((uint8)item->m_value); + msg->Append(setback->GetValue()); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + } + setback->Release(); + } + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "ClimateControlSchedule::SetValue couldn't Find ValueID_Index_ClimateControlSchedule::OverrideSetback"); + } + } + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "ClimateControlSchedule::SetValue state->GetItem() returned nullptr"); + } + state->Release(); + } + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "ClimateControlSchedule::SetValue couldn't Find ValueID_Index_ClimateControlSchedule::OverrideState"); + } + } - for( uint8_t i=0; i<9; ++i ) - { - uint8_t hours; - uint8_t minutes; - int8 setback; - if( value->GetSwitchPoint( i, &hours, &minutes, &setback ) ) - { - msg->Append( hours ); - msg->Append( minutes ); - msg->Append( setback ); + return true; } - else - { - // Unused switch point - msg->Append( 0 ); - msg->Append( 0 ); - msg->Append( 0x7f ); - } - } - - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - } - else - { - // Set an override - ValueList* state = static_cast( GetValue( instance, ClimateControlScheduleIndex_OverrideState ) ); - ValueByte* setback = static_cast( GetValue( instance, ClimateControlScheduleIndex_OverrideSetback ) ); - - if( state && setback ) - { - ValueList::Item const *item = state->GetItem(); - if (item == NULL) { - return false; - } - - Msg* msg = new Msg( "ClimateControlScheduleCmd_OverrideSet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, instance ); - msg->Append( GetNodeId() ); - msg->Append( 4 ); - msg->Append( GetCommandClassId() ); - msg->Append( ClimateControlScheduleCmd_OverrideSet ); - msg->Append( (uint8)item->m_value ); - msg->Append( setback->GetValue() ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - } - } - - return true; -} //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void ClimateControlSchedule::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - // Add a ValueSchedule for each day of the week. - for( uint8 i=0; i<7; ++i ) - { - node->CreateValueSchedule( ValueID::ValueGenre_User, GetCommandClassId(), _instance, i+1, c_dayNames[i+1], "", false, false, 0 ); - } - - // Add values for the override state and setback - vector items; - - ValueList::Item item; - for( uint8 i=0; i<3; ++i ) - { - item.m_label = c_overrideStateNames[i]; - item.m_value = i; - items.push_back( item ); - } - - node->CreateValueList( ValueID::ValueGenre_User, GetCommandClassId(), _instance, ClimateControlScheduleIndex_OverrideState, "Override State", "", false, false, 1, items, 0, 0 ); - node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, ClimateControlScheduleIndex_OverrideSetback, "Override Setback", "", false, false, 0, 0 ); - } -} + void ClimateControlSchedule::CreateVars(uint8 const _instance) + { + if (Node* node = GetNodeUnsafe()) + { + // Add a ValueSchedule for each day of the week. + for (uint8 i = 0; i < 7; ++i) + { + node->CreateValueSchedule(ValueID::ValueGenre_User, GetCommandClassId(), _instance, i + 1, c_dayNames[i + 1], "", false, false, 0); + } + + // Add values for the override state and setback + vector items; + + Internal::VC::ValueList::Item item; + for (uint8 i = 0; i < 3; ++i) + { + item.m_label = c_overrideStateNames[i]; + item.m_value = i; + items.push_back(item); + } + + node->CreateValueList(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_ClimateControlSchedule::OverrideState, "Override State", "", false, false, 1, items, 0, 0); + node->CreateValueByte(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_ClimateControlSchedule::OverrideSetback, "Override Setback", "", false, false, 0, 0); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/ClimateControlSchedule.h b/cpp/src/command_classes/ClimateControlSchedule.h index 41676f7969..fc905a0274 100644 --- a/cpp/src/command_classes/ClimateControlSchedule.h +++ b/cpp/src/command_classes/ClimateControlSchedule.h @@ -32,37 +32,56 @@ namespace OpenZWave { - class ValueSchedule; - class ValueList; - class ValueByte; - - /** \brief Implements COMMAND_CLASS_CLIMATE_CONTROL_SCHEDULE (0x46), a Z-Wave device command class. - * \ingroup CommandClass - */ - class ClimateControlSchedule: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new ClimateControlSchedule( _homeId, _nodeId ); } - virtual ~ClimateControlSchedule(){} + namespace CC + { - static uint8 const StaticGetCommandClassId(){ return 0x46; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_CLIMATE_CONTROL_SCHEDULE"; } + /** \brief Implements COMMAND_CLASS_CLIMATE_CONTROL_SCHEDULE (0x46), a Z-Wave device command class. + * \ingroup CommandClass + */ + class ClimateControlSchedule: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new ClimateControlSchedule(_homeId, _nodeId); + } + virtual ~ClimateControlSchedule() + { + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool SetValue( Value const& _value ); + static uint8 const StaticGetCommandClassId() + { + return 0x46; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_CLIMATE_CONTROL_SCHEDULE"; + } - protected: - virtual void CreateVars( uint8 const _instance ); + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool SetValue(Internal::VC::Value const& _value) override; - private: - ClimateControlSchedule( uint32 const _homeId, uint8 const _nodeId ); - }; + protected: + virtual void CreateVars(uint8 const _instance) override; + private: + ClimateControlSchedule(uint32 const _homeId, uint8 const _nodeId); + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/Clock.cpp b/cpp/src/command_classes/Clock.cpp index bf8f5316c0..d47eb54e5c 100644 --- a/cpp/src/command_classes/Clock.cpp +++ b/cpp/src/command_classes/Clock.cpp @@ -36,222 +36,200 @@ #include "value_classes/ValueByte.h" #include "value_classes/ValueList.h" -using namespace OpenZWave; - -enum ClockCmd +namespace OpenZWave { - ClockCmd_Set = 0x04, - ClockCmd_Get = 0x05, - ClockCmd_Report = 0x06 -}; + namespace Internal + { + namespace CC + { -enum -{ - ClockIndex_Day = 0, - ClockIndex_Hour, - ClockIndex_Minute -}; + enum ClockCmd + { + ClockCmd_Set = 0x04, + ClockCmd_Get = 0x05, + ClockCmd_Report = 0x06 + }; -static char const* c_dayNames[] = -{ - "Invalid", - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday", - "Sunday" -}; + static char const* c_dayNames[] = + { "Invalid", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" }; //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool Clock::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _requestFlags & RequestFlag_Dynamic ) - { - return RequestValue( _requestFlags, 0, _instance, _queue ); - } - - return false; -} + bool Clock::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_requestFlags & RequestFlag_Dynamic) + { + return RequestValue(_requestFlags, 0, _instance, _queue); + } + + return false; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool Clock::RequestValue -( - uint32 const _requestFlags, - uint16 const _dummy1, // = 0 (not used) - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Msg* msg = new Msg( "ClockCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( ClockCmd_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "ClockCmd_Get Not Supported on this node"); - } - return false; -} + bool Clock::RequestValue(uint32 const _requestFlags, uint16 const _dummy1, // = 0 (not used) + uint8 const _instance, Driver::MsgQueue const _queue) + { + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Msg* msg = new Msg("ClockCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(ClockCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "ClockCmd_Get Not Supported on this node"); + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool Clock::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if (ClockCmd_Report == (ClockCmd)_data[0]) - { - uint8 day = _data[1] >> 5; - uint8 hour = _data[1] & 0x1f; - uint8 minute = _data[2]; - - if (day > 7) /* size of c_dayNames */ - { - Log::Write (LogLevel_Warning, GetNodeId(), "Day Value was greater than range. Setting to Invalid"); - day = 0; - } - - Log::Write( LogLevel_Info, GetNodeId(), "Received Clock report: %s %.2d:%.2d", c_dayNames[day], hour, minute ); - - - if( ValueList* dayValue = static_cast( GetValue( _instance, ClockIndex_Day ) ) ) - { - dayValue->OnValueRefreshed( day ); - dayValue->Release(); - } - if( ValueByte* hourValue = static_cast( GetValue( _instance, ClockIndex_Hour ) ) ) - { - hourValue->OnValueRefreshed( hour ); - hourValue->Release(); - } - if( ValueByte* minuteValue = static_cast( GetValue( _instance, ClockIndex_Minute ) ) ) - { - minuteValue->OnValueRefreshed( minute ); - minuteValue->Release(); - } - return true; - } - - return false; -} + bool Clock::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) + { + if (ClockCmd_Report == (ClockCmd) _data[0]) + { + uint8 day = _data[1] >> 5; + uint8 hour = _data[1] & 0x1f; + uint8 minute = _data[2]; + + if (day > 7) /* size of c_dayNames */ + { + Log::Write(LogLevel_Warning, GetNodeId(), "Day Value was greater than range. Setting to Invalid"); + day = 0; + } + + Log::Write(LogLevel_Info, GetNodeId(), "Received Clock report: %s %.2d:%.2d", c_dayNames[day], hour, minute); + + if (Internal::VC::ValueList* dayValue = static_cast(GetValue(_instance, ValueID_Index_Clock::Day))) + { + dayValue->OnValueRefreshed(day); + dayValue->Release(); + } + if (Internal::VC::ValueByte* hourValue = static_cast(GetValue(_instance, ValueID_Index_Clock::Hour))) + { + hourValue->OnValueRefreshed(hour); + hourValue->Release(); + } + if (Internal::VC::ValueByte* minuteValue = static_cast(GetValue(_instance, ValueID_Index_Clock::Minute))) + { + minuteValue->OnValueRefreshed(minute); + minuteValue->Release(); + } + return true; + } + + return false; + } //----------------------------------------------------------------------------- // // Set a value in the Z-Wave device //----------------------------------------------------------------------------- -bool Clock::SetValue -( - Value const& _value -) -{ - bool ret = false; - - uint8 instance = _value.GetID().GetInstance(); - - ValueList* dayValue = static_cast( GetValue( instance, ClockIndex_Day ) ); - ValueByte* hourValue = static_cast( GetValue( instance, ClockIndex_Hour ) ); - ValueByte* minuteValue = static_cast( GetValue( instance, ClockIndex_Minute ) ); - - if( dayValue && hourValue && minuteValue ) - { - if (dayValue->GetItem() == NULL) { - ret = false; - } else { - uint8 day = dayValue->GetItem()->m_value; - if (_value.GetID() == dayValue->GetID()) { - ValueList const * dayvaluetmp = static_cast(&_value); - day = dayvaluetmp->GetItem()->m_value; - dayValue->OnValueRefreshed(day); - } - uint8 hour = hourValue->GetValue(); - if (_value.GetID() == hourValue->GetID()) { - ValueByte const * hourvaluetmp = static_cast(&_value); - hour = hourvaluetmp->GetValue(); - hourValue->OnValueRefreshed(hour); + bool Clock::SetValue(Internal::VC::Value const& _value) + { + bool ret = false; + + uint8 instance = _value.GetID().GetInstance(); + + Internal::VC::ValueList* dayValue = static_cast(GetValue(instance, ValueID_Index_Clock::Day)); + Internal::VC::ValueByte* hourValue = static_cast(GetValue(instance, ValueID_Index_Clock::Hour)); + Internal::VC::ValueByte* minuteValue = static_cast(GetValue(instance, ValueID_Index_Clock::Minute)); + + if (dayValue && hourValue && minuteValue) + { + if (dayValue->GetItem() == NULL) + { + ret = false; + } + else + { + uint8 day = dayValue->GetItem()->m_value; + if (_value.GetID() == dayValue->GetID()) + { + Internal::VC::ValueList const * dayvaluetmp = static_cast(&_value); + day = dayvaluetmp->GetItem()->m_value; + dayValue->OnValueRefreshed(day); + } + uint8 hour = hourValue->GetValue(); + if (_value.GetID() == hourValue->GetID()) + { + Internal::VC::ValueByte const * hourvaluetmp = static_cast(&_value); + hour = hourvaluetmp->GetValue(); + hourValue->OnValueRefreshed(hour); + } + uint8 minute = minuteValue->GetValue(); + if (_value.GetID() == minuteValue->GetID()) + { + Internal::VC::ValueByte const * minuteValuetmp = static_cast(&_value); + minute = minuteValuetmp->GetValue(); + minuteValue->OnValueRefreshed(minute); + } + + Msg* msg = new Msg("ClockCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->SetInstance(this, instance); + msg->Append(GetNodeId()); + msg->Append(4); + msg->Append(GetCommandClassId()); + msg->Append(ClockCmd_Set); + msg->Append((day << 5) | hour); + msg->Append(minute); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + ret = true; + } + } + + if (dayValue != NULL) + { + dayValue->Release(); + } + if (hourValue != NULL) + { + hourValue->Release(); + } + if (minuteValue != NULL) + { + minuteValue->Release(); + } + return ret; } - uint8 minute = minuteValue->GetValue(); - if (_value.GetID() == minuteValue->GetID()) { - ValueByte const * minuteValuetmp = static_cast(&_value); - minute = minuteValuetmp->GetValue(); - minuteValue->OnValueRefreshed(minute); - } - - - Msg* msg = new Msg( "ClockCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->SetInstance( this, instance ); - msg->Append( GetNodeId() ); - msg->Append( 4 ); - msg->Append( GetCommandClassId() ); - msg->Append( ClockCmd_Set ); - msg->Append( ( day << 5 ) | hour ); - msg->Append( minute ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - ret = true; - } - } - - if( dayValue != NULL ) - { - dayValue->Release(); - } - if( hourValue != NULL ) - { - hourValue->Release(); - } - if( minuteValue != NULL ) - { - minuteValue->Release(); - } - return ret; -} //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void Clock::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - vector items; - for( int i=1; i<=7; ++i ) - { - ValueList::Item item; - item.m_label = c_dayNames[i]; - item.m_value = i; - items.push_back( item ); - } - - node->CreateValueList( ValueID::ValueGenre_User, GetCommandClassId(), _instance, ClockIndex_Day, "Day", "", false, false, 1, items, 0, 0 ); - node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, ClockIndex_Hour, "Hour", "", false, false, 12, 0 ); - node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, ClockIndex_Minute, "Minute", "", false, false, 0, 0 ); - } -} + void Clock::CreateVars(uint8 const _instance) + { + if (Node* node = GetNodeUnsafe()) + { + vector items; + for (int i = 1; i <= 7; ++i) + { + Internal::VC::ValueList::Item item; + item.m_label = c_dayNames[i]; + item.m_value = i; + items.push_back(item); + } + + node->CreateValueList(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_Clock::Day, "Day", "", false, false, 1, items, 0, 0); + node->CreateValueByte(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_Clock::Hour, "Hour", "", false, false, 12, 0); + node->CreateValueByte(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_Clock::Minute, "Minute", "", false, false, 0, 0); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/Clock.h b/cpp/src/command_classes/Clock.h index 01907a7e15..096a4aa112 100644 --- a/cpp/src/command_classes/Clock.h +++ b/cpp/src/command_classes/Clock.h @@ -32,36 +32,59 @@ namespace OpenZWave { - class ValueByte; - class ValueList; - - /** \brief Implements COMMAND_CLASS_CLOCK (0x81), a Z-Wave device command class. - * \ingroup CommandClass - */ - class Clock: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Clock( _homeId, _nodeId ); } - virtual ~Clock(){} + namespace CC + { - static uint8 const StaticGetCommandClassId(){ return 0x81; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_CLOCK"; } + /** \brief Implements COMMAND_CLASS_CLOCK (0x81), a Z-Wave device command class. + * \ingroup CommandClass + */ + class Clock: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new Clock(_homeId, _nodeId); + } + virtual ~Clock() + { + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool SetValue( Value const& _value ); + static uint8 const StaticGetCommandClassId() + { + return 0x81; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_CLOCK"; + } - protected: - virtual void CreateVars( uint8 const _instance ); + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool SetValue(Internal::VC::Value const& _value) override; - private: - Clock( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} - }; + protected: + virtual void CreateVars(uint8 const _instance) override; + private: + Clock(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + } + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/Color.cpp b/cpp/src/command_classes/Color.cpp index 5889f219d4..98e42cb050 100644 --- a/cpp/src/command_classes/Color.cpp +++ b/cpp/src/command_classes/Color.cpp @@ -28,7 +28,6 @@ #include #include - #include "command_classes/CommandClasses.h" #include "command_classes/Color.h" #include "Defs.h" @@ -43,20 +42,24 @@ #include "tinyxml.h" - -using namespace OpenZWave; - -enum ColorCmd +namespace OpenZWave { - ColorCmd_Capability_Get = 0x01, - ColorCmd_Capability_Report = 0x02, - ColorCmd_Get = 0x03, - ColorCmd_Report = 0x04, - ColorCmd_Set = 0x05, - /* Version 2 */ - ColorCmd_StartCapabilityLevelChange = 0x06, - ColorCmd_StopStateChange = 0x07 -}; + namespace Internal + { + namespace CC + { + + enum ColorCmd + { + ColorCmd_Capability_Get = 0x01, + ColorCmd_Capability_Report = 0x02, + ColorCmd_Get = 0x03, + ColorCmd_Report = 0x04, + ColorCmd_Set = 0x05, + /* Version 2 */ + ColorCmd_StartCapabilityLevelChange = 0x06, + ColorCmd_StopStateChange = 0x07 + }; //Capabilities //0=Warm White (0x00 - 0xFF: 0 100%) @@ -69,178 +72,136 @@ enum ColorCmd //7=Purple (for 6ch Color mixing) (0x00 - 0xFF: 0 100%) //8=Indexed Color (0x00 0x0FF: Color Index 0 - 255 + enum ColorIDX + { + COLORIDX_WARMWHITE, + COLORIDX_COLDWHITE, + COLORIDX_RED, + COLORIDX_GREEN, + COLORIDX_BLUE, + COLORIDX_AMBER, + COLORIDX_CYAN, + COLORIDX_PURPLE, + COLORIDX_INDEXCOLOR + }; -enum ColorIDX { - COLORIDX_WARMWHITE, - COLORIDX_COLDWHITE, - COLORIDX_RED, - COLORIDX_GREEN, - COLORIDX_BLUE, - COLORIDX_AMBER, - COLORIDX_CYAN, - COLORIDX_PURPLE, - COLORIDX_INDEXCOLOR -}; - -static char const* c_ColorIndex[] = -{ - "Off", - "Cool White", - "Warm White", - "Red", - "Lime", - "Blue", - "Yellow", - "Cyan", - "Magenta", - "Silver", - "Gray", - "Maroon", - "Olive", - "Green", - "Purple", - "Teal", - "Navy", - "Custom" -}; - - - -enum ValueIDSystemIndexes -{ - Value_Color = 0x00, /* RGB Color */ - Value_Color_Index = 0x01, /* Color Index if Set */ - Value_Color_Channels_Capabilities = 0x02, /* Color Channels Capabilities */ - Value_Color_Duration = 0x03 -}; + static char const* c_ColorIndex[] = + { "Off", "Cool White", "Warm White", "Red", "Lime", "Blue", "Yellow", "Cyan", "Magenta", "Silver", "Gray", "Maroon", "Olive", "Green", "Purple", "Teal", "Navy", "Custom" }; + enum ValueIDSystemIndexes + { + }; -Color::Color -( - uint32 const _homeId, - uint8 const _nodeId -): -CommandClass( _homeId, _nodeId ), -m_refreshinprogress ( false ), -m_coloridxcount ( 0 ) -{ - m_com.EnableFlag(COMPAT_FLAG_COLOR_IDXBUG, false); - m_dom.EnableFlag(STATE_FLAG_COLOR_CHANNELS, 0); + Color::Color(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId), m_refreshinprogress(false), m_coloridxcount(0) + { + m_com.EnableFlag(COMPAT_FLAG_COLOR_IDXBUG, false); + m_dom.EnableFlag(STATE_FLAG_COLOR_CHANNELS, 0); - for (uint8 i = 0; i < 9; i++) - m_colorvalues[i] = 0; - SetStaticRequest( StaticRequest_Values ); -} + for (uint8 i = 0; i < 9; i++) + m_colorvalues[i] = 0; + SetStaticRequest(StaticRequest_Values); + } //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool Color::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - bool requests = false; - if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) ) - { - /* if we havn't got a valid capability from our Config File, then get what the device is capable of. If the user changes the Color Channels Value we use the stored version instead */ - if (m_dom.GetFlagShort(STATE_FLAG_COLOR_CHANNELS) == 0) { - Msg* msg = new Msg("ColorCmd_CapabilityGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); - msg->Append(GetNodeId()); - msg->Append(2); - msg->Append(GetCommandClassId()); - msg->Append(ColorCmd_Capability_Get); - msg->Append(GetDriver()->GetTransmitOptions()); - GetDriver()->SendMsg(msg, _queue); - } - return true; - } - if (_requestFlags & RequestFlag_Dynamic) - { - /* do a request for each channel. the RequestValue will filter out channels that are not supported - * by the device - */ - if (m_refreshinprogress == true) { - Log::Write(LogLevel_Info, GetNodeId(), "Color Refresh in progress"); - return false; - } + bool Color::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + bool requests = false; + if ((_requestFlags & RequestFlag_Static) && HasStaticRequest(StaticRequest_Values)) + { + /* if we havn't got a valid capability from our Config File, then get what the device is capable of. If the user changes the Color Channels Value we use the stored version instead */ + if (m_dom.GetFlagShort(STATE_FLAG_COLOR_CHANNELS) == 0) + { + Msg* msg = new Msg("ColorCmd_CapabilityGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(ColorCmd_Capability_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + } + return true; + } + if (_requestFlags & RequestFlag_Dynamic) + { + /* do a request for each channel. the RequestValue will filter out channels that are not supported + * by the device + */ + if (m_refreshinprogress == true) + { + Log::Write(LogLevel_Info, GetNodeId(), "Color Refresh in progress"); + return false; + } - /* if the device has the ColorIDX bug, then only request the first channel. We will get the rest later */ - for (int i = 0; i <= 9; i++) { - bool tmprequests = RequestColorChannelReport(i, _instance, _queue ); - if (tmprequests) - m_coloridxcount = i; - requests |= tmprequests; - if (m_com.GetFlagBool(COMPAT_FLAG_COLOR_IDXBUG) && tmprequests) { - m_refreshinprogress = true; - break; - } - } - } + /* if the device has the ColorIDX bug, then only request the first channel. We will get the rest later */ + for (int i = 0; i <= 9; i++) + { + bool tmprequests = RequestColorChannelReport(i, _instance, _queue); + if (tmprequests) + m_coloridxcount = i; + requests |= tmprequests; + if (m_com.GetFlagBool(COMPAT_FLAG_COLOR_IDXBUG) && tmprequests) + { + m_refreshinprogress = true; + break; + } + } + } - return requests; -} + return requests; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool Color::RequestValue -( - uint32 const _requestFlags, - uint16 const _what, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) && (_what == Value_Color || _what == Value_Color_Index)) - { - if (m_com.GetFlagBool(COMPAT_FLAG_COLOR_IDXBUG) && m_refreshinprogress == true) - { - Log::Write(LogLevel_Warning, GetNodeId(), "ColorRefresh is already in progress. Ignoring Get Request"); - return false; - } - for (int i = 0; i <= 9; i++) { - if (RequestColorChannelReport(i, _instance, _queue)) + bool Color::RequestValue(uint32 const _requestFlags, uint16 const _what, uint8 const _instance, Driver::MsgQueue const _queue) { - if (m_com.GetFlagBool(COMPAT_FLAG_COLOR_IDXBUG)) { - m_refreshinprogress = true; - m_coloridxcount = 0; - return true; + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) && (_what == ValueID_Index_Color::Color || _what == ValueID_Index_Color::Index)) + { + if (m_com.GetFlagBool(COMPAT_FLAG_COLOR_IDXBUG) && m_refreshinprogress == true) + { + Log::Write(LogLevel_Warning, GetNodeId(), "ColorRefresh is already in progress. Ignoring Get Request"); + return false; + } + for (int i = 0; i <= 9; i++) + { + if (RequestColorChannelReport(i, _instance, _queue)) + { + if (m_com.GetFlagBool(COMPAT_FLAG_COLOR_IDXBUG)) + { + m_refreshinprogress = true; + m_coloridxcount = 0; + return true; + } + } + } } + return false; } - } - } - return false; -} - -bool Color::RequestColorChannelReport -( - uint8 const coloridx, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - /* make sure our coloridx is valid */ - if ((m_dom.GetFlagShort(STATE_FLAG_COLOR_CHANNELS)) & (1<<(coloridx))) { - Msg* msg = new Msg("ColorCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( ColorCmd_Get ); - msg->Append( coloridx ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } - return false; -} + bool Color::RequestColorChannelReport(uint8 const coloridx, uint8 const _instance, Driver::MsgQueue const _queue) + { + /* make sure our coloridx is valid */ + if ((m_dom.GetFlagShort(STATE_FLAG_COLOR_CHANNELS)) & (1 << (coloridx))) + { + Msg* msg = new Msg("ColorCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(ColorCmd_Get); + msg->Append(coloridx); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + return false; + } //----------------------------------------------------------------------------- // @@ -249,825 +210,936 @@ bool Color::RequestColorChannelReport // where the color values in [] are optional. // throws a exception when position is out of bounds //----------------------------------------------------------------------------- -uint16 GetColor(string rgbstring, uint8 const position) { + uint16 GetColor(std::string rgbstring, uint8 const position) + { - /* check the length of the string based on position value we passed in including the #*/ - if (rgbstring.length() < (size_t)(position *2)+1) { - Log::Write( LogLevel_Warning, "Request for Color Position %d exceeds String Length: %s", position, rgbstring.c_str()); - throw; - } - string result = rgbstring.substr(((position - 1) * 2) +1, 2); - std::stringstream ss(result); - uint16 rawresult; - ss >> std::hex >> rawresult; - return rawresult; -} + /* check the length of the string based on position value we passed in including the #*/ + if (rgbstring.length() < (size_t) (position * 2) + 1) + { + OpenZWave::Log::Write(OpenZWave::LogLevel_Warning, "Request for Color Position %d exceeds String Length: %s", position, rgbstring.c_str()); + throw; + } + std::string result = rgbstring.substr(((position - 1) * 2) + 1, 2); + std::stringstream ss(result); + uint16 rawresult; + ss >> std::hex >> rawresult; + return rawresult; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool Color::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if (ColorCmd_Capability_Report == (ColorCmd)_data[0]) - { - m_dom.SetFlagShort(STATE_FLAG_COLOR_CHANNELS, (_data[1] + (_data[2] << 8))); - uint16_t f_capabilities = m_dom.GetFlagShort(STATE_FLAG_COLOR_CHANNELS); - string helpstr = "#RRGGBB"; - Log::Write(LogLevel_Info, GetNodeId(), "Received an Color Capability Report: Capability=%x", f_capabilities); - if (f_capabilities & 0x04) - Log::Write(LogLevel_Info, GetNodeId(), "Red (0x02)"); - if (f_capabilities & 0x08) - Log::Write(LogLevel_Info, GetNodeId(), "Green (0x03)"); - if (f_capabilities & 0x10) - Log::Write(LogLevel_Info, GetNodeId(), "Blue (0x04)"); - if (f_capabilities & 0x01) { - Log::Write(LogLevel_Info, GetNodeId(), "Warm White (0x00)"); - helpstr += "WW"; - } - if (f_capabilities & 0x02) { - Log::Write(LogLevel_Info, GetNodeId(), "Cold White (0x01)"); - helpstr += "CW"; - } - if (f_capabilities & 0x20) { - Log::Write(LogLevel_Info, GetNodeId(), "Amber (0x05)"); - helpstr += "AM"; - } - if (f_capabilities & 0x40) { - Log::Write(LogLevel_Info, GetNodeId(), "Cyan (0x06)"); - helpstr += "CY"; - } - if (f_capabilities & 0x80) { - Log::Write(LogLevel_Info, GetNodeId(), "Purple (0x07)"); - helpstr += "PR"; - } - if (f_capabilities & 0x100) - Log::Write(LogLevel_Info, GetNodeId(), "Indexed Color (0x08)"); - if( ValueInt* colorchannels = static_cast( GetValue( _instance, Value_Color_Channels_Capabilities ) ) ) - { - colorchannels->OnValueRefreshed( f_capabilities ); - colorchannels->Release(); - } - if( Node* node = GetNodeUnsafe() ) - { - if ( ValueString *color = static_cast( GetValue( _instance, Value_Color ) ) ) - { - color->SetUnits(helpstr); - } - else - { - node->CreateValueString( ValueID::ValueGenre_User, GetCommandClassId(), _instance, Value_Color, "Color", helpstr, false, false, "#000000", 0 ); - } - - /* always create the ColorIndex Value - If the device doesn't support Indexed Colors, we fake it up when sending */ + bool Color::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) { - vector items; - unsigned int size = (sizeof(c_ColorIndex)/sizeof(c_ColorIndex[0])); - for( unsigned int i=0; i < size; i++) + if (ColorCmd_Capability_Report == (ColorCmd) _data[0]) { - ValueList::Item item; - item.m_label = c_ColorIndex[i]; - item.m_value = i; - items.push_back( item ); - } - node->CreateValueList( ValueID::ValueGenre_User, GetCommandClassId(), _instance, Value_Color_Index, "Color Index", "", false, false, (sizeof(c_ColorIndex)/sizeof(c_ColorIndex[0])), items, 0, 0 ); - - } - - if (GetVersion() > 1) - node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, Value_Color_Duration, "Duration", "Sec", false, false, 255, 0 ); + m_dom.SetFlagShort(STATE_FLAG_COLOR_CHANNELS, (_data[1] + (_data[2] << 8))); + uint16_t f_capabilities = m_dom.GetFlagShort(STATE_FLAG_COLOR_CHANNELS); + string helpstr = "#RRGGBB"; + Log::Write(LogLevel_Info, GetNodeId(), "Received an Color Capability Report: Capability=%x", f_capabilities); + if (f_capabilities & 0x04) + Log::Write(LogLevel_Info, GetNodeId(), "Red (0x02)"); + if (f_capabilities & 0x08) + Log::Write(LogLevel_Info, GetNodeId(), "Green (0x03)"); + if (f_capabilities & 0x10) + Log::Write(LogLevel_Info, GetNodeId(), "Blue (0x04)"); + if (f_capabilities & 0x01) + { + Log::Write(LogLevel_Info, GetNodeId(), "Warm White (0x00)"); + helpstr += "WW"; + } + if (f_capabilities & 0x02) + { + Log::Write(LogLevel_Info, GetNodeId(), "Cold White (0x01)"); + helpstr += "CW"; + } + if (f_capabilities & 0x20) + { + Log::Write(LogLevel_Info, GetNodeId(), "Amber (0x05)"); + helpstr += "AM"; + } + if (f_capabilities & 0x40) + { + Log::Write(LogLevel_Info, GetNodeId(), "Cyan (0x06)"); + helpstr += "CY"; + } + if (f_capabilities & 0x80) + { + Log::Write(LogLevel_Info, GetNodeId(), "Purple (0x07)"); + helpstr += "PR"; + } + if (f_capabilities & 0x100) + Log::Write(LogLevel_Info, GetNodeId(), "Indexed Color (0x08)"); + if (Internal::VC::ValueInt* colorchannels = static_cast(GetValue(_instance, ValueID_Index_Color::Channels_Capabilities))) + { + colorchannels->OnValueRefreshed(f_capabilities); + colorchannels->Release(); + } + if (Node* node = GetNodeUnsafe()) + { + if (Internal::VC::ValueString *color = static_cast(GetValue(_instance, ValueID_Index_Color::Color))) + { + color->SetUnits(helpstr); + } + else + { + node->CreateValueString(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_Color::Color, "Color", helpstr, false, false, "#000000", 0); + } - } - return true; - } - if (ColorCmd_Report == (ColorCmd)_data[0]) - { - /* Fibaro is messed up. It always returns 0x03 as the Coloridx in a report message, but the values are correct for what the request was. - * I read a forum post about it being a bug. If this is a case, its going to make this class messy as hell :( - * - * http://forum.z-wave.me/viewtopic.php?f=3422&t=20042 - * - * Received: 0x01, 0x0a, 0x00, 0x04, 0x00, 0x34, 0x04, 0x33, 0x04, 0x03, 0xff, 0x0a - * ^^^^ - * Always 0x03 - * ^^^^ - * But this appears to be the right value for the channel we requested - * - */ - /* request the next color index if we are bugged */ - uint8 coloridx = _data[1]; - if (m_com.GetFlagBool(COMPAT_FLAG_COLOR_IDXBUG)) { - coloridx = m_coloridxcount; - for (uint8 idx = m_coloridxcount + 1; idx < 9; idx++ ) { - if (RequestColorChannelReport(idx, _instance, Driver::MsgQueue_Send)) { - m_coloridxcount = idx; - break; - } - } - } - m_colorvalues[coloridx] = _data[2]; + /* always create the ColorIndex Value - If the device doesn't support Indexed Colors, we fake it up when sending */ + { + vector items; + unsigned int size = (sizeof(c_ColorIndex) / sizeof(c_ColorIndex[0])); + for (unsigned int i = 0; i < size; i++) + { + Internal::VC::ValueList::Item item; + item.m_label = c_ColorIndex[i]; + item.m_value = i; + items.push_back(item); + } + node->CreateValueList(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_Color::Index, "Color Index", "", false, false, (sizeof(c_ColorIndex) / sizeof(c_ColorIndex[0])), items, 0, 0); - /* test if there are any more valid coloridx */ - for ( uint8 idx = coloridx+1; idx < 9; idx++ ) { - if ((m_dom.GetFlagShort(STATE_FLAG_COLOR_CHANNELS)) & (1<<(idx))) { - return true; - } - } - if (m_com.GetFlagBool(COMPAT_FLAG_COLOR_IDXBUG)) - m_refreshinprogress = false; + } - /* if we get here, then we can update our ValueID */ - if( ValueString* color = static_cast( GetValue( _instance, Value_Color ) ) ) - { - /* create a RGB[W] String */ - std::stringstream ss; - std::stringstream ssbuf; - bool usingbuf = false; - uint16_t f_capabilities = m_dom.GetFlagShort(STATE_FLAG_COLOR_CHANNELS); - ss << "#"; - /* do R */ - if ((f_capabilities) & (1<<(COLORIDX_RED))) - ss << std::setw(2) << std::uppercase << std::hex << std::setfill('0') << (int)m_colorvalues[COLORIDX_RED]; - else - ss << "00"; - /* do G */ - if ((f_capabilities) & (1<<(COLORIDX_GREEN))) - ss << std::setw(2) << std::uppercase << std::hex << std::setfill('0') << (int)m_colorvalues[COLORIDX_GREEN]; - else - ss << "00"; - /* do B */ - if ((f_capabilities) & (1<<(COLORIDX_BLUE))) - ss << std::setw(2) << std::uppercase << std::hex << std::setfill('0') << (int)m_colorvalues[COLORIDX_BLUE]; - else - ss << "00"; + if (GetVersion() > 1) + node->CreateValueByte(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_Color::Duration, "Duration", "Sec", false, false, 255, 0); - /* if both whites are present.... */ - if (((f_capabilities) & (1<<(COLORIDX_WARMWHITE))) - && ((f_capabilities) & (1<<(COLORIDX_COLDWHITE)))) { - /* append them both */ - ss << std::setw(2) << std::uppercase << std::hex << std::setfill('0') << (int)m_colorvalues[COLORIDX_WARMWHITE]; - ss << std::setw(2) << std::uppercase << std::hex << std::setfill('0') << (int)m_colorvalues[COLORIDX_COLDWHITE]; - } else if ((f_capabilities) & (1<<(COLORIDX_WARMWHITE))) { - /* else, if the warm white is present, append that */ - ss << std::setw(2) << std::uppercase << std::hex << std::setfill('0') << (int)m_colorvalues[COLORIDX_WARMWHITE]; - } else if ((f_capabilities) & (1<<(COLORIDX_COLDWHITE))) { - /* else, if the cold white is present, append that */ - ss << std::setw(2) << std::uppercase << std::hex << std::setfill('0') << (int)m_colorvalues[COLORIDX_COLDWHITE]; - } else { - /* we put 0000 into our buffer to represent both Warm and Cold white */ - ssbuf << "0000"; - usingbuf = true; - } - if ((f_capabilities) & (1<<(COLORIDX_AMBER))) { - /* if AMBER is present, append our buffer if needed */ - if (usingbuf) { - ss << ssbuf.str(); - ssbuf.str(""); - ssbuf.clear(); - usingbuf = false; - } - /* and then our Color */ - ss << std::setw(2) << std::uppercase << std::hex << std::setfill('0') << (int)m_colorvalues[COLORIDX_AMBER]; - } else { - /* put 00 into our buffer */ - ssbuf << "00"; - usingbuf = true; - } - if ((f_capabilities) & (1<<(COLORIDX_CYAN))) { - /* if CYAN is present, append our buffer if needed */ - if (usingbuf) { - ss << ssbuf.str(); - ssbuf.str(""); - ssbuf.clear(); - usingbuf = false; - } - /* and then our Color */ - ss << std::setw(2) << std::uppercase << std::hex << std::setfill('0') << (int)m_colorvalues[COLORIDX_CYAN]; - } else { - /* put 00 into our buffer */ - ssbuf << "00"; - usingbuf = true; - } - if ((f_capabilities) & (1<<(COLORIDX_PURPLE))) { - /* if PURPLE is present, append our buffer if needed */ - if (usingbuf) { - ss << ssbuf.str(); - ssbuf.str(""); - ssbuf.clear(); - usingbuf = false; + } + return true; } - /* and then our Color */ - ss << std::setw(2) << std::uppercase << std::hex << std::setfill('0') << (int)m_colorvalues[COLORIDX_PURPLE]; - } - /* No need for a else case here as COLORIDX_PURPLE is the last color. If its not supported, we - * don't put anything in our Color String - */ - - Log::Write(LogLevel_Info, GetNodeId(), "Received a updated Color from Device: %s", ss.str().c_str() ); - color->OnValueRefreshed( string(ss.str()) ); - color->Release(); - - /* if we don't support the Color Index then fake it */ - if (!(f_capabilities & (1<<(COLORIDX_INDEXCOLOR)))) { - if( ValueList* coloridx = static_cast( GetValue( _instance, Value_Color_Index ) ) ) + if (ColorCmd_Report == (ColorCmd) _data[0]) { - /* it supports the AMBER/CYAN/PURPLE Channels */ - if (f_capabilities > 31) { - /* Custom */ - coloridx->OnValueRefreshed( 17 ); - coloridx->Release(); - return true; - } - if ((f_capabilities) & (1<<(COLORIDX_WARMWHITE))) { - if (ss.str().substr(0, 9) == "#000000FF") { - /* Warm White */ - coloridx->OnValueRefreshed(2); - coloridx->Release(); - return true; + /* Fibaro is messed up. It always returns 0x03 as the Coloridx in a report message, but the values are correct for what the request was. + * I read a forum post about it being a bug. If this is a case, its going to make this class messy as hell :( + * + * http://forum.z-wave.me/viewtopic.php?f=3422&t=20042 + * + * Received: 0x01, 0x0a, 0x00, 0x04, 0x00, 0x34, 0x04, 0x33, 0x04, 0x03, 0xff, 0x0a + * ^^^^ + * Always 0x03 + * ^^^^ + * But this appears to be the right value for the channel we requested + * + */ + /* request the next color index if we are bugged */ + uint8 coloridx = _data[1]; + if (m_com.GetFlagBool(COMPAT_FLAG_COLOR_IDXBUG)) + { + coloridx = m_coloridxcount; + for (uint8 idx = m_coloridxcount + 1; idx < 9; idx++) + { + if (RequestColorChannelReport(idx, _instance, Driver::MsgQueue_Send)) + { + m_coloridxcount = idx; + break; + } } } - if ((f_capabilities) & (1<<(COLORIDX_COLDWHITE))) { - if (ss.str().substr(0, 11) == "#00000000FF") { - /* Cool White */ - coloridx->OnValueRefreshed(1); - coloridx->Release(); + m_colorvalues[coloridx] = _data[2]; + + /* test if there are any more valid coloridx */ + for (uint8 idx = coloridx + 1; idx < 9; idx++) + { + if ((m_dom.GetFlagShort(STATE_FLAG_COLOR_CHANNELS)) & (1 << (idx))) + { return true; } } - if (ss.str().substr(0,7) == "#000000") { - /* off */ - coloridx->OnValueRefreshed(0); - coloridx->Release(); - return true; - } else if (ss.str().substr(0,7) == "#FFFFFF") { - /* White */ - coloridx->OnValueRefreshed(1); - coloridx->Release(); - return true; - } else if (ss.str().substr(0,7) == "#FF9329") { - /* warm white */ - coloridx->OnValueRefreshed(2); - coloridx->Release(); - return true; - } else if (ss.str().substr(0,7) == "#FF0000") { - /* red */ - coloridx->OnValueRefreshed(3); - coloridx->Release(); - return true; - } else if (ss.str().substr(0,7) == "#00FF00") { - /* lime */ - coloridx->OnValueRefreshed(4); - coloridx->Release(); - return true; - } else if (ss.str().substr(0,7) == "#0000FF") { - /* blue */ - coloridx->OnValueRefreshed(5); - coloridx->Release(); - return true; - } else if (ss.str().substr(0,7) == "#FFFF00") { - /* yellow */ - coloridx->OnValueRefreshed(6); - coloridx->Release(); - return true; - } else if (ss.str().substr(0,7) == "#00FFFF") { - /* Cyan */ - coloridx->OnValueRefreshed(7); - coloridx->Release(); - return true; - } else if (ss.str().substr(0,7) == "#FF00FF") { - /* Magenta */ - coloridx->OnValueRefreshed(8); - coloridx->Release(); - return true; - } else if (ss.str().substr(0,7) == "#C0C0C0") { - /* Silver */ - coloridx->OnValueRefreshed(9); - coloridx->Release(); - return true; - } else if (ss.str().substr(0,7) == "#808080") { - /* gray */ - coloridx->OnValueRefreshed(10); - coloridx->Release(); - return true; - } else if (ss.str().substr(0,7) == "#800000") { - /* maroon */ - coloridx->OnValueRefreshed(11); - coloridx->Release(); - return true; - } else if (ss.str().substr(0,7) == "#808000") { - /* Olive */ - coloridx->OnValueRefreshed(12); - coloridx->Release(); - return true; - } else if (ss.str().substr(0,7) == "#008000") { - /* green */ - coloridx->OnValueRefreshed(13); - coloridx->Release(); - return true; - } else if (ss.str().substr(0,7) == "#800080") { - /* purple */ - coloridx->OnValueRefreshed(14); - coloridx->Release(); - return true; - } else if (ss.str().substr(0,7) == "#008080") { - /* teal */ - coloridx->OnValueRefreshed(15); - coloridx->Release(); - return true; - } else if (ss.str().substr(0,7) == "#000080") { - /* navy */ - coloridx->OnValueRefreshed(16); - coloridx->Release(); - return true; - } else { - /* custom */ - coloridx->OnValueRefreshed(17); - coloridx->Release(); - return true; - } + if (m_com.GetFlagBool(COMPAT_FLAG_COLOR_IDXBUG)) + m_refreshinprogress = false; + /* if we get here, then we can update our ValueID */ + if (Internal::VC::ValueString* color = static_cast(GetValue(_instance, ValueID_Index_Color::Color))) + { + /* create a RGB[W] String */ + std::stringstream ss; + std::stringstream ssbuf; + bool usingbuf = false; + uint16_t f_capabilities = m_dom.GetFlagShort(STATE_FLAG_COLOR_CHANNELS); + ss << "#"; + /* do R */ + if ((f_capabilities) & (1 << (COLORIDX_RED))) + ss << std::setw(2) << std::uppercase << std::hex << std::setfill('0') << (int) m_colorvalues[COLORIDX_RED]; + else + ss << "00"; + /* do G */ + if ((f_capabilities) & (1 << (COLORIDX_GREEN))) + ss << std::setw(2) << std::uppercase << std::hex << std::setfill('0') << (int) m_colorvalues[COLORIDX_GREEN]; + else + ss << "00"; + /* do B */ + if ((f_capabilities) & (1 << (COLORIDX_BLUE))) + ss << std::setw(2) << std::uppercase << std::hex << std::setfill('0') << (int) m_colorvalues[COLORIDX_BLUE]; + else + ss << "00"; - } - } - } - /* if we got a updated Color Index Value - Update our ValueID */ - if ((m_dom.GetFlagShort(STATE_FLAG_COLOR_CHANNELS)) & (1<<(COLORIDX_INDEXCOLOR))) { - if( ValueList* coloridx = static_cast( GetValue( _instance, Value_Color_Index ) ) ) - { - coloridx->OnValueRefreshed( m_colorvalues[COLORIDX_INDEXCOLOR] ); - coloridx->Release(); - } - } - return true; - } - return false; -} + /* if both whites are present.... */ + if (((f_capabilities) & (1 << (COLORIDX_WARMWHITE))) && ((f_capabilities) & (1 << (COLORIDX_COLDWHITE)))) + { + /* append them both */ + ss << std::setw(2) << std::uppercase << std::hex << std::setfill('0') << (int) m_colorvalues[COLORIDX_WARMWHITE]; + ss << std::setw(2) << std::uppercase << std::hex << std::setfill('0') << (int) m_colorvalues[COLORIDX_COLDWHITE]; + } + else if ((f_capabilities) & (1 << (COLORIDX_WARMWHITE))) + { + /* else, if the warm white is present, append that */ + ss << std::setw(2) << std::uppercase << std::hex << std::setfill('0') << (int) m_colorvalues[COLORIDX_WARMWHITE]; + } + else if ((f_capabilities) & (1 << (COLORIDX_COLDWHITE))) + { + /* else, if the cold white is present, append that */ + ss << std::setw(2) << std::uppercase << std::hex << std::setfill('0') << (int) m_colorvalues[COLORIDX_COLDWHITE]; + } + else + { + /* we put 0000 into our buffer to represent both Warm and Cold white */ + ssbuf << "0000"; + usingbuf = true; + } + if ((f_capabilities) & (1 << (COLORIDX_AMBER))) + { + /* if AMBER is present, append our buffer if needed */ + if (usingbuf) + { + ss << ssbuf.str(); + ssbuf.str(""); + ssbuf.clear(); + usingbuf = false; + } + /* and then our Color */ + ss << std::setw(2) << std::uppercase << std::hex << std::setfill('0') << (int) m_colorvalues[COLORIDX_AMBER]; + } + else + { + /* put 00 into our buffer */ + ssbuf << "00"; + usingbuf = true; + } + if ((f_capabilities) & (1 << (COLORIDX_CYAN))) + { + /* if CYAN is present, append our buffer if needed */ + if (usingbuf) + { + ss << ssbuf.str(); + ssbuf.str(""); + ssbuf.clear(); + usingbuf = false; + } + /* and then our Color */ + ss << std::setw(2) << std::uppercase << std::hex << std::setfill('0') << (int) m_colorvalues[COLORIDX_CYAN]; + } + else + { + /* put 00 into our buffer */ + ssbuf << "00"; + usingbuf = true; + } + if ((f_capabilities) & (1 << (COLORIDX_PURPLE))) + { + /* if PURPLE is present, append our buffer if needed */ + if (usingbuf) + { + ss << ssbuf.str(); + ssbuf.str(""); + ssbuf.clear(); + usingbuf = false; + } + /* and then our Color */ + ss << std::setw(2) << std::uppercase << std::hex << std::setfill('0') << (int) m_colorvalues[COLORIDX_PURPLE]; + } + /* No need for a else case here as COLORIDX_PURPLE is the last color. If its not supported, we + * don't put anything in our Color String + */ + Log::Write(LogLevel_Info, GetNodeId(), "Received a updated Color from Device: %s", ss.str().c_str()); + color->OnValueRefreshed(string(ss.str())); + color->Release(); + /* if we don't support the Color Index then fake it */ + if (!(f_capabilities & (1 << (COLORIDX_INDEXCOLOR)))) + { + if (Internal::VC::ValueList* coloridx = static_cast(GetValue(_instance, ValueID_Index_Color::Index))) + { + /* it supports the AMBER/CYAN/PURPLE Channels */ + if (f_capabilities > 31) + { + /* Custom */ + coloridx->OnValueRefreshed(17); + coloridx->Release(); + return true; + } + if ((f_capabilities) & (1 << (COLORIDX_WARMWHITE))) + { + if (ss.str().substr(0, 9) == "#000000FF") + { + /* Warm White */ + coloridx->OnValueRefreshed(2); + coloridx->Release(); + return true; + } + } + if ((f_capabilities) & (1 << (COLORIDX_COLDWHITE))) + { + if (ss.str().substr(0, 11) == "#00000000FF") + { + /* Cool White */ + coloridx->OnValueRefreshed(1); + coloridx->Release(); + return true; + } + } + if (ss.str().substr(0, 7) == "#000000") + { + /* off */ + coloridx->OnValueRefreshed(0); + coloridx->Release(); + return true; + } + else if (ss.str().substr(0, 7) == "#FFFFFF") + { + /* White */ + coloridx->OnValueRefreshed(1); + coloridx->Release(); + return true; + } + else if (ss.str().substr(0, 7) == "#FF9329") + { + /* warm white */ + coloridx->OnValueRefreshed(2); + coloridx->Release(); + return true; + } + else if (ss.str().substr(0, 7) == "#FF0000") + { + /* red */ + coloridx->OnValueRefreshed(3); + coloridx->Release(); + return true; + } + else if (ss.str().substr(0, 7) == "#00FF00") + { + /* lime */ + coloridx->OnValueRefreshed(4); + coloridx->Release(); + return true; + } + else if (ss.str().substr(0, 7) == "#0000FF") + { + /* blue */ + coloridx->OnValueRefreshed(5); + coloridx->Release(); + return true; + } + else if (ss.str().substr(0, 7) == "#FFFF00") + { + /* yellow */ + coloridx->OnValueRefreshed(6); + coloridx->Release(); + return true; + } + else if (ss.str().substr(0, 7) == "#00FFFF") + { + /* Cyan */ + coloridx->OnValueRefreshed(7); + coloridx->Release(); + return true; + } + else if (ss.str().substr(0, 7) == "#FF00FF") + { + /* Magenta */ + coloridx->OnValueRefreshed(8); + coloridx->Release(); + return true; + } + else if (ss.str().substr(0, 7) == "#C0C0C0") + { + /* Silver */ + coloridx->OnValueRefreshed(9); + coloridx->Release(); + return true; + } + else if (ss.str().substr(0, 7) == "#808080") + { + /* gray */ + coloridx->OnValueRefreshed(10); + coloridx->Release(); + return true; + } + else if (ss.str().substr(0, 7) == "#800000") + { + /* maroon */ + coloridx->OnValueRefreshed(11); + coloridx->Release(); + return true; + } + else if (ss.str().substr(0, 7) == "#808000") + { + /* Olive */ + coloridx->OnValueRefreshed(12); + coloridx->Release(); + return true; + } + else if (ss.str().substr(0, 7) == "#008000") + { + /* green */ + coloridx->OnValueRefreshed(13); + coloridx->Release(); + return true; + } + else if (ss.str().substr(0, 7) == "#800080") + { + /* purple */ + coloridx->OnValueRefreshed(14); + coloridx->Release(); + return true; + } + else if (ss.str().substr(0, 7) == "#008080") + { + /* teal */ + coloridx->OnValueRefreshed(15); + coloridx->Release(); + return true; + } + else if (ss.str().substr(0, 7) == "#000080") + { + /* navy */ + coloridx->OnValueRefreshed(16); + coloridx->Release(); + return true; + } + else + { + /* custom */ + coloridx->OnValueRefreshed(17); + coloridx->Release(); + return true; + } + } + } + } + /* if we got a updated Color Index Value - Update our ValueID */ + if ((m_dom.GetFlagShort(STATE_FLAG_COLOR_CHANNELS)) & (1 << (COLORIDX_INDEXCOLOR))) + { + if (Internal::VC::ValueList* coloridx = static_cast(GetValue(_instance, ValueID_Index_Color::Index))) + { + coloridx->OnValueRefreshed(m_colorvalues[COLORIDX_INDEXCOLOR]); + coloridx->Release(); + } + } + return true; + } + return false; + } //----------------------------------------------------------------------------- // // Set the device's Color value //----------------------------------------------------------------------------- -bool Color::SetValue -( - Value const& _value -) -{ - if (Value_Color == _value.GetID().GetIndex()) - { - ValueString const* value = static_cast(&_value); - string s = value->GetValue(); - /* make sure the first char is # */ - if (s.at(0) != '#') { - Log::Write( LogLevel_Warning, GetNodeId(), "Color::SetValue - String is Malformed. Missing #: %s", s.c_str()); - return false; - } - /* length minus the # has to be multiple of 2's */ - if ((s.length()-1) % 2 != 0 ) { - Log::Write( LogLevel_Warning, GetNodeId(), "Color::SetValue - Uneven Length string. Each Color should be 2 chars: %s", s.c_str()); - return false; - } - - /* the size of the string tells us how many colors are set */ - uint8_t nocols = (uint8_t)((s.length() -1) / 2) & 0xFF; - uint8_t colvals[8] = { 0, 0, 0, 0, 0, 0, 0, 0}; - bool colvalset[8] = { false, false, false, false, false, false, false, false }; - + bool Color::SetValue(Internal::VC::Value const& _value) + { + if (ValueID_Index_Color::Color == _value.GetID().GetIndex()) + { + Internal::VC::ValueString const* value = static_cast(&_value); + string s = value->GetValue(); + /* make sure the first char is # */ + if (s.at(0) != '#') + { + Log::Write(LogLevel_Warning, GetNodeId(), "Color::SetValue - String is Malformed. Missing #: %s", s.c_str()); + return false; + } + /* length minus the # has to be multiple of 2's */ + if ((s.length() - 1) % 2 != 0) + { + Log::Write(LogLevel_Warning, GetNodeId(), "Color::SetValue - Uneven Length string. Each Color should be 2 chars: %s", s.c_str()); + return false; + } - try { - /* we always will have at least RGB */ - colvals[COLORIDX_RED] = GetColor(s, 1); - colvals[COLORIDX_GREEN] = GetColor(s, 2); - colvals[COLORIDX_BLUE] = GetColor(s, 3); + /* the size of the string tells us how many colors are set */ + uint8_t nocols = (uint8_t) ((s.length() - 1) / 2) & 0xFF; + uint8_t colvals[8] = + { 0, 0, 0, 0, 0, 0, 0, 0 }; + bool colvalset[8] = + { false, false, false, false, false, false, false, false }; - /* if nocols = 4 then allwhite is set */ - if (nocols == 4) { - /* use ww as the var for all white */ - colvals[COLORIDX_WARMWHITE] = GetColor(s, 4); - colvalset[COLORIDX_WARMWHITE] = true; - } - if (nocols >= 5) { - /* warm white and cold white are set */ - colvals[COLORIDX_WARMWHITE] = GetColor(s, 4); - colvals[COLORIDX_COLDWHITE] = GetColor(s, 5); - colvalset[COLORIDX_WARMWHITE] = true; - colvalset[COLORIDX_COLDWHITE] = true; - } - if (nocols >= 6) { - /* amber is also set */ - colvals[COLORIDX_AMBER] = GetColor(s, 6); - colvalset[COLORIDX_AMBER] = true; - } - if (nocols >= 7) { - /* cyan is also set */ - colvals[COLORIDX_CYAN] = GetColor(s, 7); - colvalset[COLORIDX_CYAN] = true; - } - if (nocols == 8) { - /* purple is also set */ - colvals[COLORIDX_PURPLE] = GetColor(s, 8); - colvalset[COLORIDX_PURPLE] = true; - } - } catch(...) { - Log::Write(LogLevel_Warning, GetNodeId(), "Color::SetValue - Color String Decoding Failed: %s", s.c_str()); - return false; - } - Log::Write( LogLevel_Info, GetNodeId(), "Color::SetValue - Setting Color value"); + try + { + /* we always will have at least RGB */ + colvals[COLORIDX_RED] = GetColor(s, 1); + colvals[COLORIDX_GREEN] = GetColor(s, 2); + colvals[COLORIDX_BLUE] = GetColor(s, 3); + /* if nocols = 4 then allwhite is set */ + if (nocols == 4) + { + /* use ww as the var for all white */ + colvals[COLORIDX_WARMWHITE] = GetColor(s, 4); + colvalset[COLORIDX_WARMWHITE] = true; + } + if (nocols >= 5) + { + /* warm white and cold white are set */ + colvals[COLORIDX_WARMWHITE] = GetColor(s, 4); + colvals[COLORIDX_COLDWHITE] = GetColor(s, 5); + colvalset[COLORIDX_WARMWHITE] = true; + colvalset[COLORIDX_COLDWHITE] = true; + } + if (nocols >= 6) + { + /* amber is also set */ + colvals[COLORIDX_AMBER] = GetColor(s, 6); + colvalset[COLORIDX_AMBER] = true; + } + if (nocols >= 7) + { + /* cyan is also set */ + colvals[COLORIDX_CYAN] = GetColor(s, 7); + colvalset[COLORIDX_CYAN] = true; + } + if (nocols == 8) + { + /* purple is also set */ + colvals[COLORIDX_PURPLE] = GetColor(s, 8); + colvalset[COLORIDX_PURPLE] = true; + } + } + catch (...) + { + Log::Write(LogLevel_Warning, GetNodeId(), "Color::SetValue - Color String Decoding Failed: %s", s.c_str()); + return false; + } + Log::Write(LogLevel_Info, GetNodeId(), "Color::SetValue - Setting Color value"); - Msg* msg = new Msg( "ColorCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, false); - msg->SetInstance( this, _value.GetID().GetInstance() ); - msg->Append( GetNodeId() ); - if( GetVersion() > 1) - msg->Append(3 + (nocols*2)+1); // each color 2 bytes - and 1 byte for duration - else - msg->Append(3 + (nocols*2)); // each color 2 bytes - msg->Append( GetCommandClassId() ); - msg->Append(ColorCmd_Set); //cmd - msg->Append(nocols); - msg->Append(COLORIDX_RED); - msg->Append(colvals[COLORIDX_RED]); - msg->Append(COLORIDX_GREEN); - msg->Append(colvals[COLORIDX_GREEN]); - msg->Append(COLORIDX_BLUE); - msg->Append(colvals[COLORIDX_BLUE]); - if (colvalset[COLORIDX_WARMWHITE] & !colvalset[COLORIDX_COLDWHITE]) { - msg->Append(COLORIDX_WARMWHITE); - msg->Append(colvals[COLORIDX_WARMWHITE]); - } - if (colvalset[COLORIDX_WARMWHITE] && colvalset[COLORIDX_COLDWHITE]) { - msg->Append(COLORIDX_WARMWHITE); - msg->Append(colvals[COLORIDX_WARMWHITE]); - msg->Append(COLORIDX_COLDWHITE); - msg->Append(colvals[COLORIDX_COLDWHITE]); - } - if (colvalset[COLORIDX_AMBER]) { - msg->Append(COLORIDX_AMBER); - msg->Append(colvals[COLORIDX_AMBER]); - } - if (colvalset[COLORIDX_CYAN]) { - msg->Append(COLORIDX_CYAN); - msg->Append(colvals[COLORIDX_CYAN]); - } - if (colvalset[COLORIDX_PURPLE]) { - msg->Append(COLORIDX_PURPLE); - msg->Append(colvals[COLORIDX_PURPLE]); - } - if (GetVersion() > 1) { - uint8 duration = 0; - if (ValueByte *valduration = static_cast(GetValue(_value.GetID().GetInstance(), Value_Color_Duration))) { - duration = valduration->GetValue(); - } - msg->Append(duration); - } - msg->Append(GetDriver()->GetTransmitOptions()); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); + Msg* msg = new Msg("ColorCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, false); + msg->SetInstance(this, _value.GetID().GetInstance()); + msg->Append(GetNodeId()); + if (GetVersion() > 1) + msg->Append(3 + (nocols * 2) + 1); // each color 2 bytes - and 1 byte for duration + else + msg->Append(3 + (nocols * 2)); // each color 2 bytes + msg->Append(GetCommandClassId()); + msg->Append(ColorCmd_Set); //cmd + msg->Append(nocols); + msg->Append(COLORIDX_RED); + msg->Append(colvals[COLORIDX_RED]); + msg->Append(COLORIDX_GREEN); + msg->Append(colvals[COLORIDX_GREEN]); + msg->Append(COLORIDX_BLUE); + msg->Append(colvals[COLORIDX_BLUE]); + if (colvalset[COLORIDX_WARMWHITE] & !colvalset[COLORIDX_COLDWHITE]) + { + msg->Append(COLORIDX_WARMWHITE); + msg->Append(colvals[COLORIDX_WARMWHITE]); + } + if (colvalset[COLORIDX_WARMWHITE] && colvalset[COLORIDX_COLDWHITE]) + { + msg->Append(COLORIDX_WARMWHITE); + msg->Append(colvals[COLORIDX_WARMWHITE]); + msg->Append(COLORIDX_COLDWHITE); + msg->Append(colvals[COLORIDX_COLDWHITE]); + } + if (colvalset[COLORIDX_AMBER]) + { + msg->Append(COLORIDX_AMBER); + msg->Append(colvals[COLORIDX_AMBER]); + } + if (colvalset[COLORIDX_CYAN]) + { + msg->Append(COLORIDX_CYAN); + msg->Append(colvals[COLORIDX_CYAN]); + } + if (colvalset[COLORIDX_PURPLE]) + { + msg->Append(COLORIDX_PURPLE); + msg->Append(colvals[COLORIDX_PURPLE]); + } + if (GetVersion() > 1) + { + uint8 duration = 0; + if (Internal::VC::ValueByte *valduration = static_cast(GetValue(_value.GetID().GetInstance(), ValueID_Index_Color::Duration))) + { + duration = valduration->GetValue(); + } + msg->Append(duration); + } + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); - return true; - } else if (Value_Color_Index == _value.GetID().GetIndex()) { + return true; + } + else if (ValueID_Index_Color::Index == _value.GetID().GetIndex()) + { - ValueList const* value = static_cast(&_value); - if (value->GetItem() == NULL) { - return false; - } - uint8 index = value->GetItem()->m_value; - if ((m_dom.GetFlagShort(STATE_FLAG_COLOR_CHANNELS)) & (1<<(COLORIDX_INDEXCOLOR))) { - Log::Write( LogLevel_Info, GetNodeId(), "Color::SetValue - Setting Color Index Value (Real)"); + Internal::VC::ValueList const* value = static_cast(&_value); + if (value->GetItem() == NULL) + { + return false; + } + uint8 index = value->GetItem()->m_value; + if ((m_dom.GetFlagShort(STATE_FLAG_COLOR_CHANNELS)) & (1 << (COLORIDX_INDEXCOLOR))) + { + Log::Write(LogLevel_Info, GetNodeId(), "Color::SetValue - Setting Color Index Value (Real)"); - Msg* msg = new Msg( "Value_Color_Index", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, false); - msg->SetInstance( this, _value.GetID().GetInstance() ); - msg->Append( GetNodeId() ); - if( GetVersion() > 1) - msg->Append(3 + 2 + 1); // each color 2 bytes - and 1 byte for duration - else - msg->Append(3 + 2); // each color 2 bytes - msg->Append( GetCommandClassId() ); - msg->Append(ColorCmd_Set); //cmd - msg->Append(1); - msg->Append(COLORIDX_INDEXCOLOR); - msg->Append(index); - if (GetVersion() > 1) { - uint8 duration = 0; - if (ValueByte *valduration = static_cast(GetValue(_value.GetID().GetInstance(), Value_Color_Duration))) { - duration = valduration->GetValue(); - } - msg->Append(duration); - } - msg->Append(GetDriver()->GetTransmitOptions()); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "Color::SetValue - Setting Color Index Value (Fake)"); + Msg* msg = new Msg("Value_Color_Index", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, false); + msg->SetInstance(this, _value.GetID().GetInstance()); + msg->Append(GetNodeId()); + if (GetVersion() > 1) + msg->Append(3 + 2 + 1); // each color 2 bytes - and 1 byte for duration + else + msg->Append(3 + 2); // each color 2 bytes + msg->Append(GetCommandClassId()); + msg->Append(ColorCmd_Set); //cmd + msg->Append(1); + msg->Append(COLORIDX_INDEXCOLOR); + msg->Append(index); + if (GetVersion() > 1) + { + uint8 duration = 0; + if (Internal::VC::ValueByte *valduration = static_cast(GetValue(_value.GetID().GetInstance(), ValueID_Index_Color::Duration))) + { + duration = valduration->GetValue(); + } + msg->Append(duration); + } + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "Color::SetValue - Setting Color Index Value (Fake)"); - /* figure out the size */ - uint8 nocols = 3; - uint16_t f_capabilities = m_dom.GetFlagShort(STATE_FLAG_COLOR_CHANNELS); - if ((f_capabilities) & (1<<(COLORIDX_WARMWHITE))) { - nocols++; - } - if ((f_capabilities) & (1<<(COLORIDX_COLDWHITE))) { - nocols++; - } - if ((f_capabilities) & (1<<(COLORIDX_AMBER))) { - nocols++; - } - if ((f_capabilities) & (1<<(COLORIDX_CYAN))) { - nocols++; - } - if ((f_capabilities) & (1<<(COLORIDX_PURPLE))) { - nocols++; - } - Msg* msg = new Msg( "ColorCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, false); - msg->SetInstance( this, _value.GetID().GetInstance() ); - msg->Append( GetNodeId() ); - if( GetVersion() > 1) - msg->Append(3 + (nocols*2) + 1); // each color 2 bytes - and 1 byte for duration - else - msg->Append(3 + (nocols*2)); // each color 2 bytes - msg->Append( GetCommandClassId() ); - msg->Append(ColorCmd_Set); //cmd - msg->Append(nocols); - bool cwset = false; - bool wwset = false; - /* fake it */ - switch (index) { - case 0: /* "Off" */ - msg->Append(COLORIDX_RED); - msg->Append(0x00); - msg->Append(COLORIDX_GREEN); - msg->Append(0x00); - msg->Append(COLORIDX_BLUE); - msg->Append(0x00); - break; - case 1: /* Cool White" */ - if ((f_capabilities) & (1<<(COLORIDX_COLDWHITE))) { - if ((f_capabilities) & (1<<(COLORIDX_WARMWHITE))) { + /* figure out the size */ + uint8 nocols = 3; + uint16_t f_capabilities = m_dom.GetFlagShort(STATE_FLAG_COLOR_CHANNELS); + if ((f_capabilities) & (1 << (COLORIDX_WARMWHITE))) + { + nocols++; + } + if ((f_capabilities) & (1 << (COLORIDX_COLDWHITE))) + { + nocols++; + } + if ((f_capabilities) & (1 << (COLORIDX_AMBER))) + { + nocols++; + } + if ((f_capabilities) & (1 << (COLORIDX_CYAN))) + { + nocols++; + } + if ((f_capabilities) & (1 << (COLORIDX_PURPLE))) + { + nocols++; + } + Msg* msg = new Msg("ColorCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, false); + msg->SetInstance(this, _value.GetID().GetInstance()); + msg->Append(GetNodeId()); + if (GetVersion() > 1) + msg->Append(3 + (nocols * 2) + 1); // each color 2 bytes - and 1 byte for duration + else + msg->Append(3 + (nocols * 2)); // each color 2 bytes + msg->Append(GetCommandClassId()); + msg->Append(ColorCmd_Set); //cmd + msg->Append(nocols); + bool cwset = false; + bool wwset = false; + /* fake it */ + switch (index) + { + case 0: /* "Off" */ + msg->Append(COLORIDX_RED); + msg->Append(0x00); + msg->Append(COLORIDX_GREEN); + msg->Append(0x00); + msg->Append(COLORIDX_BLUE); + msg->Append(0x00); + break; + case 1: /* Cool White" */ + if ((f_capabilities) & (1 << (COLORIDX_COLDWHITE))) + { + if ((f_capabilities) & (1 << (COLORIDX_WARMWHITE))) + { + msg->Append(COLORIDX_WARMWHITE); + msg->Append(0x00); + wwset = true; + } + if ((f_capabilities) & (1 << (COLORIDX_COLDWHITE))) + { + msg->Append(COLORIDX_COLDWHITE); + msg->Append(0xFF); + cwset = true; + } + msg->Append(COLORIDX_RED); + msg->Append(0x00); + msg->Append(COLORIDX_GREEN); + msg->Append(0x00); + msg->Append(COLORIDX_BLUE); + msg->Append(0x00); + } + else + { + msg->Append(COLORIDX_RED); + msg->Append(0xFF); + msg->Append(COLORIDX_GREEN); + msg->Append(0xFF); + msg->Append(COLORIDX_BLUE); + msg->Append(0xFF); + } + break; + case 2: /* Warm White */ + if ((f_capabilities) & (1 << (COLORIDX_WARMWHITE))) + { + if ((f_capabilities) & (1 << (COLORIDX_WARMWHITE))) + { + msg->Append(COLORIDX_WARMWHITE); + msg->Append(0xFF); + wwset = true; + } + if ((f_capabilities) & (1 << (COLORIDX_COLDWHITE))) + { + msg->Append(COLORIDX_COLDWHITE); + msg->Append(0x00); + cwset = true; + } + msg->Append(COLORIDX_RED); + msg->Append(0x00); + msg->Append(COLORIDX_GREEN); + msg->Append(0x00); + msg->Append(COLORIDX_BLUE); + msg->Append(0x00); + } + else + { + msg->Append(COLORIDX_RED); + msg->Append(0xFF); + msg->Append(COLORIDX_GREEN); + msg->Append(0x93); + msg->Append(COLORIDX_BLUE); + msg->Append(0x29); + } + break; + case 3: /* "Red" */ + msg->Append(COLORIDX_RED); + msg->Append(0xFF); + msg->Append(COLORIDX_GREEN); + msg->Append(0x00); + msg->Append(COLORIDX_BLUE); + msg->Append(0x00); + break; + case 4: /* "Lime" */ + msg->Append(COLORIDX_RED); + msg->Append(0x00); + msg->Append(COLORIDX_GREEN); + msg->Append(0xFF); + msg->Append(COLORIDX_BLUE); + msg->Append(0x00); + break; + case 5: /* "Blue" */ + msg->Append(COLORIDX_RED); + msg->Append(0x00); + msg->Append(COLORIDX_GREEN); + msg->Append(0x00); + msg->Append(COLORIDX_BLUE); + msg->Append(0xFF); + break; + case 6: /* "Yellow" */ + msg->Append(COLORIDX_RED); + msg->Append(0xFF); + msg->Append(COLORIDX_GREEN); + msg->Append(0xFF); + msg->Append(COLORIDX_BLUE); + msg->Append(0x00); + break; + case 7: /* "Cyan" */ + msg->Append(COLORIDX_RED); + msg->Append(0x00); + msg->Append(COLORIDX_GREEN); + msg->Append(0xFF); + msg->Append(COLORIDX_BLUE); + msg->Append(0xFF); + break; + case 8: /* "Magenta" */ + msg->Append(COLORIDX_RED); + msg->Append(0xFF); + msg->Append(COLORIDX_GREEN); + msg->Append(0x00); + msg->Append(COLORIDX_BLUE); + msg->Append(0xFF); + break; + case 9: /* "Silver" */ + msg->Append(COLORIDX_RED); + msg->Append(0xC0); + msg->Append(COLORIDX_GREEN); + msg->Append(0xC0); + msg->Append(COLORIDX_BLUE); + msg->Append(0xC0); + break; + case 10: /* "Gray" */ + msg->Append(COLORIDX_RED); + msg->Append(0x80); + msg->Append(COLORIDX_GREEN); + msg->Append(0x80); + msg->Append(COLORIDX_BLUE); + msg->Append(0x80); + break; + case 11: /* "Maroon" */ + msg->Append(COLORIDX_RED); + msg->Append(0x80); + msg->Append(COLORIDX_GREEN); + msg->Append(0x00); + msg->Append(COLORIDX_BLUE); + msg->Append(0x00); + break; + case 12: /* "Olive" */ + msg->Append(COLORIDX_RED); + msg->Append(0x80); + msg->Append(COLORIDX_GREEN); + msg->Append(0x80); + msg->Append(COLORIDX_BLUE); + msg->Append(0x00); + break; + case 13: /* "Green" */ + msg->Append(COLORIDX_RED); + msg->Append(0x00); + msg->Append(COLORIDX_GREEN); + msg->Append(0x80); + msg->Append(COLORIDX_BLUE); + msg->Append(0x00); + break; + case 14: /* "Purple" */ + msg->Append(COLORIDX_RED); + msg->Append(0x80); + msg->Append(COLORIDX_GREEN); + msg->Append(0x00); + msg->Append(COLORIDX_BLUE); + msg->Append(0x80); + break; + case 15: /* "Teal" */ + msg->Append(COLORIDX_RED); + msg->Append(0x00); + msg->Append(COLORIDX_GREEN); + msg->Append(0x80); + msg->Append(COLORIDX_BLUE); + msg->Append(0x80); + break; + case 16: /* "Navy" */ + msg->Append(COLORIDX_RED); + msg->Append(0x00); + msg->Append(COLORIDX_GREEN); + msg->Append(0x00); + msg->Append(COLORIDX_BLUE); + msg->Append(0x80); + break; + case 17: /* "Custom" */ + msg->Append(COLORIDX_RED); + msg->Append(0x00); + msg->Append(COLORIDX_GREEN); + msg->Append(0x00); + msg->Append(COLORIDX_BLUE); + msg->Append(0x00); + break; + } + if (((f_capabilities) & (1 << (COLORIDX_WARMWHITE))) && !wwset) + { msg->Append(COLORIDX_WARMWHITE); msg->Append(0x00); - wwset = true; } - if ((f_capabilities) & (1<<(COLORIDX_COLDWHITE))) { + if (((f_capabilities) & (1 << (COLORIDX_COLDWHITE))) && !cwset) + { msg->Append(COLORIDX_COLDWHITE); - msg->Append(0xFF); - cwset = true; + msg->Append(0x00); } - msg->Append(COLORIDX_RED); - msg->Append(0x00); - msg->Append(COLORIDX_GREEN); - msg->Append(0x00); - msg->Append(COLORIDX_BLUE); - msg->Append(0x00); - } else { - msg->Append(COLORIDX_RED); - msg->Append(0xFF); - msg->Append(COLORIDX_GREEN); - msg->Append(0xFF); - msg->Append(COLORIDX_BLUE); - msg->Append(0xFF); - } - break; - case 2: /* Warm White */ - if ((f_capabilities) & (1 <<(COLORIDX_WARMWHITE))) { - if ((f_capabilities) & (1<<(COLORIDX_WARMWHITE))) { - msg->Append(COLORIDX_WARMWHITE); - msg->Append(0xFF); - wwset = true; + if ((f_capabilities) & (1 << (COLORIDX_AMBER))) + { + msg->Append(COLORIDX_AMBER); + msg->Append(0x00); } - if ((f_capabilities) & (1<<(COLORIDX_COLDWHITE))) { - msg->Append(COLORIDX_COLDWHITE); + if ((f_capabilities) & (1 << (COLORIDX_CYAN))) + { + msg->Append(COLORIDX_CYAN); + msg->Append(0x00); + } + if ((f_capabilities) & (1 << (COLORIDX_PURPLE))) + { + msg->Append(COLORIDX_PURPLE); msg->Append(0x00); - cwset = true; } - msg->Append(COLORIDX_RED); - msg->Append(0x00); - msg->Append(COLORIDX_GREEN); - msg->Append(0x00); - msg->Append(COLORIDX_BLUE); - msg->Append(0x00); - } else { - msg->Append(COLORIDX_RED); - msg->Append(0xFF); - msg->Append(COLORIDX_GREEN); - msg->Append(0x93); - msg->Append(COLORIDX_BLUE); - msg->Append(0x29); + if (GetVersion() > 1) + { + uint8 duration = 0; + if (Internal::VC::ValueByte *valduration = static_cast(GetValue(_value.GetID().GetInstance(), ValueID_Index_Color::Duration))) + { + duration = valduration->GetValue(); + } + msg->Append(duration); + } + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return true; } - break; - case 3: /* "Red" */ - msg->Append(COLORIDX_RED); - msg->Append(0xFF); - msg->Append(COLORIDX_GREEN); - msg->Append(0x00); - msg->Append(COLORIDX_BLUE); - msg->Append(0x00); - break; - case 4: /* "Lime" */ - msg->Append(COLORIDX_RED); - msg->Append(0x00); - msg->Append(COLORIDX_GREEN); - msg->Append(0xFF); - msg->Append(COLORIDX_BLUE); - msg->Append(0x00); - break; - case 5: /* "Blue" */ - msg->Append(COLORIDX_RED); - msg->Append(0x00); - msg->Append(COLORIDX_GREEN); - msg->Append(0x00); - msg->Append(COLORIDX_BLUE); - msg->Append(0xFF); - break; - case 6: /* "Yellow" */ - msg->Append(COLORIDX_RED); - msg->Append(0xFF); - msg->Append(COLORIDX_GREEN); - msg->Append(0xFF); - msg->Append(COLORIDX_BLUE); - msg->Append(0x00); - break; - case 7: /* "Cyan" */ - msg->Append(COLORIDX_RED); - msg->Append(0x00); - msg->Append(COLORIDX_GREEN); - msg->Append(0xFF); - msg->Append(COLORIDX_BLUE); - msg->Append(0xFF); - break; - case 8: /* "Magenta" */ - msg->Append(COLORIDX_RED); - msg->Append(0xFF); - msg->Append(COLORIDX_GREEN); - msg->Append(0x00); - msg->Append(COLORIDX_BLUE); - msg->Append(0xFF); - break; - case 9: /* "Silver" */ - msg->Append(COLORIDX_RED); - msg->Append(0xC0); - msg->Append(COLORIDX_GREEN); - msg->Append(0xC0); - msg->Append(COLORIDX_BLUE); - msg->Append(0xC0); - break; - case 10: /* "Gray" */ - msg->Append(COLORIDX_RED); - msg->Append(0x80); - msg->Append(COLORIDX_GREEN); - msg->Append(0x80); - msg->Append(COLORIDX_BLUE); - msg->Append(0x80); - break; - case 11: /* "Maroon" */ - msg->Append(COLORIDX_RED); - msg->Append(0x80); - msg->Append(COLORIDX_GREEN); - msg->Append(0x00); - msg->Append(COLORIDX_BLUE); - msg->Append(0x00); - break; - case 12: /* "Olive" */ - msg->Append(COLORIDX_RED); - msg->Append(0x80); - msg->Append(COLORIDX_GREEN); - msg->Append(0x80); - msg->Append(COLORIDX_BLUE); - msg->Append(0x00); - break; - case 13: /* "Green" */ - msg->Append(COLORIDX_RED); - msg->Append(0x00); - msg->Append(COLORIDX_GREEN); - msg->Append(0x80); - msg->Append(COLORIDX_BLUE); - msg->Append(0x00); - break; - case 14: /* "Purple" */ - msg->Append(COLORIDX_RED); - msg->Append(0x80); - msg->Append(COLORIDX_GREEN); - msg->Append(0x00); - msg->Append(COLORIDX_BLUE); - msg->Append(0x80); - break; - case 15: /* "Teal" */ - msg->Append(COLORIDX_RED); - msg->Append(0x00); - msg->Append(COLORIDX_GREEN); - msg->Append(0x80); - msg->Append(COLORIDX_BLUE); - msg->Append(0x80); - break; - case 16: /* "Navy" */ - msg->Append(COLORIDX_RED); - msg->Append(0x00); - msg->Append(COLORIDX_GREEN); - msg->Append(0x00); - msg->Append(COLORIDX_BLUE); - msg->Append(0x80); - break; - case 17: /* "Custom" */ - msg->Append(COLORIDX_RED); - msg->Append(0x00); - msg->Append(COLORIDX_GREEN); - msg->Append(0x00); - msg->Append(COLORIDX_BLUE); - msg->Append(0x00); - break; - } - if (((f_capabilities) & (1<<(COLORIDX_WARMWHITE))) && !wwset) { - msg->Append(COLORIDX_WARMWHITE); - msg->Append(0x00); - } - if (((f_capabilities) & (1<<(COLORIDX_COLDWHITE))) && !cwset) { - msg->Append(COLORIDX_COLDWHITE); - msg->Append(0x00); - } - if ((f_capabilities) & (1<<(COLORIDX_AMBER))) { - msg->Append(COLORIDX_AMBER); - msg->Append(0x00); } - if ((f_capabilities) & (1<<(COLORIDX_CYAN))) { - msg->Append(COLORIDX_CYAN); - msg->Append(0x00); } - if ((f_capabilities) & (1<<(COLORIDX_PURPLE))) { - msg->Append(COLORIDX_PURPLE); - msg->Append(0x00); - } - if (GetVersion() > 1) { - uint8 duration = 0; - if (ValueByte *valduration = static_cast(GetValue(_value.GetID().GetInstance(), Value_Color_Duration))) { - duration = valduration->GetValue(); } - msg->Append(duration); + else if (ValueID_Index_Color::Duration == _value.GetID().GetIndex()) + { + Log::Write(LogLevel_Info, GetNodeId(), "Color::SetValue - Setting Color Fade Duration"); + Internal::VC::ValueByte const* value = static_cast(&_value); + uint8 _duration = value->GetValue(); + if (Internal::VC::ValueByte * m_value = static_cast(GetValue(_value.GetID().GetInstance(), ValueID_Index_Color::Duration))) + { + m_value->OnValueRefreshed(_duration); + m_value->Release(); + } + return true; + } + else if (ValueID_Index_Color::Channels_Capabilities == _value.GetID().GetIndex()) + { + Log::Write(LogLevel_Info, GetNodeId(), "Color::SetValue - Setting Color Channels"); + Internal::VC::ValueInt const* value = static_cast(&_value); + m_dom.SetFlagShort(STATE_FLAG_COLOR_CHANNELS, value->GetValue()); + /* if the Capabilities is set to 0 by the user, then refresh the defaults from the device */ + if (m_dom.GetFlagShort(STATE_FLAG_COLOR_CHANNELS) == 0) + { + Msg* msg = new Msg("ColorCmd_CapabilityGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(ColorCmd_Capability_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + } + if (Internal::VC::ValueInt *m_value = static_cast(GetValue(_value.GetID().GetInstance(), ValueID_Index_Color::Channels_Capabilities))) + { + m_value->OnValueRefreshed(m_dom.GetFlagShort(STATE_FLAG_COLOR_CHANNELS)); + m_value->Release(); + } + } + return false; } - msg->Append(GetDriver()->GetTransmitOptions()); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - return true; - } - } else if (Value_Color_Duration == _value.GetID().GetIndex()) { - Log::Write( LogLevel_Info, GetNodeId(), "Color::SetValue - Setting Color Fade Duration"); - ValueByte const* value = static_cast(&_value); - uint8 _duration = value->GetValue(); - if (ValueByte * m_value = static_cast(GetValue(_value.GetID().GetInstance(), Value_Color_Duration))) { - m_value->OnValueRefreshed(_duration); - m_value->Release(); - } - return true; - } else if (Value_Color_Channels_Capabilities == _value.GetID().GetIndex()) { - Log::Write( LogLevel_Info, GetNodeId(), "Color::SetValue - Setting Color Channels"); - ValueInt const* value = static_cast(&_value); - m_dom.SetFlagShort(STATE_FLAG_COLOR_CHANNELS, value->GetValue()); - /* if the Capabilities is set to 0 by the user, then refresh the defaults from the device */ - if (m_dom.GetFlagShort(STATE_FLAG_COLOR_CHANNELS) == 0) { - Msg* msg = new Msg("ColorCmd_CapabilityGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); - msg->Append(GetNodeId()); - msg->Append(2); - msg->Append(GetCommandClassId()); - msg->Append(ColorCmd_Capability_Get); - msg->Append(GetDriver()->GetTransmitOptions()); - GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); - } - if (ValueInt *m_value = static_cast(GetValue(_value.GetID().GetInstance(), Value_Color_Channels_Capabilities))) { - m_value->OnValueRefreshed(m_dom.GetFlagShort(STATE_FLAG_COLOR_CHANNELS)); - m_value->Release(); - } - } - return false; -} //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void Color::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - /* XXX TODO convert this to a bitset when we implement */ - node->CreateValueInt( ValueID::ValueGenre_System, GetCommandClassId(), _instance, Value_Color_Channels_Capabilities, "Color Channels", "", false, false, m_dom.GetFlagShort(STATE_FLAG_COLOR_CHANNELS), 0 ); - } - + void Color::CreateVars(uint8 const _instance) + { + if (Node* node = GetNodeUnsafe()) + { + /* XXX TODO convert this to a bitset when we implement */ + node->CreateValueInt(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_Color::Channels_Capabilities, "Color Channels", "", false, false, m_dom.GetFlagShort(STATE_FLAG_COLOR_CHANNELS), 0); + } -} + } //----------------------------------------------------------------------------- // // Update class values based in BASIC mapping //----------------------------------------------------------------------------- -void Color::SetValueBasic -( - uint8 const _instance, - uint8 const _value -) -{ - RequestValue( 0, Value_Color, _instance, Driver::MsgQueue_Send ); -} + void Color::SetValueBasic(uint8 const _instance, uint8 const _value) + { + RequestValue(0, ValueID_Index_Color::Color, _instance, Driver::MsgQueue_Send); + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/Color.h b/cpp/src/command_classes/Color.h index 38da5953ee..96c54ab603 100644 --- a/cpp/src/command_classes/Color.h +++ b/cpp/src/command_classes/Color.h @@ -32,41 +32,65 @@ namespace OpenZWave { - class ValueByte; - - /** \brief Implements COMMAND_CLASS_COLOR (0x33), a Z-Wave device command class. - * \ingroup CommandClass - */ - class Color: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Color( _homeId, _nodeId ); } - virtual ~Color(){} + namespace CC + { - static uint8 const StaticGetCommandClassId(){ return 0x33; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_COLOR"; } + /** \brief Implements COMMAND_CLASS_COLOR (0x33), a Z-Wave device command class. + * \ingroup CommandClass + */ + class Color: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new Color(_homeId, _nodeId); + } + virtual ~Color() + { + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - bool RequestColorChannelReport( uint8 const coloridx, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool SetValue( Value const& _value ); - virtual uint8 GetMaxVersion(){ return 2; } - virtual void SetValueBasic( uint8 const _instance, uint8 const _value ); + static uint8 const StaticGetCommandClassId() + { + return 0x33; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_COLOR"; + } - protected: - virtual void CreateVars( uint8 const _instance ); + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + bool RequestColorChannelReport(uint8 const coloridx, uint8 const _instance, Driver::MsgQueue const _queue); + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool SetValue(Internal::VC::Value const& _value) override; + virtual uint8 GetMaxVersion() override + { + return 2; + } + virtual void SetValueBasic(uint8 const _instance, uint8 const _value) override; - private: - Color( uint32 const _homeId, uint8 const _nodeId ); - bool m_refreshinprogress; - uint8 m_coloridxcount; - uint8 m_colorvalues[9]; - }; + protected: + virtual void CreateVars(uint8 const _instance) override; + private: + Color(uint32 const _homeId, uint8 const _nodeId); + bool m_refreshinprogress; + uint8 m_coloridxcount; + uint8 m_colorvalues[9]; + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/CommandClass.cpp b/cpp/src/command_classes/CommandClass.cpp index 269d7ed962..b6f25f1429 100644 --- a/cpp/src/command_classes/CommandClass.cpp +++ b/cpp/src/command_classes/CommandClass.cpp @@ -27,6 +27,7 @@ #include #include +#include "Defs.h" #include "tinyxml.h" #include "command_classes/CommandClass.h" #include "command_classes/Basic.h" @@ -38,282 +39,250 @@ #include "Localization.h" #include "Manager.h" #include "platform/Log.h" +#include "value_classes/Value.h" #include "value_classes/ValueStore.h" -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace CC + { -static uint8 const c_sizeMask = 0x07; -static uint8 const c_scaleMask = 0x18; -static uint8 const c_scaleShift = 0x03; -static uint8 const c_precisionMask = 0xe0; -static uint8 const c_precisionShift = 0x05; + static uint8 const c_sizeMask = 0x07; + static uint8 const c_scaleMask = 0x18; + static uint8 const c_scaleShift = 0x03; + static uint8 const c_precisionMask = 0xe0; + static uint8 const c_precisionShift = 0x05; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -CommandClass::CommandClass -( - uint32 const _homeId, - uint8 const _nodeId -): -m_com(CompatOptionType_Compatibility, this), -m_dom(CompatOptionType_Discovery, this), -m_homeId( _homeId ), -m_nodeId( _nodeId ), -m_SecureSupport( true ), -m_sentCnt( 0 ), -m_receivedCnt( 0 ) -{ - m_com.EnableFlag(COMPAT_FLAG_GETSUPPORTED, true); - m_com.EnableFlag(COMPAT_FLAG_OVERRIDEPRECISION, 0); - m_com.EnableFlag(COMPAT_FLAG_FORCEVERSION, 0); - m_com.EnableFlag(COMPAT_FLAG_CREATEVARS, true); - m_com.EnableFlag(COMPAT_FLAG_REFRESHONWAKEUP, false); - m_dom.EnableFlag(STATE_FLAG_CCVERSION, 1); - m_dom.EnableFlag(STATE_FLAG_STATIC_REQUESTS, 0); - m_dom.EnableFlag(STATE_FLAG_AFTERMARK, false); - m_dom.EnableFlag(STATE_FLAG_ENCRYPTED, false); - m_dom.EnableFlag(STATE_FLAG_INNIF, false); -} + CommandClass::CommandClass(uint32 const _homeId, uint8 const _nodeId) : + m_com(CompatOptionType_Compatibility, this), m_dom(CompatOptionType_Discovery, this), m_homeId(_homeId), m_nodeId(_nodeId), m_SecureSupport(true), m_sentCnt(0), m_receivedCnt(0) + { + m_com.EnableFlag(COMPAT_FLAG_GETSUPPORTED, true); + m_com.EnableFlag(COMPAT_FLAG_OVERRIDEPRECISION, 0); + m_com.EnableFlag(COMPAT_FLAG_FORCEVERSION, 0); + m_com.EnableFlag(COMPAT_FLAG_CREATEVARS, true); + m_com.EnableFlag(COMPAT_FLAG_REFRESHONWAKEUP, false); + m_com.EnableFlag(COMPAT_FLAG_VERIFYCHANGED, false); + m_dom.EnableFlag(STATE_FLAG_CCVERSION, 1); + m_dom.EnableFlag(STATE_FLAG_STATIC_REQUESTS, 0); + m_dom.EnableFlag(STATE_FLAG_AFTERMARK, false); + m_dom.EnableFlag(STATE_FLAG_ENCRYPTED, false); + m_dom.EnableFlag(STATE_FLAG_INNIF, false); + + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -CommandClass::~CommandClass -( -) -{ - while( !m_endPointMap.empty() ) - { - map::iterator it = m_endPointMap.begin(); - m_endPointMap.erase( it ); - } - while ( !m_RefreshClassValues.empty() ) - { - for (unsigned int i = 0; i < m_RefreshClassValues.size(); i++) - { - RefreshValue *rcc = m_RefreshClassValues.at(i); - while(!rcc->RefreshClasses.empty()) { - delete rcc->RefreshClasses.back(); - rcc->RefreshClasses.pop_back(); - } - // for (unsigned int j = 0; j < rcc->RefreshClasses.size(); i++) - // { - // delete rcc->RefreshClasses[j]; - // } - rcc->RefreshClasses.clear(); - delete rcc; - } - m_RefreshClassValues.clear(); - } + CommandClass::~CommandClass() + { + while (!m_endPointMap.empty()) + { + map::iterator it = m_endPointMap.begin(); + m_endPointMap.erase(it); + } + while (!m_RefreshClassValues.empty()) + { + for (unsigned int i = 0; i < m_RefreshClassValues.size(); i++) + { + RefreshValue *rcc = m_RefreshClassValues.at(i); + while (!rcc->RefreshClasses.empty()) + { + delete rcc->RefreshClasses.back(); + rcc->RefreshClasses.pop_back(); + } + // for (unsigned int j = 0; j < rcc->RefreshClasses.size(); i++) + // { + // delete rcc->RefreshClasses[j]; + // } + rcc->RefreshClasses.clear(); + delete rcc; + } + m_RefreshClassValues.clear(); + } -} + } //----------------------------------------------------------------------------- // // Get a pointer to our driver //----------------------------------------------------------------------------- -Driver* CommandClass::GetDriver -( -)const -{ - return( Manager::Get()->GetDriver( m_homeId ) ); -} + OpenZWave::Driver* CommandClass::GetDriver() const + { + return (Manager::Get()->GetDriver(m_homeId)); + } //----------------------------------------------------------------------------- // // Get a pointer to our node without locking the mutex //----------------------------------------------------------------------------- -Node* CommandClass::GetNodeUnsafe -( -)const -{ - return( GetDriver()->GetNodeUnsafe( m_nodeId ) ); -} + OpenZWave::Node* CommandClass::GetNodeUnsafe() const + { + return (GetDriver()->GetNodeUnsafe(m_nodeId)); + } //----------------------------------------------------------------------------- // // Get a pointer to a value by its instance and index //----------------------------------------------------------------------------- -Value* CommandClass::GetValue -( - uint8 const _instance, - uint16 const _index -) -{ - Value* value = NULL; - if( Node* node = GetNodeUnsafe() ) - { - value = node->GetValue( GetCommandClassId(), _instance, _index ); - } - return value; -} + OpenZWave::Internal::VC::Value* CommandClass::GetValue(uint8 const _instance, uint16 const _index) + { + Internal::VC::Value* value = NULL; + if (Node* node = GetNodeUnsafe()) + { + value = node->GetValue(GetCommandClassId(), _instance, _index); + } + return value; + } //----------------------------------------------------------------------------- // // Remove a value by its instance and index //----------------------------------------------------------------------------- -bool CommandClass::RemoveValue -( - uint8 const _instance, - uint16 const _index -) -{ - if( Node* node = GetNodeUnsafe() ) - { - return node->RemoveValue( GetCommandClassId(), _instance, _index ); - } - return false; -} + bool CommandClass::RemoveValue(uint8 const _instance, uint16 const _index) + { + if (Node* node = GetNodeUnsafe()) + { + return node->RemoveValue(GetCommandClassId(), _instance, _index); + } + return false; + } //----------------------------------------------------------------------------- // // Instances as set by the MultiInstance V1 command class //----------------------------------------------------------------------------- -void CommandClass::SetInstances -( - uint8 const _instances -) -{ - // Ensure we have a set of reported variables for each new instance - if( !m_dom.GetFlagBool(STATE_FLAG_AFTERMARK) ) - { - for( uint8 i=0; i<_instances; ++i ) - { - SetInstance( i+1 ); - } - } -} + void CommandClass::SetInstances(uint8 const _instances) + { + // Ensure we have a set of reported variables for each new instance + if (!m_dom.GetFlagBool(STATE_FLAG_AFTERMARK)) + { + for (uint8 i = 0; i < _instances; ++i) + { + SetInstance(i + 1); + } + } + } //----------------------------------------------------------------------------- // // Instances as set by the MultiChannel (i.e. MultiInstance V2) command class //----------------------------------------------------------------------------- -void CommandClass::SetInstance -( - uint8 const _endPoint -) -{ - if( !m_instances.IsSet( _endPoint ) ) - { - m_instances.Set( _endPoint ); - if( m_com.GetFlagBool(COMPAT_FLAG_CREATEVARS) ) - { - CreateVars( _endPoint ); - } - } -} + void CommandClass::SetInstance(uint8 const _endPoint) + { + if (!m_instances.IsSet(_endPoint)) + { + m_instances.Set(_endPoint); + if (m_com.GetFlagBool(COMPAT_FLAG_CREATEVARS)) + { + CreateVars(_endPoint); + } + } + } //----------------------------------------------------------------------------- // // Set the Label for a Instance of this CommandClass //----------------------------------------------------------------------------- -void CommandClass::SetInstanceLabel -( - uint8 const _instance, - char *label -) -{ - m_instanceLabel[_instance] = string(label); -} + void CommandClass::SetInstanceLabel(uint8 const _instance, char *label) + { + m_instanceLabel[_instance] = std::string(label); + } //----------------------------------------------------------------------------- // // Get the Label for a Instance of this CommandClass //----------------------------------------------------------------------------- -string CommandClass::GetInstanceLabel -( - uint8 const _instance -) -{ - if ( m_instanceLabel.count(_instance) ) - { - return Localization::Get()->GetGlobalLabel(m_instanceLabel[_instance]); - } - return string(); -} + std::string CommandClass::GetInstanceLabel(uint8 const _instance) + { + if (m_instanceLabel.count(_instance)) + { + return Localization::Get()->GetGlobalLabel(m_instanceLabel[_instance]); + } + return std::string(); + } //----------------------------------------------------------------------------- // // Read the saved command class data //----------------------------------------------------------------------------- -void CommandClass::ReadXML -( - TiXmlElement const* _ccElement -) -{ - int32 intVal; - char const* str; + void CommandClass::ReadXML(TiXmlElement const* _ccElement) + { + int32 intVal; + char const* str; - m_com.ReadXML(_ccElement); - m_dom.ReadXML(_ccElement); + m_com.ReadXML(_ccElement); + m_dom.ReadXML(_ccElement); - // Apply any differences from the saved XML to the values - TiXmlElement const* child = _ccElement->FirstChildElement(); - while( child ) - { - str = child->Value(); - if( str ) - { - if( !strcmp( str, "Instance" ) ) - { - uint8 instance = 0; - // Add an instance to the command class - if( TIXML_SUCCESS == child->QueryIntAttribute( "index", &intVal ) ) - { - instance = (uint8)intVal; - SetInstance( instance ); - } - // See if its associated endpoint is present - if( TIXML_SUCCESS == child->QueryIntAttribute( "endpoint", &intVal ) ) - { - uint8 endpoint = (uint8)intVal; - SetEndPoint( instance, endpoint ); - } - str = child->Attribute( "label"); - if ( str ) + // Apply any differences from the saved XML to the values + TiXmlElement const* child = _ccElement->FirstChildElement(); + while (child) { - SetInstanceLabel(instance, (char *)str); - Localization::Get()->SetGlobalLabel(str, str, ""); - TiXmlElement const *labellang = child->FirstChildElement(); - while ( labellang ) + str = child->Value(); + if (str) { - char const* str2 = labellang->Value(); - if ( str2 && !strcmp( str2, "Label" ) ) + if (!strcmp(str, "Instance")) + { + uint8 instance = 0; + // Add an instance to the command class + if (TIXML_SUCCESS == child->QueryIntAttribute("index", &intVal)) + { + instance = (uint8) intVal; + SetInstance(instance); + } + // See if its associated endpoint is present + if (TIXML_SUCCESS == child->QueryIntAttribute("endpoint", &intVal)) + { + uint8 endpoint = (uint8) intVal; + SetEndPoint(instance, endpoint); + } + str = child->Attribute("label"); + if (str) + { + SetInstanceLabel(instance, (char *) str); + Localization::Get()->SetGlobalLabel(str, str, ""); + TiXmlElement const *labellang = child->FirstChildElement(); + while (labellang) + { + char const* str2 = labellang->Value(); + if (str2 && !strcmp(str2, "Label")) + { + char const *lang = labellang->Attribute("lang"); + Localization::Get()->SetGlobalLabel(str, labellang->GetText(), lang); + } + labellang = labellang->NextSiblingElement(); + } + } + } + else if (!strcmp(str, "Value")) { - char const *lang = labellang->Attribute("lang"); - Localization::Get()->SetGlobalLabel(str, labellang->GetText(), lang); + // Apply any differences from the saved XML to the value + GetNodeUnsafe()->ReadValueFromXML(GetCommandClassId(), child); + } + else if (!strcmp(str, "TriggerRefreshValue")) + { + ReadValueRefreshXML(child); } - labellang = labellang->NextSiblingElement(); } - } - } - else if( !strcmp( str, "Value" ) ) - { - // Apply any differences from the saved XML to the value - GetNodeUnsafe()->ReadValueFromXML( GetCommandClassId(), child ); - } - else if (!strcmp( str, "TriggerRefreshValue" ) ) - { - ReadValueRefreshXML(child); - } - } - - child = child->NextSiblingElement(); - } - // Make sure previously created values are removed if create_vars=false - if( !m_com.GetFlagBool(COMPAT_FLAG_CREATEVARS) ) - { - if( Node* node = GetNodeUnsafe() ) - { - node->GetValueStore()->RemoveCommandClassValues( GetCommandClassId() ); - } - } + child = child->NextSiblingElement(); + } + // Make sure previously created values are removed if create_vars=false + if (!m_com.GetFlagBool(COMPAT_FLAG_CREATEVARS)) + { + if (Node* node = GetNodeUnsafe()) + { + node->GetValueStore()->RemoveCommandClassValues(GetCommandClassId()); + } + } -} + } //----------------------------------------------------------------------------- // @@ -321,76 +290,80 @@ void CommandClass::ReadXML // we recieve u updated Value from a device. (This helps Yale Door Locks, which send a // Alarm Report instead of DoorLock Report when the status of the Door Lock is changed //----------------------------------------------------------------------------- -void CommandClass::ReadValueRefreshXML -( - TiXmlElement const* _ccElement -) -{ - - char const* str; - bool ok = false; - const char *genre; - RefreshValue *rcc = new RefreshValue(); - rcc->cc = GetCommandClassId(); - genre = _ccElement->Attribute( "Genre" ); - rcc->genre = Value::GetGenreEnumFromName(genre); - int temp; - _ccElement->QueryIntAttribute( "Instance", &temp); - rcc->instance = (uint8)temp; - _ccElement->QueryIntAttribute( "Index", &temp); - rcc->index = (uint8)temp; - Log::Write(LogLevel_Info, GetNodeId(), "Value Refresh triggered by CommandClass: %s, Genre: %d, Instance: %d, Index: %d for:", GetCommandClassName().c_str(), rcc->genre, rcc->instance, rcc->index); - TiXmlElement const* child = _ccElement->FirstChildElement(); - while( child ) - { - str = child->Value(); - if( str ) - { - if ( !strcmp(str, "RefreshClassValue")) + void CommandClass::ReadValueRefreshXML(TiXmlElement const* _ccElement) { - RefreshValue *arcc = new RefreshValue(); - if (child->QueryIntAttribute( "CommandClass", &temp) != TIXML_SUCCESS) { - Log::Write(LogLevel_Warning, GetNodeId(), " Invalid XML - CommandClass Attribute is wrong type or missing"); - child = child->NextSiblingElement(); - continue; - } - arcc->cc = (uint8)temp; - if (child->QueryIntAttribute( "RequestFlags", &temp) != TIXML_SUCCESS) { - Log::Write(LogLevel_Warning, GetNodeId(), " Invalid XML - RequestFlags Attribute is wrong type or missing"); + + char const* str; + bool ok = false; + const char *genre; + RefreshValue *rcc = new RefreshValue(); + rcc->cc = GetCommandClassId(); + genre = _ccElement->Attribute("Genre"); + rcc->genre = Internal::VC::Value::GetGenreEnumFromName(genre); + int temp; + _ccElement->QueryIntAttribute("Instance", &temp); + rcc->instance = (uint8) temp; + _ccElement->QueryIntAttribute("Index", &temp); + rcc->index = (uint8) temp; + Log::Write(LogLevel_Info, GetNodeId(), "Value Refresh triggered by CommandClass: %s, Genre: %d, Instance: %d, Index: %d for:", GetCommandClassName().c_str(), rcc->genre, rcc->instance, rcc->index); + TiXmlElement const* child = _ccElement->FirstChildElement(); + while (child) + { + str = child->Value(); + if (str) + { + if (!strcmp(str, "RefreshClassValue")) + { + RefreshValue *arcc = new RefreshValue(); + if (child->QueryIntAttribute("CommandClass", &temp) != TIXML_SUCCESS) + { + Log::Write(LogLevel_Warning, GetNodeId(), " Invalid XML - CommandClass Attribute is wrong type or missing"); + child = child->NextSiblingElement(); + continue; + } + arcc->cc = (uint8) temp; + if (child->QueryIntAttribute("RequestFlags", &temp) != TIXML_SUCCESS) + { + Log::Write(LogLevel_Warning, GetNodeId(), " Invalid XML - RequestFlags Attribute is wrong type or missing"); + child = child->NextSiblingElement(); + continue; + } + arcc->genre = (uint8) temp; + if (child->QueryIntAttribute("Instance", &temp) != TIXML_SUCCESS) + { + Log::Write(LogLevel_Warning, GetNodeId(), " Invalid XML - Instance Attribute is wrong type or missing"); + child = child->NextSiblingElement(); + continue; + } + arcc->instance = (uint8) temp; + if (child->QueryIntAttribute("Index", &temp) != TIXML_SUCCESS) + { + Log::Write(LogLevel_Warning, GetNodeId(), " Invalid XML - Index Attribute is wrong type or missing"); + child = child->NextSiblingElement(); + continue; + } + arcc->index = (uint8) temp; + Log::Write(LogLevel_Info, GetNodeId(), " CommandClass: %s, RequestFlags: %d, Instance: %d, Index: %d", CommandClasses::GetName(arcc->cc).c_str(), arcc->genre, arcc->instance, arcc->index); + rcc->RefreshClasses.push_back(arcc); + ok = true; + } + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "Got Unhandled Child Entry in TriggerRefreshValue XML Config: %s", str); + } + } child = child->NextSiblingElement(); - continue; } - arcc->genre = (uint8)temp; - if (child->QueryIntAttribute( "Instance", &temp) != TIXML_SUCCESS) { - Log::Write(LogLevel_Warning, GetNodeId(), " Invalid XML - Instance Attribute is wrong type or missing"); - child = child->NextSiblingElement(); - continue; + if (ok == true) + { + m_RefreshClassValues.push_back(rcc); } - arcc->instance = (uint8)temp; - if (child->QueryIntAttribute( "Index", &temp) != TIXML_SUCCESS) { - Log::Write(LogLevel_Warning, GetNodeId(), " Invalid XML - Index Attribute is wrong type or missing"); - child = child->NextSiblingElement(); - continue; + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "Failed to add a RefreshClassValue from XML"); + delete rcc; } - arcc->index = (uint8)temp; - Log::Write(LogLevel_Info, GetNodeId(), " CommandClass: %s, RequestFlags: %d, Instance: %d, Index: %d", CommandClasses::GetName(arcc->cc).c_str(), arcc->genre, arcc->instance, arcc->index); - rcc->RefreshClasses.push_back(arcc); - ok = true; } - else - { - Log::Write(LogLevel_Warning, GetNodeId(), "Got Unhandled Child Entry in TriggerRefreshValue XML Config: %s", str); - } - } - child = child->NextSiblingElement(); - } - if (ok == true) { - m_RefreshClassValues.push_back( rcc ); - } else { - Log::Write(LogLevel_Warning, GetNodeId(), "Failed to add a RefreshClassValue from XML"); - delete rcc; - } -} //----------------------------------------------------------------------------- // @@ -398,483 +371,444 @@ void CommandClass::ReadValueRefreshXML // Command Classes to refresh their value //----------------------------------------------------------------------------- -bool CommandClass::CheckForRefreshValues ( - Value const* _value -) -{ - if (m_RefreshClassValues.empty()) - { - //Log::Write(LogLevel_Debug, GetNodeId(), "Bailing out of CheckForRefreshValues"); - return false; - } - Node* node = GetNodeUnsafe(); - if( node != NULL ) - { - for (uint32 i = 0; i < m_RefreshClassValues.size(); i++) - { - RefreshValue *rcc = m_RefreshClassValues.at(i); - //Log::Write(LogLevel_Debug, GetNodeId(), "Checking Value Against RefreshClassList: CommandClass %s = %s, Genre %d = %d, Instance %d = %d, Index %d = %d", CommandClasses::GetName(rcc->cc).c_str(), CommandClasses::GetName(_value->GetID().GetCommandClassId()).c_str(), rcc->genre, _value->GetID().GetGenre(), rcc->instance, _value->GetID().GetInstance(), rcc->index, _value->GetID().GetIndex()); - if ((rcc->genre == _value->GetID().GetGenre()) && (rcc->instance == _value->GetID().GetInstance()) && (rcc->index == _value->GetID().GetIndex()) ) + bool CommandClass::CheckForRefreshValues(Internal::VC::Value const* _value) { - /* we got a match..... */ - for (uint32 j = 0; j < rcc->RefreshClasses.size(); j++) + if (m_RefreshClassValues.empty()) + { + //Log::Write(LogLevel_Debug, GetNodeId(), "Bailing out of CheckForRefreshValues"); + return false; + } + Node* node = GetNodeUnsafe(); + if (node != NULL) { - RefreshValue *arcc = rcc->RefreshClasses.at(j); - Log::Write(LogLevel_Debug, GetNodeId(), "Requesting Refresh of Value: CommandClass: %s Genre %d, Instance %d, Index %d", CommandClasses::GetName(arcc->cc).c_str(), arcc->genre, arcc->instance, arcc->index); - if( CommandClass* cc = node->GetCommandClass( arcc->cc ) ) + for (uint32 i = 0; i < m_RefreshClassValues.size(); i++) { - cc->RequestValue(arcc->genre, arcc->index, arcc->instance, Driver::MsgQueue_Send); + RefreshValue *rcc = m_RefreshClassValues.at(i); + //Log::Write(LogLevel_Debug, GetNodeId(), "Checking Value Against RefreshClassList: CommandClass %s = %s, Genre %d = %d, Instance %d = %d, Index %d = %d", CommandClasses::GetName(rcc->cc).c_str(), CommandClasses::GetName(_value->GetID().GetCommandClassId()).c_str(), rcc->genre, _value->GetID().GetGenre(), rcc->instance, _value->GetID().GetInstance(), rcc->index, _value->GetID().GetIndex()); + if ((rcc->genre == _value->GetID().GetGenre()) && (rcc->instance == _value->GetID().GetInstance()) && (rcc->index == _value->GetID().GetIndex())) + { + /* we got a match..... */ + for (uint32 j = 0; j < rcc->RefreshClasses.size(); j++) + { + RefreshValue *arcc = rcc->RefreshClasses.at(j); + Log::Write(LogLevel_Debug, GetNodeId(), "Requesting Refresh of Value: CommandClass: %s Genre %d, Instance %d, Index %d", CommandClasses::GetName(arcc->cc).c_str(), arcc->genre, arcc->instance, arcc->index); + if (CommandClass* cc = node->GetCommandClass(arcc->cc)) + { + cc->RequestValue(arcc->genre, arcc->index, arcc->instance, Driver::MsgQueue_Send); + } + } + } } } + else /* Driver */ + { + Log::Write(LogLevel_Warning, GetNodeId(), "Can't get Node"); + } + return true; } - } - } - else /* Driver */ - { - Log::Write(LogLevel_Warning, GetNodeId(), "Can't get Node"); - } - return true; -} //----------------------------------------------------------------------------- // // Save the static node configuration data //----------------------------------------------------------------------------- -void CommandClass::WriteXML -( - TiXmlElement* _ccElement -) -{ - char str[32]; - - m_com.WriteXML(_ccElement); - m_dom.WriteXML(_ccElement); - + void CommandClass::WriteXML(TiXmlElement* _ccElement) + { + char str[32]; - snprintf( str, sizeof(str), "%d", GetCommandClassId() ); - _ccElement->SetAttribute( "id", str ); - _ccElement->SetAttribute( "name", GetCommandClassName().c_str() ); + m_com.WriteXML(_ccElement); + m_dom.WriteXML(_ccElement); + snprintf(str, sizeof(str), "%d", GetCommandClassId()); + _ccElement->SetAttribute("id", str); + _ccElement->SetAttribute("name", GetCommandClassName().c_str()); + // Write out the instances + for (Bitfield::Iterator it = m_instances.Begin(); it != m_instances.End(); ++it) + { + TiXmlElement* instanceElement = new TiXmlElement("Instance"); + _ccElement->LinkEndChild(instanceElement); + snprintf(str, sizeof(str), "%d", *it); + instanceElement->SetAttribute("index", str); - // Write out the instances - for( Bitfield::Iterator it = m_instances.Begin(); it != m_instances.End(); ++ it ) - { - TiXmlElement* instanceElement = new TiXmlElement( "Instance" ); - _ccElement->LinkEndChild( instanceElement ); - - snprintf( str, sizeof(str), "%d", *it ); - instanceElement->SetAttribute( "index", str ); + map::iterator eit = m_endPointMap.find(*it); + if (eit != m_endPointMap.end()) + { + snprintf(str, sizeof(str), "%d", eit->second); + instanceElement->SetAttribute("endpoint", str); + } + if (m_instanceLabel.count(*it) > 0) + instanceElement->SetAttribute("label", GetInstanceLabel(*it).c_str()); + } - map::iterator eit = m_endPointMap.find( *it ); - if( eit != m_endPointMap.end() ) - { - snprintf( str, sizeof(str), "%d", eit->second ); - instanceElement->SetAttribute( "endpoint", str ); - } - if ( m_instanceLabel.count(*it) > 0 ) - instanceElement->SetAttribute( "label", GetInstanceLabel(*it).c_str()); - } - - // Write out the values for this command class - ValueStore* store = GetNodeUnsafe()->GetValueStore(); - for( ValueStore::Iterator it = store->Begin(); it != store->End(); ++it ) - { - Value* value = it->second; - if( value->GetID().GetCommandClassId() == GetCommandClassId() ) - { - TiXmlElement* valueElement = new TiXmlElement( "Value" ); - _ccElement->LinkEndChild( valueElement ); - value->WriteXML( valueElement ); - } - } - // Write out the TriggerRefreshValue if it exists - for (uint32 i = 0; i < m_RefreshClassValues.size(); i++) - { - RefreshValue *rcc = m_RefreshClassValues.at(i); - TiXmlElement* RefreshElement = new TiXmlElement("TriggerRefreshValue"); - _ccElement->LinkEndChild( RefreshElement ); - RefreshElement->SetAttribute("Genre", Value::GetGenreNameFromEnum((ValueID::ValueGenre)rcc->genre)); - RefreshElement->SetAttribute("Instance", rcc->instance); - RefreshElement->SetAttribute("Index", rcc->index); - for (uint32 j = 0; j < rcc->RefreshClasses.size(); j++) - { - RefreshValue *arcc = rcc->RefreshClasses.at(j); - TiXmlElement *ClassElement = new TiXmlElement("RefreshClassValue"); - RefreshElement->LinkEndChild(ClassElement); - ClassElement->SetAttribute("CommandClass", arcc->cc); - ClassElement->SetAttribute("RequestFlags", arcc->genre); - ClassElement->SetAttribute("Instance", arcc->instance); - ClassElement->SetAttribute("Index", arcc->index); - } - } -} + // Write out the values for this command class + Internal::VC::ValueStore* store = GetNodeUnsafe()->GetValueStore(); + for (Internal::VC::ValueStore::Iterator it = store->Begin(); it != store->End(); ++it) + { + Internal::VC::Value* value = it->second; + if (value->GetID().GetCommandClassId() == GetCommandClassId()) + { + TiXmlElement* valueElement = new TiXmlElement("Value"); + _ccElement->LinkEndChild(valueElement); + value->WriteXML(valueElement); + } + } + // Write out the TriggerRefreshValue if it exists + for (uint32 i = 0; i < m_RefreshClassValues.size(); i++) + { + RefreshValue *rcc = m_RefreshClassValues.at(i); + TiXmlElement* RefreshElement = new TiXmlElement("TriggerRefreshValue"); + _ccElement->LinkEndChild(RefreshElement); + RefreshElement->SetAttribute("Genre", Internal::VC::Value::GetGenreNameFromEnum((ValueID::ValueGenre) rcc->genre)); + RefreshElement->SetAttribute("Instance", rcc->instance); + RefreshElement->SetAttribute("Index", rcc->index); + for (uint32 j = 0; j < rcc->RefreshClasses.size(); j++) + { + RefreshValue *arcc = rcc->RefreshClasses.at(j); + TiXmlElement *ClassElement = new TiXmlElement("RefreshClassValue"); + RefreshElement->LinkEndChild(ClassElement); + ClassElement->SetAttribute("CommandClass", arcc->cc); + ClassElement->SetAttribute("RequestFlags", arcc->genre); + ClassElement->SetAttribute("Instance", arcc->instance); + ClassElement->SetAttribute("Index", arcc->index); + } + } + } //----------------------------------------------------------------------------- // // Read a value from a variable length sequence of bytes //----------------------------------------------------------------------------- -string CommandClass::ExtractValue -( - uint8 const* _data, - uint8* _scale, - uint8* _precision, - uint8 _valueOffset // = 1 -)const -{ - uint8 const size = _data[0] & c_sizeMask; - uint8 const precision = (_data[0] & c_precisionMask) >> c_precisionShift; + std::string CommandClass::ExtractValue(uint8 const* _data, uint8* _scale, uint8* _precision, uint8 _valueOffset // = 1 + ) const + { + uint8 const size = _data[0] & c_sizeMask; + uint8 const precision = (_data[0] & c_precisionMask) >> c_precisionShift; - if( _scale ) - { - *_scale = (_data[0] & c_scaleMask) >> c_scaleShift; - } + if (_scale) + { + *_scale = (_data[0] & c_scaleMask) >> c_scaleShift; + } - if( _precision ) - { - *_precision = precision; - } + if (_precision) + { + *_precision = precision; + } - uint32 value = 0; - uint8 i; - for( i=0; idecimal_point); + // Insert the decimal point + struct lconv const* locale = localeconv(); + numBuf[decimal] = *(locale->decimal_point); - // Copy the buffer into res - res += &numBuf[start]; - } + // Copy the buffer into res + res += &numBuf[start]; + } - return res; -} + return res; + } //----------------------------------------------------------------------------- // // Add a value to a message as a sequence of bytes //----------------------------------------------------------------------------- -void CommandClass::AppendValue -( - Msg* _msg, - string const& _value, - uint8 const _scale -)const -{ - uint8 precision; - uint8 size; - int32 val = ValueToInteger( _value, &precision, &size ); + void CommandClass::AppendValue(Msg* _msg, std::string const& _value, uint8 const _scale) const + { + uint8 precision; + uint8 size; + int32 val = ValueToInteger(_value, &precision, &size); - _msg->Append( (precision<Append((precision << c_precisionShift) | (_scale << c_scaleShift) | size); - int32 shift = (size-1)<<3; - for( int32 i=size; i>0; --i, shift-=8 ) - { - _msg->Append( (uint8)(val >> shift) ); - } -} + int32 shift = (size - 1) << 3; + for (int32 i = size; i > 0; --i, shift -= 8) + { + _msg->Append((uint8) (val >> shift)); + } + } //----------------------------------------------------------------------------- // // Get the number of bytes that would be added by a call to AppendValue //----------------------------------------------------------------------------- -uint8 const CommandClass::GetAppendValueSize -( - string const& _value -)const -{ - uint8 size; - ValueToInteger( _value, NULL, &size ); - return size; -} + uint8 const CommandClass::GetAppendValueSize(std::string const& _value) const + { + uint8 size; + ValueToInteger(_value, NULL, &size); + return size; + } //----------------------------------------------------------------------------- // // Convert a decimal string to an integer and report the precision and // number of bytes required to store the value. //----------------------------------------------------------------------------- -int32 CommandClass::ValueToInteger -( - string const& _value, - uint8* o_precision, - uint8* o_size -)const -{ - int32 val; - uint8 precision; + int32 CommandClass::ValueToInteger(std::string const& _value, uint8* o_precision, uint8* o_size) const + { + int32 val; + uint8 precision; - // Find the decimal point - size_t pos = _value.find_first_of( "." ); - if( pos == string::npos ) - pos = _value.find_first_of( "," ); + // Find the decimal point + size_t pos = _value.find_first_of("."); + if (pos == std::string::npos) + pos = _value.find_first_of(","); - if( pos == string::npos ) - { - // No decimal point - precision = 0; + if (pos == std::string::npos) + { + // No decimal point + precision = 0; - // Convert the string to an integer - val = atol( _value.c_str() ); - } - else - { - // Remove the decimal point and convert to an integer - precision = (uint8) ((_value.size()-pos)-1); + // Convert the string to an integer + val = atol(_value.c_str()); + } + else + { + // Remove the decimal point and convert to an integer + precision = (uint8) ((_value.size() - pos) - 1); - string str = _value.substr( 0, pos ) + _value.substr( pos+1 ); - val = atol( str.c_str() ); - } + std::string str = _value.substr(0, pos) + _value.substr(pos + 1); + val = atol(str.c_str()); + } - uint8_t orp = m_com.GetFlagByte(COMPAT_FLAG_OVERRIDEPRECISION); - if ( orp > 0 ) - { - while ( precision < orp ) { - precision++; - val *= 10; - } - } + uint8_t orp = m_com.GetFlagByte(COMPAT_FLAG_OVERRIDEPRECISION); + if (orp > 0) + { + while (precision < orp) + { + precision++; + val *= 10; + } + } - if ( o_precision ) *o_precision = precision; + if (o_precision) + *o_precision = precision; - if( o_size ) - { - // Work out the size as either 1, 2 or 4 bytes - *o_size = 4; - if( val < 0 ) - { - if( ( val & 0xffffff80 ) == 0xffffff80 ) - { - *o_size = 1; - } - else if( ( val & 0xffff8000 ) == 0xffff8000 ) - { - *o_size = 2; - } - } - else - { - if( ( val & 0xffffff00 ) == 0 ) - { - *o_size = 1; - } - else if( ( val & 0xffff0000 ) == 0 ) - { - *o_size = 2; - } - } - } + if (o_size) + { + // Work out the size as either 1, 2 or 4 bytes + *o_size = 4; + if (val < 0) + { + if ((val & 0xffffff80) == 0xffffff80) + { + *o_size = 1; + } + else if ((val & 0xffff8000) == 0xffff8000) + { + *o_size = 2; + } + } + else + { + if ((val & 0xffffff00) == 0) + { + *o_size = 1; + } + else if ((val & 0xffff0000) == 0) + { + *o_size = 2; + } + } + } - return val; -} + return val; + } //----------------------------------------------------------------------------- // // Update the mapped class if there is one with BASIC level //----------------------------------------------------------------------------- -void CommandClass::UpdateMappedClass -( - uint8 const _instance, - uint8 const _classId, - uint8 const _level -) -{ - if( _classId ) - { - if( Node* node = GetNodeUnsafe() ) - { - CommandClass* cc = node->GetCommandClass( _classId ); - if( cc != NULL ) + void CommandClass::UpdateMappedClass(uint8 const _instance, uint8 const _classId, uint8 const _level) { - cc->SetValueBasic( _instance, _level ); + if (_classId) + { + if (Node* node = GetNodeUnsafe()) + { + CommandClass* cc = node->GetCommandClass(_classId); + if (cc != NULL) + { + cc->SetValueBasic(_instance, _level); + } + } + } } - } - } -} //----------------------------------------------------------------------------- // // The static data for this command class has been read from the device //----------------------------------------------------------------------------- -void CommandClass::ClearStaticRequest -( - uint8_t _request -) -{ - uint8_t f_staticRequests = m_dom.GetFlagByte(STATE_FLAG_STATIC_REQUESTS); - f_staticRequests &= ~_request; - m_dom.SetFlagByte(STATE_FLAG_STATIC_REQUESTS, f_staticRequests); -} + void CommandClass::ClearStaticRequest(uint8_t _request) + { + uint8_t f_staticRequests = m_dom.GetFlagByte(STATE_FLAG_STATIC_REQUESTS); + f_staticRequests &= ~_request; + m_dom.SetFlagByte(STATE_FLAG_STATIC_REQUESTS, f_staticRequests); + } //----------------------------------------------------------------------------- // // The static data for this command class has been read from the device //----------------------------------------------------------------------------- -void CommandClass::SetStaticRequest -( - uint8_t _request -) -{ - uint8_t f_staticRequests = m_dom.GetFlagByte(STATE_FLAG_STATIC_REQUESTS); - f_staticRequests |= _request; - m_dom.SetFlagByte(STATE_FLAG_STATIC_REQUESTS, f_staticRequests); -} + void CommandClass::SetStaticRequest(uint8_t _request) + { + uint8_t f_staticRequests = m_dom.GetFlagByte(STATE_FLAG_STATIC_REQUESTS); + f_staticRequests |= _request; + m_dom.SetFlagByte(STATE_FLAG_STATIC_REQUESTS, f_staticRequests); + } //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool CommandClass::RequestStateForAllInstances -( - uint32 const _requestFlags, - Driver::MsgQueue const _queue -) -{ - bool res = false; - if( m_com.GetFlagBool(COMPAT_FLAG_CREATEVARS) ) - { - if( Node* node = GetNodeUnsafe() ) - { - MultiInstance* multiInstance = static_cast( node->GetCommandClass( MultiInstance::StaticGetCommandClassId() ) ); - if( multiInstance != NULL ) + bool CommandClass::RequestStateForAllInstances(uint32 const _requestFlags, Driver::MsgQueue const _queue) { - for( Bitfield::Iterator it = m_instances.Begin(); it != m_instances.End(); ++it ) + bool res = false; + if (m_com.GetFlagBool(COMPAT_FLAG_CREATEVARS)) { - res |= RequestState( _requestFlags, (uint8)*it, _queue ); + if (Node* node = GetNodeUnsafe()) + { + MultiInstance* multiInstance = static_cast(node->GetCommandClass(MultiInstance::StaticGetCommandClassId())); + if (multiInstance != NULL) + { + for (Bitfield::Iterator it = m_instances.Begin(); it != m_instances.End(); ++it) + { + res |= RequestState(_requestFlags, (uint8) *it, _queue); + } + } + else + { + res = RequestState(_requestFlags, 1, _queue); + } + } } - } - else - { - res = RequestState( _requestFlags, 1, _queue ); - } - } - } - return res; -} + return res; + } //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -string const CommandClass::GetCommandClassLabel -( -) -{ - return m_commandClassLabel; -} + std::string const CommandClass::GetCommandClassLabel() + { + return m_commandClassLabel; + } //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -void CommandClass::SetCommandClassLabel -( - string label -) -{ - m_commandClassLabel = label; -} - + void CommandClass::SetCommandClassLabel(std::string label) + { + m_commandClassLabel = label; + } //----------------------------------------------------------------------------- // // Made out-of-line to allow overriding //----------------------------------------------------------------------------- -void CommandClass::SetVersion -( - uint8 const _version -) -{ - if( m_com.GetFlagByte(COMPAT_FLAG_FORCEVERSION) == 0 ) - { - if( _version >= m_dom.GetFlagByte(STATE_FLAG_CCVERSION) ) - { - m_dom.SetFlagByte(STATE_FLAG_CCVERSION, _version); - } - else { - Log::Write( LogLevel_Warning, GetNodeId(), "Trying to Downgrade Command Class %s version from %d to %d. Ignored", GetCommandClassName().c_str(), m_dom.GetFlagByte(STATE_FLAG_CCVERSION), _version); - } - } - else - { - m_dom.SetFlagByte(STATE_FLAG_CCVERSION, m_com.GetFlagByte(COMPAT_FLAG_FORCEVERSION)); - Log::Write( LogLevel_Warning, GetNodeId(), "Attempt to update Command Class %s version from %d to %d. Ignored", GetCommandClassName().c_str(), m_dom.GetFlagByte(STATE_FLAG_CCVERSION), _version); - } + void CommandClass::SetVersion(uint8 const _version) + { + if (m_com.GetFlagByte(COMPAT_FLAG_FORCEVERSION) == 0) + { + if (_version >= m_dom.GetFlagByte(STATE_FLAG_CCVERSION)) + { + m_dom.SetFlagByte(STATE_FLAG_CCVERSION, _version); + } + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "Trying to Downgrade Command Class %s version from %d to %d. Ignored", GetCommandClassName().c_str(), m_dom.GetFlagByte(STATE_FLAG_CCVERSION), _version); + } + } + else + { + m_dom.SetFlagByte(STATE_FLAG_CCVERSION, m_com.GetFlagByte(COMPAT_FLAG_FORCEVERSION)); + Log::Write(LogLevel_Warning, GetNodeId(), "Attempt to update Command Class %s version from %d to %d. Ignored", GetCommandClassName().c_str(), m_dom.GetFlagByte(STATE_FLAG_CCVERSION), _version); + } -} + } //----------------------------------------------------------------------------- // // Refresh Values upon Wakeup Notification //----------------------------------------------------------------------------- -void CommandClass::refreshValuesOnWakeup -( -) -{ - if (m_com.GetFlagBool(COMPAT_FLAG_REFRESHONWAKEUP)) { - Log::Write(LogLevel_Debug, GetNodeId(), "Refreshing Dynamic Values on Wakeup for CommandClass %s", GetCommandClassName().c_str()); - RequestStateForAllInstances( CommandClass::RequestFlag_Dynamic, Driver::MsgQueue_Send ); - } -} + void CommandClass::refreshValuesOnWakeup() + { + if (m_com.GetFlagBool(COMPAT_FLAG_REFRESHONWAKEUP)) + { + Log::Write(LogLevel_Debug, GetNodeId(), "Refreshing Dynamic Values on Wakeup for CommandClass %s", GetCommandClassName().c_str()); + RequestStateForAllInstances(CommandClass::RequestFlag_Dynamic, Driver::MsgQueue_Send); + } + } + + bool CommandClass::HandleIncomingMsg(uint8 const* _data, uint32 const _length, uint32 const _instance) + { + Log::Write(LogLevel_Warning, GetNodeId(), "Routing HandleIncomingMsg to HandleMsg - Please Report: %s ", GetCommandClassName().c_str()); + return HandleMsg(_data, _length, _instance); + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/CommandClass.h b/cpp/src/command_classes/CommandClass.h index 936ee94e70..1b76a5d11d 100644 --- a/cpp/src/command_classes/CommandClass.h +++ b/cpp/src/command_classes/CommandClass.h @@ -38,177 +38,259 @@ namespace OpenZWave { -class Msg; -class Node; -class Value; -/** \defgroup CommandClass Z-Wave CommandClass Support - * - * This is the CommandClasses that OZW currently supports. Typically, a Application does not need - * to be aware of the CommandClasses a Device exposes, as they would be transparently exposed to the - * application as ValueID's - */ - - -/** \brief Base class for all Z-Wave command classes. - * \ingroup CommandClass - */ -class OPENZWAVE_EXPORT CommandClass -{ -public: - enum - { - RequestFlag_Static = 0x00000001, /**< Values that never change. */ - RequestFlag_Session = 0x00000002, /**< Values that change infrequently, and so only need to be requested at start up, or via a manual refresh. */ - RequestFlag_Dynamic = 0x00000004, /**< Values that change and will be requested if polling is enabled on the node. */ - RequestFlag_AfterMark = 0x00000008 /**< Values relevent to Controlling CC, not Controlled CC. */ - }; - - CommandClass( uint32 const _homeId, uint8 const _nodeId ); - virtual ~CommandClass(); - - virtual void ReadXML( TiXmlElement const* _ccElement ); - virtual void WriteXML( TiXmlElement* _ccElement ); - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ){ return false; } - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ) { return false; } - virtual void refreshValuesOnWakeup(); - - - virtual uint8 const GetCommandClassId()const = 0; - virtual string const GetCommandClassName()const = 0; - string const GetCommandClassLabel(); - void SetCommandClassLabel(string label); - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ) = 0; - virtual bool HandleIncomingMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ) { return false; } - virtual bool SetValue( Value const& _value ){ return false; } - virtual void SetValueBasic( uint8 const _instance, uint8 const _level ){} // Class specific handling of BASIC value mapping - virtual void SetVersion( uint8 const _version ); // Made out-of-line to allow checks against downgrade - - bool RequestStateForAllInstances( uint32 const _requestFlags, Driver::MsgQueue const _queue ); - bool CheckForRefreshValues(Value const* _value ); - - // The highest version number of the command class implemented by OpenZWave. We only need - // to do version gets on command classes that override this with a number greater than one. - virtual uint8 GetMaxVersion(){ return 1; } - - uint8 GetVersion()const{ return m_dom.GetFlagByte(STATE_FLAG_CCVERSION); } - Bitfield const* GetInstances()const{ return &m_instances; } - uint32 GetHomeId()const{ return m_homeId; } - uint8 GetNodeId()const{ return m_nodeId; } - Driver* GetDriver()const; - Node* GetNodeUnsafe()const; - Value* GetValue( uint8 const _instance, uint16 const _index ); - bool RemoveValue( uint8 const _instance, uint16 const _index ); - uint8 GetEndPoint( uint8 const _instance ) - { - map::iterator it = m_endPointMap.find( _instance ); - return( it == m_endPointMap.end() ? 0 : it->second ); - } - uint8 GetInstance( uint8 const _endPoint ) + class Msg; + class Node; + class Value; + + namespace Internal { - for( map::iterator it = m_endPointMap.begin(); it != m_endPointMap.end(); ++it ) + namespace CC { - if( _endPoint == it->second ) + /** \defgroup CommandClass Z-Wave CommandClass Support + * + * This is the CommandClasses that OZW currently supports. Typically, a Application does not need + * to be aware of the CommandClasses a Device exposes, as they would be transparently exposed to the + * application as ValueID's + */ + + /** \brief Base class for all Z-Wave command classes. + * \ingroup CommandClass + */ + class OPENZWAVE_EXPORT CommandClass { - return it->first; - } - } - return 0; - } - - void SetInstances( uint8 const _instances ); - void SetInstance( uint8 const _endPoint ); - /* overridden in the MultiInstance CC to set the Global Label for each Instance */ - virtual void SetInstanceLabel(uint8 const _instance, char *label); - string GetInstanceLabel(uint8 const _instance); - uint8 GetNumInstances() { return (uint8)m_endPointMap.size(); }; - void SetAfterMark(){ m_dom.SetFlagBool(STATE_FLAG_AFTERMARK, true); } - void SetEndPoint( uint8 const _instance, uint8 const _endpoint){ m_endPointMap[_instance] = _endpoint; } - bool IsAfterMark()const{ return m_dom.GetFlagBool(STATE_FLAG_AFTERMARK); } - bool IsSecured()const{ return m_dom.GetFlagBool(STATE_FLAG_ENCRYPTED); } - void SetSecured(){ m_dom.SetFlagBool(STATE_FLAG_ENCRYPTED, true); } - bool IsSecureSupported()const { return m_SecureSupport; } - void ClearSecureSupport() { m_SecureSupport = false; } - void SetSecureSupport() { m_SecureSupport = true; } - void SetInNIF() { m_dom.SetFlagBool(STATE_FLAG_INNIF, true); } - bool IsInNIF() { return m_dom.GetFlagBool(STATE_FLAG_INNIF); } - - // Helper methods - string ExtractValue( uint8 const* _data, uint8* _scale, uint8* _precision, uint8 _valueOffset = 1 )const; - - /** - * Append a floating-point value to a message. - * \param _msg The message to which the value should be appended. - * \param _value A string containing a decimal number to be appended. - * \param _scale A byte indicating the scale corresponding to this value (e.g., 1=F and 0=C for temperatures). - * \see Msg - */ - void AppendValue( Msg* _msg, string const& _value, uint8 const _scale )const; - uint8 const GetAppendValueSize( string const& _value )const; - int32 ValueToInteger( string const& _value, uint8* o_precision, uint8* o_size )const; - - void UpdateMappedClass( uint8 const _instance, uint8 const _classId, uint8 const _value ); // Update mapped class's value from BASIC class - - typedef struct RefreshValue { - uint8 cc; - uint8 genre; - uint8 instance; - uint16 index; - std::vector RefreshClasses; - } RefreshValue; - -protected: - virtual void CreateVars( uint8 const _instance ){} - void ReadValueRefreshXML ( TiXmlElement const* _ccElement ); - CompatOptionManager m_com; - CompatOptionManager m_dom; - - -public: - virtual void CreateVars( uint8 const _instance, uint8 const _index ){} - -private: - uint32 m_homeId; - uint8 m_nodeId; - Bitfield m_instances; - OPENZWAVE_EXPORT_WARNINGS_OFF - map m_endPointMap; - map m_instanceLabel; - OPENZWAVE_EXPORT_WARNINGS_ON - bool m_SecureSupport; // Does this commandclass support secure encryption (eg, the Security CC doesn't encrypt itself, so it doesn't support encryption) - std::vector m_RefreshClassValues; // what Command Class Values should we refresh ? - string m_commandClassLabel; - //----------------------------------------------------------------------------- - // Record which items of static data have been read from the device - //----------------------------------------------------------------------------- -public: - enum StaticRequest - { - StaticRequest_Instances = 0x01, - StaticRequest_Values = 0x02, - StaticRequest_Version = 0x04 - }; - - bool HasStaticRequest( uint8_t _request )const{ return( (m_dom.GetFlagByte(STATE_FLAG_STATIC_REQUESTS) & _request) != 0 ); } - void SetStaticRequest( uint8_t _request ); - void ClearStaticRequest( uint8_t _request ); - - - //----------------------------------------------------------------------------- - // Statistics - //----------------------------------------------------------------------------- -public: - uint32 GetSentCnt()const{ return m_sentCnt; } - uint32 GetReceivedCnt()const{ return m_receivedCnt; } - void SentCntIncr(){ m_sentCnt++; } - void ReceivedCntIncr(){ m_receivedCnt++; } - -private: - uint32 m_sentCnt; // Number of messages sent from this command class. - uint32 m_receivedCnt; // Number of messages received from this commandclass. - -}; + friend Internal::VC::ValueStore; + public: + enum + { + RequestFlag_Static = 0x00000001, /**< Values that never change. */ + RequestFlag_Session = 0x00000002, /**< Values that change infrequently, and so only need to be requested at start up, or via a manual refresh. */ + RequestFlag_Dynamic = 0x00000004, /**< Values that change and will be requested if polling is enabled on the node. */ + RequestFlag_AfterMark = 0x00000008 /**< Values relevent to Controlling CC, not Controlled CC. */ + }; + + CommandClass(uint32 const _homeId, uint8 const _nodeId); + virtual ~CommandClass(); + + virtual void ReadXML(TiXmlElement const* _ccElement); + virtual void WriteXML(TiXmlElement* _ccElement); + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + return false; + } + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) + { + return false; + } + virtual void refreshValuesOnWakeup(); + + virtual uint8 const GetCommandClassId() const = 0; + virtual string const GetCommandClassName() const = 0; + string const GetCommandClassLabel(); + void SetCommandClassLabel(string label); + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) = 0; + virtual bool HandleIncomingMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1); + virtual bool SetValue(Internal::VC::Value const& _value) + { + return false; + } + virtual void SetValueBasic(uint8 const _instance, uint8 const _level) + { + } // Class specific handling of BASIC value mapping + virtual void SetVersion(uint8 const _version); // Made out-of-line to allow checks against downgrade + + bool RequestStateForAllInstances(uint32 const _requestFlags, Driver::MsgQueue const _queue); + bool CheckForRefreshValues(Internal::VC::Value const* _value); + + // The highest version number of the command class implemented by OpenZWave. We only need + // to do version gets on command classes that override this with a number greater than one. + virtual uint8 GetMaxVersion() + { + return 1; + } + + uint8 GetVersion() const + { + return m_dom.GetFlagByte(STATE_FLAG_CCVERSION); + } + Bitfield const* GetInstances() const + { + return &m_instances; + } + uint32 GetHomeId() const + { + return m_homeId; + } + uint8 GetNodeId() const + { + return m_nodeId; + } + Driver* GetDriver() const; + Node* GetNodeUnsafe() const; + Internal::VC::Value* GetValue(uint8 const _instance, uint16 const _index); + bool RemoveValue(uint8 const _instance, uint16 const _index); + uint8 GetEndPoint(uint8 const _instance) + { + map::iterator it = m_endPointMap.find(_instance); + return (it == m_endPointMap.end() ? 0 : it->second); + } + uint8 GetInstance(uint8 const _endPoint) + { + for (map::iterator it = m_endPointMap.begin(); it != m_endPointMap.end(); ++it) + { + if (_endPoint == it->second) + { + return it->first; + } + } + return 0; + } + + void SetInstances(uint8 const _instances); + void SetInstance(uint8 const _endPoint); + /* overridden in the MultiInstance CC to set the Global Label for each Instance */ + virtual void SetInstanceLabel(uint8 const _instance, char *label); + string GetInstanceLabel(uint8 const _instance); + uint8 GetNumInstances() + { + return (uint8) m_endPointMap.size(); + } + ; + void SetAfterMark() + { + m_dom.SetFlagBool(STATE_FLAG_AFTERMARK, true); + } + void SetEndPoint(uint8 const _instance, uint8 const _endpoint) + { + m_endPointMap[_instance] = _endpoint; + } + bool IsAfterMark() const + { + return m_dom.GetFlagBool(STATE_FLAG_AFTERMARK); + } + bool IsSecured() const + { + return m_dom.GetFlagBool(STATE_FLAG_ENCRYPTED); + } + void SetSecured() + { + m_dom.SetFlagBool(STATE_FLAG_ENCRYPTED, true); + } + bool IsSecureSupported() const + { + return m_SecureSupport; + } + void ClearSecureSupport() + { + m_SecureSupport = false; + } + void SetSecureSupport() + { + m_SecureSupport = true; + } + void SetInNIF() + { + m_dom.SetFlagBool(STATE_FLAG_INNIF, true); + } + bool IsInNIF() + { + return m_dom.GetFlagBool(STATE_FLAG_INNIF); + } + + // Helper methods + string ExtractValue(uint8 const* _data, uint8* _scale, uint8* _precision, uint8 _valueOffset = 1) const; + + /** + * Append a floating-point value to a message. + * \param _msg The message to which the value should be appended. + * \param _value A string containing a decimal number to be appended. + * \param _scale A byte indicating the scale corresponding to this value (e.g., 1=F and 0=C for temperatures). + * \see Msg + */ + void AppendValue(Msg* _msg, string const& _value, uint8 const _scale) const; + uint8 const GetAppendValueSize(string const& _value) const; + int32 ValueToInteger(string const& _value, uint8* o_precision, uint8* o_size) const; + + void UpdateMappedClass(uint8 const _instance, uint8 const _classId, uint8 const _value); // Update mapped class's value from BASIC class + + typedef struct RefreshValue + { + uint8 cc; + uint8 genre; + uint8 instance; + uint16 index; + std::vector RefreshClasses; + } RefreshValue; + + protected: + virtual void CreateVars(uint8 const _instance) + { + } + void ReadValueRefreshXML(TiXmlElement const* _ccElement); + CompatOptionManager m_com; + CompatOptionManager m_dom; + + public: + virtual void CreateVars(uint8 const _instance, uint8 const _index) + { + } + + private: + uint32 m_homeId; + uint8 m_nodeId; + Bitfield m_instances; + map m_endPointMap; + map m_instanceLabel; + bool m_SecureSupport; // Does this commandclass support secure encryption (eg, the Security CC doesn't encrypt itself, so it doesn't support encryption) + std::vector m_RefreshClassValues; // what Command Class Values should we refresh ? + string m_commandClassLabel; + //----------------------------------------------------------------------------- + // Record which items of static data have been read from the device + //----------------------------------------------------------------------------- + public: + enum StaticRequest + { + StaticRequest_Instances = 0x01, + StaticRequest_Values = 0x02, + StaticRequest_Version = 0x04 + }; + + bool HasStaticRequest(uint8_t _request) const + { + return ((m_dom.GetFlagByte(STATE_FLAG_STATIC_REQUESTS) & _request) != 0); + } + void SetStaticRequest(uint8_t _request); + void ClearStaticRequest(uint8_t _request); + + //----------------------------------------------------------------------------- + // Statistics + //----------------------------------------------------------------------------- + public: + uint32 GetSentCnt() const + { + return m_sentCnt; + } + uint32 GetReceivedCnt() const + { + return m_receivedCnt; + } + void SentCntIncr() + { + m_sentCnt++; + } + void ReceivedCntIncr() + { + m_receivedCnt++; + } + + private: + uint32 m_sentCnt; // Number of messages sent from this command class. + uint32 m_receivedCnt; // Number of messages received from this commandclass. + + }; //@} + }// namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/CommandClasses.cpp b/cpp/src/command_classes/CommandClasses.cpp index 2fec96638f..d8748caeec 100644 --- a/cpp/src/command_classes/CommandClasses.cpp +++ b/cpp/src/command_classes/CommandClasses.cpp @@ -28,9 +28,6 @@ #include #include "command_classes/CommandClasses.h" - -using namespace OpenZWave; - #include "command_classes/Alarm.h" #include "command_classes/ApplicationStatus.h" #include "command_classes/Association.h" @@ -104,254 +101,234 @@ using namespace OpenZWave; #include "Utils.h" #include "Localization.h" +namespace OpenZWave +{ + namespace Internal + { + namespace CC + { + //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -CommandClasses::CommandClasses -( -) -{ - memset( m_commandClassCreators, 0, sizeof(pfnCreateCommandClass_t)*256 ); - memset( m_supportedCommandClasses, 0, sizeof(uint32)*8 ); -} + CommandClasses::CommandClasses() + { + memset(m_commandClassCreators, 0, sizeof(pfnCreateCommandClass_t) * 256); + memset(m_supportedCommandClasses, 0, sizeof(uint32) * 8); + } //----------------------------------------------------------------------------- // // Static method to determine whether a command class is supported //----------------------------------------------------------------------------- -bool CommandClasses::IsSupported -( - uint8 const _commandClassId -) -{ - // Test the bit representing the command class - return( (Get().m_supportedCommandClasses[_commandClassId>>5] & (1u<<(_commandClassId&0x1f))) != 0 ); -} -string CommandClasses::GetName -( - uint8 const _commandClassId -) -{ - for (std::map::iterator it = Get().m_namesToIDs.begin(); it != Get().m_namesToIDs.end(); it++) { - if (it->second == _commandClassId) - return it->first; - } - return string("Unknown"); -} + bool CommandClasses::IsSupported(uint8 const _commandClassId) + { + // Test the bit representing the command class + return ((Get().m_supportedCommandClasses[_commandClassId >> 5] & (1u << (_commandClassId & 0x1f))) != 0); + } + std::string CommandClasses::GetName(uint8 const _commandClassId) + { + for (std::map::iterator it = Get().m_namesToIDs.begin(); it != Get().m_namesToIDs.end(); it++) + { + if (it->second == _commandClassId) + return it->first; + } + return string("Unknown"); + } //----------------------------------------------------------------------------- // // Static method to register a command class creator method //----------------------------------------------------------------------------- -void CommandClasses::Register -( - uint8 const _commandClassId, - string const& _commandClassName, - pfnCreateCommandClass_t _creator, - bool advertised -) -{ - m_commandClassCreators[_commandClassId] = _creator; + void CommandClasses::Register(uint8 const _commandClassId, string const& _commandClassName, pfnCreateCommandClass_t _creator, bool advertised) + { + m_commandClassCreators[_commandClassId] = _creator; - // Set the bit representing the command class - Get().m_supportedCommandClasses[_commandClassId>>5] |= (1u<<(_commandClassId&0x1f)); + // Set the bit representing the command class + Get().m_supportedCommandClasses[_commandClassId >> 5] |= (1u << (_commandClassId & 0x1f)); - m_namesToIDs[_commandClassName] = _commandClassId; - if (advertised) - { - /* ZWavePlus CC must always be first */ - if (_commandClassId == ZWavePlusInfo::StaticGetCommandClassId()) - m_advertisedCommandClasses.push_front(_commandClassId); - else - m_advertisedCommandClasses.push_back(_commandClassId); - } -} + m_namesToIDs[_commandClassName] = _commandClassId; + if (advertised) + { + /* ZWavePlus CC must always be first */ + if (_commandClassId == ZWavePlusInfo::StaticGetCommandClassId()) + m_advertisedCommandClasses.push_front(_commandClassId); + else + m_advertisedCommandClasses.push_back(_commandClassId); + } + } //----------------------------------------------------------------------------- // // Create a command class object using the registered method //----------------------------------------------------------------------------- -CommandClass* CommandClasses::CreateCommandClass -( - uint8 const _commandClassId, - uint32 const _homeId, - uint8 const _nodeId -) -{ - // Get a pointer to the required CommandClass's Create method - pfnCreateCommandClass_t creator = Get().m_commandClassCreators[_commandClassId]; - if( NULL == creator ) - { - return NULL; - } + CommandClass* CommandClasses::CreateCommandClass(uint8 const _commandClassId, uint32 const _homeId, uint8 const _nodeId) + { + // Get a pointer to the required CommandClass's Create method + pfnCreateCommandClass_t creator = Get().m_commandClassCreators[_commandClassId]; + if ( NULL == creator) + { + return NULL; + } - // Create an instance of the command class - CommandClass *cc = creator( _homeId, _nodeId); - Localization::Get()->SetupCommandClass(cc); - return cc; -} + // Create an instance of the command class + CommandClass *cc = creator(_homeId, _nodeId); + Localization::Get()->SetupCommandClass(cc); + return cc; + } //----------------------------------------------------------------------------- // // Register all our implemented command classes //----------------------------------------------------------------------------- -void CommandClasses::RegisterCommandClasses -( -) -{ - CommandClasses& cc = Get(); - cc.Register( Alarm::StaticGetCommandClassId(), Alarm::StaticGetCommandClassName(), Alarm::Create ); - cc.Register( ApplicationStatus::StaticGetCommandClassId(), ApplicationStatus::StaticGetCommandClassName(), ApplicationStatus::Create ); - cc.Register( Association::StaticGetCommandClassId(), Association::StaticGetCommandClassName(), Association::Create ); - cc.Register( AssociationCommandConfiguration::StaticGetCommandClassId(), AssociationCommandConfiguration::StaticGetCommandClassName(), AssociationCommandConfiguration::Create ); - cc.Register( SimpleAV::StaticGetCommandClassId(), AssociationCommandConfiguration::StaticGetCommandClassName(), SimpleAV::Create ); - cc.Register( BarrierOperator::StaticGetCommandClassId(), BarrierOperator::StaticGetCommandClassName(), BarrierOperator::Create); - cc.Register( Basic::StaticGetCommandClassId(), Basic::StaticGetCommandClassName(), Basic::Create ); - cc.Register( BasicWindowCovering::StaticGetCommandClassId(), BasicWindowCovering::StaticGetCommandClassName(), BasicWindowCovering::Create ); - cc.Register( Battery::StaticGetCommandClassId(), Battery::StaticGetCommandClassName(), Battery::Create ); - cc.Register( CentralScene::StaticGetCommandClassId(), CentralScene::StaticGetCommandClassName(), CentralScene::Create ); - cc.Register( ClimateControlSchedule::StaticGetCommandClassId(), ClimateControlSchedule::StaticGetCommandClassName(), ClimateControlSchedule::Create ); - cc.Register( Clock::StaticGetCommandClassId(), Clock::StaticGetCommandClassName(), Clock::Create ); - cc.Register( Color::StaticGetCommandClassId(), Color::StaticGetCommandClassName(), Color::Create ); - cc.Register( Configuration::StaticGetCommandClassId(), Configuration::StaticGetCommandClassName(), Configuration::Create ); - cc.Register( ControllerReplication::StaticGetCommandClassId(), ControllerReplication::StaticGetCommandClassName(), ControllerReplication::Create ); - cc.Register( CRC16Encap::StaticGetCommandClassId(), CRC16Encap::StaticGetCommandClassName(), CRC16Encap::Create ); - cc.Register( DeviceResetLocally::StaticGetCommandClassId(), DeviceResetLocally::StaticGetCommandClassName(), DeviceResetLocally::Create ); - cc.Register( DoorLock::StaticGetCommandClassId(), DoorLock::StaticGetCommandClassName(), DoorLock::Create ); - cc.Register( DoorLockLogging::StaticGetCommandClassId(), DoorLockLogging::StaticGetCommandClassName(), DoorLockLogging::Create); - cc.Register( EnergyProduction::StaticGetCommandClassId(), EnergyProduction::StaticGetCommandClassName(), EnergyProduction::Create ); - cc.Register( Hail::StaticGetCommandClassId(), Hail::StaticGetCommandClassName(), Hail::Create ); - cc.Register( Indicator::StaticGetCommandClassId(), Indicator::StaticGetCommandClassName(), Indicator::Create ); - cc.Register( Language::StaticGetCommandClassId(), Language::StaticGetCommandClassName(), Language::Create ); - cc.Register( Lock::StaticGetCommandClassId(), Lock::StaticGetCommandClassName(), Lock::Create ); - cc.Register( ManufacturerProprietary::StaticGetCommandClassId(), ManufacturerProprietary::StaticGetCommandClassName(), ManufacturerProprietary::Create ); - cc.Register( ManufacturerSpecific::StaticGetCommandClassId(), ManufacturerSpecific::StaticGetCommandClassName(), ManufacturerSpecific::Create ); - cc.Register( Meter::StaticGetCommandClassId(), Meter::StaticGetCommandClassName(), Meter::Create ); - cc.Register( MeterPulse::StaticGetCommandClassId(), MeterPulse::StaticGetCommandClassName(), MeterPulse::Create ); - cc.Register( MultiCmd::StaticGetCommandClassId(), MultiCmd::StaticGetCommandClassName(), MultiCmd::Create ); - cc.Register( MultiInstance::StaticGetCommandClassId(), MultiInstance::StaticGetCommandClassName(), MultiInstance::Create ); - cc.Register( MultiChannelAssociation::StaticGetCommandClassId(), MultiChannelAssociation::StaticGetCommandClassName(), MultiChannelAssociation::Create ); - cc.Register( NodeNaming::StaticGetCommandClassId(), NodeNaming::StaticGetCommandClassName(), NodeNaming::Create ); - cc.Register( NoOperation::StaticGetCommandClassId(), NoOperation::StaticGetCommandClassName(), NoOperation::Create ); - cc.Register( Powerlevel::StaticGetCommandClassId(), Powerlevel::StaticGetCommandClassName(), Powerlevel::Create ); - cc.Register( Proprietary::StaticGetCommandClassId(), Proprietary::StaticGetCommandClassName(), Proprietary::Create ); - cc.Register( Protection::StaticGetCommandClassId(), Protection::StaticGetCommandClassName(), Protection::Create ); - cc.Register( SceneActivation::StaticGetCommandClassId(), SceneActivation::StaticGetCommandClassName(), SceneActivation::Create ); - cc.Register( Security::StaticGetCommandClassId(), Security::StaticGetCommandClassName(), Security::Create); - cc.Register( SensorAlarm::StaticGetCommandClassId(), SensorAlarm::StaticGetCommandClassName(), SensorAlarm::Create ); - cc.Register( SensorBinary::StaticGetCommandClassId(), SensorBinary::StaticGetCommandClassName(), SensorBinary::Create ); - cc.Register( SensorMultilevel::StaticGetCommandClassId(), SensorMultilevel::StaticGetCommandClassName(), SensorMultilevel::Create ); - cc.Register( SoundSwitch::StaticGetCommandClassId(), SoundSwitch::StaticGetCommandClassName(), SoundSwitch::Create ); - cc.Register( SwitchAll::StaticGetCommandClassId(), SwitchAll::StaticGetCommandClassName(), SwitchAll::Create ); - cc.Register( SwitchBinary::StaticGetCommandClassId(), SwitchBinary::StaticGetCommandClassName(), SwitchBinary::Create ); - cc.Register( SwitchMultilevel::StaticGetCommandClassId(), SwitchMultilevel::StaticGetCommandClassName(), SwitchMultilevel::Create ); - cc.Register( SwitchToggleBinary::StaticGetCommandClassId(), SwitchToggleBinary::StaticGetCommandClassName(), SwitchToggleBinary::Create ); - cc.Register( SwitchToggleMultilevel::StaticGetCommandClassId(), SwitchToggleMultilevel::StaticGetCommandClassName(), SwitchToggleMultilevel::Create ); - cc.Register( TimeParameters::StaticGetCommandClassId(), TimeParameters::StaticGetCommandClassName(), TimeParameters::Create); - cc.Register( ThermostatFanMode::StaticGetCommandClassId(), ThermostatFanMode::StaticGetCommandClassName(), ThermostatFanMode::Create ); - cc.Register( ThermostatFanState::StaticGetCommandClassId(), ThermostatFanState::StaticGetCommandClassName(), ThermostatFanState::Create ); - cc.Register( ThermostatMode::StaticGetCommandClassId(), ThermostatMode::StaticGetCommandClassName(), ThermostatMode::Create ); - cc.Register( ThermostatOperatingState::StaticGetCommandClassId(), ThermostatOperatingState::StaticGetCommandClassName(), ThermostatOperatingState::Create ); - cc.Register( ThermostatSetpoint::StaticGetCommandClassId(), ThermostatSetpoint::StaticGetCommandClassName(), ThermostatSetpoint::Create ); - cc.Register( UserCode::StaticGetCommandClassId(), UserCode::StaticGetCommandClassName(), UserCode::Create ); - cc.Register( Version::StaticGetCommandClassId(), Version::StaticGetCommandClassName(), Version::Create ); - cc.Register( WakeUp::StaticGetCommandClassId(), WakeUp::StaticGetCommandClassName(), WakeUp::Create ); - cc.Register( ZWavePlusInfo::StaticGetCommandClassId(), ZWavePlusInfo::StaticGetCommandClassName(), ZWavePlusInfo::Create, true); + void CommandClasses::RegisterCommandClasses() + { + CommandClasses& cc = Get(); + cc.Register(Alarm::StaticGetCommandClassId(), Alarm::StaticGetCommandClassName(), Alarm::Create); + cc.Register(ApplicationStatus::StaticGetCommandClassId(), ApplicationStatus::StaticGetCommandClassName(), ApplicationStatus::Create); + cc.Register(Association::StaticGetCommandClassId(), Association::StaticGetCommandClassName(), Association::Create); + cc.Register(AssociationCommandConfiguration::StaticGetCommandClassId(), AssociationCommandConfiguration::StaticGetCommandClassName(), AssociationCommandConfiguration::Create); + cc.Register(SimpleAV::StaticGetCommandClassId(), SimpleAV::StaticGetCommandClassName(), SimpleAV::Create); + cc.Register(BarrierOperator::StaticGetCommandClassId(), BarrierOperator::StaticGetCommandClassName(), BarrierOperator::Create); + cc.Register(Basic::StaticGetCommandClassId(), Basic::StaticGetCommandClassName(), Basic::Create); + cc.Register(BasicWindowCovering::StaticGetCommandClassId(), BasicWindowCovering::StaticGetCommandClassName(), BasicWindowCovering::Create); + cc.Register(Battery::StaticGetCommandClassId(), Battery::StaticGetCommandClassName(), Battery::Create); + cc.Register(CentralScene::StaticGetCommandClassId(), CentralScene::StaticGetCommandClassName(), CentralScene::Create); + cc.Register(ClimateControlSchedule::StaticGetCommandClassId(), ClimateControlSchedule::StaticGetCommandClassName(), ClimateControlSchedule::Create); + cc.Register(Clock::StaticGetCommandClassId(), Clock::StaticGetCommandClassName(), Clock::Create); + cc.Register(Color::StaticGetCommandClassId(), Color::StaticGetCommandClassName(), Color::Create); + cc.Register(Configuration::StaticGetCommandClassId(), Configuration::StaticGetCommandClassName(), Configuration::Create); + cc.Register(ControllerReplication::StaticGetCommandClassId(), ControllerReplication::StaticGetCommandClassName(), ControllerReplication::Create); + cc.Register(CRC16Encap::StaticGetCommandClassId(), CRC16Encap::StaticGetCommandClassName(), CRC16Encap::Create); + cc.Register(DeviceResetLocally::StaticGetCommandClassId(), DeviceResetLocally::StaticGetCommandClassName(), DeviceResetLocally::Create); + cc.Register(DoorLock::StaticGetCommandClassId(), DoorLock::StaticGetCommandClassName(), DoorLock::Create); + cc.Register(DoorLockLogging::StaticGetCommandClassId(), DoorLockLogging::StaticGetCommandClassName(), DoorLockLogging::Create); + cc.Register(EnergyProduction::StaticGetCommandClassId(), EnergyProduction::StaticGetCommandClassName(), EnergyProduction::Create); + cc.Register(Hail::StaticGetCommandClassId(), Hail::StaticGetCommandClassName(), Hail::Create); + cc.Register(Indicator::StaticGetCommandClassId(), Indicator::StaticGetCommandClassName(), Indicator::Create); + cc.Register(Language::StaticGetCommandClassId(), Language::StaticGetCommandClassName(), Language::Create); + cc.Register(Lock::StaticGetCommandClassId(), Lock::StaticGetCommandClassName(), Lock::Create); + cc.Register(ManufacturerProprietary::StaticGetCommandClassId(), ManufacturerProprietary::StaticGetCommandClassName(), ManufacturerProprietary::Create); + cc.Register(ManufacturerSpecific::StaticGetCommandClassId(), ManufacturerSpecific::StaticGetCommandClassName(), ManufacturerSpecific::Create); + cc.Register(Meter::StaticGetCommandClassId(), Meter::StaticGetCommandClassName(), Meter::Create); + cc.Register(MeterPulse::StaticGetCommandClassId(), MeterPulse::StaticGetCommandClassName(), MeterPulse::Create); + cc.Register(MultiCmd::StaticGetCommandClassId(), MultiCmd::StaticGetCommandClassName(), MultiCmd::Create); + cc.Register(MultiInstance::StaticGetCommandClassId(), MultiInstance::StaticGetCommandClassName(), MultiInstance::Create); + cc.Register(MultiChannelAssociation::StaticGetCommandClassId(), MultiChannelAssociation::StaticGetCommandClassName(), MultiChannelAssociation::Create); + cc.Register(NodeNaming::StaticGetCommandClassId(), NodeNaming::StaticGetCommandClassName(), NodeNaming::Create); + cc.Register(NoOperation::StaticGetCommandClassId(), NoOperation::StaticGetCommandClassName(), NoOperation::Create); + cc.Register(Powerlevel::StaticGetCommandClassId(), Powerlevel::StaticGetCommandClassName(), Powerlevel::Create); + cc.Register(Proprietary::StaticGetCommandClassId(), Proprietary::StaticGetCommandClassName(), Proprietary::Create); + cc.Register(Protection::StaticGetCommandClassId(), Protection::StaticGetCommandClassName(), Protection::Create); + cc.Register(SceneActivation::StaticGetCommandClassId(), SceneActivation::StaticGetCommandClassName(), SceneActivation::Create); + cc.Register(Security::StaticGetCommandClassId(), Security::StaticGetCommandClassName(), Security::Create); + cc.Register(SensorAlarm::StaticGetCommandClassId(), SensorAlarm::StaticGetCommandClassName(), SensorAlarm::Create); + cc.Register(SensorBinary::StaticGetCommandClassId(), SensorBinary::StaticGetCommandClassName(), SensorBinary::Create); + cc.Register(SensorMultilevel::StaticGetCommandClassId(), SensorMultilevel::StaticGetCommandClassName(), SensorMultilevel::Create); + cc.Register(SoundSwitch::StaticGetCommandClassId(), SoundSwitch::StaticGetCommandClassName(), SoundSwitch::Create); + cc.Register(SwitchAll::StaticGetCommandClassId(), SwitchAll::StaticGetCommandClassName(), SwitchAll::Create); + cc.Register(SwitchBinary::StaticGetCommandClassId(), SwitchBinary::StaticGetCommandClassName(), SwitchBinary::Create); + cc.Register(SwitchMultilevel::StaticGetCommandClassId(), SwitchMultilevel::StaticGetCommandClassName(), SwitchMultilevel::Create); + cc.Register(SwitchToggleBinary::StaticGetCommandClassId(), SwitchToggleBinary::StaticGetCommandClassName(), SwitchToggleBinary::Create); + cc.Register(SwitchToggleMultilevel::StaticGetCommandClassId(), SwitchToggleMultilevel::StaticGetCommandClassName(), SwitchToggleMultilevel::Create); + cc.Register(TimeParameters::StaticGetCommandClassId(), TimeParameters::StaticGetCommandClassName(), TimeParameters::Create); + cc.Register(ThermostatFanMode::StaticGetCommandClassId(), ThermostatFanMode::StaticGetCommandClassName(), ThermostatFanMode::Create); + cc.Register(ThermostatFanState::StaticGetCommandClassId(), ThermostatFanState::StaticGetCommandClassName(), ThermostatFanState::Create); + cc.Register(ThermostatMode::StaticGetCommandClassId(), ThermostatMode::StaticGetCommandClassName(), ThermostatMode::Create); + cc.Register(ThermostatOperatingState::StaticGetCommandClassId(), ThermostatOperatingState::StaticGetCommandClassName(), ThermostatOperatingState::Create); + cc.Register(ThermostatSetpoint::StaticGetCommandClassId(), ThermostatSetpoint::StaticGetCommandClassName(), ThermostatSetpoint::Create); + cc.Register(UserCode::StaticGetCommandClassId(), UserCode::StaticGetCommandClassName(), UserCode::Create); + cc.Register(Version::StaticGetCommandClassId(), Version::StaticGetCommandClassName(), Version::Create); + cc.Register(WakeUp::StaticGetCommandClassId(), WakeUp::StaticGetCommandClassName(), WakeUp::Create); + cc.Register(ZWavePlusInfo::StaticGetCommandClassId(), ZWavePlusInfo::StaticGetCommandClassName(), ZWavePlusInfo::Create, true); - // Now all the command classes have been registered, we can modify the - // supported command classes array according to the program options. - string str; - Options::Get()->GetOptionAsString( "Include", &str ); - if( str != "" ) - { - // The include list has entries, so we assume that it is a - // complete list of what should be supported. - // Any existing support is cleared first. - memset( cc.m_supportedCommandClasses, 0, sizeof(uint32)*8 ); - cc.ParseCommandClassOption( str, true ); - } + // Now all the command classes have been registered, we can modify the + // supported command classes array according to the program options. + string str; + Options::Get()->GetOptionAsString("Include", &str); + if (str != "") + { + // The include list has entries, so we assume that it is a + // complete list of what should be supported. + // Any existing support is cleared first. + memset(cc.m_supportedCommandClasses, 0, sizeof(uint32) * 8); + cc.ParseCommandClassOption(str, true); + } - // Apply the excluded command class option - Options::Get()->GetOptionAsString( "Exclude", &str ); - if( str != "" ) - { - cc.ParseCommandClassOption( str, false ); - } -} + // Apply the excluded command class option + Options::Get()->GetOptionAsString("Exclude", &str); + if (str != "") + { + cc.ParseCommandClassOption(str, false); + } + } //----------------------------------------------------------------------------- // // Parse a comma delimited list of included/excluded command classes //----------------------------------------------------------------------------- -void CommandClasses::ParseCommandClassOption -( - string const& _optionStr, - bool const _include -) -{ - size_t pos = 0; - size_t start = 0; - bool parsing = true; - while( parsing ) - { - string ccStr; + void CommandClasses::ParseCommandClassOption(string const& _optionStr, bool const _include) + { + size_t pos = 0; + size_t start = 0; + bool parsing = true; + while (parsing) + { + string ccStr; - pos = _optionStr.find_first_of( ",", start ); - if( string::npos == pos ) - { - ccStr = _optionStr.substr( start ); - parsing = false; - } - else - { - ccStr = _optionStr.substr( start, pos-start ); - start = pos + 1; - } + pos = _optionStr.find_first_of(",", start); + if (string::npos == pos) + { + ccStr = _optionStr.substr(start); + parsing = false; + } + else + { + ccStr = _optionStr.substr(start, pos - start); + start = pos + 1; + } - if( ccStr != "" ) - { - uint8 ccIdx = GetCommandClassId( ccStr ); - if( _include ) - { - m_supportedCommandClasses[ccIdx>>5] |= (1u<<(ccIdx&0x1f)); - } - else - { - m_supportedCommandClasses[ccIdx>>5] &= ~(1u<<(ccIdx&0x1f)); + if (ccStr != "") + { + uint8 ccIdx = GetCommandClassId(ccStr); + if (_include) + { + m_supportedCommandClasses[ccIdx >> 5] |= (1u << (ccIdx & 0x1f)); + } + else + { + m_supportedCommandClasses[ccIdx >> 5] &= ~(1u << (ccIdx & 0x1f)); + } + } + } } - } - } -} //----------------------------------------------------------------------------- // // Convert a command class name (e.g COMMAND_CLASS_BASIC) into its 8-bit ID //----------------------------------------------------------------------------- -uint8 CommandClasses::GetCommandClassId -( - string const& _name -) -{ - string upperName = ToUpper( _name ); - map::iterator it = m_namesToIDs.find( upperName ); - if( it != m_namesToIDs.end() ) - { - return it->second; - } + uint8 CommandClasses::GetCommandClassId(string const& _name) + { + string upperName = ToUpper(_name); + map::iterator it = m_namesToIDs.find(upperName); + if (it != m_namesToIDs.end()) + { + return it->second; + } - return 0xff; -} + return 0xff; + } //----------------------------------------------------------------------------- // // return a list of Advertised CommandClasses //----------------------------------------------------------------------------- -list CommandClasses::GetAdvertisedCommandClasses -( -) -{ - CommandClasses& cc = Get(); - return cc.m_advertisedCommandClasses; -} - + std::list CommandClasses::GetAdvertisedCommandClasses() + { + CommandClasses& cc = Get(); + return cc.m_advertisedCommandClasses; + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/CommandClasses.h b/cpp/src/command_classes/CommandClasses.h index 79fad95433..0c6c90219f 100644 --- a/cpp/src/command_classes/CommandClasses.h +++ b/cpp/src/command_classes/CommandClasses.h @@ -35,52 +35,56 @@ namespace OpenZWave { - class CommandClass; - - /** \brief Manages a map of command classes supported by a specific Z-Wave node. - * \ingroup CommandClass - */ - class CommandClasses + namespace Internal { - public: - typedef CommandClass* (*pfnCreateCommandClass_t)( uint32 const _homeId, uint8 const _nodeId ); + namespace CC + { + class CommandClass; - static void RegisterCommandClasses(); - static CommandClass* CreateCommandClass( uint8 const _commandClassId, uint32 const _homeId, uint8 const _nodeId ); + /** \brief Manages a map of command classes supported by a specific Z-Wave node. + * \ingroup CommandClass + */ + class CommandClasses + { + public: + typedef CommandClass* (*pfnCreateCommandClass_t)(uint32 const _homeId, uint8 const _nodeId); - static bool IsSupported( uint8 const _commandClassId ); - static string GetName(uint8 const _commandClassId); - static list GetAdvertisedCommandClasses(); - private: - CommandClasses(); - CommandClasses( CommandClasses const& ); // prevent copy - CommandClasses& operator = ( CommandClasses const& ); // prevent assignment + static void RegisterCommandClasses(); + static CommandClass* CreateCommandClass(uint8 const _commandClassId, uint32 const _homeId, uint8 const _nodeId); - static CommandClasses& Get() - { - static CommandClasses instance; - return instance; - } + static bool IsSupported(uint8 const _commandClassId); + static string GetName(uint8 const _commandClassId); + static list GetAdvertisedCommandClasses(); + private: + CommandClasses(); + CommandClasses(CommandClasses const&); // prevent copy + CommandClasses& operator =(CommandClasses const&); // prevent assignment - void Register( uint8 const _commandClassId, string const& _commandClassName, pfnCreateCommandClass_t _create, bool advertised = false ); - void ParseCommandClassOption( string const& _optionStr, bool const _include ); - uint8 GetCommandClassId( string const& _name ); + static CommandClasses& Get() + { + static CommandClasses instance; + return instance; + } - pfnCreateCommandClass_t m_commandClassCreators[256]; - map m_namesToIDs; - /* a list of CommandClasses that are advertised on the controllers NIF packet and can be controlled - * via other Nodes - */ - list m_advertisedCommandClasses; + void Register(uint8 const _commandClassId, string const& _commandClassName, pfnCreateCommandClass_t _create, bool advertised = false); + void ParseCommandClassOption(string const& _optionStr, bool const _include); + uint8 GetCommandClassId(string const& _name); - // m_supportedCommandClasses uses single bits to mark whether OpenZWave supports a command class - // Checking this is not the same as looking for non-NULL entried in m_commandClassCreators, since - // this may be modified by the program options --Include and --Ingnore to filter out support - // for unwanted command classes. - uint32 m_supportedCommandClasses[8]; - }; + pfnCreateCommandClass_t m_commandClassCreators[256]; + map m_namesToIDs; + /* a list of CommandClasses that are advertised on the controllers NIF packet and can be controlled + * via other Nodes + */ + list m_advertisedCommandClasses; + // m_supportedCommandClasses uses single bits to mark whether OpenZWave supports a command class + // Checking this is not the same as looking for non-NULL entried in m_commandClassCreators, since + // this may be modified by the program options --Include and --Ingnore to filter out support + // for unwanted command classes. + uint32 m_supportedCommandClasses[8]; + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave - #endif diff --git a/cpp/src/command_classes/Configuration.cpp b/cpp/src/command_classes/Configuration.cpp index a478cee30d..5759727c74 100644 --- a/cpp/src/command_classes/Configuration.cpp +++ b/cpp/src/command_classes/Configuration.cpp @@ -40,252 +40,245 @@ #include "value_classes/ValueList.h" #include "value_classes/ValueShort.h" -using namespace OpenZWave; - -enum ConfigurationCmd +namespace OpenZWave { - ConfigurationCmd_Set = 0x04, - ConfigurationCmd_Get = 0x05, - ConfigurationCmd_Report = 0x06 -}; + namespace Internal + { + namespace CC + { + + enum ConfigurationCmd + { + ConfigurationCmd_Set = 0x04, + ConfigurationCmd_Get = 0x05, + ConfigurationCmd_Report = 0x06 + }; //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool Configuration::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if (ConfigurationCmd_Report == (ConfigurationCmd)_data[0]) - { - // Extract the parameter index and value - uint8 parameter = _data[1]; - uint8 size = _data[2] & 0x07; - int32 paramValue = 0; - for( uint8 i=0; iGetID().GetType() ) + bool Configuration::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) { - case ValueID::ValueType_BitSet: - { - ValueBitSet* vbs = static_cast( value ); - vbs->OnValueRefreshed( paramValue != 0 ); - break; - } - case ValueID::ValueType_Bool: - { - ValueBool* valueBool = static_cast( value ); - valueBool->OnValueRefreshed( paramValue != 0 ); - break; - } - case ValueID::ValueType_Byte: - { - ValueByte* valueByte = static_cast( value ); - valueByte->OnValueRefreshed( (uint8)paramValue ); - break; - } - case ValueID::ValueType_Short: - { - ValueShort* valueShort = static_cast( value ); - valueShort->OnValueRefreshed( (int16)paramValue ); - break; - } - case ValueID::ValueType_Int: - { - ValueInt* valueInt = static_cast( value ); - valueInt->OnValueRefreshed( paramValue ); - break; - } - case ValueID::ValueType_List: - { - ValueList* valueList = static_cast( value ); - valueList->OnValueRefreshed( paramValue ); - break; - } - default: + if (ConfigurationCmd_Report == (ConfigurationCmd) _data[0]) { - Log::Write( LogLevel_Info, GetNodeId(), "Invalid type (%d) for configuration parameter %d", value->GetID().GetType(), parameter ); + // Extract the parameter index and value + uint8 parameter = _data[1]; + uint8 size = _data[2] & 0x07; + int32 paramValue = 0; + for (uint8 i = 0; i < size; ++i) + { + paramValue <<= 8; + paramValue |= (int32) _data[i + 3]; + } + + if (Internal::VC::Value* value = GetValue(1, parameter)) + { + switch (value->GetID().GetType()) + { + case ValueID::ValueType_BitSet: + { + Internal::VC::ValueBitSet* vbs = static_cast(value); + vbs->OnValueRefreshed(paramValue); + break; + } + case ValueID::ValueType_Bool: + { + Internal::VC::ValueBool* valueBool = static_cast(value); + valueBool->OnValueRefreshed(paramValue != 0); + break; + } + case ValueID::ValueType_Byte: + { + Internal::VC::ValueByte* valueByte = static_cast(value); + valueByte->OnValueRefreshed((uint8) paramValue); + break; + } + case ValueID::ValueType_Short: + { + Internal::VC::ValueShort* valueShort = static_cast(value); + valueShort->OnValueRefreshed((int16) paramValue); + break; + } + case ValueID::ValueType_Int: + { + Internal::VC::ValueInt* valueInt = static_cast(value); + valueInt->OnValueRefreshed(paramValue); + break; + } + case ValueID::ValueType_List: + { + Internal::VC::ValueList* valueList = static_cast(value); + valueList->OnValueRefreshed(paramValue); + break; + } + default: + { + Log::Write(LogLevel_Info, GetNodeId(), "Invalid type (%d) for configuration parameter %d", value->GetID().GetType(), parameter); + } + } + value->Release(); + } + else + { + char label[16]; + snprintf(label, 16, "Parameter #%d", parameter); + + // Create a new value + if (Node* node = GetNodeUnsafe()) + { + switch (size) + { + case 1: + { + node->CreateValueByte(ValueID::ValueGenre_Config, GetCommandClassId(), _instance, parameter, label, "", false, false, (uint8) paramValue, 0); + break; + } + case 2: + { + node->CreateValueShort(ValueID::ValueGenre_Config, GetCommandClassId(), _instance, parameter, label, "", false, false, (int16) paramValue, 0); + break; + } + case 4: + { + node->CreateValueInt(ValueID::ValueGenre_Config, GetCommandClassId(), _instance, parameter, label, "", false, false, (int32) paramValue, 0); + break; + } + default: + { + Log::Write(LogLevel_Info, GetNodeId(), "Invalid size of %d bytes for configuration parameter %d", size, parameter); + } + } + } + } + + Log::Write(LogLevel_Info, GetNodeId(), "Received Configuration report: Parameter=%d, Value=%d", parameter, paramValue); + return true; } + + return false; } - value->Release(); - } - else - { - char label[16]; - snprintf( label, 16, "Parameter #%d", parameter ); - // Create a new value - if( Node* node = GetNodeUnsafe() ) +//----------------------------------------------------------------------------- +// +// Set a value in the Z-Wave device +//----------------------------------------------------------------------------- + bool Configuration::SetValue(Internal::VC::Value const& _value) { - switch( size ) + uint16 param = _value.GetID().GetIndex(); + switch (_value.GetID().GetType()) { - case 1: + case ValueID::ValueType_BitSet: + { + Internal::VC::ValueBitSet const& vbs = static_cast(_value); + Set(param, (int32) vbs.GetValue(), vbs.GetSize()); + return true; + } + case ValueID::ValueType_Bool: + { + Internal::VC::ValueBool const& valueBool = static_cast(_value); + Set(param, (int32) valueBool.GetValue(), 1); + return true; + } + case ValueID::ValueType_Byte: + { + Internal::VC::ValueByte const& valueByte = static_cast(_value); + Set(param, (int32) valueByte.GetValue(), 1); + return true; + } + case ValueID::ValueType_Short: + { + Internal::VC::ValueShort const& valueShort = static_cast(_value); + Set(param, (int32) valueShort.GetValue(), 2); + return true; + } + case ValueID::ValueType_Int: { - node->CreateValueByte( ValueID::ValueGenre_Config, GetCommandClassId(), _instance, parameter, label, "", false, false, (uint8)paramValue, 0 ); - break; + Internal::VC::ValueInt const& valueInt = static_cast(_value); + Set(param, valueInt.GetValue(), 4); + return true; } - case 2: + case ValueID::ValueType_List: { - node->CreateValueShort( ValueID::ValueGenre_Config, GetCommandClassId(), _instance, parameter, label, "", false, false, (int16)paramValue, 0 ); - break; + Internal::VC::ValueList const& valueList = static_cast(_value); + if (valueList.GetItem() != NULL) + Set(param, valueList.GetItem()->m_value, valueList.GetSize()); + return true; } - case 4: + case ValueID::ValueType_Button: { - node->CreateValueInt( ValueID::ValueGenre_Config, GetCommandClassId(), _instance, parameter, label, "", false, false, (int32)paramValue, 0 ); - break; + Internal::VC::ValueButton const& valueButton = static_cast(_value); + Set(param, valueButton.IsPressed(), 1); + return true; } default: { - Log::Write( LogLevel_Info, GetNodeId(), "Invalid size of %d bytes for configuration parameter %d", size, parameter ); } } - } - } - - Log::Write( LogLevel_Info, GetNodeId(), "Received Configuration report: Parameter=%d, Value=%d", parameter, paramValue ); - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// -// Set a value in the Z-Wave device -//----------------------------------------------------------------------------- -bool Configuration::SetValue -( - Value const& _value -) -{ - uint16 param = _value.GetID().GetIndex(); - switch( _value.GetID().GetType() ) - { - case ValueID::ValueType_BitSet: - { - ValueBitSet const& vbs = static_cast( _value ); - Set( param, (int32)vbs.GetValue(), vbs.GetSize() ); - return true; - } - case ValueID::ValueType_Bool: - { - ValueBool const& valueBool = static_cast( _value ); - Set( param, (int32)valueBool.GetValue(), 1 ); - return true; - } - case ValueID::ValueType_Byte: - { - ValueByte const& valueByte = static_cast( _value ); - Set( param, (int32)valueByte.GetValue(), 1 ); - return true; - } - case ValueID::ValueType_Short: - { - ValueShort const& valueShort = static_cast( _value ); - Set( param, (int32)valueShort.GetValue(), 2 ); - return true; - } - case ValueID::ValueType_Int: - { - ValueInt const& valueInt = static_cast( _value ); - Set( param, valueInt.GetValue(), 4 ); - return true; - } - case ValueID::ValueType_List: - { - ValueList const& valueList = static_cast( _value ); - if (valueList.GetItem() != NULL) - Set( param, valueList.GetItem()->m_value, valueList.GetSize() ); - return true; - } - case ValueID::ValueType_Button: - { - ValueButton const& valueButton = static_cast( _value ); - Set( param, valueButton.IsPressed(), 1 ); - return true; - } - default: - { - } - } - Log::Write( LogLevel_Info, GetNodeId(), "Configuration::Set failed (bad value or value type) - Parameter=%d", param ); - return false; -} + Log::Write(LogLevel_Info, GetNodeId(), "Configuration::Set failed (bad value or value type) - Parameter=%d", param); + return false; + } //----------------------------------------------------------------------------- // // Request current parameter value from the device //----------------------------------------------------------------------------- -bool Configuration::RequestValue -( - uint32 const _requestFlags, - uint16 const _parameter, // parameter number is encoded as the Index portion of ValueID - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _instance != 1 ) - { - // This command class doesn't work with multiple instances - return false; - } - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Msg* msg = new Msg( "ConfigurationCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( ConfigurationCmd_Get ); - msg->Append( (_parameter & 0xFF) ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "ConfigurationCmd_Get Not Supported on this node"); - } - return false; -} + bool Configuration::RequestValue(uint32 const _requestFlags, uint16 const _parameter, // parameter number is encoded as the Index portion of ValueID + uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_instance != 1) + { + // This command class doesn't work with multiple instances + return false; + } + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Msg* msg = new Msg("ConfigurationCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(ConfigurationCmd_Get); + msg->Append((_parameter & 0xFF)); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "ConfigurationCmd_Get Not Supported on this node"); + } + return false; + } //----------------------------------------------------------------------------- // // Set the device's //----------------------------------------------------------------------------- -void Configuration::Set -( - uint16 const _parameter, - int32 const _value, - uint8 const _size -) -{ - Log::Write( LogLevel_Info, GetNodeId(), "Configuration::Set - Parameter=%d, Value=%d Size=%d", _parameter, _value, _size ); + void Configuration::Set(uint16 const _parameter, int32 const _value, uint8 const _size) + { + Log::Write(LogLevel_Info, GetNodeId(), "Configuration::Set - Parameter=%d, Value=%d Size=%d", _parameter, _value, _size); - Msg* msg = new Msg( "ConfigurationCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); - msg->Append( GetNodeId() ); - msg->Append( 4 + _size ); - msg->Append( GetCommandClassId() ); - msg->Append( ConfigurationCmd_Set ); - msg->Append( (_parameter & 0xFF) ); - msg->Append( _size ); - if( _size > 2 ) - { - msg->Append( (uint8)( ( _value>>24 ) & 0xff ) ); - msg->Append( (uint8)( ( _value>>16 ) & 0xff ) ); - } - if( _size > 1 ) - { - msg->Append( (uint8)( ( _value>>8 ) & 0xff ) ); - } - msg->Append( (uint8)( _value & 0xff ) ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); -} + Msg* msg = new Msg("ConfigurationCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->Append(GetNodeId()); + msg->Append(4 + _size); + msg->Append(GetCommandClassId()); + msg->Append(ConfigurationCmd_Set); + msg->Append((_parameter & 0xFF)); + msg->Append(_size); + if (_size > 2) + { + msg->Append((uint8) ((_value >> 24) & 0xff)); + msg->Append((uint8) ((_value >> 16) & 0xff)); + } + if (_size > 1) + { + msg->Append((uint8) ((_value >> 8) & 0xff)); + } + msg->Append((uint8) (_value & 0xff)); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/Configuration.h b/cpp/src/command_classes/Configuration.h index 4714f410b2..ad9ae44236 100644 --- a/cpp/src/command_classes/Configuration.h +++ b/cpp/src/command_classes/Configuration.h @@ -33,35 +33,59 @@ namespace OpenZWave { - class Value; - - /** \brief Implements COMMAND_CLASS_CONFIGURATION (0x70), a Z-Wave device command class. - * \ingroup CommandClass - */ - class Configuration: public CommandClass + namespace Internal { - friend class Node; + namespace CC + { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Configuration( _homeId, _nodeId ); } - virtual ~Configuration(){} + /** \brief Implements COMMAND_CLASS_CONFIGURATION (0x70), a Z-Wave device command class. + * \ingroup CommandClass + */ + class Configuration: public CommandClass + { + friend class Node; - static uint8 const StaticGetCommandClassId(){ return 0x70; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_CONFIGURATION"; } + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new Configuration(_homeId, _nodeId); + } + virtual ~Configuration() + { + } - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _parameter, uint8 const _index, Driver::MsgQueue const _queue ); - void Set( uint16 const _parameter, int32 const _value, uint8 const _size ); + static uint8 const StaticGetCommandClassId() + { + return 0x70; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_CONFIGURATION"; + } - // From CommandClass - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool SetValue( Value const& _value ); + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _parameter, uint8 const _index, Driver::MsgQueue const _queue) override; + void Set(uint16 const _parameter, int32 const _value, uint8 const _size); - private: - Configuration( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} - }; + // From CommandClass + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool SetValue(Internal::VC::Value const& _value) override; + private: + Configuration(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + } + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/ControllerReplication.cpp b/cpp/src/command_classes/ControllerReplication.cpp index 9b520bb824..bb6d746395 100644 --- a/cpp/src/command_classes/ControllerReplication.cpp +++ b/cpp/src/command_classes/ControllerReplication.cpp @@ -33,295 +33,265 @@ #include "Node.h" #include "Utils.h" - #include "value_classes/ValueByte.h" #include "value_classes/ValueList.h" #include "value_classes/ValueButton.h" -using namespace OpenZWave; - -enum ControllerReplicationCmd +namespace OpenZWave { - ControllerReplicationCmd_TransferGroup = 0x31, - ControllerReplicationCmd_TransferGroupName = 0x32, - ControllerReplicationCmd_TransferScene = 0x33, - ControllerReplicationCmd_TransferSceneName = 0x34 -}; + namespace Internal + { + namespace CC + { -enum -{ - ControllerReplicationIndex_NodeId = 0, - ControllerReplicationIndex_Function, - ControllerReplicationIndex_Replicate -}; + enum ControllerReplicationCmd + { + ControllerReplicationCmd_TransferGroup = 0x31, + ControllerReplicationCmd_TransferGroupName = 0x32, + ControllerReplicationCmd_TransferScene = 0x33, + ControllerReplicationCmd_TransferSceneName = 0x34 + }; -static char const* c_controllerReplicationFunctionNames[] = -{ - "Groups", - "Group Names", - "Scenes", - "Scene Names", -}; + static char const* c_controllerReplicationFunctionNames[] = + { "Groups", "Group Names", "Scenes", "Scene Names", }; //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -ControllerReplication::ControllerReplication -( - uint32 const _homeId, - uint8 const _nodeId -): - CommandClass( _homeId, _nodeId ), - m_busy( false ), - m_targetNodeId( 0 ), - m_funcId( 0 ), - m_nodeId( -1 ), - m_groupCount( -1 ), - m_groupIdx( -1 ) -{ -} + ControllerReplication::ControllerReplication(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId), m_busy(false), m_targetNodeId(0), m_funcId(0), m_nodeId(-1), m_groupCount(-1), m_groupIdx(-1) + { + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool ControllerReplication::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - // When creating replication messages, use FUNC_ID_ZW_SEND_REPLICATION_DATA instead of FUNC_ID_ZW_SEND_DATA - // e.g. Msg* msg = new Msg( "TransferGroup", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_REPLICATION_DATA, true, false ); + bool ControllerReplication::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) + { + // When creating replication messages, use FUNC_ID_ZW_SEND_REPLICATION_DATA instead of FUNC_ID_ZW_SEND_DATA + // e.g. Msg* msg = new Msg( "TransferGroup", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_REPLICATION_DATA, true, false ); - switch( _data[0] ) - { - case ControllerReplicationCmd_TransferGroup: - { - break; - } - case ControllerReplicationCmd_TransferGroupName: - { - break; - } - case ControllerReplicationCmd_TransferScene: - { - break; - } - case ControllerReplicationCmd_TransferSceneName: - { - break; - } - } + switch (_data[0]) + { + case ControllerReplicationCmd_TransferGroup: + { + break; + } + case ControllerReplicationCmd_TransferGroupName: + { + break; + } + case ControllerReplicationCmd_TransferScene: + { + break; + } + case ControllerReplicationCmd_TransferSceneName: + { + break; + } + } - Msg* msg = new Msg( "ControllerReplicationCmd_Complete", GetNodeId(), REQUEST, FUNC_ID_ZW_REPLICATION_COMMAND_COMPLETE, false, false ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Command ); - return true; -} + Msg* msg = new Msg("ControllerReplicationCmd_Complete", GetNodeId(), REQUEST, FUNC_ID_ZW_REPLICATION_COMMAND_COMPLETE, false, false); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Command); + return true; + } //----------------------------------------------------------------------------- // // Set a value on the Z-Wave device //----------------------------------------------------------------------------- -bool ControllerReplication::SetValue -( - Value const& _value -) -{ - bool res = false; - uint8 instance = _value.GetID().GetInstance(); - - switch( _value.GetID().GetIndex() ) - { - case ControllerReplicationIndex_NodeId: - { - if( ValueByte* value = static_cast( GetValue( instance, (uint16)ControllerReplicationIndex_NodeId ) ) ) - { - value->OnValueRefreshed( (static_cast( &_value))->GetValue() ); - value->Release(); - res = true; - } - break; - } - case ControllerReplicationIndex_Function: - { - if( ValueList* value = static_cast( GetValue( instance, ControllerReplicationIndex_Function ) ) ) - { - ValueList::Item const *item = (static_cast( &_value))->GetItem(); - value->OnValueRefreshed( item->m_value ); - value->Release(); - res = true; - } - break; - } - case ControllerReplicationIndex_Replicate: - { - if( ValueButton* button = static_cast( GetValue( instance, ControllerReplicationIndex_Replicate ) ) ) + bool ControllerReplication::SetValue(Internal::VC::Value const& _value) { - if( button->IsPressed() ) + bool res = false; + uint8 instance = _value.GetID().GetInstance(); + + switch (_value.GetID().GetIndex()) { - res = StartReplication( instance ); + case ValueID_Index_ControllerReplication::NodeId: + { + if (Internal::VC::ValueByte* value = static_cast(GetValue(instance, (uint16) ValueID_Index_ControllerReplication::NodeId))) + { + value->OnValueRefreshed((static_cast(&_value))->GetValue()); + value->Release(); + res = true; + } + break; + } + case ValueID_Index_ControllerReplication::Function: + { + if (Internal::VC::ValueList* value = static_cast(GetValue(instance, ValueID_Index_ControllerReplication::Function))) + { + Internal::VC::ValueList::Item const *item = (static_cast(&_value))->GetItem(); + value->OnValueRefreshed(item->m_value); + value->Release(); + res = true; + } + break; + } + case ValueID_Index_ControllerReplication::Replicate: + { + if (Internal::VC::ValueButton* button = static_cast(GetValue(instance, ValueID_Index_ControllerReplication::Replicate))) + { + if (button->IsPressed()) + { + res = StartReplication(instance); + } + button->Release(); + } + break; + } } - button->Release(); + return res; } - break; - } - } - return res; -} //----------------------------------------------------------------------------- // // Set up the group and scene data to be sent to the other controller //----------------------------------------------------------------------------- -bool ControllerReplication::StartReplication -( - uint8 const _instance -) -{ - if( m_busy ) - { - return false; - } + bool ControllerReplication::StartReplication(uint8 const _instance) + { + if (m_busy) + { + return false; + } - if( ValueByte* value = static_cast( GetValue( _instance, ControllerReplicationIndex_NodeId ) ) ) - { - m_targetNodeId = value->GetValue(); - value->Release(); - } - else - { - return false; - } + if (Internal::VC::ValueByte* value = static_cast(GetValue(_instance, ValueID_Index_ControllerReplication::NodeId))) + { + m_targetNodeId = value->GetValue(); + value->Release(); + } + else + { + return false; + } - if( ValueList* value = static_cast( GetValue( _instance, ControllerReplicationIndex_Function ) ) ) - { - ValueList::Item const *item = value->GetItem(); - if (item) - m_funcId = item->m_value; - value->Release(); - } - else - { - return false; - } + if (Internal::VC::ValueList* value = static_cast(GetValue(_instance, ValueID_Index_ControllerReplication::Function))) + { + Internal::VC::ValueList::Item const *item = value->GetItem(); + if (item) + m_funcId = item->m_value; + value->Release(); + } + else + { + return false; + } - // Store the Z-Wave command we should use when replication has completed. - m_nodeId = -1; - m_groupCount = -1; - m_groupIdx = -1; - m_busy = true; + // Store the Z-Wave command we should use when replication has completed. + m_nodeId = -1; + m_groupCount = -1; + m_groupIdx = -1; + m_busy = true; - // Set up the groups and scenes to be sent - SendNextData(); - return true; -} + // Set up the groups and scenes to be sent + SendNextData(); + return true; + } //----------------------------------------------------------------------------- // // Send the next block of replication data //----------------------------------------------------------------------------- -void ControllerReplication::SendNextData -( -) -{ - uint16 i = 255; + void ControllerReplication::SendNextData() + { + uint16 i = 255; - if( !m_busy ) - { - return; - } + if (!m_busy) + { + return; + } - while( 1 ) - { - if( m_groupIdx != -1 ) - { - m_groupIdx++; - if( m_groupIdx <= m_groupCount ) - { - break; - } - } - i = m_nodeId == -1 ? 0 : m_nodeId+1; - LockGuard LG(GetDriver()->m_nodeMutex); - while( i < 256 ) - { - if( GetDriver()->m_nodes[i] ) - { - m_groupCount = GetDriver()->m_nodes[i]->GetNumGroups(); - if( m_groupCount != 0 ) + while (1) { - m_groupName = GetDriver()->m_nodes[i]->GetGroupLabel( m_groupIdx ); - m_groupIdx = m_groupName.length() > 0 ? 0 : 1; + if (m_groupIdx != -1) + { + m_groupIdx++; + if (m_groupIdx <= m_groupCount) + { + break; + } + } + i = m_nodeId == -1 ? 0 : m_nodeId + 1; + LockGuard LG(GetDriver()->m_nodeMutex); + while (i < 256) + { + if (GetDriver()->m_nodes[i]) + { + m_groupCount = GetDriver()->m_nodes[i]->GetNumGroups(); + if (m_groupCount != 0) + { + m_groupName = GetDriver()->m_nodes[i]->GetGroupLabel(m_groupIdx); + m_groupIdx = m_groupName.length() > 0 ? 0 : 1; + break; + } + } + i++; + } + m_nodeId = i; break; } + if (i < 255) + { + Msg* msg = new Msg((m_groupName.length() > 0 ? "ControllerReplicationCmd_TransferGroupName" : "ControllerReplicationCmd_TransferGroup"), m_targetNodeId, REQUEST, FUNC_ID_ZW_REPLICATION_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(m_targetNodeId); + if (m_groupName.length() > 0) + { + msg->Append((uint8) (m_groupName.length() + 4)); + msg->Append(GetCommandClassId()); + msg->Append(ControllerReplicationCmd_TransferGroupName); + msg->Append(0); + msg->Append(m_groupIdx); + for (uint8 j = 0; j < m_groupName.length(); j++) + { + msg->Append(m_groupName[j]); + } + m_groupName = ""; + } + else + { + msg->Append(5); + msg->Append(GetCommandClassId()); + msg->Append(ControllerReplicationCmd_TransferGroup); + msg->Append(0); + msg->Append(m_groupIdx); + msg->Append(m_nodeId); + } + msg->Append( TRANSMIT_OPTION_ACK); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Command); + } + else + { + GetDriver()->AddNodeStop(m_funcId); + m_busy = false; + } } - i++; - } - m_nodeId = i; - break; - } - if( i < 255 ) - { - Msg* msg = new Msg( (m_groupName.length() > 0 ? "ControllerReplicationCmd_TransferGroupName" : "ControllerReplicationCmd_TransferGroup"), m_targetNodeId, REQUEST, FUNC_ID_ZW_REPLICATION_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( m_targetNodeId ); - if( m_groupName.length() > 0 ) - { - msg->Append((uint8) (m_groupName.length() + 4 )); - msg->Append( GetCommandClassId() ); - msg->Append( ControllerReplicationCmd_TransferGroupName ); - msg->Append( 0 ); - msg->Append( m_groupIdx ); - for( uint8 j = 0; j < m_groupName.length(); j++ ) - { - msg->Append( m_groupName[j] ); - } - m_groupName = ""; - } - else - { - msg->Append( 5 ); - msg->Append( GetCommandClassId() ); - msg->Append( ControllerReplicationCmd_TransferGroup ); - msg->Append( 0 ); - msg->Append( m_groupIdx ); - msg->Append( m_nodeId ); - } - msg->Append( TRANSMIT_OPTION_ACK ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Command ); - } - else - { - GetDriver()->AddNodeStop( m_funcId ); - m_busy = false; - } -} //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void ControllerReplication::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - node->CreateValueByte( ValueID::ValueGenre_System, GetCommandClassId(), _instance, ControllerReplicationIndex_NodeId, "Node", "", false, false, 0, 0 ); - vector items; + void ControllerReplication::CreateVars(uint8 const _instance) + { + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueByte(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_ControllerReplication::NodeId, "Node", "", false, false, 0, 0); + vector items; - ValueList::Item item; - for( uint8 i=0; i<4; ++i ) - { - item.m_label = c_controllerReplicationFunctionNames[i]; - item.m_value = ControllerReplicationCmd_TransferGroup + i; - items.push_back( item ); - } + Internal::VC::ValueList::Item item; + for (uint8 i = 0; i < 4; ++i) + { + item.m_label = c_controllerReplicationFunctionNames[i]; + item.m_value = ControllerReplicationCmd_TransferGroup + i; + items.push_back(item); + } - node->CreateValueList( ValueID::ValueGenre_System, GetCommandClassId(), _instance, ControllerReplicationIndex_Function, "Functions", "", false, false, 1, items, 0, 0 ); - node->CreateValueButton( ValueID::ValueGenre_System, GetCommandClassId(), _instance, ControllerReplicationIndex_Replicate, "Replicate", 0 ); - } -} + node->CreateValueList(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_ControllerReplication::Function, "Functions", "", false, false, 1, items, 0, 0); + node->CreateValueButton(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_ControllerReplication::Replicate, "Replicate", 0); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/ControllerReplication.h b/cpp/src/command_classes/ControllerReplication.h index 2050d964c3..733514028c 100644 --- a/cpp/src/command_classes/ControllerReplication.h +++ b/cpp/src/command_classes/ControllerReplication.h @@ -32,43 +32,65 @@ namespace OpenZWave { - /** \brief Implements COMMAND_CLASS_CONTROLLER_REPLICATION (0x21), a Z-Wave device command class. - * \ingroup CommandClass - */ - class ControllerReplication: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new ControllerReplication( _homeId, _nodeId ); } - virtual ~ControllerReplication(){} + namespace CC + { - static uint8 const StaticGetCommandClassId(){ return 0x21; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_CONTROLLER_REPLICATION"; } + /** \brief Implements COMMAND_CLASS_CONTROLLER_REPLICATION (0x21), a Z-Wave device command class. + * \ingroup CommandClass + */ + class ControllerReplication: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new ControllerReplication(_homeId, _nodeId); + } + virtual ~ControllerReplication() + { + } - // From CommandClass - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool SetValue( Value const& _value ); + static uint8 const StaticGetCommandClassId() + { + return 0x21; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_CONTROLLER_REPLICATION"; + } - void SendNextData(); + // From CommandClass + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool SetValue(Internal::VC::Value const& _value) override; - protected: - virtual void CreateVars( uint8 const _instance ); + void SendNextData(); - private: - ControllerReplication( uint32 const _homeId, uint8 const _nodeId ); - bool StartReplication( uint8 const _instance ); + protected: + virtual void CreateVars(uint8 const _instance) override; + private: + ControllerReplication(uint32 const _homeId, uint8 const _nodeId); + bool StartReplication(uint8 const _instance); - bool m_busy; - uint8 m_targetNodeId; - uint8 m_funcId; - int m_nodeId; - int m_groupCount; - int m_groupIdx; - string m_groupName; - }; - + bool m_busy; + uint8 m_targetNodeId; + uint8 m_funcId; + int m_nodeId; + int m_groupCount; + int m_groupIdx; + string m_groupName; + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/DeviceResetLocally.cpp b/cpp/src/command_classes/DeviceResetLocally.cpp index 35efafd548..dd344584be 100644 --- a/cpp/src/command_classes/DeviceResetLocally.cpp +++ b/cpp/src/command_classes/DeviceResetLocally.cpp @@ -32,45 +32,48 @@ #include "Manager.h" #include "platform/Log.h" -using namespace OpenZWave; - -enum DeviceResetLocallyCmd +namespace OpenZWave { - DeviceResetLocallyCmd_Notification = 1 -}; + namespace Internal + { + namespace CC + { + enum DeviceResetLocallyCmd + { + DeviceResetLocallyCmd_Notification = 1 + }; //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool DeviceResetLocally::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if( DeviceResetLocallyCmd_Notification == _data[0] ) - { - // device has been reset - Log::Write( LogLevel_Info, GetNodeId(), "Received Device Reset Locally from node %d", GetNodeId() ); - - // send a NoOperation message to the node, this will fail since the node is no longer included in the network - // we must do this because the Controller will only remove failed nodes - if( Node* node = GetNodeUnsafe() ) - { - if( NoOperation* noop = static_cast( node->GetCommandClass( NoOperation::StaticGetCommandClassId(), false ) ) ) + bool DeviceResetLocally::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) { - noop->Set( true ); - } - } - // the Controller now knows the node has failed - Manager::Get()->HasNodeFailed( GetHomeId(), GetNodeId() ); - m_deviceReset = true; + if (DeviceResetLocallyCmd_Notification == _data[0]) + { + // device has been reset + Log::Write(LogLevel_Info, GetNodeId(), "Received Device Reset Locally from node %d", GetNodeId()); - return true; - } - return false; -} + // send a NoOperation message to the node, this will fail since the node is no longer included in the network + // we must do this because the Controller will only remove failed nodes + if (Node* node = GetNodeUnsafe()) + { + if (NoOperation* noop = static_cast(node->GetCommandClass(NoOperation::StaticGetCommandClassId()))) + { + noop->Set(true); + } + } + // the Controller now knows the node has failed + Manager::Get()->HasNodeFailed(GetHomeId(), GetNodeId()); + m_deviceReset = true; + + return true; + } + return false; + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/DeviceResetLocally.h b/cpp/src/command_classes/DeviceResetLocally.h index be7c2c002c..de3ca3aeea 100644 --- a/cpp/src/command_classes/DeviceResetLocally.h +++ b/cpp/src/command_classes/DeviceResetLocally.h @@ -32,28 +32,59 @@ namespace OpenZWave { - /** \brief Implements COMMAND_CLASS_DEVICE_RESET_LOCALLY (0x5a), a Z-Wave device command class. - * \ingroup CommandClass - */ - class DeviceResetLocally: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new DeviceResetLocally( _homeId, _nodeId ); } - virtual ~DeviceResetLocally(){} - - static uint8 const StaticGetCommandClassId(){ return 0x5a; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_DEVICE_RESET_LOCALLY"; } - - // From CommandClass - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool IsDeviceReset() { return m_deviceReset; }; - private: - DeviceResetLocally( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ), m_deviceReset(false) {}; - bool m_deviceReset; - }; + namespace CC + { + /** \brief Implements COMMAND_CLASS_DEVICE_RESET_LOCALLY (0x5a), a Z-Wave device command class. + * \ingroup CommandClass + */ + class DeviceResetLocally: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new DeviceResetLocally(_homeId, _nodeId); + } + virtual ~DeviceResetLocally() + { + } + + static uint8 const StaticGetCommandClassId() + { + return 0x5a; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_DEVICE_RESET_LOCALLY"; + } + + // From CommandClass + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool IsDeviceReset() + { + return m_deviceReset; + } + ; + private: + DeviceResetLocally(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId), m_deviceReset(false) + { + } + ; + bool m_deviceReset; + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/DoorLock.cpp b/cpp/src/command_classes/DoorLock.cpp index 20cb27e8d1..877b30e2e8 100644 --- a/cpp/src/command_classes/DoorLock.cpp +++ b/cpp/src/command_classes/DoorLock.cpp @@ -40,486 +40,454 @@ #include "tinyxml.h" -using namespace OpenZWave; - -enum DoorLockCmd -{ - DoorLockCmd_Set = 0x01, - DoorLockCmd_Get = 0x02, - DoorLockCmd_Report = 0x03, - DoorLockCmd_Configuration_Set = 0x04, - DoorLockCmd_Configuration_Get = 0x05, - DoorLockCmd_Configuration_Report= 0x06 -}; - -enum TimeOutMode -{ - DoorLockConfig_NoTimeout = 0x01, - DoorLockConfig_Timeout = 0x02 -}; - -static char const* c_TimeOutModeNames[] = -{ - "No Timeout", - "Secure Lock after Timeout" -}; - -enum DoorLockControlState +namespace OpenZWave { - DoorLockControlState_Handle1 = 0x01, - DoorLockControlState_Handle2 = 0x02, - DoorLockControlState_Handle3 = 0x04, - DoorLockControlState_Handle4 = 0x08 -}; + namespace Internal + { + namespace CC + { -enum ValueIDSystemIndexes -{ - Value_Lock = 0x00, /* Simple On/Off Mode for Lock */ - Value_Lock_Mode = 0x01, /* To Set more Complex Lock Modes (Such as timeouts etc) */ - Value_System_Config_Mode = 0x02, /* To Set/Unset if Locks should return to Secured Mode after a timeout */ - Value_System_Config_Minutes = 0x03, /* If Timeouts are enabled, how many minutes before a Lock "AutoLocks" */ - Value_System_Config_Seconds = 0x04, /* If Timeouts are enabled, how many seconds beofre a Lock "Autolocks" */ - Value_System_Config_OutsideHandles = 0x05, /* What Outside Handles are controlled via Z-Wave (BitMask 1-4) */ - Value_System_Config_InsideHandles = 0x06, /* What inside Handles are control via ZWave (BitMask 1-4) */ -}; - -enum DoorLockState -{ - DoorLockState_Unsecured = 0x00, - DoorLockState_Unsecured_Timeout = 0x01, - DoorLockState_Inside_Unsecured = 0x10, - DoorLockState_Inside_Unsecured_Timeout = 0x11, - DoorLockState_Outside_Unsecured = 0x20, - DoorLockState_Outside_Unsecured_Timeout = 0x21, - DoorLockState_Secured = 0xFF -}; + enum DoorLockCmd + { + DoorLockCmd_Set = 0x01, + DoorLockCmd_Get = 0x02, + DoorLockCmd_Report = 0x03, + DoorLockCmd_Configuration_Set = 0x04, + DoorLockCmd_Configuration_Get = 0x05, + DoorLockCmd_Configuration_Report = 0x06 + }; + + enum TimeOutMode + { + DoorLockConfig_NoTimeout = 0x01, + DoorLockConfig_Timeout = 0x02 + }; + static char const* c_TimeOutModeNames[] = + { "No Timeout", "Secure Lock after Timeout" }; -static char const* c_LockStateNames[] = -{ - "Unsecure", - "Unsecured with Timeout", - "Inside Handle Unsecured", - "Inside Handle Unsecured with Timeout", - "Outside Handle Unsecured", - "Outside Handle Unsecured with Timeout", - "Secured", - "Invalid" -}; + enum DoorLockControlState + { + DoorLockControlState_Handle1 = 0x01, + DoorLockControlState_Handle2 = 0x02, + DoorLockControlState_Handle3 = 0x04, + DoorLockControlState_Handle4 = 0x08 + }; + enum DoorLockState + { + DoorLockState_Unsecured = 0x00, + DoorLockState_Unsecured_Timeout = 0x01, + DoorLockState_Inside_Unsecured = 0x10, + DoorLockState_Inside_Unsecured_Timeout = 0x11, + DoorLockState_Outside_Unsecured = 0x20, + DoorLockState_Outside_Unsecured_Timeout = 0x21, + DoorLockState_Secured = 0xFF + }; + + static char const* c_LockStateNames[] = + { "Unsecure", "Unsecured with Timeout", "Inside Handle Unsecured", "Inside Handle Unsecured with Timeout", "Outside Handle Unsecured", "Outside Handle Unsecured with Timeout", "Secured", "Invalid" }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -DoorLock::DoorLock -( - uint32 const _homeId, - uint8 const _nodeId -): - CommandClass( _homeId, _nodeId ) -{ - m_dom.EnableFlag(STATE_FLAG_DOORLOCK_TIMEOUT, 0); - m_dom.EnableFlag(STATE_FLAG_DOORLOCK_INSIDEMODE, 0); - m_dom.EnableFlag(STATE_FLAG_DOORLOCK_OUTSIDEMODE, 0); - m_dom.EnableFlag(STATE_FLAG_DOORLOCK_TIMEOUTMINS, 0xFE); - m_dom.EnableFlag(STATE_FLAG_DOORLOCK_TIMEOUTSECS, 0xFE); - SetStaticRequest( StaticRequest_Values ); -} + DoorLock::DoorLock(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + m_dom.EnableFlag(STATE_FLAG_DOORLOCK_TIMEOUT, 0); + m_dom.EnableFlag(STATE_FLAG_DOORLOCK_INSIDEMODE, 0); + m_dom.EnableFlag(STATE_FLAG_DOORLOCK_OUTSIDEMODE, 0); + m_dom.EnableFlag(STATE_FLAG_DOORLOCK_TIMEOUTMINS, 0xFE); + m_dom.EnableFlag(STATE_FLAG_DOORLOCK_TIMEOUTSECS, 0xFE); + SetStaticRequest(StaticRequest_Values); + } //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool DoorLock::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - bool requests = false; - if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) ) - { - requests = RequestValue( _requestFlags, Value_System_Config_Mode, _instance, _queue ); - } - - if( _requestFlags & RequestFlag_Dynamic ) - { - requests |= RequestValue( _requestFlags, Value_Lock, _instance, _queue ); - } - - return requests; -} - + bool DoorLock::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + bool requests = false; + if ((_requestFlags & RequestFlag_Static) && HasStaticRequest(StaticRequest_Values)) + { + requests = RequestValue(_requestFlags, ValueID_Index_DoorLock::System_Config_Mode, _instance, _queue); + } + if (_requestFlags & RequestFlag_Dynamic) + { + requests |= RequestValue(_requestFlags, ValueID_Index_DoorLock::Lock, _instance, _queue); + } + return requests; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool DoorLock::RequestValue -( - uint32 const _requestFlags, - uint16 const _what, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if ( _what >= Value_System_Config_Mode) { - Msg* msg = new Msg( "DoorLockCmd_Configuration_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( DoorLockCmd_Configuration_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - - } else if ((_what == Value_Lock) || (_what == Value_Lock_Mode)) { - - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Msg* msg = new Msg( "DoorLockCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( DoorLockCmd_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "DoorLockCmd_Get Not Supported on this node"); - } - } - return false; -} + bool DoorLock::RequestValue(uint32 const _requestFlags, uint16 const _what, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_what >= ValueID_Index_DoorLock::System_Config_Mode) + { + Msg* msg = new Msg("DoorLockCmd_Configuration_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(DoorLockCmd_Configuration_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else if ((_what == ValueID_Index_DoorLock::Lock) || (_what == ValueID_Index_DoorLock::Lock_Mode)) + { + + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Msg* msg = new Msg("DoorLockCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(DoorLockCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "DoorLockCmd_Get Not Supported on this node"); + } + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool DoorLock::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - - if( DoorLockCmd_Report == (DoorLockCmd)_data[0] ) - { - uint8 lockState = (_data[1] == 0xFF) ? 6 : _data[1]; - if (lockState > 6) /* size of c_LockStateNames minus Invalid Entry */ - { - Log::Write (LogLevel_Warning, GetNodeId(), "LockState Value was greater than range. Setting to Invalid"); - lockState = 7; - } - - Log::Write( LogLevel_Info, GetNodeId(), "Received DoorLock report: DoorLock is %s", c_LockStateNames[lockState] ); + bool DoorLock::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) + { - if( ValueBool* value = static_cast( GetValue( _instance, Value_Lock ) ) ) - { - value->OnValueRefreshed( lockState == 0x06 ); - value->Release(); - } - if( ValueList* value = static_cast( GetValue( _instance, Value_Lock_Mode ) ) ) - { - value->OnValueRefreshed( lockState); - value->Release(); - } - return true; - } else if (DoorLockCmd_Configuration_Report == (DoorLockCmd)_data[0] ) - { - switch (_data[1]) { - case DoorLockConfig_NoTimeout: - m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_TIMEOUT, DoorLockConfig_NoTimeout); - RemoveValue(_instance, Value_System_Config_Minutes); - RemoveValue(_instance, Value_System_Config_Seconds); - m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_TIMEOUTMINS, 0xFE); - m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_TIMEOUTSECS, 0xFE); - break; - case DoorLockConfig_Timeout: - /* if we have a timeout, then create the Values for the timeout config */ - if( Node* node = GetNodeUnsafe() ) + if (DoorLockCmd_Report == (DoorLockCmd) _data[0]) { - node->CreateValueInt( ValueID::ValueGenre_System, GetCommandClassId(), _instance, Value_System_Config_Minutes, "Timeout Minutes", "Mins", false, false, _data[3], 0 ); - node->CreateValueInt( ValueID::ValueGenre_System, GetCommandClassId(), _instance, Value_System_Config_Seconds, "Timeout Seconds", "Secs", false, false, _data[4], 0 ); + uint8 lockState = (_data[1] == 0xFF) ? 6 : _data[1]; + if (lockState > 6) /* size of c_LockStateNames minus Invalid Entry */ + { + Log::Write(LogLevel_Warning, GetNodeId(), "LockState Value was greater than range. Setting to Invalid"); + lockState = 7; + } + + Log::Write(LogLevel_Info, GetNodeId(), "Received DoorLock report: DoorLock is %s", c_LockStateNames[lockState]); + + if (Internal::VC::ValueBool* value = static_cast(GetValue(_instance, ValueID_Index_DoorLock::Lock))) + { + value->OnValueRefreshed(lockState == 0x06); + value->Release(); + } + if (Internal::VC::ValueList* value = static_cast(GetValue(_instance, ValueID_Index_DoorLock::Lock_Mode))) + { + value->OnValueRefreshed(lockState); + value->Release(); + } + return true; } - m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_TIMEOUT, DoorLockConfig_Timeout); - m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_TIMEOUTMINS, _data[3]); - m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_TIMEOUTSECS, _data[4]); - break; - default: - Log::Write(LogLevel_Warning, GetNodeId(), "Received a Unsupported Door Lock Config Report %d", _data[1]); - } - - if( ValueByte* value = static_cast( GetValue( _instance, Value_System_Config_OutsideHandles ) ) ) - { - value->OnValueRefreshed( ((_data[2] & 0xF0)>>4) ); - value->Release(); - m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_OUTSIDEMODE, ((_data[2] & 0xF0)>>4)); - } - if( ValueByte* value = static_cast( GetValue( _instance, Value_System_Config_InsideHandles ) ) ) - { - value->OnValueRefreshed( (_data[2] & 0x0F) ); - value->Release(); - m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_INSIDEMODE, (_data[2] & 0x0F)); - } - - - ClearStaticRequest( StaticRequest_Values ); - - } - return false; -} + else if (DoorLockCmd_Configuration_Report == (DoorLockCmd) _data[0]) + { + switch (_data[1]) + { + case DoorLockConfig_NoTimeout: + m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_TIMEOUT, DoorLockConfig_NoTimeout); + RemoveValue(_instance, ValueID_Index_DoorLock::System_Config_Minutes); + RemoveValue(_instance, ValueID_Index_DoorLock::System_Config_Seconds); + m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_TIMEOUTMINS, 0xFE); + m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_TIMEOUTSECS, 0xFE); + break; + case DoorLockConfig_Timeout: + /* if we have a timeout, then create the Values for the timeout config */ + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueInt(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_DoorLock::System_Config_Minutes, "Timeout Minutes", "Mins", false, false, _data[3], 0); + node->CreateValueInt(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_DoorLock::System_Config_Seconds, "Timeout Seconds", "Secs", false, false, _data[4], 0); + } + m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_TIMEOUT, DoorLockConfig_Timeout); + m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_TIMEOUTMINS, _data[3]); + m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_TIMEOUTSECS, _data[4]); + break; + default: + Log::Write(LogLevel_Warning, GetNodeId(), "Received a Unsupported Door Lock Config Report %d", _data[1]); + } + + if (Internal::VC::ValueByte* value = static_cast(GetValue(_instance, ValueID_Index_DoorLock::System_Config_OutsideHandles))) + { + value->OnValueRefreshed(((_data[2] & 0xF0) >> 4)); + value->Release(); + m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_OUTSIDEMODE, ((_data[2] & 0xF0) >> 4)); + } + if (Internal::VC::ValueByte* value = static_cast(GetValue(_instance, ValueID_Index_DoorLock::System_Config_InsideHandles))) + { + value->OnValueRefreshed((_data[2] & 0x0F)); + value->Release(); + m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_INSIDEMODE, (_data[2] & 0x0F)); + } + + ClearStaticRequest(StaticRequest_Values); + Log::Write(LogLevel_Info, GetNodeId(), "REcieved DoorLock Config Report: OutsideMode %d, InsideMode %d, Timeout Enabled: %d : %d:%d", ((_data[2] & 0xF0) >> 4), (_data[2] & 0x0F), _data[1], _data[3], _data[4]); + return true; + } + return false; + } //----------------------------------------------------------------------------- // // Set the lock's state //----------------------------------------------------------------------------- -bool DoorLock::SetValue -( - Value const& _value -) -{ - uint8 instance = _value.GetID().GetInstance(); - if( (Value_Lock == _value.GetID().GetIndex()) && ValueID::ValueType_Bool == _value.GetID().GetType() ) - { - ValueBool const* value = static_cast(&_value); - - Log::Write( LogLevel_Info, GetNodeId(), "Value_Lock::Set - Requesting lock to be %s", value->GetValue() ? "Locked" : "Unlocked" ); - Msg* msg = new Msg( "DoorLockCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _value.GetID().GetInstance() ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( DoorLockCmd_Set ); - msg->Append( value->GetValue() ? 0xFF:0x00 ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - return true; - } - if ( (Value_Lock_Mode == _value.GetID().GetIndex()) && (ValueID::ValueType_List == _value.GetID().GetType()) ) - { - ValueList const* value = static_cast(&_value); - ValueList::Item const *item = value->GetItem(); - if (item == NULL) - return false; - - - Log::Write( LogLevel_Info, GetNodeId(), "Value_Lock_Mode::Set - Requesting lock to be %s", item->m_label.c_str() ); - Msg* msg = new Msg( "DoorLockCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _value.GetID().GetInstance() ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( DoorLockCmd_Set ); - msg->Append( item->m_value ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - return true; - } - /* if its any of our System Messages.... */ - if ( Value_System_Config_Mode <= _value.GetID().GetIndex() && Value_System_Config_InsideHandles >= _value.GetID().GetIndex() ) - { - bool sendmsg = true; - switch (_value.GetID().GetIndex()) { - /* this is a List */ - case Value_System_Config_Mode: - if (ValueID::ValueType_List != _value.GetID().GetType()) { - sendmsg = false; - break; - } - if( ValueList* value = static_cast( GetValue( instance, _value.GetID().GetIndex() ) ) ) + bool DoorLock::SetValue(Internal::VC::Value const& _value) + { + uint8 instance = _value.GetID().GetInstance(); + if ((ValueID_Index_DoorLock::Lock == _value.GetID().GetIndex()) && ValueID::ValueType_Bool == _value.GetID().GetType()) { - ValueList::Item const *item = (static_cast( &_value))->GetItem(); - if (item != NULL) - value->OnValueRefreshed( item->m_value ); - value->Release(); + Internal::VC::ValueBool const* value = static_cast(&_value); + + Log::Write(LogLevel_Info, GetNodeId(), "ValueID_Index_DoorLock::Lock::Set - Requesting lock to be %s", value->GetValue() ? "Locked" : "Unlocked"); + Msg* msg = new Msg("DoorLockCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _value.GetID().GetInstance()); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(DoorLockCmd_Set); + msg->Append(value->GetValue() ? 0xFF : 0x00); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return true; } - - break; - - /* these are a int */ - case Value_System_Config_Minutes: - case Value_System_Config_Seconds: - if (ValueID::ValueType_Int != _value.GetID().GetType()) { - sendmsg = false; - break; - } - if( ValueInt* value = static_cast( GetValue( instance, _value.GetID().GetIndex() ) ) ) + if ((ValueID_Index_DoorLock::Lock_Mode == _value.GetID().GetIndex()) && (ValueID::ValueType_List == _value.GetID().GetType())) { - value->OnValueRefreshed( (static_cast( &_value))->GetValue() ); - value->Release(); - } - break; - /* these are a byte */ - case Value_System_Config_OutsideHandles: - case Value_System_Config_InsideHandles: - if (ValueID::ValueType_Byte != _value.GetID().GetType()) { - sendmsg = false; - break; + Internal::VC::ValueList const* value = static_cast(&_value); + Internal::VC::ValueList::Item const *item = value->GetItem(); + if (item == NULL) + return false; + + Log::Write(LogLevel_Info, GetNodeId(), "ValueID_Index_DoorLock::Lock_Mode::Set - Requesting lock to be %s", item->m_label.c_str()); + Msg* msg = new Msg("DoorLockCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _value.GetID().GetInstance()); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(DoorLockCmd_Set); + msg->Append(item->m_value); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return true; } - if( ValueByte* value = static_cast( GetValue( instance, _value.GetID().GetIndex() ) ) ) + /* if its any of our System Messages.... */ + if (ValueID_Index_DoorLock::System_Config_Mode <= _value.GetID().GetIndex() && ValueID_Index_DoorLock::System_Config_InsideHandles >= _value.GetID().GetIndex()) { - value->OnValueRefreshed( (static_cast( &_value))->GetValue() ); - value->Release(); + bool sendmsg = true; + switch (_value.GetID().GetIndex()) + { + /* this is a List */ + case ValueID_Index_DoorLock::System_Config_Mode: + if (ValueID::ValueType_List != _value.GetID().GetType()) + { + sendmsg = false; + break; + } + if (Internal::VC::ValueList* value = static_cast(GetValue(instance, _value.GetID().GetIndex()))) + { + Internal::VC::ValueList::Item const *item = (static_cast(&_value))->GetItem(); + if (item != NULL) + value->OnValueRefreshed(item->m_value); + value->Release(); + } + + break; + + /* these are a int */ + case ValueID_Index_DoorLock::System_Config_Minutes: + case ValueID_Index_DoorLock::System_Config_Seconds: + if (ValueID::ValueType_Int != _value.GetID().GetType()) + { + sendmsg = false; + break; + } + if (Internal::VC::ValueInt* value = static_cast(GetValue(instance, _value.GetID().GetIndex()))) + { + value->OnValueRefreshed((static_cast(&_value))->GetValue()); + value->Release(); + } + break; + /* these are a byte */ + case ValueID_Index_DoorLock::System_Config_OutsideHandles: + case ValueID_Index_DoorLock::System_Config_InsideHandles: + if (ValueID::ValueType_Byte != _value.GetID().GetType()) + { + sendmsg = false; + break; + } + if (Internal::VC::ValueByte* value = static_cast(GetValue(instance, _value.GetID().GetIndex()))) + { + value->OnValueRefreshed((static_cast(&_value))->GetValue()); + value->Release(); + } + break; + default: + Log::Write(LogLevel_Warning, GetNodeId(), "DoorLock::SetValue - Unhandled System_Config Variable %d", _value.GetID().GetIndex()); + sendmsg = false; + break; + } + + if (sendmsg) + { + bool ok = true; + if (Internal::VC::ValueList* value = static_cast(GetValue(instance, ValueID_Index_DoorLock::System_Config_Mode))) + { + Internal::VC::ValueList::Item const *item = value->GetItem(); + if (item != NULL) + m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_TIMEOUT, item->m_value); + } + else + { + ok = false; + Log::Write(LogLevel_Warning, GetNodeId(), "Failed To Retrieve ValueID_Index_DoorLock::System_Config_Mode For SetValue"); + } + uint8 control = 0; + if (Internal::VC::ValueByte* value = static_cast(GetValue(instance, ValueID_Index_DoorLock::System_Config_OutsideHandles))) + { + control = (value->GetValue() << 4); + m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_INSIDEMODE, control); + } + else + { + ok = false; + Log::Write(LogLevel_Warning, GetNodeId(), "Failed To Retrieve ValueID_Index_DoorLock::System_Config_OutsideHandles For SetValue"); + } + if (Internal::VC::ValueByte* value = static_cast(GetValue(instance, ValueID_Index_DoorLock::System_Config_InsideHandles))) + { + control += (value->GetValue() & 0x0F); + m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_OUTSIDEMODE, (value->GetValue() & 0x0F)); + } + else + { + ok = false; + Log::Write(LogLevel_Warning, GetNodeId(), "Failed To Retrieve ValueID_Index_DoorLock::System_Config_InsideHandles For SetValue"); + } + if (Internal::VC::ValueInt* value = static_cast(GetValue(instance, ValueID_Index_DoorLock::System_Config_Minutes))) + { + m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_TIMEOUTMINS, value->GetValue()); + } + else + { + /* Minutes and Seconds Might Not Exist, this is fine. Set to 0xFE */ + m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_TIMEOUTMINS, 0xFE); + } + if (Internal::VC::ValueInt* value = static_cast(GetValue(instance, ValueID_Index_DoorLock::System_Config_Seconds))) + { + m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_TIMEOUTSECS, value->GetValue()); + } + else + { + /* Minutes and Seconds Might Not Exist, this is fine. Set to 0xFE */ + m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_TIMEOUTSECS, 0xFE); + } + if (ok) + { + Msg* msg = new Msg("DoorLockCmd_Configuration_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _value.GetID().GetInstance()); + msg->Append(GetNodeId()); + msg->Append(6); + msg->Append(GetCommandClassId()); + msg->Append(DoorLockCmd_Configuration_Set); + msg->Append(m_dom.GetFlagByte(STATE_FLAG_DOORLOCK_TIMEOUT)); + msg->Append(control); + msg->Append(m_dom.GetFlagByte(STATE_FLAG_DOORLOCK_TIMEOUTMINS)); + msg->Append(m_dom.GetFlagByte(STATE_FLAG_DOORLOCK_TIMEOUTSECS)); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return true; + } + return false; + } + } - break; - default: - Log::Write(LogLevel_Warning, GetNodeId(), "DoorLock::SetValue - Unhandled System_Config Variable %d", _value.GetID().GetIndex()); - sendmsg = false; - break; - } - - if (sendmsg) - { - bool ok = true; - if( ValueList* value = static_cast( GetValue( instance, Value_System_Config_Mode ) ) ) { - ValueList::Item const *item = value->GetItem(); - if (item != NULL) - m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_TIMEOUT, item->m_value); - } else { - ok = false; - Log::Write(LogLevel_Warning, GetNodeId(), "Failed To Retrieve Value_System_Config_Mode For SetValue"); + return false; } - uint8 control = 0; - if( ValueByte* value = static_cast( GetValue( instance, Value_System_Config_OutsideHandles ) ) ) - { - control = (value->GetValue() << 4); - m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_INSIDEMODE, control); - } else { - ok = false; - Log::Write(LogLevel_Warning, GetNodeId(), "Failed To Retrieve Value_System_Config_OutsideHandles For SetValue"); - } - if( ValueByte* value = static_cast( GetValue( instance, Value_System_Config_InsideHandles ) ) ) - { - control += (value->GetValue() & 0x0F); - m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_OUTSIDEMODE, (value->GetValue() & 0x0F)); - } else { - ok = false; - Log::Write(LogLevel_Warning, GetNodeId(), "Failed To Retrieve Value_System_Config_InsideHandles For SetValue"); - } - if( ValueInt* value = static_cast( GetValue( instance, Value_System_Config_Minutes ) ) ) - { - m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_TIMEOUTMINS, value->GetValue()); - } else { - /* Minutes and Seconds Might Not Exist, this is fine. Set to 0xFE */ - m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_TIMEOUTMINS, 0xFE); - } - if( ValueInt* value = static_cast( GetValue( instance, Value_System_Config_Seconds ) ) ) - { - m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_TIMEOUTSECS, value->GetValue()); - } else { - /* Minutes and Seconds Might Not Exist, this is fine. Set to 0xFE */ - m_dom.SetFlagByte(STATE_FLAG_DOORLOCK_TIMEOUTSECS, 0xFE); - } - if (ok) { - Msg* msg = new Msg( "DoorLockCmd_Configuration_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _value.GetID().GetInstance() ); - msg->Append( GetNodeId() ); - msg->Append( 6 ); - msg->Append( GetCommandClassId() ); - msg->Append( DoorLockCmd_Configuration_Set ); - msg->Append( m_dom.GetFlagByte(STATE_FLAG_DOORLOCK_TIMEOUT) ); - msg->Append( control ); - msg->Append( m_dom.GetFlagByte(STATE_FLAG_DOORLOCK_TIMEOUTMINS) ); - msg->Append( m_dom.GetFlagByte(STATE_FLAG_DOORLOCK_TIMEOUTSECS) ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - return true; - } - return false; - } - - } - return false; -} //----------------------------------------------------------------------------- // // Update class values based in BASIC mapping //----------------------------------------------------------------------------- -void DoorLock::SetValueBasic -( - uint8 const _instance, - uint8 const _value -) -{ - - - - // Send a request for new value to synchronize it with the BASIC set/report. - // In case the device is sleeping, we set the value anyway so the BASIC set/report - // stays in sync with it. We must be careful mapping the uint8 BASIC value - // into a class specific value. - // When the device wakes up, the real requested value will be retrieved. - RequestValue( 0, DoorLockCmd_Get, _instance, Driver::MsgQueue_Send ); - if( Node* node = GetNodeUnsafe() ) - { - if( WakeUp* wakeUp = static_cast( node->GetCommandClass( WakeUp::StaticGetCommandClassId() ) ) ) - { - if( !wakeUp->IsAwake() ) + void DoorLock::SetValueBasic(uint8 const _instance, uint8 const _value) { - if( ValueBool* value = static_cast( GetValue( _instance, Value_Lock ) ) ) + + // Send a request for new value to synchronize it with the BASIC set/report. + // In case the device is sleeping, we set the value anyway so the BASIC set/report + // stays in sync with it. We must be careful mapping the uint8 BASIC value + // into a class specific value. + // When the device wakes up, the real requested value will be retrieved. + RequestValue(0, DoorLockCmd_Get, _instance, Driver::MsgQueue_Send); + if (Node* node = GetNodeUnsafe()) { - value->OnValueRefreshed( _value != 0 ); - value->Release(); + if (WakeUp* wakeUp = static_cast(node->GetCommandClass(WakeUp::StaticGetCommandClassId()))) + { + if (!wakeUp->IsAwake()) + { + if (Internal::VC::ValueBool* value = static_cast(GetValue(_instance, ValueID_Index_DoorLock::Lock))) + { + value->OnValueRefreshed(_value != 0); + value->Release(); + } + } + } } } - } - } -} //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void DoorLock::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - node->CreateValueBool( ValueID::ValueGenre_User, GetCommandClassId(), _instance, Value_Lock, "Locked", "", false, false, false, 0 ); - - /* Complex Lock Option */ - { - vector items; - ValueList::Item item; - for( uint8 i=0; i<8; ++i ) - { - item.m_label = c_LockStateNames[i]; - item.m_value = (i < 6) ? i : 0xFF; - items.push_back( item ); - } - node->CreateValueList( ValueID::ValueGenre_User, GetCommandClassId(), _instance, Value_Lock_Mode, "Locked (Advanced)", "", false, false, 1, items, 0, 0 ); - - - } - - /* Timeout mode for Locks that support it */ - { - vector items; - ValueList::Item item; - for( uint8 i=0; i<2; ++i ) - { - item.m_label = c_TimeOutModeNames[i]; - item.m_value = i+1; - items.push_back( item ); - } - node->CreateValueList( ValueID::ValueGenre_System, GetCommandClassId(), _instance, Value_System_Config_Mode, "Timeout Mode", "", false, false, 1, items, 0, 0 ); - } - node->CreateValueByte( ValueID::ValueGenre_System, GetCommandClassId(), _instance, Value_System_Config_OutsideHandles, "Outside Handle Control", "", false, false, 0x0F, 0 ); - node->CreateValueByte( ValueID::ValueGenre_System, GetCommandClassId(), _instance, Value_System_Config_InsideHandles, "Inside Handle Control", "", false, false, 0x0F, 0 ); - - } -} + void DoorLock::CreateVars(uint8 const _instance) + { + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueBool(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_DoorLock::Lock, "Locked", "", false, false, false, 0); + + /* Complex Lock Option */ + { + vector items; + Internal::VC::ValueList::Item item; + for (uint8 i = 0; i < 8; ++i) + { + item.m_label = c_LockStateNames[i]; + item.m_value = (i < 6) ? i : 0xFF; + items.push_back(item); + } + node->CreateValueList(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_DoorLock::Lock_Mode, "Locked (Advanced)", "", false, false, 1, items, 0, 0); + + } + + /* Timeout mode for Locks that support it */ + { + vector items; + Internal::VC::ValueList::Item item; + for (uint8 i = 0; i < 2; ++i) + { + item.m_label = c_TimeOutModeNames[i]; + item.m_value = i + 1; + items.push_back(item); + } + node->CreateValueList(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_DoorLock::System_Config_Mode, "Timeout Mode", "", false, false, 1, items, 0, 0); + } + node->CreateValueByte(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_DoorLock::System_Config_OutsideHandles, "Outside Handle Control", "", false, false, 0x0F, 0); + node->CreateValueByte(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_DoorLock::System_Config_InsideHandles, "Inside Handle Control", "", false, false, 0x0F, 0); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/DoorLock.h b/cpp/src/command_classes/DoorLock.h index eda5073b6d..70f26aae57 100644 --- a/cpp/src/command_classes/DoorLock.h +++ b/cpp/src/command_classes/DoorLock.h @@ -32,36 +32,57 @@ namespace OpenZWave { - class ValueBool; - - /** \brief Implements COMMAND_CLASS_DOOR_LOCK (0x62), a Z-Wave device command class. - * \ingroup CommandClass - */ - class DoorLock: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new DoorLock( _homeId, _nodeId ); } - virtual ~DoorLock(){} + namespace CC + { - static uint8 const StaticGetCommandClassId(){ return 0x62; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_DOOR_LOCK"; } + /** \brief Implements COMMAND_CLASS_DOOR_LOCK (0x62), a Z-Wave device command class. + * \ingroup CommandClass + */ + class DoorLock: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new DoorLock(_homeId, _nodeId); + } + virtual ~DoorLock() + { + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool SetValue( Value const& _value ); - virtual void SetValueBasic( uint8 const _instance, uint8 const _value ); + static uint8 const StaticGetCommandClassId() + { + return 0x62; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_DOOR_LOCK"; + } - protected: - virtual void CreateVars( uint8 const _instance ); + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool SetValue(Internal::VC::Value const& _value) override; + virtual void SetValueBasic(uint8 const _instance, uint8 const _value) override; - private: - DoorLock( uint32 const _homeId, uint8 const _nodeId ); - }; + protected: + virtual void CreateVars(uint8 const _instance) override; + private: + DoorLock(uint32 const _homeId, uint8 const _nodeId); + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/DoorLockLogging.cpp b/cpp/src/command_classes/DoorLockLogging.cpp index f318b3e59f..e6ace768aa 100644 --- a/cpp/src/command_classes/DoorLockLogging.cpp +++ b/cpp/src/command_classes/DoorLockLogging.cpp @@ -40,302 +40,242 @@ #include "tinyxml.h" -using namespace OpenZWave; - -enum DoorLockLoggingCmd -{ - DoorLockLoggingCmd_RecordSupported_Get = 0x01, - DoorLockLoggingCmd_RecordSupported_Report = 0x02, - DoorLockLoggingCmd_Record_Get = 0x03, - DoorLockLoggingCmd_Record_Report = 0x04 -}; - -enum DoorLockEventType -{ - DoorLockEventType_LockCode = 0x01, - DoorLockEventType_UnLockCode = 0x02, - DoorLockEventType_LockButton = 0x03, - DoorLockEventType_UnLockButton = 0x04, - DoorLockEventType_LockCodeOOSchedule = 0x05, - DoorLockEventType_UnLockCodeOOSchedule = 0x06, - DoorLockEventType_IllegalCode = 0x07, - DoorLockEventType_LockManual = 0x08, - DoorLockEventType_UnLockManual = 0x09, - DoorLockEventType_LockAuto = 0x0A, - DoorLockEventType_UnLockAuto = 0x0B, - DoorLockEventType_LockRemoteCode = 0x0C, - DoorLockEventType_UnLockRemoteCode = 0x0D, - DoorLockEventType_LockRemote = 0x0E, - DoorLockEventType_UnLockRemote = 0x0F, - DoorLockEventType_LockRemoteCodeOOSchedule = 0x10, - DoorLockEventType_UnLockRemoteCodeOOSchedule = 0x11, - DoorLockEventType_RemoteIllegalCode = 0x12, - DoorLockEventType_LockManual2 = 0x13, - DoorLockEventType_UnlockManual2 = 0x14, - DoorLockEventType_LockSecured = 0x15, - DoorLockEventType_LockUnsecured = 0x16, - DoorLockEventType_UserCodeAdded = 0x17, - DoorLockEventType_UserCodeDeleted = 0x18, - DoorLockEventType_AllUserCodesDeleted = 0x19, - DoorLockEventType_MasterCodeChanged = 0x1A, - DoorLockEventType_UserCodeChanged = 0x1B, - DoorLockEventType_LockReset = 0x1C, - DoorLockEventType_ConfigurationChanged = 0x1D, - DoorLockEventType_LowBattery = 0x1E, - DoorLockEventType_NewBattery = 0x1F, - DoorLockEventType_Max = 0x20 -}; - -static char const* c_DoorLockEventType[] = +namespace OpenZWave { - "Locked via Access Code", - "Unlocked via Access Code", - "Locked via Lock Button", - "Unlocked via UnLock Button", - "Lock Attempt via Out of Schedule Access Code", - "Unlock Attemp via Out of Schedule Access Code", - "Illegal Access Code Entered", - "Manually Locked", - "Manually UnLocked", - "Auto Locked", - "Auto Unlocked", - "Locked via Remote Out of Schedule Access Code", - "Unlocked via Remote Out of Schedule Access Code", - "Locked via Remote", - "Unlocked via Remote", - "Lock Attempt via Remote Out of Schedule Access Code", - "Unlock Attempt via Remote Out of Schedule Access Code", - "Illegal Remote Access Code", - "Manually Locked (2)", - "Manually Unlocked (2)", - "Lock Secured", - "Lock Unsecured", - "User Code Added", - "User Code Deleted", - "All User Codes Deleted", - "Master Code Changed", - "User Code Changed", - "Lock Reset", - "Configuration Changed", - "Low Battery", - "New Battery Installed", - "Unknown" -}; -/* size = 31 entries */ - -enum ValueIDSystemIndexes -{ - Value_System_Config_MaxRecords = 0x00, /* Max Number of Records the Device can Hold */ - Value_GetRecordNo = 0x01, /* Current Record Number after refresh */ - Value_LogRecord = 0x02 /* Simple String Representation of the Log Record - Tab Delimited Fields */ -}; + namespace Internal + { + namespace CC + { + enum DoorLockLoggingCmd + { + DoorLockLoggingCmd_RecordSupported_Get = 0x01, + DoorLockLoggingCmd_RecordSupported_Report = 0x02, + DoorLockLoggingCmd_Record_Get = 0x03, + DoorLockLoggingCmd_Record_Report = 0x04 + }; + enum DoorLockEventType + { + DoorLockEventType_LockCode = 0x01, + DoorLockEventType_UnLockCode = 0x02, + DoorLockEventType_LockButton = 0x03, + DoorLockEventType_UnLockButton = 0x04, + DoorLockEventType_LockCodeOOSchedule = 0x05, + DoorLockEventType_UnLockCodeOOSchedule = 0x06, + DoorLockEventType_IllegalCode = 0x07, + DoorLockEventType_LockManual = 0x08, + DoorLockEventType_UnLockManual = 0x09, + DoorLockEventType_LockAuto = 0x0A, + DoorLockEventType_UnLockAuto = 0x0B, + DoorLockEventType_LockRemoteCode = 0x0C, + DoorLockEventType_UnLockRemoteCode = 0x0D, + DoorLockEventType_LockRemote = 0x0E, + DoorLockEventType_UnLockRemote = 0x0F, + DoorLockEventType_LockRemoteCodeOOSchedule = 0x10, + DoorLockEventType_UnLockRemoteCodeOOSchedule = 0x11, + DoorLockEventType_RemoteIllegalCode = 0x12, + DoorLockEventType_LockManual2 = 0x13, + DoorLockEventType_UnlockManual2 = 0x14, + DoorLockEventType_LockSecured = 0x15, + DoorLockEventType_LockUnsecured = 0x16, + DoorLockEventType_UserCodeAdded = 0x17, + DoorLockEventType_UserCodeDeleted = 0x18, + DoorLockEventType_AllUserCodesDeleted = 0x19, + DoorLockEventType_MasterCodeChanged = 0x1A, + DoorLockEventType_UserCodeChanged = 0x1B, + DoorLockEventType_LockReset = 0x1C, + DoorLockEventType_ConfigurationChanged = 0x1D, + DoorLockEventType_LowBattery = 0x1E, + DoorLockEventType_NewBattery = 0x1F, + DoorLockEventType_Max = 0x20 + }; + + static char const* c_DoorLockEventType[] = + { "Locked via Access Code", "Unlocked via Access Code", "Locked via Lock Button", "Unlocked via UnLock Button", "Lock Attempt via Out of Schedule Access Code", "Unlock Attempt via Out of Schedule Access Code", "Illegal Access Code Entered", "Manually Locked", "Manually UnLocked", "Auto Locked", "Auto Unlocked", "Locked via Remote Out of Schedule Access Code", "Unlocked via Remote Out of Schedule Access Code", "Locked via Remote", "Unlocked via Remote", + "Lock Attempt via Remote Out of Schedule Access Code", "Unlock Attempt via Remote Out of Schedule Access Code", "Illegal Remote Access Code", "Manually Locked (2)", "Manually Unlocked (2)", "Lock Secured", "Lock Unsecured", "User Code Added", "User Code Deleted", "All User Codes Deleted", "Master Code Changed", "User Code Changed", "Lock Reset", "Configuration Changed", "Low Battery", "New Battery Installed", "Unknown" }; + /* size = 31 entries */ //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -DoorLockLogging::DoorLockLogging -( - uint32 const _homeId, - uint8 const _nodeId -): - CommandClass( _homeId, _nodeId ), - m_CurRecord(0) -{ - m_dom.EnableFlag(STATE_FLAG_DOORLOCKLOG_MAXRECORDS, 0); - SetStaticRequest( StaticRequest_Values ); -} + DoorLockLogging::DoorLockLogging(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId), m_CurRecord(0) + { + m_dom.EnableFlag(STATE_FLAG_DOORLOCKLOG_MAXRECORDS, 0); + SetStaticRequest(StaticRequest_Values); + } //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool DoorLockLogging::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - bool requests = false; - if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) ) - { - requests = RequestValue( _requestFlags, DoorLockLoggingCmd_RecordSupported_Get, _instance, _queue ); - } - - if( _requestFlags & RequestFlag_Dynamic ) - { - requests |= RequestValue( _requestFlags, DoorLockLoggingCmd_Record_Get, _instance, _queue ); - } - - return requests; -} - + bool DoorLockLogging::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + bool requests = false; + if ((_requestFlags & RequestFlag_Static) && HasStaticRequest(StaticRequest_Values)) + { + requests = RequestValue(_requestFlags, DoorLockLoggingCmd_RecordSupported_Get, _instance, _queue); + } + if (_requestFlags & RequestFlag_Dynamic) + { + requests |= RequestValue(_requestFlags, DoorLockLoggingCmd_Record_Get, _instance, _queue); + } + return requests; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool DoorLockLogging::RequestValue -( - uint32 const _requestFlags, - uint16 const _what, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if ( _what == DoorLockLoggingCmd_RecordSupported_Get) { - Msg* msg = new Msg( "DoorLockLoggingCmd_RecordSupported_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( DoorLockLoggingCmd_RecordSupported_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - - } else if (_what == DoorLockLoggingCmd_Record_Get) { - Msg* msg = new Msg( "DoorLockLoggingCmd_Record_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( DoorLockLoggingCmd_Record_Get ); - msg->Append( m_CurRecord ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } - return false; -} + bool DoorLockLogging::RequestValue(uint32 const _requestFlags, uint16 const _what, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_what == DoorLockLoggingCmd_RecordSupported_Get) + { + Msg* msg = new Msg("DoorLockLoggingCmd_RecordSupported_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(DoorLockLoggingCmd_RecordSupported_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else if (_what == DoorLockLoggingCmd_Record_Get) + { + Msg* msg = new Msg("DoorLockLoggingCmd_Record_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(DoorLockLoggingCmd_Record_Get); + msg->Append(m_CurRecord); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool DoorLockLogging::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - - if( DoorLockLoggingCmd_RecordSupported_Report == (DoorLockLoggingCmd)_data[0] ) - { - Log::Write( LogLevel_Info, GetNodeId(), "Received DoorLockLoggingCmd_RecordSupported_Report: Max Records is %d ", _data[1]); - m_dom.SetFlagByte(STATE_FLAG_DOORLOCKLOG_MAXRECORDS, _data[1]); - if( ValueByte* value = static_cast( GetValue( _instance, Value_System_Config_MaxRecords ) ) ) - { - - value->OnValueRefreshed( _data[1] ); - value->Release(); - } - ClearStaticRequest( StaticRequest_Values ); - return true; - } else if (DoorLockLoggingCmd_Record_Report == (DoorLockLoggingCmd)_data[0] ) - { - uint8 EventType = _data[9]; - if (EventType >= DoorLockEventType_Max) - EventType = DoorLockEventType_Max; - - Log::Write (LogLevel_Info, GetNodeId(), "Received a DoorLockLogging Record %d which is \"%s\"", _data[1], c_DoorLockEventType[EventType-1]); - - if( ValueByte* value = static_cast( GetValue( _instance, Value_GetRecordNo ) ) ) - { - value->OnValueRefreshed( _data[1]); - value->Release(); - } - if( ValueString* value = static_cast( GetValue( _instance, Value_LogRecord ) ) ) - { - char msg[512]; - uint16 year = (_data[2] << 8) + (_data[3] & 0xFF); - uint8 month = (_data[4] & 0x0F); - uint8 day = (_data[5] & 0x1F); - uint8 hour = (_data[6] & 0x1F); - uint8 minute = (_data[7] & 0x3F); - uint8 second = (_data[8] & 0x3F); - bool valid = false; - if (((_data[6] & 0xE0) >> 5) > 0) + bool DoorLockLogging::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) { - valid = true; - } - uint8 userid = (_data[10]); - uint8 usercodelength = (_data[11]); - char usercode[254], tmpusercode[10]; - snprintf(usercode, sizeof(usercode), "UserCode:"); - if (usercodelength > 0) - for (int i = 0; i < usercodelength; i++ ) + + if (DoorLockLoggingCmd_RecordSupported_Report == (DoorLockLoggingCmd) _data[0]) { - snprintf(tmpusercode, sizeof(tmpusercode), "%d", (int)_data[12+i]); - strncat(usercode, tmpusercode, 10); + Log::Write(LogLevel_Info, GetNodeId(), "Received DoorLockLoggingCmd_RecordSupported_Report: Max Records is %d ", _data[1]); + m_dom.SetFlagByte(STATE_FLAG_DOORLOCKLOG_MAXRECORDS, _data[1]); + if (Internal::VC::ValueByte* value = static_cast(GetValue(_instance, ValueID_Index_DoorLockLogging::System_Config_MaxRecords))) + { + + value->OnValueRefreshed(_data[1]); + value->Release(); + } + ClearStaticRequest(StaticRequest_Values); + return true; } + else if (DoorLockLoggingCmd_Record_Report == (DoorLockLoggingCmd) _data[0]) + { + uint8 EventType = _data[9]; + if (EventType >= DoorLockEventType_Max) + EventType = DoorLockEventType_Max; + + Log::Write(LogLevel_Info, GetNodeId(), "Received a DoorLockLogging Record %d which is \"%s\"", _data[1], c_DoorLockEventType[EventType - 1]); + + if (Internal::VC::ValueByte* value = static_cast(GetValue(_instance, ValueID_Index_DoorLockLogging::GetRecordNo))) + { + value->OnValueRefreshed(_data[1]); + value->Release(); + } + if (Internal::VC::ValueString* value = static_cast(GetValue(_instance, ValueID_Index_DoorLockLogging::LogRecord))) + { + char msg[512]; + uint16 year = (_data[2] << 8) + (_data[3] & 0xFF); + uint8 month = (_data[4] & 0x0F); + uint8 day = (_data[5] & 0x1F); + uint8 hour = (_data[6] & 0x1F); + uint8 minute = (_data[7] & 0x3F); + uint8 second = (_data[8] & 0x3F); + bool valid = false; + if (((_data[6] & 0xE0) >> 5) > 0) + { + valid = true; + } + uint8 userid = (_data[10]); + uint8 usercodelength = (_data[11]); + char usercode[254], tmpusercode[10]; + snprintf(usercode, sizeof(usercode), "UserCode:"); + if (usercodelength > 0) + for (int i = 0; i < usercodelength; i++) + { + snprintf(tmpusercode, sizeof(tmpusercode), "%d", (int) _data[12 + i]); + strncat(usercode, tmpusercode, 10); + } + + if (valid) + { + snprintf(msg, sizeof(msg), "%02d/%02d/%02d %02d:%02d:%02d \tMessage: %s \tUserID: %d \t%s", (int) day, (int) month, (int) year, (int) hour, (int) minute, (int) second, c_DoorLockEventType[EventType], (int) userid, usercode); + } + else + snprintf(msg, sizeof(msg), "Invalid Record"); + value->OnValueRefreshed(msg); + value->Release(); + } + return true; - if (valid) { - snprintf(msg, sizeof(msg), "%02d/%02d/%02d %02d:%02d:%02d \tMessage: %s \tUserID: %d \t%s", (int)day, (int)month, (int)year, (int)hour, (int)minute, (int)second, c_DoorLockEventType[EventType], (int)userid, usercode); - } else - snprintf(msg, sizeof(msg), "Invalid Record"); - value->OnValueRefreshed(msg); - value->Release(); - } - return true; - - } - return false; -} + } + return false; + } //----------------------------------------------------------------------------- // // Set the lock's state //----------------------------------------------------------------------------- -bool DoorLockLogging::SetValue -( - Value const& _value -) -{ - if( (Value_GetRecordNo == _value.GetID().GetIndex()) && ValueID::ValueType_Byte == _value.GetID().GetType() ) - { - ValueByte const* value = static_cast(&_value); - - Log::Write( LogLevel_Info, GetNodeId(), "DoorLockLoggingCmd_Record_Get - Requesting Log Record %d", value->GetValue() ); - Msg* msg = new Msg( "DoorLockLoggingCmd_Record_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _value.GetID().GetInstance() ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( DoorLockLoggingCmd_Record_Get ); - msg->Append( value->GetValue() ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - m_CurRecord = value->GetValue(); - return true; - } - return false; -} - - + bool DoorLockLogging::SetValue(Internal::VC::Value const& _value) + { + if ((ValueID_Index_DoorLockLogging::GetRecordNo == _value.GetID().GetIndex()) && ValueID::ValueType_Byte == _value.GetID().GetType()) + { + Internal::VC::ValueByte const* value = static_cast(&_value); + + Log::Write(LogLevel_Info, GetNodeId(), "DoorLockLoggingCmd_Record_Get - Requesting Log Record %d", value->GetValue()); + Msg* msg = new Msg("DoorLockLoggingCmd_Record_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _value.GetID().GetInstance()); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(DoorLockLoggingCmd_Record_Get); + msg->Append(value->GetValue()); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + m_CurRecord = value->GetValue(); + return true; + } + return false; + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void DoorLockLogging::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - node->CreateValueByte( ValueID::ValueGenre_System, GetCommandClassId(), _instance, Value_System_Config_MaxRecords, "Max Number of Records", "", true, false, 0x0, 0 ); - node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, Value_GetRecordNo, "Current Record Number", "", false, false, 0x0, 0 ); - node->CreateValueString( ValueID::ValueGenre_User, GetCommandClassId(), _instance, Value_LogRecord, "Log Record", "", true, false, "", 0 ); - } -} - + void DoorLockLogging::CreateVars(uint8 const _instance) + { + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueByte(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_DoorLockLogging::System_Config_MaxRecords, "Max Number of Records", "", true, false, 0x0, 0); + node->CreateValueByte(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_DoorLockLogging::GetRecordNo, "Current Record Number", "", false, false, 0x0, 0); + node->CreateValueString(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_DoorLockLogging::LogRecord, "Log Record", "", true, false, "", 0); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/DoorLockLogging.h b/cpp/src/command_classes/DoorLockLogging.h index 149c574315..5d3340f101 100644 --- a/cpp/src/command_classes/DoorLockLogging.h +++ b/cpp/src/command_classes/DoorLockLogging.h @@ -32,35 +32,56 @@ namespace OpenZWave { - class ValueBool; - - /** \brief Implements COMMAND_CLASS_DOOR_LOCK_LOGGING (0x4C), a Z-Wave device command class. - * \ingroup CommandClass - */ - class DoorLockLogging: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new DoorLockLogging( _homeId, _nodeId ); } - virtual ~DoorLockLogging(){} + namespace CC + { - static uint8 const StaticGetCommandClassId(){ return 0x4c; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_DOOR_LOCK_LOGGING"; } + /** \brief Implements COMMAND_CLASS_DOOR_LOCK_LOGGING (0x4C), a Z-Wave device command class. + * \ingroup CommandClass + */ + class DoorLockLogging: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new DoorLockLogging(_homeId, _nodeId); + } + virtual ~DoorLockLogging() + { + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool SetValue( Value const& _value ); - protected: - virtual void CreateVars( uint8 const _instance ); + static uint8 const StaticGetCommandClassId() + { + return 0x4c; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_DOOR_LOCK_LOGGING"; + } - private: - DoorLockLogging( uint32 const _homeId, uint8 const _nodeId ); - uint8 m_CurRecord; - }; + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool SetValue(Internal::VC::Value const& _value) override; + protected: + virtual void CreateVars(uint8 const _instance) override; + private: + DoorLockLogging(uint32 const _homeId, uint8 const _nodeId); + uint8 m_CurRecord; + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/EnergyProduction.cpp b/cpp/src/command_classes/EnergyProduction.cpp index 11ffd81f51..d6fff20024 100644 --- a/cpp/src/command_classes/EnergyProduction.cpp +++ b/cpp/src/command_classes/EnergyProduction.cpp @@ -35,146 +35,124 @@ #include "value_classes/ValueDecimal.h" -using namespace OpenZWave; - -enum EnergyProductionCmd +namespace OpenZWave { - EnergyProductionCmd_Get = 0x02, - EnergyProductionCmd_Report = 0x03 -}; + namespace Internal + { + namespace CC + { -enum -{ - EnergyProductionIndex_Instant = 0, - EnergyProductionIndex_Total, - EnergyProductionIndex_Today, - EnergyProductionIndex_Time -}; + enum EnergyProductionCmd + { + EnergyProductionCmd_Get = 0x02, + EnergyProductionCmd_Report = 0x03 + }; -static char const* c_energyParameterNames[] = -{ - "Instant energy production", - "Total energy production", - "Energy production today", - "Total production time" -}; + static char const* c_energyParameterNames[] = + { "Instant energy production", "Total energy production", "Energy production today", "Total production time" }; //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool EnergyProduction::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - bool request = false; - if( _requestFlags & RequestFlag_Dynamic ) - { - // Request each of the production values - request |= RequestValue( _requestFlags, EnergyProductionIndex_Instant, _instance, _queue ); - request |= RequestValue( _requestFlags, EnergyProductionIndex_Total, _instance, _queue ); - request |= RequestValue( _requestFlags, EnergyProductionIndex_Today, _instance, _queue ); - request |= RequestValue( _requestFlags, EnergyProductionIndex_Time, _instance, _queue ); - } - - return request; -} + bool EnergyProduction::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + bool request = false; + if (_requestFlags & RequestFlag_Dynamic) + { + // Request each of the production values + request |= RequestValue(_requestFlags, ValueID_Index_EnergyProduction::Instant, _instance, _queue); + request |= RequestValue(_requestFlags, ValueID_Index_EnergyProduction::Total, _instance, _queue); + request |= RequestValue(_requestFlags, ValueID_Index_EnergyProduction::Today, _instance, _queue); + request |= RequestValue(_requestFlags, ValueID_Index_EnergyProduction::Time, _instance, _queue); + } + + return request; + } //----------------------------------------------------------------------------- // // Request current production from the device //----------------------------------------------------------------------------- -bool EnergyProduction::RequestValue -( - uint32 const _requestFlags, - uint16 const _valueEnum, // one of EnergyProductionIndex enums - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if (_valueEnum > EnergyProductionIndex_Time) - { - Log::Write (LogLevel_Warning, GetNodeId(), "RequestValue _valueEnum was greater than range. Dropping"); - return false; - } - - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Log::Write( LogLevel_Info, GetNodeId(), "Requesting the %s value", c_energyParameterNames[_valueEnum] ); - Msg* msg = new Msg( "EnergyProductionCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( EnergyProductionCmd_Get ); - msg->Append( (_valueEnum & 0xFF) ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "EnergyProductionCmd_Get Not Supported on this node"); - } - return false; -} + bool EnergyProduction::RequestValue(uint32 const _requestFlags, uint16 const _valueEnum, // one of EnergyProductionIndex enums + uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_valueEnum > ValueID_Index_EnergyProduction::Time) + { + Log::Write(LogLevel_Warning, GetNodeId(), "RequestValue _valueEnum was greater than range. Dropping"); + return false; + } + + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Log::Write(LogLevel_Info, GetNodeId(), "Requesting the %s value", c_energyParameterNames[_valueEnum]); + Msg* msg = new Msg("EnergyProductionCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(EnergyProductionCmd_Get); + msg->Append((_valueEnum & 0xFF)); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "EnergyProductionCmd_Get Not Supported on this node"); + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool EnergyProduction::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if (EnergyProductionCmd_Report == (EnergyProductionCmd)_data[0]) - { - uint8 scale; - uint8 precision = 0; - string value = ExtractValue( &_data[2], &scale, &precision ); - uint8 paramType = _data[1]; - if (paramType > 4) /* size of c_energyParameterNames minus Invalid Entry*/ - { - Log::Write (LogLevel_Warning, GetNodeId(), "paramType Value was greater than range. Dropping Message"); - return false; - } - - Log::Write( LogLevel_Info, GetNodeId(), "Received an Energy production report: %s = %s", c_energyParameterNames[_data[1]], value.c_str() ); - if( ValueDecimal* decimalValue = static_cast( GetValue( _instance, _data[1] ) ) ) - { - decimalValue->OnValueRefreshed( value ); - if( decimalValue->GetPrecision() != precision ) + bool EnergyProduction::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) { - decimalValue->SetPrecision( precision ); + if (EnergyProductionCmd_Report == (EnergyProductionCmd) _data[0]) + { + uint8 scale; + uint8 precision = 0; + string value = ExtractValue(&_data[2], &scale, &precision); + uint8 paramType = _data[1]; + if (paramType > 4) /* size of c_energyParameterNames minus Invalid Entry*/ + { + Log::Write(LogLevel_Warning, GetNodeId(), "paramType Value was greater than range. Dropping Message"); + return false; + } + + Log::Write(LogLevel_Info, GetNodeId(), "Received an Energy production report: %s = %s", c_energyParameterNames[_data[1]], value.c_str()); + if (Internal::VC::ValueDecimal* decimalValue = static_cast(GetValue(_instance, _data[1]))) + { + decimalValue->OnValueRefreshed(value); + if (decimalValue->GetPrecision() != precision) + { + decimalValue->SetPrecision(precision); + } + decimalValue->Release(); + } + return true; + } + + return false; } - decimalValue->Release(); - } - return true; - } - - return false; -} //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void EnergyProduction::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, (uint8)EnergyProductionIndex_Instant, c_energyParameterNames[EnergyProductionIndex_Instant], "W", true, false, "0.0", 0 ); - node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, (uint8)EnergyProductionIndex_Total, c_energyParameterNames[EnergyProductionIndex_Total], "kWh", true, false, "0.0", 0 ); - node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, (uint8)EnergyProductionIndex_Today, c_energyParameterNames[EnergyProductionIndex_Today], "kWh", true, false, "0.0", 0 ); - node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, (uint8)EnergyProductionIndex_Time, c_energyParameterNames[EnergyProductionIndex_Time], "", true, false, "0.0", 0 ); - } -} - - + void EnergyProduction::CreateVars(uint8 const _instance) + { + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueDecimal(ValueID::ValueGenre_User, GetCommandClassId(), _instance, (uint8) ValueID_Index_EnergyProduction::Instant, c_energyParameterNames[ValueID_Index_EnergyProduction::Instant], "W", true, false, "0.0", 0); + node->CreateValueDecimal(ValueID::ValueGenre_User, GetCommandClassId(), _instance, (uint8) ValueID_Index_EnergyProduction::Total, c_energyParameterNames[ValueID_Index_EnergyProduction::Total], "kWh", true, false, "0.0", 0); + node->CreateValueDecimal(ValueID::ValueGenre_User, GetCommandClassId(), _instance, (uint8) ValueID_Index_EnergyProduction::Today, c_energyParameterNames[ValueID_Index_EnergyProduction::Today], "kWh", true, false, "0.0", 0); + node->CreateValueDecimal(ValueID::ValueGenre_User, GetCommandClassId(), _instance, (uint8) ValueID_Index_EnergyProduction::Time, c_energyParameterNames[ValueID_Index_EnergyProduction::Time], "", true, false, "0.0", 0); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/EnergyProduction.h b/cpp/src/command_classes/EnergyProduction.h index fe65712946..62a77e575f 100644 --- a/cpp/src/command_classes/EnergyProduction.h +++ b/cpp/src/command_classes/EnergyProduction.h @@ -32,34 +32,58 @@ namespace OpenZWave { - class ValueDecimal; - - /** \brief Implements COMMAND_CLASS_ENERGY_PRODUCTION (0x90), a Z-Wave device command class. - * \ingroup CommandClass - */ - class EnergyProduction: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new EnergyProduction( _homeId, _nodeId ); } - virtual ~EnergyProduction(){} + namespace CC + { - static uint8 const StaticGetCommandClassId(){ return 0x90; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_ENERGY_PRODUCTION"; } + /** \brief Implements COMMAND_CLASS_ENERGY_PRODUCTION (0x90), a Z-Wave device command class. + * \ingroup CommandClass + */ + class EnergyProduction: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new EnergyProduction(_homeId, _nodeId); + } + virtual ~EnergyProduction() + { + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _valueEnum, uint8 const _dummy, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); + static uint8 const StaticGetCommandClassId() + { + return 0x90; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_ENERGY_PRODUCTION"; + } - protected: - virtual void CreateVars( uint8 const _instance ); + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _valueEnum, uint8 const _dummy, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; - private: - EnergyProduction( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} - }; + protected: + virtual void CreateVars(uint8 const _instance) override; + private: + EnergyProduction(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + } + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/Hail.cpp b/cpp/src/command_classes/Hail.cpp index a611196b06..927d01a38c 100644 --- a/cpp/src/command_classes/Hail.cpp +++ b/cpp/src/command_classes/Hail.cpp @@ -33,36 +33,39 @@ #include "Driver.h" #include "platform/Log.h" -using namespace OpenZWave; - -enum HailCmdEnum +namespace OpenZWave { - HailCmd_Hail = 1 -}; + namespace Internal + { + namespace CC + { + enum HailCmdEnum + { + HailCmd_Hail = 1 + }; //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool Hail::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if( HailCmd_Hail == _data[0] ) - { - // We have received a hail from the Z-Wave device. - // Request an update of the dynamic values. - Log::Write( LogLevel_Info, GetNodeId(), "Received Hail command from node %d", GetNodeId() ); - if( Node* node = GetNodeUnsafe() ) - { - node->RequestDynamicValues(); - } - return true; - } - return false; -} + bool Hail::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) + { + if (HailCmd_Hail == _data[0]) + { + // We have received a hail from the Z-Wave device. + // Request an update of the dynamic values. + Log::Write(LogLevel_Info, GetNodeId(), "Received Hail command from node %d", GetNodeId()); + if (Node* node = GetNodeUnsafe()) + { + node->RequestDynamicValues(); + } + return true; + } + return false; + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/Hail.h b/cpp/src/command_classes/Hail.h index 3c1959e1bd..320102fd5c 100644 --- a/cpp/src/command_classes/Hail.h +++ b/cpp/src/command_classes/Hail.h @@ -32,27 +32,53 @@ namespace OpenZWave { - /** \brief Implements COMMAND_CLASS_HAIL (0x82), a Z-Wave device command class. - * \ingroup CommandClass - */ - class Hail: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Hail( _homeId, _nodeId ); } - virtual ~Hail(){} + namespace CC + { - static uint8 const StaticGetCommandClassId(){ return 0x82; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_HAIL"; } + /** \brief Implements COMMAND_CLASS_HAIL (0x82), a Z-Wave device command class. + * \ingroup CommandClass + */ + class Hail: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new Hail(_homeId, _nodeId); + } + virtual ~Hail() + { + } - // From CommandClass - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); + static uint8 const StaticGetCommandClassId() + { + return 0x82; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_HAIL"; + } - private: - Hail( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} - }; + // From CommandClass + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + private: + Hail(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + } + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/Indicator.cpp b/cpp/src/command_classes/Indicator.cpp index d1620a97f6..32b646ab5a 100644 --- a/cpp/src/command_classes/Indicator.cpp +++ b/cpp/src/command_classes/Indicator.cpp @@ -35,130 +35,119 @@ #include "value_classes/ValueByte.h" -using namespace OpenZWave; - -enum IndicatorCmd +namespace OpenZWave { - IndicatorCmd_Set = 0x01, - IndicatorCmd_Get = 0x02, - IndicatorCmd_Report = 0x03 -}; + namespace Internal + { + namespace CC + { + + enum IndicatorCmd + { + IndicatorCmd_Set = 0x01, + IndicatorCmd_Get = 0x02, + IndicatorCmd_Report = 0x03 + }; //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool Indicator::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _requestFlags & RequestFlag_Dynamic ) - { - return RequestValue( _requestFlags, 0, _instance, _queue ); - } + bool Indicator::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_requestFlags & RequestFlag_Dynamic) + { + return RequestValue(_requestFlags, 0, _instance, _queue); + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool Indicator::RequestValue -( - uint32 const _requestFlags, - uint16 const _dummy1, // = 0 (not used) - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Msg* msg = new Msg( "IndicatorCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( IndicatorCmd_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "IndicatorCmd_Get Not Supported on this node"); - } - return false; -} - + bool Indicator::RequestValue(uint32 const _requestFlags, uint16 const _dummy1, // = 0 (not used) + uint8 const _instance, Driver::MsgQueue const _queue) + { + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Msg* msg = new Msg("IndicatorCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(IndicatorCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "IndicatorCmd_Get Not Supported on this node"); + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool Indicator::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if( IndicatorCmd_Report == (IndicatorCmd)_data[0] ) - { - Log::Write( LogLevel_Info, GetNodeId(), "Received an Indicator report: Indicator=%d", _data[1] ); + bool Indicator::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) + { + if (IndicatorCmd_Report == (IndicatorCmd) _data[0]) + { + Log::Write(LogLevel_Info, GetNodeId(), "Received an Indicator report: Indicator=%d", _data[1]); - if( ValueByte* value = static_cast( GetValue( _instance, 0 ) ) ) - { - value->OnValueRefreshed( _data[1] ); - value->Release(); - } - return true; - } + if (Internal::VC::ValueByte* value = static_cast(GetValue(_instance, ValueID_Index_Indicator::Indicator))) + { + value->OnValueRefreshed(_data[1]); + value->Release(); + } + return true; + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Set the device's indicator value //----------------------------------------------------------------------------- -bool Indicator::SetValue -( - Value const& _value -) -{ - if( ValueID::ValueType_Byte == _value.GetID().GetType() ) - { - ValueByte const* value = static_cast(&_value); + bool Indicator::SetValue(Internal::VC::Value const& _value) + { + if (ValueID::ValueType_Byte == _value.GetID().GetType()) + { + Internal::VC::ValueByte const* value = static_cast(&_value); - Log::Write( LogLevel_Info, GetNodeId(), "Indicator::SetValue - Setting indicator to %d", value->GetValue()); - Msg* msg = new Msg( "IndicatorCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->SetInstance( this, _value.GetID().GetInstance() ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( IndicatorCmd_Set ); - msg->Append( value->GetValue() ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - return true; - } + Log::Write(LogLevel_Info, GetNodeId(), "Indicator::SetValue - Setting indicator to %d", value->GetValue()); + Msg* msg = new Msg("IndicatorCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->SetInstance(this, _value.GetID().GetInstance()); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(IndicatorCmd_Set); + msg->Append(value->GetValue()); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return true; + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void Indicator::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, "Indicator", "", false, false, false, 0 ); - } -} + void Indicator::CreateVars(uint8 const _instance) + { + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueByte(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_Indicator::Indicator, "Indicator", "", false, false, false, 0); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/Indicator.h b/cpp/src/command_classes/Indicator.h index f5b049d9d9..1dcb1d4ba0 100644 --- a/cpp/src/command_classes/Indicator.h +++ b/cpp/src/command_classes/Indicator.h @@ -32,35 +32,59 @@ namespace OpenZWave { - class ValueByte; - - /** \brief Implements COMMAND_CLASS_INDICATOR (0x87), a Z-Wave device command class. - * \ingroup CommandClass - */ - class Indicator: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Indicator( _homeId, _nodeId ); } - virtual ~Indicator(){} + namespace CC + { - static uint8 const StaticGetCommandClassId(){ return 0x87; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_INDICATOR"; } + /** \brief Implements COMMAND_CLASS_INDICATOR (0x87), a Z-Wave device command class. + * \ingroup CommandClass + */ + class Indicator: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new Indicator(_homeId, _nodeId); + } + virtual ~Indicator() + { + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool SetValue( Value const& _value ); + static uint8 const StaticGetCommandClassId() + { + return 0x87; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_INDICATOR"; + } - protected: - virtual void CreateVars( uint8 const _instance ); + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool SetValue(Internal::VC::Value const& _value) override; - private: - Indicator( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} - }; + protected: + virtual void CreateVars(uint8 const _instance) override; + private: + Indicator(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + } + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/Language.cpp b/cpp/src/command_classes/Language.cpp index 06d04b003f..1582a06489 100644 --- a/cpp/src/command_classes/Language.cpp +++ b/cpp/src/command_classes/Language.cpp @@ -35,130 +35,117 @@ #include "value_classes/ValueString.h" -using namespace OpenZWave; - -enum LanguageCmd +namespace OpenZWave { - LanguageCmd_Set = 0x01, - LanguageCmd_Get = 0x02, - LanguageCmd_Report = 0x03 -}; + namespace Internal + { + namespace CC + { -enum -{ - LanguageIndex_Language = 0, - LanguageIndex_Country -}; + enum LanguageCmd + { + LanguageCmd_Set = 0x01, + LanguageCmd_Get = 0x02, + LanguageCmd_Report = 0x03 + }; //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool Language::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) ) - { - return RequestValue( _requestFlags, 0, _instance, _queue ); - } + bool Language::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + if ((_requestFlags & RequestFlag_Static) && HasStaticRequest(StaticRequest_Values)) + { + return RequestValue(_requestFlags, 0, _instance, _queue); + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool Language::RequestValue -( - uint32 const _requestFlags, - uint16 const _dummy1, // = 0 (not used) - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _instance != 1 ) - { - // This command class doesn't work with multiple instances - return false; - } - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Msg* msg = new Msg( "LanguageCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( LanguageCmd_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "LanguageCmd_Get Not Supported on this node"); - } - return false; -} + bool Language::RequestValue(uint32 const _requestFlags, uint16 const _dummy1, // = 0 (not used) + uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_instance != 1) + { + // This command class doesn't work with multiple instances + return false; + } + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Msg* msg = new Msg("LanguageCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(LanguageCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "LanguageCmd_Get Not Supported on this node"); + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool Language::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if( LanguageCmd_Report == (LanguageCmd)_data[0] ) - { - char language[4]; - char country[3]; - - language[0] = _data[1]; - language[1] = _data[2]; - language[2] = _data[3]; - language[3] = 0; - - country[0] = _data[4]; - country[1] = _data[5]; - country[2] = 0; - - Log::Write( LogLevel_Info, GetNodeId(), "Received Language report: Language=%s, Country=%s", language, country ); - ClearStaticRequest( StaticRequest_Values ); - - if( ValueString* languageValue = static_cast( GetValue( _instance, LanguageIndex_Language ) ) ) - { - languageValue->OnValueRefreshed( language ); - languageValue->Release(); - } - if( ValueString* countryValue = static_cast( GetValue( _instance, LanguageIndex_Country ) ) ) - { - countryValue->OnValueRefreshed( country ); - countryValue->Release(); - } - return true; - } - - return false; -} + bool Language::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) + { + if (LanguageCmd_Report == (LanguageCmd) _data[0]) + { + char language[4]; + char country[3]; + + language[0] = _data[1]; + language[1] = _data[2]; + language[2] = _data[3]; + language[3] = 0; + + country[0] = _data[4]; + country[1] = _data[5]; + country[2] = 0; + + Log::Write(LogLevel_Info, GetNodeId(), "Received Language report: Language=%s, Country=%s", language, country); + ClearStaticRequest(StaticRequest_Values); + + if (Internal::VC::ValueString* languageValue = static_cast(GetValue(_instance, ValueID_Index_Language::Language))) + { + languageValue->OnValueRefreshed(language); + languageValue->Release(); + } + if (Internal::VC::ValueString* countryValue = static_cast(GetValue(_instance, ValueID_Index_Language::Country))) + { + countryValue->OnValueRefreshed(country); + countryValue->Release(); + } + return true; + } + + return false; + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void Language::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - node->CreateValueString( ValueID::ValueGenre_System, GetCommandClassId(), _instance, (uint8)LanguageIndex_Language, "Language", "", false, false, "", 0 ); - node->CreateValueString( ValueID::ValueGenre_System, GetCommandClassId(), _instance, (uint8)LanguageIndex_Country, "Country", "", false, false, "", 0 ); - } -} + void Language::CreateVars(uint8 const _instance) + { + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueString(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_Language::Language, "Language", "", false, false, "", 0); + node->CreateValueString(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_Language::Country, "Country", "", false, false, "", 0); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/Language.h b/cpp/src/command_classes/Language.h index d593d0bbbd..75f09afa8e 100644 --- a/cpp/src/command_classes/Language.h +++ b/cpp/src/command_classes/Language.h @@ -32,34 +32,59 @@ namespace OpenZWave { - class ValueString; - - /** \brief Implements COMMAND_CLASS_LANGUAGE (0x89), a Z-Wave device command class. - * \ingroup CommandClass - */ - class Language: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Language( _homeId, _nodeId ); } - virtual ~Language(){} + namespace CC + { - static uint8 const StaticGetCommandClassId(){ return 0x89; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_LANGUAGE"; } + /** \brief Implements COMMAND_CLASS_LANGUAGE (0x89), a Z-Wave device command class. + * \ingroup CommandClass + */ + class Language: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new Language(_homeId, _nodeId); + } + virtual ~Language() + { + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); + static uint8 const StaticGetCommandClassId() + { + return 0x89; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_LANGUAGE"; + } - protected: - virtual void CreateVars( uint8 const _instance ); + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; - private: - Language( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){ SetStaticRequest( StaticRequest_Values ); } - }; + protected: + virtual void CreateVars(uint8 const _instance) override; + private: + Language(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + SetStaticRequest(StaticRequest_Values); + } + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/Lock.cpp b/cpp/src/command_classes/Lock.cpp index d5d51de2a6..afa100f971 100644 --- a/cpp/src/command_classes/Lock.cpp +++ b/cpp/src/command_classes/Lock.cpp @@ -35,132 +35,120 @@ #include "value_classes/ValueBool.h" -using namespace OpenZWave; - -enum LockCmd +namespace OpenZWave { - LockCmd_Set = 0x01, - LockCmd_Get = 0x02, - LockCmd_Report = 0x03 -}; + namespace Internal + { + namespace CC + { + + enum LockCmd + { + LockCmd_Set = 0x01, + LockCmd_Get = 0x02, + LockCmd_Report = 0x03 + }; //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool Lock::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _requestFlags & RequestFlag_Dynamic ) - { - return RequestValue( _requestFlags, 0, _instance, _queue ); - } + bool Lock::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_requestFlags & RequestFlag_Dynamic) + { + return RequestValue(_requestFlags, 0, _instance, _queue); + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool Lock::RequestValue -( - uint32 const _requestFlags, - uint16 const _dummy1, // = 0 (not used) - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Msg* msg = new Msg( "LockCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( LockCmd_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "LockCmd_Get Not Supported on this node"); - } - return false; -} - + bool Lock::RequestValue(uint32 const _requestFlags, uint16 const _dummy1, // = 0 (not used) + uint8 const _instance, Driver::MsgQueue const _queue) + { + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Msg* msg = new Msg("LockCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(LockCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "LockCmd_Get Not Supported on this node"); + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool Lock::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if( LockCmd_Report == (LockCmd)_data[0] ) - { - Log::Write( LogLevel_Info, GetNodeId(), "Received Lock report: Lock is %s", _data[1] ? "Locked" : "Unlocked" ); - - if( ValueBool* value = static_cast( GetValue( _instance, 0 ) ) ) - { - value->OnValueRefreshed( _data[1] != 0 ); - value->Release(); - } - return true; - } - - return false; -} + bool Lock::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) + { + if (LockCmd_Report == (LockCmd) _data[0]) + { + Log::Write(LogLevel_Info, GetNodeId(), "Received Lock report: Lock is %s", _data[1] ? "Locked" : "Unlocked"); + + if (Internal::VC::ValueBool* value = static_cast(GetValue(_instance, ValueID_Index_Lock::Locked))) + { + value->OnValueRefreshed(_data[1] != 0); + value->Release(); + } + return true; + } + + return false; + } //----------------------------------------------------------------------------- // // Set the lock's state //----------------------------------------------------------------------------- -bool Lock::SetValue -( - Value const& _value -) -{ - if( ValueID::ValueType_Bool == _value.GetID().GetType() ) - { - ValueBool const* value = static_cast(&_value); - - Log::Write( LogLevel_Info, GetNodeId(), "Lock::Set - Requesting lock to be %s", value->GetValue() ? "Locked" : "Unlocked" ); - Msg* msg = new Msg( "LockCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->SetInstance( this, _value.GetID().GetInstance() ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( LockCmd_Set ); - msg->Append( value->GetValue() ? 0x01:0x00 ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - return true; - } - - return false; -} + bool Lock::SetValue(Internal::VC::Value const& _value) + { + if (ValueID::ValueType_Bool == _value.GetID().GetType()) + { + Internal::VC::ValueBool const* value = static_cast(&_value); + + Log::Write(LogLevel_Info, GetNodeId(), "Lock::Set - Requesting lock to be %s", value->GetValue() ? "Locked" : "Unlocked"); + Msg* msg = new Msg("LockCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->SetInstance(this, _value.GetID().GetInstance()); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(LockCmd_Set); + msg->Append(value->GetValue() ? 0x01 : 0x00); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return true; + } + + return false; + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void Lock::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - node->CreateValueBool( ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, "Locked", "", false, false, false, 0 ); - } -} - + void Lock::CreateVars(uint8 const _instance) + { + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueBool(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_Lock::Locked, "Locked", "", false, false, false, 0); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/Lock.h b/cpp/src/command_classes/Lock.h index 2249968c78..b50d9a8806 100644 --- a/cpp/src/command_classes/Lock.h +++ b/cpp/src/command_classes/Lock.h @@ -32,35 +32,59 @@ namespace OpenZWave { - class ValueBool; - - /** \brief Implements COMMAND_CLASS_LOCK (0x76), a Z-Wave device command class. - * \ingroup CommandClass - */ - class Lock: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Lock( _homeId, _nodeId ); } - virtual ~Lock(){} + namespace CC + { - static uint8 const StaticGetCommandClassId(){ return 0x76; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_LOCK"; } + /** \brief Implements COMMAND_CLASS_LOCK (0x76), a Z-Wave device command class. + * \ingroup CommandClass + */ + class Lock: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new Lock(_homeId, _nodeId); + } + virtual ~Lock() + { + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool SetValue( Value const& _value ); + static uint8 const StaticGetCommandClassId() + { + return 0x76; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_LOCK"; + } - protected: - virtual void CreateVars( uint8 const _instance ); + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool SetValue(Internal::VC::Value const& _value) override; - private: - Lock( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} - }; + protected: + virtual void CreateVars(uint8 const _instance) override; + private: + Lock(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + } + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/ManufacturerProprietary.cpp b/cpp/src/command_classes/ManufacturerProprietary.cpp index bfe9364e45..4cb0cd9bf5 100644 --- a/cpp/src/command_classes/ManufacturerProprietary.cpp +++ b/cpp/src/command_classes/ManufacturerProprietary.cpp @@ -34,145 +34,139 @@ #include "value_classes/ValueByte.h" -using namespace OpenZWave; - +namespace OpenZWave +{ + namespace Internal + { + namespace CC + { -const uint8 MANUFACTURER_ID_FIBARO[2] = { 0x01, 0x0f }; + const uint8 MANUFACTURER_ID_FIBARO[2] = + { 0x01, 0x0f }; //manufacturer proprietary message identifier for venetian blinds reports and get/set -const uint8 FIBARO_VENETIEN_BLINDS_REPORT_ID[3] = { 0x26, 0x03, 0x03 }; -const uint8 FIBARO_VENETIAN_BLINDS_GET_POSITION_TILT[5] = { 0x26, 0x02, 0x02, 0x00, 0x00 }; -const uint8 FIBARO_VENETIAN_BLINDS_SET_TILT[4] = { 0x26, 0x01, 0x01, 0x00 }; -const uint8 FIBARO_VENETIAN_BLINDS_SET_POSITION[3] = { 0x26, 0x01, 0x02 }; - - -enum FibaroVenetianBlindsValueIds -{ - FibaroVenetianBlindsValueIds_Blinds = 0, - FibaroVenetianBlindsValueIds_Tilt = 1 -}; + const uint8 FIBARO_VENETIEN_BLINDS_REPORT_ID[3] = + { 0x26, 0x03, 0x03 }; + const uint8 FIBARO_VENETIAN_BLINDS_GET_POSITION_TILT[5] = + { 0x26, 0x02, 0x02, 0x00, 0x00 }; + const uint8 FIBARO_VENETIAN_BLINDS_SET_TILT[4] = + { 0x26, 0x01, 0x01, 0x00 }; + const uint8 FIBARO_VENETIAN_BLINDS_SET_POSITION[3] = + { 0x26, 0x01, 0x02 }; //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool ManufacturerProprietary::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - uint8 const* payload = _data+2; - if( MANUFACTURER_ID_FIBARO[0] == _data[0] && - MANUFACTURER_ID_FIBARO[1] == _data[1] ) - { - - if( FIBARO_VENETIEN_BLINDS_REPORT_ID[0] == payload[0] && - FIBARO_VENETIEN_BLINDS_REPORT_ID[1] == payload[1] && - FIBARO_VENETIEN_BLINDS_REPORT_ID[2] == payload[2] ) - { - ValueByte* blindsValue = static_cast( GetValue( _instance, FibaroVenetianBlindsValueIds_Blinds ) ); - ValueByte* tiltValue = static_cast( GetValue( _instance, FibaroVenetianBlindsValueIds_Tilt ) ); - - if( NULL != blindsValue && NULL != tiltValue) - { - Log::Write( LogLevel_Info, GetNodeId(), "Received Fibaro proprietary blind/slat position for node %d: Blinds: %d Slats: %d", - GetNodeId(), payload[3], payload[4] ); - blindsValue->OnValueRefreshed( payload[3] ); - tiltValue->OnValueRefreshed( payload[4] ); - blindsValue->Release(); - tiltValue->Release(); - } - else - { - Log::Write( LogLevel_Warning, GetNodeId(), "Error setting Fibaro blind/slat position. Values were not found." ); - } - return true; - } - else - { - Log::Write( LogLevel_Warning, GetNodeId(), "Received unknown Fibaro proprietary message for node %d.", - GetNodeId()); - return false; - } - } - Log::Write( LogLevel_Warning, GetNodeId(), "Received unknown manufacturer proprietary message for node %d.", - GetNodeId()); - return false; -} + bool ManufacturerProprietary::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) + { + uint8 const* payload = _data + 2; + if (MANUFACTURER_ID_FIBARO[0] == _data[0] && MANUFACTURER_ID_FIBARO[1] == _data[1]) + { + + if (FIBARO_VENETIEN_BLINDS_REPORT_ID[0] == payload[0] && FIBARO_VENETIEN_BLINDS_REPORT_ID[1] == payload[1] && FIBARO_VENETIEN_BLINDS_REPORT_ID[2] == payload[2]) + { + Internal::VC::ValueByte* blindsValue = static_cast(GetValue(_instance, ValueID_Index_ManufacturerProprietary::FibaroVenetianBlinds_Blinds)); + Internal::VC::ValueByte* tiltValue = static_cast(GetValue(_instance, ValueID_Index_ManufacturerProprietary::FibaroVenetianBlinds_Tilt)); + + if ( NULL != blindsValue && NULL != tiltValue) + { + Log::Write(LogLevel_Info, GetNodeId(), "Received Fibaro proprietary blind/slat position for node %d: Blinds: %d Slats: %d", GetNodeId(), payload[3], payload[4]); + blindsValue->OnValueRefreshed(payload[3]); + tiltValue->OnValueRefreshed(payload[4]); + blindsValue->Release(); + tiltValue->Release(); + } + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "Error setting Fibaro blind/slat position. Values were not found."); + } + return true; + } + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "Received unknown Fibaro proprietary message for node %d.", GetNodeId()); + return false; + } + } + Log::Write(LogLevel_Warning, GetNodeId(), "Received unknown manufacturer proprietary message for node %d.", GetNodeId()); + return false; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool ManufacturerProprietary::RequestValue -( - uint32 const _requestFlags, - uint16 const _index, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Msg* msg = new Msg( "ManufacturerProprietary_RequestValue", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - if (FibaroVenetianBlindsValueIds_Blinds == _index || FibaroVenetianBlindsValueIds_Tilt == _index){ - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 1+sizeof(MANUFACTURER_ID_FIBARO)+sizeof(FIBARO_VENETIAN_BLINDS_GET_POSITION_TILT) ); // length of data - msg->Append( GetCommandClassId() ); - msg->AppendArray( MANUFACTURER_ID_FIBARO, sizeof(MANUFACTURER_ID_FIBARO) ); - msg->AppendArray( FIBARO_VENETIAN_BLINDS_GET_POSITION_TILT, sizeof(FIBARO_VENETIAN_BLINDS_GET_POSITION_TILT) ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "ManufacturerProprietary_RequestValue Not Supported for value index %d", - _index); - } - } else { - Log::Write( LogLevel_Info, GetNodeId(), "ManufacturerProprietary_RequestValue Not Supported on this node"); - } - return false; -} + bool ManufacturerProprietary::RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Msg* msg = new Msg("ManufacturerProprietary_RequestValue", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + if (ValueID_Index_ManufacturerProprietary::FibaroVenetianBlinds_Blinds == _index || ValueID_Index_ManufacturerProprietary::FibaroVenetianBlinds_Tilt == _index) + { + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(1 + sizeof(MANUFACTURER_ID_FIBARO) + sizeof(FIBARO_VENETIAN_BLINDS_GET_POSITION_TILT)); // length of data + msg->Append(GetCommandClassId()); + msg->AppendArray(MANUFACTURER_ID_FIBARO, sizeof(MANUFACTURER_ID_FIBARO)); + msg->AppendArray(FIBARO_VENETIAN_BLINDS_GET_POSITION_TILT, sizeof(FIBARO_VENETIAN_BLINDS_GET_POSITION_TILT)); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "ManufacturerProprietary_RequestValue Not Supported for value index %d", _index); + } + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "ManufacturerProprietary_RequestValue Not Supported on this node"); + } + return false; + } //----------------------------------------------------------------------------- // // Set the lock's state //----------------------------------------------------------------------------- -bool ManufacturerProprietary::SetValue -( - Value const& _value -) -{ - uint64 value_id = _value.GetID().GetIndex(); - Msg* msg = new Msg( "ManufacturerProprietary_SetValue", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - - if (FibaroVenetianBlindsValueIds_Blinds == value_id || FibaroVenetianBlindsValueIds_Tilt == value_id){ - ValueByte const* value = static_cast(&_value); - - msg->SetInstance( this, _value.GetID().GetInstance() ); - msg->Append( GetNodeId() ); - msg->Append( 2 + // length of data - sizeof(MANUFACTURER_ID_FIBARO) + - sizeof(FIBARO_VENETIAN_BLINDS_GET_POSITION_TILT) ); - msg->Append( GetCommandClassId() ); - msg->AppendArray( MANUFACTURER_ID_FIBARO, sizeof(MANUFACTURER_ID_FIBARO) ); - if (FibaroVenetianBlindsValueIds_Blinds == value_id) { - msg->AppendArray( FIBARO_VENETIAN_BLINDS_SET_POSITION, sizeof(FIBARO_VENETIAN_BLINDS_SET_POSITION) ); - msg->Append( value->GetValue() ); - msg->Append( 0x00 ); - } else if (FibaroVenetianBlindsValueIds_Tilt == value_id) { - msg->AppendArray( FIBARO_VENETIAN_BLINDS_SET_TILT, sizeof(FIBARO_VENETIAN_BLINDS_SET_TILT) ); - msg->Append( value->GetValue() ); - } - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "ManufacturerProprietary_SetValue %d not supported on node %d", value_id, GetNodeId()); - return false; - } -} - + bool ManufacturerProprietary::SetValue(Internal::VC::Value const& _value) + { + uint64 value_id = _value.GetID().GetIndex(); + Msg* msg = new Msg("ManufacturerProprietary_SetValue", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + + if (ValueID_Index_ManufacturerProprietary::FibaroVenetianBlinds_Blinds == value_id || ValueID_Index_ManufacturerProprietary::FibaroVenetianBlinds_Tilt == value_id) + { + Internal::VC::ValueByte const* value = static_cast(&_value); + + msg->SetInstance(this, _value.GetID().GetInstance()); + msg->Append(GetNodeId()); + msg->Append(2 + // length of data + sizeof(MANUFACTURER_ID_FIBARO) + sizeof(FIBARO_VENETIAN_BLINDS_GET_POSITION_TILT)); + msg->Append(GetCommandClassId()); + msg->AppendArray(MANUFACTURER_ID_FIBARO, sizeof(MANUFACTURER_ID_FIBARO)); + if (ValueID_Index_ManufacturerProprietary::FibaroVenetianBlinds_Blinds == value_id) + { + msg->AppendArray(FIBARO_VENETIAN_BLINDS_SET_POSITION, sizeof(FIBARO_VENETIAN_BLINDS_SET_POSITION)); + msg->Append(value->GetValue()); + msg->Append(0x00); + } + else if (ValueID_Index_ManufacturerProprietary::FibaroVenetianBlinds_Tilt == value_id) + { + msg->AppendArray(FIBARO_VENETIAN_BLINDS_SET_TILT, sizeof(FIBARO_VENETIAN_BLINDS_SET_TILT)); + msg->Append(value->GetValue()); + } + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "ManufacturerProprietary_SetValue %d not supported on node %d", value_id, GetNodeId()); + return false; + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/ManufacturerProprietary.h b/cpp/src/command_classes/ManufacturerProprietary.h index 9c4ea58f30..4d953fbfe3 100644 --- a/cpp/src/command_classes/ManufacturerProprietary.h +++ b/cpp/src/command_classes/ManufacturerProprietary.h @@ -32,29 +32,55 @@ namespace OpenZWave { - /** \brief Implements COMMAND_CLASS_PROPRIETARY (0x91), a Z-Wave device command class. - * \ingroup CommandClass - */ - class ManufacturerProprietary: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new ManufacturerProprietary( _homeId, _nodeId ); } - virtual ~ManufacturerProprietary(){} + namespace CC + { - static uint8 const StaticGetCommandClassId(){ return 0x91; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_MANUFACTURER_PROPRIETARY"; } + /** \brief Implements COMMAND_CLASS_PROPRIETARY (0x91), a Z-Wave device command class. + * \ingroup CommandClass + */ + class ManufacturerProprietary: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new ManufacturerProprietary(_homeId, _nodeId); + } + virtual ~ManufacturerProprietary() + { + } - // From CommandClass - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool SetValue( Value const& _value ); + static uint8 const StaticGetCommandClassId() + { + return 0x91; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_MANUFACTURER_PROPRIETARY"; + } - private: - ManufacturerProprietary( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} - }; + // From CommandClass + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool SetValue(Internal::VC::Value const& _value) override; + private: + ManufacturerProprietary(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + } + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/ManufacturerSpecific.cpp b/cpp/src/command_classes/ManufacturerSpecific.cpp index caa60639d5..182f2d0894 100644 --- a/cpp/src/command_classes/ManufacturerSpecific.cpp +++ b/cpp/src/command_classes/ManufacturerSpecific.cpp @@ -43,384 +43,357 @@ #include "value_classes/ValueString.h" #include "value_classes/ValueInt.h" -using namespace OpenZWave; - -enum ManufacturerSpecificCmd +namespace OpenZWave { - ManufacturerSpecificCmd_Get = 0x04, - ManufacturerSpecificCmd_Report = 0x05, - ManufacturerSpecificCmd_DeviceGet = 0x06, - ManufacturerSpecificCmd_DeviceReport = 0x07 -}; - -enum { - DeviceSpecificGet_DeviceIDType_FactoryDefault = 0x00, - DeviceSpecificGet_DeviceIDType_SerialNumber = 0x01, - DeviceSpecificGet_DeviceIDType_PseudoRandom = 0x02, -}; - -enum { - ManufacturerSpecific_LoadedConfig, - ManufacturerSpecific_LocalConfig, - ManufacturerSpecific_LatestConfig, - ManufacturerSpecific_DeviceID, - ManufacturerSpecific_SerialNumber -}; + namespace Internal + { + namespace CC + { + enum ManufacturerSpecificCmd + { + ManufacturerSpecificCmd_Get = 0x04, + ManufacturerSpecificCmd_Report = 0x05, + ManufacturerSpecificCmd_DeviceGet = 0x06, + ManufacturerSpecificCmd_DeviceReport = 0x07 + }; + + enum + { + DeviceSpecificGet_DeviceIDType_FactoryDefault = 0x00, + DeviceSpecificGet_DeviceIDType_SerialNumber = 0x01, + DeviceSpecificGet_DeviceIDType_PseudoRandom = 0x02, + }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -ManufacturerSpecific::ManufacturerSpecific -( - uint32 const _homeId, - uint8 const _nodeId -): - CommandClass( _homeId, _nodeId ), - m_fileConfigRevision(0), - m_loadedConfigRevision(0), - m_latestConfigRevision(0) -{ - SetStaticRequest( StaticRequest_Values ); -} - + ManufacturerSpecific::ManufacturerSpecific(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId), m_fileConfigRevision(0), m_loadedConfigRevision(0), m_latestConfigRevision(0) + { + SetStaticRequest(StaticRequest_Values); + } //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool ManufacturerSpecific::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - - bool res = false; - if( GetVersion() > 1 ) - { - if( _requestFlags & RequestFlag_Static ) - { + bool ManufacturerSpecific::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) { - Msg* msg = new Msg( "ManufacturerSpecificCmd_DeviceGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( ManufacturerSpecificCmd_DeviceGet ); - msg->Append( DeviceSpecificGet_DeviceIDType_FactoryDefault ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - } - { - Msg* msg = new Msg( "ManufacturerSpecificCmd_DeviceGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( ManufacturerSpecificCmd_DeviceGet ); - msg->Append( DeviceSpecificGet_DeviceIDType_SerialNumber ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - } - - res = true; - } - } - - - if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) ) - { - res |= RequestValue( _requestFlags, 0, _instance, _queue ); - } - - return res; -} + bool res = false; + if (GetVersion() > 1) + { + if (_requestFlags & RequestFlag_Static) + { + { + Msg* msg = new Msg("ManufacturerSpecificCmd_DeviceGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(ManufacturerSpecificCmd_DeviceGet); + msg->Append(DeviceSpecificGet_DeviceIDType_FactoryDefault); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + } + { + Msg* msg = new Msg("ManufacturerSpecificCmd_DeviceGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(ManufacturerSpecificCmd_DeviceGet); + msg->Append(DeviceSpecificGet_DeviceIDType_SerialNumber); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + } + + res = true; + } + } + + if ((_requestFlags & RequestFlag_Static) && HasStaticRequest(StaticRequest_Values)) + { + res |= RequestValue(_requestFlags, 0, _instance, _queue); + } + + return res; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool ManufacturerSpecific::RequestValue -( - uint32 const _requestFlags, - uint16 const _dummy1, // = 0 (not used) - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _instance != 1 ) - { - // This command class doesn't work with multiple instances - return false; - } - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Msg* msg = new Msg( "ManufacturerSpecificCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( ManufacturerSpecificCmd_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "ManufacturerSpecificCmd_Get Not Supported on this node"); - } - return false; -} - -void ManufacturerSpecific::SetProductDetails -( - uint16 manufacturerId, - uint16 productType, - uint16 productId -) -{ + bool ManufacturerSpecific::RequestValue(uint32 const _requestFlags, uint16 const _dummy1, // = 0 (not used) + uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_instance != 1) + { + // This command class doesn't work with multiple instances + return false; + } + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Msg* msg = new Msg("ManufacturerSpecificCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(ManufacturerSpecificCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "ManufacturerSpecificCmd_Get Not Supported on this node"); + } + return false; + } - string configPath = ""; - ProductDescriptor *product = GetDriver()->GetManufacturerSpecificDB()->getProduct(manufacturerId, productType, productId); + void ManufacturerSpecific::SetProductDetails(uint16 manufacturerId, uint16 productType, uint16 productId) + { - Node *node = GetNodeUnsafe(); - if (!product) { - char str[64]; - snprintf( str, sizeof(str), "Unknown: id=%.4x", manufacturerId ); - string manufacturerName = str; + string configPath = ""; + std::shared_ptr product = GetDriver()->GetManufacturerSpecificDB()->getProduct(manufacturerId, productType, productId); - snprintf( str, sizeof(str), "Unknown: type=%.4x, id=%.4x", productType, productId ); - string productName = str; + Node *node = GetNodeUnsafe(); + if (!product) + { + char str[64]; + snprintf(str, sizeof(str), "Unknown: id=%.4x", manufacturerId); + string manufacturerName = str; - node->SetManufacturerName( manufacturerName ); - node->SetProductName( productName ); - } else { - node->SetManufacturerName( product->GetManufacturerName() ); - node->SetProductName( product->GetProductName() ); - node->SetProductDetails(product); - } + snprintf(str, sizeof(str), "Unknown: type=%.4x, id=%.4x", productType, productId); + string productName = str; - node->SetManufacturerId( manufacturerId ); + node->SetManufacturerName(manufacturerName); + node->SetProductName(productName); + } + else + { + node->SetManufacturerName(product->GetManufacturerName()); + node->SetProductName(product->GetProductName()); + node->SetProductDetails(product); + } - node->SetProductType( productType ); + node->SetManufacturerId(manufacturerId); - node->SetProductId( productId ); + node->SetProductType(productType); -} + node->SetProductId(productId); + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool ManufacturerSpecific::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if( ManufacturerSpecificCmd_Report == (ManufacturerSpecificCmd)_data[0] ) - { - - // first two bytes are manufacturer id code - uint16 manufacturerId = (((uint16)_data[1])<<8) | (uint16)_data[2]; - - // next four are product type and product id - uint16 productType = (((uint16)_data[3])<<8) | (uint16)_data[4]; - uint16 productId = (((uint16)_data[5])<<8) | (uint16)_data[6]; - - if( Node* node = GetNodeUnsafe() ) - { - // Attempt to create the config parameters - SetProductDetails(manufacturerId, productType, productId); - ClearStaticRequest( StaticRequest_Values ); - node->m_manufacturerSpecificClassReceived = true; - - if( node->getConfigPath().size() > 0 ) + bool ManufacturerSpecific::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) { - LoadConfigXML( ); + if (ManufacturerSpecificCmd_Report == (ManufacturerSpecificCmd) _data[0]) + { + + // first two bytes are manufacturer id code + uint16 manufacturerId = (((uint16) _data[1]) << 8) | (uint16) _data[2]; + + // next four are product type and product id + uint16 productType = (((uint16) _data[3]) << 8) | (uint16) _data[4]; + uint16 productId = (((uint16) _data[5]) << 8) | (uint16) _data[6]; + + if (Node* node = GetNodeUnsafe()) + { + // Attempt to create the config parameters + SetProductDetails(manufacturerId, productType, productId); + ClearStaticRequest(StaticRequest_Values); + node->m_manufacturerSpecificClassReceived = true; + + if (node->getConfigPath().size() > 0) + { + LoadConfigXML(); + } + + Log::Write(LogLevel_Info, GetNodeId(), "Received manufacturer specific report from node %d: Manufacturer=%s, Product=%s", GetNodeId(), node->GetManufacturerName().c_str(), node->GetProductName().c_str()); + Log::Write(LogLevel_Info, GetNodeId(), "Node Identity Codes: %.4x:%.4x:%.4x", manufacturerId, productType, productId); + } + + // Notify the watchers of the name changes + Notification* notification = new Notification(Notification::Type_NodeNaming); + notification->SetHomeAndNodeIds(GetHomeId(), GetNodeId()); + GetDriver()->QueueNotification(notification); + + return true; + } + else if (ManufacturerSpecificCmd_DeviceReport == (ManufacturerSpecificCmd) _data[0]) + { + uint8 deviceIDType = (_data[1] & 0x07); + uint8 dataFormat = (_data[2] & 0xe0) >> 0x05; + uint8 data_length = (_data[2] & 0x1f); + uint8 const* deviceIDData = &_data[3]; + string deviceID = ""; + for (int i = 0; i < data_length; i++) + { + char temp_chr[32]; + memset(temp_chr, 0, sizeof(temp_chr)); + if (dataFormat == 0x00) + { + temp_chr[0] = deviceIDData[i]; + } + else + { + snprintf(temp_chr, sizeof(temp_chr), "%.2x", deviceIDData[i]); + } + deviceID += temp_chr; + } + if (deviceIDType == DeviceSpecificGet_DeviceIDType_FactoryDefault) + { + Internal::VC::ValueString *default_value = static_cast(GetValue(_instance, ValueID_Index_ManufacturerSpecific::DeviceID)); + default_value->OnValueRefreshed(deviceID); + default_value->Release(); + } + else if (deviceIDType == DeviceSpecificGet_DeviceIDType_SerialNumber) + { + Internal::VC::ValueString *serial_value = static_cast(GetValue(_instance, ValueID_Index_ManufacturerSpecific::SerialNumber)); + serial_value->OnValueRefreshed(deviceID); + serial_value->Release(); + } + return true; + } + + return false; } - Log::Write( LogLevel_Info, GetNodeId(), "Received manufacturer specific report from node %d: Manufacturer=%s, Product=%s", - GetNodeId(), node->GetManufacturerName().c_str(), node->GetProductName().c_str() ); - Log::Write( LogLevel_Info, GetNodeId(), "Node Identity Codes: %.4x:%.4x:%.4x", manufacturerId, productType, productId ); - } - - // Notify the watchers of the name changes - Notification* notification = new Notification( Notification::Type_NodeNaming ); - notification->SetHomeAndNodeIds( GetHomeId(), GetNodeId() ); - GetDriver()->QueueNotification( notification ); - - return true; - } else if( ManufacturerSpecificCmd_DeviceReport == (ManufacturerSpecificCmd)_data[0] ) { - uint8 deviceIDType = (_data[1] & 0x07); - uint8 dataFormat = (_data[2] & 0xe0)>>0x05; - uint8 data_length = (_data[2] & 0x1f); - uint8 const* deviceIDData = &_data[3]; - string deviceID = ""; - for (int i=0; i( GetValue(_instance, ManufacturerSpecific_DeviceID) ); - default_value->OnValueRefreshed(deviceID); - default_value->Release(); - } - else if (deviceIDType == DeviceSpecificGet_DeviceIDType_SerialNumber) { - ValueString *serial_value = static_cast( GetValue(_instance, ManufacturerSpecific_SerialNumber) ); - serial_value->OnValueRefreshed(deviceID); - serial_value->Release(); - } - return true; - } - - return false; -} - - - //----------------------------------------------------------------------------- // // Try to find and load an XML file describing the device's config params //----------------------------------------------------------------------------- -bool ManufacturerSpecific::LoadConfigXML -( -) -{ - if (GetNodeUnsafe()->getConfigPath().size() == 0) - return false; - - - string configPath; - Options::Get()->GetOptionAsString( "ConfigPath", &configPath ); - - string filename = configPath + GetNodeUnsafe()->getConfigPath(); - - TiXmlDocument* doc = new TiXmlDocument(); - Log::Write( LogLevel_Info, GetNodeId(), " Opening config param file %s", filename.c_str() ); - if( !doc->LoadFile( filename.c_str(), TIXML_ENCODING_UTF8 ) ) - { - delete doc; - Log::Write( LogLevel_Info, GetNodeId(), "Unable to find or load Config Param file %s", filename.c_str() ); - return false; - } - doc->SetUserData((void *)filename.c_str()); - Node::QueryStage qs = GetNodeUnsafe()->GetCurrentQueryStage(); - if( qs == Node::QueryStage_ManufacturerSpecific1 ) - { - GetNodeUnsafe()->ReadDeviceProtocolXML( doc->RootElement() ); - } - else - { - if( ! GetNodeUnsafe()->m_manufacturerSpecificClassReceived ) - { - GetNodeUnsafe()->ReadDeviceProtocolXML( doc->RootElement() ); - } - } - GetNodeUnsafe()->ReadCommandClassesXML( doc->RootElement() ); - GetNodeUnsafe()->ReadMetaDataFromXML( doc->RootElement() ); - delete doc; - return true; -} + bool ManufacturerSpecific::LoadConfigXML() + { + if (GetNodeUnsafe()->getConfigPath().size() == 0) + return false; + + string configPath; + Options::Get()->GetOptionAsString("ConfigPath", &configPath); + + string filename = configPath + GetNodeUnsafe()->getConfigPath(); + + TiXmlDocument* doc = new TiXmlDocument(); + Log::Write(LogLevel_Info, GetNodeId(), " Opening config param file %s", filename.c_str()); + if (!doc->LoadFile(filename.c_str(), TIXML_ENCODING_UTF8)) + { + delete doc; + Log::Write(LogLevel_Info, GetNodeId(), "Unable to find or load Config Param file %s", filename.c_str()); + return false; + } + doc->SetUserData((void *) filename.c_str()); + /* make sure it has the right xmlns */ + TiXmlElement *product = doc->RootElement(); + char const *xmlns = product->Attribute("xmlns"); + if (xmlns && strcmp(xmlns, "https://github.com/OpenZWave/open-zwave")) + { + delete doc; + Log::Write(LogLevel_Warning, GetNodeId(), "Invalid XML Namespace in %s - Ignoring", filename.c_str()); + return false; + } + + Node::QueryStage qs = GetNodeUnsafe()->GetCurrentQueryStage(); + if (qs == Node::QueryStage_ManufacturerSpecific1) + { + GetNodeUnsafe()->ReadDeviceProtocolXML(doc->RootElement()); + } + else + { + if (!GetNodeUnsafe()->m_manufacturerSpecificClassReceived) + { + GetNodeUnsafe()->ReadDeviceProtocolXML(doc->RootElement()); + } + } + GetNodeUnsafe()->ReadCommandClassesXML(doc->RootElement()); + GetNodeUnsafe()->ReadMetaDataFromXML(doc->RootElement()); + delete doc; + return true; + } //----------------------------------------------------------------------------- // // Reload previously discovered device configuration. //----------------------------------------------------------------------------- -void ManufacturerSpecific::ReLoadConfigXML -( -) -{ - LoadConfigXML( ); -} + void ManufacturerSpecific::ReLoadConfigXML() + { + LoadConfigXML(); + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void ManufacturerSpecific::CreateVars -( - uint8 const _instance -) -{ - if (_instance == 1) { - if( Node* node = GetNodeUnsafe() ) - { - node->CreateValueInt( ValueID::ValueGenre_System, GetCommandClassId(), _instance, ManufacturerSpecific_LoadedConfig, "Loaded Config Revision", "", true, false, m_loadedConfigRevision, 0 ); - node->CreateValueInt( ValueID::ValueGenre_System, GetCommandClassId(), _instance, ManufacturerSpecific_LocalConfig, "Config File Revision", "", true, false, m_fileConfigRevision, 0 ); - node->CreateValueInt( ValueID::ValueGenre_System, GetCommandClassId(), _instance, ManufacturerSpecific_LatestConfig, "Latest Available Config File Revision", "", true, false, m_latestConfigRevision, 0 ); - node->CreateValueString( ValueID::ValueGenre_System, GetCommandClassId(), _instance, ManufacturerSpecific_DeviceID, "Device ID", "", true, false, "", 0); - node->CreateValueString( ValueID::ValueGenre_System, GetCommandClassId(), _instance, ManufacturerSpecific_SerialNumber, "Serial Number", "", true, false, "", 0); - } - } + void ManufacturerSpecific::CreateVars(uint8 const _instance) + { + if (_instance == 1) + { + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueInt(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_ManufacturerSpecific::LoadedConfig, "Loaded Config Revision", "", true, false, m_loadedConfigRevision, 0); + node->CreateValueInt(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_ManufacturerSpecific::LocalConfig, "Config File Revision", "", true, false, m_fileConfigRevision, 0); + node->CreateValueInt(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_ManufacturerSpecific::LatestConfig, "Latest Available Config File Revision", "", true, false, m_latestConfigRevision, 0); + node->CreateValueString(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_ManufacturerSpecific::DeviceID, "Device ID", "", true, false, "", 0); + node->CreateValueString(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_ManufacturerSpecific::SerialNumber, "Serial Number", "", true, false, "", 0); + } + } -} + } //----------------------------------------------------------------------------- // // Set the Latest Config Revision Available for this device //----------------------------------------------------------------------------- -void ManufacturerSpecific::setLatestConfigRevision -( - uint32 rev -) -{ + void ManufacturerSpecific::setLatestConfigRevision(uint32 rev) + { - m_latestConfigRevision = rev; + m_latestConfigRevision = rev; - if( ValueInt* value = static_cast( GetValue( 1, ManufacturerSpecific_LatestConfig ) ) ) - { - value->OnValueRefreshed( rev ); - value->Release(); - } + if (Internal::VC::ValueInt* value = static_cast(GetValue(1, ValueID_Index_ManufacturerSpecific::LatestConfig))) + { + value->OnValueRefreshed(rev); + value->Release(); + } -} + } //----------------------------------------------------------------------------- // // Set the File Config Revision for this device //----------------------------------------------------------------------------- -void ManufacturerSpecific::setFileConfigRevision -( - uint32 rev -) -{ - m_fileConfigRevision = rev; + void ManufacturerSpecific::setFileConfigRevision(uint32 rev) + { + m_fileConfigRevision = rev; - if( ValueInt* value = static_cast( GetValue( 1, ManufacturerSpecific_LocalConfig ) ) ) - { - value->OnValueRefreshed( rev ); - value->Release(); - } + if (Internal::VC::ValueInt* value = static_cast(GetValue(1, ValueID_Index_ManufacturerSpecific::LocalConfig))) + { + value->OnValueRefreshed(rev); + value->Release(); + } -} + } //----------------------------------------------------------------------------- // // Set the File Config Revision for this device //----------------------------------------------------------------------------- -void ManufacturerSpecific::setLoadedConfigRevision -( - uint32 rev -) -{ - m_latestConfigRevision = rev; - - if( ValueInt* value = static_cast( GetValue( 1, ManufacturerSpecific_LoadedConfig ) ) ) - { - value->OnValueRefreshed( rev ); - value->Release(); - } + void ManufacturerSpecific::setLoadedConfigRevision(uint32 rev) + { + m_latestConfigRevision = rev; -} + if (Internal::VC::ValueInt* value = static_cast(GetValue(1, ValueID_Index_ManufacturerSpecific::LoadedConfig))) + { + value->OnValueRefreshed(rev); + value->Release(); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/ManufacturerSpecific.h b/cpp/src/command_classes/ManufacturerSpecific.h index e5bf1a528b..1c22c6ec56 100644 --- a/cpp/src/command_classes/ManufacturerSpecific.h +++ b/cpp/src/command_classes/ManufacturerSpecific.h @@ -33,50 +33,72 @@ namespace OpenZWave { - /** \brief Implements COMMAND_CLASS_MANUFACTURER_SPECIFIC (0x72), a Z-Wave device command class. - * \ingroup CommandClass - */ - class ManufacturerSpecific: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new ManufacturerSpecific( _homeId, _nodeId ); } - virtual ~ManufacturerSpecific(){ } - - static uint8 const StaticGetCommandClassId(){ return 0x72; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_MANUFACTURER_SPECIFIC"; } - - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual uint8 GetMaxVersion(){ return 2; } - - - void SetProductDetails( uint16 _manufacturerId, uint16 _productType, uint16 _productId ); - bool LoadConfigXML(); - - void ReLoadConfigXML(); - - void setLatestConfigRevision(uint32 rev); - void setFileConfigRevision(uint32 rev); - void setLoadedConfigRevision(uint32 rev); - - - - protected: - virtual void CreateVars( uint8 const _instance ); - - - private: - ManufacturerSpecific( uint32 const _homeId, uint8 const _nodeId ); - - uint32 m_fileConfigRevision; - uint32 m_loadedConfigRevision; - uint32 m_latestConfigRevision; - }; - + namespace CC + { + + /** \brief Implements COMMAND_CLASS_MANUFACTURER_SPECIFIC (0x72), a Z-Wave device command class. + * \ingroup CommandClass + */ + class ManufacturerSpecific: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new ManufacturerSpecific(_homeId, _nodeId); + } + virtual ~ManufacturerSpecific() + { + } + + static uint8 const StaticGetCommandClassId() + { + return 0x72; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_MANUFACTURER_SPECIFIC"; + } + + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual uint8 GetMaxVersion() override + { + return 2; + } + + void SetProductDetails(uint16 _manufacturerId, uint16 _productType, uint16 _productId); + bool LoadConfigXML(); + + void ReLoadConfigXML(); + + void setLatestConfigRevision(uint32 rev); + void setFileConfigRevision(uint32 rev); + void setLoadedConfigRevision(uint32 rev); + + protected: + virtual void CreateVars(uint8 const _instance) override; + + private: + ManufacturerSpecific(uint32 const _homeId, uint8 const _nodeId); + + uint32 m_fileConfigRevision; + uint32 m_loadedConfigRevision; + uint32 m_latestConfigRevision; + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/Meter.cpp b/cpp/src/command_classes/Meter.cpp index d725ad7aff..3eadc25fe1 100644 --- a/cpp/src/command_classes/Meter.cpp +++ b/cpp/src/command_classes/Meter.cpp @@ -33,6 +33,7 @@ #include "Node.h" #include "Driver.h" #include "platform/Log.h" +#include "Utils.h" #include "value_classes/ValueDecimal.h" #include "value_classes/ValueList.h" @@ -40,522 +41,471 @@ #include "value_classes/ValueInt.h" #include "value_classes/ValueBool.h" -using namespace OpenZWave; - -enum MeterCmd -{ - MeterCmd_Get = 0x01, - MeterCmd_Report = 0x02, - // Version 2 - MeterCmd_SupportedGet = 0x03, - MeterCmd_SupportedReport = 0x04, - MeterCmd_Reset = 0x05 -}; - -enum MeterType +namespace OpenZWave { - MeterType_Electric = 1, - MeterType_Gas, - MeterType_Water -}; - -enum -{ - MeterIndex_Exporting = 32, - MeterIndex_Reset -}; - - -static char const* c_meterTypes[] = -{ - "Unknown", - "Electric", - "Gas", - "Water" -}; - -static char const* c_electricityUnits[] = -{ - "kWh", - "kVAh", - "W", - "pulses", - "V", - "A", - "Power Factor", - "" -}; - -static char const* c_gasUnits[] = -{ - "cubic meters", - "cubic feet", - "", - "pulses", - "", - "", - "", - "" -}; - -static char const* c_waterUnits[] = -{ - "cubic meters", - "cubic feet", - "US gallons", - "pulses", - "", - "", - "", - "" -}; - -static char const* c_electricityLabels[] = -{ - "Energy", - "Energy", - "Power", - "Count", - "Voltage", - "Current", - "Power Factor", - "Unknown" -}; + namespace Internal + { + namespace CC + { + enum MeterCmd + { + MeterCmd_Get = 0x01, + MeterCmd_Report = 0x02, + // Version 2 + MeterCmd_SupportedGet = 0x03, + MeterCmd_SupportedReport = 0x04, + MeterCmd_Reset = 0x05 + }; + + enum MeterType + { + MeterType_Electric = 0, + MeterType_Gas, + MeterType_Water, + MeterType_Heating, + MeterType_Cooling + }; + + struct s_MeterTypes { + string Label; + string Unit; + }; + std::map MeterTypes = { + {ValueID_Index_Meter::Electric_kWh, {"Electric - kWh", "kWh"}}, + {ValueID_Index_Meter::Electric_kVah, {"Electric - kVah", "kVah"}}, + {ValueID_Index_Meter::Electric_W, {"Electric - W", "W"}}, + {ValueID_Index_Meter::Electric_Pulse, {"Electric - Pulses", "Pulses"}}, + {ValueID_Index_Meter::Electric_V, {"Electric - V", "V"}}, + {ValueID_Index_Meter::Electric_A, {"Electric - A", "A"}}, + {ValueID_Index_Meter::Electric_PowerFactor, {"Electric - PF", "PF"}}, + {ValueID_Index_Meter::Electric_Unknown_1, {"Electric (Unknown)", ""}}, + {ValueID_Index_Meter::Electric_kVar, {"Electric - kVar", "kVar"}}, + {ValueID_Index_Meter::Electric_kVarh, {"Electric - kVarh", "kVarh"}}, + {ValueID_Index_Meter::Electric_Unknown_2, {"Electric (Unknown)", ""}}, + {ValueID_Index_Meter::Electric_Unknown_3, {"Electric (Unknown)", ""}}, + {ValueID_Index_Meter::Electric_Unknown_4, {"Electric (Unknown)", ""}}, + {ValueID_Index_Meter::Electric_Unknown_5, {"Electric (Unknown)", ""}}, + {ValueID_Index_Meter::Electric_Unknown_6, {"Electric (Unknown)", ""}}, + {ValueID_Index_Meter::Electric_Unknown_7, {"Electric (Unknown)", ""}}, + {ValueID_Index_Meter::Gas_Cubic_Meters, {"Gas - m3", "m3"}}, + {ValueID_Index_Meter::Gas_Cubic_Feet, {"Gas - ft3", "ft3"}}, + {ValueID_Index_Meter::Gas_Unknown_1, {"Gas (Unknown)", ""}}, + {ValueID_Index_Meter::Gas_Pulse, {"Gas - Pulses", "Pulses"}}, + {ValueID_Index_Meter::Gas_Unknown_2, {"Gas (Unknown)", ""}}, + {ValueID_Index_Meter::Gas_Unknown_3, {"Gas (Unknown)", ""}}, + {ValueID_Index_Meter::Gas_Unknown_4, {"Gas (Unknown)", ""}}, + {ValueID_Index_Meter::Gas_Unknown_5, {"Gas (Unknown)", ""}}, + {ValueID_Index_Meter::Gas_Unknown_6, {"Gas (Unknown)", ""}}, + {ValueID_Index_Meter::Gas_Unknown_7, {"Gas (Unknown)", ""}}, + {ValueID_Index_Meter::Gas_Unknown_8, {"Gas (Unknown)", ""}}, + {ValueID_Index_Meter::Gas_Unknown_9, {"Gas (Unknown)", ""}}, + {ValueID_Index_Meter::Gas_Unknown_10, {"Gas (Unknown)", ""}}, + {ValueID_Index_Meter::Gas_Unknown_11, {"Gas (Unknown)", ""}}, + {ValueID_Index_Meter::Gas_Unknown_12, {"Gas (Unknown)", ""}}, + {ValueID_Index_Meter::Gas_Unknown_13, {"Gas (Unknown)", ""}}, + {ValueID_Index_Meter::Water_Cubic_Meters, {"Water - m3", "m3"}}, + {ValueID_Index_Meter::Water_Cubic_Feet, {"Water - ft3", "ft3"}}, + {ValueID_Index_Meter::Water_Cubic_US_Gallons, {"Water - gal", "gal"}}, + {ValueID_Index_Meter::Water_Cubic_Pulse, {"Water - Pulses", "Pulses"}}, + {ValueID_Index_Meter::Water_Unknown_1, {"Water (Unknown)", ""}}, + {ValueID_Index_Meter::Water_Unknown_2, {"Water (Unknown)", ""}}, + {ValueID_Index_Meter::Water_Unknown_3, {"Water (Unknown)", ""}}, + {ValueID_Index_Meter::Water_Unknown_4, {"Water (Unknown)", ""}}, + {ValueID_Index_Meter::Water_Unknown_5, {"Water (Unknown)", ""}}, + {ValueID_Index_Meter::Water_Unknown_6, {"Water (Unknown)", ""}}, + {ValueID_Index_Meter::Water_Unknown_7, {"Water (Unknown)", ""}}, + {ValueID_Index_Meter::Water_Unknown_8, {"Water (Unknown)", ""}}, + {ValueID_Index_Meter::Water_Unknown_9, {"Water (Unknown)", ""}}, + {ValueID_Index_Meter::Water_Unknown_10, {"Water (Unknown)", ""}}, + {ValueID_Index_Meter::Water_Unknown_11, {"Water (Unknown)", ""}}, + {ValueID_Index_Meter::Water_Unknown_12, {"Water (Unknown)", ""}}, + {ValueID_Index_Meter::Heating_kWh, {"Heating - kWh", "kWh"}}, + {ValueID_Index_Meter::Heating_Unknown_1, {"Heating (Unknown)", ""}}, + {ValueID_Index_Meter::Heating_Unknown_2, {"Heating (Unknown)", ""}}, + {ValueID_Index_Meter::Heating_Unknown_3, {"Heating (Unknown)", ""}}, + {ValueID_Index_Meter::Heating_Unknown_4, {"Heating (Unknown)", ""}}, + {ValueID_Index_Meter::Heating_Unknown_5, {"Heating (Unknown)", ""}}, + {ValueID_Index_Meter::Heating_Unknown_6, {"Heating (Unknown)", ""}}, + {ValueID_Index_Meter::Heating_Unknown_7, {"Heating (Unknown)", ""}}, + {ValueID_Index_Meter::Heating_Unknown_8, {"Heating (Unknown)", ""}}, + {ValueID_Index_Meter::Heating_Unknown_9, {"Heating (Unknown)", ""}}, + {ValueID_Index_Meter::Heating_Unknown_10, {"Heating (Unknown)", ""}}, + {ValueID_Index_Meter::Heating_Unknown_11, {"Heating (Unknown)", ""}}, + {ValueID_Index_Meter::Heating_Unknown_12, {"Heating (Unknown)", ""}}, + {ValueID_Index_Meter::Heating_Unknown_13, {"Heating (Unknown)", ""}}, + {ValueID_Index_Meter::Heating_Unknown_14, {"Heating (Unknown)", ""}}, + {ValueID_Index_Meter::Heating_Unknown_15, {"Heating (Unknown)", ""}}, + {ValueID_Index_Meter::Cooling_kWh, {"Cooling - kWh", "kWh"}}, + {ValueID_Index_Meter::Cooling_Unknown_1, {"Cooling (Unknown)", ""}}, + {ValueID_Index_Meter::Cooling_Unknown_2, {"Cooling (Unknown)", ""}}, + {ValueID_Index_Meter::Cooling_Unknown_3, {"Cooling (Unknown)", ""}}, + {ValueID_Index_Meter::Cooling_Unknown_4, {"Cooling (Unknown)", ""}}, + {ValueID_Index_Meter::Cooling_Unknown_5, {"Cooling (Unknown)", ""}}, + {ValueID_Index_Meter::Cooling_Unknown_6, {"Cooling (Unknown)", ""}}, + {ValueID_Index_Meter::Cooling_Unknown_7, {"Cooling (Unknown)", ""}}, + {ValueID_Index_Meter::Cooling_Unknown_8, {"Cooling (Unknown)", ""}}, + {ValueID_Index_Meter::Cooling_Unknown_9, {"Cooling (Unknown)", ""}}, + {ValueID_Index_Meter::Cooling_Unknown_10, {"Cooling (Unknown)", ""}}, + {ValueID_Index_Meter::Cooling_Unknown_11, {"Cooling (Unknown)", ""}}, + {ValueID_Index_Meter::Cooling_Unknown_12, {"Cooling (Unknown)", ""}}, + {ValueID_Index_Meter::Cooling_Unknown_13, {"Cooling (Unknown)", ""}}, + {ValueID_Index_Meter::Cooling_Unknown_14, {"Cooling (Unknown)", ""}}, + {ValueID_Index_Meter::Cooling_Unknown_15, {"Cooling (Unknown)", ""}} + }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -Meter::Meter -( - uint32 const _homeId, - uint8 const _nodeId -): - CommandClass( _homeId, _nodeId ) -{ - SetStaticRequest( StaticRequest_Values ); -} + Meter::Meter(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { +#if 0 + std::map::iterator it; + for (it = MeterTypes.begin(); it != MeterTypes.end(); it++) { + std::cout << "Type: " << it->first << std::endl; + std::cout << "\tLabel: " << it->second.Label << std::endl; + std::cout << "\tUnit: " << it->second.Unit << std::endl; + } +#endif + SetStaticRequest(StaticRequest_Values); + } //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool Meter::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - bool res = false; - if( GetVersion() > 1 ) - { - if( _requestFlags & RequestFlag_Static ) - { - Msg* msg = new Msg( "MeterCmd_SupportedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( MeterCmd_SupportedGet ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - res = true; - } - } + bool Meter::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + bool res = false; + if (GetVersion() > 1) + { + if (_requestFlags & RequestFlag_Static) + { + Msg* msg = new Msg("MeterCmd_SupportedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(MeterCmd_SupportedGet); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + res = true; + } + } - if( _requestFlags & RequestFlag_Dynamic ) - { - res |= RequestValue( _requestFlags, 0, _instance, _queue ); - } + if (_requestFlags & RequestFlag_Dynamic) + { + res |= RequestValue(_requestFlags, 0, _instance, _queue); + } - return res; -} + return res; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool Meter::RequestValue -( - uint32 const _requestFlags, - uint16 const _dummy1, // = 0 (not used) - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - bool res = false; - if ( !m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) - { - Log::Write( LogLevel_Info, GetNodeId(), "MeterCmd_Get Not Supported on this node"); - return false; - } - for( uint8 i=0; i<8; ++i ) - { - uint8 baseIndex = i<<2; - - Value* value = GetValue( _instance, baseIndex ); - if( value != NULL ) - { - value->Release(); - Msg* msg = new Msg( "MeterCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( MeterCmd_Get ); - msg->Append( (uint8)( i << 3 ) ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - res |= true; - } - } - return res; -} + bool Meter::RequestValue(uint32 const _requestFlags, uint16 const _dummy1, // = 0 (not used) + uint8 const _instance, Driver::MsgQueue const _queue) + { + bool res = false; + if (!m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Log::Write(LogLevel_Info, GetNodeId(), "MeterCmd_Get Not Supported on this node"); + return false; + } + for (uint8 i = 0; i < MeterTypes.size(); ++i) + { + Internal::VC::Value* value = GetValue(_instance, i); + if (value != NULL) + { + value->Release(); + Msg* msg = new Msg("MeterCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + if (GetVersion() == 1) + msg->Append(2); + else if (GetVersion() <= 3) + msg->Append(3); + else if (GetVersion() >= 4) { + uint8 scale = (i % 16); + if (scale > ValueID_Index_Meter::Electric_Unknown_1) + msg->Append(4); + else + msg->Append(3); + } + msg->Append(GetCommandClassId()); + msg->Append(MeterCmd_Get); + if (GetVersion() == 2) + msg->Append((((i % 16) & 0x03) << 3)); + else if (GetVersion() == 3) + msg->Append((((i % 16) & 0x07) << 3)); + else if (GetVersion() >= 4) { + uint8 scale = (i % 16); + if (scale > ValueID_Index_Meter::Electric_Unknown_1) { + /* 4.55.3 - 0x38 is scale value 7 unshifted */ + msg->Append(0x38); + msg->Append(scale-8); + } else { + /* our Scale can fit in Scale 1 */ + msg->Append((((i % 16) & 0x07) << 3)); + } + } + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + res |= true; + } + } +// exit(-1); + return res; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool Meter::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - bool handled = false; - if (MeterCmd_SupportedReport == (MeterCmd)_data[0]) - { - handled = HandleSupportedReport( _data, _length, _instance ); - } - else if (MeterCmd_Report == (MeterCmd)_data[0]) - { - handled = HandleReport( _data, _length, _instance ); - } + bool Meter::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) + { + bool handled = false; + if (MeterCmd_SupportedReport == (MeterCmd) _data[0]) + { + handled = HandleSupportedReport(_data, _length, _instance); + } + else if (MeterCmd_Report == (MeterCmd) _data[0]) + { + handled = HandleReport(_data, _length, _instance); + } - return handled; -} + return handled; + } //----------------------------------------------------------------------------- // // Create the values for this command class based on the reported parameters //----------------------------------------------------------------------------- -bool Meter::HandleSupportedReport -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance -) -{ - bool canReset = ((_data[1] & 0x80) != 0); - int8 meterType = (MeterType)(_data[1] & 0x1f); - if (meterType > 4) /* size of c_meterTypes */ - { - Log::Write (LogLevel_Warning, GetNodeId(), "meterType Value was greater than range. Dropping Message"); - return false; - } - - - ClearStaticRequest( StaticRequest_Version ); - if( Node* node = GetNodeUnsafe() ) - { - string msg; - msg = c_meterTypes[meterType]; - msg += ": "; - // Create the list of supported scales - uint8 scaleSupported = _data[2]; - if( GetVersion() == 2 ) - { - // Only four scales are allowed in version 2 - scaleSupported &= 0x0f; - } - - for( uint8 i=0; i<8; ++i ) - { - if( scaleSupported & (1< MeterType_Cooling) /* size of c_meterTypes */ { - case MeterType_Electric: - { - if( ValueDecimal* value = static_cast( GetValue( _instance, baseIndex ) ) ) - { - value->SetLabel( c_electricityLabels[i] ); - value->SetUnits( c_electricityUnits[i] ); - value->Release(); - } - else - { - node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, baseIndex, c_electricityLabels[i], c_electricityUnits[i], true, false, "0.0", 0 ); - } - if( i != 0 ) - msg += ", "; - msg += c_electricityUnits[i]; - break; - } - case MeterType_Gas: - { - if( ValueDecimal* value = static_cast( GetValue( _instance, baseIndex ) ) ) - { - value->SetLabel( c_meterTypes[MeterType_Gas] ); - value->SetUnits( c_gasUnits[i] ); - value->Release(); - } - else - { - node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, baseIndex, c_meterTypes[meterType], c_gasUnits[i], true, false, "0.0", 0 ); + Log::Write(LogLevel_Warning, GetNodeId(), "meterType Value was greater than range. Dropping Message"); + return false; + } + uint32 scale = 0; + uint8 scalesize = 1; + /* decode the Scale */ + /* Version 1 Doesn't have a Supported Report Message + * The Scale is encoded in the Report Message instead + */ + if (GetVersion() == 2) { + scale = (_data[2] & 0x0F); + } + if (GetVersion() == 3) { + scale = (_data[2] & 0xFF); + } + /* Version 4 has the Scale All Over the Place */ + if (GetVersion() >= 4) { + /* if the MSB is set - Then the Scales Supported are specified as optional + * bytes following this byte + */ + scale = (_data[2] & 0x7F); + if (_data[2] & 0x80) { + uint8_t size = _data[3]; + for (int i = 1; i <= size; i++) { + uint8 scale2 = _data[3+1]; + scale |= (scale2 << 8*i); } - if( i != 0 ) - msg += ", "; - msg += c_gasUnits[i]; - break; + size += scalesize; } - case MeterType_Water: + } + if (Node* node = GetNodeUnsafe()) + { + for (uint8 i = 0; i <= (scalesize*8)+1; ++i) { - if( ValueDecimal* value = static_cast( GetValue( _instance, baseIndex ) ) ) + if (scale & (1 << i)) { - value->SetLabel( c_meterTypes[MeterType_Water] ); - value->SetUnits( c_waterUnits[i] ); - value->Release(); + uint32 type = ((meterType-1) * 16) + i; + if (type > MeterTypes.size()) { + /* error */ + Log::Write(LogLevel_Warning, GetNodeId(), "MeterType %d and Unit %d is unknown", meterType, i); + continue; + } + Log::Write(LogLevel_Info, GetNodeId(), "Creating MeterType %s (%d) with Unit %s (%d) at Index %d", MeterTypes.at(type).Label.c_str(), meterType, MeterTypes.at(type).Unit.c_str(), i, type); + node->CreateValueDecimal(ValueID::ValueGenre_User, GetCommandClassId(), _instance, type, MeterTypes.at(type).Label, MeterTypes.at(type).Unit, true, false, "0.0", 0); } - else - { - node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, baseIndex, c_meterTypes[meterType], c_waterUnits[i], true, false, "0.0", 0 ); - } - if( i != 0 ) - msg += ", "; - msg += c_waterUnits[i]; - break; } - default: + // Create the export flag + node->CreateValueBool(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_Meter::Exporting, "Exporting", "", true, false, false, 0); + + // Create the reset button + if (canReset) { - break; + node->CreateValueButton(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_Meter::Reset, "Reset", 0); } + return true; } + return false; } - } - - // Create the export flag - node->CreateValueBool( ValueID::ValueGenre_User, GetCommandClassId(), _instance, MeterIndex_Exporting, "Exporting", "", true, false, false, 0 ); - - // Create the reset button - if( canReset ) - { - node->CreateValueButton( ValueID::ValueGenre_System, GetCommandClassId(), _instance, MeterIndex_Reset, "Reset", 0 ); - } - - Log::Write( LogLevel_Info, GetNodeId(), "Received Meter supported report from node %d, %s", GetNodeId(), msg.c_str() ); - return true; - } - - return false; -} //----------------------------------------------------------------------------- // // Read the reported meter value //----------------------------------------------------------------------------- -bool Meter::HandleReport -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance -) -{ - // Import or Export (only valid in version > 1) - bool exporting = false; - if( GetVersion() > 1 ) - { - exporting = ((_data[1] & 0x60) == 0x40 ); - if( ValueBool* value = static_cast( GetValue( _instance, MeterIndex_Exporting ) ) ) - { - value->OnValueRefreshed( exporting ); - value->Release(); - } - } - - // Get the value and scale - uint8 scale; - uint8 precision = 0; - string valueStr = ExtractValue( &_data[2], &scale, &precision ); - - if (scale > 7) /* size of c_electricityLabels, c_electricityUnits, c_gasUnits, c_waterUnits */ - { - Log::Write (LogLevel_Warning, GetNodeId(), "Scale was greater than range. Setting to Invalid"); - scale = 7; - } - - - if( GetVersion() == 1 ) - { - // In version 1, we don't know the scale until we get the first value report - string label; - string units; - int8 meterType = (MeterType)(_data[1] & 0x1f); - if (meterType > 4) /* size of c_meterTypes */ - { - Log::Write (LogLevel_Warning, GetNodeId(), "meterType Value was greater than range. Dropping Message"); - return false; - } - - switch( (MeterType)(_data[1] & 0x1f) ) - { - case MeterType_Electric: - { - // Electricity Meter - label = c_electricityLabels[scale]; - units = c_electricityUnits[scale]; - break; - } - case MeterType_Gas: - { - // Gas Meter - label = c_meterTypes[MeterType_Gas]; - units = c_gasUnits[scale]; - break; - } - case MeterType_Water: - { - // Water Meter - label = c_meterTypes[MeterType_Water]; - units = c_waterUnits[scale]; - break; - } - default: + bool Meter::HandleReport(uint8 const* _data, uint32 const _length, uint32 const _instance) { - break; - } - } - if( ValueDecimal* value = static_cast( GetValue( _instance, 0 ) ) ) - { - Log::Write( LogLevel_Info, GetNodeId(), "Received Meter report from node %d: %s=%s%s", GetNodeId(), label.c_str(), valueStr.c_str(), units.c_str() ); - value->SetLabel( label ); - value->SetUnits( units ); - value->OnValueRefreshed( valueStr ); - if( value->GetPrecision() != precision ) - { - value->SetPrecision( precision ); - } - value->Release(); - } - } - else - { - // Version 2 and above - uint8 baseIndex = scale << 2; - if( GetVersion() > 2 ) - { - // In version 3, an extra scale bit is stored in the meter type byte. - scale |= ((_data[1]&0x80)>>5); - baseIndex = scale << 2; - } + // Get the value and scale + uint8 scale; + uint8 precision = 0; + string valueStr = ExtractValue(&_data[2], &scale, &precision); + scale = GetScale(_data, _length); + int8 meterType = (MeterType) (_data[1] & 0x1f); - if( ValueDecimal* value = static_cast( GetValue( _instance, baseIndex ) ) ) - { - Log::Write( LogLevel_Info, GetNodeId(), "Received Meter report from node %d: %s%s=%s%s", GetNodeId(), exporting ? "Exporting ": "", value->GetLabel().c_str(), valueStr.c_str(), value->GetUnits().c_str() ); - value->OnValueRefreshed( valueStr ); - if( value->GetPrecision() != precision ) - { - value->SetPrecision( precision ); - } - value->Release(); + uint16_t index = (((meterType -1) * 16) + scale); - // Read any previous value and time delta - uint8 size = _data[2] & 0x07; - uint16 delta = (uint16)( (_data[3+size]<<8) | _data[4+size]); + if (MeterTypes.count(index) == 0) { + Log::Write(LogLevel_Warning, GetNodeId(), "MeterTypes Index is out of range/not valid - %d", index); + return false; + } - if( delta ) - { - // There is only a previous value if the time delta is non-zero - ValueDecimal* previous = static_cast( GetValue( _instance, baseIndex+1 ) ); - if( NULL == previous ) + Log::Write(LogLevel_Info, GetNodeId(), "Received Meter Report for %s (%d) with Units %s (%d) on Index %d: %s",MeterTypes.at(index).Label.c_str(), meterType, MeterTypes.at(index).Unit.c_str(), scale, index, valueStr.c_str()); + + Internal::VC::ValueDecimal* value = static_cast(GetValue(_instance, index)); + if (!value && (GetVersion() == 1)) { - // We need to create a value to hold the previous - if( Node* node = GetNodeUnsafe() ) + if (Node* node = GetNodeUnsafe()) { - node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, baseIndex+1, "Previous Reading", value->GetUnits().c_str(), true, false, "0.0", 0 ); - previous = static_cast( GetValue( _instance, baseIndex+1 ) ); + Log::Write(LogLevel_Info, GetNodeId(), "Creating Version 1 MeterType %s (%d) with Unit %s (%d) at Index %d", MeterTypes.at(index).Label.c_str(), meterType, MeterTypes.at(index).Unit.c_str(), scale, index); + node->CreateValueDecimal(ValueID::ValueGenre_User, GetCommandClassId(), _instance, index, MeterTypes.at(index).Label, MeterTypes.at(index).Unit, true, false, "0.0", 0); + value = static_cast(GetValue(_instance, index)); } + } else if (!value) { + Log::Write(LogLevel_Warning, GetNodeId(), "Can't Find a ValueID Index for %s (%d) with Unit %s (%d) - Index %d", MeterTypes.at(index).Label.c_str(), meterType, MeterTypes.at(index).Unit.c_str(), scale, index); + return false; } - if( previous ) + value->OnValueRefreshed(valueStr); + if (value->GetPrecision() != precision) { - precision = 0; - valueStr = ExtractValue( &_data[2], &scale, &precision, 3+size ); - Log::Write( LogLevel_Info, GetNodeId(), " Previous value was %s%s, received %d seconds ago.", valueStr.c_str(), previous->GetUnits().c_str(), delta ); - previous->OnValueRefreshed( valueStr ); - if( previous->GetPrecision() != precision ) + value->SetPrecision(precision); + } + value->Release(); + bool exporting = false; + if (GetVersion() > 1) + { + exporting = ((_data[1] & 0x60) == 0x40); + if (Internal::VC::ValueBool* value = static_cast(GetValue(_instance, ValueID_Index_Meter::Exporting))) { - previous->SetPrecision( precision ); + value->OnValueRefreshed(exporting); + value->Release(); } - previous->Release(); } - // Time delta - ValueInt* interval = static_cast( GetValue( _instance, baseIndex+2 ) ); - if( NULL == interval ) +#if 0 + /* Are Previous Values Important? */ + // Read any previous value and time delta + uint8 size = _data[2] & 0x07; + uint16 delta = (uint16) ((_data[3 + size] << 8) | _data[4 + size]); + + if (delta) { - // We need to create a value to hold the time delta - if( Node* node = GetNodeUnsafe() ) + // There is only a previous value if the time delta is non-zero + Internal::VC::ValueDecimal* previous = static_cast(GetValue(_instance, baseIndex + 1)); + if ( NULL == previous) { - node->CreateValueInt( ValueID::ValueGenre_User, GetCommandClassId(), _instance, baseIndex+2, "Interval", "seconds", true, false, 0, 0 ); - interval = static_cast( GetValue( _instance, baseIndex+2 ) ); + // We need to create a value to hold the previous + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueDecimal(ValueID::ValueGenre_User, GetCommandClassId(), _instance, baseIndex + 1, "Previous Reading", value->GetUnits().c_str(), true, false, "0.0", 0); + previous = static_cast(GetValue(_instance, baseIndex + 1)); + } + } + if (previous) + { + precision = 0; + valueStr = ExtractValue(&_data[2], &scale, &precision, 3 + size); + Log::Write(LogLevel_Info, GetNodeId(), " Previous value was %s%s, received %d seconds ago.", valueStr.c_str(), previous->GetUnits().c_str(), delta); + previous->OnValueRefreshed(valueStr); + if (previous->GetPrecision() != precision) + { + previous->SetPrecision(precision); + } + previous->Release(); + } + + // Time delta + Internal::VC::ValueInt* interval = static_cast(GetValue(_instance, baseIndex + 2)); + if ( NULL == interval) + { + // We need to create a value to hold the time delta + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueInt(ValueID::ValueGenre_User, GetCommandClassId(), _instance, baseIndex + 2, "Interval", "seconds", true, false, 0, 0); + interval = static_cast(GetValue(_instance, baseIndex + 2)); + } + } + if (interval) + { + interval->OnValueRefreshed((int32) delta); + interval->Release(); } } - if( interval ) - { - interval->OnValueRefreshed( (int32)delta ); - interval->Release(); - } +#endif + return true; } - } - } - - return true; -} //----------------------------------------------------------------------------- // // Set the device's scale, or reset its accumulated values. //----------------------------------------------------------------------------- -bool Meter::SetValue -( - Value const& _value -) -{ - if( MeterIndex_Reset == _value.GetID().GetIndex() ) - { - ValueButton const* button = static_cast(&_value); - if( button->IsPressed() ) - { - Msg* msg = new Msg( "MeterCmd_Reset", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->SetInstance( this, _value.GetID().GetInstance() ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( MeterCmd_Reset ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - return true; - } - } + bool Meter::SetValue(Internal::VC::Value const& _value) + { + if (ValueID_Index_Meter::Reset == _value.GetID().GetIndex()) + { + Internal::VC::ValueButton const* button = static_cast(&_value); + if (button->IsPressed()) + { + Msg* msg = new Msg("MeterCmd_Reset", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->SetInstance(this, _value.GetID().GetInstance()); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(MeterCmd_Reset); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return true; + } + } - return false; -} + return false; + } -//----------------------------------------------------------------------------- -// -// Create the values managed by this command class -//----------------------------------------------------------------------------- -void Meter::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, "Unknown", "", true, false, "0.0", 0 ); - } -} + //----------------------------------------------------------------------------- + // + // Decode The Scale as its all over the place in different versions + //----------------------------------------------------------------------------- + + int32_t Meter::GetScale(uint8_t const *_data, uint32_t const _length) { + uint8 scale = 0; + //uint8 size = (_data[2] & 0x07); + if (GetVersion() >= 1) { + scale = ((_data[2] & 0x18) >> 3); + } + if (GetVersion() >= 3) { + scale |= ((_data[1] & 0x80) >> 5); + } + if (GetVersion() >= 4) { + /* 4.55.4 - Bit 7 indicates to use Scale 2 Field */ + if (scale == 7) { + scale = (_data[_length-2] + 8); + } + } + return scale; + } + + + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/Meter.h b/cpp/src/command_classes/Meter.h index 0f9c9b6db8..258cf706bb 100644 --- a/cpp/src/command_classes/Meter.h +++ b/cpp/src/command_classes/Meter.h @@ -32,42 +32,60 @@ namespace OpenZWave { - class ValueDecimal; - - /** \brief Implements COMMAND_CLASS_METER (0x32), a Z-Wave device command class. - * \ingroup CommandClass - */ - class Meter: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Meter( _homeId, _nodeId ); } - virtual ~Meter(){} - - static uint8 const StaticGetCommandClassId(){ return 0x32; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_METER"; } - - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool SetValue( Value const& _value ); - virtual uint8 GetMaxVersion(){ return 3; } + namespace CC + { + /** \brief Implements COMMAND_CLASS_METER (0x32), a Z-Wave device command class. + * \ingroup CommandClass + */ + class Meter: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new Meter(_homeId, _nodeId); + } + virtual ~Meter() + { + } - protected: - virtual void CreateVars( uint8 const _instance ); + static uint8 const StaticGetCommandClassId() + { + return 0x32; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_METER"; + } - private: - Meter( uint32 const _homeId, uint8 const _nodeId ); - - bool HandleSupportedReport( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - bool HandleReport( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - - }; + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool SetValue(Internal::VC::Value const& _value) override; + virtual uint8 GetMaxVersion() override + { + return 5; + } + private: + Meter(uint32 const _homeId, uint8 const _nodeId); + int32_t GetScale(uint8_t const *_data, uint32_t const_length); + bool HandleSupportedReport(uint8 const* _data, uint32 const _length, uint32 const _instance = 1); + bool HandleReport(uint8 const* _data, uint32 const _length, uint32 const _instance = 1); + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave - #endif diff --git a/cpp/src/command_classes/MeterPulse.cpp b/cpp/src/command_classes/MeterPulse.cpp index 31c43ae3bc..cf6cd18d22 100644 --- a/cpp/src/command_classes/MeterPulse.cpp +++ b/cpp/src/command_classes/MeterPulse.cpp @@ -35,109 +35,100 @@ #include "value_classes/ValueInt.h" -using namespace OpenZWave; - -enum MeterPulseCmd +namespace OpenZWave { - MeterPulseCmd_Get = 0x04, - MeterPulseCmd_Report = 0x05 -}; + namespace Internal + { + namespace CC + { + + enum MeterPulseCmd + { + MeterPulseCmd_Get = 0x04, + MeterPulseCmd_Report = 0x05 + }; //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool MeterPulse::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _requestFlags & RequestFlag_Dynamic ) - { - return RequestValue( _requestFlags, 0, _instance, _queue ); - } + bool MeterPulse::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_requestFlags & RequestFlag_Dynamic) + { + return RequestValue(_requestFlags, 0, _instance, _queue); + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool MeterPulse::RequestValue -( - uint32 const _requestFlags, - uint16 const _dummy1, // = 0 (not used) - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Msg* msg = new Msg( "MeterPulseCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( MeterPulseCmd_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "MeterPulseCmd_Get Not Supported on this node"); - } - return false; -} + bool MeterPulse::RequestValue(uint32 const _requestFlags, uint16 const _dummy1, // = 0 (not used) + uint8 const _instance, Driver::MsgQueue const _queue) + { + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Msg* msg = new Msg("MeterPulseCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(MeterPulseCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "MeterPulseCmd_Get Not Supported on this node"); + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool MeterPulse::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if( MeterPulseCmd_Report == (MeterPulseCmd)_data[0] ) - { - int32 count = 0; - for( uint8 i=0; i<4; ++i ) - { - count <<= 8; - count |= (uint32)_data[i+1]; - } + bool MeterPulse::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) + { + if (MeterPulseCmd_Report == (MeterPulseCmd) _data[0]) + { + int32 count = 0; + for (uint8 i = 0; i < 4; ++i) + { + count <<= 8; + count |= (uint32) _data[i + 1]; + } - Log::Write( LogLevel_Info, GetNodeId(), "Received a meter pulse count: Count=%d", count ); - if( ValueInt* value = static_cast( GetValue( _instance, 0 ) ) ) - { - value->OnValueRefreshed( count ); - value->Release(); - } + Log::Write(LogLevel_Info, GetNodeId(), "Received a meter pulse count: Count=%d", count); + if (Internal::VC::ValueInt* value = static_cast(GetValue(_instance, ValueID_Index_MeterPulse::Count))) + { + value->OnValueRefreshed(count); + value->Release(); + } - return true; - } + return true; + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void MeterPulse::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - node->CreateValueInt( ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, "Count", "", true, false, 0, 0 ); - } -} - - + void MeterPulse::CreateVars(uint8 const _instance) + { + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueInt(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_MeterPulse::Count, "Count", "", true, false, 0, 0); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/MeterPulse.h b/cpp/src/command_classes/MeterPulse.h index 91990b2ca7..7678974f1b 100644 --- a/cpp/src/command_classes/MeterPulse.h +++ b/cpp/src/command_classes/MeterPulse.h @@ -32,34 +32,58 @@ namespace OpenZWave { - class ValueInt; - - /** \brief Implements COMMAND_CLASS_METER_PULSE (0x35), a Z-Wave device command class. - * \ingroup CommandClass - */ - class MeterPulse: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new MeterPulse( _homeId, _nodeId ); } - virtual ~MeterPulse(){} + namespace CC + { - static uint8 const StaticGetCommandClassId(){ return 0x35; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_METER_PULSE"; } + /** \brief Implements COMMAND_CLASS_METER_PULSE (0x35), a Z-Wave device command class. + * \ingroup CommandClass + */ + class MeterPulse: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new MeterPulse(_homeId, _nodeId); + } + virtual ~MeterPulse() + { + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); + static uint8 const StaticGetCommandClassId() + { + return 0x35; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_METER_PULSE"; + } - protected: - virtual void CreateVars( uint8 const _instance ); + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; - private: - MeterPulse( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} - }; + protected: + virtual void CreateVars(uint8 const _instance) override; + private: + MeterPulse(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + } + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/MultiChannelAssociation.cpp b/cpp/src/command_classes/MultiChannelAssociation.cpp index cc5f00be31..9e2126fbc1 100644 --- a/cpp/src/command_classes/MultiChannelAssociation.cpp +++ b/cpp/src/command_classes/MultiChannelAssociation.cpp @@ -35,431 +35,394 @@ #include "Group.h" #include "platform/Log.h" -using namespace OpenZWave; - -enum MultiChannelAssociationCmd +namespace OpenZWave { - MultiChannelAssociationCmd_Set = 0x01, - MultiChannelAssociationCmd_Get = 0x02, - MultiChannelAssociationCmd_Report = 0x03, - MultiChannelAssociationCmd_Remove = 0x04, - MultiChannelAssociationCmd_GroupingsGet = 0x05, - MultiChannelAssociationCmd_GroupingsReport = 0x06 -}; + namespace Internal + { + namespace CC + { + + enum MultiChannelAssociationCmd + { + MultiChannelAssociationCmd_Set = 0x01, + MultiChannelAssociationCmd_Get = 0x02, + MultiChannelAssociationCmd_Report = 0x03, + MultiChannelAssociationCmd_Remove = 0x04, + MultiChannelAssociationCmd_GroupingsGet = 0x05, + MultiChannelAssociationCmd_GroupingsReport = 0x06 + }; // // Constructor //----------------------------------------------------------------------------- -MultiChannelAssociation::MultiChannelAssociation -( - uint32 const _homeId, - uint8 const _nodeId -): - CommandClass( _homeId, _nodeId ), - m_queryAll(false), - m_numGroups(0) -{ - m_com.EnableFlag(COMPAT_FLAG_MCA_FORCEINSTANCES, true); - SetStaticRequest( StaticRequest_Values ); -} + MultiChannelAssociation::MultiChannelAssociation(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId), m_queryAll(false), m_numGroups(0) + { + m_com.EnableFlag(COMPAT_FLAG_MCA_FORCEINSTANCES, true); + SetStaticRequest(StaticRequest_Values); + } //----------------------------------------------------------------------------- // // Read the saved association data //----------------------------------------------------------------------------- -void MultiChannelAssociation::ReadXML -( - TiXmlElement const* _ccElement -) -{ - CommandClass::ReadXML( _ccElement ); - - TiXmlElement const* associationsElement = _ccElement->FirstChildElement(); - while( associationsElement ) - { - char const* str = associationsElement->Value(); - if( str && !strcmp( str, "Associations" ) ) - { - int intVal; - if( TIXML_SUCCESS == associationsElement->QueryIntAttribute( "num_groups", &intVal ) ) + void MultiChannelAssociation::ReadXML(TiXmlElement const* _ccElement) { - m_numGroups = (uint8)intVal; - } + CommandClass::ReadXML(_ccElement); - TiXmlElement const* groupElement = associationsElement->FirstChildElement(); - while( groupElement ) - { - if( Node* node = GetNodeUnsafe() ) + TiXmlElement const* associationsElement = _ccElement->FirstChildElement(); + while (associationsElement) { - Group* group = new Group( GetHomeId(), GetNodeId(), groupElement ); - node->AddGroup( group ); - } + char const* str = associationsElement->Value(); + if (str && !strcmp(str, "Associations")) + { + int intVal; + if (TIXML_SUCCESS == associationsElement->QueryIntAttribute("num_groups", &intVal)) + { + m_numGroups = (uint8) intVal; + } - groupElement = groupElement->NextSiblingElement(); - } + TiXmlElement const* groupElement = associationsElement->FirstChildElement(); + while (groupElement) + { + if (Node* node = GetNodeUnsafe()) + { + Group* group = new Group(GetHomeId(), GetNodeId(), groupElement); + node->AddGroup(group); + } + + groupElement = groupElement->NextSiblingElement(); + } - break; - } + break; + } - associationsElement = associationsElement->NextSiblingElement(); - } + associationsElement = associationsElement->NextSiblingElement(); + } -} + } //----------------------------------------------------------------------------- // // Save the association data //----------------------------------------------------------------------------- -void MultiChannelAssociation::WriteXML -( - TiXmlElement* _ccElement -) -{ - CommandClass::WriteXML( _ccElement ); + void MultiChannelAssociation::WriteXML(TiXmlElement* _ccElement) + { + CommandClass::WriteXML(_ccElement); - if( Node* node = GetNodeUnsafe() ) - { - TiXmlElement* associationsElement = new TiXmlElement( "Associations" ); + if (Node* node = GetNodeUnsafe()) + { + TiXmlElement* associationsElement = new TiXmlElement("Associations"); - char str[8]; - snprintf( str, 8, "%d", m_numGroups ); - associationsElement->SetAttribute( "num_groups", str ); + char str[8]; + snprintf(str, 8, "%d", m_numGroups); + associationsElement->SetAttribute("num_groups", str); - _ccElement->LinkEndChild( associationsElement ); - node->WriteGroups( associationsElement ); - } -} + _ccElement->LinkEndChild(associationsElement); + node->WriteGroups(associationsElement); + } + } //----------------------------------------------------------------------------- // // Nothing to do for Association //----------------------------------------------------------------------------- -bool MultiChannelAssociation::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) ) - { - // Request the supported group info - return RequestValue( _requestFlags, 0, _instance, _queue ); - } + bool MultiChannelAssociation::RequestState(uint32 const _requestFlags, uint8 const _endPoint, Driver::MsgQueue const _queue) + { + if ((_requestFlags & RequestFlag_Static) && HasStaticRequest(StaticRequest_Values)) + { + // Request the supported group info + return RequestValue(_requestFlags, 0, _endPoint, _queue); + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Nothing to do for Association //----------------------------------------------------------------------------- -bool MultiChannelAssociation::RequestValue -( - uint32 const _requestFlags, - uint16 const _dummy1, // = 0 (not used) - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _instance != 1 ) - { - // This command class doesn't work with multiple instances - return false; - } - // Request the supported group info - Msg* msg = new Msg( "MultiChannelAssociationCmd_GroupingsGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( MultiChannelAssociationCmd_GroupingsGet ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; -} + bool MultiChannelAssociation::RequestValue(uint32 const _requestFlags, uint16 const _dummy1, // = 0 (not used) + uint8 const _endPoint, Driver::MsgQueue const _queue) + { + if (_endPoint != 1) + { + // This command class doesn't work with multiple End Points + return false; + } + // Request the supported group info + Msg* msg = new Msg("MultiChannelAssociationCmd_GroupingsGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(MultiChannelAssociationCmd_GroupingsGet); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } //----------------------------------------------------------------------------- // // Request the contents of each group in turn //----------------------------------------------------------------------------- -void MultiChannelAssociation::RequestAllGroups -( - uint32 const _requestFlags -) -{ - m_queryAll = true; + void MultiChannelAssociation::RequestAllGroups(uint32 const _requestFlags) + { + m_queryAll = true; - // Request the contents of the individual groups in turn. - if( m_numGroups == 0xff ) - { - // We start with group 255, and will then move to group 1, 2 etc and stop when we find a group with a maxAssociations of zero. - Log::Write( LogLevel_Info, GetNodeId(), "Number of association groups reported for node %d is 255, which requires special case handling.", GetNodeId() ); - QueryGroup( 0xff, _requestFlags ); - } - else - { - // We start with group 1, and will then move to group 2, 3 etc and stop when the group index is greater than m_numGroups. - Log::Write( LogLevel_Info, GetNodeId(), "Number of association groups reported for node %d is %d.", GetNodeId(), m_numGroups ); - QueryGroup( 1, _requestFlags ); - } -} + // Request the contents of the individual groups in turn. + if (m_numGroups == 0xff) + { + // We start with group 255, and will then move to group 1, 2 etc and stop when we find a group with a maxAssociations of zero. + Log::Write(LogLevel_Info, GetNodeId(), "Number of association groups reported for node %d is 255, which requires special case handling.", GetNodeId()); + QueryGroup(0xff, _requestFlags); + } + else + { + // We start with group 1, and will then move to group 2, 3 etc and stop when the group index is greater than m_numGroups. + Log::Write(LogLevel_Info, GetNodeId(), "Number of association groups reported for node %d is %d.", GetNodeId(), m_numGroups); + QueryGroup(1, _requestFlags); + } + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool MultiChannelAssociation::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - bool handled = false; - uint32 i; - - if( Node* node = GetNodeUnsafe() ) - { - if( MultiChannelAssociationCmd_GroupingsReport == (MultiChannelAssociationCmd)_data[0] ) - { - // Retrieve the number of groups this device supports. - // The groups will be queried with the session data. - m_numGroups = _data[1]; - Log::Write( LogLevel_Info, GetNodeId(), "Received Multi Instance Association Groupings report from node %d. Number of groups is %d", GetNodeId(), m_numGroups ); - ClearStaticRequest( StaticRequest_Values ); - handled = true; - } - else if( MultiChannelAssociationCmd_Report == (MultiChannelAssociationCmd)_data[0] ) - { - // Get the group info - uint8 groupIdx = _data[1]; - uint8 maxAssociations = _data[2]; // If the maxAssociations is zero, this is not a supported group. - uint8 numReportsToFollow = _data[3]; // If a device supports a lot of associations, they may come in more than one message. - - if( maxAssociations ) + bool MultiChannelAssociation::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _endPoint // = 1 + ) { - if( _length >= 5 ) + bool handled = false; + uint32 i; + + if (Node* node = GetNodeUnsafe()) { - // format: - // node A - // node B - // 0x00 Marker - // node C - // instance # - // node D - // instance # - Log::Write( LogLevel_Info, GetNodeId(), "Received Multi Instance Association report from node %d, group %d", GetNodeId(), groupIdx ); - Log::Write( LogLevel_Info, GetNodeId(), " The group contains:" ); - bool pastMarker = false; - for( i=0; i < _length-5; ++i ) - { - if (_data[i+4] == 0x00) + if (MultiChannelAssociationCmd_GroupingsReport == (MultiChannelAssociationCmd) _data[0]) + { + // Retrieve the number of groups this device supports. + // The groups will be queried with the session data. + m_numGroups = _data[1]; + Log::Write(LogLevel_Info, GetNodeId(), "Received MULTI_CHANNEL_ASSOCIATION_GROUPINGS_REPORT from node %d. Number of groups is %d", GetNodeId(), m_numGroups); + ClearStaticRequest(StaticRequest_Values); + handled = true; + } + else if (MultiChannelAssociationCmd_Report == (MultiChannelAssociationCmd) _data[0]) + { + // Get the group info + uint8 groupIdx = _data[1]; + uint8 maxAssociations = _data[2]; // If the maxAssociations is zero, this is not a supported group. + uint8 numReportsToFollow = _data[3]; // If a device supports a lot of associations, they may come in more than one message. + + if (maxAssociations) { - pastMarker = true; - } - else + if (_length >= 5) + { + // format: + // node A + // node B + // 0x00 Marker + // node C + // End Point # + // node D + // End Point # + Log::Write(LogLevel_Info, GetNodeId(), "Received MULTI_CHANNEL_ASSOCIATION_REPORT from node %d, group %d", GetNodeId(), groupIdx); + Log::Write(LogLevel_Info, GetNodeId(), " The group contains:"); + bool pastMarker = false; + for (i = 0; i < _length - 5; ++i) + { + if (_data[i + 4] == 0x00) + { + pastMarker = true; + } + else + { + if (!pastMarker) + { + Log::Write(LogLevel_Info, GetNodeId(), " Node %d", _data[i + 4]); + InstanceAssociation association; + association.m_nodeId = _data[i + 4]; + association.m_instance = 0x00; + m_pendingMembers.push_back(association); + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), " Node %d End Point %d", _data[i + 4], _data[i + 5]); + InstanceAssociation association; + association.m_nodeId = _data[i + 4]; + association.m_instance = _data[i + 5]; + m_pendingMembers.push_back(association); + i++; + } + } + } + } + + if (numReportsToFollow) + { + // We're expecting more reports for this group + Log::Write(LogLevel_Info, GetNodeId(), "%d more association reports expected for node %d, group %d", numReportsToFollow, GetNodeId(), groupIdx); + return true; + } + else + { + // No more reports to come for this group, so we can apply the pending list + Group* group = node->GetGroup(groupIdx); + if ( NULL == group) + { + // Group has not been created yet + group = new Group(GetHomeId(), GetNodeId(), groupIdx, maxAssociations); + node->AddGroup(group); + } + group->SetMultiInstance(true); + + // Update the group with its new contents + group->OnGroupChanged(m_pendingMembers); + m_pendingMembers.clear(); + } + } + else { - if (!pastMarker) + // maxAssociations is zero, so we've reached the end of the query process + Log::Write(LogLevel_Info, GetNodeId(), "Max associations for node %d, group %d is zero. Querying associations for this node is complete.", GetNodeId(), groupIdx); + node->AutoAssociate(); + m_queryAll = false; + } + + if (m_queryAll) + { + // Work out which is the next group we will query. + // If we are currently on group 255, the next group will be 1. + uint8 nextGroup = groupIdx + 1; + if (!nextGroup) + { + nextGroup = 1; + } + + if (nextGroup <= m_numGroups) { - Log::Write( LogLevel_Info, GetNodeId(), " Node %d", _data[i+4] ); - InstanceAssociation association; - association.m_nodeId=_data[i+4]; - association.m_instance=0x00; - m_pendingMembers.push_back( association ); - } - else + // Query the next group + QueryGroup(nextGroup, 0); + } + else { - Log::Write( LogLevel_Info, GetNodeId(), " Node %d instance %d", _data[i+4], _data[i+5] ); - InstanceAssociation association; - association.m_nodeId=_data[i+4]; - association.m_instance=_data[i+5]; - m_pendingMembers.push_back( association ); - i++; + // We're all done + Log::Write(LogLevel_Info, GetNodeId(), "Querying associations for node %d is complete.", GetNodeId()); + node->AutoAssociate(); + m_queryAll = false; } } - } - } - if( numReportsToFollow ) - { - // We're expecting more reports for this group - Log::Write( LogLevel_Info, GetNodeId(), "%d more association reports expected for node %d, group %d", numReportsToFollow, GetNodeId(), groupIdx ); - return true; - } - else - { - // No more reports to come for this group, so we can apply the pending list - Group* group = node->GetGroup( groupIdx ); - if( NULL == group ) - { - // Group has not been created yet - group = new Group( GetHomeId(), GetNodeId(), groupIdx, maxAssociations ); - node->AddGroup( group ); + handled = true; } - group->SetMultiInstance( true ); - - // Update the group with its new contents - group->OnGroupChanged( m_pendingMembers ); - m_pendingMembers.clear(); } - } - else - { - // maxAssociations is zero, so we've reached the end of the query process - Log::Write( LogLevel_Info, GetNodeId(), "Max associations for node %d, group %d is zero. Querying associations for this node is complete.", GetNodeId(), groupIdx ); - node->AutoAssociate(); - m_queryAll = false; + + return handled; } - if( m_queryAll ) +//----------------------------------------------------------------------------- +// +// Request details of an association group +//----------------------------------------------------------------------------- + void MultiChannelAssociation::QueryGroup(uint8 _groupIdx, uint32 const _requestFlags) { - // Work out which is the next group we will query. - // If we are currently on group 255, the next group will be 1. - uint8 nextGroup = groupIdx + 1; - if( !nextGroup ) - { - nextGroup = 1; - } - - if( nextGroup <= m_numGroups ) + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) { - // Query the next group - QueryGroup( nextGroup, 0 ); + Log::Write(LogLevel_Info, GetNodeId(), "Get MultiChannelAssociation for group %d of node %d", _groupIdx, GetNodeId()); + Msg* msg = new Msg("MultiChannelAssociationCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(MultiChannelAssociationCmd_Get); + msg->Append(_groupIdx); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return; } else { - // We're all done - Log::Write( LogLevel_Info, GetNodeId(), "Querying associations for node %d is complete.", GetNodeId() ); - node->AutoAssociate(); - m_queryAll = false; + Log::Write(LogLevel_Info, GetNodeId(), "MultiChannelAssociationCmd_Get Not Supported on this node"); } + return; } - handled = true; - } - } - - return handled; -} - -//----------------------------------------------------------------------------- -// -// Request details of an association group -//----------------------------------------------------------------------------- -void MultiChannelAssociation::QueryGroup -( - uint8 _groupIdx, - uint32 const _requestFlags -) -{ - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Log::Write( LogLevel_Info, GetNodeId(), "Get MultiChannelAssociation for group %d of node %d", _groupIdx, GetNodeId() ); - Msg* msg = new Msg( "MultiChannelAssociationCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( MultiChannelAssociationCmd_Get ); - msg->Append( _groupIdx ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - return; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "MultiChannelAssociationCmd_Get Not Supported on this node"); - } - return; -} - //----------------------------------------------------------------------------- // // Add an association between devices //----------------------------------------------------------------------------- -void MultiChannelAssociation::Set -( - uint8 _groupIdx, - uint8 _targetNodeId, - uint8 _instance -) -{ + void MultiChannelAssociation::Set(uint8 _groupIdx, uint8 _targetNodeId, uint8 _endPoint) + { - /* for Qubino devices, we should always set a Instance if its the ControllerNode, so MultChannelEncap works. - See Bug #857 */ - if ( ( m_com.GetFlagBool(COMPAT_FLAG_MCA_FORCEINSTANCES) == true ) - && ( _instance == 0 ) - && ( GetDriver()->GetControllerNodeId() == _targetNodeId ) ) - { - _instance = 0x01; - } + /* for Qubino devices, we should always set a End Point if its the ControllerNode, so MultChannelEncap works. - See Bug #857 */ + if ((m_com.GetFlagBool(COMPAT_FLAG_MCA_FORCEINSTANCES) == true) && (_endPoint == 0) && (GetDriver()->GetControllerNodeId() == _targetNodeId)) + { + _endPoint = 0x01; + } - Log::Write( LogLevel_Info, GetNodeId(), "MultiChannelAssociation::Set - Adding instance %d on node %d to group %d of node %d", - _instance, _targetNodeId, _groupIdx, GetNodeId() ); + Log::Write(LogLevel_Info, GetNodeId(), "MultiChannelAssociation::Set - Adding End Point %d on node %d to group %d of node %d", _endPoint, _targetNodeId, _groupIdx, GetNodeId()); - if ( _instance == 0x00 ) - { - Msg* msg = new Msg( "MultiChannelAssociationCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->Append( GetNodeId() ); - msg->Append( 4 ); - msg->Append( GetCommandClassId() ); - msg->Append( MultiChannelAssociationCmd_Set ); - msg->Append( _groupIdx ); - msg->Append( _targetNodeId ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - } - else - { - Msg* msg = new Msg( "MultiChannelAssociationCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->Append( GetNodeId() ); - msg->Append( 6 ); - msg->Append( GetCommandClassId() ); - msg->Append( MultiChannelAssociationCmd_Set ); - msg->Append( _groupIdx ); - msg->Append( 0x00 ); // marker - msg->Append( _targetNodeId ); - msg->Append( _instance ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - } -} + if (_endPoint == 0x00) + { + Msg* msg = new Msg("MultiChannelAssociationCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->Append(GetNodeId()); + msg->Append(4); + msg->Append(GetCommandClassId()); + msg->Append(MultiChannelAssociationCmd_Set); + msg->Append(_groupIdx); + msg->Append(_targetNodeId); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + } + else + { + Msg* msg = new Msg("MultiChannelAssociationCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->Append(GetNodeId()); + msg->Append(6); + msg->Append(GetCommandClassId()); + msg->Append(MultiChannelAssociationCmd_Set); + msg->Append(_groupIdx); + msg->Append(0x00); // marker + msg->Append(_targetNodeId); + msg->Append(_endPoint); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + } + } //----------------------------------------------------------------------------- // // Remove an association between devices //----------------------------------------------------------------------------- -void MultiChannelAssociation::Remove -( - uint8 _groupIdx, - uint8 _targetNodeId, - uint8 _instance -) -{ - Log::Write( LogLevel_Info, GetNodeId(), "MultiChannelAssociation::Remove - Removing instance %d on node %d from group %d of node %d", - _instance, _targetNodeId, _groupIdx, GetNodeId()); + void MultiChannelAssociation::Remove(uint8 _groupIdx, uint8 _targetNodeId, uint8 _endPoint) + { + Log::Write(LogLevel_Info, GetNodeId(), "MultiChannelAssociation::Remove - Removing End Point %d on node %d from group %d of node %d", _endPoint, _targetNodeId, _groupIdx, GetNodeId()); - if ( _instance == 0x00 ) - { - Msg* msg = new Msg( "MultiChannelAssociationCmd_Remove", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->Append( GetNodeId() ); - msg->Append( 4 ); - msg->Append( GetCommandClassId() ); - msg->Append( MultiChannelAssociationCmd_Remove ); - msg->Append( _groupIdx ); - msg->Append( _targetNodeId ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - } - else - { - Msg* msg = new Msg( "MultiChannelAssociationCmd_Remove", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->Append( GetNodeId() ); - msg->Append( 6 ); - msg->Append( GetCommandClassId() ); - msg->Append( MultiChannelAssociationCmd_Remove ); - msg->Append( _groupIdx ); - msg->Append( 0x00 ); // marker - msg->Append( _targetNodeId ); - msg->Append( _instance ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - } -} + if (_endPoint == 0x00) + { + Msg* msg = new Msg("MultiChannelAssociationCmd_Remove", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->Append(GetNodeId()); + msg->Append(4); + msg->Append(GetCommandClassId()); + msg->Append(MultiChannelAssociationCmd_Remove); + msg->Append(_groupIdx); + msg->Append(_targetNodeId); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + } + else + { + Msg* msg = new Msg("MultiChannelAssociationCmd_Remove", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->Append(GetNodeId()); + msg->Append(6); + msg->Append(GetCommandClassId()); + msg->Append(MultiChannelAssociationCmd_Remove); + msg->Append(_groupIdx); + msg->Append(0x00); // marker + msg->Append(_targetNodeId); + msg->Append(_endPoint); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/MultiChannelAssociation.h b/cpp/src/command_classes/MultiChannelAssociation.h index fd07e78bb6..94def6d994 100644 --- a/cpp/src/command_classes/MultiChannelAssociation.h +++ b/cpp/src/command_classes/MultiChannelAssociation.h @@ -34,44 +34,67 @@ namespace OpenZWave { - /** \brief Implements COMMAND_CLASS_MULTI_CHANNEL_ASSOCIATION (0x8E), a Z-Wave device command class. - * \ingroup CommandClass - */ - class MultiChannelAssociation: public CommandClass + namespace Internal { - friend class Group; - - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new MultiChannelAssociation( _homeId, _nodeId ); } - virtual ~MultiChannelAssociation(){} + namespace CC + { - static uint8 const StaticGetCommandClassId(){ return 0x8e; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_MULTI_CHANNEL_ASSOCIATION"; } + /** \brief Implements COMMAND_CLASS_MULTI_CHANNEL_ASSOCIATION (0x8E), a Z-Wave device command class. + * \ingroup CommandClass + */ + class MultiChannelAssociation: public CommandClass + { + friend class OpenZWave::Group; - // From CommandClass - virtual void ReadXML( TiXmlElement const* _ccElement ); - virtual void WriteXML( TiXmlElement* _ccElement ); - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new MultiChannelAssociation(_homeId, _nodeId); + } + virtual ~MultiChannelAssociation() + { + } - void RequestAllGroups( uint32 const _requestFlags ); - void Set( uint8 const _group, uint8 const _nodeId, uint8 const _instance ); - void Remove( uint8 const _group, uint8 const _nodeId, uint8 const _instance ); + static uint8 const StaticGetCommandClassId() + { + return 0x8e; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_MULTI_CHANNEL_ASSOCIATION"; + } - private: - MultiChannelAssociation( uint32 const _homeId, uint8 const _nodeId ); - void QueryGroup( uint8 _groupIdx, uint32 const _requestFlags ); - void AutoAssociate(); + // From CommandClass + virtual void ReadXML(TiXmlElement const* _ccElement) override; + virtual void WriteXML(TiXmlElement* _ccElement) override; + virtual bool RequestState(uint32 const _requestFlags, uint8 const _endPoint, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _endPoint, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _endPoint = 1) override; - bool m_queryAll; // When true, once a group has been queried, we request the next one. - uint8 m_numGroups; // Number of groups supported by the device. 255 is reported by certain manufacturers and requires special handling. - vector m_pendingMembers; // Used to build a list of group members from multiple reports - - }; + void RequestAllGroups(uint32 const _requestFlags); + void Set(uint8 const _group, uint8 const _nodeId, uint8 const _endPoint); + void Remove(uint8 const _group, uint8 const _nodeId, uint8 const _endPoint); + private: + MultiChannelAssociation(uint32 const _homeId, uint8 const _nodeId); + void QueryGroup(uint8 _groupIdx, uint32 const _requestFlags); + void AutoAssociate(); + + bool m_queryAll; // When true, once a group has been queried, we request the next one. + uint8 m_numGroups; // Number of groups supported by the device. 255 is reported by certain manufacturers and requires special handling. + vector m_pendingMembers; // Used to build a list of group members from multiple reports + + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/MultiCmd.cpp b/cpp/src/command_classes/MultiCmd.cpp index ac8ecd9ba9..dcd03c0f76 100644 --- a/cpp/src/command_classes/MultiCmd.cpp +++ b/cpp/src/command_classes/MultiCmd.cpp @@ -33,50 +33,82 @@ #include "Driver.h" #include "platform/Log.h" -using namespace OpenZWave; - +namespace OpenZWave +{ + namespace Internal + { + namespace CC + { //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool MultiCmd::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if( MultiCmdCmd_Encap == (MultiCmdCmd)_data[0] ) - { - Log::Write( LogLevel_Info, GetNodeId(), "Received encapsulated multi-command from node %d", GetNodeId() ); - - if( Node const* node = GetNodeUnsafe() ) - { - // Iterate over commands - uint8 base = 2; - for( uint8 i=0; i<_data[1]; ++i ) + bool MultiCmd::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) { - uint8 length = _data[base]; - uint8 commandClassId = _data[base+1]; - - if( CommandClass* pCommandClass = node->GetCommandClass( commandClassId, false ) ) + if (MultiCmdCmd_Encap == (MultiCmdCmd) _data[0]) { - pCommandClass->HandleMsg( &_data[base+2], length-1 ); - } + int commands; - if( CommandClass* pCommandClass = node->GetCommandClass( commandClassId, true ) ) - { - pCommandClass->HandleIncomingMsg( &_data[base+2], length-1 ); - } + if (_length < 3) + { + Log::Write(LogLevel_Error, GetNodeId(), "Multi-command frame received is invalid, _length is < 3"); + return false; + } + else + { + commands = _data[1]; + Log::Write(LogLevel_Info, GetNodeId(), "Multi-command frame received, encapsulates %d command(s)", commands); + } - base += (length + 1); - } - } + if (Node const *node = GetNodeUnsafe()) + { + // Iterate over commands + int base = 2; + // Highest possible index is _length minus two because + // array is zero-based and _data starts at second byte of command frame + int highest_index = _length - 2; + for (uint8 i = 1; i <= commands; ++i) + { + if (base > highest_index) + { + Log::Write(LogLevel_Error, GetNodeId(), + "Multi-command command part %d is invalid, frame is too short: base > highest_index (%d > %d)", + i, base, highest_index); + return false; + } + + uint8 length = _data[base]; + int end = base + length; + if (end > highest_index) + { + Log::Write(LogLevel_Error, GetNodeId(), + "Multi-command command part %d with base %d is invalid, end > highest_index (%d > %d)", + i, base, end, highest_index); + return false; + } + + uint8 commandClassId = _data[base + 1]; - Log::Write( LogLevel_Info, GetNodeId(), "End of encapsulated multi-command from node %d", GetNodeId() ); - return true; - } - return false; -} + if (CommandClass *pCommandClass = node->GetCommandClass(commandClassId)) + { + if (!pCommandClass->IsAfterMark()) + pCommandClass->HandleMsg(&_data[base + 2], length - 1); + else + pCommandClass->HandleIncomingMsg(&_data[base + 2], length - 1); + } + + base += (length + 1); + } + } + + Log::Write(LogLevel_Info, GetNodeId(), "Multi-command, all %d command(s) processed", commands); + return true; + } + return false; + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/MultiCmd.h b/cpp/src/command_classes/MultiCmd.h index 615e2b633c..2391572bfd 100644 --- a/cpp/src/command_classes/MultiCmd.h +++ b/cpp/src/command_classes/MultiCmd.h @@ -32,32 +32,58 @@ namespace OpenZWave { - /** \brief Implements COMMAND_CLASS_MULTI_CMD (0x8f), a Z-Wave device command class. - * \ingroup CommandClass - */ - class MultiCmd: public CommandClass + namespace Internal { - public: - enum MultiCmdCmd + namespace CC { - MultiCmdCmd_Encap = 0x01 - }; - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new MultiCmd( _homeId, _nodeId ); } - virtual ~MultiCmd(){} + /** \brief Implements COMMAND_CLASS_MULTI_CMD (0x8f), a Z-Wave device command class. + * \ingroup CommandClass + */ + class MultiCmd: public CommandClass + { + public: + enum MultiCmdCmd + { + MultiCmdCmd_Encap = 0x01 + }; - static uint8 const StaticGetCommandClassId(){ return 0x8f; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_MULTI_CMD"; } + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new MultiCmd(_homeId, _nodeId); + } + virtual ~MultiCmd() + { + } - // From CommandClass - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); + static uint8 const StaticGetCommandClassId() + { + return 0x8f; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_MULTI_CMD"; + } - private: - MultiCmd( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} - }; + // From CommandClass + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + private: + MultiCmd(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + } + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/MultiInstance.cpp b/cpp/src/command_classes/MultiInstance.cpp index 013b9a2a0d..a60f93cd42 100644 --- a/cpp/src/command_classes/MultiInstance.cpp +++ b/cpp/src/command_classes/MultiInstance.cpp @@ -37,647 +37,623 @@ #include "Node.h" #include "platform/Log.h" -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace CC + { // Reduced set of Generic Device classes sorted to reduce // the likely number of calls to MultiChannelCmd_EndPointFind. -uint8 const c_genericClass[] = -{ - 0x21, // Multilevel Sensor - 0x20, // Binary Sensor - 0x31, // Meter - 0x08, // Thermostat - 0x11, // Multilevel Switch - 0x10, // Binary Switch - 0x12, // Remote Switch - 0xa1, // Alarm Sensor - 0x16, // Ventilation - 0x30, // Pulse Meter - 0x40, // Entry Control - 0x13, // Toggle Switch - 0x03, // AV Control Point - 0x04, // Display - 0x00 // End of list -}; - -char const* c_genericClassName[] = -{ - "Multilevel Sensor", - "Binary Sensor", - "Meter", - "Thermostat", - "Multilevel Switch", - "Binary Switch", - "Remote Switch", - "Alarm Sensor", - "Ventilation", - "Pulse Meter", - "Entry Control", - "Toggle Switch", - "AV Control Point", - "Display", - "Unknown" -}; + uint8 const c_genericClass[] = + { 0x21, // Multilevel Sensor + 0x20, // Binary Sensor + 0x31, // Meter + 0x08, // Thermostat + 0x11, // Multilevel Switch + 0x10, // Binary Switch + 0x12, // Remote Switch + 0xa1, // Alarm Sensor + 0x16, // Ventilation + 0x30, // Pulse Meter + 0x40, // Entry Control + 0x13, // Toggle Switch + 0x03, // AV Control Point + 0x04, // Display + 0x00 // End of list + }; + + char const* c_genericClassName[] = + { "Multilevel Sensor", "Binary Sensor", "Meter", "Thermostat", "Multilevel Switch", "Binary Switch", "Remote Switch", "Alarm Sensor", "Ventilation", "Pulse Meter", "Entry Control", "Toggle Switch", "AV Control Point", "Display", "Unknown" }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -MultiInstance::MultiInstance -( - uint32 const _homeId, - uint8 const _nodeId -): -CommandClass( _homeId, _nodeId ), -m_numEndPoints( 0 ) -{ - m_com.EnableFlag(COMPAT_FLAG_MI_MAPROOTTOENDPOINT, false); - m_com.EnableFlag(COMPAT_FLAG_MI_FORCEUNIQUEENDPOINTS, false); - m_com.EnableFlag(COMPAT_FLAG_MI_IGNMCCAPREPORTS, false); - m_com.EnableFlag(COMPAT_FLAG_MI_ENDPOINTHINT, 0); -} + MultiInstance::MultiInstance(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId), m_numEndPoints(0) + { + m_com.EnableFlag(COMPAT_FLAG_MI_MAPROOTTOENDPOINT, false); + m_com.EnableFlag(COMPAT_FLAG_MI_FORCEUNIQUEENDPOINTS, false); + m_com.EnableFlag(COMPAT_FLAG_MI_IGNMCCAPREPORTS, false); + m_com.EnableFlag(COMPAT_FLAG_MI_ENDPOINTHINT, 0); + m_com.EnableFlag(COMPAT_FLAG_MI_REMOVECC, false); + } //----------------------------------------------------------------------------- // // Request number of instances of the specified command class from the device //----------------------------------------------------------------------------- -bool MultiInstance::RequestInstances -( -) -{ - bool res = false; - - if( GetVersion() == 1 ) - { - if( Node* node = GetNodeUnsafe() ) - { - // MULTI_INSTANCE - for( map::const_iterator it = node->m_commandClassMap.begin(); it != node->m_commandClassMap.end(); ++it ) + bool MultiInstance::RequestInstances() { - CommandClass* cc = it->second; - if( cc->GetCommandClassId() == NoOperation::StaticGetCommandClassId() ) + bool res = false; + + if (GetVersion() == 1) { - continue; + if (Node* node = GetNodeUnsafe()) + { + // MULTI_INSTANCE + for (map::const_iterator it = node->m_commandClassMap.begin(); it != node->m_commandClassMap.end(); ++it) + { + CommandClass* cc = it->second; + if (cc->GetCommandClassId() == NoOperation::StaticGetCommandClassId()) + { + continue; + } + if (cc->HasStaticRequest(StaticRequest_Instances)) + { + Log::Write(LogLevel_Info, GetNodeId(), "MultiInstanceCmd_Get for %s", cc->GetCommandClassName().c_str()); + + Msg* msg = new Msg("MultiInstanceCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(MultiInstanceCmd_Get); + msg->Append(cc->GetCommandClassId()); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Query); + res = true; + } + } + } } - if( cc->HasStaticRequest( StaticRequest_Instances ) ) + else { - Log::Write( LogLevel_Info, GetNodeId(), "MultiInstanceCmd_Get for %s", cc->GetCommandClassName().c_str() ); - - Msg* msg = new Msg( "MultiInstanceCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( MultiInstanceCmd_Get ); - msg->Append( cc->GetCommandClassId() ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Query ); + // MULTI_CHANNEL + + Log::Write(LogLevel_Info, GetNodeId(), "MultiChannelCmd_EndPointGet for node %d", GetNodeId()); + + Msg* msg = new Msg("MultiChannelCmd_EndPointGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(MultiChannelCmd_EndPointGet); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Query); res = true; } + + return res; } - } - } - else - { - // MULTI_CHANNEL - - Log::Write( LogLevel_Info, GetNodeId(), "MultiChannelCmd_EndPointGet for node %d", GetNodeId() ); - - Msg* msg = new Msg( "MultiChannelCmd_EndPointGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( MultiChannelCmd_EndPointGet ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Query ); - res = true; - } - - return res; -} - -bool MultiInstance::HandleIncomingMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance -) -{ - return HandleMsg(_data, _length, _instance); -} + bool MultiInstance::HandleIncomingMsg(uint8 const* _data, uint32 const _length, uint32 const _instance) + { + return HandleMsg(_data, _length, _instance); + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool MultiInstance::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - bool handled = false; - Node* node = GetNodeUnsafe(); - if( node != NULL ) - { - handled = true; - switch( (MultiInstanceCmd)_data[0] ) - { - case MultiInstanceCmd_Report: - { - HandleMultiInstanceReport( _data, _length ); - break; - } - case MultiInstanceCmd_Encap: - { - HandleMultiInstanceEncap( _data, _length ); - break; - } - case MultiChannelCmd_EndPointReport: - { - HandleMultiChannelEndPointReport( _data, _length ); - break; - } - case MultiChannelCmd_CapabilityReport: + bool MultiInstance::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) { - HandleMultiChannelCapabilityReport( _data, _length ); - break; - } - case MultiChannelCmd_EndPointFindReport: - { - HandleMultiChannelEndPointFindReport( _data, _length ); - break; - } - case MultiChannelCmd_Encap: - { - HandleMultiChannelEncap( _data, _length ); - break; - } - default: - { - handled = false; - break; - } - } - } + bool handled = false; + Node* node = GetNodeUnsafe(); + if (node != NULL) + { + handled = true; + switch ((MultiInstanceCmd) _data[0]) + { + case MultiInstanceCmd_Report: + { + HandleMultiInstanceReport(_data, _length); + break; + } + case MultiInstanceCmd_Encap: + { + HandleMultiInstanceEncap(_data, _length); + break; + } + case MultiChannelCmd_EndPointReport: + { + HandleMultiChannelEndPointReport(_data, _length); + break; + } + case MultiChannelCmd_CapabilityReport: + { + HandleMultiChannelCapabilityReport(_data, _length); + break; + } + case MultiChannelCmd_EndPointFindReport: + { + HandleMultiChannelEndPointFindReport(_data, _length); + break; + } + case MultiChannelCmd_Encap: + { + HandleMultiChannelEncap(_data, _length); + break; + } + default: + { + handled = false; + break; + } + } + } - return handled; -} + return handled; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -void MultiInstance::HandleMultiInstanceReport -( - uint8 const* _data, - uint32 const _length -) -{ - if( Node* node = GetNodeUnsafe() ) - { - uint8 commandClassId = _data[1]; - uint8 instances = _data[2]; + void MultiInstance::HandleMultiInstanceReport(uint8 const* _data, uint32 const _length) + { + if (Node* node = GetNodeUnsafe()) + { + uint8 commandClassId = _data[1]; + uint8 instances = _data[2]; - if( CommandClass* pCommandClass = node->GetCommandClass( commandClassId ) ) - { - Log::Write( LogLevel_Info, GetNodeId(), "Received MultiInstanceReport from node %d for %s: Number of instances = %d", GetNodeId(), pCommandClass->GetCommandClassName().c_str(), instances ); - pCommandClass->SetInstances( instances ); - pCommandClass->ClearStaticRequest( StaticRequest_Instances ); - } - } -} + if (CommandClass* pCommandClass = node->GetCommandClass(commandClassId)) + { + Log::Write(LogLevel_Info, GetNodeId(), "Received MultiInstanceReport from node %d for %s: Number of instances = %d", GetNodeId(), pCommandClass->GetCommandClassName().c_str(), instances); + pCommandClass->SetInstances(instances); + pCommandClass->ClearStaticRequest(StaticRequest_Instances); + } + } + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -void MultiInstance::HandleMultiInstanceEncap -( - uint8 const* _data, - uint32 const _length -) -{ - if( Node* node = GetNodeUnsafe() ) - { - uint8 instance = _data[1]; - if( GetVersion() > 1 ) - { - instance &= 0x7f; - } - uint8 commandClassId = _data[2]; + void MultiInstance::HandleMultiInstanceEncap(uint8 const* _data, uint32 const _length) + { + if (Node* node = GetNodeUnsafe()) + { + uint8 instance = _data[1]; + if (GetVersion() > 1) + { + instance &= 0x7f; + } + uint8 commandClassId = _data[2]; - if( CommandClass* pCommandClass = node->GetCommandClass( commandClassId ) ) - { - Log::Write( LogLevel_Info, GetNodeId(), "Received a MultiInstanceEncap from node %d, instance %d, for Command Class %s", GetNodeId(), instance, pCommandClass->GetCommandClassName().c_str() ); - pCommandClass->ReceivedCntIncr(); - pCommandClass->HandleMsg( &_data[3], _length-3, instance ); - } - else - { - Log::Write( LogLevel_Warning, GetNodeId(), "Received invalid MultiInstanceReport from node %d. Attempting to process as MultiChannel", GetNodeId()); - HandleMultiChannelEncap( _data, _length ); - } - } -} + if (CommandClass* pCommandClass = node->GetCommandClass(commandClassId)) + { + Log::Write(LogLevel_Info, GetNodeId(), "Received a MultiInstanceEncap from node %d, instance %d, for Command Class %s", GetNodeId(), instance, pCommandClass->GetCommandClassName().c_str()); + pCommandClass->ReceivedCntIncr(); + pCommandClass->HandleMsg(&_data[3], _length - 3, instance); + } + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "Received invalid MultiInstanceReport from node %d. Attempting to process as MultiChannel", GetNodeId()); + HandleMultiChannelEncap(_data, _length); + } + } + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -void MultiInstance::HandleMultiChannelEndPointReport -( - uint8 const* _data, - uint32 const _length -) -{ - int len; - - if( m_numEndPoints != 0 ) - { - return; - } + void MultiInstance::HandleMultiChannelEndPointReport(uint8 const* _data, uint32 const _length) + { + int len; - m_numEndPointsCanChange = (( _data[1] & 0x80 ) != 0 ); // Number of endpoints can change. - m_endPointsAreSameClass = (( _data[1] & 0x40 ) != 0 ); // All endpoints are the same command class. + if (m_numEndPoints != 0) + { + return; + } - /* some devices (eg, Aeotec Smart Dimmer 6 incorrectly report all endpoints are the same */ - if (m_com.GetFlagBool(COMPAT_FLAG_MI_FORCEUNIQUEENDPOINTS)) - m_endPointsAreSameClass = false; + m_numEndPointsCanChange = ((_data[1] & 0x80) != 0); // Number of endpoints can change. + m_endPointsAreSameClass = ((_data[1] & 0x40) != 0); // All endpoints are the same command class. + /* some devices (eg, Aeotec Smart Dimmer 6 incorrectly report all endpoints are the same */ + if (m_com.GetFlagBool(COMPAT_FLAG_MI_FORCEUNIQUEENDPOINTS)) + m_endPointsAreSameClass = false; - m_numEndPoints = _data[2] & 0x7f; - if( m_com.GetFlagByte(COMPAT_FLAG_MI_ENDPOINTHINT) != 0 ) - { - m_numEndPoints = m_com.GetFlagByte(COMPAT_FLAG_MI_ENDPOINTHINT); // don't use device's number - } + m_numEndPoints = _data[2] & 0x7f; + if (m_com.GetFlagByte(COMPAT_FLAG_MI_ENDPOINTHINT) != 0) + { + m_numEndPoints = m_com.GetFlagByte(COMPAT_FLAG_MI_ENDPOINTHINT); // don't use device's number + } - len = m_numEndPoints; - if( m_endPointsAreSameClass ) // only need to check single end point - { - len = 1; - Log::Write( LogLevel_Info, GetNodeId(), "Received MultiChannelEndPointReport from node %d. All %d endpoints are the same.", GetNodeId(), m_numEndPoints ); - } - else - { - Log::Write( LogLevel_Info, GetNodeId(), "Received MultiChannelEndPointReport from node %d. %d endpoints are not all the same.", GetNodeId(), m_numEndPoints ); - } + len = m_numEndPoints; + if (m_endPointsAreSameClass) // only need to check single end point + { + len = 1; + Log::Write(LogLevel_Info, GetNodeId(), "Received MultiChannelEndPointReport from node %d. All %d endpoints are the same.", GetNodeId(), m_numEndPoints); + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "Received MultiChannelEndPointReport from node %d. %d endpoints are not all the same.", GetNodeId(), m_numEndPoints); + } - // This code assumes the endpoints are all in numeric sequential order. - // Since the end point finds do not appear to work this is the best estimate. - for( uint8 i = 1; i <= len; i++ ) - { + // This code assumes the endpoints are all in numeric sequential order. + // Since the end point finds do not appear to work this is the best estimate. + for (uint8 i = 1; i <= len; i++) + { - // Send a single capability request to each endpoint - Log::Write( LogLevel_Info, GetNodeId(), "MultiChannelCmd_CapabilityGet for endpoint %d", i ); - Msg* msg = new Msg( "MultiChannelCmd_CapabilityGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( MultiChannelCmd_CapabilityGet ); - msg->Append( i ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - } -} + // Send a single capability request to each endpoint + Log::Write(LogLevel_Info, GetNodeId(), "MultiChannelCmd_CapabilityGet for endpoint %d", i); + Msg* msg = new Msg("MultiChannelCmd_CapabilityGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(MultiChannelCmd_CapabilityGet); + msg->Append(i); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + } + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -void MultiInstance::HandleMultiChannelCapabilityReport -( - uint8 const* _data, - uint32 const _length -) -{ - - bool dynamic = ((_data[1] & 0x80)!=0); + void MultiInstance::HandleMultiChannelCapabilityReport(uint8 const* _data, uint32 const _length) + { + bool dynamic = ((_data[1] & 0x80) != 0); - if( Node* node = GetNodeUnsafe() ) - { - /* if you having problems with Dynamic Devices not correctly - * updating the commandclasses, see this email thread: - * https://groups.google.com/d/topic/openzwave/IwepxScRAVo/discussion - */ - if ((m_com.GetFlagBool(COMPAT_FLAG_MI_IGNMCCAPREPORTS) && (node->GetCurrentQueryStage() != Node::QueryStage_Instances)) - && !dynamic && m_endPointCommandClasses.size() > 0) { - Log::Write(LogLevel_Error, GetNodeId(), "Received a Unsolicited MultiChannelEncap when we are not in QueryState_Instances"); - return; - } - - uint8 endPoint = _data[1] & 0x7f; - - Log::Write( LogLevel_Info, GetNodeId(), "Received MultiChannelCapabilityReport from node %d for endpoint %d", GetNodeId(), endPoint ); - Log::Write( LogLevel_Info, GetNodeId(), " Endpoint is%sdynamic, and is a %s", dynamic ? " " : " not ", node->GetEndPointDeviceClassLabel( _data[2], _data[3] ).c_str() ); - Log::Write( LogLevel_Info, GetNodeId(), " Command classes supported by the endpoint are:" ); - - // Store the command classes for later use - bool afterMark = false; - m_endPointCommandClasses.clear(); - uint8 numCommandClasses = _length - 5; - for( uint8 i = 0; i < numCommandClasses; ++i ) - { - uint8 commandClassId = _data[i+4]; - if( commandClassId == 0xef ) - { - afterMark = true; - Log::Write( LogLevel_Info, GetNodeId(), " Controlled CommandClasses:"); - } + if (Node* node = GetNodeUnsafe()) + { + /* if you having problems with Dynamic Devices not correctly + * updating the commandclasses, see this email thread: + * https://groups.google.com/d/topic/openzwave/IwepxScRAVo/discussion + */ + if ((m_com.GetFlagBool(COMPAT_FLAG_MI_IGNMCCAPREPORTS) && (node->GetCurrentQueryStage() != Node::QueryStage_Instances)) && !dynamic && m_endPointCommandClasses.size() > 0) + { + Log::Write(LogLevel_Error, GetNodeId(), "Received a Unsolicited MultiChannelEncap when we are not in QueryState_Instances"); + return; + } - m_endPointCommandClasses.insert( commandClassId ); + uint8 endPoint = _data[1] & 0x7f; + m_endPointGenericType.insert(std::pair(endPoint, _data[2])); + m_endPointSpecificType.insert(std::pair(endPoint, _data[3])); + Log::Write(LogLevel_Info, GetNodeId(), "Received MultiChannelCapabilityReport from node %d for endpoint %d", GetNodeId(), endPoint); + Log::Write(LogLevel_Info, GetNodeId(), " Endpoint is%sdynamic, and is a %s", dynamic ? " " : " not ", node->GetEndPointDeviceClassLabel(_data[2], _data[3]).c_str()); + Log::Write(LogLevel_Info, GetNodeId(), " Command classes supported by the endpoint are:"); + + // Store the command classes for later use + bool afterMark = false; + m_endPointCommandClasses.clear(); + uint8 numCommandClasses = _length - 5; + for (uint8 i = 0; i < numCommandClasses; ++i) + { + uint8 commandClassId = _data[i + 4]; + if (commandClassId == 0xef) + { + afterMark = true; + Log::Write(LogLevel_Info, GetNodeId(), " Controlled CommandClasses:"); + } - // Ensure the node supports this command class - CommandClass* cc = node->GetCommandClass( commandClassId, afterMark ); + if (m_com.GetFlagBool(COMPAT_FLAG_MI_REMOVECC, commandClassId) == true) { + Log::Write(LogLevel_Info, GetNodeId(), " %s (%d) (Disabled By Config)", CommandClasses::GetName(commandClassId).c_str(), commandClassId); + continue; + } - if( !cc ) - { - cc = node->AddCommandClass( commandClassId, afterMark ); - } - if( cc && afterMark ) - { - cc->SetAfterMark(); - Log::Write( LogLevel_Info, GetNodeId(), " %s", cc->GetCommandClassName().c_str() ); - } - else if ( cc ) - { - Log::Write( LogLevel_Info, GetNodeId(), " %s", cc->GetCommandClassName().c_str() ); - } - /* The AddCommandClass will bitch about unsupported CC's so we don't need to duplicate that output */ - } + m_endPointCommandClasses.insert(commandClassId); - // Create internal library instances for each command class in the list - // Also set up mapping from intances to endpoints for encapsulation - Basic* basic = static_cast( node->GetCommandClass( Basic::StaticGetCommandClassId() ) ); - if( m_endPointsAreSameClass ) // Create all the same instances here - { - int len; + // Ensure the node supports this command class + CommandClass* cc = node->GetCommandClass(commandClassId); - if( m_com.GetFlagBool(COMPAT_FLAG_MI_MAPROOTTOENDPOINT) == false ) // Include the non-endpoint instance - { - endPoint = 0; - len = m_numEndPoints + 1; - } - else - { - endPoint = 1; - len = m_numEndPoints; - } + if (!cc) + { + cc = node->AddCommandClass(commandClassId); + } + if (cc && afterMark) + { + cc->SetAfterMark(); + Log::Write(LogLevel_Info, GetNodeId(), " %s", cc->GetCommandClassName().c_str()); + } + else if (cc) + { + Log::Write(LogLevel_Info, GetNodeId(), " %s", cc->GetCommandClassName().c_str()); + } + /* The AddCommandClass will bitch about unsupported CC's so we don't need to duplicate that output */ + } - // Create all the command classes for all the endpoints - for( uint8 i = 1; i <= len; i++ ) - { - //std::cout << "Num Instances: " << len << std::endl; - for( set::iterator it = m_endPointCommandClasses.begin(); it != m_endPointCommandClasses.end(); ++it ) - { - uint8 commandClassId = *it; - CommandClass* cc = node->GetCommandClass( commandClassId ); - if( cc ) + // Create internal library instances for each command class in the list + // Also set up mapping from intances to endpoints for encapsulation + Basic* basic = static_cast(node->GetCommandClass(Basic::StaticGetCommandClassId())); + if (m_endPointsAreSameClass) // Create all the same instances here { - cc->SetInstance( i ); - if( m_com.GetFlagBool(COMPAT_FLAG_MI_MAPROOTTOENDPOINT) != false || i != 1 ) + int len; + + if (m_com.GetFlagBool(COMPAT_FLAG_MI_MAPROOTTOENDPOINT) == false) // Include the non-endpoint instance + { + endPoint = 0; + len = m_numEndPoints + 1; + } + else { - cc->SetEndPoint( i, endPoint ); + endPoint = 1; + len = m_numEndPoints; } - // If we support the BASIC command class and it is mapped to a command class - // assigned to this end point, make sure the BASIC command class is also associated - // with this end point. - if( basic != NULL && basic->GetMapping() == commandClassId ) + + // Create all the command classes for all the endpoints + for (uint8 i = 1; i <= len; i++) { - basic->SetInstance( i ); - if( m_com.GetFlagBool(COMPAT_FLAG_MI_MAPROOTTOENDPOINT) != false || i != 1 ) + //std::cout << "Num Instances: " << len << std::endl; + for (set::iterator it = m_endPointCommandClasses.begin(); it != m_endPointCommandClasses.end(); ++it) { - basic->SetEndPoint( i, endPoint ); + uint8 commandClassId = *it; + CommandClass* cc = node->GetCommandClass(commandClassId); + if (cc) + { + cc->SetInstance(i); + if (m_com.GetFlagBool(COMPAT_FLAG_MI_MAPROOTTOENDPOINT) != false || i != 1) + { + cc->SetEndPoint(i, endPoint); + } + // If we support the BASIC command class and it is mapped to a command class + // assigned to this end point, make sure the BASIC command class is also associated + // with this end point. + if (basic != NULL && basic->GetMapping() == commandClassId) + { + basic->SetInstance(i); + if (m_com.GetFlagBool(COMPAT_FLAG_MI_MAPROOTTOENDPOINT) != false || i != 1) + { + basic->SetEndPoint(i, endPoint); + } + } + /* if its the Security CC, on a instance > 1, then this has come from the Security CC found in a MultiInstance Capability Report. + * So we need to Query the endpoint for Secured CC's + */ + if ((commandClassId == Security::StaticGetCommandClassId()) && (i > 1)) + { + if (!node->IsSecured()) + { + Log::Write(LogLevel_Info, GetNodeId(), " Skipping Security_Supported_Get, as the Node is not Secured"); + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), " Sending Security_Supported_Get to Instance %d", i); + Security *seccc = static_cast(node->GetCommandClass(Security::StaticGetCommandClassId())); + /* this will trigger a SecurityCmd_SupportedGet on the _instance of the Device. */ + if (seccc && !seccc->IsAfterMark()) + { + seccc->Init(i); + } + } + } + + } } + endPoint++; } - /* if its the Security CC, on a instance > 1, then this has come from the Security CC found in a MultiInstance Capability Report. - * So we need to Query the endpoint for Secured CC's - */ - if ((commandClassId == Security::StaticGetCommandClassId()) && (i > 1)) { - if (!node->IsSecured()) { - Log::Write(LogLevel_Info, GetNodeId(), " Skipping Security_Supported_Get, as the Node is not Secured"); - } else { - Log::Write(LogLevel_Info, GetNodeId(), " Sending Security_Supported_Get to Instance %d", i); - Security *seccc = static_cast(node->GetCommandClass(Security::StaticGetCommandClassId(), afterMark)); - /* this will trigger a SecurityCmd_SupportedGet on the _instance of the Device. */ - if (seccc) { - seccc->Init(i); + } + else // Endpoints are different + { + for (set::iterator it = m_endPointCommandClasses.begin(); it != m_endPointCommandClasses.end(); ++it) + { + uint8 commandClassId = *it; + + CommandClass* cc = node->GetCommandClass(commandClassId); + if (cc) + { + // get instance gets an instance for an endpoint + // but i'm only interested if there is a related instance for an endpoint and not in the actual result + // soo if the result is != 0, the endpoint is already handled + bool endpointAlreadyHandled = cc->GetInstance(endPoint) != 0; + if (endpointAlreadyHandled) + { + Log::Write(LogLevel_Warning, GetNodeId(), "Received MultiChannelCapabilityReport from node %d for endpoint %d - Endpoint already handled for CommandClass %d", GetNodeId(), endPoint, cc->GetCommandClassId()); + continue; + } + uint8 i; + // Find the next free instance of this class + for (i = 1; i <= 127; i++) + { + if (m_com.GetFlagBool(COMPAT_FLAG_MI_MAPROOTTOENDPOINT) == false) // Include the non-endpoint instance + { + if (!cc->GetInstances()->IsSet(i)) + { + break; + } + } + // Reuse non-endpoint instances first time we see it + else if (i == 1 && cc->GetInstances()->IsSet(i) && cc->GetEndPoint(i) == 0) + { + break; + } + // Find the next free instance + else if (!cc->GetInstances()->IsSet(i)) + { + break; + } + } + cc->SetInstance(i); + cc->SetEndPoint(i, endPoint); + // If we support the BASIC command class and it is mapped to a command class + // assigned to this end point, make sure the BASIC command class is also associated + // with this end point. + if (basic != NULL && basic->GetMapping() == commandClassId) + { + basic->SetInstance(i); + basic->SetEndPoint(i, endPoint); } } } - } } - endPoint++; } - } - else // Endpoints are different - { - for( set::iterator it = m_endPointCommandClasses.begin(); it != m_endPointCommandClasses.end(); ++it ) + +//----------------------------------------------------------------------------- +// +// Handle a message from the Z-Wave network +//----------------------------------------------------------------------------- + void MultiInstance::HandleMultiChannelEndPointFindReport(uint8 const* _data, uint32 const _length) { - uint8 commandClassId = *it; - CommandClass* cc = node->GetCommandClass( commandClassId ); - if( cc ) + Log::Write(LogLevel_Info, GetNodeId(), "Received MultiChannelEndPointFindReport from node %d", GetNodeId()); + uint8 numEndPoints = _length - 5; + for (uint8 i = 0; i < numEndPoints; ++i) { - // get instance gets an instance for an endpoint - // but i'm only interested if there is a related instance for an endpoint and not in the actual result - // soo if the result is != 0, the endpoint is already handled - bool endpointAlreadyHandled = cc->GetInstance( endPoint ) != 0 ; - if ( endpointAlreadyHandled ) - { - Log::Write( LogLevel_Warning, GetNodeId(), "Received MultiChannelCapabilityReport from node %d for endpoint %d - Endpoint already handled for CommandClass %d", GetNodeId(), endPoint, cc->GetCommandClassId() ); - continue; - } - uint8 i; - // Find the next free instance of this class - for( i = 1; i <= 127; i++ ) + uint8 endPoint = _data[i + 4] & 0x7f; + + if (m_endPointsAreSameClass) { - if( m_com.GetFlagBool(COMPAT_FLAG_MI_MAPROOTTOENDPOINT) == false ) // Include the non-endpoint instance + // Use the stored command class list to set up the endpoint. + if (Node* node = GetNodeUnsafe()) { - if( !cc->GetInstances()->IsSet( i ) ) + for (set::iterator it = m_endPointCommandClasses.begin(); it != m_endPointCommandClasses.end(); ++it) { - break; + uint8 commandClassId = *it; + CommandClass* cc = node->GetCommandClass(commandClassId); + if (cc) + { + Log::Write(LogLevel_Info, GetNodeId(), " Endpoint %d: Adding %s", endPoint, cc->GetCommandClassName().c_str()); + cc->SetInstance(endPoint); + } } } - // Reuse non-endpoint instances first time we see it - else if( i == 1 && cc->GetInstances()->IsSet( i ) && cc->GetEndPoint( i ) == 0 ) - { - break; - } - // Find the next free instance - else if( !cc->GetInstances()->IsSet( i ) ) - { - break; - } } - cc->SetInstance( i ); - cc->SetEndPoint( i, endPoint ); - // If we support the BASIC command class and it is mapped to a command class - // assigned to this end point, make sure the BASIC command class is also associated - // with this end point. - if( basic != NULL && basic->GetMapping() == commandClassId ) + else { - basic->SetInstance( i ); - basic->SetEndPoint( i, endPoint ); + // Endpoints are different, so request the capabilities + Log::Write(LogLevel_Info, GetNodeId(), "MultiChannelCmd_CapabilityGet for node %d, endpoint %d", GetNodeId(), endPoint); + Msg* msg = new Msg("MultiChannelCmd_CapabilityGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(MultiChannelCmd_CapabilityGet); + msg->Append(endPoint); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); } } - } - } - } -} -//----------------------------------------------------------------------------- -// -// Handle a message from the Z-Wave network -//----------------------------------------------------------------------------- -void MultiInstance::HandleMultiChannelEndPointFindReport -( - uint8 const* _data, - uint32 const _length -) -{ - Log::Write( LogLevel_Info, GetNodeId(), "Received MultiChannelEndPointFindReport from node %d", GetNodeId() ); - uint8 numEndPoints = _length - 5; - for( uint8 i=0; i::iterator it=m_endPointCommandClasses.begin(); it!=m_endPointCommandClasses.end(); ++it ) + m_numEndPointsFound += numEndPoints; + if (!m_endPointsAreSameClass) { - uint8 commandClassId = *it; - CommandClass* cc = node->GetCommandClass( commandClassId ); - if( cc ) + if (_data[1] == 0) { - Log::Write( LogLevel_Info, GetNodeId(), " Endpoint %d: Adding %s", endPoint, cc->GetCommandClassName().c_str() ); - cc->SetInstance( endPoint ); + // No more reports to follow this one, so we can continue the search. + if (m_numEndPointsFound < numEndPoints) + { + // We have not yet found all the endpoints, so move to the next generic class request + ++m_endPointFindIndex; + if (m_endPointFindIndex <= 13) /* we are finished */ + { + if (c_genericClass[m_endPointFindIndex] > 0) + { + if (m_endPointFindIndex > 13) /* size of c_genericClassName minus Unknown Entry */ + { + Log::Write(LogLevel_Warning, GetNodeId(), "m_endPointFindIndex Value was greater than range. Setting to Unknown"); + m_endPointFindIndex = 14; + } + + Log::Write(LogLevel_Info, GetNodeId(), "MultiChannelCmd_EndPointFind for generic device class 0x%.2x (%s)", c_genericClass[m_endPointFindIndex], c_genericClassName[m_endPointFindIndex]); + Msg* msg = new Msg("MultiChannelCmd_EndPointFind", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(4); + msg->Append(GetCommandClassId()); + msg->Append(MultiChannelCmd_EndPointFind); + msg->Append(c_genericClass[m_endPointFindIndex]); // Generic device class + msg->Append(0xff); // Any specific device class + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + } + } + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "m_endPointFindIndex is higher than range. Not Sending MultiChannelCmd_EndPointFind message"); + } + } } } } - } - else - { - // Endpoints are different, so request the capabilities - Log::Write(LogLevel_Info, GetNodeId(), "MultiChannelCmd_CapabilityGet for node %d, endpoint %d", GetNodeId(), endPoint ); - Msg* msg = new Msg( "MultiChannelCmd_CapabilityGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( MultiChannelCmd_CapabilityGet ); - msg->Append( endPoint ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - } - } - - m_numEndPointsFound += numEndPoints; - if( !m_endPointsAreSameClass ) - { - if( _data[1] == 0 ) - { - // No more reports to follow this one, so we can continue the search. - if( m_numEndPointsFound < numEndPoints ) + +//----------------------------------------------------------------------------- +// +// Handle a message from the Z-Wave network +//----------------------------------------------------------------------------- + void MultiInstance::HandleMultiChannelEncap(uint8 const* _data, uint32 const _length) { - // We have not yet found all the endpoints, so move to the next generic class request - ++m_endPointFindIndex; - if (m_endPointFindIndex <= 13) /* we are finished */ + if (Node* node = GetNodeUnsafe()) { - if( c_genericClass[m_endPointFindIndex] > 0 ) + uint8 endPoint = _data[1] & 0x7f; + uint8 commandClassId = _data[3]; + if (CommandClass* pCommandClass = node->GetCommandClass(commandClassId)) { - if (m_endPointFindIndex > 13) /* size of c_genericClassName minus Unknown Entry */ + /* 4.85.13 - If the Root Device is originating a command to an End Point in another node, the Source End Point MUST be set to 0. + * + */ + if (endPoint == 0) { - Log::Write (LogLevel_Warning, GetNodeId(), "m_endPointFindIndex Value was greater than range. Setting to Unknown"); - m_endPointFindIndex = 14; + Log::Write(LogLevel_Info, GetNodeId(), "MultiChannelEncap with endpoint set to 0 - Send to Root Device"); + pCommandClass->HandleMsg(&_data[4], _length - 4); + return; } - Log::Write(LogLevel_Info, GetNodeId(), "MultiChannelCmd_EndPointFind for generic device class 0x%.2x (%s)", c_genericClass[m_endPointFindIndex], c_genericClassName[m_endPointFindIndex] ); - Msg* msg = new Msg( "MultiChannelCmd_EndPointFind", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( 4 ); - msg->Append( GetCommandClassId() ); - msg->Append( MultiChannelCmd_EndPointFind ); - msg->Append( c_genericClass[m_endPointFindIndex] ); // Generic device class - msg->Append( 0xff ); // Any specific device class - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); + uint8 instance = pCommandClass->GetInstance(endPoint); + /* we can never have a 0 Instance */ + if (instance == 0) + instance = 1; + Log::Write(LogLevel_Info, GetNodeId(), "Received a MultiChannelEncap from node %d, endpoint %d for Command Class %s", GetNodeId(), endPoint, pCommandClass->GetCommandClassName().c_str()); + if (!pCommandClass->IsAfterMark()) + pCommandClass->HandleMsg(&_data[4], _length - 4, instance); + else + pCommandClass->HandleIncomingMsg(&_data[4], _length - 4, instance); + } + else + { + Log::Write(LogLevel_Error, GetNodeId(), "Received a MultiChannelEncap for endpoint %d for Command Class %d, which we can't find", endPoint, commandClassId); } - } else { - Log::Write (LogLevel_Warning, GetNodeId(), "m_endPointFindIndex is higher than range. Not Sending MultiChannelCmd_EndPointFind message"); } } - } - } -} - //----------------------------------------------------------------------------- -// -// Handle a message from the Z-Wave network +// +// Set the Generic Label for a Instance //----------------------------------------------------------------------------- -void MultiInstance::HandleMultiChannelEncap -( - uint8 const* _data, - uint32 const _length -) -{ - if( Node* node = GetNodeUnsafe() ) - { - uint8 endPoint = _data[1] & 0x7f; - uint8 commandClassId = _data[3]; - if( CommandClass* pCommandClass = node->GetCommandClass( commandClassId ) ) - { - /* 4.85.13 - If the Root Device is originating a command to an End Point in another node, the Source End Point MUST be set to 0. - * - */ - if (endPoint == 0) { - Log::Write( LogLevel_Error, GetNodeId(), "MultiChannelEncap with endpoint set to 0 - Send to Root Device"); - pCommandClass->HandleMsg(&_data[4], _length-4); - return; + void MultiInstance::SetInstanceLabel(uint8 const _instance, char *label) + { + CommandClass::SetInstanceLabel(_instance, label); + /* Set the Default Global Instance Label for CC that don't define their own instance labels */ + if (Node* node = GetNodeUnsafe()) + { + node->SetInstanceLabel(_instance, label); + } } - - uint8 instance = pCommandClass->GetInstance( endPoint ); - /* we can never have a 0 Instance */ - if (instance == 0) - instance = 1; - Log::Write( LogLevel_Info, GetNodeId(), "Received a MultiChannelEncap from node %d, endpoint %d for Command Class %s", GetNodeId(), endPoint, pCommandClass->GetCommandClassName().c_str() ); - pCommandClass->HandleMsg( &_data[4], _length-4, instance ); - } - else if (CommandClass* pCommandClass = node->GetCommandClass( commandClassId, true ) ) - { - uint8 instance = pCommandClass->GetInstance( endPoint ); - /* we can never have a 0 Instance */ - if (instance == 0) - instance = 1; - Log::Write( LogLevel_Info, GetNodeId(), "Received a Incoming MultiChannelEncap from node %d, endpoint %d for Command Class %s", GetNodeId(), endPoint, pCommandClass->GetCommandClassName().c_str() ); - pCommandClass->HandleIncomingMsg( &_data[4], _length-4, instance ); - - } - else - { - Log::Write(LogLevel_Error, GetNodeId(), "Received a MultiChannelEncap for endpoint %d for Command Class %d, which we can't find", endPoint, commandClassId); - } - } -} //----------------------------------------------------------------------------- -// -// Handle a message from the Z-Wave network +// +// Get the Generic DeviceType for a EndPoint //----------------------------------------------------------------------------- -void MultiInstance::SetInstanceLabel -( - uint8 const _instance, - char *label -) -{ - CommandClass::SetInstanceLabel(_instance, label); - /* Set the Default Global Instance Label for CC that don't define their own instance labels */ - if( Node* node = GetNodeUnsafe() ) - { - node->SetInstanceLabel(_instance, label); - } -} + uint8 MultiInstance::GetGenericInstanceDeviceType(uint8 _instance) + { + if (m_endPointGenericType.find(_instance) != m_endPointGenericType.end()) + return m_endPointGenericType.at(_instance); + + return 0; + } +//----------------------------------------------------------------------------- +// +// Get the Specific DeviceType for a Endpoint +//----------------------------------------------------------------------------- + uint8 MultiInstance::GetSpecificInstanceDeviceType(uint8 _instance) + { + if (m_endPointSpecificType.find(_instance) != m_endPointSpecificType.end()) + return m_endPointSpecificType.at(_instance); + + return 0; + } + + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/MultiInstance.h b/cpp/src/command_classes/MultiInstance.h index a58349907c..c34c0a4e33 100644 --- a/cpp/src/command_classes/MultiInstance.h +++ b/cpp/src/command_classes/MultiInstance.h @@ -33,65 +33,95 @@ namespace OpenZWave { - /** \brief Implements COMMAND_CLASS_MULTI_INSTANCE (0x60), a Z-Wave device command class. - * \ingroup CommandClass - */ - class MultiInstance: public CommandClass + namespace Internal { - public: - enum MultiInstanceCmd + namespace CC { - MultiInstanceCmd_Get = 0x04, - MultiInstanceCmd_Report = 0x05, - MultiInstanceCmd_Encap = 0x06, - - // Version 2 - MultiChannelCmd_EndPointGet = 0x07, - MultiChannelCmd_EndPointReport = 0x08, - MultiChannelCmd_CapabilityGet = 0x09, - MultiChannelCmd_CapabilityReport = 0x0a, - MultiChannelCmd_EndPointFind = 0x0b, - MultiChannelCmd_EndPointFindReport = 0x0c, - MultiChannelCmd_Encap = 0x0d - }; - - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new MultiInstance( _homeId, _nodeId ); } - virtual ~MultiInstance(){} - - static uint8 const StaticGetCommandClassId(){ return 0x60; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_MULTI_INSTANCE/CHANNEL"; } - - bool RequestInstances(); - - // From CommandClass - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool HandleIncomingMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual uint8 GetMaxVersion(){ return 2; } - void SetInstanceLabel(uint8 const _instance, char *label); - - private: - MultiInstance( uint32 const _homeId, uint8 const _nodeId ); - - void HandleMultiInstanceReport( uint8 const* _data, uint32 const _length ); - void HandleMultiInstanceEncap( uint8 const* _data, uint32 const _length ); - void HandleMultiChannelEndPointReport( uint8 const* _data, uint32 const _length ); - void HandleMultiChannelCapabilityReport( uint8 const* _data, uint32 const _length ); - void HandleMultiChannelEndPointFindReport( uint8 const* _data, uint32 const _length ); - void HandleMultiChannelEncap( uint8 const* _data, uint32 const _length ); - - bool m_numEndPointsCanChange; - bool m_endPointsAreSameClass; - uint8 m_numEndPoints; - - // Finding endpoints - uint8 m_endPointFindIndex; - uint8 m_numEndPointsFound; - set m_endPointCommandClasses; - - }; + /** \brief Implements COMMAND_CLASS_MULTI_INSTANCE (0x60), a Z-Wave device command class. + * \ingroup CommandClass + */ + class MultiInstance: public CommandClass + { + public: + enum MultiInstanceCmd + { + MultiInstanceCmd_Get = 0x04, + MultiInstanceCmd_Report = 0x05, + MultiInstanceCmd_Encap = 0x06, + + // Version 2 + MultiChannelCmd_EndPointGet = 0x07, + MultiChannelCmd_EndPointReport = 0x08, + MultiChannelCmd_CapabilityGet = 0x09, + MultiChannelCmd_CapabilityReport = 0x0a, + MultiChannelCmd_EndPointFind = 0x0b, + MultiChannelCmd_EndPointFindReport = 0x0c, + MultiChannelCmd_Encap = 0x0d + }; + + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new MultiInstance(_homeId, _nodeId); + } + virtual ~MultiInstance() + { + } + + static uint8 const StaticGetCommandClassId() + { + return 0x60; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_MULTI_INSTANCE/CHANNEL"; + } + + bool RequestInstances(); + + // From CommandClass + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool HandleIncomingMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual uint8 GetMaxVersion() override + { + return 2; + } + void SetInstanceLabel(uint8 const _instance, char *label) override; + + uint8 GetGenericInstanceDeviceType(uint8); + uint8 GetSpecificInstanceDeviceType(uint8); + + private: + MultiInstance(uint32 const _homeId, uint8 const _nodeId); + + void HandleMultiInstanceReport(uint8 const* _data, uint32 const _length); + void HandleMultiInstanceEncap(uint8 const* _data, uint32 const _length); + void HandleMultiChannelEndPointReport(uint8 const* _data, uint32 const _length); + void HandleMultiChannelCapabilityReport(uint8 const* _data, uint32 const _length); + void HandleMultiChannelEndPointFindReport(uint8 const* _data, uint32 const _length); + void HandleMultiChannelEncap(uint8 const* _data, uint32 const _length); + + bool m_numEndPointsCanChange; + bool m_endPointsAreSameClass; + uint8 m_numEndPoints; + + // Finding endpoints + uint8 m_endPointFindIndex; + uint8 m_numEndPointsFound; + set m_endPointCommandClasses; + map m_endPointGenericType; + map m_endPointSpecificType; + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/NoOperation.cpp b/cpp/src/command_classes/NoOperation.cpp index a099d57124..bdfe5ebca5 100644 --- a/cpp/src/command_classes/NoOperation.cpp +++ b/cpp/src/command_classes/NoOperation.cpp @@ -33,44 +33,45 @@ #include "Driver.h" #include "platform/Log.h" -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace CC + { //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool NoOperation::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - // We have received a no operation from the Z-Wave device. - Log::Write( LogLevel_Info, GetNodeId(), "Received NoOperation command from node %d", GetNodeId() ); - return true; -} + bool NoOperation::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) + { + // We have received a no operation from the Z-Wave device. + Log::Write(LogLevel_Info, GetNodeId(), "Received NoOperation command from node %d", GetNodeId()); + return true; + } //----------------------------------------------------------------------------- // // Send a No Operation message class. //----------------------------------------------------------------------------- -void NoOperation::Set -( - bool const _route, - Driver::MsgQueue _queue // = Driver::MsgQueue_NoOp -) -{ - Log::Write( LogLevel_Info, GetNodeId(), "NoOperation::Set - Routing=%s", _route ? "true" : "false" ); + void NoOperation::Set(bool const _route, Driver::MsgQueue _queue // = Driver::MsgQueue_NoOp + ) + { + Log::Write(LogLevel_Info, GetNodeId(), "NoOperation::Set - Routing=%s", _route ? "true" : "false"); - Msg* msg = new Msg( "NoOperation_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( 0 ); - if( _route ) - msg->Append( GetDriver()->GetTransmitOptions() ); - else - msg->Append( TRANSMIT_OPTION_ACK | TRANSMIT_OPTION_NO_ROUTE ); - GetDriver()->SendMsg( msg, _queue ); -} + Msg* msg = new Msg("NoOperation_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(0); + if (_route) + msg->Append(GetDriver()->GetTransmitOptions()); + else + msg->Append( TRANSMIT_OPTION_ACK | TRANSMIT_OPTION_NO_ROUTE); + GetDriver()->SendMsg(msg, _queue); + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/NoOperation.h b/cpp/src/command_classes/NoOperation.h index 16f192406f..86a927a073 100644 --- a/cpp/src/command_classes/NoOperation.h +++ b/cpp/src/command_classes/NoOperation.h @@ -32,29 +32,54 @@ namespace OpenZWave { - /** \brief Implements COMMAND_CLASS_NO_OPERATION (0x00), a Z-Wave device command class. - * \ingroup CommandClass - */ - class NoOperation: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new NoOperation( _homeId, _nodeId ); } - virtual ~NoOperation(){} + namespace CC + { + /** \brief Implements COMMAND_CLASS_NO_OPERATION (0x00), a Z-Wave device command class. + * \ingroup CommandClass + */ + class NoOperation: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new NoOperation(_homeId, _nodeId); + } + virtual ~NoOperation() + { + } - static uint8 const StaticGetCommandClassId(){ return 0x00; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_NO_OPERATION"; } + static uint8 const StaticGetCommandClassId() + { + return 0x00; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_NO_OPERATION"; + } - void Set( bool const _route, Driver::MsgQueue const _queue = Driver::MsgQueue_NoOp ); + void Set(bool const _route, Driver::MsgQueue const _queue = Driver::MsgQueue_NoOp); - // From CommandClass - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - - private: - NoOperation( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} - }; + // From CommandClass + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + private: + NoOperation(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + } + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/NodeNaming.cpp b/cpp/src/command_classes/NodeNaming.cpp index 576c80bb18..0efd4a135f 100644 --- a/cpp/src/command_classes/NodeNaming.cpp +++ b/cpp/src/command_classes/NodeNaming.cpp @@ -35,497 +35,474 @@ #include "Notification.h" #include "platform/Log.h" -using namespace OpenZWave; - -enum NodeNamingCmd -{ - NodeNamingCmd_Set = 0x01, - NodeNamingCmd_Get = 0x02, - NodeNamingCmd_Report = 0x03, - NodeNamingCmd_LocationSet = 0x04, - NodeNamingCmd_LocationGet = 0x05, - NodeNamingCmd_LocationReport = 0x06 -}; - -enum StringEncoding +namespace OpenZWave { - StringEncoding_ASCII = 0, - StringEncoding_ExtendedASCII, - StringEncoding_UTF16 -}; + namespace Internal + { + namespace CC + { + + enum NodeNamingCmd + { + NodeNamingCmd_Set = 0x01, + NodeNamingCmd_Get = 0x02, + NodeNamingCmd_Report = 0x03, + NodeNamingCmd_LocationSet = 0x04, + NodeNamingCmd_LocationGet = 0x05, + NodeNamingCmd_LocationReport = 0x06 + }; + + enum StringEncoding + { + StringEncoding_ASCII = 0, + StringEncoding_ExtendedASCII, + StringEncoding_UTF16 + }; // Mapping of characters 0x80 and above to Unicode. -uint16 const c_extendedAsciiToUnicode[] = -{ - 0x20ac, // 0x80 - Euro Sign - 0x0081, // 0x81 - - 0x201a, // 0x82 - Single Low-9 Quotation Mark - 0x0192, // 0x83 - Latin Small Letter F With Hook - 0x201e, // 0x84 - Double Low-9 Quotation Mark - 0x2026, // 0x85 - Horizontal Ellipsis - 0x2020, // 0x86 - Dagger - 0x2021, // 0x87 - Double Dagger - 0x02c6, // 0x88 - Modifier Letter Circumflex Accent - 0x2030, // 0x89 - Per Mille Sign - 0x0160, // 0x8a - Latin Capital Letter S With Caron - 0x2039, // 0x8b - Single Left-Pointing Angle Quotation Mark - 0x0152, // 0x8c - Latin Capital Ligature Oe - 0x008d, // 0x8d - - 0x017d, // 0x8e - Latin Capital Letter Z With Caron - 0x008f, // 0x8f - - - 0x0090, // 0x90 - - 0x2018, // 0x91 - Left Single Quotation Mark - 0x2019, // 0x92 - Right Single Quotation Mark - 0x201c, // 0x93 - Left Double Quotation Mark - 0x201d, // 0x94 - Right Double Quotation Mark - 0x2022, // 0x95 - Bullet - 0x2013, // 0x96 - En Dash - 0x2014, // 0x97 - Em Dash - 0x02dc, // 0x98 - Small Tilde - 0x2122, // 0x99 - Trade Mark Sign - 0x0161, // 0x9a - Latin Small Letter S With Caron - 0x203a, // 0x9b - Single Right-Pointing Angle Quotation Mark - 0x0153, // 0x9c - Latin Small Ligature Oe - 0x009d, // 0x9d - - 0x017e, // 0x9e - Latin Small Letter Z With Caron - 0x0178, // 0x9f - Latin Capital Letter Y With Diaeresis - - 0x00a0, // 0xa0 - No-Break Space - 0x00a1, // 0xa1 - Inverted Exclamation Mark - 0x00a2, // 0xa2 - Cent Sign - 0x00a3, // 0xa3 - Pound Sign - 0x00a4, // 0xa4 - Currency Sign - 0x00a5, // 0xa5 - Yen Sign - 0x00a6, // 0xa6 - Broken Bar - 0x00a7, // 0xa7 - Section Sign - 0x00a8, // 0xa8 - Diaeresis - 0x00a9, // 0xa9 - Copyright Sign - 0x00aa, // 0xaa - Feminine Ordinal Indicator - 0x00ab, // 0xab - Left-Pointing Double Angle Quotation Mark - 0x00ac, // 0xac - Not Sign - 0x00ad, // 0xad - Soft Hyphen - 0x00ae, // 0xae - Registered Sign - 0x00af, // 0xaf - Macron - - 0x00b0, // 0xb0 - Degree Sign - 0x00b1, // 0xb1 - Plus-Minus Sign - 0x00b2, // 0xb2 - Superscript Two - 0x00b3, // 0xb3 - Superscript Three - 0x00b4, // 0xb4 - Acute Accent - 0x00b5, // 0xb5 - Micro Sign - 0x00b6, // 0xb6 - Pilcrow Sign - 0x00b7, // 0xb7 - Middle Dot - 0x00b8, // 0xb8 - Cedilla - 0x00b9, // 0xb9 - Superscript One - 0x00ba, // 0xba - Masculine Ordinal Indicator - 0x00bb, // 0xbb - Right-Pointing Double Angle Quotation Mark - 0x00bc, // 0xbc - Vulgar Fraction One Quarter - 0x00bd, // 0xbd - Vulgar Fraction One Half - 0x00be, // 0xbe - Vulgar Fraction Three Quarters - 0x00bf, // 0xbf - Inverted Question Mark - - 0x00c0, // 0xc0 - Latin Capital Letter A With Grave - 0x00c1, // 0xc1 - Latin Capital Letter A With Acute - 0x00c2, // 0xc2 - Latin Capital Letter A With Circumflex - 0x00c3, // 0xc3 - Latin Capital Letter A With Tilde - 0x00c4, // 0xc4 - Latin Capital Letter A With Diaeresis - 0x00c5, // 0xc5 - Latin Capital Letter A With Ring Above - 0x00c6, // 0xc6 - Latin Capital Ligature Ae - 0x00c7, // 0xc7 - Latin Capital Letter C With Cedilla - 0x00c8, // 0xc8 - Latin Capital Letter E With Grave - 0x00c9, // 0xc9 - Latin Capital Letter E With Acute - 0x00ca, // 0xca - Latin Capital Letter E With Circumflex - 0x00cb, // 0xcb - Latin Capital Letter E With Diaeresis - 0x00cc, // 0xcc - Latin Capital Letter I With Grave - 0x00cd, // 0xcd - Latin Capital Letter I With Acute - 0x00ce, // 0xce - Latin Capital Letter I With Circumflex - 0x00cf, // 0xcf - Latin Capital Letter I With Diaeresis - - 0x00d0, // 0xd0 - Latin Capital Letter Eth - 0x00d1, // 0xd1 - Latin Capital Letter N With Tilde - 0x00d2, // 0xd2 - Latin Capital Letter O With Grave - 0x00d3, // 0xd3 - Latin Capital Letter O With Acute - 0x00d4, // 0xd4 - Latin Capital Letter O With Circumflex - 0x00d5, // 0xd5 - Latin Capital Letter O With Tilde - 0x00d6, // 0xd6 - Latin Capital Letter O With Diaeresis - 0x00d7, // 0xd7 - Multiplication Sign - 0x00d8, // 0xd8 - Latin Capital Letter O With Stroke - 0x00d9, // 0xd9 - Latin Capital Letter U With Grave - 0x00da, // 0xda - Latin Capital Letter U With Acute - 0x00db, // 0xdb - Latin Capital Letter U With Circumflex - 0x00dc, // 0xdc - Latin Capital Letter U With Diaeresis - 0x00dd, // 0xdd - Latin Capital Letter Y With Acute - 0x00de, // 0xde - Latin Capital Letter Thorn - 0x00df, // 0xdf - Latin Small Letter Sharp S - - 0x00e0, // 0xe0 - Latin Small Letter A With Grave - 0x00e1, // 0xe1 - Latin Small Letter A With Acute - 0x00e2, // 0xe2 - Latin Small Letter A With Circumflex - 0x00e3, // 0xe3 - Latin Small Letter A With Tilde - 0x00e4, // 0xe4 - Latin Small Letter A With Diaeresis - 0x00e5, // 0xe5 - Latin Small Letter A With Ring Above - 0x00e6, // 0xe6 - Latin Small Ligature Ae - 0x00e7, // 0xe7 - Latin Small Letter C With Cedilla - 0x00e8, // 0xe8 - Latin Small Letter E With Grave - 0x00e9, // 0xe9 - Latin Small Letter E With Acute - 0x00ea, // 0xea - Latin Small Letter E With Circumflex - 0x00eb, // 0xeb - Latin Small Letter E With Diaeresis - 0x00ec, // 0xec - Latin Small Letter I With Grave - 0x00ed, // 0xed - Latin Small Letter I With Acute - 0x00ee, // 0xee - Latin Small Letter I With Circumflex - 0x00ef, // 0xef - Latin Small Letter I With Diaeresis - - 0x00f0, // 0xf0 - Latin Small Letter Eth - 0x00f1, // 0xf1 - Latin Small Letter N With Tilde - 0x00f2, // 0xf2 - Latin Small Letter O With Grave - 0x00f3, // 0xf3 - Latin Small Letter O With Acute - 0x00f4, // 0xf4 - Latin Small Letter O With Circumflex - 0x00f5, // 0xf5 - Latin Small Letter O With Tilde - 0x00f6, // 0xf6 - Latin Small Letter O With Diaeresis - 0x00f7, // 0xf7 - Division Sign - 0x00f8, // 0xf8 - Latin Small Letter O With Stroke - 0x00f9, // 0xf9 - Latin Small Letter U With Grave - 0x00fa, // 0xfa - Latin Small Letter U With Acute - 0x00fb, // 0xfb - Latin Small Letter U With Circumflex - 0x00fc, // 0xfc - Latin Small Letter U With Diaeresis - 0x00fd, // 0xfd - Latin Small Letter Y With Acute - 0x00fe, // 0xfe - Latin Small Letter Thorn - 0x00ff // 0xff - Latin Small Letter Y With Diaeresis -}; + uint16 const c_extendedAsciiToUnicode[] = + { 0x20ac, // 0x80 - Euro Sign + 0x0081, // 0x81 - + 0x201a, // 0x82 - Single Low-9 Quotation Mark + 0x0192, // 0x83 - Latin Small Letter F With Hook + 0x201e, // 0x84 - Double Low-9 Quotation Mark + 0x2026, // 0x85 - Horizontal Ellipsis + 0x2020, // 0x86 - Dagger + 0x2021, // 0x87 - Double Dagger + 0x02c6, // 0x88 - Modifier Letter Circumflex Accent + 0x2030, // 0x89 - Per Mille Sign + 0x0160, // 0x8a - Latin Capital Letter S With Caron + 0x2039, // 0x8b - Single Left-Pointing Angle Quotation Mark + 0x0152, // 0x8c - Latin Capital Ligature Oe + 0x008d, // 0x8d - + 0x017d, // 0x8e - Latin Capital Letter Z With Caron + 0x008f, // 0x8f - + + 0x0090, // 0x90 - + 0x2018, // 0x91 - Left Single Quotation Mark + 0x2019, // 0x92 - Right Single Quotation Mark + 0x201c, // 0x93 - Left Double Quotation Mark + 0x201d, // 0x94 - Right Double Quotation Mark + 0x2022, // 0x95 - Bullet + 0x2013, // 0x96 - En Dash + 0x2014, // 0x97 - Em Dash + 0x02dc, // 0x98 - Small Tilde + 0x2122, // 0x99 - Trade Mark Sign + 0x0161, // 0x9a - Latin Small Letter S With Caron + 0x203a, // 0x9b - Single Right-Pointing Angle Quotation Mark + 0x0153, // 0x9c - Latin Small Ligature Oe + 0x009d, // 0x9d - + 0x017e, // 0x9e - Latin Small Letter Z With Caron + 0x0178, // 0x9f - Latin Capital Letter Y With Diaeresis + + 0x00a0, // 0xa0 - No-Break Space + 0x00a1, // 0xa1 - Inverted Exclamation Mark + 0x00a2, // 0xa2 - Cent Sign + 0x00a3, // 0xa3 - Pound Sign + 0x00a4, // 0xa4 - Currency Sign + 0x00a5, // 0xa5 - Yen Sign + 0x00a6, // 0xa6 - Broken Bar + 0x00a7, // 0xa7 - Section Sign + 0x00a8, // 0xa8 - Diaeresis + 0x00a9, // 0xa9 - Copyright Sign + 0x00aa, // 0xaa - Feminine Ordinal Indicator + 0x00ab, // 0xab - Left-Pointing Double Angle Quotation Mark + 0x00ac, // 0xac - Not Sign + 0x00ad, // 0xad - Soft Hyphen + 0x00ae, // 0xae - Registered Sign + 0x00af, // 0xaf - Macron + + 0x00b0, // 0xb0 - Degree Sign + 0x00b1, // 0xb1 - Plus-Minus Sign + 0x00b2, // 0xb2 - Superscript Two + 0x00b3, // 0xb3 - Superscript Three + 0x00b4, // 0xb4 - Acute Accent + 0x00b5, // 0xb5 - Micro Sign + 0x00b6, // 0xb6 - Pilcrow Sign + 0x00b7, // 0xb7 - Middle Dot + 0x00b8, // 0xb8 - Cedilla + 0x00b9, // 0xb9 - Superscript One + 0x00ba, // 0xba - Masculine Ordinal Indicator + 0x00bb, // 0xbb - Right-Pointing Double Angle Quotation Mark + 0x00bc, // 0xbc - Vulgar Fraction One Quarter + 0x00bd, // 0xbd - Vulgar Fraction One Half + 0x00be, // 0xbe - Vulgar Fraction Three Quarters + 0x00bf, // 0xbf - Inverted Question Mark + + 0x00c0, // 0xc0 - Latin Capital Letter A With Grave + 0x00c1, // 0xc1 - Latin Capital Letter A With Acute + 0x00c2, // 0xc2 - Latin Capital Letter A With Circumflex + 0x00c3, // 0xc3 - Latin Capital Letter A With Tilde + 0x00c4, // 0xc4 - Latin Capital Letter A With Diaeresis + 0x00c5, // 0xc5 - Latin Capital Letter A With Ring Above + 0x00c6, // 0xc6 - Latin Capital Ligature Ae + 0x00c7, // 0xc7 - Latin Capital Letter C With Cedilla + 0x00c8, // 0xc8 - Latin Capital Letter E With Grave + 0x00c9, // 0xc9 - Latin Capital Letter E With Acute + 0x00ca, // 0xca - Latin Capital Letter E With Circumflex + 0x00cb, // 0xcb - Latin Capital Letter E With Diaeresis + 0x00cc, // 0xcc - Latin Capital Letter I With Grave + 0x00cd, // 0xcd - Latin Capital Letter I With Acute + 0x00ce, // 0xce - Latin Capital Letter I With Circumflex + 0x00cf, // 0xcf - Latin Capital Letter I With Diaeresis + + 0x00d0, // 0xd0 - Latin Capital Letter Eth + 0x00d1, // 0xd1 - Latin Capital Letter N With Tilde + 0x00d2, // 0xd2 - Latin Capital Letter O With Grave + 0x00d3, // 0xd3 - Latin Capital Letter O With Acute + 0x00d4, // 0xd4 - Latin Capital Letter O With Circumflex + 0x00d5, // 0xd5 - Latin Capital Letter O With Tilde + 0x00d6, // 0xd6 - Latin Capital Letter O With Diaeresis + 0x00d7, // 0xd7 - Multiplication Sign + 0x00d8, // 0xd8 - Latin Capital Letter O With Stroke + 0x00d9, // 0xd9 - Latin Capital Letter U With Grave + 0x00da, // 0xda - Latin Capital Letter U With Acute + 0x00db, // 0xdb - Latin Capital Letter U With Circumflex + 0x00dc, // 0xdc - Latin Capital Letter U With Diaeresis + 0x00dd, // 0xdd - Latin Capital Letter Y With Acute + 0x00de, // 0xde - Latin Capital Letter Thorn + 0x00df, // 0xdf - Latin Small Letter Sharp S + + 0x00e0, // 0xe0 - Latin Small Letter A With Grave + 0x00e1, // 0xe1 - Latin Small Letter A With Acute + 0x00e2, // 0xe2 - Latin Small Letter A With Circumflex + 0x00e3, // 0xe3 - Latin Small Letter A With Tilde + 0x00e4, // 0xe4 - Latin Small Letter A With Diaeresis + 0x00e5, // 0xe5 - Latin Small Letter A With Ring Above + 0x00e6, // 0xe6 - Latin Small Ligature Ae + 0x00e7, // 0xe7 - Latin Small Letter C With Cedilla + 0x00e8, // 0xe8 - Latin Small Letter E With Grave + 0x00e9, // 0xe9 - Latin Small Letter E With Acute + 0x00ea, // 0xea - Latin Small Letter E With Circumflex + 0x00eb, // 0xeb - Latin Small Letter E With Diaeresis + 0x00ec, // 0xec - Latin Small Letter I With Grave + 0x00ed, // 0xed - Latin Small Letter I With Acute + 0x00ee, // 0xee - Latin Small Letter I With Circumflex + 0x00ef, // 0xef - Latin Small Letter I With Diaeresis + + 0x00f0, // 0xf0 - Latin Small Letter Eth + 0x00f1, // 0xf1 - Latin Small Letter N With Tilde + 0x00f2, // 0xf2 - Latin Small Letter O With Grave + 0x00f3, // 0xf3 - Latin Small Letter O With Acute + 0x00f4, // 0xf4 - Latin Small Letter O With Circumflex + 0x00f5, // 0xf5 - Latin Small Letter O With Tilde + 0x00f6, // 0xf6 - Latin Small Letter O With Diaeresis + 0x00f7, // 0xf7 - Division Sign + 0x00f8, // 0xf8 - Latin Small Letter O With Stroke + 0x00f9, // 0xf9 - Latin Small Letter U With Grave + 0x00fa, // 0xfa - Latin Small Letter U With Acute + 0x00fb, // 0xfb - Latin Small Letter U With Circumflex + 0x00fc, // 0xfc - Latin Small Letter U With Diaeresis + 0x00fd, // 0xfd - Latin Small Letter Y With Acute + 0x00fe, // 0xfe - Latin Small Letter Thorn + 0x00ff // 0xff - Latin Small Letter Y With Diaeresis + }; //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool NodeNaming::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - bool res = false; - if( _requestFlags & RequestFlag_Session ) - { - if( Node* node = GetNodeUnsafe() ) - { - if( node->m_nodeName == "" ) + bool NodeNaming::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) { - // If we don't already have a user-defined name, fetch it from the device - res |= RequestValue( _requestFlags, NodeNamingCmd_Get, _instance, _queue ); - } + bool res = false; + if (_requestFlags & RequestFlag_Session) + { + if (Node* node = GetNodeUnsafe()) + { + if (node->m_nodeName == "") + { + // If we don't already have a user-defined name, fetch it from the device + res |= RequestValue(_requestFlags, NodeNamingCmd_Get, _instance, _queue); + } + + if (node->m_location == "") + { + // If we don't already have a user-defined location, fetch it from the device + res |= RequestValue(_requestFlags, NodeNamingCmd_LocationGet, _instance, _queue); + } + } + } - if( node->m_location == "" ) - { - // If we don't already have a user-defined location, fetch it from the device - res |= RequestValue( _requestFlags, NodeNamingCmd_LocationGet, _instance, _queue ); + return res; } - } - } - - return res; -} //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool NodeNaming::RequestValue -( - uint32 const _requestFlags, - uint16 const _getTypeEnum, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _instance != 1 ) - { - // This command class doesn't work with multiple instances - return false; - } + bool NodeNaming::RequestValue(uint32 const _requestFlags, uint16 const _getTypeEnum, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_instance != 1) + { + // This command class doesn't work with multiple instances + return false; + } - Msg* msg; - if( _getTypeEnum == NodeNamingCmd_Get ) - { - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - msg = new Msg( "NodeNamingCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( NodeNamingCmd_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "NodeNamingCmd_Get Not Supported on this node"); - } - return false; - } - - if( _getTypeEnum == NodeNamingCmd_LocationGet ) - { - // If we don't already have a user-defined name, fetch it from the device - msg = new Msg( "NodeNamingCmd_LocationGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( NodeNamingCmd_LocationGet ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } - return false; -} + Msg* msg; + if (_getTypeEnum == NodeNamingCmd_Get) + { + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + msg = new Msg("NodeNamingCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(NodeNamingCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "NodeNamingCmd_Get Not Supported on this node"); + } + return false; + } + + if (_getTypeEnum == NodeNamingCmd_LocationGet) + { + // If we don't already have a user-defined name, fetch it from the device + msg = new Msg("NodeNamingCmd_LocationGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(NodeNamingCmd_LocationGet); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool NodeNaming::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - bool updated = false; - if( Node* node = GetNodeUnsafe() ) - { - if( NodeNamingCmd_Report == (NodeNamingCmd)_data[0] ) - { - string name = ExtractString( _data, _length ); - if( node->m_nodeName == "" ) + bool NodeNaming::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) { - // We only overwrite the name if it is empty - node->m_nodeName = name; - Log::Write( LogLevel_Info, GetNodeId(), "Received the name: %s.", name.c_str() ); - updated = true; - } - } - else if( NodeNamingCmd_LocationReport == (NodeNamingCmd)_data[0] ) - { - string location = ExtractString( _data, _length ); - if( node->m_location == "" ) - { - // We only overwrite the location if it is empty - node->m_location = location; - Log::Write( LogLevel_Info, GetNodeId(), "Received the location: %s.", location.c_str() ); - updated = true; - } - } - } + bool updated = false; + if (Node* node = GetNodeUnsafe()) + { + if (NodeNamingCmd_Report == (NodeNamingCmd) _data[0]) + { + string name = ExtractString(_data, _length); + if (node->m_nodeName == "") + { + // We only overwrite the name if it is empty + node->m_nodeName = name; + Log::Write(LogLevel_Info, GetNodeId(), "Received the name: %s.", name.c_str()); + updated = true; + } + } + else if (NodeNamingCmd_LocationReport == (NodeNamingCmd) _data[0]) + { + string location = ExtractString(_data, _length); + if (node->m_location == "") + { + // We only overwrite the location if it is empty + node->m_location = location; + Log::Write(LogLevel_Info, GetNodeId(), "Received the location: %s.", location.c_str()); + updated = true; + } + } + } - if( updated ) - { - Notification* notification = new Notification( Notification::Type_NodeNaming ); - notification->SetHomeAndNodeIds( GetHomeId(), GetNodeId() ); - GetDriver()->QueueNotification( notification ); - } + if (updated) + { + Notification* notification = new Notification(Notification::Type_NodeNaming); + notification->SetHomeAndNodeIds(GetHomeId(), GetNodeId()); + GetDriver()->QueueNotification(notification); + } - return true; -} + return true; + } //----------------------------------------------------------------------------- // // Set the name in the device //----------------------------------------------------------------------------- -void NodeNaming::SetName -( - string const& _name -) -{ - size_t length = _name.size(); - if( length > 16 ) - { - length = 16; - } - - Log::Write( LogLevel_Info, GetNodeId(), "NodeNaming::Set - Naming to '%s'", _name.c_str() ); - Msg* msg = new Msg( "NodeNamingCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->Append( GetNodeId() ); - msg->Append( (uint8)(length + 3) ); - msg->Append( GetCommandClassId() ); - msg->Append( NodeNamingCmd_Set ); - msg->Append( (uint8)StringEncoding_ASCII ); - - for( uint32 i=0; iAppend( _name[i] ); - } + void NodeNaming::SetName(string const& _name) + { + size_t length = _name.size(); + if (length > 16) + { + length = 16; + } + + Log::Write(LogLevel_Info, GetNodeId(), "NodeNaming::Set - Naming to '%s'", _name.c_str()); + Msg* msg = new Msg("NodeNamingCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->Append(GetNodeId()); + msg->Append((uint8) (length + 3)); + msg->Append(GetCommandClassId()); + msg->Append(NodeNamingCmd_Set); + msg->Append((uint8) StringEncoding_ASCII); + + for (uint32 i = 0; i < length; ++i) + { + msg->Append(_name[i]); + } - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); -} + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + } //----------------------------------------------------------------------------- // // Set the location in the device //----------------------------------------------------------------------------- -void NodeNaming::SetLocation -( - string const& _location -) -{ - size_t length = _location.size(); - if( length > 16 ) - { - length = 16; - } - - Log::Write( LogLevel_Info, GetNodeId(), "NodeNaming::SetLocation - Setting location to '%s'", _location.c_str() ); - Msg* msg = new Msg( "NodeNamingCmd_LocationSet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->Append( GetNodeId() ); - msg->Append( (uint8)(length + 3) ); - msg->Append( GetCommandClassId() ); - msg->Append( NodeNamingCmd_LocationSet ); - msg->Append( (uint8)StringEncoding_ASCII ); - - for( uint32 i=0; iAppend( _location[i] ); - } + void NodeNaming::SetLocation(string const& _location) + { + size_t length = _location.size(); + if (length > 16) + { + length = 16; + } - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); -} + Log::Write(LogLevel_Info, GetNodeId(), "NodeNaming::SetLocation - Setting location to '%s'", _location.c_str()); + Msg* msg = new Msg("NodeNamingCmd_LocationSet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->Append(GetNodeId()); + msg->Append((uint8) (length + 3)); + msg->Append(GetCommandClassId()); + msg->Append(NodeNamingCmd_LocationSet); + msg->Append((uint8) StringEncoding_ASCII); + + for (uint32 i = 0; i < length; ++i) + { + msg->Append(_location[i]); + } + + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + } //----------------------------------------------------------------------------- // // Extract a string from the report data //----------------------------------------------------------------------------- -string OpenZWave::ExtractString -( - uint8 const* _data, - uint32 const _length -) -{ - uint8 i; - char str[32]; - uint32 pos = 0; - - str[0] = 0; - StringEncoding encoding = (StringEncoding)( _data[1] & 0x07 ); + std::string ExtractString(uint8 const* _data, uint32 const _length) + { + uint8 i; + char str[32]; + uint32 pos = 0; - if( _length >= 3 ) - { - // Get the length of the string (maximum allowed is 16 bytes) - uint8 numBytes = _length - 3; - if( numBytes > 16 ) - { - numBytes = 16; - } + str[0] = 0; + StringEncoding encoding = (StringEncoding) (_data[1] & 0x07); - switch( encoding ) - { - case StringEncoding_ASCII: - { - // Copy data as-is - for( i=0; i= 3) { - str[pos++] = _data[i+2]; - } - break; - } - case StringEncoding_ExtendedASCII: - { - // Convert Extended ASCII characters to UTF-8 - for( i=0; i= 0x80 ) + // Get the length of the string (maximum allowed is 16 bytes) + uint8 numBytes = _length - 3; + if (numBytes > 16) { - uint16 utf16 = c_extendedAsciiToUnicode[ch-0x80]; - pos = ConvertUFT16ToUTF8( utf16, str, pos ); + numBytes = 16; } - else + + switch (encoding) { - str[pos++] = (char)ch; + case StringEncoding_ASCII: + { + // Copy data as-is + for (i = 0; i < numBytes; ++i) + { + str[pos++] = _data[i + 2]; + } + break; + } + case StringEncoding_ExtendedASCII: + { + // Convert Extended ASCII characters to UTF-8 + for (i = 0; i < numBytes; ++i) + { + uint8 ch = _data[i + 2]; + if (ch >= 0x80) + { + uint16 utf16 = c_extendedAsciiToUnicode[ch - 0x80]; + pos = ConvertUFT16ToUTF8(utf16, str, pos); + } + else + { + str[pos++] = (char) ch; + } + } + break; + } + case StringEncoding_UTF16: + { + // Convert UTF-16 characters to UTF-8 + for (i = 0; i < numBytes; i += 2) + { + uint16 utf16 = (((uint16) _data[i + 2]) << 8) | (uint16) _data[i + 3]; + pos = ConvertUFT16ToUTF8(utf16, str, pos); + } + break; + } + default: + { + } } - } - break; - } - case StringEncoding_UTF16: - { - // Convert UTF-16 characters to UTF-8 - for( i=0; i // Convert a UTF-16 string into UTF-8 encoding. //----------------------------------------------------------------------------- -uint32 OpenZWave::ConvertUFT16ToUTF8 -( - uint16 _utf16, - char* _buffer, - uint32 pos -) -{ - static uint16 surrogate = 0; - - if( ( surrogate != 0 ) && ( ( _utf16 & 0xdc00 ) == 0xdc00 ) ) - { - // UTF-16 surrogate character pair converts to four UTF-8 characters. - // We have the second member of the pair, so we can do the conversion now. - _buffer[pos++] = (char)( ((surrogate>>7) & 0x0007) | 0x00f0 ); - _buffer[pos++] = (char)( ((surrogate>>1) & 0x0020) | ((surrogate>>2) & 0x000f) | 0x0090 ); - _buffer[pos++] = (char)( ((_utf16>>6) & 0x000f) | ((surrogate<<4) & 0x0030) | 0x0080 ); - _buffer[pos++] = (char)( (_utf16 & 0x003f) | 0x0080 ); - } - else - { - surrogate = 0; - if( _utf16 & 0xff80 ) - { - if( _utf16 & 0xf800 ) + uint32 ConvertUFT16ToUTF8(uint16 _utf16, char* _buffer, uint32 pos) { - if( ( _utf16 & 0xd800 ) == 0xd800 ) + static uint16 surrogate = 0; + + if ((surrogate != 0) && ((_utf16 & 0xdc00) == 0xdc00)) { // UTF-16 surrogate character pair converts to four UTF-8 characters. - // We have the first member of the pair, so we store it for next time. - surrogate = _utf16; + // We have the second member of the pair, so we can do the conversion now. + _buffer[pos++] = (char) (((surrogate >> 7) & 0x0007) | 0x00f0); + _buffer[pos++] = (char) (((surrogate >> 1) & 0x0020) | ((surrogate >> 2) & 0x000f) | 0x0090); + _buffer[pos++] = (char) (((_utf16 >> 6) & 0x000f) | ((surrogate << 4) & 0x0030) | 0x0080); + _buffer[pos++] = (char) ((_utf16 & 0x003f) | 0x0080); } else { - // UTF-16 character can be represented by three UTF-8 characters. - _buffer[pos++] = (char)( (_utf16>>12) | 0x00e0 ); - _buffer[pos++] = (char)( ((_utf16>>6) & 0x003f) | 0x0080 ); - _buffer[pos++] = (char)( (_utf16 & 0x003f) | 0x0080 ); + surrogate = 0; + if (_utf16 & 0xff80) + { + if (_utf16 & 0xf800) + { + if ((_utf16 & 0xd800) == 0xd800) + { + // UTF-16 surrogate character pair converts to four UTF-8 characters. + // We have the first member of the pair, so we store it for next time. + surrogate = _utf16; + } + else + { + // UTF-16 character can be represented by three UTF-8 characters. + _buffer[pos++] = (char) ((_utf16 >> 12) | 0x00e0); + _buffer[pos++] = (char) (((_utf16 >> 6) & 0x003f) | 0x0080); + _buffer[pos++] = (char) ((_utf16 & 0x003f) | 0x0080); + } + } + else + { + // UTF-16 character can be represented by two UTF-8 characters. + _buffer[pos++] = (char) ((_utf16 >> 6) | 0x00c0); + _buffer[pos++] = (char) ((_utf16 & 0x003f) | 0x0080); + } + } + else + { + // UTF-16 character matches single ascii character. + _buffer[pos++] = (char) _utf16; + } } - } - else - { - // UTF-16 character can be represented by two UTF-8 characters. - _buffer[pos++] = (char)( (_utf16>>6) | 0x00c0 ); - _buffer[pos++] = (char)( (_utf16 & 0x003f) | 0x0080 ); - } - } - else - { - // UTF-16 character matches single ascii character. - _buffer[pos++] = (char)_utf16; - } - } - - return pos; -} - + return pos; + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/NodeNaming.h b/cpp/src/command_classes/NodeNaming.h index c280599cac..85e1cca42a 100644 --- a/cpp/src/command_classes/NodeNaming.h +++ b/cpp/src/command_classes/NodeNaming.h @@ -32,48 +32,71 @@ namespace OpenZWave { - - /** \brief Extract a String from a Z-Wave Encoded Packet - * \ingroup CommandClass - * - * this function is used by the NodeNaming CC as well as the Alarm CC - */ - string ExtractString( uint8 const* _data, uint32 const _length ); - - /** \brief Convert from UTF16 to UTF8 - * \ingroup CommandClass - * - * this function is used by the NodeNaming CC as well as the Alarm CC - */ - uint32 ConvertUFT16ToUTF8( uint16 _utf16, char* _buffer, uint32 pos ); - - - /** \brief Implements COMMAND_CLASS_NODE_NAMING (0x77), a Z-Wave device command class. - * \ingroup CommandClass - */ - class NodeNaming: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new NodeNaming( _homeId, _nodeId ); } - virtual ~NodeNaming(){} + namespace CC + { + /** \brief Extract a String from a Z-Wave Encoded Packet + * \ingroup CommandClass + * + * this function is used by the NodeNaming CC as well as the Alarm CC + */ + string ExtractString(uint8 const* _data, uint32 const _length); + + /** \brief Convert from UTF16 to UTF8 + * \ingroup CommandClass + * + * this function is used by the NodeNaming CC as well as the Alarm CC + */ + uint32 ConvertUFT16ToUTF8(uint16 _utf16, char* _buffer, uint32 pos); - static uint8 const StaticGetCommandClassId(){ return 0x77; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_NODE_NAMING"; } + /** \brief Implements COMMAND_CLASS_NODE_NAMING (0x77), a Z-Wave device command class. + * \ingroup CommandClass + */ + class NodeNaming: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new NodeNaming(_homeId, _nodeId); + } + virtual ~NodeNaming() + { + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); + static uint8 const StaticGetCommandClassId() + { + return 0x77; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_NODE_NAMING"; + } - void SetName( string const& _name ); - void SetLocation( string const& _location ); + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; - private: - NodeNaming( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} - }; + void SetName(string const& _name); + void SetLocation(string const& _location); + private: + NodeNaming(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + } + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/Powerlevel.cpp b/cpp/src/command_classes/Powerlevel.cpp index 198d487207..e71499ce30 100644 --- a/cpp/src/command_classes/Powerlevel.cpp +++ b/cpp/src/command_classes/Powerlevel.cpp @@ -39,467 +39,413 @@ #include "value_classes/ValueList.h" #include "value_classes/ValueButton.h" -using namespace OpenZWave; - -enum PowerlevelCmd -{ - PowerlevelCmd_Set = 0x01, - PowerlevelCmd_Get = 0x02, - PowerlevelCmd_Report = 0x03, - PowerlevelCmd_TestNodeSet = 0x04, - PowerlevelCmd_TestNodeGet = 0x05, - PowerlevelCmd_TestNodeReport = 0x06 -}; - -enum +namespace OpenZWave { - PowerlevelIndex_Powerlevel = 0, - PowerlevelIndex_Timeout, - PowerlevelIndex_Set, - PowerlevelIndex_TestNode, - PowerlevelIndex_TestPowerlevel, - PowerlevelIndex_TestFrames, - PowerlevelIndex_Test, - PowerlevelIndex_Report, - PowerlevelIndex_TestStatus, - PowerlevelIndex_TestAckFrames -}; + namespace Internal + { + namespace CC + { -static char const* c_powerLevelNames[] = -{ - "Normal", - "-1dB", - "-2dB", - "-3dB", - "-4dB", - "-5dB", - "-6dB", - "-7dB", - "-8dB", - "-9dB", - "Unknown" -}; + enum PowerlevelCmd + { + PowerlevelCmd_Set = 0x01, + PowerlevelCmd_Get = 0x02, + PowerlevelCmd_Report = 0x03, + PowerlevelCmd_TestNodeSet = 0x04, + PowerlevelCmd_TestNodeGet = 0x05, + PowerlevelCmd_TestNodeReport = 0x06 + }; -static char const* c_powerLevelStatusNames[] = -{ - "Failed", - "Success", - "In Progress", - "Unknown" -}; + static char const* c_powerLevelNames[] = + { "Normal", "-1dB", "-2dB", "-3dB", "-4dB", "-5dB", "-6dB", "-7dB", "-8dB", "-9dB", "Unknown" }; + static char const* c_powerLevelStatusNames[] = + { "Failed", "Success", "In Progress", "Unknown" }; //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool Powerlevel::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _requestFlags & RequestFlag_Session ) - { - return RequestValue( _requestFlags, 0, _instance, _queue ); - } + bool Powerlevel::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_requestFlags & RequestFlag_Session) + { + return RequestValue(_requestFlags, 0, _instance, _queue); + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool Powerlevel::RequestValue -( - uint32 const _requestFlags, - uint16 const _index, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _index == 0 ) - { - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Msg* msg = new Msg( "PowerlevelCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( PowerlevelCmd_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "Powerlevel_Get Not Supported on this node"); - } - } - return false; -} + bool Powerlevel::RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_index == 0) + { + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Msg* msg = new Msg("PowerlevelCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(PowerlevelCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "Powerlevel_Get Not Supported on this node"); + } + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool Powerlevel::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if( PowerlevelCmd_Report == (PowerlevelCmd)_data[0] ) - { - PowerLevelEnum powerLevel = (PowerLevelEnum)_data[1]; - if (powerLevel > 9) /* size of c_powerLevelNames minus Unknown*/ - { - Log::Write (LogLevel_Warning, GetNodeId(), "powerLevel Value was greater than range. Setting to Invalid"); - powerLevel = (PowerLevelEnum)10; - } - uint8 timeout = _data[2]; - - Log::Write( LogLevel_Info, GetNodeId(), "Received a PowerLevel report: PowerLevel=%s, Timeout=%d", c_powerLevelNames[powerLevel], timeout ); - if( ValueList* value = static_cast( GetValue( _instance, PowerlevelIndex_Powerlevel ) ) ) - { - value->OnValueRefreshed( (int)powerLevel ); - value->Release(); - } - if( ValueByte* value = static_cast( GetValue( _instance, PowerlevelIndex_Timeout ) ) ) - { - value->OnValueRefreshed( timeout ); - value->Release(); - } - return true; - } - - if( PowerlevelCmd_TestNodeReport == (PowerlevelCmd)_data[0] ) - { - uint8 testNode = _data[1]; - PowerLevelStatusEnum status = (PowerLevelStatusEnum)_data[2]; - uint16 ackCount = (((uint16)_data[3])<<8) | (uint16)_data[4]; - - if (status > 2) /* size of c_powerLevelStatusNames minus Unknown */ - { - Log::Write (LogLevel_Warning, GetNodeId(), "status Value was greater than range. Setting to Unknown"); - status = (PowerLevelStatusEnum)3; - } - - Log::Write( LogLevel_Info, GetNodeId(), "Received a PowerLevel Test Node report: Test Node=%d, Status=%s, Test Frame ACK Count=%d", testNode, c_powerLevelStatusNames[status], ackCount ); - if( ValueByte* value = static_cast( GetValue( _instance, PowerlevelIndex_TestNode ) ) ) - { - value->OnValueRefreshed( testNode ); - value->Release(); - } - if( ValueList* value = static_cast( GetValue( _instance, PowerlevelIndex_TestStatus ) ) ) - { - value->OnValueRefreshed( (int)status ); - value->Release(); - } - if( ValueShort* value = static_cast( GetValue( _instance, PowerlevelIndex_TestAckFrames ) ) ) - { - value->OnValueRefreshed( (short)ackCount ); - value->Release(); - } - return true; - } - return false; -} - -//----------------------------------------------------------------------------- -// -// Set a value on the Z-Wave device -//----------------------------------------------------------------------------- -bool Powerlevel::SetValue -( - Value const& _value -) -{ - bool res = false; - uint8 instance = _value.GetID().GetInstance(); - - switch( _value.GetID().GetIndex() ) - { - case PowerlevelIndex_Powerlevel: - { - if( ValueList* value = static_cast( GetValue( instance, PowerlevelIndex_Powerlevel ) ) ) - { - ValueList::Item const *item = (static_cast( &_value))->GetItem(); - if (item != NULL) - value->OnValueRefreshed( item->m_value ); - value->Release(); - } - res = true; - break; - } - case PowerlevelIndex_Timeout: - { - if( ValueByte* value = static_cast( GetValue( instance, PowerlevelIndex_Timeout ) ) ) - { - value->OnValueRefreshed( (static_cast( &_value))->GetValue() ); - value->Release(); - } - res = true; - break; - } - case PowerlevelIndex_Set: - { - // Set - if( ValueButton* button = static_cast( GetValue( instance, PowerlevelIndex_Set ) ) ) + bool Powerlevel::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) { - if( button->IsPressed() ) + if (PowerlevelCmd_Report == (PowerlevelCmd) _data[0]) { - res = Set( instance ); + PowerLevelEnum powerLevel = (PowerLevelEnum) _data[1]; + if (powerLevel > 9) /* size of c_powerLevelNames minus Unknown*/ + { + Log::Write(LogLevel_Warning, GetNodeId(), "powerLevel Value was greater than range. Setting to Invalid"); + powerLevel = (PowerLevelEnum) 10; + } + uint8 timeout = _data[2]; + + Log::Write(LogLevel_Info, GetNodeId(), "Received a PowerLevel report: PowerLevel=%s, Timeout=%d", c_powerLevelNames[powerLevel], timeout); + if (Internal::VC::ValueList* value = static_cast(GetValue(_instance, ValueID_Index_PowerLevel::Powerlevel))) + { + value->OnValueRefreshed((int) powerLevel); + value->Release(); + } + if (Internal::VC::ValueByte* value = static_cast(GetValue(_instance, ValueID_Index_PowerLevel::Timeout))) + { + value->OnValueRefreshed(timeout); + value->Release(); + } + return true; } - button->Release(); - } - break; - } - case PowerlevelIndex_TestNode: - { - if( ValueByte* value = static_cast( GetValue( instance, PowerlevelIndex_TestNode ) ) ) - { - value->OnValueRefreshed( (static_cast( &_value))->GetValue() ); - value->Release(); - } - res = true; - break; - } - case PowerlevelIndex_TestPowerlevel: - { - if( ValueList* value = static_cast( GetValue( instance, PowerlevelIndex_TestPowerlevel ) ) ) - { - ValueList::Item const *item = (static_cast( &_value))->GetItem(); - if (item != NULL) - value->OnValueRefreshed( item->m_value ); - value->Release(); - } - res = true; - break; - } - case PowerlevelIndex_TestFrames: - { - if( ValueShort* value = static_cast( GetValue( instance, PowerlevelIndex_TestFrames ) ) ) - { - value->OnValueRefreshed( (static_cast( &_value))->GetValue() ); - value->Release(); - } - res = true; - break; - } - case PowerlevelIndex_Test: - { - // Test - if( ValueButton* button = static_cast( GetValue( instance, PowerlevelIndex_Test ) ) ) - { - if( button->IsPressed() ) + + if (PowerlevelCmd_TestNodeReport == (PowerlevelCmd) _data[0]) { - res = Test( instance ); + uint8 testNode = _data[1]; + PowerLevelStatusEnum status = (PowerLevelStatusEnum) _data[2]; + uint16 ackCount = (((uint16) _data[3]) << 8) | (uint16) _data[4]; + + if (status > 2) /* size of c_powerLevelStatusNames minus Unknown */ + { + Log::Write(LogLevel_Warning, GetNodeId(), "status Value was greater than range. Setting to Unknown"); + status = (PowerLevelStatusEnum) 3; + } + + Log::Write(LogLevel_Info, GetNodeId(), "Received a PowerLevel Test Node report: Test Node=%d, Status=%s, Test Frame ACK Count=%d", testNode, c_powerLevelStatusNames[status], ackCount); + if (Internal::VC::ValueByte* value = static_cast(GetValue(_instance, ValueID_Index_PowerLevel::TestNode))) + { + value->OnValueRefreshed(testNode); + value->Release(); + } + if (Internal::VC::ValueList* value = static_cast(GetValue(_instance, ValueID_Index_PowerLevel::TestStatus))) + { + value->OnValueRefreshed((int) status); + value->Release(); + } + if (Internal::VC::ValueShort* value = static_cast(GetValue(_instance, ValueID_Index_PowerLevel::TestAckFrames))) + { + value->OnValueRefreshed((short) ackCount); + value->Release(); + } + return true; } - button->Release(); + return false; } - break; - } - case PowerlevelIndex_Report: - { - // Test - if( ValueButton* button = static_cast( GetValue( instance, PowerlevelIndex_Report ) ) ) + +//----------------------------------------------------------------------------- +// +// Set a value on the Z-Wave device +//----------------------------------------------------------------------------- + bool Powerlevel::SetValue(Internal::VC::Value const& _value) { - if( button->IsPressed() ) + bool res = false; + uint8 instance = _value.GetID().GetInstance(); + + switch (_value.GetID().GetIndex()) { - res = Report( instance ); + case ValueID_Index_PowerLevel::Powerlevel: + { + if (Internal::VC::ValueList* value = static_cast(GetValue(instance, ValueID_Index_PowerLevel::Powerlevel))) + { + Internal::VC::ValueList::Item const *item = (static_cast(&_value))->GetItem(); + if (item != NULL) + value->OnValueRefreshed(item->m_value); + value->Release(); + } + res = true; + break; + } + case ValueID_Index_PowerLevel::Timeout: + { + if (Internal::VC::ValueByte* value = static_cast(GetValue(instance, ValueID_Index_PowerLevel::Timeout))) + { + value->OnValueRefreshed((static_cast(&_value))->GetValue()); + value->Release(); + } + res = true; + break; + } + case ValueID_Index_PowerLevel::Set: + { + // Set + if (Internal::VC::ValueButton* button = static_cast(GetValue(instance, ValueID_Index_PowerLevel::Set))) + { + if (button->IsPressed()) + { + res = Set(instance); + } + button->Release(); + } + break; + } + case ValueID_Index_PowerLevel::TestNode: + { + if (Internal::VC::ValueByte* value = static_cast(GetValue(instance, ValueID_Index_PowerLevel::TestNode))) + { + value->OnValueRefreshed((static_cast(&_value))->GetValue()); + value->Release(); + } + res = true; + break; + } + case ValueID_Index_PowerLevel::TestPowerlevel: + { + if (Internal::VC::ValueList* value = static_cast(GetValue(instance, ValueID_Index_PowerLevel::TestPowerlevel))) + { + Internal::VC::ValueList::Item const *item = (static_cast(&_value))->GetItem(); + if (item != NULL) + value->OnValueRefreshed(item->m_value); + value->Release(); + } + res = true; + break; + } + case ValueID_Index_PowerLevel::TestFrames: + { + if (Internal::VC::ValueShort* value = static_cast(GetValue(instance, ValueID_Index_PowerLevel::TestFrames))) + { + value->OnValueRefreshed((static_cast(&_value))->GetValue()); + value->Release(); + } + res = true; + break; + } + case ValueID_Index_PowerLevel::Test: + { + // Test + if (Internal::VC::ValueButton* button = static_cast(GetValue(instance, ValueID_Index_PowerLevel::Test))) + { + if (button->IsPressed()) + { + res = Test(instance); + } + button->Release(); + } + break; + } + case ValueID_Index_PowerLevel::Report: + { + // Test + if (Internal::VC::ValueButton* button = static_cast(GetValue(instance, ValueID_Index_PowerLevel::Report))) + { + if (button->IsPressed()) + { + res = Report(instance); + } + button->Release(); + } + break; + } } - button->Release(); + return res; } - break; - } - } - return res; -} //----------------------------------------------------------------------------- // // Set the transmit power of a node for a specified time //----------------------------------------------------------------------------- -bool Powerlevel::Set -( - uint8 const _instance -) -{ - PowerLevelEnum powerLevel = PowerLevel_Normal; - uint8 timeout; - - if( ValueList* value = static_cast( GetValue( _instance, PowerlevelIndex_Powerlevel ) ) ) - { - ValueList::Item const *item = value->GetItem(); - if (item != NULL) - powerLevel = (PowerLevelEnum)item->m_value; - value->Release(); - } - else - { - return false; - } + bool Powerlevel::Set(uint8 const _instance) + { + PowerLevelEnum powerLevel = PowerLevel_Normal; + uint8 timeout; - if( ValueByte* value = static_cast( GetValue( _instance, PowerlevelIndex_Timeout ) ) ) - { - timeout = value->GetValue(); - value->Release(); - } - else - { - return false; - } - if (powerLevel > 9) /* size of c_powerLevelNames minus Unknown */ - { - Log::Write (LogLevel_Warning, GetNodeId(), "powerLevel Value was greater than range. Dropping"); - /* Drop it */ - return false; - } + if (Internal::VC::ValueList* value = static_cast(GetValue(_instance, ValueID_Index_PowerLevel::Powerlevel))) + { + Internal::VC::ValueList::Item const *item = value->GetItem(); + if (item != NULL) + powerLevel = (PowerLevelEnum) item->m_value; + value->Release(); + } + else + { + return false; + } + if (Internal::VC::ValueByte* value = static_cast(GetValue(_instance, ValueID_Index_PowerLevel::Timeout))) + { + timeout = value->GetValue(); + value->Release(); + } + else + { + return false; + } + if (powerLevel > 9) /* size of c_powerLevelNames minus Unknown */ + { + Log::Write(LogLevel_Warning, GetNodeId(), "powerLevel Value was greater than range. Dropping"); + /* Drop it */ + return false; + } - Log::Write( LogLevel_Info, GetNodeId(), "Setting the power level to %s for %d seconds", c_powerLevelNames[powerLevel], timeout ); - Msg* msg = new Msg( "PowerlevelCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 4 ); - msg->Append( GetCommandClassId() ); - msg->Append( PowerlevelCmd_Set ); - msg->Append( (uint8)powerLevel ); - msg->Append( timeout ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - return true; -} + Log::Write(LogLevel_Info, GetNodeId(), "Setting the power level to %s for %d seconds", c_powerLevelNames[powerLevel], timeout); + Msg* msg = new Msg("PowerlevelCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(4); + msg->Append(GetCommandClassId()); + msg->Append(PowerlevelCmd_Set); + msg->Append((uint8) powerLevel); + msg->Append(timeout); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return true; + } //----------------------------------------------------------------------------- // // Test node to node communications //----------------------------------------------------------------------------- -bool Powerlevel::Test -( - uint8 const _instance -) -{ - uint8 testNodeId; - PowerLevelEnum powerLevel = PowerLevel_Normal; - uint16 numFrames; - - if( ValueByte* value = static_cast( GetValue( _instance, PowerlevelIndex_TestNode ) ) ) - { - testNodeId = value->GetValue(); - value->Release(); - } - else - { - return false; - } + bool Powerlevel::Test(uint8 const _instance) + { + uint8 testNodeId; + PowerLevelEnum powerLevel = PowerLevel_Normal; + uint16 numFrames; - if( ValueList* value = static_cast( GetValue( _instance, PowerlevelIndex_TestPowerlevel ) ) ) - { - ValueList::Item const *item = value->GetItem(); - if (item != NULL) - powerLevel = (PowerLevelEnum)item->m_value; - value->Release(); - } - else - { - return false; - } + if (Internal::VC::ValueByte* value = static_cast(GetValue(_instance, ValueID_Index_PowerLevel::TestNode))) + { + testNodeId = value->GetValue(); + value->Release(); + } + else + { + return false; + } - if( ValueShort* value = static_cast( GetValue( _instance, PowerlevelIndex_TestFrames ) ) ) - { - numFrames = value->GetValue(); - value->Release(); - } - else - { - return false; - } - if (powerLevel > 9) /* size of c_powerLevelNames minus Unknown */ - { - Log::Write (LogLevel_Warning, GetNodeId(), "powerLevel Value was greater than range. Dropping"); - return false; - } + if (Internal::VC::ValueList* value = static_cast(GetValue(_instance, ValueID_Index_PowerLevel::TestPowerlevel))) + { + Internal::VC::ValueList::Item const *item = value->GetItem(); + if (item != NULL) + powerLevel = (PowerLevelEnum) item->m_value; + value->Release(); + } + else + { + return false; + } + if (Internal::VC::ValueShort* value = static_cast(GetValue(_instance, ValueID_Index_PowerLevel::TestFrames))) + { + numFrames = value->GetValue(); + value->Release(); + } + else + { + return false; + } + if (powerLevel > 9) /* size of c_powerLevelNames minus Unknown */ + { + Log::Write(LogLevel_Warning, GetNodeId(), "powerLevel Value was greater than range. Dropping"); + return false; + } - Log::Write( LogLevel_Info, GetNodeId(), "Running a Power Level Test: Target Node = %d, Power Level = %s, Number of Frames = %d", testNodeId, c_powerLevelNames[powerLevel], numFrames ); - Msg* msg = new Msg( "PowerlevelCmd_TestNodeSet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 6 ); - msg->Append( GetCommandClassId() ); - msg->Append( PowerlevelCmd_TestNodeSet ); - msg->Append( testNodeId ); - msg->Append( (uint8)powerLevel ); - msg->Append( (uint8)(numFrames >> 8) ); - msg->Append( (uint8)(numFrames & 0x00ff) ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - return true; -} + Log::Write(LogLevel_Info, GetNodeId(), "Running a Power Level Test: Target Node = %d, Power Level = %s, Number of Frames = %d", testNodeId, c_powerLevelNames[powerLevel], numFrames); + Msg* msg = new Msg("PowerlevelCmd_TestNodeSet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(6); + msg->Append(GetCommandClassId()); + msg->Append(PowerlevelCmd_TestNodeSet); + msg->Append(testNodeId); + msg->Append((uint8) powerLevel); + msg->Append((uint8) (numFrames >> 8)); + msg->Append((uint8) (numFrames & 0x00ff)); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return true; + } //----------------------------------------------------------------------------- // // Request test report //----------------------------------------------------------------------------- -bool Powerlevel::Report -( - uint8 const _instance -) -{ - Log::Write( LogLevel_Info, GetNodeId(), "Power Level Report" ); - Msg* msg = new Msg( "PowerlevelCmd_TestNodeGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 6 ); - msg->Append( GetCommandClassId() ); - msg->Append( PowerlevelCmd_TestNodeGet ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - return true; -} + bool Powerlevel::Report(uint8 const _instance) + { + Log::Write(LogLevel_Info, GetNodeId(), "Power Level Report"); + Msg* msg = new Msg("PowerlevelCmd_TestNodeGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(6); + msg->Append(GetCommandClassId()); + msg->Append(PowerlevelCmd_TestNodeGet); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return true; + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void Powerlevel::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - vector items; - - ValueList::Item item; - for( uint8 i=0; i<10; ++i ) - { - item.m_label = c_powerLevelNames[i]; - item.m_value = i; - items.push_back( item ); - } - - node->CreateValueList( ValueID::ValueGenre_System, GetCommandClassId(), _instance, PowerlevelIndex_Powerlevel, "Powerlevel", "dB", false, false, 1, items, 0, 0 ); - node->CreateValueByte( ValueID::ValueGenre_System, GetCommandClassId(), _instance, PowerlevelIndex_Timeout, "Timeout", "seconds", false, false, 0, 0 ); - node->CreateValueButton( ValueID::ValueGenre_System, GetCommandClassId(), _instance, PowerlevelIndex_Set, "Set Powerlevel", 0 ); - node->CreateValueByte( ValueID::ValueGenre_System, GetCommandClassId(), _instance, PowerlevelIndex_TestNode, "Test Node", "", false, false, 0, 0 ); - node->CreateValueList( ValueID::ValueGenre_System, GetCommandClassId(), _instance, PowerlevelIndex_TestPowerlevel, "Test Powerlevel", "dB", false, false, 1, items, 0, 0 ); - node->CreateValueShort( ValueID::ValueGenre_System, GetCommandClassId(), _instance, PowerlevelIndex_TestFrames, "Frame Count", "", false, false, 0, 0 ); - node->CreateValueButton( ValueID::ValueGenre_System, GetCommandClassId(), _instance, PowerlevelIndex_Test, "Test", 0 ); - node->CreateValueButton( ValueID::ValueGenre_System, GetCommandClassId(), _instance, PowerlevelIndex_Report, "Report", 0 ); - - items.clear(); - for( uint8 i=0; i<3; ++i ) - { - item.m_label = c_powerLevelStatusNames[i]; - item.m_value = i; - items.push_back( item ); - } - node->CreateValueList( ValueID::ValueGenre_System, GetCommandClassId(), _instance, PowerlevelIndex_TestStatus, "Test Status", "", true, false, 1, items, 0, 0 ); - node->CreateValueShort( ValueID::ValueGenre_System, GetCommandClassId(), _instance, PowerlevelIndex_TestAckFrames, "Acked Frames", "", true, false, 0, 0 ); - } -} + void Powerlevel::CreateVars(uint8 const _instance) + { + if (Node* node = GetNodeUnsafe()) + { + vector items; + + Internal::VC::ValueList::Item item; + for (uint8 i = 0; i < 10; ++i) + { + item.m_label = c_powerLevelNames[i]; + item.m_value = i; + items.push_back(item); + } + + node->CreateValueList(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_PowerLevel::Powerlevel, "Powerlevel", "dB", false, false, 1, items, 0, 0); + node->CreateValueByte(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_PowerLevel::Timeout, "Timeout", "seconds", false, false, 0, 0); + node->CreateValueButton(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_PowerLevel::Set, "Set Powerlevel", 0); + node->CreateValueByte(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_PowerLevel::TestNode, "Test Node", "", false, false, 0, 0); + node->CreateValueList(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_PowerLevel::TestPowerlevel, "Test Powerlevel", "dB", false, false, 1, items, 0, 0); + node->CreateValueShort(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_PowerLevel::TestFrames, "Frame Count", "", false, false, 0, 0); + node->CreateValueButton(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_PowerLevel::Test, "Test", 0); + node->CreateValueButton(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_PowerLevel::Report, "Report", 0); + + items.clear(); + for (uint8 i = 0; i < 3; ++i) + { + item.m_label = c_powerLevelStatusNames[i]; + item.m_value = i; + items.push_back(item); + } + node->CreateValueList(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_PowerLevel::TestStatus, "Test Status", "", true, false, 1, items, 0, 0); + node->CreateValueShort(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_PowerLevel::TestAckFrames, "Acked Frames", "", true, false, 0, 0); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/Powerlevel.h b/cpp/src/command_classes/Powerlevel.h index bd99e6b789..675adba490 100644 --- a/cpp/src/command_classes/Powerlevel.h +++ b/cpp/src/command_classes/Powerlevel.h @@ -32,60 +32,84 @@ namespace OpenZWave { - class ValueList; - - /** \brief Implements COMMAND_CLASS_POWERLEVEL (0x73), a Z-Wave device command class. - * \ingroup CommandClass - */ - class Powerlevel: public CommandClass + namespace Internal { - public: - enum PowerLevelEnum + namespace CC { - PowerLevel_Normal = 0, - PowerLevel_Minus1dB, - PowerLevel_Minus2dB, - PowerLevel_Minus3dB, - PowerLevel_Minus4dB, - PowerLevel_Minus5dB, - PowerLevel_Minus6dB, - PowerLevel_Minus7dB, - PowerLevel_Minus8dB, - PowerLevel_Minus9dB - }; - enum PowerLevelStatusEnum - { - PowerLevelStatus_Failed = 0, - PowerLevelStatus_Success, - PowerLevelStatus_InProgress - }; + /** \brief Implements COMMAND_CLASS_POWERLEVEL (0x73), a Z-Wave device command class. + * \ingroup CommandClass + */ + class Powerlevel: public CommandClass + { + public: + enum PowerLevelEnum + { + PowerLevel_Normal = 0, + PowerLevel_Minus1dB, + PowerLevel_Minus2dB, + PowerLevel_Minus3dB, + PowerLevel_Minus4dB, + PowerLevel_Minus5dB, + PowerLevel_Minus6dB, + PowerLevel_Minus7dB, + PowerLevel_Minus8dB, + PowerLevel_Minus9dB + }; - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Powerlevel( _homeId, _nodeId ); } - virtual ~Powerlevel(){} + enum PowerLevelStatusEnum + { + PowerLevelStatus_Failed = 0, + PowerLevelStatus_Success, + PowerLevelStatus_InProgress + }; - static uint8 const StaticGetCommandClassId(){ return 0x73; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_POWERLEVEL"; } + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new Powerlevel(_homeId, _nodeId); + } + virtual ~Powerlevel() + { + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool SetValue( Value const& _value ); + static uint8 const StaticGetCommandClassId() + { + return 0x73; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_POWERLEVEL"; + } - protected: - virtual void CreateVars( uint8 const _instance ); + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool SetValue(Internal::VC::Value const& _value) override; - private: - Powerlevel( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} + protected: + virtual void CreateVars(uint8 const _instance) override; - bool Set( uint8 const _instance ); - bool Test( uint8 const _instance ); - bool Report( uint8 const _instance ); - }; + private: + Powerlevel(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + } + bool Set(uint8 const _instance); + bool Test(uint8 const _instance); + bool Report(uint8 const _instance); + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/Proprietary.cpp b/cpp/src/command_classes/Proprietary.cpp index bfd81a2c1c..519dc1f26d 100644 --- a/cpp/src/command_classes/Proprietary.cpp +++ b/cpp/src/command_classes/Proprietary.cpp @@ -32,31 +32,33 @@ #include "Driver.h" #include "platform/Log.h" -using namespace OpenZWave; - -enum ProprietaryCmd +namespace OpenZWave { - ProprietaryCmd_Set = 0x01, - ProprietaryCmd_Get = 0x02, - ProprietaryCmd_Report = 0x03 -}; + namespace Internal + { + namespace CC + { + enum ProprietaryCmd + { + ProprietaryCmd_Set = 0x01, + ProprietaryCmd_Get = 0x02, + ProprietaryCmd_Report = 0x03 + }; //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool Proprietary::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if (ProprietaryCmd_Report == (ProprietaryCmd)_data[0]) - { - return true; - } - return false; -} - + bool Proprietary::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) + { + if (ProprietaryCmd_Report == (ProprietaryCmd) _data[0]) + { + return true; + } + return false; + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/Proprietary.h b/cpp/src/command_classes/Proprietary.h index c6044a70cf..8e8d2fe8d0 100644 --- a/cpp/src/command_classes/Proprietary.h +++ b/cpp/src/command_classes/Proprietary.h @@ -32,27 +32,53 @@ namespace OpenZWave { - /** \brief Implements COMMAND_CLASS_PROPRIETARY (0x88), a Z-Wave device command class. - * \ingroup CommandClass - */ - class Proprietary: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Proprietary( _homeId, _nodeId ); } - virtual ~Proprietary(){} + namespace CC + { - static uint8 const StaticGetCommandClassId(){ return 0x88; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_PROPRIETARY"; } + /** \brief Implements COMMAND_CLASS_PROPRIETARY (0x88), a Z-Wave device command class. + * \ingroup CommandClass + */ + class Proprietary: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new Proprietary(_homeId, _nodeId); + } + virtual ~Proprietary() + { + } - // From CommandClass - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); + static uint8 const StaticGetCommandClassId() + { + return 0x88; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_PROPRIETARY"; + } - private: - Proprietary( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} - }; + // From CommandClass + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + private: + Proprietary(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + } + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/Protection.cpp b/cpp/src/command_classes/Protection.cpp index d1d67c695d..2eaca9ff6a 100644 --- a/cpp/src/command_classes/Protection.cpp +++ b/cpp/src/command_classes/Protection.cpp @@ -37,156 +37,141 @@ #include "value_classes/ValueList.h" -using namespace OpenZWave; - -enum ProtectionCmd +namespace OpenZWave { - ProtectionCmd_Set = 0x01, - ProtectionCmd_Get = 0x02, - ProtectionCmd_Report = 0x03 -}; + namespace Internal + { + namespace CC + { -static char const* c_protectionStateNames[] = -{ - "Unprotected", - "Protection by Sequence", - "No Operation Possible", - "Unknown" -}; + enum ProtectionCmd + { + ProtectionCmd_Set = 0x01, + ProtectionCmd_Get = 0x02, + ProtectionCmd_Report = 0x03 + }; + + static char const* c_protectionStateNames[] = + { "Unprotected", "Protection by Sequence", "No Operation Possible", "Unknown" }; //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool Protection::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _requestFlags & RequestFlag_Session ) - { - return RequestValue( _requestFlags, 0, _instance, _queue ); - } + bool Protection::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_requestFlags & RequestFlag_Session) + { + return RequestValue(_requestFlags, 0, _instance, _queue); + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool Protection::RequestValue -( - uint32 const _requestFlags, - uint16 const _dummy1, // = 0 (not used) - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Msg* msg = new Msg( "ProtectionCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( ProtectionCmd_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "ProtectionCmd_Get Not Supported on this node"); - } - return false; -} + bool Protection::RequestValue(uint32 const _requestFlags, uint16 const _dummy1, // = 0 (not used) + uint8 const _instance, Driver::MsgQueue const _queue) + { + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Msg* msg = new Msg("ProtectionCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(ProtectionCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "ProtectionCmd_Get Not Supported on this node"); + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool Protection::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if (ProtectionCmd_Report == (ProtectionCmd)_data[0]) - { - int8 stateValue = _data[1]; - if (stateValue > 2) /* size of c_protectionStateNames minus Invalid */ - { - Log::Write (LogLevel_Warning, GetNodeId(), "State Value was greater than range. Setting to Invalid"); - stateValue = 3; - } - Log::Write( LogLevel_Info, GetNodeId(), "Received a Protection report: %s", c_protectionStateNames[_data[1]] ); - if( ValueList* value = static_cast( GetValue( _instance, 0 ) ) ) - { - value->OnValueRefreshed( (int)_data[1] ); - value->Release(); - } - - return true; - } - - return false; -} + bool Protection::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) + { + if (ProtectionCmd_Report == (ProtectionCmd) _data[0]) + { + int8 stateValue = _data[1]; + if (stateValue > 2) /* size of c_protectionStateNames minus Invalid */ + { + Log::Write(LogLevel_Warning, GetNodeId(), "State Value was greater than range. Setting to Invalid"); + stateValue = 3; + } + Log::Write(LogLevel_Info, GetNodeId(), "Received a Protection report: %s", c_protectionStateNames[_data[1]]); + if (Internal::VC::ValueList* value = static_cast(GetValue(_instance, ValueID_Index_Protection::Protection))) + { + value->OnValueRefreshed((int) _data[1]); + value->Release(); + } + + return true; + } + + return false; + } //----------------------------------------------------------------------------- // // Set the device's protection state //----------------------------------------------------------------------------- -bool Protection::SetValue -( - Value const& _value -) -{ - if( ValueID::ValueType_List == _value.GetID().GetType() ) - { - ValueList const* value = static_cast(&_value); - ValueList::Item const *item = value->GetItem(); - if (item == NULL) - return false; - - Log::Write( LogLevel_Info, GetNodeId(), "Protection::Set - Setting protection state to '%s'", item->m_label.c_str() ); - Msg* msg = new Msg( "ProtectionCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->SetInstance( this, _value.GetID().GetInstance() ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( ProtectionCmd_Set ); - msg->Append( (uint8)item->m_value ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - return true; - } - - return false; -} + bool Protection::SetValue(Internal::VC::Value const& _value) + { + if (ValueID::ValueType_List == _value.GetID().GetType()) + { + Internal::VC::ValueList const* value = static_cast(&_value); + Internal::VC::ValueList::Item const *item = value->GetItem(); + if (item == NULL) + return false; + + Log::Write(LogLevel_Info, GetNodeId(), "Protection::Set - Setting protection state to '%s'", item->m_label.c_str()); + Msg* msg = new Msg("ProtectionCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->SetInstance(this, _value.GetID().GetInstance()); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(ProtectionCmd_Set); + msg->Append((uint8) item->m_value); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return true; + } + + return false; + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void Protection::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - vector items; - - ValueList::Item item; - for( uint8 i=0; i<3; ++i ) - { - item.m_label = c_protectionStateNames[i]; - item.m_value = i; - items.push_back( item ); - } - - node->CreateValueList( ValueID::ValueGenre_System, GetCommandClassId(), _instance, 0, "Protection", "", false, false, 1, items, 0, 0 ); - } -} + void Protection::CreateVars(uint8 const _instance) + { + if (Node* node = GetNodeUnsafe()) + { + vector items; + + Internal::VC::ValueList::Item item; + for (uint8 i = 0; i < 3; ++i) + { + item.m_label = c_protectionStateNames[i]; + item.m_value = i; + items.push_back(item); + } + + node->CreateValueList(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_Protection::Protection, "Protection", "", false, false, 1, items, 0, 0); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/Protection.h b/cpp/src/command_classes/Protection.h index 9b71ea1aa4..b46f531d3e 100644 --- a/cpp/src/command_classes/Protection.h +++ b/cpp/src/command_classes/Protection.h @@ -32,42 +32,66 @@ namespace OpenZWave { - class ValueList; - - /** \brief Implements COMMAND_CLASS_PROTECTION (0x75), a Z-Wave device command class. - * \ingroup CommandClass - */ - class Protection: public CommandClass + namespace Internal { - public: - enum ProtectionEnum + namespace CC { - Protection_Unprotected = 0, - Protection_Sequence, - Protection_NOP - }; - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Protection( _homeId, _nodeId ); } - virtual ~Protection(){} + /** \brief Implements COMMAND_CLASS_PROTECTION (0x75), a Z-Wave device command class. + * \ingroup CommandClass + */ + class Protection: public CommandClass + { + public: + enum ProtectionEnum + { + Protection_Unprotected = 0, + Protection_Sequence, + Protection_NOP + }; - static uint8 const StaticGetCommandClassId(){ return 0x75; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_PROTECTION"; } + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new Protection(_homeId, _nodeId); + } + virtual ~Protection() + { + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool SetValue( Value const& _value ); + static uint8 const StaticGetCommandClassId() + { + return 0x75; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_PROTECTION"; + } - protected: - virtual void CreateVars( uint8 const _instance ); + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool SetValue(Internal::VC::Value const& _value) override; - private: - Protection( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} - }; + protected: + virtual void CreateVars(uint8 const _instance) override; + private: + Protection(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + } + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/SceneActivation.cpp b/cpp/src/command_classes/SceneActivation.cpp index 1cfce0f37a..4e38ed1081 100644 --- a/cpp/src/command_classes/SceneActivation.cpp +++ b/cpp/src/command_classes/SceneActivation.cpp @@ -35,136 +35,133 @@ #include "platform/Log.h" #include "value_classes/ValueInt.h" -using namespace OpenZWave; - -enum SceneActivationCmd +namespace OpenZWave { - SceneActivationCmd_Set = 0x01 -}; + namespace Internal + { + namespace CC + { -enum -{ - SceneActivationIndex_SceneID = 0, - SceneActivationIndex_Duration = 1, -}; + enum SceneActivationCmd + { + SceneActivationCmd_Set = 0x01 + }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -SceneActivation::SceneActivation -( - uint32 const _homeId, - uint8 const _nodeId -): -CommandClass( _homeId, _nodeId ) -{ - Timer::SetDriver(GetDriver()); -} + SceneActivation::SceneActivation(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + Timer::SetDriver(GetDriver()); + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool SceneActivation::HandleIncommingMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if( SceneActivationCmd_Set == (SceneActivationCmd)_data[0] ) - { - // Scene Activation Set received so send notification - char msg[64]; - uint32 duration; - if( _data[2] == 0 ) { - snprintf( msg, sizeof(msg), "now" ); - duration = 0; - } else if( _data[2] <= 0x7F ) { - snprintf( msg, sizeof(msg), "%d seconds", _data[2] ); - duration = _data[2]; - } else if( _data[2] <= 0xFE ) { - snprintf( msg, sizeof(msg), "%d minutes", _data[2] ); - duration = _data[2] * 60; - } else { - snprintf( msg, sizeof(msg), "via configuration" ); - duration = 0; - } - Log::Write( LogLevel_Info, GetNodeId(), "Received SceneActivation set from node %d: scene id=%d %s. Sending event notification.", GetNodeId(), _data[1], msg ); - /* Sending the Scene ID via a notification should be depreciated in 1.8 */ - Notification* notification = new Notification( Notification::Type_SceneEvent ); - notification->SetHomeAndNodeIds( GetHomeId(), GetNodeId() ); - notification->SetSceneId( _data[1] ); - GetDriver()->QueueNotification( notification ); + bool SceneActivation::HandleIncomingMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) + { + if (SceneActivationCmd_Set == (SceneActivationCmd) _data[0]) + { + // Scene Activation Set received so send notification + char msg[64]; + uint32 duration; + if (_data[2] == 0) + { + snprintf(msg, sizeof(msg), "now"); + duration = 0; + } + else if (_data[2] <= 0x7F) + { + snprintf(msg, sizeof(msg), "%d seconds", _data[2]); + duration = _data[2]; + } + else if (_data[2] <= 0xFE) + { + snprintf(msg, sizeof(msg), "%d minutes", _data[2]); + duration = _data[2] * 60; + } + else + { + snprintf(msg, sizeof(msg), "via configuration"); + duration = 0; + } + Log::Write(LogLevel_Info, GetNodeId(), "Received SceneActivation set from node %d: scene id=%d %s. Sending event notification.", GetNodeId(), _data[1], msg); + /* Sending the Scene ID via a notification should be depreciated in 1.8 */ + Notification* notification = new Notification(Notification::Type_SceneEvent); + notification->SetHomeAndNodeIds(GetHomeId(), GetNodeId()); + notification->SetSceneId(_data[1]); + GetDriver()->QueueNotification(notification); - Log::Write( LogLevel_Info, GetNodeId(), "Received SceneActivation report: %d (duration: %d)", _data[1]); - if( ValueInt* value = static_cast( GetValue( _instance, SceneActivationIndex_SceneID ) ) ) - { - value->OnValueRefreshed( _data[1] ); - value->Release(); - } - if( ValueInt* value = static_cast( GetValue( _instance, SceneActivationIndex_Duration ) ) ) - { - value->OnValueRefreshed( duration ); - value->Release(); - } + Log::Write(LogLevel_Info, GetNodeId(), "Received SceneActivation report: %d (duration: %d)", _data[1], duration); + if (Internal::VC::ValueInt* value = static_cast(GetValue(_instance, ValueID_Index_SceneActivation::SceneID))) + { + value->OnValueRefreshed(_data[1]); + value->Release(); + } + if (Internal::VC::ValueInt* value = static_cast(GetValue(_instance, ValueID_Index_SceneActivation::Duration))) + { + value->OnValueRefreshed(duration); + value->Release(); + } + if (duration < 1000) + duration = 1000; + else + duration = duration * 1000; - Log::Write( LogLevel_Info, GetNodeId(), "Automatically Clearing Alarm in %d ms", duration ); - TimerThread::TimerCallback callback = bind(&SceneActivation::ClearScene, this, _instance); - TimerSetEvent(duration, callback, _instance); - return true; - } + Log::Write(LogLevel_Info, GetNodeId(), "Automatically Clearing SceneID/Duration in %d ms", duration); + TimerThread::TimerCallback callback = bind(&SceneActivation::ClearScene, this, _instance); + TimerSetEvent(duration, callback, _instance); + return true; + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool SceneActivation::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - Log::Write( LogLevel_Warning, GetNodeId(), "Received a SceneActivation Message for a Controlled CommandClass"); - return false; -} + bool SceneActivation::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) + { + Log::Write(LogLevel_Warning, GetNodeId(), "Received a SceneActivation Message for a Controlled CommandClass"); + return false; + } //----------------------------------------------------------------------------- // // Return the Scene ValueID's to defaults, after the duration has expired //----------------------------------------------------------------------------- -void SceneActivation::ClearScene(uint32 _instance) { - if( ValueInt* value = static_cast( GetValue( _instance, SceneActivationIndex_SceneID ) ) ) - { - value->OnValueRefreshed( 0 ); - value->Release(); - } - if( ValueInt* value = static_cast( GetValue( _instance, SceneActivationIndex_Duration ) ) ) - { - value->OnValueRefreshed( 0 ); - value->Release(); - } -} - - + void SceneActivation::ClearScene(uint32 _instance) + { + if (Internal::VC::ValueInt* value = static_cast(GetValue(_instance, ValueID_Index_SceneActivation::SceneID))) + { + value->OnValueRefreshed(0); + value->Release(); + } + if (Internal::VC::ValueInt* value = static_cast(GetValue(_instance, ValueID_Index_SceneActivation::Duration))) + { + value->OnValueRefreshed(0); + value->Release(); + } + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void SceneActivation::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - node->CreateValueInt( ValueID::ValueGenre_User, GetCommandClassId(), _instance, SceneActivationIndex_SceneID, "Scene", "", true, false, 0, 0 ); - node->CreateValueInt( ValueID::ValueGenre_User, GetCommandClassId(), _instance, SceneActivationIndex_Duration, "Duration", "", true, false, 0, 0 ); - } -} + void SceneActivation::CreateVars(uint8 const _instance) + { + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueInt(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_SceneActivation::SceneID, "Scene", "", true, false, 0, 0); + node->CreateValueInt(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_SceneActivation::Duration, "Duration", "", true, false, 0, 0); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/SceneActivation.h b/cpp/src/command_classes/SceneActivation.h index c359f292e0..de9ec7df96 100644 --- a/cpp/src/command_classes/SceneActivation.h +++ b/cpp/src/command_classes/SceneActivation.h @@ -33,40 +33,61 @@ namespace OpenZWave { - class ValueByte; - - /** \brief Implements COMMAND_CLASS_SCENEACTIVATION (0x2B), a Z-Wave device command class. - * \ingroup CommandClass - */ - class SceneActivation: public CommandClass, private Timer + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new SceneActivation( _homeId, _nodeId ); } - virtual ~SceneActivation(){} + namespace CC + { - /** \brief Get command class ID (1 byte) identifying this command class. */ - static uint8 const StaticGetCommandClassId(){ return 0x2B; } - /** \brief Get a string containing the name of this command class. */ - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_SCENE_ACTIVATION"; } + /** \brief Implements COMMAND_CLASS_SCENEACTIVATION (0x2B), a Z-Wave device command class. + * \ingroup CommandClass + */ + class SceneActivation: public CommandClass, private Timer + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new SceneActivation(_homeId, _nodeId); + } + virtual ~SceneActivation() + { + } - // From CommandClass - /** \brief Get command class ID (1 byte) identifying this command class. (Inherited from CommandClass) */ - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - /** \brief Get a string containing the name of this command class. (Inherited from CommandClass) */ - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - /** \brief Handle a response to a message associated with this command class. (Inherited from CommandClass) */ - virtual bool HandleIncommingMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); + /** \brief Get command class ID (1 byte) identifying this command class. */ + static uint8 const StaticGetCommandClassId() + { + return 0x2B; + } + /** \brief Get a string containing the name of this command class. */ + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_SCENE_ACTIVATION"; + } - protected: - virtual void CreateVars( uint8 const _instance ); + // From CommandClass + /** \brief Get command class ID (1 byte) identifying this command class. (Inherited from CommandClass) */ + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + /** \brief Get a string containing the name of this command class. (Inherited from CommandClass) */ + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + /** \brief Handle a response to a message associated with this command class. (Inherited from CommandClass) */ + virtual bool HandleIncomingMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; - private: - void ClearScene(uint32 id); - SceneActivation( uint32 const _homeId, uint8 const _nodeId ); + protected: + virtual void CreateVars(uint8 const _instance) override; - }; + private: + void ClearScene(uint32 id); + SceneActivation(uint32 const _homeId, uint8 const _nodeId); + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/Security.cpp b/cpp/src/command_classes/Security.cpp index c9f78393b9..f4b176a03c 100644 --- a/cpp/src/command_classes/Security.cpp +++ b/cpp/src/command_classes/Security.cpp @@ -27,7 +27,6 @@ #include - #include "command_classes/CommandClasses.h" #include "command_classes/Security.h" #include "Defs.h" @@ -39,264 +38,232 @@ #include "value_classes/ValueBool.h" - -using namespace OpenZWave; - - - -Security::Security -( - uint32 const _homeId, - uint8 const _nodeId -): -CommandClass( _homeId, _nodeId ), -m_schemeagreed(false), -m_secured(false) - +namespace OpenZWave { - /* We don't want the Driver to route "Security" messages back to us for Encryption, - * so disable SecureSupport for the Security Command Class - * (This stops this Command Class getting Marked as as IsSecured() if its listed - * in the SecurityCmd_SupportedReport from the device - Which some devices do) - */ - ClearSecureSupport(); + namespace Internal + { + namespace CC + { -} + Security::Security(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId), m_schemeagreed(false), m_secured(false) -Security::~Security -( -) -{ -} + { + /* We don't want the Driver to route "Security" messages back to us for Encryption, + * so disable SecureSupport for the Security Command Class + * (This stops this Command Class getting Marked as as IsSecured() if its listed + * in the SecurityCmd_SupportedReport from the device - Which some devices do) + */ + ClearSecureSupport(); + } -bool Security::Init -( - uint32 const _instance -) -{ - Msg* msg = new Msg( "SecurityCmd_SupportedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( SecurityCmd_SupportedGet ); - msg->Append( GetDriver()->GetTransmitOptions() ); - msg->setEncrypted(); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Command); - return true; -} + Security::~Security() + { + } + + bool Security::Init(uint32 const _instance) + { + Msg* msg = new Msg("SecurityCmd_SupportedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(SecurityCmd_SupportedGet); + msg->Append(GetDriver()->GetTransmitOptions()); + msg->setEncrypted(); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Command); + return true; + } //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool Security::ExchangeNetworkKeys -( -) -{ - if (GetNodeUnsafe()->IsAddingNode()) { - Msg * msg = new Msg ("SecurityCmd_SchemeGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( SecurityCmd_SchemeGet ); - msg->Append( 0 ); - msg->Append( GetDriver()->GetTransmitOptions() ); - /* SchemeGet is unencrypted */ - GetDriver()->SendMsg(msg, Driver::MsgQueue_Command); - return true; - } - return false; -} - + bool Security::ExchangeNetworkKeys() + { + if (GetNodeUnsafe()->IsAddingNode()) + { + Msg * msg = new Msg("SecurityCmd_SchemeGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(SecurityCmd_SchemeGet); + msg->Append(0); + msg->Append(GetDriver()->GetTransmitOptions()); + /* SchemeGet is unencrypted */ + GetDriver()->SendMsg(msg, Driver::MsgQueue_Command); + return true; + } + return false; + } //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool Security::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ + bool Security::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { #if 0 - if( _requestFlags & RequestFlag_Static ) - { + if( _requestFlags & RequestFlag_Static ) + { - } - return false; + } + return false; #endif - return true; -} + return true; + } //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool Security::RequestValue -( - uint32 const _requestFlags, - uint16 const _index, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - Log::Write(LogLevel_Info, GetNodeId(), "Got a RequestValue Call"); - return true; -} - + bool Security::RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) + { + Log::Write(LogLevel_Info, GetNodeId(), "Got a RequestValue Call"); + return true; + } -bool Security::HandleSupportedReport -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance -) -{ + bool Security::HandleSupportedReport(uint8 const* _data, uint32 const _length, uint32 const _instance) + { #ifdef DEBUG - PrintHex("Security Classes", _data, _length); + PrintHex("Security Classes", _data, _length); #endif - GetNodeUnsafe()->SetSecuredClasses(_data, _length, _instance); - return true; -} + GetNodeUnsafe()->SetSecuredClasses(_data, _length, _instance); + return true; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool Security::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - switch( (SecurityCmd)_data[0] ) - { - case SecurityCmd_SupportedReport: - { - /* this is a list of CommandClasses that should be Encrypted. - * and it might contain new command classes that were not present in the NodeInfoFrame - * so we have to run through, mark existing Command Classes as SetSecured (so SendMsg in the Driver - * class will route the unecrypted messages to our SendMsg) and for New Command - * Classes, create them, and of course, also do a SetSecured on them. - * - * This means we must do a SecurityCmd_SupportedGet request ASAP so we dont have - * Command Classes created after the Discovery Phase is completed! - */ - Log::Write(LogLevel_Info, GetNodeId(), "Received SecurityCmd_SupportedReport from node %d (instance %d)", GetNodeId(), _instance ); - m_secured = true; - if( ValueBool* value = static_cast( GetValue( _instance, 0 ) ) ) - { - value->OnValueRefreshed( m_secured ); - value->Release(); - } - HandleSupportedReport(&_data[2], _length-3, _instance); - break; - } - case SecurityCmd_SchemeReport: - { - Log::Write(LogLevel_Info, GetNodeId(), "Received SecurityCmd_SchemeReport from node %d: %d", GetNodeId(), _data[1]); - uint8 schemes = _data[1]; - if (m_schemeagreed == true) { - Log::Write(LogLevel_Warning, GetNodeId(), " Already Received a SecurityCmd_SchemeReport from the node. Ignoring"); - break; - } - if( schemes == SecurityScheme_Zero ) - { - /* We're good to go. We now should send our NetworkKey to the device if this is the first - * time we have seen it - */ - Log::Write(LogLevel_Info, GetNodeId(), " Security scheme agreed." ); - /* create the NetworkKey Packet. EncryptMessage will encrypt it for us (And request the NONCE) */ - Msg * msg = new Msg ("SecurityCmd_NetworkKeySet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( 18 ); - msg->Append( GetCommandClassId() ); - msg->Append( SecurityCmd_NetworkKeySet ); - for (int i = 0; i < 16; i++) - msg->Append(GetDriver()->GetNetworkKey()[i]); - msg->Append( GetDriver()->GetTransmitOptions() ); - msg->setEncrypted(); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Command); - m_schemeagreed = true; - } - else + bool Security::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) { - /* No common security scheme. The device should continue as an unsecured node. - * but Some Command Classes might not be present... - */ - Log::Write(LogLevel_Warning, GetNodeId(), " No common security scheme. The device will continue as an unsecured node." ); - } - break; - } - case SecurityCmd_NetworkKeySet: - { - /* we shouldn't get a NetworkKeySet from a node if we are the controller - * as we send it out to the Devices - */ - Log::Write(LogLevel_Info, GetNodeId(), "Received SecurityCmd_NetworkKeySet from node %d", GetNodeId() ); - break; - } - case SecurityCmd_NetworkKeyVerify: - { - /* if we can decrypt this packet, then we are assured that our NetworkKeySet is successfull - * and thus should set the Flag referenced in SecurityCmd_SchemeReport - */ - Log::Write(LogLevel_Info, GetNodeId(), "Received SecurityCmd_NetworkKeyVerify from node %d", GetNodeId() ); - /* now as for our SupportedGet */ - Msg* msg = new Msg( "SecurityCmd_SupportedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( SecurityCmd_SupportedGet ); - msg->Append( GetDriver()->GetTransmitOptions() ); - msg->setEncrypted(); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Command); + switch ((SecurityCmd) _data[0]) + { + case SecurityCmd_SupportedReport: + { + /* this is a list of CommandClasses that should be Encrypted. + * and it might contain new command classes that were not present in the NodeInfoFrame + * so we have to run through, mark existing Command Classes as SetSecured (so SendMsg in the Driver + * class will route the unecrypted messages to our SendMsg) and for New Command + * Classes, create them, and of course, also do a SetSecured on them. + * + * This means we must do a SecurityCmd_SupportedGet request ASAP so we dont have + * Command Classes created after the Discovery Phase is completed! + */ + Log::Write(LogLevel_Info, GetNodeId(), "Received SecurityCmd_SupportedReport from node %d (instance %d)", GetNodeId(), _instance); + m_secured = true; + if (Internal::VC::ValueBool* value = static_cast(GetValue(_instance, ValueID_Index_Security::Secured))) + { + value->OnValueRefreshed(m_secured); + value->Release(); + } + HandleSupportedReport(&_data[2], _length - 3, _instance); + break; + } + case SecurityCmd_SchemeReport: + { + Log::Write(LogLevel_Info, GetNodeId(), "Received SecurityCmd_SchemeReport from node %d: %d", GetNodeId(), _data[1]); + uint8 schemes = _data[1]; + if (m_schemeagreed == true) + { + Log::Write(LogLevel_Warning, GetNodeId(), " Already Received a SecurityCmd_SchemeReport from the node. Ignoring"); + break; + } + if (schemes == SecurityScheme_Zero) + { + /* We're good to go. We now should send our NetworkKey to the device if this is the first + * time we have seen it + */ + Log::Write(LogLevel_Info, GetNodeId(), " Security scheme agreed."); + /* create the NetworkKey Packet. EncryptMessage will encrypt it for us (And request the NONCE) */ + Msg * msg = new Msg("SecurityCmd_NetworkKeySet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(18); + msg->Append(GetCommandClassId()); + msg->Append(SecurityCmd_NetworkKeySet); + for (int i = 0; i < 16; i++) + msg->Append(GetDriver()->GetNetworkKey()[i]); + msg->Append(GetDriver()->GetTransmitOptions()); + msg->setEncrypted(); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Command); + m_schemeagreed = true; + } + else + { + /* No common security scheme. The device should continue as an unsecured node. + * but Some Command Classes might not be present... + */ + Log::Write(LogLevel_Warning, GetNodeId(), " No common security scheme. The device will continue as an unsecured node."); + } + break; + } + case SecurityCmd_NetworkKeySet: + { + /* we shouldn't get a NetworkKeySet from a node if we are the controller + * as we send it out to the Devices + */ + Log::Write(LogLevel_Info, GetNodeId(), "Received SecurityCmd_NetworkKeySet from node %d", GetNodeId()); + break; + } + case SecurityCmd_NetworkKeyVerify: + { + /* if we can decrypt this packet, then we are assured that our NetworkKeySet is successfull + * and thus should set the Flag referenced in SecurityCmd_SchemeReport + */ + Log::Write(LogLevel_Info, GetNodeId(), "Received SecurityCmd_NetworkKeyVerify from node %d", GetNodeId()); + /* now as for our SupportedGet */ + Msg* msg = new Msg("SecurityCmd_SupportedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(SecurityCmd_SupportedGet); + msg->Append(GetDriver()->GetTransmitOptions()); + msg->setEncrypted(); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Command); - break; - } - case SecurityCmd_SchemeInherit: - { - /* only used in a Controller Replication Type enviroment. - * - */ - Log::Write(LogLevel_Info, GetNodeId(), "Received SecurityCmd_SchemeInherit from node %d", GetNodeId() ); - break; - } - /* the rest of these should be handled by the Driver Code (in Driver::ProcessMsg) */ - case SecurityCmd_NonceGet: - case SecurityCmd_NonceReport: - case SecurityCmd_MessageEncap: - case SecurityCmd_MessageEncapNonceGet: - { - Log::Write(LogLevel_Warning, GetNodeId(), "Received a Security Message that should have been handled in the Driver"); - break; - } - default: - { - return false; - } - } + break; + } + case SecurityCmd_SchemeInherit: + { + /* only used in a Controller Replication Type enviroment. + * + */ + Log::Write(LogLevel_Info, GetNodeId(), "Received SecurityCmd_SchemeInherit from node %d", GetNodeId()); + break; + } + /* the rest of these should be handled by the Driver Code (in Driver::ProcessMsg) */ + case SecurityCmd_NonceGet: + case SecurityCmd_NonceReport: + case SecurityCmd_MessageEncap: + case SecurityCmd_MessageEncapNonceGet: + { + Log::Write(LogLevel_Warning, GetNodeId(), "Received a Security Message that should have been handled in the Driver"); + break; + } + default: + { + return false; + } + } - return true; -} + return true; + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void Security::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - node->CreateValueBool( ValueID::ValueGenre_System, GetCommandClassId(), _instance, 0, "Secured", "", true, false, false, 0 ); - } -} + void Security::CreateVars(uint8 const _instance) + { + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueBool(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_Security::Secured, "Secured", "", true, false, false, 0); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/Security.h b/cpp/src/command_classes/Security.h index 14efc2d75b..3b67ac444d 100644 --- a/cpp/src/command_classes/Security.h +++ b/cpp/src/command_classes/Security.h @@ -34,67 +34,81 @@ namespace OpenZWave { - - - enum SecurityCmd + namespace Internal { - SecurityCmd_SupportedGet = 0x02, - SecurityCmd_SupportedReport = 0x03, - SecurityCmd_SchemeGet = 0x04, - SecurityCmd_SchemeReport = 0x05, - SecurityCmd_NetworkKeySet = 0x06, - SecurityCmd_NetworkKeyVerify = 0x07, - SecurityCmd_SchemeInherit = 0x08, - SecurityCmd_NonceGet = 0x40, - SecurityCmd_NonceReport = 0x80, - SecurityCmd_MessageEncap = 0x81, - SecurityCmd_MessageEncapNonceGet = 0xc1 - }; - - enum SecurityScheme - { - SecurityScheme_Zero = 0x00, - }; - - - /** \brief Implements COMMAND_CLASS_SECURITY (0x98), a Z-Wave device command class. - * \ingroup CommandClass - */ - - class Security: public CommandClass - { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Security( _homeId, _nodeId ); } - virtual ~Security(); - - static uint8 const StaticGetCommandClassId(){ return 0x98; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_SECURITY"; } - bool Init(uint32 const _instance = 1); - bool ExchangeNetworkKeys(); - // From CommandClass - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - void SendMsg( Msg* _msg ); - - protected: - void CreateVars( uint8 const _instance ); - - private: - Security( uint32 const _homeId, uint8 const _nodeId ); - bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue); - bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue); - bool HandleSupportedReport(uint8 const* _data, uint32 const _length, uint32 const _instance = 1); - - bool m_schemeagreed; - bool m_secured; - - - - - - }; - + namespace CC + { + + enum SecurityCmd + { + SecurityCmd_SupportedGet = 0x02, + SecurityCmd_SupportedReport = 0x03, + SecurityCmd_SchemeGet = 0x04, + SecurityCmd_SchemeReport = 0x05, + SecurityCmd_NetworkKeySet = 0x06, + SecurityCmd_NetworkKeyVerify = 0x07, + SecurityCmd_SchemeInherit = 0x08, + SecurityCmd_NonceGet = 0x40, + SecurityCmd_NonceReport = 0x80, + SecurityCmd_MessageEncap = 0x81, + SecurityCmd_MessageEncapNonceGet = 0xc1 + }; + + enum SecurityScheme + { + SecurityScheme_Zero = 0x00, + }; + + /** \brief Implements COMMAND_CLASS_SECURITY (0x98), a Z-Wave device command class. + * \ingroup CommandClass + */ + + class Security: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new Security(_homeId, _nodeId); + } + virtual ~Security(); + + static uint8 const StaticGetCommandClassId() + { + return 0x98; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_SECURITY"; + } + bool Init(uint32 const _instance = 1); + bool ExchangeNetworkKeys(); + // From CommandClass + bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + void SendMsg(Msg* _msg); + + protected: + void CreateVars(uint8 const _instance) override; + + private: + Security(uint32 const _homeId, uint8 const _nodeId); + bool HandleSupportedReport(uint8 const* _data, uint32 const _length, uint32 const _instance = 1); + + bool m_schemeagreed; + bool m_secured; + + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/SensorAlarm.cpp b/cpp/src/command_classes/SensorAlarm.cpp index 24adc7db13..c98c16499d 100644 --- a/cpp/src/command_classes/SensorAlarm.cpp +++ b/cpp/src/command_classes/SensorAlarm.cpp @@ -35,181 +35,164 @@ #include "value_classes/ValueByte.h" -using namespace OpenZWave; - -enum SensorAlarmCmd +namespace OpenZWave { - SensorAlarmCmd_Get = 0x01, - SensorAlarmCmd_Report = 0x02, - SensorAlarmCmd_SupportedGet = 0x03, - SensorAlarmCmd_SupportedReport = 0x04 -}; + namespace Internal + { + namespace CC + { -static char const* c_alarmTypeName[] = -{ - "General", - "Smoke", - "Carbon Monoxide", - "Carbon Dioxide", - "Heat", - "Flood" -}; + enum SensorAlarmCmd + { + SensorAlarmCmd_Get = 0x01, + SensorAlarmCmd_Report = 0x02, + SensorAlarmCmd_SupportedGet = 0x03, + SensorAlarmCmd_SupportedReport = 0x04 + }; + static char const* c_alarmTypeName[] = + { "General", "Smoke", "Carbon Monoxide", "Carbon Dioxide", "Heat", "Flood" }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -SensorAlarm::SensorAlarm -( - uint32 const _homeId, - uint8 const _nodeId -): - CommandClass( _homeId, _nodeId ) -{ - SetStaticRequest( StaticRequest_Values ); -} + SensorAlarm::SensorAlarm(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + SetStaticRequest(StaticRequest_Values); + } //----------------------------------------------------------------------------- // // Get the static thermostat setpoint details from the device //----------------------------------------------------------------------------- -bool SensorAlarm::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - bool requests = false; - if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) ) - { - requests = RequestValue( _requestFlags, 0xff, _instance, _queue ); - } - - if( _requestFlags & RequestFlag_Dynamic ) - { - for( uint8 i=0; iRelease(); - // There is a value for this alarm type, so request it - requests |= RequestValue( _requestFlags, i, _instance, _queue ); - } - } - } + bool requests = false; + if ((_requestFlags & RequestFlag_Static) && HasStaticRequest(StaticRequest_Values)) + { + requests = RequestValue(_requestFlags, 0xff, _instance, _queue); + } + + if (_requestFlags & RequestFlag_Dynamic) + { + for (uint8 i = 0; i < SensorAlarm_Count; ++i) + { + Internal::VC::Value* value = GetValue(1, i); + if (value != NULL) + { + value->Release(); + // There is a value for this alarm type, so request it + requests |= RequestValue(_requestFlags, i, _instance, _queue); + } + } + } - return requests; -} + return requests; + } //----------------------------------------------------------------------------- // // Get the sensor alarm details from the device //----------------------------------------------------------------------------- -bool SensorAlarm::RequestValue -( - uint32 const _requestFlags, - uint16 const _alarmType, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _alarmType == 0xff ) - { - // Request the supported alarm types - Msg* msg = new Msg( "SensorAlarmCmd_SupportedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( SensorAlarmCmd_SupportedGet ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } - else - { - // Request the alarm state - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Msg* msg = new Msg( "SensorAlarmCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( SensorAlarmCmd_Get ); - msg->Append( (_alarmType & 0xFF) ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "SensorAlarmCmd_Get Not Supported on this node"); - } - } - return false; -} + bool SensorAlarm::RequestValue(uint32 const _requestFlags, uint16 const _alarmType, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_alarmType == 0xff) + { + // Request the supported alarm types + Msg* msg = new Msg("SensorAlarmCmd_SupportedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(SensorAlarmCmd_SupportedGet); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + // Request the alarm state + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Msg* msg = new Msg("SensorAlarmCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(SensorAlarmCmd_Get); + msg->Append((_alarmType & 0xFF)); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "SensorAlarmCmd_Get Not Supported on this node"); + } + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool SensorAlarm::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if( SensorAlarmCmd_Report == (SensorAlarmCmd)_data[0] ) - { - // We have received an alarm state report from the Z-Wave device - if( ValueByte* value = static_cast( GetValue( _instance, _data[2] ) ) ) - { - uint8 sourceNodeId = _data[1]; - uint8 state = _data[3]; - // uint16 time = (((uint16)_data[4])<<8) | (uint16)_data[5]; Don't know what to do with this yet. - - value->OnValueRefreshed( state ); - value->Release(); - Log::Write( LogLevel_Info, GetNodeId(), "Received alarm state report from node %d: %s = %d", sourceNodeId, value->GetLabel().c_str(), state ); - } + bool SensorAlarm::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) + { + if (SensorAlarmCmd_Report == (SensorAlarmCmd) _data[0]) + { + // We have received an alarm state report from the Z-Wave device + if (Internal::VC::ValueByte* value = static_cast(GetValue(_instance, _data[2]))) + { + uint8 sourceNodeId = _data[1]; + uint8 state = _data[3]; + // uint16 time = (((uint16)_data[4])<<8) | (uint16)_data[5]; Don't know what to do with this yet. - return true; - } + value->OnValueRefreshed(state); + value->Release(); + Log::Write(LogLevel_Info, GetNodeId(), "Received alarm state report from node %d: %s = %d", sourceNodeId, value->GetLabel().c_str(), state); + } - if( SensorAlarmCmd_SupportedReport == (SensorAlarmCmd)_data[0] ) - { - if( Node* node = GetNodeUnsafe() ) - { - // We have received the supported alarm types from the Z-Wave device - Log::Write( LogLevel_Info, GetNodeId(), "Received supported alarm types" ); + return true; + } - // Parse the data for the supported alarm types - uint8 numBytes = _data[1]; - for( uint32 i=0; iCreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, index, c_alarmTypeName[index], "", true, false, 0, 0 ); - Log::Write( LogLevel_Info, GetNodeId(), " Added alarm type: %s", c_alarmTypeName[index] ); + for (int32 bit = 0; bit < 8; ++bit) + { + if ((_data[i + 2] & (1 << bit)) != 0) + { + // Add supported setpoint + int32 index = (int32) (i << 3) + bit; + if (index < SensorAlarm_Count) + { + node->CreateValueByte(ValueID::ValueGenre_User, GetCommandClassId(), _instance, index, c_alarmTypeName[index], "", true, false, 0, 0); + Log::Write(LogLevel_Info, GetNodeId(), " Added alarm type: %s", c_alarmTypeName[index]); + } + } + } } } - } - } - } - ClearStaticRequest( StaticRequest_Values ); - return true; - } + ClearStaticRequest(StaticRequest_Values); + return true; + } - return false; -} + return false; + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/SensorAlarm.h b/cpp/src/command_classes/SensorAlarm.h index 842ff150dc..bd0b494a93 100644 --- a/cpp/src/command_classes/SensorAlarm.h +++ b/cpp/src/command_classes/SensorAlarm.h @@ -34,45 +34,64 @@ namespace OpenZWave { - class ValueByte; - - /** \brief Implements COMMAND_CLASS_SENSOR_ALARM (0x9c), a Z-Wave device command class. - * \ingroup CommandClass - */ - class SensorAlarm: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new SensorAlarm( _homeId, _nodeId ); } - virtual ~SensorAlarm(){} + namespace CC + { - static uint8 const StaticGetCommandClassId(){ return 0x9c; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_SENSOR_ALARM"; } + /** \brief Implements COMMAND_CLASS_SENSOR_ALARM (0x9c), a Z-Wave device command class. + * \ingroup CommandClass + */ + class SensorAlarm: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new SensorAlarm(_homeId, _nodeId); + } + virtual ~SensorAlarm() + { + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _alarmType, uint8 const _dummy, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); + static uint8 const StaticGetCommandClassId() + { + return 0x9c; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_SENSOR_ALARM"; + } - private: - SensorAlarm( uint32 const _homeId, uint8 const _nodeId ); + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _alarmType, uint8 const _dummy, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; - enum - { - SensorAlarm_General = 0, - SensorAlarm_Smoke, - SensorAlarm_CarbonMonoxide, - SensorAlarm_CarbonDioxide, - SensorAlarm_Heat, - SensorAlarm_Flood, - SensorAlarm_Count - }; - }; + private: + SensorAlarm(uint32 const _homeId, uint8 const _nodeId); + enum + { + SensorAlarm_General = 0, + SensorAlarm_Smoke, + SensorAlarm_CarbonMonoxide, + SensorAlarm_CarbonDioxide, + SensorAlarm_Heat, + SensorAlarm_Flood, + SensorAlarm_Count + }; + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif - - diff --git a/cpp/src/command_classes/SensorBinary.cpp b/cpp/src/command_classes/SensorBinary.cpp index c773d3db88..c72305f1e4 100644 --- a/cpp/src/command_classes/SensorBinary.cpp +++ b/cpp/src/command_classes/SensorBinary.cpp @@ -36,208 +36,192 @@ #include "value_classes/ValueBool.h" #include "tinyxml.h" -using namespace OpenZWave; - -enum SensorBinaryCmd +namespace OpenZWave { - SensorBinaryCmd_Get = 0x02, - SensorBinaryCmd_Report = 0x03 -}; + namespace Internal + { + namespace CC + { + + enum SensorBinaryCmd + { + SensorBinaryCmd_Get = 0x02, + SensorBinaryCmd_Report = 0x03 + }; //----------------------------------------------------------------------------- // // Read node configuration data //----------------------------------------------------------------------------- -void SensorBinary::ReadXML -( - TiXmlElement const* _ccElement -) -{ - CommandClass::ReadXML( _ccElement ); - - TiXmlElement const* child = _ccElement->FirstChildElement(); + void SensorBinary::ReadXML(TiXmlElement const* _ccElement) + { + CommandClass::ReadXML(_ccElement); - char const* str; int index; int type; + TiXmlElement const* child = _ccElement->FirstChildElement(); - while( child ) - { - str = child->Value(); + char const* str; + int index; + int type; - if( str ) - { - if( !strcmp( str, "SensorMap" ) ) - { - if( TIXML_SUCCESS == child->QueryIntAttribute( "index", &index ) && - TIXML_SUCCESS == child->QueryIntAttribute( "type", &type ) ) + while (child) { - m_sensorsMap[(uint8)type] = (uint8)index; + str = child->Value(); + + if (str) + { + if (!strcmp(str, "SensorMap")) + { + if (TIXML_SUCCESS == child->QueryIntAttribute("index", &index) && TIXML_SUCCESS == child->QueryIntAttribute("type", &type)) + { + m_sensorsMap[(uint8) type] = (uint8) index; + } + } + } + + child = child->NextSiblingElement(); } } - } - - child = child->NextSiblingElement(); - } -} //----------------------------------------------------------------------------- // // Write node configuration data //----------------------------------------------------------------------------- -void SensorBinary::WriteXML -( - TiXmlElement* _ccElement -) -{ - CommandClass::WriteXML( _ccElement ); + void SensorBinary::WriteXML(TiXmlElement* _ccElement) + { + CommandClass::WriteXML(_ccElement); - char str[8]; + char str[8]; - for( map::iterator it = m_sensorsMap.begin(); it != m_sensorsMap.end(); it++ ) - { - TiXmlElement* sensorMapElement = new TiXmlElement( "SensorMap" ); - _ccElement->LinkEndChild( sensorMapElement ); + for (map::iterator it = m_sensorsMap.begin(); it != m_sensorsMap.end(); it++) + { + TiXmlElement* sensorMapElement = new TiXmlElement("SensorMap"); + _ccElement->LinkEndChild(sensorMapElement); - snprintf( str, 8, "%d", it->second ); - sensorMapElement->SetAttribute( "index", str ); + snprintf(str, 8, "%d", it->second); + sensorMapElement->SetAttribute("index", str); - snprintf( str, 8, "%d", it->first ); - sensorMapElement->SetAttribute( "type", str ); - } -} + snprintf(str, 8, "%d", it->first); + sensorMapElement->SetAttribute("type", str); + } + } //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool SensorBinary::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _requestFlags & RequestFlag_Dynamic ) - { - return RequestValue( _requestFlags, 0, _instance, _queue ); - } + bool SensorBinary::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_requestFlags & RequestFlag_Dynamic) + { + return RequestValue(_requestFlags, 0, _instance, _queue); + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool SensorBinary::RequestValue -( - uint32 const _requestFlags, - uint16 const _dummy1, // = 0 (not used) - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Msg* msg = new Msg( "SensorBinaryCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( SensorBinaryCmd_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "SensorBinaryCmd_Get Not Supported on this node"); - } - return false; -} + bool SensorBinary::RequestValue(uint32 const _requestFlags, uint16 const _dummy1, // = 0 (not used) + uint8 const _instance, Driver::MsgQueue const _queue) + { + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Msg* msg = new Msg("SensorBinaryCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(SensorBinaryCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "SensorBinaryCmd_Get Not Supported on this node"); + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool SensorBinary::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if (SensorBinaryCmd_Report == (SensorBinaryCmd)_data[0]) - { - if( _length > 2 ) - { - uint8 index = m_sensorsMap[_data[2]]; - - Log::Write( LogLevel_Info, GetNodeId(), "Received SensorBinary report: Sensor:%d State=%s", _data[2], _data[1] ? "On" : "Off" ); - - if( ValueBool* value = static_cast( GetValue( _instance, index ) ) ) - { - value->OnValueRefreshed( _data[1] != 0 ); - value->Release(); - } - - return true; - } - else - { - Log::Write( LogLevel_Info, GetNodeId(), "Received SensorBinary report: State=%s", _data[1] ? "On" : "Off" ); - - if( ValueBool* value = static_cast( GetValue( _instance, 0 ) ) ) - { - value->OnValueRefreshed( _data[1] != 0 ); - value->Release(); - } - - return true; - } - } + bool SensorBinary::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) + { + if (SensorBinaryCmd_Report == (SensorBinaryCmd) _data[0]) + { + if (_length > 3) + { + uint8 index = m_sensorsMap[_data[2]]; + + Log::Write(LogLevel_Info, GetNodeId(), "Received SensorBinary report: Sensor:%d State=%s", _data[2], _data[1] ? "On" : "Off"); + + if (Internal::VC::ValueBool* value = static_cast(GetValue(_instance, index))) + { + value->OnValueRefreshed(_data[1] != 0); + value->Release(); + } + + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "Received SensorBinary report: State=%s", _data[1] ? "On" : "Off"); + + if (Internal::VC::ValueBool* value = static_cast(GetValue(_instance, ValueID_Index_SensorBinary::Sensor_1))) + { + value->OnValueRefreshed(_data[1] != 0); + value->Release(); + } + + return true; + } + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Update class values based in BASIC mapping //----------------------------------------------------------------------------- -void SensorBinary::SetValueBasic -( - uint8 const _instance, - uint8 const _value -) -{ - // Send a request for new value to synchronize it with the BASIC set/report. - // In case the device is sleeping, we set the value anyway so the BASIC set/report - // stays in sync with it. We must be careful mapping the uint8 BASIC value - // into a class specific value. - // When the device wakes up, the real requested value will be retrieved. - RequestValue( 0, 0, _instance, Driver::MsgQueue_Send ); - if( Node* node = GetNodeUnsafe() ) - { - if( WakeUp* wakeUp = static_cast( node->GetCommandClass( WakeUp::StaticGetCommandClassId() ) ) ) - { - if( !wakeUp->IsAwake() ) + void SensorBinary::SetValueBasic(uint8 const _instance, uint8 const _value) { - if( ValueBool* value = static_cast( GetValue( _instance, 0 ) ) ) + // Send a request for new value to synchronize it with the BASIC set/report. + // In case the device is sleeping, we set the value anyway so the BASIC set/report + // stays in sync with it. We must be careful mapping the uint8 BASIC value + // into a class specific value. + // When the device wakes up, the real requested value will be retrieved. + RequestValue(0, 0, _instance, Driver::MsgQueue_Send); + if (Node* node = GetNodeUnsafe()) { - value->OnValueRefreshed( _value != 0 ); - value->Release(); + if (WakeUp* wakeUp = static_cast(node->GetCommandClass(WakeUp::StaticGetCommandClassId()))) + { + if (!wakeUp->IsAwake()) + { + if (Internal::VC::ValueBool* value = static_cast(GetValue(_instance, 0))) + { + value->OnValueRefreshed(_value != 0); + value->Release(); + } + } + } } } - } - } -} //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void SensorBinary::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - node->CreateValueBool( ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, "Sensor", "", true, false, false, 0 ); - } -} + void SensorBinary::CreateVars(uint8 const _instance) + { + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueBool(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_SensorBinary::Sensor_1, "Sensor", "", true, false, false, 0); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/SensorBinary.h b/cpp/src/command_classes/SensorBinary.h index 35eb3f6265..e8b525a6fc 100644 --- a/cpp/src/command_classes/SensorBinary.h +++ b/cpp/src/command_classes/SensorBinary.h @@ -32,38 +32,62 @@ namespace OpenZWave { - class ValueBool; - - /** \brief Implements COMMAND_CLASS_SENSOR_BINARY (0x30), a Z-Wave device command class. - * \ingroup CommandClass - */ - class SensorBinary: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new SensorBinary( _homeId, _nodeId ); } - virtual ~SensorBinary(){} + namespace CC + { - static uint8 const StaticGetCommandClassId(){ return 0x30; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_SENSOR_BINARY"; } + /** \brief Implements COMMAND_CLASS_SENSOR_BINARY (0x30), a Z-Wave device command class. + * \ingroup CommandClass + */ + class SensorBinary: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new SensorBinary(_homeId, _nodeId); + } + virtual ~SensorBinary() + { + } - // From CommandClass - virtual void ReadXML( TiXmlElement const* _ccElement ); - virtual void WriteXML( TiXmlElement* _ccElement ); - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual void SetValueBasic( uint8 const _instance, uint8 const _value ); + static uint8 const StaticGetCommandClassId() + { + return 0x30; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_SENSOR_BINARY"; + } - protected: - virtual void CreateVars( uint8 const _instance ); + // From CommandClass + virtual void ReadXML(TiXmlElement const* _ccElement) override; + virtual void WriteXML(TiXmlElement* _ccElement) override; + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual void SetValueBasic(uint8 const _instance, uint8 const _value) override; - private: - SensorBinary( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} - map m_sensorsMap; - }; + protected: + virtual void CreateVars(uint8 const _instance) override; + private: + SensorBinary(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + } + map m_sensorsMap; + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/SensorMultilevel.cpp b/cpp/src/command_classes/SensorMultilevel.cpp index de21ac92ce..98a187601f 100644 --- a/cpp/src/command_classes/SensorMultilevel.cpp +++ b/cpp/src/command_classes/SensorMultilevel.cpp @@ -32,536 +32,277 @@ #include "Msg.h" #include "Node.h" #include "Driver.h" +#include "SensorMultiLevelCCTypes.h" #include "platform/Log.h" -#include "value_classes/ValueDecimal.h" - -using namespace OpenZWave; - -enum SensorMultilevelCmd -{ - SensorMultilevelCmd_SupportedGet = 0x01, - SensorMultilevelCmd_SupportedReport = 0x02, - SensorMultilevelCmd_Get = 0x04, - SensorMultilevelCmd_Report = 0x05 -}; - -enum SensorType -{ - SensorType_Temperature = 1, - SensorType_General, /* deprecated by v11 */ - SensorType_Luminance, - SensorType_Power, - SensorType_RelativeHumidity, - SensorType_Velocity, - SensorType_Direction, - SensorType_AtmosphericPressure, - SensorType_BarometricPressure, - SensorType_SolarRadiation, - SensorType_DewPoint, - SensorType_RainRate, - SensorType_TideLevel, - SensorType_Weight, - SensorType_Voltage, - SensorType_Current, - SensorType_CO2, - SensorType_AirFlow, - SensorType_TankCapacity, - SensorType_Distance, - SensorType_AnglePosition, - SensorType_Rotation, - SensorType_WaterTemperature, - SensorType_SoilTemperature, - SensorType_SeismicIntensity, - SensorType_SeismicMagnitude, - SensorType_Ultraviolet, - SensorType_ElectricalResistivity, - SensorType_ElectricalConductivity, - SensorType_Loudness, - SensorType_Moisture, - SensorType_Frequency, - SensorType_Time, - SensorType_TargetTemperature, - SensorType_PM25, - SensorType_CH2O, - SensorType_RadonConcentration, - SensorType_CH4Density, - SensorType_VOC, - SensorType_CO, - SensorType_SoilHumidity, - SensorType_SoilReactivity, - SensorType_SoilSalinity, - SensorType_HeartRate, - SensorType_BloodPressure, - SensorType_MuscleMass, - SensorType_FatMass, - SensorType_BoneMass, - SensorType_TBW, - SensorType_BMR, - SensorType_BMI, - SensorType_AccelerationX, - SensorType_AccelerationY, - SensorType_AccelerationZ, - SensorType_SmokeDensity, - SensorType_WaterFlow, - SensorType_WaterPressure, - SensorType_RFSignalStrength, - SensorType_PM10, - SensorType_RespiratoryRate, - SensorType_RelativeModulationLevel, - SensorType_BoilerWaterTemperature, - SensorType_DHWTemperature, - SensorType_OutsideTemperature, - SensorType_ExhaustTemperature, - SensorType_WaterChlorineLevel, - SensorType_WaterAcidity, - SensorType_WaterOxidation, - SensorType_MaxType -}; - -static char const* c_sensorTypeNames[] = -{ - "Undefined", - "Temperature", - "General", - "Luminance", - "Power", - "Relative Humidity", - "Velocity", - "Direction", - "Atmospheric Pressure", - "Barometric Pressure", - "Solar Radiation", - "Dew Point", - "Rain Rate", - "Tide Level", - "Weight", - "Voltage", - "Current", - "CO2 Level", - "Air Flow", - "Tank Capacity", - "Distance", - "Angle Position", - "Rotation", - "Water Temperature", - "Soil Temperature", - "Seismic Intensity", - "Seismic Magnitude", - "Ultraviolet", - "Electrical Resistivity", - "Electrical Conductivity", - "Loudness", - "Moisture", - "Frequency", - "Time", - "Target Temperature", - "Particulate Matter 2.5", - "Formaldehyde CH20-level", - "Radon Concentration", - "Methane (CH4) Density", - "Volatile Organic Compound Level", - "CO Level", - "Soil Humidity", - "Soil Reactivity", - "Soil Salinity", - "Heart Rate", - "Blood Pressure", - "Muscle Mass", - "Fat Mass", - "Bone Mass", - "Total Body Water", - "Basis Metabolic Rate", - "Body Mass Index", - "Acceleration X-axis", - "Acceleration Y-axis", - "Acceleration Z-axis", - "Smoke Density", - "Water Flow", - "Water Pressure", - "RF Signal Strength", - "Particulate Matter 10", - "Respiratory Rate", - "Relative Mdulation Level", - "Boiler Water Temperature", - "Domestic Hot Water Temperature", - "Outside Temperature", - "Exhaust Temperature", - "Water Chlorine Level", - "Water Acidity", - "Water Oxidation" -}; -static char const* c_tankCapcityUnits[] = -{ - "l", - "cbm", - "gal", - "" -}; - -static char const* c_distanceUnits[] = -{ - "m", - "cm", - "ft", - "" -}; - -static char const* c_anglePositionUnits[] = -{ - "%", - "deg N", - "deg S", - "" -}; +#include "value_classes/ValueDecimal.h" -static char const* c_seismicIntensityUnits[] = +namespace OpenZWave { - "mercalli", - "EU macroseismic", - "liedu", - "shindo", - "" -}; + namespace Internal + { + namespace CC + { -static char const* c_seismicMagnitudeUnits[] = -{ - "local", - "moment", - "surface wave", - "body wave", - "" -}; + enum SensorMultilevelCmd + { + SensorMultilevelCmd_SupportedGet = 0x01, + SensorMultilevelCmd_SupportedReport = 0x02, + SensorMultiLevelCmd_SupportedGetScale = 0x03, + SensorMultiLevelCmd_SupportedReportScale = 0x06, + SensorMultilevelCmd_Get = 0x04, + SensorMultilevelCmd_Report = 0x05 + }; -static char const* c_moistureUnits[] = -{ - "%", - "content", - "k ohms", - "water activity", - "" -}; //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool SensorMultilevel::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - bool res = false; - if( GetVersion() > 4 ) - { - if( _requestFlags & RequestFlag_Static ) - { - Msg* msg = new Msg( "SensorMultilevelCmd_SupportedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( SensorMultilevelCmd_SupportedGet ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - res = true; - } - } + bool SensorMultilevel::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + bool res = false; + if (GetVersion() > 4) + { + if (_requestFlags & RequestFlag_Static) + { + /* for Versions 5 and Above + * Send a Supported Get. When we get the Reply + * We will send a SupportedScaleGet Message + */ + Msg* msg = new Msg("SensorMultilevelCmd_SupportedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(SensorMultilevelCmd_SupportedGet); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + res = true; + } + } else { + if (_requestFlags & RequestFlag_Static) + { + /* For Versions 1-4 + ** Set a Get Message - The Reply will create our ValueID + */ + Msg* msg = new Msg("SensorMultilevelCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(SensorMultilevelCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + res = true; + } + } - if( _requestFlags & RequestFlag_Dynamic ) - { - res |= RequestValue( _requestFlags, 0, _instance, _queue ); - } + if (_requestFlags & RequestFlag_Dynamic) + { + res |= RequestValue(_requestFlags, 0, _instance, _queue); + } - return res; -} + return res; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool SensorMultilevel::RequestValue -( - uint32 const _requestFlags, - uint16 const _dummy, // = 0 (not used) - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - bool res = false; - if ( !m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) { - Log::Write( LogLevel_Info, GetNodeId(), "SensorMultilevelCmd_Get Not Supported on this node"); - return false; - } - if( GetVersion() < 5 ) - { - Msg* msg = new Msg( "SensorMultilevelCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( SensorMultilevelCmd_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - res = true; - } - else - { - for( uint8 i = 1; i < SensorType_MaxType; i++ ) - { - Value* value = GetValue( _instance, i ); - if( value != NULL ) + bool SensorMultilevel::RequestValue(uint32 const _requestFlags, uint16 const _index, // = 0 (not used) + uint8 const _instance, Driver::MsgQueue const _queue) { - value->Release(); - Msg* msg = new Msg( "SensorMultilevelCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( SensorMultilevelCmd_Get ); - msg->Append( i ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - res = true; - } - } - } - return res; -} - -//----------------------------------------------------------------------------- -// -// Handle a message from the Z-Wave network -//----------------------------------------------------------------------------- -bool SensorMultilevel::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if (SensorMultilevelCmd_SupportedReport == (SensorMultilevelCmd)_data[0]) - { - string msg = ""; - - if( Node* node = GetNodeUnsafe() ) - { - for( uint8 i = 1; i <= ( _length - 2 ); i++ ) - { - for( uint8 j = 0; j < 8; j++ ) + bool res = false; + if (!m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) { - if( _data[i] & ( 1 << j ) ) + Log::Write(LogLevel_Info, GetNodeId(), "SensorMultilevelCmd_Get Not Supported on this node"); + return false; + } + /* if Index is 0, then its a being called from RequestState + * so we just get all possible Sensor Values + */ + if (_index == 0) { + if (GetVersion() < 5) + { + Msg* msg = new Msg("SensorMultilevelCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(SensorMultilevelCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + res = true; + } + else { - if( msg != "" ) - msg += ", "; - uint8 index = ( ( i - 1 ) * 8 ) + j + 1; - if (index >= SensorType_MaxType) /* max size for c_sensorTypeNames */ + for (uint8 i = 1; i < 255; i++) { - Log::Write (LogLevel_Warning, GetNodeId(), "SensorType Value was greater than range. Dropping"); - continue; + Internal::VC::Value* value = GetValue(_instance, i); + if (value != NULL) + { + uint8_t scale = 0; + /* get the Default Scale they want */ + Internal::VC::ValueList *requestedScale = static_cast(GetValue(_instance, i+255)); + if (requestedScale) { + const Internal::VC::ValueList::Item *item = requestedScale->GetItem(); + if (item) + scale = item->m_value; + requestedScale->Release(); + } + value->Release(); + Msg* msg = new Msg("SensorMultilevelCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(4); + msg->Append(GetCommandClassId()); + msg->Append(SensorMultilevelCmd_Get); + msg->Append(i); + msg->Append(scale); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + res = true; + } } - msg += c_sensorTypeNames[index]; - ValueDecimal* value = static_cast( GetValue( _instance, index ) ); - if( value == NULL) - { - node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, index, c_sensorTypeNames[index], "", true, false, "0.0", 0 ); + } + return res; + } else if (_index < 256) { + Internal::VC::Value* value = GetValue(_instance, _index); + if (value != NULL) { + uint8_t scale = 0; + /* get the Default Scale they want */ + Internal::VC::ValueList *requestedScale = static_cast(GetValue(_instance, _index+255)); + if (requestedScale) { + const Internal::VC::ValueList::Item *item = requestedScale->GetItem(); + if (item) + scale = item->m_value; + requestedScale->Release(); } + value->Release(); + Msg* msg = new Msg("SensorMultilevelCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(4); + msg->Append(GetCommandClassId()); + msg->Append(SensorMultilevelCmd_Get); + msg->Append((uint8_t)(_index & 0xFF)); + msg->Append(scale); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; } } + return false; } - } - Log::Write( LogLevel_Info, GetNodeId(), "Received SensorMultiLevel supported report from node %d: %s", GetNodeId(), msg.c_str() ); - } - else if (SensorMultilevelCmd_Report == (SensorMultilevelCmd)_data[0]) - { - uint8 scale; - uint8 precision = 0; - uint8 sensorType = _data[1]; - string valueStr = ExtractValue( &_data[2], &scale, &precision ); - Node* node = GetNodeUnsafe(); - if( node != NULL ) - { - char const* units = ""; - switch( sensorType ) +//----------------------------------------------------------------------------- +// +// Handle a message from the Z-Wave network +//----------------------------------------------------------------------------- + bool SensorMultilevel::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) { - case SensorType_Temperature: units = scale ? "F" : "C"; break; - case SensorType_General: units = scale ? "" : "%"; break; - case SensorType_Luminance: units = scale ? "lux" : "%"; break; - case SensorType_Power: units = scale ? "BTU/h" : "W"; break; - case SensorType_RelativeHumidity: units = scale ? "" : "%"; break; - case SensorType_Velocity: units = scale ? "mph" : "m/s"; break; - case SensorType_Direction: units = ""; break; - case SensorType_AtmosphericPressure: units = scale ? "inHg" : "kPa"; break; - case SensorType_BarometricPressure: units = scale ? "inHg" : "kPa"; break; - case SensorType_SolarRadiation: units = "W/m2"; break; - case SensorType_DewPoint: units = scale ? "F" : "C"; break; - case SensorType_RainRate: units = scale ? "in/h" : "mm/h"; break; - case SensorType_TideLevel: units = scale ? "ft" : "m"; break; - case SensorType_Weight: units = scale ? "lb" : "kg"; break; - case SensorType_Voltage: units = scale ? "mV" : "V"; break; - case SensorType_Current: units = scale ? "mA" : "A"; break; - case SensorType_CO2: units = "ppm"; break; - case SensorType_AirFlow: units = scale ? "cfm" : "m3/h"; break; - case SensorType_TankCapacity: { - if (scale > 2) /* size of c_tankCapcityUnits minus invalid */ - { - Log::Write (LogLevel_Warning, GetNodeId(), "Scale Value for c_tankCapcityUnits was greater than range. Setting to empty"); - units = c_tankCapcityUnits[3]; /* empty entry */ - } - else - { - units = c_tankCapcityUnits[scale]; - } - } - break; - case SensorType_Distance: { - if (scale > 2) /* size of c_distanceUnits minus invalid */ - { - Log::Write (LogLevel_Warning, GetNodeId(), "Scale Value for c_distanceUnits was greater than range. Setting to empty"); - units = c_distanceUnits[3]; /* empty entry */ - } - else - { - units = c_distanceUnits[scale]; - } - } - break; - case SensorType_AnglePosition: { - if (scale > 2) /* size of c_anglePositionUnits minus invalid */ - { - Log::Write (LogLevel_Warning, GetNodeId(), "Scale Value for c_anglePositionUnits was greater than range. Setting to empty"); - units = c_anglePositionUnits[3]; /* empty entry */ - } - else - { - units = c_anglePositionUnits[scale]; - } - } - break; - case SensorType_Rotation: units = scale ? "hz" : "rpm"; break; - case SensorType_WaterTemperature: units = scale ? "F" : "C"; break; - case SensorType_SoilTemperature: units = scale ? "F" : "C"; break; - case SensorType_SeismicIntensity: { - if (scale > 3) /* size of c_seismicIntensityUnits minus invalid */ - { - Log::Write (LogLevel_Warning, GetNodeId(), "Scale Value for c_seismicIntensityUnits was greater than range. Setting to empty"); - units = c_seismicIntensityUnits[4]; /* empty entry */ - } - else + if (SensorMultilevelCmd_SupportedReport == (SensorMultilevelCmd) _data[0]) + { + string msg = ""; + + if (GetNodeUnsafe()) { - units = c_seismicIntensityUnits[scale]; + for (uint8 i = 1; i <= (_length - 2); i++) + { + for (uint8 j = 0; j < 8; j++) + { + if (_data[i] & (1 << j)) + { + uint32_t sensorType = ((i - 1) * 8) + j + 1; + Log::Write(LogLevel_Info, GetNodeId(), "Received SensorMultiLevel supported report from node %d: %s (%d)", GetNodeId(), SensorMultiLevelCCTypes::Get()->GetSensorName(sensorType).c_str(), sensorType); + Msg* msg = new Msg("SensorMultiLevelCmd_SupportedGetScale", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(SensorMultiLevelCmd_SupportedGetScale); + msg->Append(sensorType); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue::MsgQueue_Send); + } + } + } } + return true; } - break; - case SensorType_SeismicMagnitude: { - if (scale > 3) /* size of c_seismicMagnitudeUnits minus invalid */ + else if (SensorMultiLevelCmd_SupportedReportScale == (SensorMultilevelCmd) _data[0]) + { + uint32_t sensorType = _data[1]; + int8_t defaultScale = -1; + vector items; + for (int i = 0; i <= 3; i++) { - Log::Write (LogLevel_Warning, GetNodeId(), "Scale Value for c_seismicMagnitudeUnits was greater than range. Setting to empty"); - units = c_seismicMagnitudeUnits[4]; /* empty entry */ + if ((_data[2] & 0x07) & (1 << i)) { + + uint8 sensorScale = i; + if (defaultScale == -1) + defaultScale = sensorScale; + Log::Write(LogLevel_Info, GetNodeId(), "Received SensorMultiLevel supported Scale report from node %d for Sensor %s: %s (%d)", GetNodeId(), SensorMultiLevelCCTypes::Get()->GetSensorName(sensorType).c_str(), SensorMultiLevelCCTypes::Get()->GetSensorUnit(sensorType, sensorScale).c_str(), sensorScale); + Internal::VC::ValueList::Item item; + item.m_label = SensorMultiLevelCCTypes::Get()->GetSensorUnitName(sensorType, sensorScale); + item.m_value = sensorScale; + items.push_back(item); + } } - else + Log::Write(LogLevel_Info, GetNodeId(), "Setting SensorMultiLevel Default Scale to: %s (%d)", SensorMultiLevelCCTypes::Get()->GetSensorUnit(sensorType, defaultScale).c_str(), defaultScale); + + if (Node* node = GetNodeUnsafe()) { - units = c_seismicMagnitudeUnits[scale]; + node->CreateValueDecimal(ValueID::ValueGenre_User, GetCommandClassId(), _instance, sensorType, SensorMultiLevelCCTypes::Get()->GetSensorName(sensorType), SensorMultiLevelCCTypes::Get()->GetSensorUnit(sensorType, defaultScale), true, false, "0.0", 0); + node->CreateValueList(ValueID::ValueGenre_System, GetCommandClassId(), _instance, sensorType+255, SensorMultiLevelCCTypes::Get()->GetSensorName(sensorType).append(" Units").c_str(), "", false, false, 1, items, 0, 0); + Internal::VC::ValueList *value = static_cast(GetValue(_instance, sensorType+255)); + if (value) + value->SetByLabel(SensorMultiLevelCCTypes::Get()->GetSensorUnit(sensorType, defaultScale)); } + return true; } - break; - case SensorType_Ultraviolet: units = ""; break; - case SensorType_ElectricalResistivity: units = "ohm"; break; - case SensorType_ElectricalConductivity: units = "siemens/m"; break; - case SensorType_Loudness: units = scale ? "dBA" : "db"; break; - case SensorType_Moisture: { - if (scale > 3) /* size of c_moistureUnits minus invalid */ - { - Log::Write (LogLevel_Warning, GetNodeId(), "Scale Value for c_moistureUnits was greater than range. Setting to empty"); - units = c_moistureUnits[4]; /* empty entry */ - } - else + else if (SensorMultilevelCmd_Report == (SensorMultilevelCmd) _data[0]) + { + uint8 scale; + uint8 precision = 0; + uint8 sensorType = _data[1]; + string valueStr = ExtractValue(&_data[2], &scale, &precision); + + Node* node = GetNodeUnsafe(); + if (node != NULL) { - units = c_moistureUnits[scale]; + Internal::VC::ValueDecimal* value = static_cast(GetValue(_instance, sensorType)); + if (value == NULL) + { + node->CreateValueDecimal(ValueID::ValueGenre_User, GetCommandClassId(), _instance, sensorType, SensorMultiLevelCCTypes::Get()->GetSensorName(sensorType), "", true, false, "0.0", 0); + value = static_cast(GetValue(_instance, sensorType)); + } + value->SetUnits(SensorMultiLevelCCTypes::Get()->GetSensorUnit(sensorType, scale)); + + Log::Write(LogLevel_Info, GetNodeId(), "Received SensorMultiLevel report from node %d, instance %d, %s: value=%s%s", GetNodeId(), _instance, SensorMultiLevelCCTypes::Get()->GetSensorName(sensorType).c_str(), valueStr.c_str(), value->GetUnits().c_str()); + if (value->GetPrecision() != precision) + { + value->SetPrecision(precision); + } + value->OnValueRefreshed(valueStr); + value->Release(); + return true; } } - break; - case SensorType_Frequency: units = scale ? "kHz" : "Hz"; break; - case SensorType_Time: units = "s"; break; - case SensorType_TargetTemperature: units = scale ? "F" : "C"; break; - case SensorType_PM25: units = scale ? "ug/m3" : "mol/m3"; break; - case SensorType_CH2O: units = "mol/m3"; break; - case SensorType_RadonConcentration: units = scale ? "pCi/l" : "bq/m3"; break; - case SensorType_CH4Density: units = "mol/m3"; break; - case SensorType_VOC: units = scale ? "ppm" : "mol/m3"; break; - case SensorType_CO: units = scale ? "ppm" : "mol/m3"; break; - case SensorType_SoilHumidity: units = "%"; break; - case SensorType_SoilReactivity: units = "pH"; break; - case SensorType_SoilSalinity: units = "mol/m3"; break; - case SensorType_HeartRate: units = "bpm"; break; - case SensorType_BloodPressure: units = scale ? "mmHg (Diastollic)" : "mmHg (Systollic)"; break; - case SensorType_MuscleMass: units = "kg"; break; - case SensorType_FatMass: units = "kg"; break; - case SensorType_BoneMass: units = "kg"; break; - case SensorType_TBW: units = "kg"; break; - case SensorType_BMR: units = "J"; break; - case SensorType_BMI: units = ""; break; - case SensorType_AccelerationX: units = "m/s2"; break; - case SensorType_AccelerationY: units = "m/s2"; break; - case SensorType_AccelerationZ: units = "m/s2"; break; - case SensorType_SmokeDensity: units = "%"; break; - case SensorType_WaterFlow: units = "l/h"; break; - case SensorType_WaterPressure: units = "kPa"; break; - case SensorType_RFSignalStrength: units = scale ? "dBm" : "% (RSSI)"; break; - case SensorType_PM10: units = scale ? "ug/m3" : "mol/m3"; break; - case SensorType_RespiratoryRate: units = "bpm"; break; - case SensorType_RelativeModulationLevel: units = "%"; break; - case SensorType_BoilerWaterTemperature: units = "C"; break; - case SensorType_DHWTemperature: units = "C"; break; - case SensorType_OutsideTemperature: units = "C"; break; - case SensorType_ExhaustTemperature: units = "C"; break; - case SensorType_WaterChlorineLevel: units = "mg/l"; break; - case SensorType_WaterAcidity: units = "pH"; break; - case SensorType_WaterOxidation: units = "mV"; break; - default: { - Log::Write (LogLevel_Warning, GetNodeId(), "sensorType Value was greater than range. Dropping"); - return false; - } - break; - - } - - ValueDecimal* value = static_cast( GetValue( _instance, sensorType ) ); - if( value == NULL) - { - node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, sensorType, c_sensorTypeNames[sensorType], units, true, false, "0.0", 0 ); - value = static_cast( GetValue( _instance, sensorType ) ); - } - else - { - value->SetUnits(units); - } - - Log::Write( LogLevel_Info, GetNodeId(), "Received SensorMultiLevel report from node %d, instance %d, %s: value=%s%s", GetNodeId(), _instance, c_sensorTypeNames[sensorType], valueStr.c_str(), value->GetUnits().c_str() ); - if( value->GetPrecision() != precision ) - { - value->SetPrecision( precision ); + return false; } - value->OnValueRefreshed( valueStr ); - value->Release(); - return true; - } - } - return false; -} //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void SensorMultilevel::CreateVars -( - uint8 const _instance -) -{ - // Don't create anything here. We do it in the report. -} + void SensorMultilevel::CreateVars(uint8 const _instance) + { + // Don't create anything here. We do it in the report. + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/SensorMultilevel.h b/cpp/src/command_classes/SensorMultilevel.h index b3d33ae26d..56cab16fdf 100644 --- a/cpp/src/command_classes/SensorMultilevel.h +++ b/cpp/src/command_classes/SensorMultilevel.h @@ -32,38 +32,65 @@ namespace OpenZWave { - class ValueDecimal; - - /** \brief Implements COMMAND_CLASS_SENSOR_MULTILEVEL (0x31), a Z-Wave device command class. - * \ingroup CommandClass - */ - class SensorMultilevel: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new SensorMultilevel( _homeId, _nodeId ); } - virtual ~SensorMultilevel(){} + namespace CC + { - static uint8 const StaticGetCommandClassId(){ return 0x31; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_SENSOR_MULTILEVEL"; } + /** \brief Implements COMMAND_CLASS_SENSOR_MULTILEVEL (0x31), a Z-Wave device command class. + * \ingroup CommandClass + */ + class SensorMultilevel: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new SensorMultilevel(_homeId, _nodeId); + } + virtual ~SensorMultilevel() + { + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _dummy, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); + static uint8 const StaticGetCommandClassId() + { + return 0x31; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_SENSOR_MULTILEVEL"; + } - virtual uint8 GetMaxVersion(){ return 11; } + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _dummy, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; - protected: - virtual void CreateVars( uint8 const _instance ); + virtual uint8 GetMaxVersion() override + { + return 11; + } - private: - SensorMultilevel( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} - }; + protected: + virtual void CreateVars(uint8 const _instance) override; + private: + SensorMultilevel(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + } + std::map SensorScaleMap; + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave - #endif diff --git a/cpp/src/command_classes/SimpleAV.cpp b/cpp/src/command_classes/SimpleAV.cpp index 7f103e02d9..449e4e8954 100644 --- a/cpp/src/command_classes/SimpleAV.cpp +++ b/cpp/src/command_classes/SimpleAV.cpp @@ -1,3 +1,29 @@ +//----------------------------------------------------------------------------- +// +// SimpleAVCommandItem.h +// +// Implementation of the Z-Wave COMMAND_CLASS_SIMPLE_AV_CONTROL +// +// Copyright (c) 2018 +// +// SOFTWARE NOTICE AND LICENSE +// +// This file is part of OpenZWave. +// +// OpenZWave is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, either version 3 of the License, +// or (at your option) any later version. +// +// OpenZWave is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with OpenZWave. If not, see . +// +//----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/MultiInstance.h" #include "command_classes/SimpleAV.h" @@ -12,153 +38,151 @@ #include "value_classes/ValueShort.h" #include "value_classes/ValueList.h" -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace CC + { -uint8 m_sequence; + uint8 m_sequence; -enum SimpleAVCmd -{ - SimpleAVCmd_Set = 0x01 -}; + enum SimpleAVCmd + { + SimpleAVCmd_Set = 0x01 + }; //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool SimpleAV::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance -) -{ - return true; -} + bool SimpleAV::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance) + { + return true; + } //----------------------------------------------------------------------------- // // Set a value in the Z-Wave device //----------------------------------------------------------------------------- -bool SimpleAV::SetValue -( - Value const& _value -) -{ - uint16 shortval; - if (ValueID::ValueType_Short == _value.GetID().GetType()) - { - ValueShort const* value = static_cast(&_value); - shortval = value->GetValue(); - } - else if (ValueID::ValueType_List == _value.GetID().GetType()) - { - ValueList const* value = static_cast(&_value); - shortval = value->GetItem()->m_value; - } - else return false; + bool SimpleAV::SetValue(Internal::VC::Value const& _value) + { + uint16 shortval; + if (ValueID::ValueType_Short == _value.GetID().GetType()) + { + Internal::VC::ValueShort const* value = static_cast(&_value); + shortval = value->GetValue(); + } + else if (ValueID::ValueType_List == _value.GetID().GetType()) + { + Internal::VC::ValueList const* value = static_cast(&_value); + shortval = value->GetItem()->m_value; + } + else + return false; - uint8 instance = _value.GetID().GetInstance(); - Msg* msg = new Msg("SimpleAVCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); - msg->SetInstance(this, instance); - msg->Append(GetNodeId()); - msg->Append(8); // Length - msg->Append(GetCommandClassId()); - msg->Append(SimpleAVCmd_Set); - msg->Append(m_sequence++); // Crutch - msg->Append(0); - msg->Append(0); - msg->Append(0); - msg->Append(shortval >> 8); - msg->Append(shortval & 0xff); - msg->Append(GetDriver()->GetTransmitOptions()); - GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + uint8 instance = _value.GetID().GetInstance(); + Msg* msg = new Msg("SimpleAVCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->SetInstance(this, instance); + msg->Append(GetNodeId()); + msg->Append(8); // Length + msg->Append(GetCommandClassId()); + msg->Append(SimpleAVCmd_Set); + msg->Append(m_sequence++); // Crutch + msg->Append(0); + msg->Append(0); + msg->Append(0); + msg->Append(shortval >> 8); + msg->Append(shortval & 0xff); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); - if (m_sequence == 255) - m_sequence = 0; + if (m_sequence == 255) + m_sequence = 0; - return true; -} + return true; + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void SimpleAV::CreateVars -( - uint8 const _instance -) -{ - if (Node* node = GetNodeUnsafe()) - { - // Create list value - vector items; - vector commands = SimpleAVCommandItem::GetCommands(); - vector::iterator iterator; - string helpList = "Possible values: \n"; - string helpNumeric = "Possible values: \n"; - for (iterator = commands.begin(); iterator != commands.end(); iterator++) - { - SimpleAVCommandItem command = *iterator; - if (command.GetVersion() <= GetVersion()) + void SimpleAV::CreateVars(uint8 const _instance) { - ValueList::Item item; - item.m_value = command.GetCode(); - item.m_label = command.GetName(); - items.push_back(item); + if (Node* node = GetNodeUnsafe()) + { + // Create list value + vector items; + vector commands = SimpleAVCommandItem::GetCommands(); + vector::iterator iterator; + string helpList = "Possible values: \n"; + string helpNumeric = "Possible values: \n"; + for (iterator = commands.begin(); iterator != commands.end(); iterator++) + { + SimpleAVCommandItem command = *iterator; + if (command.GetVersion() <= GetVersion()) + { + Internal::VC::ValueList::Item item; + item.m_value = command.GetCode(); + item.m_label = command.GetName(); + items.push_back(item); #if 0 - // ValueList - create command description for help - string codeStr = string("ZWave command number: ").append(std::to_string(command.GetCode())); - string descriptionFull = ""; - if (command.GetDescription() == "") - { - descriptionFull = - command - .GetName() - .append(" (") - .append(codeStr) - .append(")\n"); - } - else - { - descriptionFull = - command - .GetName() - .append(" (") - .append(command.GetDescription()) - .append("; ") - .append(codeStr) - .append(")\n"); - } - helpList += descriptionFull; + // ValueList - create command description for help + string codeStr = string("ZWave command number: ").append(std::to_string(command.GetCode())); + string descriptionFull = ""; + if (command.GetDescription() == "") + { + descriptionFull = + command + .GetName() + .append(" (") + .append(codeStr) + .append(")\n"); + } + else + { + descriptionFull = + command + .GetName() + .append(" (") + .append(command.GetDescription()) + .append("; ") + .append(codeStr) + .append(")\n"); + } + helpList += descriptionFull; - // ValueShort - create command description for help - if (command.GetDescription() == "") - { - descriptionFull = - std::to_string(command.GetCode()) - .append(" (") - .append(command.GetName()) - .append(")\n"); - } - else - { - descriptionFull = - std::to_string(command.GetCode()) - .append(" (") - .append(command.GetName()) - .append("; ") - .append(command.GetDescription()) - .append(")\n"); - } - helpNumeric += descriptionFull; + // ValueShort - create command description for help + if (command.GetDescription() == "") + { + descriptionFull = + std::to_string(command.GetCode()) + .append(" (") + .append(command.GetName()) + .append(")\n"); + } + else + { + descriptionFull = + std::to_string(command.GetCode()) + .append(" (") + .append(command.GetName()) + .append("; ") + .append(command.GetDescription()) + .append(")\n"); + } + helpNumeric += descriptionFull; #endif - } - } + } + } + + node->CreateValueList(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_SimpleAV::Command, string("OutputAVCommand_").append(std::to_string(_instance)), "", false, true, 2, items, 0, 0); - node->CreateValueList(ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, string("OutputAVCommand_").append(std::to_string(_instance)), "", false, true, 2, items, 0, 0); - - // Create a similar numeric value - // node->CreateValueShort(ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, string("OutputAVCommandNumber_").append(std::to_string(_instance)), "", false, true, 0, 0, helpNumeric); - } -} \ No newline at end of file + // Create a similar numeric value + // node->CreateValueShort(ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, string("OutputAVCommandNumber_").append(std::to_string(_instance)), "", false, true, 0, 0, helpNumeric); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/SimpleAV.h b/cpp/src/command_classes/SimpleAV.h index 1433dbe3ac..759a082a85 100644 --- a/cpp/src/command_classes/SimpleAV.h +++ b/cpp/src/command_classes/SimpleAV.h @@ -1,29 +1,80 @@ +//----------------------------------------------------------------------------- +// +// SimpleAVCommandItem.h +// +// Implementation of the Z-Wave COMMAND_CLASS_SIMPLE_AV_CONTROL +// +// Copyright (c) 2018 +// +// SOFTWARE NOTICE AND LICENSE +// +// This file is part of OpenZWave. +// +// OpenZWave is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, either version 3 of the License, +// or (at your option) any later version. +// +// OpenZWave is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with OpenZWave. If not, see . +// +//----------------------------------------------------------------------------- #include "command_classes/CommandClass.h" namespace OpenZWave { - /** Implements COMMAND_CLASS_SIMPLE_AV_CONTROL (0x94), a Z-Wave device command class. */ - class SimpleAV : public CommandClass + namespace Internal { - public: - static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) { return new SimpleAV(_homeId, _nodeId); } - virtual ~SimpleAV() {} + namespace CC + { + /** Implements COMMAND_CLASS_SIMPLE_AV_CONTROL (0x94), a Z-Wave device command class. */ + class SimpleAV: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new SimpleAV(_homeId, _nodeId); + } + virtual ~SimpleAV() + { + } - static uint8 const StaticGetCommandClassId() { return 0x94; } - static string const StaticGetCommandClassName() { return "COMMAND_CLASS_SIMPLE_AV_CONTROL"; } + static uint8 const StaticGetCommandClassId() + { + return 0x94; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_SIMPLE_AV_CONTROL"; + } - // From CommandClass - virtual uint8 const GetCommandClassId()const { return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const { return StaticGetCommandClassName(); } - virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1); - virtual bool SetValue(Value const& _value); + // From CommandClass + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool SetValue(Internal::VC::Value const& _value) override; - protected: - virtual void CreateVars(uint8 const _instance); - - private: - SimpleAV(uint32 const _homeId, uint8 const _nodeId) : CommandClass(_homeId, _nodeId) {} - uint8 m_sequence; - }; + protected: + virtual void CreateVars(uint8 const _instance) override; -} // namespace OpenZWave \ No newline at end of file + private: + SimpleAV(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId), m_sequence(0) + { + } + uint8 m_sequence; + }; + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/SimpleAVCommandItem.cpp b/cpp/src/command_classes/SimpleAVCommandItem.cpp index 3389ba76b5..cf36d7f917 100644 --- a/cpp/src/command_classes/SimpleAVCommandItem.cpp +++ b/cpp/src/command_classes/SimpleAVCommandItem.cpp @@ -1,525 +1,553 @@ +//----------------------------------------------------------------------------- +// +// SimpleAVCommandItem.h +// +// Implementation of the Z-Wave COMMAND_CLASS_SIMPLE_AV_CONTROL +// +// Copyright (c) 2018 +// +// SOFTWARE NOTICE AND LICENSE +// +// This file is part of OpenZWave. +// +// OpenZWave is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, either version 3 of the License, +// or (at your option) any later version. +// +// OpenZWave is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with OpenZWave. If not, see . +// +//----------------------------------------------------------------------------- #include "SimpleAVCommandItem.h" #include #include #include "Defs.h" -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace CC + { -static vector m_commands; + static std::vector m_commands; //----------------------------------------------------------------------------- // // SimpleAVCommand constructor //----------------------------------------------------------------------------- -SimpleAVCommandItem::SimpleAVCommandItem -( - uint16 const _code, - string _name, - string _description, - uint16 const _version -) -{ - m_code = _code; - m_name = _name; - m_description = _description; - m_version = _version; -} + SimpleAVCommandItem::SimpleAVCommandItem(uint16 const _code, string _name, string _description, uint16 const _version) + { + m_code = _code; + m_name = _name; + m_description = _description; + m_version = _version; + } //----------------------------------------------------------------------------- // // Get code of ZWave AV command //----------------------------------------------------------------------------- -uint16 SimpleAVCommandItem::GetCode() -{ - return m_code; -} + uint16 SimpleAVCommandItem::GetCode() + { + return m_code; + } //----------------------------------------------------------------------------- // // Get version of AV simple command class of command //----------------------------------------------------------------------------- -uint16 SimpleAVCommandItem::GetVersion() -{ - return m_version; -} + uint16 SimpleAVCommandItem::GetVersion() + { + return m_version; + } //----------------------------------------------------------------------------- // // Get human-friendly name of AV command //----------------------------------------------------------------------------- -string SimpleAVCommandItem::GetName() -{ - return m_name; -} + std::string SimpleAVCommandItem::GetName() + { + return m_name; + } //----------------------------------------------------------------------------- // // Get human-friendly description of AV command //----------------------------------------------------------------------------- -string SimpleAVCommandItem::GetDescription() -{ - return m_description; -} + std::string SimpleAVCommandItem::GetDescription() + { + return m_description; + } //----------------------------------------------------------------------------- // // Get all available AV commands //----------------------------------------------------------------------------- -vector SimpleAVCommandItem::GetCommands() -{ - if (m_commands.size() == 0) - { - // Generated code - m_commands.push_back(SimpleAVCommandItem(1, "Mute", "", 1)); - m_commands.push_back(SimpleAVCommandItem(2, "Volume Down", "Level Down", 1)); - m_commands.push_back(SimpleAVCommandItem(3, "Volume Up", "Level Up", 1)); - m_commands.push_back(SimpleAVCommandItem(4, "Channel Up", "Program Up", 1)); - m_commands.push_back(SimpleAVCommandItem(5, "Channel Down", "Program Down", 1)); - m_commands.push_back(SimpleAVCommandItem(6, "0", "Preset 10", 1)); - m_commands.push_back(SimpleAVCommandItem(7, "1", "Preset 1", 1)); - m_commands.push_back(SimpleAVCommandItem(8, "2", "Preset 2", 1)); - m_commands.push_back(SimpleAVCommandItem(9, "3", "Preset 3", 1)); - m_commands.push_back(SimpleAVCommandItem(10, "4", "Preset 4", 1)); - m_commands.push_back(SimpleAVCommandItem(11, "5", "Preset 5", 1)); - m_commands.push_back(SimpleAVCommandItem(12, "6", "Preset 6", 1)); - m_commands.push_back(SimpleAVCommandItem(13, "7", "Preset 7", 1)); - m_commands.push_back(SimpleAVCommandItem(14, "8", "Preset 8", 1)); - m_commands.push_back(SimpleAVCommandItem(15, "9", "Preset 9", 1)); - m_commands.push_back(SimpleAVCommandItem(16, "Last Channel", "Recall, Previous Channel (WMC)", 1)); - m_commands.push_back(SimpleAVCommandItem(17, "Display", "Info", 1)); - m_commands.push_back(SimpleAVCommandItem(18, "Favorite Channel", "Favorite", 1)); - m_commands.push_back(SimpleAVCommandItem(19, "Play", "", 1)); - m_commands.push_back(SimpleAVCommandItem(20, "Stop", "", 1)); - m_commands.push_back(SimpleAVCommandItem(21, "Pause", "Still", 1)); - m_commands.push_back(SimpleAVCommandItem(22, "Fast Forward", "Search Forward", 1)); - m_commands.push_back(SimpleAVCommandItem(23, "Rewind", "Search Reverse", 1)); - m_commands.push_back(SimpleAVCommandItem(24, "Instant Replay", "Replay", 1)); - m_commands.push_back(SimpleAVCommandItem(25, "Record", "", 1)); - m_commands.push_back(SimpleAVCommandItem(26, "AC3", "Dolby Digital", 1)); - m_commands.push_back(SimpleAVCommandItem(27, "PVR Menu", "Tivo", 1)); - m_commands.push_back(SimpleAVCommandItem(28, "Guide", "EPG", 1)); - m_commands.push_back(SimpleAVCommandItem(29, "Menu", "Settings", 1)); - m_commands.push_back(SimpleAVCommandItem(30, "Menu Up", "Adjust Up", 1)); - m_commands.push_back(SimpleAVCommandItem(31, "Menu Down", "Adjust Down", 1)); - m_commands.push_back(SimpleAVCommandItem(32, "Menu Left", "Cursor Left", 1)); - m_commands.push_back(SimpleAVCommandItem(33, "Menu Right", "Cursor Right", 1)); - m_commands.push_back(SimpleAVCommandItem(34, "Page Up", "", 1)); - m_commands.push_back(SimpleAVCommandItem(35, "Page Down", "", 1)); - m_commands.push_back(SimpleAVCommandItem(36, "Select", "OK", 1)); - m_commands.push_back(SimpleAVCommandItem(37, "Exit", "", 1)); - m_commands.push_back(SimpleAVCommandItem(38, "Input", "Input Select", 1)); - m_commands.push_back(SimpleAVCommandItem(39, "Power", "Standby", 1)); - m_commands.push_back(SimpleAVCommandItem(40, "Enter Channel", "Channel Enter", 1)); - m_commands.push_back(SimpleAVCommandItem(41, "10", "", 1)); - m_commands.push_back(SimpleAVCommandItem(42, "11", "", 1)); - m_commands.push_back(SimpleAVCommandItem(43, "12", "", 1)); - m_commands.push_back(SimpleAVCommandItem(44, "13", "", 1)); - m_commands.push_back(SimpleAVCommandItem(45, "14", "", 1)); - m_commands.push_back(SimpleAVCommandItem(46, "15", "", 1)); - m_commands.push_back(SimpleAVCommandItem(47, "16", "", 1)); - m_commands.push_back(SimpleAVCommandItem(48, "10", "10+", 1)); - m_commands.push_back(SimpleAVCommandItem(49, "20", "20+", 1)); - m_commands.push_back(SimpleAVCommandItem(50, "100", "", 1)); - m_commands.push_back(SimpleAVCommandItem(51, "-/--", "", 1)); - m_commands.push_back(SimpleAVCommandItem(52, "3-CH", "", 1)); - m_commands.push_back(SimpleAVCommandItem(53, "3D", "Simulated Stereo", 1)); - m_commands.push_back(SimpleAVCommandItem(54, "6-CH Input", "6 Channel", 1)); - m_commands.push_back(SimpleAVCommandItem(55, "A", "", 1)); - m_commands.push_back(SimpleAVCommandItem(56, "Add", "Write", 1)); - m_commands.push_back(SimpleAVCommandItem(57, "Alarm", "", 1)); - m_commands.push_back(SimpleAVCommandItem(58, "AM", "", 1)); - m_commands.push_back(SimpleAVCommandItem(59, "Analog", "", 1)); - m_commands.push_back(SimpleAVCommandItem(60, "Angle", "", 1)); - m_commands.push_back(SimpleAVCommandItem(61, "Antenna", "External", 1)); - m_commands.push_back(SimpleAVCommandItem(62, "Antenna East", "", 1)); - m_commands.push_back(SimpleAVCommandItem(63, "Antenna West", "", 1)); - m_commands.push_back(SimpleAVCommandItem(64, "Aspect", "Size", 1)); - m_commands.push_back(SimpleAVCommandItem(65, "Audio 1", "Audio", 1)); - m_commands.push_back(SimpleAVCommandItem(66, "Audio 2", "", 1)); - m_commands.push_back(SimpleAVCommandItem(67, "Audio 3", "", 1)); - m_commands.push_back(SimpleAVCommandItem(68, "Audio Dubbing", "", 1)); - m_commands.push_back(SimpleAVCommandItem(69, "Audio Level Down", "", 1)); - m_commands.push_back(SimpleAVCommandItem(70, "Audio Level Up", "", 1)); - m_commands.push_back(SimpleAVCommandItem(71, "Auto/Manual", "", 1)); - m_commands.push_back(SimpleAVCommandItem(72, "Aux 1", "Aux", 1)); - m_commands.push_back(SimpleAVCommandItem(73, "Aux 2", "", 1)); - m_commands.push_back(SimpleAVCommandItem(74, "B", "", 1)); - m_commands.push_back(SimpleAVCommandItem(75, "Back", "Previous Screen", 1)); - m_commands.push_back(SimpleAVCommandItem(76, "Background", "Backlight", 1)); - m_commands.push_back(SimpleAVCommandItem(77, "Balance", "", 1)); - m_commands.push_back(SimpleAVCommandItem(78, "Balance Left", "", 1)); - m_commands.push_back(SimpleAVCommandItem(79, "Balance Right", "", 1)); - m_commands.push_back(SimpleAVCommandItem(80, "Band", "FM/AM", 1)); - m_commands.push_back(SimpleAVCommandItem(81, "Bandwidth", "Wide/Narrow", 1)); - m_commands.push_back(SimpleAVCommandItem(82, "Bass", "", 1)); - m_commands.push_back(SimpleAVCommandItem(83, "Bass Down", "", 1)); - m_commands.push_back(SimpleAVCommandItem(84, "Bass Up", "", 1)); - m_commands.push_back(SimpleAVCommandItem(85, "Blank", "", 1)); - m_commands.push_back(SimpleAVCommandItem(86, "Breeze Mode", "", 1)); - m_commands.push_back(SimpleAVCommandItem(87, "Bright", "Brighten", 1)); - m_commands.push_back(SimpleAVCommandItem(88, "Brightness", "", 1)); - m_commands.push_back(SimpleAVCommandItem(89, "Brightness Down", "", 1)); - m_commands.push_back(SimpleAVCommandItem(90, "Brightness Up", "", 1)); - m_commands.push_back(SimpleAVCommandItem(91, "Buy", "", 1)); - m_commands.push_back(SimpleAVCommandItem(92, "C", "", 1)); - m_commands.push_back(SimpleAVCommandItem(93, "Camera", "", 1)); - m_commands.push_back(SimpleAVCommandItem(94, "Category Down", "", 1)); - m_commands.push_back(SimpleAVCommandItem(95, "Category Up", "", 1)); - m_commands.push_back(SimpleAVCommandItem(96, "Center", "", 1)); - m_commands.push_back(SimpleAVCommandItem(97, "Center Down", "Center Volume Down", 1)); - m_commands.push_back(SimpleAVCommandItem(98, "Center Mode", "", 1)); - m_commands.push_back(SimpleAVCommandItem(99, "Center Up", "Center Volume Up", 1)); - m_commands.push_back(SimpleAVCommandItem(100, "Channel/Program", "C/P", 1)); - m_commands.push_back(SimpleAVCommandItem(101, "Clear", "Cancel", 1)); - m_commands.push_back(SimpleAVCommandItem(102, "Close", "", 1)); - m_commands.push_back(SimpleAVCommandItem(103, "Closed Caption", "CC", 1)); - m_commands.push_back(SimpleAVCommandItem(104, "Cold", "A/C", 1)); - m_commands.push_back(SimpleAVCommandItem(105, "Color", "", 1)); - m_commands.push_back(SimpleAVCommandItem(106, "Color Down", "", 1)); - m_commands.push_back(SimpleAVCommandItem(107, "Color Up", "", 1)); - m_commands.push_back(SimpleAVCommandItem(108, "Component 1", "RGB 1", 1)); - m_commands.push_back(SimpleAVCommandItem(109, "Component 2", "RGB 2", 1)); - m_commands.push_back(SimpleAVCommandItem(110, "Component 3", "", 1)); - m_commands.push_back(SimpleAVCommandItem(111, "Concert", "", 1)); - m_commands.push_back(SimpleAVCommandItem(112, "Confirm", "Check", 1)); - m_commands.push_back(SimpleAVCommandItem(113, "Continue", "Continuous", 1)); - m_commands.push_back(SimpleAVCommandItem(114, "Contrast", "", 1)); - m_commands.push_back(SimpleAVCommandItem(115, "Contrast Down", "", 1)); - m_commands.push_back(SimpleAVCommandItem(116, "Contrast Up", "", 1)); - m_commands.push_back(SimpleAVCommandItem(117, "Counter", "", 1)); - m_commands.push_back(SimpleAVCommandItem(118, "Counter Reset", "", 1)); - m_commands.push_back(SimpleAVCommandItem(119, "D", "", 1)); - m_commands.push_back(SimpleAVCommandItem(120, "Day Down", "", 1)); - m_commands.push_back(SimpleAVCommandItem(121, "Day Up", "", 1)); - m_commands.push_back(SimpleAVCommandItem(122, "Delay", "", 1)); - m_commands.push_back(SimpleAVCommandItem(123, "Delay Down", "", 1)); - m_commands.push_back(SimpleAVCommandItem(124, "Delay Up", "", 1)); - m_commands.push_back(SimpleAVCommandItem(125, "Delete", "Erase", 1)); - m_commands.push_back(SimpleAVCommandItem(126, "Delimiter", "Sub-Channel", 1)); - m_commands.push_back(SimpleAVCommandItem(127, "Digest", "", 1)); - m_commands.push_back(SimpleAVCommandItem(128, "Digital", "", 1)); - m_commands.push_back(SimpleAVCommandItem(129, "Dim", "Dimmer", 1)); - m_commands.push_back(SimpleAVCommandItem(130, "Direct", "", 1)); - m_commands.push_back(SimpleAVCommandItem(131, "Disarm", "", 1)); - m_commands.push_back(SimpleAVCommandItem(132, "Disc", "", 1)); - m_commands.push_back(SimpleAVCommandItem(133, "Disc 1", "", 1)); - m_commands.push_back(SimpleAVCommandItem(134, "Disc 2", "", 1)); - m_commands.push_back(SimpleAVCommandItem(135, "Disc 3", "", 1)); - m_commands.push_back(SimpleAVCommandItem(136, "Disc 4", "", 1)); - m_commands.push_back(SimpleAVCommandItem(137, "Disc 5", "", 1)); - m_commands.push_back(SimpleAVCommandItem(138, "Disc 6", "", 1)); - m_commands.push_back(SimpleAVCommandItem(139, "Disc Down", "", 1)); - m_commands.push_back(SimpleAVCommandItem(140, "Disc Up", "", 1)); - m_commands.push_back(SimpleAVCommandItem(141, "Disco", "", 1)); - m_commands.push_back(SimpleAVCommandItem(142, "Edit", "", 1)); - m_commands.push_back(SimpleAVCommandItem(143, "Effect Down", "", 1)); - m_commands.push_back(SimpleAVCommandItem(144, "Effect Up", "", 1)); - m_commands.push_back(SimpleAVCommandItem(145, "Eject", "Open/Close", 1)); - m_commands.push_back(SimpleAVCommandItem(146, "End", "", 1)); - m_commands.push_back(SimpleAVCommandItem(147, "EQ", "Equalizer", 1)); - m_commands.push_back(SimpleAVCommandItem(148, "Fader", "", 1)); - m_commands.push_back(SimpleAVCommandItem(149, "Fan", "", 1)); - m_commands.push_back(SimpleAVCommandItem(150, "Fan High", "", 1)); - m_commands.push_back(SimpleAVCommandItem(151, "Fan Low", "", 1)); - m_commands.push_back(SimpleAVCommandItem(152, "Fan Medium", "", 1)); - m_commands.push_back(SimpleAVCommandItem(153, "Fan Speed", "", 1)); - m_commands.push_back(SimpleAVCommandItem(154, "Fastext Blue", "", 1)); - m_commands.push_back(SimpleAVCommandItem(155, "Fastext Green", "", 1)); - m_commands.push_back(SimpleAVCommandItem(156, "Fastext Purple", "", 1)); - m_commands.push_back(SimpleAVCommandItem(157, "Fastext Red", "", 1)); - m_commands.push_back(SimpleAVCommandItem(158, "Fastext White", "", 1)); - m_commands.push_back(SimpleAVCommandItem(159, "Fastext Yellow", "", 1)); - m_commands.push_back(SimpleAVCommandItem(160, "Favorite Channel Down", "", 1)); - m_commands.push_back(SimpleAVCommandItem(161, "Favorite Channel Up", "", 1)); - m_commands.push_back(SimpleAVCommandItem(162, "Finalize", "", 1)); - m_commands.push_back(SimpleAVCommandItem(163, "Fine Tune", "", 1)); - m_commands.push_back(SimpleAVCommandItem(164, "Flat", "", 1)); - m_commands.push_back(SimpleAVCommandItem(165, "FM", "", 1)); - m_commands.push_back(SimpleAVCommandItem(166, "Focus Down", "", 1)); - m_commands.push_back(SimpleAVCommandItem(167, "Focus Up", "", 1)); - m_commands.push_back(SimpleAVCommandItem(168, "Freeze", "", 1)); - m_commands.push_back(SimpleAVCommandItem(169, "Front", "", 1)); - m_commands.push_back(SimpleAVCommandItem(170, "Game", "", 1)); - m_commands.push_back(SimpleAVCommandItem(171, "GoTo", "Index Search", 1)); - m_commands.push_back(SimpleAVCommandItem(172, "Hall", "", 1)); - m_commands.push_back(SimpleAVCommandItem(173, "Heat", "", 1)); - m_commands.push_back(SimpleAVCommandItem(174, "Help", "", 1)); - m_commands.push_back(SimpleAVCommandItem(175, "Home", "", 1)); - m_commands.push_back(SimpleAVCommandItem(176, "Index", "VISS", 1)); - m_commands.push_back(SimpleAVCommandItem(177, "Index Forward", "", 1)); - m_commands.push_back(SimpleAVCommandItem(178, "Index Reverse", "", 1)); - m_commands.push_back(SimpleAVCommandItem(179, "Interactive", "Planner", 1)); - m_commands.push_back(SimpleAVCommandItem(180, "Intro Scan", "", 1)); - m_commands.push_back(SimpleAVCommandItem(181, "Jazz", "", 1)); - m_commands.push_back(SimpleAVCommandItem(182, "Karaoke", "", 1)); - m_commands.push_back(SimpleAVCommandItem(183, "Keystone", "", 1)); - m_commands.push_back(SimpleAVCommandItem(184, "Keystone Down", "", 1)); - m_commands.push_back(SimpleAVCommandItem(185, "Keystone Up", "", 1)); - m_commands.push_back(SimpleAVCommandItem(186, "Language", "SAP", 1)); - m_commands.push_back(SimpleAVCommandItem(187, "Left Click", "", 1)); - m_commands.push_back(SimpleAVCommandItem(188, "Level", "Volume", 1)); - m_commands.push_back(SimpleAVCommandItem(189, "Light", "Lamp", 1)); - m_commands.push_back(SimpleAVCommandItem(190, "List", "My Shows", 1)); - m_commands.push_back(SimpleAVCommandItem(191, "Live TV", "Return to Live", 1)); - m_commands.push_back(SimpleAVCommandItem(192, "Local/Dx", "", 1)); - m_commands.push_back(SimpleAVCommandItem(193, "Loudness", "", 1)); - m_commands.push_back(SimpleAVCommandItem(194, "Mail", "Email", 1)); - m_commands.push_back(SimpleAVCommandItem(195, "Mark", "Bookmark", 1)); - m_commands.push_back(SimpleAVCommandItem(196, "Memory Recall", "", 1)); - m_commands.push_back(SimpleAVCommandItem(197, "Monitor", "Tape Monitor", 1)); - m_commands.push_back(SimpleAVCommandItem(198, "Movie", "", 1)); - m_commands.push_back(SimpleAVCommandItem(199, "Multi Room", "", 1)); - m_commands.push_back(SimpleAVCommandItem(200, "Music", "TV/Radio, My Music (WMC)", 1)); - m_commands.push_back(SimpleAVCommandItem(201, "Music Scan", "Memory Scan", 1)); - m_commands.push_back(SimpleAVCommandItem(202, "Natural", "", 1)); - m_commands.push_back(SimpleAVCommandItem(203, "Night", "", 1)); - m_commands.push_back(SimpleAVCommandItem(204, "Noise Reduction", "Dolby NR", 1)); - m_commands.push_back(SimpleAVCommandItem(205, "Normalize", "Personal Preference", 1)); - m_commands.push_back(SimpleAVCommandItem(206, "Discrete input Cable", "CATV", 1)); - m_commands.push_back(SimpleAVCommandItem(207, "Discrete input CD 1", "CD", 1)); - m_commands.push_back(SimpleAVCommandItem(208, "Discrete input CD 2", "CDR", 1)); - m_commands.push_back(SimpleAVCommandItem(209, "Discrete input CDR", "Compact Disc Recorder", 1)); - m_commands.push_back(SimpleAVCommandItem(210, "Discrete input DAT", "Digital Audio Tape", 1)); - m_commands.push_back(SimpleAVCommandItem(211, "Discrete input DVD", "Digital Video Disk", 1)); - m_commands.push_back(SimpleAVCommandItem(212, "Discrete input DVI", "Digital Video Interface", 1)); - m_commands.push_back(SimpleAVCommandItem(213, "Discrete input HDTV", "", 1)); - m_commands.push_back(SimpleAVCommandItem(214, "Discrete input LD", "Laser Disc", 1)); - m_commands.push_back(SimpleAVCommandItem(215, "Discrete input MD", "Mini Disc", 1)); - m_commands.push_back(SimpleAVCommandItem(216, "Discrete input PC", "Personal Computer", 1)); - m_commands.push_back(SimpleAVCommandItem(217, "Discrete input PVR", "Personal Video Recorder", 1)); - m_commands.push_back(SimpleAVCommandItem(218, "Discrete input TV", "", 1)); - m_commands.push_back(SimpleAVCommandItem(219, "Discrete input TV/VCR", "TV/DVD", 1)); - m_commands.push_back(SimpleAVCommandItem(220, "Discrete input VCR", "", 1)); - m_commands.push_back(SimpleAVCommandItem(221, "One Touch Playback", "OTPB", 1)); - m_commands.push_back(SimpleAVCommandItem(222, "One Touch Record", "OTR", 1)); - m_commands.push_back(SimpleAVCommandItem(223, "Open", "", 1)); - m_commands.push_back(SimpleAVCommandItem(224, "Optical", "", 1)); - m_commands.push_back(SimpleAVCommandItem(225, "Options", "", 1)); - m_commands.push_back(SimpleAVCommandItem(226, "Orchestra", "", 1)); - m_commands.push_back(SimpleAVCommandItem(227, "PAL/NTSC", "System Select", 1)); - m_commands.push_back(SimpleAVCommandItem(228, "Parental Lock", "Parental Control", 1)); - m_commands.push_back(SimpleAVCommandItem(229, "PBC", "Playback Control", 1)); - m_commands.push_back(SimpleAVCommandItem(230, "Phono", "", 1)); - m_commands.push_back(SimpleAVCommandItem(231, "Photos", "Pictures, My Pictures (WMC)", 1)); - m_commands.push_back(SimpleAVCommandItem(232, "Picture Menu", "Picture Adjust", 1)); - m_commands.push_back(SimpleAVCommandItem(233, "Picture Mode", "Smart Picture", 1)); - m_commands.push_back(SimpleAVCommandItem(234, "Picture Mute", "", 1)); - m_commands.push_back(SimpleAVCommandItem(235, "PIP Channel Down", "", 1)); - m_commands.push_back(SimpleAVCommandItem(236, "PIP Channel Up", "", 1)); - m_commands.push_back(SimpleAVCommandItem(237, "PIP Freeze", "", 1)); - m_commands.push_back(SimpleAVCommandItem(238, "PIP Input", "PIP Mode", 1)); - m_commands.push_back(SimpleAVCommandItem(239, "PIP Move", "PIP Position", 1)); - m_commands.push_back(SimpleAVCommandItem(240, "PIP Off", "", 1)); - m_commands.push_back(SimpleAVCommandItem(241, "PIP On", "PIP", 1)); - m_commands.push_back(SimpleAVCommandItem(242, "PIP Size", "", 1)); - m_commands.push_back(SimpleAVCommandItem(243, "PIP Split", "Multi Screen", 1)); - m_commands.push_back(SimpleAVCommandItem(244, "PIP Swap", "PIP Exchange", 1)); - m_commands.push_back(SimpleAVCommandItem(245, "Play Mode", "", 1)); - m_commands.push_back(SimpleAVCommandItem(246, "Play Reverse", "", 1)); - m_commands.push_back(SimpleAVCommandItem(247, "Power Off", "", 1)); - m_commands.push_back(SimpleAVCommandItem(248, "Power On", "", 1)); - m_commands.push_back(SimpleAVCommandItem(249, "PPV", "Pay Per View", 1)); - m_commands.push_back(SimpleAVCommandItem(250, "Preset", "", 1)); - m_commands.push_back(SimpleAVCommandItem(251, "Program", "Program Memory", 1)); - m_commands.push_back(SimpleAVCommandItem(252, "Progressive Scan", "Progressive", 1)); - m_commands.push_back(SimpleAVCommandItem(253, "ProLogic", "Dolby Prologic", 1)); - m_commands.push_back(SimpleAVCommandItem(254, "PTY", "Audio Program Type", 1)); - m_commands.push_back(SimpleAVCommandItem(255, "Quick Skip", "Commercial Skip", 1)); - m_commands.push_back(SimpleAVCommandItem(256, "Random", "Shuffle", 1)); - m_commands.push_back(SimpleAVCommandItem(257, "RDS", "Radio Data System", 1)); - m_commands.push_back(SimpleAVCommandItem(258, "Rear", "", 1)); - m_commands.push_back(SimpleAVCommandItem(259, "Rear Volume Down", "", 1)); - m_commands.push_back(SimpleAVCommandItem(260, "Rear Volume Up", "", 1)); - m_commands.push_back(SimpleAVCommandItem(261, "Record Mute", "", 1)); - m_commands.push_back(SimpleAVCommandItem(262, "Record Pause", "", 1)); - m_commands.push_back(SimpleAVCommandItem(263, "Repeat", "", 1)); - m_commands.push_back(SimpleAVCommandItem(264, "Repeat A-B", "", 1)); - m_commands.push_back(SimpleAVCommandItem(265, "Resume", "", 1)); - m_commands.push_back(SimpleAVCommandItem(266, "RGB", "Red Green Blue Component Video", 1)); - m_commands.push_back(SimpleAVCommandItem(267, "Right Click", "", 1)); - m_commands.push_back(SimpleAVCommandItem(268, "Rock", "", 1)); - m_commands.push_back(SimpleAVCommandItem(269, "Rotate Left", "", 1)); - m_commands.push_back(SimpleAVCommandItem(270, "Rotate Right", "", 1)); - m_commands.push_back(SimpleAVCommandItem(271, "SAT", "Sky", 1)); - m_commands.push_back(SimpleAVCommandItem(272, "Scan", "Channel Scan", 1)); - m_commands.push_back(SimpleAVCommandItem(273, "Scart", "", 1)); - m_commands.push_back(SimpleAVCommandItem(274, "Scene", "", 1)); - m_commands.push_back(SimpleAVCommandItem(275, "Scroll", "", 1)); - m_commands.push_back(SimpleAVCommandItem(276, "Services", "", 1)); - m_commands.push_back(SimpleAVCommandItem(277, "Setup Menu", "Setup", 1)); - m_commands.push_back(SimpleAVCommandItem(278, "Sharp", "", 1)); - m_commands.push_back(SimpleAVCommandItem(279, "Sharpness", "", 1)); - m_commands.push_back(SimpleAVCommandItem(280, "Sharpness Down", "", 1)); - m_commands.push_back(SimpleAVCommandItem(281, "Sharpness Up", "", 1)); - m_commands.push_back(SimpleAVCommandItem(282, "Side A/B", "", 1)); - m_commands.push_back(SimpleAVCommandItem(283, "Skip Forward", "Next", 1)); - m_commands.push_back(SimpleAVCommandItem(284, "Skip Reverse", "Previous", 1)); - m_commands.push_back(SimpleAVCommandItem(285, "Sleep", "Off Timer", 1)); - m_commands.push_back(SimpleAVCommandItem(286, "Slow", "", 1)); - m_commands.push_back(SimpleAVCommandItem(287, "Slow Forward", "", 1)); - m_commands.push_back(SimpleAVCommandItem(288, "Slow Reverse", "", 1)); - m_commands.push_back(SimpleAVCommandItem(289, "Sound Menu", "Audio Menu", 1)); - m_commands.push_back(SimpleAVCommandItem(290, "Sound Mode", "Smart Sound", 1)); - m_commands.push_back(SimpleAVCommandItem(291, "Speed", "Record Speed", 1)); - m_commands.push_back(SimpleAVCommandItem(292, "Speed Down", "", 1)); - m_commands.push_back(SimpleAVCommandItem(293, "Speed Up", "", 1)); - m_commands.push_back(SimpleAVCommandItem(294, "Sports", "Digital Surround Processing", 1)); - m_commands.push_back(SimpleAVCommandItem(295, "Stadium", "", 1)); - m_commands.push_back(SimpleAVCommandItem(296, "Start", "", 1)); - m_commands.push_back(SimpleAVCommandItem(297, "Start ID Erase", "Erase", 1)); - m_commands.push_back(SimpleAVCommandItem(298, "Start ID Renumber", "Renumber", 1)); - m_commands.push_back(SimpleAVCommandItem(299, "Start ID Write", "Write", 1)); - m_commands.push_back(SimpleAVCommandItem(300, "Step", "", 1)); - m_commands.push_back(SimpleAVCommandItem(301, "Stereo/Mono", "L/R", 1)); - m_commands.push_back(SimpleAVCommandItem(302, "Still Forward", "Frame Advance", 1)); - m_commands.push_back(SimpleAVCommandItem(303, "Still Reverse", "Frame Reverse", 1)); - m_commands.push_back(SimpleAVCommandItem(304, "Subtitle", "Subtitle On-Off", 1)); - m_commands.push_back(SimpleAVCommandItem(305, "Subwoofer Down", "", 1)); - m_commands.push_back(SimpleAVCommandItem(306, "Subwoofer Up", "", 1)); - m_commands.push_back(SimpleAVCommandItem(307, "Super Bass", "Bass Boost", 1)); - m_commands.push_back(SimpleAVCommandItem(308, "Surround", "", 1)); - m_commands.push_back(SimpleAVCommandItem(309, "Surround Mode", "Sound Field", 1)); - m_commands.push_back(SimpleAVCommandItem(310, "S-Video", "", 1)); - m_commands.push_back(SimpleAVCommandItem(311, "Sweep", "Oscillate", 1)); - m_commands.push_back(SimpleAVCommandItem(312, "Synchro Record", "CD Synchro", 1)); - m_commands.push_back(SimpleAVCommandItem(313, "Tape 1", "Deck 1", 1)); - m_commands.push_back(SimpleAVCommandItem(314, "Tape 1-2", "Deck 1-2", 1)); - m_commands.push_back(SimpleAVCommandItem(315, "Tape 2", "Deck 2", 1)); - m_commands.push_back(SimpleAVCommandItem(316, "Temperature Down", "", 1)); - m_commands.push_back(SimpleAVCommandItem(317, "Temperature Up", "", 1)); - m_commands.push_back(SimpleAVCommandItem(318, "Test Tone", "", 1)); - m_commands.push_back(SimpleAVCommandItem(319, "Text", "Teletext", 1)); - m_commands.push_back(SimpleAVCommandItem(320, "Text Expand", "", 1)); - m_commands.push_back(SimpleAVCommandItem(321, "Text Hold", "", 1)); - m_commands.push_back(SimpleAVCommandItem(322, "Text Index", "", 1)); - m_commands.push_back(SimpleAVCommandItem(323, "Text Mix", "", 1)); - m_commands.push_back(SimpleAVCommandItem(324, "Text Off", "", 1)); - m_commands.push_back(SimpleAVCommandItem(325, "Text Reveal", "", 1)); - m_commands.push_back(SimpleAVCommandItem(326, "Text Subpage", "", 1)); - m_commands.push_back(SimpleAVCommandItem(327, "Text Timed Page", "", 1)); - m_commands.push_back(SimpleAVCommandItem(328, "Text Update", "Text Cancel", 1)); - m_commands.push_back(SimpleAVCommandItem(329, "Theater", "Cinema EQ", 1)); - m_commands.push_back(SimpleAVCommandItem(330, "Theme", "Category Select", 1)); - m_commands.push_back(SimpleAVCommandItem(331, "Thumbs Down", "", 1)); - m_commands.push_back(SimpleAVCommandItem(332, "Thumbs Up", "", 1)); - m_commands.push_back(SimpleAVCommandItem(333, "Tilt Down", "", 1)); - m_commands.push_back(SimpleAVCommandItem(334, "Tilt Up", "", 1)); - m_commands.push_back(SimpleAVCommandItem(335, "Time", "Clock", 1)); - m_commands.push_back(SimpleAVCommandItem(336, "Timer", "", 1)); - m_commands.push_back(SimpleAVCommandItem(337, "Timer Down", "", 1)); - m_commands.push_back(SimpleAVCommandItem(338, "Timer Up", "", 1)); - m_commands.push_back(SimpleAVCommandItem(339, "Tint", "", 1)); - m_commands.push_back(SimpleAVCommandItem(340, "Tint Down", "", 1)); - m_commands.push_back(SimpleAVCommandItem(341, "Tint Up", "", 1)); - m_commands.push_back(SimpleAVCommandItem(342, "Title", "Top Menu", 1)); - m_commands.push_back(SimpleAVCommandItem(343, "Track", "Chapter", 1)); - m_commands.push_back(SimpleAVCommandItem(344, "Tracking", "", 1)); - m_commands.push_back(SimpleAVCommandItem(345, "Tracking Down", "", 1)); - m_commands.push_back(SimpleAVCommandItem(346, "Tracking Up", "", 1)); - m_commands.push_back(SimpleAVCommandItem(347, "Treble", "", 1)); - m_commands.push_back(SimpleAVCommandItem(348, "Treble Down", "", 1)); - m_commands.push_back(SimpleAVCommandItem(349, "Treble Up", "", 1)); - m_commands.push_back(SimpleAVCommandItem(350, "Tune Down", "Audio Tune Down", 1)); - m_commands.push_back(SimpleAVCommandItem(351, "Tune Up", "Audio Tune Up", 1)); - m_commands.push_back(SimpleAVCommandItem(352, "Tuner", "", 1)); - m_commands.push_back(SimpleAVCommandItem(353, "VCR Plus+", "Showview", 1)); - m_commands.push_back(SimpleAVCommandItem(354, "Video 1", "A/V 1", 1)); - m_commands.push_back(SimpleAVCommandItem(355, "Video 2", "A/V 2", 1)); - m_commands.push_back(SimpleAVCommandItem(356, "Video 3", "A/V 3", 1)); - m_commands.push_back(SimpleAVCommandItem(357, "Video 4", "A/V 4", 1)); - m_commands.push_back(SimpleAVCommandItem(358, "Video 5", "A/V 5", 1)); - m_commands.push_back(SimpleAVCommandItem(359, "View", "", 1)); - m_commands.push_back(SimpleAVCommandItem(360, "Voice", "Vocals", 1)); - m_commands.push_back(SimpleAVCommandItem(361, "Zoom", "Magnify", 1)); - m_commands.push_back(SimpleAVCommandItem(362, "Zoom In", "Zoom Up", 1)); - m_commands.push_back(SimpleAVCommandItem(363, "Zoom Out", "Zoom Down", 1)); - m_commands.push_back(SimpleAVCommandItem(364, "eHome", "(Windows Media Center)", 2)); - m_commands.push_back(SimpleAVCommandItem(365, "Details", "(Windows Media Center)", 2)); - m_commands.push_back(SimpleAVCommandItem(366, "DVD Menu", "(Windows Media Center)", 2)); - m_commands.push_back(SimpleAVCommandItem(367, "My TV", "(Windows Media Center)", 2)); - m_commands.push_back(SimpleAVCommandItem(368, "Recorded TV", "(Windows Media Center)", 2)); - m_commands.push_back(SimpleAVCommandItem(369, "My Videos", "(Windows Media Center)", 2)); - m_commands.push_back(SimpleAVCommandItem(370, "DVD Angle", "(Windows Media Center)", 2)); - m_commands.push_back(SimpleAVCommandItem(371, "DVD Audio", "(Windows Media Center)", 2)); - m_commands.push_back(SimpleAVCommandItem(372, "DVD Subtitle", "(Windows Media Center)", 2)); - m_commands.push_back(SimpleAVCommandItem(373, "Radio", "(Windows Media Center)", 2)); - m_commands.push_back(SimpleAVCommandItem(374, "#", "(Windows Media Center)", 2)); - m_commands.push_back(SimpleAVCommandItem(375, "*", "(Windows Media Center)", 2)); - m_commands.push_back(SimpleAVCommandItem(376, "OEM 1", "(Windows Media Center)", 2)); - m_commands.push_back(SimpleAVCommandItem(377, "OEM 2", "(Windows Media Center)", 2)); - m_commands.push_back(SimpleAVCommandItem(378, "Info", "Used to request information", 3)); - m_commands.push_back(SimpleAVCommandItem(379, "CAPS NUM", "Switch between numeric and alpha (Shift)", 3)); - m_commands.push_back(SimpleAVCommandItem(380, "TV MODE", "Cycles through video output modes/resolutions", 3)); - m_commands.push_back(SimpleAVCommandItem(381, "SOURCE", "Displays the possible sources for the playback. [NFS, ext., USB, UPnP]", 3)); - m_commands.push_back(SimpleAVCommandItem(382, "FILEMODE", "File manipulation. Add/remove to list, create folder, rename file", 3)); - m_commands.push_back(SimpleAVCommandItem(383, "Time Seek", "This seeks to time position. Used for DVD/CD/others", 3)); - m_commands.push_back(SimpleAVCommandItem(384, "Mouse enable", "Mouse pointer enable", 4)); - m_commands.push_back(SimpleAVCommandItem(385, "Mouse disable", "Mouse pointer disable", 4)); - m_commands.push_back(SimpleAVCommandItem(386, "VOD", "Video on demand", 4)); - m_commands.push_back(SimpleAVCommandItem(387, "Thumbs Up", "Thumbs up for positive feedback in GUI", 4)); - m_commands.push_back(SimpleAVCommandItem(388, "Thumbs Down", "Thumbs down for negative feedback in GUI", 4)); - m_commands.push_back(SimpleAVCommandItem(389, "Apps", "Application selection/launch", 4)); - m_commands.push_back(SimpleAVCommandItem(390, "Mouse toggle", "Will toggle a mouse pointer between on and off", 4)); - m_commands.push_back(SimpleAVCommandItem(391, "TV Mode", "Will direct an AV device to go the TV mode (the mode is configured on the device)", 4)); - m_commands.push_back(SimpleAVCommandItem(392, "DVD Mode", "Will direct an AV device to go the DVD mode (the mode is configured on the device)", 4)); - m_commands.push_back(SimpleAVCommandItem(393, "STB Mode", "Will direct an AV device to go the STB mode (the mode is configured on the device)", 4)); - m_commands.push_back(SimpleAVCommandItem(394, "AUX Mode", "Will direct an AV device to go the AUX mode (the mode is configured on the device)", 4)); - m_commands.push_back(SimpleAVCommandItem(395, "BluRay Mode", "Will direct an AV device to go the BluRay mode (the mode is configured on the device)", 4)); - m_commands.push_back(SimpleAVCommandItem(404, "Standby 1", "Used for AV devices that support multiple standby mode. Power ON should be used to turn on the device", 4)); - m_commands.push_back(SimpleAVCommandItem(405, "Standby 2", "Used for AV devices that support multiple standby mode. Power ON should be used to turn on the device", 4)); - m_commands.push_back(SimpleAVCommandItem(406, "Standby 3", "Used for AV devices that support multiple standby mode. Power ON should be used to turn on the device", 4)); - m_commands.push_back(SimpleAVCommandItem(407, "HDMI 1", "Discrete command used to set an AV device to HDMI input 1", 4)); - m_commands.push_back(SimpleAVCommandItem(408, "HDMI 2", "Discrete command used to set an AV device to HDMI input 2", 4)); - m_commands.push_back(SimpleAVCommandItem(409, "HDMI 3", "Discrete command used to set an AV device to HDMI input 3", 4)); - m_commands.push_back(SimpleAVCommandItem(410, "HDMI 4", "Discrete command used to set an AV device to HDMI input 4", 4)); - m_commands.push_back(SimpleAVCommandItem(411, "HDMI 5", "Discrete command used to set an AV device to HDMI input 5", 4)); - m_commands.push_back(SimpleAVCommandItem(412, "HDMI 6", "Discrete command used to set an AV device to HDMI input 6", 4)); - m_commands.push_back(SimpleAVCommandItem(413, "HDMI 7", "Discrete command used to set an AV device to HDMI input 7", 4)); - m_commands.push_back(SimpleAVCommandItem(414, "HDMI 8", "Discrete command used to set an AV device to HDMI input 8", 4)); - m_commands.push_back(SimpleAVCommandItem(415, "HDMI 9", "Discrete command used to set an AV device to HDMI input 9", 4)); - m_commands.push_back(SimpleAVCommandItem(416, "USB 1", "Discrete command used to set an AV device to USB input 1", 4)); - m_commands.push_back(SimpleAVCommandItem(417, "USB 2", "Discrete command used to set an AV device to USB input 2", 4)); - m_commands.push_back(SimpleAVCommandItem(418, "USB 3", "Discrete command used to set an AV device to USB input 3", 4)); - m_commands.push_back(SimpleAVCommandItem(419, "USB 4", "Discrete command used to set an AV device to USB input 4", 4)); - m_commands.push_back(SimpleAVCommandItem(420, "USB 5", "Discrete command used to set an AV device to USB input 5", 4)); - m_commands.push_back(SimpleAVCommandItem(421, "ZOOM - 4:3 Normal", "Discrete commands that is used to set a TV a direct Zoom mode", 4)); - m_commands.push_back(SimpleAVCommandItem(422, "ZOOM - 4:3 Zoom", "Discrete commands that is used to set a TV a direct Zoom mode", 4)); - m_commands.push_back(SimpleAVCommandItem(423, "ZOOM - 16:9 Normal", "Discrete commands that is used to set a TV a direct Zoom mode", 4)); - m_commands.push_back(SimpleAVCommandItem(424, "ZOOM - 16:9 Zoom", "Discrete commands that is used to set a TV a direct Zoom mode", 4)); - m_commands.push_back(SimpleAVCommandItem(425, "ZOOM - 16:9 Wide 1", "Discrete commands that is used to set a TV a direct Zoom mode", 4)); - m_commands.push_back(SimpleAVCommandItem(426, "ZOOM 16:9 Wide 2", "Discrete commands that is used to set a TV a direct Zoom mode", 4)); - m_commands.push_back(SimpleAVCommandItem(427, "ZOOM 16:9 Wide 3", "Discrete commands that is used to set a TV a direct Zoom mode", 4)); - m_commands.push_back(SimpleAVCommandItem(428, "ZOOM 16:9 Cinema", "Discrete commands that is used to set a TV a direct Zoom mode", 4)); - m_commands.push_back(SimpleAVCommandItem(429, "ZOOM Default", "Discrete commands that is used to set a TV the default Zoom mode", 4)); - m_commands.push_back(SimpleAVCommandItem(432, "Auto Zoom", "Will set Zoom mode automatically", 4)); - m_commands.push_back(SimpleAVCommandItem(433, "ZOOM - Set as Default Zoom", "Will set the current active Zoom level to default", 4)); - m_commands.push_back(SimpleAVCommandItem(434, "Mute ON", "Discrete Mute ON command", 4)); - m_commands.push_back(SimpleAVCommandItem(435, "Mute OFF", "Discrete Mute OFF command", 4)); - m_commands.push_back(SimpleAVCommandItem(436, "AUDIO Mode - AUDYSSEY AUDIO OFF", "Discrete Audio mode for Audussey audio processing (Off) ", 4)); - m_commands.push_back(SimpleAVCommandItem(437, "AUDIO Mode - AUDYSSEY AUDIO LO", "Discrete Audio mode for Audussey audio processing (Low) ", 4)); - m_commands.push_back(SimpleAVCommandItem(438, "AUDIO Mode - AUDYSSEY AUDIO MED", "Discrete Audio mode for Audussey audio processing (Medium) ", 4)); - m_commands.push_back(SimpleAVCommandItem(439, "AUDIO Mode - AUDYSSEY AUDIO HI", "Discrete Audio mode for Audussey audio processing (High) ", 4)); - m_commands.push_back(SimpleAVCommandItem(442, "AUDIO Mode - SRS SURROUND ON", "Discrete Audio mode for SRS audio processing", 4)); - m_commands.push_back(SimpleAVCommandItem(443, "AUDIO Mode - SRS SURROUND OFF", "Discrete Audio mode for SRS audio processing", 4)); - m_commands.push_back(SimpleAVCommandItem(447, "Picture Mode - Home", "Discrete picture for TVs", 4)); - m_commands.push_back(SimpleAVCommandItem(448, "Picture Mode - Retail", "Discrete picture for TVs", 4)); - m_commands.push_back(SimpleAVCommandItem(449, "Picture Mode - Vivid", "Discrete picture for TVs", 4)); - m_commands.push_back(SimpleAVCommandItem(450, "Picture Mode - Standard", "Discrete picture for TVs", 4)); - m_commands.push_back(SimpleAVCommandItem(451, "Picture Mode - Theater", "Discrete picture for TVs", 4)); - m_commands.push_back(SimpleAVCommandItem(452, "Picture Mode - Sports", "Discrete picture for TVs", 4)); - m_commands.push_back(SimpleAVCommandItem(453, "Picture Mode - Energy savings ", "Discrete picture for TVs", 4)); - m_commands.push_back(SimpleAVCommandItem(454, "Picture Mode - Custom", "Discrete picture for TVs", 4)); - m_commands.push_back(SimpleAVCommandItem(455, "Cool", "Discrete picture temperature adjustments", 4)); - m_commands.push_back(SimpleAVCommandItem(456, "Medium", "Discrete picture temperature adjustments", 4)); - m_commands.push_back(SimpleAVCommandItem(457, "Warm_D65", "Discrete picture temperature adjustments", 4)); - m_commands.push_back(SimpleAVCommandItem(458, "CC ON", "Discrete Closed caption commands", 4)); - m_commands.push_back(SimpleAVCommandItem(459, "CC OFF", "Discrete Closed caption commands", 4)); - m_commands.push_back(SimpleAVCommandItem(460, "Video Mute ON", "Discrete Video mute command", 4)); - m_commands.push_back(SimpleAVCommandItem(461, "Video Mute OFF", "Discrete Video mute command", 4)); - m_commands.push_back(SimpleAVCommandItem(462, "Next Event", "Go to next state or event ", 4)); - m_commands.push_back(SimpleAVCommandItem(463, "Previous Event", "Go to previous state or event", 4)); - m_commands.push_back(SimpleAVCommandItem(464, "CEC device list", "Brings up the CES device list", 4)); - m_commands.push_back(SimpleAVCommandItem(465, "MTS SAP", "Secondary Audio programming", 4)); - } - return m_commands; -} \ No newline at end of file + std::vector SimpleAVCommandItem::GetCommands() + { + if (m_commands.size() == 0) + { + // Generated code + m_commands.push_back(SimpleAVCommandItem(1, "Mute", "", 1)); + m_commands.push_back(SimpleAVCommandItem(2, "Volume Down", "Level Down", 1)); + m_commands.push_back(SimpleAVCommandItem(3, "Volume Up", "Level Up", 1)); + m_commands.push_back(SimpleAVCommandItem(4, "Channel Up", "Program Up", 1)); + m_commands.push_back(SimpleAVCommandItem(5, "Channel Down", "Program Down", 1)); + m_commands.push_back(SimpleAVCommandItem(6, "0", "Preset 10", 1)); + m_commands.push_back(SimpleAVCommandItem(7, "1", "Preset 1", 1)); + m_commands.push_back(SimpleAVCommandItem(8, "2", "Preset 2", 1)); + m_commands.push_back(SimpleAVCommandItem(9, "3", "Preset 3", 1)); + m_commands.push_back(SimpleAVCommandItem(10, "4", "Preset 4", 1)); + m_commands.push_back(SimpleAVCommandItem(11, "5", "Preset 5", 1)); + m_commands.push_back(SimpleAVCommandItem(12, "6", "Preset 6", 1)); + m_commands.push_back(SimpleAVCommandItem(13, "7", "Preset 7", 1)); + m_commands.push_back(SimpleAVCommandItem(14, "8", "Preset 8", 1)); + m_commands.push_back(SimpleAVCommandItem(15, "9", "Preset 9", 1)); + m_commands.push_back(SimpleAVCommandItem(16, "Last Channel", "Recall, Previous Channel (WMC)", 1)); + m_commands.push_back(SimpleAVCommandItem(17, "Display", "Info", 1)); + m_commands.push_back(SimpleAVCommandItem(18, "Favorite Channel", "Favorite", 1)); + m_commands.push_back(SimpleAVCommandItem(19, "Play", "", 1)); + m_commands.push_back(SimpleAVCommandItem(20, "Stop", "", 1)); + m_commands.push_back(SimpleAVCommandItem(21, "Pause", "Still", 1)); + m_commands.push_back(SimpleAVCommandItem(22, "Fast Forward", "Search Forward", 1)); + m_commands.push_back(SimpleAVCommandItem(23, "Rewind", "Search Reverse", 1)); + m_commands.push_back(SimpleAVCommandItem(24, "Instant Replay", "Replay", 1)); + m_commands.push_back(SimpleAVCommandItem(25, "Record", "", 1)); + m_commands.push_back(SimpleAVCommandItem(26, "AC3", "Dolby Digital", 1)); + m_commands.push_back(SimpleAVCommandItem(27, "PVR Menu", "Tivo", 1)); + m_commands.push_back(SimpleAVCommandItem(28, "Guide", "EPG", 1)); + m_commands.push_back(SimpleAVCommandItem(29, "Menu", "Settings", 1)); + m_commands.push_back(SimpleAVCommandItem(30, "Menu Up", "Adjust Up", 1)); + m_commands.push_back(SimpleAVCommandItem(31, "Menu Down", "Adjust Down", 1)); + m_commands.push_back(SimpleAVCommandItem(32, "Menu Left", "Cursor Left", 1)); + m_commands.push_back(SimpleAVCommandItem(33, "Menu Right", "Cursor Right", 1)); + m_commands.push_back(SimpleAVCommandItem(34, "Page Up", "", 1)); + m_commands.push_back(SimpleAVCommandItem(35, "Page Down", "", 1)); + m_commands.push_back(SimpleAVCommandItem(36, "Select", "OK", 1)); + m_commands.push_back(SimpleAVCommandItem(37, "Exit", "", 1)); + m_commands.push_back(SimpleAVCommandItem(38, "Input", "Input Select", 1)); + m_commands.push_back(SimpleAVCommandItem(39, "Power", "Standby", 1)); + m_commands.push_back(SimpleAVCommandItem(40, "Enter Channel", "Channel Enter", 1)); + m_commands.push_back(SimpleAVCommandItem(41, "10", "", 1)); + m_commands.push_back(SimpleAVCommandItem(42, "11", "", 1)); + m_commands.push_back(SimpleAVCommandItem(43, "12", "", 1)); + m_commands.push_back(SimpleAVCommandItem(44, "13", "", 1)); + m_commands.push_back(SimpleAVCommandItem(45, "14", "", 1)); + m_commands.push_back(SimpleAVCommandItem(46, "15", "", 1)); + m_commands.push_back(SimpleAVCommandItem(47, "16", "", 1)); + m_commands.push_back(SimpleAVCommandItem(48, "10", "10+", 1)); + m_commands.push_back(SimpleAVCommandItem(49, "20", "20+", 1)); + m_commands.push_back(SimpleAVCommandItem(50, "100", "", 1)); + m_commands.push_back(SimpleAVCommandItem(51, "-/--", "", 1)); + m_commands.push_back(SimpleAVCommandItem(52, "3-CH", "", 1)); + m_commands.push_back(SimpleAVCommandItem(53, "3D", "Simulated Stereo", 1)); + m_commands.push_back(SimpleAVCommandItem(54, "6-CH Input", "6 Channel", 1)); + m_commands.push_back(SimpleAVCommandItem(55, "A", "", 1)); + m_commands.push_back(SimpleAVCommandItem(56, "Add", "Write", 1)); + m_commands.push_back(SimpleAVCommandItem(57, "Alarm", "", 1)); + m_commands.push_back(SimpleAVCommandItem(58, "AM", "", 1)); + m_commands.push_back(SimpleAVCommandItem(59, "Analog", "", 1)); + m_commands.push_back(SimpleAVCommandItem(60, "Angle", "", 1)); + m_commands.push_back(SimpleAVCommandItem(61, "Antenna", "External", 1)); + m_commands.push_back(SimpleAVCommandItem(62, "Antenna East", "", 1)); + m_commands.push_back(SimpleAVCommandItem(63, "Antenna West", "", 1)); + m_commands.push_back(SimpleAVCommandItem(64, "Aspect", "Size", 1)); + m_commands.push_back(SimpleAVCommandItem(65, "Audio 1", "Audio", 1)); + m_commands.push_back(SimpleAVCommandItem(66, "Audio 2", "", 1)); + m_commands.push_back(SimpleAVCommandItem(67, "Audio 3", "", 1)); + m_commands.push_back(SimpleAVCommandItem(68, "Audio Dubbing", "", 1)); + m_commands.push_back(SimpleAVCommandItem(69, "Audio Level Down", "", 1)); + m_commands.push_back(SimpleAVCommandItem(70, "Audio Level Up", "", 1)); + m_commands.push_back(SimpleAVCommandItem(71, "Auto/Manual", "", 1)); + m_commands.push_back(SimpleAVCommandItem(72, "Aux 1", "Aux", 1)); + m_commands.push_back(SimpleAVCommandItem(73, "Aux 2", "", 1)); + m_commands.push_back(SimpleAVCommandItem(74, "B", "", 1)); + m_commands.push_back(SimpleAVCommandItem(75, "Back", "Previous Screen", 1)); + m_commands.push_back(SimpleAVCommandItem(76, "Background", "Backlight", 1)); + m_commands.push_back(SimpleAVCommandItem(77, "Balance", "", 1)); + m_commands.push_back(SimpleAVCommandItem(78, "Balance Left", "", 1)); + m_commands.push_back(SimpleAVCommandItem(79, "Balance Right", "", 1)); + m_commands.push_back(SimpleAVCommandItem(80, "Band", "FM/AM", 1)); + m_commands.push_back(SimpleAVCommandItem(81, "Bandwidth", "Wide/Narrow", 1)); + m_commands.push_back(SimpleAVCommandItem(82, "Bass", "", 1)); + m_commands.push_back(SimpleAVCommandItem(83, "Bass Down", "", 1)); + m_commands.push_back(SimpleAVCommandItem(84, "Bass Up", "", 1)); + m_commands.push_back(SimpleAVCommandItem(85, "Blank", "", 1)); + m_commands.push_back(SimpleAVCommandItem(86, "Breeze Mode", "", 1)); + m_commands.push_back(SimpleAVCommandItem(87, "Bright", "Brighten", 1)); + m_commands.push_back(SimpleAVCommandItem(88, "Brightness", "", 1)); + m_commands.push_back(SimpleAVCommandItem(89, "Brightness Down", "", 1)); + m_commands.push_back(SimpleAVCommandItem(90, "Brightness Up", "", 1)); + m_commands.push_back(SimpleAVCommandItem(91, "Buy", "", 1)); + m_commands.push_back(SimpleAVCommandItem(92, "C", "", 1)); + m_commands.push_back(SimpleAVCommandItem(93, "Camera", "", 1)); + m_commands.push_back(SimpleAVCommandItem(94, "Category Down", "", 1)); + m_commands.push_back(SimpleAVCommandItem(95, "Category Up", "", 1)); + m_commands.push_back(SimpleAVCommandItem(96, "Center", "", 1)); + m_commands.push_back(SimpleAVCommandItem(97, "Center Down", "Center Volume Down", 1)); + m_commands.push_back(SimpleAVCommandItem(98, "Center Mode", "", 1)); + m_commands.push_back(SimpleAVCommandItem(99, "Center Up", "Center Volume Up", 1)); + m_commands.push_back(SimpleAVCommandItem(100, "Channel/Program", "C/P", 1)); + m_commands.push_back(SimpleAVCommandItem(101, "Clear", "Cancel", 1)); + m_commands.push_back(SimpleAVCommandItem(102, "Close", "", 1)); + m_commands.push_back(SimpleAVCommandItem(103, "Closed Caption", "CC", 1)); + m_commands.push_back(SimpleAVCommandItem(104, "Cold", "A/C", 1)); + m_commands.push_back(SimpleAVCommandItem(105, "Color", "", 1)); + m_commands.push_back(SimpleAVCommandItem(106, "Color Down", "", 1)); + m_commands.push_back(SimpleAVCommandItem(107, "Color Up", "", 1)); + m_commands.push_back(SimpleAVCommandItem(108, "Component 1", "RGB 1", 1)); + m_commands.push_back(SimpleAVCommandItem(109, "Component 2", "RGB 2", 1)); + m_commands.push_back(SimpleAVCommandItem(110, "Component 3", "", 1)); + m_commands.push_back(SimpleAVCommandItem(111, "Concert", "", 1)); + m_commands.push_back(SimpleAVCommandItem(112, "Confirm", "Check", 1)); + m_commands.push_back(SimpleAVCommandItem(113, "Continue", "Continuous", 1)); + m_commands.push_back(SimpleAVCommandItem(114, "Contrast", "", 1)); + m_commands.push_back(SimpleAVCommandItem(115, "Contrast Down", "", 1)); + m_commands.push_back(SimpleAVCommandItem(116, "Contrast Up", "", 1)); + m_commands.push_back(SimpleAVCommandItem(117, "Counter", "", 1)); + m_commands.push_back(SimpleAVCommandItem(118, "Counter Reset", "", 1)); + m_commands.push_back(SimpleAVCommandItem(119, "D", "", 1)); + m_commands.push_back(SimpleAVCommandItem(120, "Day Down", "", 1)); + m_commands.push_back(SimpleAVCommandItem(121, "Day Up", "", 1)); + m_commands.push_back(SimpleAVCommandItem(122, "Delay", "", 1)); + m_commands.push_back(SimpleAVCommandItem(123, "Delay Down", "", 1)); + m_commands.push_back(SimpleAVCommandItem(124, "Delay Up", "", 1)); + m_commands.push_back(SimpleAVCommandItem(125, "Delete", "Erase", 1)); + m_commands.push_back(SimpleAVCommandItem(126, "Delimiter", "Sub-Channel", 1)); + m_commands.push_back(SimpleAVCommandItem(127, "Digest", "", 1)); + m_commands.push_back(SimpleAVCommandItem(128, "Digital", "", 1)); + m_commands.push_back(SimpleAVCommandItem(129, "Dim", "Dimmer", 1)); + m_commands.push_back(SimpleAVCommandItem(130, "Direct", "", 1)); + m_commands.push_back(SimpleAVCommandItem(131, "Disarm", "", 1)); + m_commands.push_back(SimpleAVCommandItem(132, "Disc", "", 1)); + m_commands.push_back(SimpleAVCommandItem(133, "Disc 1", "", 1)); + m_commands.push_back(SimpleAVCommandItem(134, "Disc 2", "", 1)); + m_commands.push_back(SimpleAVCommandItem(135, "Disc 3", "", 1)); + m_commands.push_back(SimpleAVCommandItem(136, "Disc 4", "", 1)); + m_commands.push_back(SimpleAVCommandItem(137, "Disc 5", "", 1)); + m_commands.push_back(SimpleAVCommandItem(138, "Disc 6", "", 1)); + m_commands.push_back(SimpleAVCommandItem(139, "Disc Down", "", 1)); + m_commands.push_back(SimpleAVCommandItem(140, "Disc Up", "", 1)); + m_commands.push_back(SimpleAVCommandItem(141, "Disco", "", 1)); + m_commands.push_back(SimpleAVCommandItem(142, "Edit", "", 1)); + m_commands.push_back(SimpleAVCommandItem(143, "Effect Down", "", 1)); + m_commands.push_back(SimpleAVCommandItem(144, "Effect Up", "", 1)); + m_commands.push_back(SimpleAVCommandItem(145, "Eject", "Open/Close", 1)); + m_commands.push_back(SimpleAVCommandItem(146, "End", "", 1)); + m_commands.push_back(SimpleAVCommandItem(147, "EQ", "Equalizer", 1)); + m_commands.push_back(SimpleAVCommandItem(148, "Fader", "", 1)); + m_commands.push_back(SimpleAVCommandItem(149, "Fan", "", 1)); + m_commands.push_back(SimpleAVCommandItem(150, "Fan High", "", 1)); + m_commands.push_back(SimpleAVCommandItem(151, "Fan Low", "", 1)); + m_commands.push_back(SimpleAVCommandItem(152, "Fan Medium", "", 1)); + m_commands.push_back(SimpleAVCommandItem(153, "Fan Speed", "", 1)); + m_commands.push_back(SimpleAVCommandItem(154, "Fastext Blue", "", 1)); + m_commands.push_back(SimpleAVCommandItem(155, "Fastext Green", "", 1)); + m_commands.push_back(SimpleAVCommandItem(156, "Fastext Purple", "", 1)); + m_commands.push_back(SimpleAVCommandItem(157, "Fastext Red", "", 1)); + m_commands.push_back(SimpleAVCommandItem(158, "Fastext White", "", 1)); + m_commands.push_back(SimpleAVCommandItem(159, "Fastext Yellow", "", 1)); + m_commands.push_back(SimpleAVCommandItem(160, "Favorite Channel Down", "", 1)); + m_commands.push_back(SimpleAVCommandItem(161, "Favorite Channel Up", "", 1)); + m_commands.push_back(SimpleAVCommandItem(162, "Finalize", "", 1)); + m_commands.push_back(SimpleAVCommandItem(163, "Fine Tune", "", 1)); + m_commands.push_back(SimpleAVCommandItem(164, "Flat", "", 1)); + m_commands.push_back(SimpleAVCommandItem(165, "FM", "", 1)); + m_commands.push_back(SimpleAVCommandItem(166, "Focus Down", "", 1)); + m_commands.push_back(SimpleAVCommandItem(167, "Focus Up", "", 1)); + m_commands.push_back(SimpleAVCommandItem(168, "Freeze", "", 1)); + m_commands.push_back(SimpleAVCommandItem(169, "Front", "", 1)); + m_commands.push_back(SimpleAVCommandItem(170, "Game", "", 1)); + m_commands.push_back(SimpleAVCommandItem(171, "GoTo", "Index Search", 1)); + m_commands.push_back(SimpleAVCommandItem(172, "Hall", "", 1)); + m_commands.push_back(SimpleAVCommandItem(173, "Heat", "", 1)); + m_commands.push_back(SimpleAVCommandItem(174, "Help", "", 1)); + m_commands.push_back(SimpleAVCommandItem(175, "Home", "", 1)); + m_commands.push_back(SimpleAVCommandItem(176, "Index", "VISS", 1)); + m_commands.push_back(SimpleAVCommandItem(177, "Index Forward", "", 1)); + m_commands.push_back(SimpleAVCommandItem(178, "Index Reverse", "", 1)); + m_commands.push_back(SimpleAVCommandItem(179, "Interactive", "Planner", 1)); + m_commands.push_back(SimpleAVCommandItem(180, "Intro Scan", "", 1)); + m_commands.push_back(SimpleAVCommandItem(181, "Jazz", "", 1)); + m_commands.push_back(SimpleAVCommandItem(182, "Karaoke", "", 1)); + m_commands.push_back(SimpleAVCommandItem(183, "Keystone", "", 1)); + m_commands.push_back(SimpleAVCommandItem(184, "Keystone Down", "", 1)); + m_commands.push_back(SimpleAVCommandItem(185, "Keystone Up", "", 1)); + m_commands.push_back(SimpleAVCommandItem(186, "Language", "SAP", 1)); + m_commands.push_back(SimpleAVCommandItem(187, "Left Click", "", 1)); + m_commands.push_back(SimpleAVCommandItem(188, "Level", "Volume", 1)); + m_commands.push_back(SimpleAVCommandItem(189, "Light", "Lamp", 1)); + m_commands.push_back(SimpleAVCommandItem(190, "List", "My Shows", 1)); + m_commands.push_back(SimpleAVCommandItem(191, "Live TV", "Return to Live", 1)); + m_commands.push_back(SimpleAVCommandItem(192, "Local/Dx", "", 1)); + m_commands.push_back(SimpleAVCommandItem(193, "Loudness", "", 1)); + m_commands.push_back(SimpleAVCommandItem(194, "Mail", "Email", 1)); + m_commands.push_back(SimpleAVCommandItem(195, "Mark", "Bookmark", 1)); + m_commands.push_back(SimpleAVCommandItem(196, "Memory Recall", "", 1)); + m_commands.push_back(SimpleAVCommandItem(197, "Monitor", "Tape Monitor", 1)); + m_commands.push_back(SimpleAVCommandItem(198, "Movie", "", 1)); + m_commands.push_back(SimpleAVCommandItem(199, "Multi Room", "", 1)); + m_commands.push_back(SimpleAVCommandItem(200, "Music", "TV/Radio, My Music (WMC)", 1)); + m_commands.push_back(SimpleAVCommandItem(201, "Music Scan", "Memory Scan", 1)); + m_commands.push_back(SimpleAVCommandItem(202, "Natural", "", 1)); + m_commands.push_back(SimpleAVCommandItem(203, "Night", "", 1)); + m_commands.push_back(SimpleAVCommandItem(204, "Noise Reduction", "Dolby NR", 1)); + m_commands.push_back(SimpleAVCommandItem(205, "Normalize", "Personal Preference", 1)); + m_commands.push_back(SimpleAVCommandItem(206, "Discrete input Cable", "CATV", 1)); + m_commands.push_back(SimpleAVCommandItem(207, "Discrete input CD 1", "CD", 1)); + m_commands.push_back(SimpleAVCommandItem(208, "Discrete input CD 2", "CDR", 1)); + m_commands.push_back(SimpleAVCommandItem(209, "Discrete input CDR", "Compact Disc Recorder", 1)); + m_commands.push_back(SimpleAVCommandItem(210, "Discrete input DAT", "Digital Audio Tape", 1)); + m_commands.push_back(SimpleAVCommandItem(211, "Discrete input DVD", "Digital Video Disk", 1)); + m_commands.push_back(SimpleAVCommandItem(212, "Discrete input DVI", "Digital Video Interface", 1)); + m_commands.push_back(SimpleAVCommandItem(213, "Discrete input HDTV", "", 1)); + m_commands.push_back(SimpleAVCommandItem(214, "Discrete input LD", "Laser Disc", 1)); + m_commands.push_back(SimpleAVCommandItem(215, "Discrete input MD", "Mini Disc", 1)); + m_commands.push_back(SimpleAVCommandItem(216, "Discrete input PC", "Personal Computer", 1)); + m_commands.push_back(SimpleAVCommandItem(217, "Discrete input PVR", "Personal Video Recorder", 1)); + m_commands.push_back(SimpleAVCommandItem(218, "Discrete input TV", "", 1)); + m_commands.push_back(SimpleAVCommandItem(219, "Discrete input TV/VCR", "TV/DVD", 1)); + m_commands.push_back(SimpleAVCommandItem(220, "Discrete input VCR", "", 1)); + m_commands.push_back(SimpleAVCommandItem(221, "One Touch Playback", "OTPB", 1)); + m_commands.push_back(SimpleAVCommandItem(222, "One Touch Record", "OTR", 1)); + m_commands.push_back(SimpleAVCommandItem(223, "Open", "", 1)); + m_commands.push_back(SimpleAVCommandItem(224, "Optical", "", 1)); + m_commands.push_back(SimpleAVCommandItem(225, "Options", "", 1)); + m_commands.push_back(SimpleAVCommandItem(226, "Orchestra", "", 1)); + m_commands.push_back(SimpleAVCommandItem(227, "PAL/NTSC", "System Select", 1)); + m_commands.push_back(SimpleAVCommandItem(228, "Parental Lock", "Parental Control", 1)); + m_commands.push_back(SimpleAVCommandItem(229, "PBC", "Playback Control", 1)); + m_commands.push_back(SimpleAVCommandItem(230, "Phono", "", 1)); + m_commands.push_back(SimpleAVCommandItem(231, "Photos", "Pictures, My Pictures (WMC)", 1)); + m_commands.push_back(SimpleAVCommandItem(232, "Picture Menu", "Picture Adjust", 1)); + m_commands.push_back(SimpleAVCommandItem(233, "Picture Mode", "Smart Picture", 1)); + m_commands.push_back(SimpleAVCommandItem(234, "Picture Mute", "", 1)); + m_commands.push_back(SimpleAVCommandItem(235, "PIP Channel Down", "", 1)); + m_commands.push_back(SimpleAVCommandItem(236, "PIP Channel Up", "", 1)); + m_commands.push_back(SimpleAVCommandItem(237, "PIP Freeze", "", 1)); + m_commands.push_back(SimpleAVCommandItem(238, "PIP Input", "PIP Mode", 1)); + m_commands.push_back(SimpleAVCommandItem(239, "PIP Move", "PIP Position", 1)); + m_commands.push_back(SimpleAVCommandItem(240, "PIP Off", "", 1)); + m_commands.push_back(SimpleAVCommandItem(241, "PIP On", "PIP", 1)); + m_commands.push_back(SimpleAVCommandItem(242, "PIP Size", "", 1)); + m_commands.push_back(SimpleAVCommandItem(243, "PIP Split", "Multi Screen", 1)); + m_commands.push_back(SimpleAVCommandItem(244, "PIP Swap", "PIP Exchange", 1)); + m_commands.push_back(SimpleAVCommandItem(245, "Play Mode", "", 1)); + m_commands.push_back(SimpleAVCommandItem(246, "Play Reverse", "", 1)); + m_commands.push_back(SimpleAVCommandItem(247, "Power Off", "", 1)); + m_commands.push_back(SimpleAVCommandItem(248, "Power On", "", 1)); + m_commands.push_back(SimpleAVCommandItem(249, "PPV", "Pay Per View", 1)); + m_commands.push_back(SimpleAVCommandItem(250, "Preset", "", 1)); + m_commands.push_back(SimpleAVCommandItem(251, "Program", "Program Memory", 1)); + m_commands.push_back(SimpleAVCommandItem(252, "Progressive Scan", "Progressive", 1)); + m_commands.push_back(SimpleAVCommandItem(253, "ProLogic", "Dolby Prologic", 1)); + m_commands.push_back(SimpleAVCommandItem(254, "PTY", "Audio Program Type", 1)); + m_commands.push_back(SimpleAVCommandItem(255, "Quick Skip", "Commercial Skip", 1)); + m_commands.push_back(SimpleAVCommandItem(256, "Random", "Shuffle", 1)); + m_commands.push_back(SimpleAVCommandItem(257, "RDS", "Radio Data System", 1)); + m_commands.push_back(SimpleAVCommandItem(258, "Rear", "", 1)); + m_commands.push_back(SimpleAVCommandItem(259, "Rear Volume Down", "", 1)); + m_commands.push_back(SimpleAVCommandItem(260, "Rear Volume Up", "", 1)); + m_commands.push_back(SimpleAVCommandItem(261, "Record Mute", "", 1)); + m_commands.push_back(SimpleAVCommandItem(262, "Record Pause", "", 1)); + m_commands.push_back(SimpleAVCommandItem(263, "Repeat", "", 1)); + m_commands.push_back(SimpleAVCommandItem(264, "Repeat A-B", "", 1)); + m_commands.push_back(SimpleAVCommandItem(265, "Resume", "", 1)); + m_commands.push_back(SimpleAVCommandItem(266, "RGB", "Red Green Blue Component Video", 1)); + m_commands.push_back(SimpleAVCommandItem(267, "Right Click", "", 1)); + m_commands.push_back(SimpleAVCommandItem(268, "Rock", "", 1)); + m_commands.push_back(SimpleAVCommandItem(269, "Rotate Left", "", 1)); + m_commands.push_back(SimpleAVCommandItem(270, "Rotate Right", "", 1)); + m_commands.push_back(SimpleAVCommandItem(271, "SAT", "Sky", 1)); + m_commands.push_back(SimpleAVCommandItem(272, "Scan", "Channel Scan", 1)); + m_commands.push_back(SimpleAVCommandItem(273, "Scart", "", 1)); + m_commands.push_back(SimpleAVCommandItem(274, "Scene", "", 1)); + m_commands.push_back(SimpleAVCommandItem(275, "Scroll", "", 1)); + m_commands.push_back(SimpleAVCommandItem(276, "Services", "", 1)); + m_commands.push_back(SimpleAVCommandItem(277, "Setup Menu", "Setup", 1)); + m_commands.push_back(SimpleAVCommandItem(278, "Sharp", "", 1)); + m_commands.push_back(SimpleAVCommandItem(279, "Sharpness", "", 1)); + m_commands.push_back(SimpleAVCommandItem(280, "Sharpness Down", "", 1)); + m_commands.push_back(SimpleAVCommandItem(281, "Sharpness Up", "", 1)); + m_commands.push_back(SimpleAVCommandItem(282, "Side A/B", "", 1)); + m_commands.push_back(SimpleAVCommandItem(283, "Skip Forward", "Next", 1)); + m_commands.push_back(SimpleAVCommandItem(284, "Skip Reverse", "Previous", 1)); + m_commands.push_back(SimpleAVCommandItem(285, "Sleep", "Off Timer", 1)); + m_commands.push_back(SimpleAVCommandItem(286, "Slow", "", 1)); + m_commands.push_back(SimpleAVCommandItem(287, "Slow Forward", "", 1)); + m_commands.push_back(SimpleAVCommandItem(288, "Slow Reverse", "", 1)); + m_commands.push_back(SimpleAVCommandItem(289, "Sound Menu", "Audio Menu", 1)); + m_commands.push_back(SimpleAVCommandItem(290, "Sound Mode", "Smart Sound", 1)); + m_commands.push_back(SimpleAVCommandItem(291, "Speed", "Record Speed", 1)); + m_commands.push_back(SimpleAVCommandItem(292, "Speed Down", "", 1)); + m_commands.push_back(SimpleAVCommandItem(293, "Speed Up", "", 1)); + m_commands.push_back(SimpleAVCommandItem(294, "Sports", "Digital Surround Processing", 1)); + m_commands.push_back(SimpleAVCommandItem(295, "Stadium", "", 1)); + m_commands.push_back(SimpleAVCommandItem(296, "Start", "", 1)); + m_commands.push_back(SimpleAVCommandItem(297, "Start ID Erase", "Erase", 1)); + m_commands.push_back(SimpleAVCommandItem(298, "Start ID Renumber", "Renumber", 1)); + m_commands.push_back(SimpleAVCommandItem(299, "Start ID Write", "Write", 1)); + m_commands.push_back(SimpleAVCommandItem(300, "Step", "", 1)); + m_commands.push_back(SimpleAVCommandItem(301, "Stereo/Mono", "L/R", 1)); + m_commands.push_back(SimpleAVCommandItem(302, "Still Forward", "Frame Advance", 1)); + m_commands.push_back(SimpleAVCommandItem(303, "Still Reverse", "Frame Reverse", 1)); + m_commands.push_back(SimpleAVCommandItem(304, "Subtitle", "Subtitle On-Off", 1)); + m_commands.push_back(SimpleAVCommandItem(305, "Subwoofer Down", "", 1)); + m_commands.push_back(SimpleAVCommandItem(306, "Subwoofer Up", "", 1)); + m_commands.push_back(SimpleAVCommandItem(307, "Super Bass", "Bass Boost", 1)); + m_commands.push_back(SimpleAVCommandItem(308, "Surround", "", 1)); + m_commands.push_back(SimpleAVCommandItem(309, "Surround Mode", "Sound Field", 1)); + m_commands.push_back(SimpleAVCommandItem(310, "S-Video", "", 1)); + m_commands.push_back(SimpleAVCommandItem(311, "Sweep", "Oscillate", 1)); + m_commands.push_back(SimpleAVCommandItem(312, "Synchro Record", "CD Synchro", 1)); + m_commands.push_back(SimpleAVCommandItem(313, "Tape 1", "Deck 1", 1)); + m_commands.push_back(SimpleAVCommandItem(314, "Tape 1-2", "Deck 1-2", 1)); + m_commands.push_back(SimpleAVCommandItem(315, "Tape 2", "Deck 2", 1)); + m_commands.push_back(SimpleAVCommandItem(316, "Temperature Down", "", 1)); + m_commands.push_back(SimpleAVCommandItem(317, "Temperature Up", "", 1)); + m_commands.push_back(SimpleAVCommandItem(318, "Test Tone", "", 1)); + m_commands.push_back(SimpleAVCommandItem(319, "Text", "Teletext", 1)); + m_commands.push_back(SimpleAVCommandItem(320, "Text Expand", "", 1)); + m_commands.push_back(SimpleAVCommandItem(321, "Text Hold", "", 1)); + m_commands.push_back(SimpleAVCommandItem(322, "Text Index", "", 1)); + m_commands.push_back(SimpleAVCommandItem(323, "Text Mix", "", 1)); + m_commands.push_back(SimpleAVCommandItem(324, "Text Off", "", 1)); + m_commands.push_back(SimpleAVCommandItem(325, "Text Reveal", "", 1)); + m_commands.push_back(SimpleAVCommandItem(326, "Text Subpage", "", 1)); + m_commands.push_back(SimpleAVCommandItem(327, "Text Timed Page", "", 1)); + m_commands.push_back(SimpleAVCommandItem(328, "Text Update", "Text Cancel", 1)); + m_commands.push_back(SimpleAVCommandItem(329, "Theater", "Cinema EQ", 1)); + m_commands.push_back(SimpleAVCommandItem(330, "Theme", "Category Select", 1)); + m_commands.push_back(SimpleAVCommandItem(331, "Thumbs Down", "", 1)); + m_commands.push_back(SimpleAVCommandItem(332, "Thumbs Up", "", 1)); + m_commands.push_back(SimpleAVCommandItem(333, "Tilt Down", "", 1)); + m_commands.push_back(SimpleAVCommandItem(334, "Tilt Up", "", 1)); + m_commands.push_back(SimpleAVCommandItem(335, "Time", "Clock", 1)); + m_commands.push_back(SimpleAVCommandItem(336, "Timer", "", 1)); + m_commands.push_back(SimpleAVCommandItem(337, "Timer Down", "", 1)); + m_commands.push_back(SimpleAVCommandItem(338, "Timer Up", "", 1)); + m_commands.push_back(SimpleAVCommandItem(339, "Tint", "", 1)); + m_commands.push_back(SimpleAVCommandItem(340, "Tint Down", "", 1)); + m_commands.push_back(SimpleAVCommandItem(341, "Tint Up", "", 1)); + m_commands.push_back(SimpleAVCommandItem(342, "Title", "Top Menu", 1)); + m_commands.push_back(SimpleAVCommandItem(343, "Track", "Chapter", 1)); + m_commands.push_back(SimpleAVCommandItem(344, "Tracking", "", 1)); + m_commands.push_back(SimpleAVCommandItem(345, "Tracking Down", "", 1)); + m_commands.push_back(SimpleAVCommandItem(346, "Tracking Up", "", 1)); + m_commands.push_back(SimpleAVCommandItem(347, "Treble", "", 1)); + m_commands.push_back(SimpleAVCommandItem(348, "Treble Down", "", 1)); + m_commands.push_back(SimpleAVCommandItem(349, "Treble Up", "", 1)); + m_commands.push_back(SimpleAVCommandItem(350, "Tune Down", "Audio Tune Down", 1)); + m_commands.push_back(SimpleAVCommandItem(351, "Tune Up", "Audio Tune Up", 1)); + m_commands.push_back(SimpleAVCommandItem(352, "Tuner", "", 1)); + m_commands.push_back(SimpleAVCommandItem(353, "VCR Plus+", "Showview", 1)); + m_commands.push_back(SimpleAVCommandItem(354, "Video 1", "A/V 1", 1)); + m_commands.push_back(SimpleAVCommandItem(355, "Video 2", "A/V 2", 1)); + m_commands.push_back(SimpleAVCommandItem(356, "Video 3", "A/V 3", 1)); + m_commands.push_back(SimpleAVCommandItem(357, "Video 4", "A/V 4", 1)); + m_commands.push_back(SimpleAVCommandItem(358, "Video 5", "A/V 5", 1)); + m_commands.push_back(SimpleAVCommandItem(359, "View", "", 1)); + m_commands.push_back(SimpleAVCommandItem(360, "Voice", "Vocals", 1)); + m_commands.push_back(SimpleAVCommandItem(361, "Zoom", "Magnify", 1)); + m_commands.push_back(SimpleAVCommandItem(362, "Zoom In", "Zoom Up", 1)); + m_commands.push_back(SimpleAVCommandItem(363, "Zoom Out", "Zoom Down", 1)); + m_commands.push_back(SimpleAVCommandItem(364, "eHome", "(Windows Media Center)", 2)); + m_commands.push_back(SimpleAVCommandItem(365, "Details", "(Windows Media Center)", 2)); + m_commands.push_back(SimpleAVCommandItem(366, "DVD Menu", "(Windows Media Center)", 2)); + m_commands.push_back(SimpleAVCommandItem(367, "My TV", "(Windows Media Center)", 2)); + m_commands.push_back(SimpleAVCommandItem(368, "Recorded TV", "(Windows Media Center)", 2)); + m_commands.push_back(SimpleAVCommandItem(369, "My Videos", "(Windows Media Center)", 2)); + m_commands.push_back(SimpleAVCommandItem(370, "DVD Angle", "(Windows Media Center)", 2)); + m_commands.push_back(SimpleAVCommandItem(371, "DVD Audio", "(Windows Media Center)", 2)); + m_commands.push_back(SimpleAVCommandItem(372, "DVD Subtitle", "(Windows Media Center)", 2)); + m_commands.push_back(SimpleAVCommandItem(373, "Radio", "(Windows Media Center)", 2)); + m_commands.push_back(SimpleAVCommandItem(374, "#", "(Windows Media Center)", 2)); + m_commands.push_back(SimpleAVCommandItem(375, "*", "(Windows Media Center)", 2)); + m_commands.push_back(SimpleAVCommandItem(376, "OEM 1", "(Windows Media Center)", 2)); + m_commands.push_back(SimpleAVCommandItem(377, "OEM 2", "(Windows Media Center)", 2)); + m_commands.push_back(SimpleAVCommandItem(378, "Info", "Used to request information", 3)); + m_commands.push_back(SimpleAVCommandItem(379, "CAPS NUM", "Switch between numeric and alpha (Shift)", 3)); + m_commands.push_back(SimpleAVCommandItem(380, "TV MODE", "Cycles through video output modes/resolutions", 3)); + m_commands.push_back(SimpleAVCommandItem(381, "SOURCE", "Displays the possible sources for the playback. [NFS, ext., USB, UPnP]", 3)); + m_commands.push_back(SimpleAVCommandItem(382, "FILEMODE", "File manipulation. Add/remove to list, create folder, rename file", 3)); + m_commands.push_back(SimpleAVCommandItem(383, "Time Seek", "This seeks to time position. Used for DVD/CD/others", 3)); + m_commands.push_back(SimpleAVCommandItem(384, "Mouse enable", "Mouse pointer enable", 4)); + m_commands.push_back(SimpleAVCommandItem(385, "Mouse disable", "Mouse pointer disable", 4)); + m_commands.push_back(SimpleAVCommandItem(386, "VOD", "Video on demand", 4)); + m_commands.push_back(SimpleAVCommandItem(387, "Thumbs Up", "Thumbs up for positive feedback in GUI", 4)); + m_commands.push_back(SimpleAVCommandItem(388, "Thumbs Down", "Thumbs down for negative feedback in GUI", 4)); + m_commands.push_back(SimpleAVCommandItem(389, "Apps", "Application selection/launch", 4)); + m_commands.push_back(SimpleAVCommandItem(390, "Mouse toggle", "Will toggle a mouse pointer between on and off", 4)); + m_commands.push_back(SimpleAVCommandItem(391, "TV Mode", "Will direct an AV device to go the TV mode (the mode is configured on the device)", 4)); + m_commands.push_back(SimpleAVCommandItem(392, "DVD Mode", "Will direct an AV device to go the DVD mode (the mode is configured on the device)", 4)); + m_commands.push_back(SimpleAVCommandItem(393, "STB Mode", "Will direct an AV device to go the STB mode (the mode is configured on the device)", 4)); + m_commands.push_back(SimpleAVCommandItem(394, "AUX Mode", "Will direct an AV device to go the AUX mode (the mode is configured on the device)", 4)); + m_commands.push_back(SimpleAVCommandItem(395, "BluRay Mode", "Will direct an AV device to go the BluRay mode (the mode is configured on the device)", 4)); + m_commands.push_back(SimpleAVCommandItem(404, "Standby 1", "Used for AV devices that support multiple standby mode. Power ON should be used to turn on the device", 4)); + m_commands.push_back(SimpleAVCommandItem(405, "Standby 2", "Used for AV devices that support multiple standby mode. Power ON should be used to turn on the device", 4)); + m_commands.push_back(SimpleAVCommandItem(406, "Standby 3", "Used for AV devices that support multiple standby mode. Power ON should be used to turn on the device", 4)); + m_commands.push_back(SimpleAVCommandItem(407, "HDMI 1", "Discrete command used to set an AV device to HDMI input 1", 4)); + m_commands.push_back(SimpleAVCommandItem(408, "HDMI 2", "Discrete command used to set an AV device to HDMI input 2", 4)); + m_commands.push_back(SimpleAVCommandItem(409, "HDMI 3", "Discrete command used to set an AV device to HDMI input 3", 4)); + m_commands.push_back(SimpleAVCommandItem(410, "HDMI 4", "Discrete command used to set an AV device to HDMI input 4", 4)); + m_commands.push_back(SimpleAVCommandItem(411, "HDMI 5", "Discrete command used to set an AV device to HDMI input 5", 4)); + m_commands.push_back(SimpleAVCommandItem(412, "HDMI 6", "Discrete command used to set an AV device to HDMI input 6", 4)); + m_commands.push_back(SimpleAVCommandItem(413, "HDMI 7", "Discrete command used to set an AV device to HDMI input 7", 4)); + m_commands.push_back(SimpleAVCommandItem(414, "HDMI 8", "Discrete command used to set an AV device to HDMI input 8", 4)); + m_commands.push_back(SimpleAVCommandItem(415, "HDMI 9", "Discrete command used to set an AV device to HDMI input 9", 4)); + m_commands.push_back(SimpleAVCommandItem(416, "USB 1", "Discrete command used to set an AV device to USB input 1", 4)); + m_commands.push_back(SimpleAVCommandItem(417, "USB 2", "Discrete command used to set an AV device to USB input 2", 4)); + m_commands.push_back(SimpleAVCommandItem(418, "USB 3", "Discrete command used to set an AV device to USB input 3", 4)); + m_commands.push_back(SimpleAVCommandItem(419, "USB 4", "Discrete command used to set an AV device to USB input 4", 4)); + m_commands.push_back(SimpleAVCommandItem(420, "USB 5", "Discrete command used to set an AV device to USB input 5", 4)); + m_commands.push_back(SimpleAVCommandItem(421, "ZOOM - 4:3 Normal", "Discrete commands that is used to set a TV a direct Zoom mode", 4)); + m_commands.push_back(SimpleAVCommandItem(422, "ZOOM - 4:3 Zoom", "Discrete commands that is used to set a TV a direct Zoom mode", 4)); + m_commands.push_back(SimpleAVCommandItem(423, "ZOOM - 16:9 Normal", "Discrete commands that is used to set a TV a direct Zoom mode", 4)); + m_commands.push_back(SimpleAVCommandItem(424, "ZOOM - 16:9 Zoom", "Discrete commands that is used to set a TV a direct Zoom mode", 4)); + m_commands.push_back(SimpleAVCommandItem(425, "ZOOM - 16:9 Wide 1", "Discrete commands that is used to set a TV a direct Zoom mode", 4)); + m_commands.push_back(SimpleAVCommandItem(426, "ZOOM 16:9 Wide 2", "Discrete commands that is used to set a TV a direct Zoom mode", 4)); + m_commands.push_back(SimpleAVCommandItem(427, "ZOOM 16:9 Wide 3", "Discrete commands that is used to set a TV a direct Zoom mode", 4)); + m_commands.push_back(SimpleAVCommandItem(428, "ZOOM 16:9 Cinema", "Discrete commands that is used to set a TV a direct Zoom mode", 4)); + m_commands.push_back(SimpleAVCommandItem(429, "ZOOM Default", "Discrete commands that is used to set a TV the default Zoom mode", 4)); + m_commands.push_back(SimpleAVCommandItem(432, "Auto Zoom", "Will set Zoom mode automatically", 4)); + m_commands.push_back(SimpleAVCommandItem(433, "ZOOM - Set as Default Zoom", "Will set the current active Zoom level to default", 4)); + m_commands.push_back(SimpleAVCommandItem(434, "Mute ON", "Discrete Mute ON command", 4)); + m_commands.push_back(SimpleAVCommandItem(435, "Mute OFF", "Discrete Mute OFF command", 4)); + m_commands.push_back(SimpleAVCommandItem(436, "AUDIO Mode - AUDYSSEY AUDIO OFF", "Discrete Audio mode for Audussey audio processing (Off) ", 4)); + m_commands.push_back(SimpleAVCommandItem(437, "AUDIO Mode - AUDYSSEY AUDIO LO", "Discrete Audio mode for Audussey audio processing (Low) ", 4)); + m_commands.push_back(SimpleAVCommandItem(438, "AUDIO Mode - AUDYSSEY AUDIO MED", "Discrete Audio mode for Audussey audio processing (Medium) ", 4)); + m_commands.push_back(SimpleAVCommandItem(439, "AUDIO Mode - AUDYSSEY AUDIO HI", "Discrete Audio mode for Audussey audio processing (High) ", 4)); + m_commands.push_back(SimpleAVCommandItem(442, "AUDIO Mode - SRS SURROUND ON", "Discrete Audio mode for SRS audio processing", 4)); + m_commands.push_back(SimpleAVCommandItem(443, "AUDIO Mode - SRS SURROUND OFF", "Discrete Audio mode for SRS audio processing", 4)); + m_commands.push_back(SimpleAVCommandItem(447, "Picture Mode - Home", "Discrete picture for TVs", 4)); + m_commands.push_back(SimpleAVCommandItem(448, "Picture Mode - Retail", "Discrete picture for TVs", 4)); + m_commands.push_back(SimpleAVCommandItem(449, "Picture Mode - Vivid", "Discrete picture for TVs", 4)); + m_commands.push_back(SimpleAVCommandItem(450, "Picture Mode - Standard", "Discrete picture for TVs", 4)); + m_commands.push_back(SimpleAVCommandItem(451, "Picture Mode - Theater", "Discrete picture for TVs", 4)); + m_commands.push_back(SimpleAVCommandItem(452, "Picture Mode - Sports", "Discrete picture for TVs", 4)); + m_commands.push_back(SimpleAVCommandItem(453, "Picture Mode - Energy savings ", "Discrete picture for TVs", 4)); + m_commands.push_back(SimpleAVCommandItem(454, "Picture Mode - Custom", "Discrete picture for TVs", 4)); + m_commands.push_back(SimpleAVCommandItem(455, "Cool", "Discrete picture temperature adjustments", 4)); + m_commands.push_back(SimpleAVCommandItem(456, "Medium", "Discrete picture temperature adjustments", 4)); + m_commands.push_back(SimpleAVCommandItem(457, "Warm_D65", "Discrete picture temperature adjustments", 4)); + m_commands.push_back(SimpleAVCommandItem(458, "CC ON", "Discrete Closed caption commands", 4)); + m_commands.push_back(SimpleAVCommandItem(459, "CC OFF", "Discrete Closed caption commands", 4)); + m_commands.push_back(SimpleAVCommandItem(460, "Video Mute ON", "Discrete Video mute command", 4)); + m_commands.push_back(SimpleAVCommandItem(461, "Video Mute OFF", "Discrete Video mute command", 4)); + m_commands.push_back(SimpleAVCommandItem(462, "Next Event", "Go to next state or event ", 4)); + m_commands.push_back(SimpleAVCommandItem(463, "Previous Event", "Go to previous state or event", 4)); + m_commands.push_back(SimpleAVCommandItem(464, "CEC device list", "Brings up the CES device list", 4)); + m_commands.push_back(SimpleAVCommandItem(465, "MTS SAP", "Secondary Audio programming", 4)); + } + return m_commands; + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/SimpleAVCommandItem.h b/cpp/src/command_classes/SimpleAVCommandItem.h index b93bee8e46..fb5b2978d0 100644 --- a/cpp/src/command_classes/SimpleAVCommandItem.h +++ b/cpp/src/command_classes/SimpleAVCommandItem.h @@ -1,25 +1,63 @@ +//----------------------------------------------------------------------------- +// +// SimpleAVCommandItem.h +// +// Implementation of the Z-Wave COMMAND_CLASS_SIMPLE_AV_CONTROL +// +// Copyright (c) 2018 +// +// SOFTWARE NOTICE AND LICENSE +// +// This file is part of OpenZWave. +// +// OpenZWave is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, either version 3 of the License, +// or (at your option) any later version. +// +// OpenZWave is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with OpenZWave. If not, see . +// +//----------------------------------------------------------------------------- + +#ifndef _SimpleAVCommandItem_H +#define _SimpleAVCommandItem_H + #include #include #include "Defs.h" namespace OpenZWave { - class SimpleAVCommandItem + namespace Internal { - public: - SimpleAVCommandItem(uint16 const _code, string _name, string _description, uint16 const _version); - uint16 GetCode(); - string GetName(); - string GetDescription(); - uint16 GetVersion(); + namespace CC + { + + class SimpleAVCommandItem + { + public: + SimpleAVCommandItem(uint16 const _code, string _name, string _description, uint16 const _version); + uint16 GetCode(); + string GetName(); + string GetDescription(); + uint16 GetVersion(); - static vector GetCommands(); + static vector GetCommands(); - private: - uint16 m_code; - string m_name; - string m_description; - uint16 m_version; - }; -} + private: + uint16 m_code; + string m_name; + string m_description; + uint16 m_version; + }; + } // namespace CC + } // namespace Internal +} // namespace CC +#endif diff --git a/cpp/src/command_classes/SoundSwitch.cpp b/cpp/src/command_classes/SoundSwitch.cpp index 4a9aac5e60..db40f8eb07 100644 --- a/cpp/src/command_classes/SoundSwitch.cpp +++ b/cpp/src/command_classes/SoundSwitch.cpp @@ -36,282 +36,266 @@ #include "value_classes/ValueByte.h" -using namespace OpenZWave; - -enum SoundSwitchCmd -{ - SoundSwitchCmd_Tones_Number_Get = 0x01, - SoundSwitchCmd_Tones_Number_Report = 0x02, - SoundSwitchCmd_Tones_Info_Get = 0x03, - SoundSwitchCmd_Tones_Info_Report = 0x04, - SoundSwitchCmd_Tones_Config_Set = 0x05, - SoundSwitchCmd_Tones_Config_Get = 0x06, - soundSwitchCmd_Tones_Config_Report = 0x07, - SoundSwitchCmd_Tones_Play_Set = 0x08, - SoundSwitchCmd_Tones_Play_Report = 0x0A -}; - -enum +namespace OpenZWave { - SoundSwitchIndex_Tone_Count = 0, - SoundSwitchIndex_Tones = 1, - SoundSwitchIndex_Volume = 2, - SoundSwitchIndex_Default_Tone = 3 -}; + namespace Internal + { + namespace CC + { + enum SoundSwitchCmd + { + SoundSwitchCmd_Tones_Number_Get = 0x01, + SoundSwitchCmd_Tones_Number_Report = 0x02, + SoundSwitchCmd_Tones_Info_Get = 0x03, + SoundSwitchCmd_Tones_Info_Report = 0x04, + SoundSwitchCmd_Tones_Config_Set = 0x05, + SoundSwitchCmd_Tones_Config_Get = 0x06, + soundSwitchCmd_Tones_Config_Report = 0x07, + SoundSwitchCmd_Tones_Play_Set = 0x08, + SoundSwitchCmd_Tones_Play_Report = 0x0A + }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -SoundSwitch::SoundSwitch -( - uint32 const _homeId, - uint8 const _nodeId -): -CommandClass( _homeId, _nodeId ), -m_toneCount( 0 ) -{ - SetStaticRequest( StaticRequest_Values ); -} - + SoundSwitch::SoundSwitch(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId), m_toneCount(0) + { + SetStaticRequest(StaticRequest_Values); + } //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool SoundSwitch::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - bool requests = false; - if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) ) - { - requests |= RequestValue( _requestFlags, SoundSwitchIndex_Tone_Count, _instance, _queue ); - } + bool SoundSwitch::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + bool requests = false; + if ((_requestFlags & RequestFlag_Static) && HasStaticRequest(StaticRequest_Values)) + { + requests |= RequestValue(_requestFlags, ValueID_Index_SoundSwitch::Tone_Count, _instance, _queue); + } - return requests; -} + return requests; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool SoundSwitch::RequestValue -( - uint32 const _requestFlags, - uint16 const _index, // = 0 (not used) - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if (_index == SoundSwitchIndex_Tone_Count ) { - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Msg* msg = new Msg( "SoundSwitchCmd_Tones_Number_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( SoundSwitchCmd_Tones_Number_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "SoundSwitchCmd_Tones_Number_Get Not Supported on this node"); - } - } - return false; -} + bool SoundSwitch::RequestValue(uint32 const _requestFlags, uint16 const _index, // = 0 (not used) + uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_index == ValueID_Index_SoundSwitch::Tone_Count) + { + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Msg* msg = new Msg("SoundSwitchCmd_Tones_Number_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(SoundSwitchCmd_Tones_Number_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "SoundSwitchCmd_Tones_Number_Get Not Supported on this node"); + } + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool SoundSwitch::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if (SoundSwitchCmd_Tones_Number_Report == (SoundSwitchCmd)_data[0]) - { - m_toneCount = _data[1]; - Log::Write( LogLevel_Info, GetNodeId(), "Received SoundSwitch Tone Count report: %d", m_toneCount); - if( ValueByte* value = static_cast( GetValue( _instance, SoundSwitchIndex_Tone_Count ) ) ) - { - value->OnValueRefreshed( m_toneCount ); - value->Release(); - } - for (int i = 1; i <= m_toneCount; i++) { - Msg* msg = new Msg( "SoundSwitchCmd_Tones_Info_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( SoundSwitchCmd_Tones_Info_Get ); - msg->Append( i ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - } - return true; - } - if (SoundSwitchCmd_Tones_Info_Report == (SoundSwitchCmd)_data[0]) - { - uint8 index = _data[1]; - uint16 duration = (_data[2] << 8) + _data[3]; - string name((const char *)&_data[5], _data[4]); - m_toneInfo[index].duration = duration; - m_toneInfo[index].name = name; - Log::Write( LogLevel_Info, GetNodeId(), "Received SoundSwitch Tone Info Report: %d - %s - %d sec", index, name.c_str(), duration); - if (index == m_toneCount) { - vector items; - { - ValueList::Item item; - item.m_label = "Inactive"; - item.m_value = 0; - items.push_back( item ); - } - for( unsigned int i=1; i <= m_toneCount; i++) + bool SoundSwitch::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) { - ValueList::Item item; - char str[32]; - snprintf( str, sizeof(str), "%s (%d sec)", m_toneInfo[i].name.c_str(), m_toneInfo[i].duration ); - item.m_label = str; - item.m_value = i; - items.push_back( item ); - } - { - ValueList::Item item; - item.m_label = "Default Tone"; - item.m_value = 0xff; - items.push_back( item ); - } - if (Node* node = GetNodeUnsafe()) { - node->CreateValueList( ValueID::ValueGenre_User, GetCommandClassId(), _instance, SoundSwitchIndex_Tones, "Tones", "", false, false, m_toneCount, items, 0, 0 ); - node->CreateValueList( ValueID::ValueGenre_Config, GetCommandClassId(), _instance, SoundSwitchIndex_Default_Tone, "Default Tone", "", false, false, m_toneCount, items, 0, 0 ); + if (SoundSwitchCmd_Tones_Number_Report == (SoundSwitchCmd) _data[0]) + { + m_toneCount = _data[1]; + Log::Write(LogLevel_Info, GetNodeId(), "Received SoundSwitch Tone Count report: %d", m_toneCount); + if (Internal::VC::ValueByte* value = static_cast(GetValue(_instance, ValueID_Index_SoundSwitch::Tone_Count))) + { + value->OnValueRefreshed(m_toneCount); + value->Release(); + } + for (int i = 1; i <= m_toneCount; i++) + { + Msg* msg = new Msg("SoundSwitchCmd_Tones_Info_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(SoundSwitchCmd_Tones_Info_Get); + msg->Append(i); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + } + return true; + } + if (SoundSwitchCmd_Tones_Info_Report == (SoundSwitchCmd) _data[0]) + { + uint8 index = _data[1]; + uint16 duration = (_data[2] << 8) + _data[3]; + string name((const char *) &_data[5], _data[4]); + m_toneInfo[index].duration = duration; + m_toneInfo[index].name = name; + Log::Write(LogLevel_Info, GetNodeId(), "Received SoundSwitch Tone Info Report: %d - %s - %d sec", index, name.c_str(), duration); + if (index == m_toneCount) + { + vector items; + { + Internal::VC::ValueList::Item item; + item.m_label = "Inactive"; + item.m_value = 0; + items.push_back(item); + } + for (unsigned int i = 1; i <= m_toneCount; i++) + { + Internal::VC::ValueList::Item item; + char str[268]; // name is max 255, duration can be max 65535 so this should be enough space + snprintf(str, sizeof(str), "%s (%d sec)", m_toneInfo[i].name.c_str(), m_toneInfo[i].duration); + item.m_label = str; + item.m_value = i; + items.push_back(item); + } + { + Internal::VC::ValueList::Item item; + item.m_label = "Default Tone"; + item.m_value = 0xff; + items.push_back(item); + } + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueList(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_SoundSwitch::Tones, "Tones", "", false, false, m_toneCount, items, 0, 0); + node->CreateValueList(ValueID::ValueGenre_Config, GetCommandClassId(), _instance, ValueID_Index_SoundSwitch::Default_Tone, "Default Tone", "", false, false, m_toneCount, items, 0, 0); + } + /* after we got the list of Tones, Get the Configuration */ + Msg* msg = new Msg("SoundSwitchCmd_Tones_Config_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(SoundSwitchCmd_Tones_Config_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + } + return true; + } + if (soundSwitchCmd_Tones_Config_Report == (SoundSwitchCmd) _data[0]) + { + uint8 volume = _data[1]; + uint8 defaulttone = _data[2]; + if (volume > 100) + volume = 100; + Log::Write(LogLevel_Info, GetNodeId(), "Received SoundSwitch Tone Config report - Volume: %d, defaulttone: %d", volume, defaulttone); + if (Internal::VC::ValueByte* value = static_cast(GetValue(_instance, ValueID_Index_SoundSwitch::Volume))) + { + value->OnValueRefreshed(volume); + value->Release(); + } + if (Internal::VC::ValueList* value = static_cast(GetValue(_instance, ValueID_Index_SoundSwitch::Default_Tone))) + { + value->OnValueRefreshed(defaulttone); + value->Release(); + } + ClearStaticRequest(StaticRequest_Values); + return true; + } + if (SoundSwitchCmd_Tones_Play_Report == (SoundSwitchCmd) _data[0]) + { + Log::Write(LogLevel_Info, GetNodeId(), "Received SoundSwitch Tone Play report: %d", _data[1]); + if (Internal::VC::ValueList* value = static_cast(GetValue(_instance, ValueID_Index_SoundSwitch::Tones))) + { + value->OnValueRefreshed(_data[1]); + value->Release(); + } + return true; + } + return false; } - /* after we got the list of Tones, Get the Configuration */ - Msg* msg = new Msg( "SoundSwitchCmd_Tones_Config_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( SoundSwitchCmd_Tones_Config_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - } - return true; - } - if (soundSwitchCmd_Tones_Config_Report == (SoundSwitchCmd)_data[0]) { - uint8 volume = _data[1]; - uint8 defaulttone = _data[2]; - if (volume > 100) - volume = 100; - Log::Write( LogLevel_Info, GetNodeId(), "Received SoundSwitch Tone Config report - Volume: %d, defaulttone: %d", volume, defaulttone); - if( ValueByte* value = static_cast( GetValue( _instance, SoundSwitchIndex_Volume ) ) ) - { - value->OnValueRefreshed( volume ); - value->Release(); - } - if( ValueList* value = static_cast( GetValue( _instance, SoundSwitchIndex_Default_Tone ) ) ) - { - value->OnValueRefreshed( defaulttone ); - value->Release(); - } - ClearStaticRequest( StaticRequest_Values ); - return true; - } - if (SoundSwitchCmd_Tones_Play_Report == (SoundSwitchCmd)_data[0]) { - Log::Write( LogLevel_Info, GetNodeId(), "Received SoundSwitch Tone Play report: %d", _data[1]); - if( ValueList* value = static_cast( GetValue( _instance, SoundSwitchIndex_Tones ) ) ) - { - value->OnValueRefreshed( _data[1] ); - value->Release(); - } - return true; - } - return false; -} //----------------------------------------------------------------------------- // // Set a value in the Z-Wave device //----------------------------------------------------------------------------- -bool SoundSwitch::SetValue -( - Value const& _value -) -{ - bool ret = false; - uint8 instance = _value.GetID().GetInstance(); - uint16 index = _value.GetID().GetIndex(); - if (index == SoundSwitchIndex_Tones) { - if (ValueList const* value = static_cast(&_value)) { - ValueList::Item const *item = value->GetItem(); - if (item == NULL) - return false; - Msg* msg = new Msg( "SoundSwitchCmd_Tones_Play_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, instance ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( SoundSwitchCmd_Tones_Play_Set ); - msg->Append( item->m_value ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - } - ret = true; - } - if (index == SoundSwitchIndex_Volume || index == SoundSwitchIndex_Default_Tone) { - uint8 volume = 0xff; - uint8 defaulttone = 0x01; - if( ValueByte const* value = static_cast( GetValue( instance, SoundSwitchIndex_Volume ) ) ) - { - volume = value->GetValue(); - } - if (ValueList const* value = static_cast( GetValue( instance, SoundSwitchIndex_Default_Tone ) ) ) - { - ValueList::Item const *item = value->GetItem(); - if (item == NULL) - return false; - defaulttone = item->m_value; - /* 0 means dont update the Default Tone 0xFF is the Default tone! */ - if (defaulttone == 0xFF) - defaulttone = 1; - } - Msg* msg = new Msg( "SoundSwitchCmd_Tones_Config_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, instance ); - msg->Append( GetNodeId() ); - msg->Append( 4 ); - msg->Append( GetCommandClassId() ); - msg->Append( SoundSwitchCmd_Tones_Config_Set ); - msg->Append( volume ); - msg->Append( defaulttone ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - ret = true; - } + bool SoundSwitch::SetValue(Internal::VC::Value const& _value) + { + bool ret = false; + uint8 instance = _value.GetID().GetInstance(); + uint16 index = _value.GetID().GetIndex(); + if (index == ValueID_Index_SoundSwitch::Tones) + { + if (Internal::VC::ValueList const* value = static_cast(&_value)) + { + Internal::VC::ValueList::Item const *item = value->GetItem(); + if (item == NULL) + return false; + Msg* msg = new Msg("SoundSwitchCmd_Tones_Play_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, instance); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(SoundSwitchCmd_Tones_Play_Set); + msg->Append(item->m_value); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + } + ret = true; + } + if (index == ValueID_Index_SoundSwitch::Volume || index == ValueID_Index_SoundSwitch::Default_Tone) + { + uint8 volume = 0xff; + uint8 defaulttone = 0x01; + if (Internal::VC::ValueByte const* value = static_cast(GetValue(instance, ValueID_Index_SoundSwitch::Volume))) + { + volume = value->GetValue(); + } + if (Internal::VC::ValueList const* value = static_cast(GetValue(instance, ValueID_Index_SoundSwitch::Default_Tone))) + { + Internal::VC::ValueList::Item const *item = value->GetItem(); + if (item == NULL) + return false; + defaulttone = item->m_value; + /* 0 means dont update the Default Tone 0xFF is the Default tone! */ + if (defaulttone == 0xFF) + defaulttone = 1; + } + Msg* msg = new Msg("SoundSwitchCmd_Tones_Config_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, instance); + msg->Append(GetNodeId()); + msg->Append(4); + msg->Append(GetCommandClassId()); + msg->Append(SoundSwitchCmd_Tones_Config_Set); + msg->Append(volume); + msg->Append(defaulttone); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + ret = true; + } - return ret; -} + return ret; + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void SoundSwitch::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - node->CreateValueByte( ValueID::ValueGenre_System, GetCommandClassId(), _instance, SoundSwitchIndex_Tone_Count, "Number of Tones", "", true, false, 0, 0 ); - node->CreateValueByte( ValueID::ValueGenre_Config, GetCommandClassId(), _instance, SoundSwitchIndex_Volume, "Volume", "", false, false, 100, 0); - } -} + void SoundSwitch::CreateVars(uint8 const _instance) + { + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueByte(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_SoundSwitch::Tone_Count, "Number of Tones", "", true, false, 0, 0); + node->CreateValueByte(ValueID::ValueGenre_Config, GetCommandClassId(), _instance, ValueID_Index_SoundSwitch::Volume, "Volume", "", false, false, 100, 0); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/SoundSwitch.h b/cpp/src/command_classes/SoundSwitch.h index d0ff41a72a..b8710f27a0 100644 --- a/cpp/src/command_classes/SoundSwitch.h +++ b/cpp/src/command_classes/SoundSwitch.h @@ -32,44 +32,65 @@ namespace OpenZWave { - class ValueByte; - class ValueList; - - /** \brief Implements COMMAND_CLASS_SOUND_SWITCH (0x79), a Z-Wave device command class. - * \ingroup CommandClass - */ - class SoundSwitch: public CommandClass + namespace Internal { - private: - struct SoundSwitchToneInfo { - uint16 duration; - string name; - }; - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new SoundSwitch( _homeId, _nodeId ); } - virtual ~SoundSwitch(){} + namespace CC + { - static uint8 const StaticGetCommandClassId(){ return 0x79; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_SOUND_SWITCH"; } + /** \brief Implements COMMAND_CLASS_SOUND_SWITCH (0x79), a Z-Wave device command class. + * \ingroup CommandClass + */ + class SoundSwitch: public CommandClass + { + private: + struct SoundSwitchToneInfo + { + uint16 duration; + string name; + }; + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new SoundSwitch(_homeId, _nodeId); + } + virtual ~SoundSwitch() + { + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool SetValue( Value const& _value ); + static uint8 const StaticGetCommandClassId() + { + return 0x79; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_SOUND_SWITCH"; + } - protected: - virtual void CreateVars( uint8 const _instance ); + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool SetValue(Internal::VC::Value const& _value) override; - private: - SoundSwitch( uint32 const _homeId, uint8 const _nodeId ); + protected: + virtual void CreateVars(uint8 const _instance) override; - uint8 m_toneCount; - std::map m_toneInfo; - }; + private: + SoundSwitch(uint32 const _homeId, uint8 const _nodeId); + uint8 m_toneCount; + std::map m_toneInfo; + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/SwitchAll.cpp b/cpp/src/command_classes/SwitchAll.cpp index 1e77dd87ec..f11536e00f 100644 --- a/cpp/src/command_classes/SwitchAll.cpp +++ b/cpp/src/command_classes/SwitchAll.cpp @@ -35,196 +35,171 @@ #include "value_classes/ValueList.h" -using namespace OpenZWave; - -enum SwitchAllCmd -{ - SwitchAllCmd_Set = 0x01, - SwitchAllCmd_Get = 0x02, - SwitchAllCmd_Report = 0x03, - SwitchAllCmd_On = 0x04, - SwitchAllCmd_Off = 0x05 -}; - -static char const* c_switchAllStateName[] = +namespace OpenZWave { - "Disabled", - "Off Enabled", - "On Enabled", - "On and Off Enabled" -}; + namespace Internal + { + namespace CC + { + + enum SwitchAllCmd + { + SwitchAllCmd_Set = 0x01, + SwitchAllCmd_Get = 0x02, + SwitchAllCmd_Report = 0x03, + SwitchAllCmd_On = 0x04, + SwitchAllCmd_Off = 0x05 + }; + + static char const* c_switchAllStateName[] = + { "Disabled", "Off Enabled", "On Enabled", "On and Off Enabled" }; //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool SwitchAll::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _requestFlags & RequestFlag_Session ) - { - return RequestValue( _requestFlags, 0, _instance, _queue ); - } + bool SwitchAll::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_requestFlags & RequestFlag_Session) + { + return RequestValue(_requestFlags, 0, _instance, _queue); + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool SwitchAll::RequestValue -( - uint32 const _requestFlags, - uint16 const _dummy1, // = 0 (not used) - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Msg* msg = new Msg( "SwitchAllCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( SwitchAllCmd_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "SwitchAllCmd_Get Not Supported on this node"); - } - return false; -} + bool SwitchAll::RequestValue(uint32 const _requestFlags, uint16 const _dummy1, // = 0 (not used) + uint8 const _instance, Driver::MsgQueue const _queue) + { + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Msg* msg = new Msg("SwitchAllCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(SwitchAllCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "SwitchAllCmd_Get Not Supported on this node"); + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool SwitchAll::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if (SwitchAllCmd_Report == (SwitchAllCmd)_data[0]) - { - if( ValueList* value = static_cast( GetValue( _instance, 0 ) ) ) - { - value->OnValueRefreshed( (int32)_data[1] ); - value->Release(); - if (value->GetItem()) - Log::Write( LogLevel_Info, GetNodeId(), "Received SwitchAll report from node %d: %s", GetNodeId(), value->GetItem()->m_label.c_str() ); - else - Log::Write( LogLevel_Info, GetNodeId(), "Received SwitchAll report from node %d: %d", GetNodeId(), _data[1]); - } - return true; - } - - return false; -} + bool SwitchAll::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) + { + if (SwitchAllCmd_Report == (SwitchAllCmd) _data[0]) + { + if (Internal::VC::ValueList* value = static_cast(GetValue(_instance, ValueID_Index_SwitchAll::SwitchAll))) + { + value->OnValueRefreshed((int32) _data[1]); + value->Release(); + if (value->GetItem()) + Log::Write(LogLevel_Info, GetNodeId(), "Received SwitchAll report from node %d: %s", GetNodeId(), value->GetItem()->m_label.c_str()); + else + Log::Write(LogLevel_Info, GetNodeId(), "Received SwitchAll report from node %d: %d", GetNodeId(), _data[1]); + } + return true; + } + + return false; + } //----------------------------------------------------------------------------- // // Set the device's response to SWITCH_ALL commands //----------------------------------------------------------------------------- -bool SwitchAll::SetValue -( - Value const& _value -) -{ - if( ValueID::ValueType_List == _value.GetID().GetType() ) - { - ValueList const* value = static_cast(&_value); - ValueList::Item const *item = value->GetItem(); - if (item == NULL) - return false; - - Log::Write( LogLevel_Info, GetNodeId(), "SwitchAll::Set - %s on node %d", item->m_label.c_str(), GetNodeId() ); - Msg* msg = new Msg( "SwitchAllCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->SetInstance( this, _value.GetID().GetInstance() ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( SwitchAllCmd_Set ); - msg->Append( (uint8)item->m_value ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - return true; - } - - return false; -} + bool SwitchAll::SetValue(Internal::VC::Value const& _value) + { + if (ValueID::ValueType_List == _value.GetID().GetType()) + { + Internal::VC::ValueList const* value = static_cast(&_value); + Internal::VC::ValueList::Item const *item = value->GetItem(); + if (item == NULL) + return false; + + Log::Write(LogLevel_Info, GetNodeId(), "SwitchAll::Set - %s on node %d", item->m_label.c_str(), GetNodeId()); + Msg* msg = new Msg("SwitchAllCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->SetInstance(this, _value.GetID().GetInstance()); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(SwitchAllCmd_Set); + msg->Append((uint8) item->m_value); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return true; + } + + return false; + } //----------------------------------------------------------------------------- // // Send a command to switch all devices off //----------------------------------------------------------------------------- -void SwitchAll::Off -( - Driver* _driver, - uint8 const _nodeId -) -{ - Log::Write( LogLevel_Info, _nodeId, "SwitchAll::Off (Node=%d)", _nodeId ); - Msg* msg = new Msg( "SwitchAllCmd_Off", _nodeId, REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->Append( _nodeId ); - msg->Append( 2 ); - msg->Append( StaticGetCommandClassId() ); - msg->Append( SwitchAllCmd_Off ); - msg->Append( _driver->GetTransmitOptions() ); - _driver->SendMsg( msg, Driver::MsgQueue_Send ); -} + void SwitchAll::Off(Driver* _driver, uint8 const _nodeId) + { + Log::Write(LogLevel_Info, _nodeId, "SwitchAll::Off (Node=%d)", _nodeId); + Msg* msg = new Msg("SwitchAllCmd_Off", _nodeId, REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->Append(_nodeId); + msg->Append(2); + msg->Append(StaticGetCommandClassId()); + msg->Append(SwitchAllCmd_Off); + msg->Append(_driver->GetTransmitOptions()); + _driver->SendMsg(msg, Driver::MsgQueue_Send); + } //----------------------------------------------------------------------------- // // Send a command to switch all devices on //----------------------------------------------------------------------------- -void SwitchAll::On -( - Driver* _driver, - uint8 const _nodeId -) -{ - Log::Write( LogLevel_Info, _nodeId, "SwitchAll::On (Node=%d)", _nodeId ); - Msg* msg = new Msg( "SwitchAllCmd_On", _nodeId, REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->Append( _nodeId ); - msg->Append( 2 ); - msg->Append( StaticGetCommandClassId() ); - msg->Append( SwitchAllCmd_On ); - msg->Append( _driver->GetTransmitOptions() ); - _driver->SendMsg( msg, Driver::MsgQueue_Send ); -} + void SwitchAll::On(Driver* _driver, uint8 const _nodeId) + { + Log::Write(LogLevel_Info, _nodeId, "SwitchAll::On (Node=%d)", _nodeId); + Msg* msg = new Msg("SwitchAllCmd_On", _nodeId, REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->Append(_nodeId); + msg->Append(2); + msg->Append(StaticGetCommandClassId()); + msg->Append(SwitchAllCmd_On); + msg->Append(_driver->GetTransmitOptions()); + _driver->SendMsg(msg, Driver::MsgQueue_Send); + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void SwitchAll::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - vector items; - for( int i=0; i<4; ++i ) - { - ValueList::Item item; - item.m_label = c_switchAllStateName[i]; - item.m_value = (i==3) ? 0x000000ff : i; - items.push_back( item ); - } - - node->CreateValueList( ValueID::ValueGenre_System, GetCommandClassId(), _instance, 0, "Switch All", "", false, false, 1, items, 0, 0 ); - } -} - - + void SwitchAll::CreateVars(uint8 const _instance) + { + if (Node* node = GetNodeUnsafe()) + { + vector items; + for (int i = 0; i < 4; ++i) + { + Internal::VC::ValueList::Item item; + item.m_label = c_switchAllStateName[i]; + item.m_value = (i == 3) ? 0x000000ff : i; + items.push_back(item); + } + + node->CreateValueList(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_SwitchAll::SwitchAll, "Switch All", "", false, false, 1, items, 0, 0); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/SwitchAll.h b/cpp/src/command_classes/SwitchAll.h index 5c98ae44d4..32adb18366 100644 --- a/cpp/src/command_classes/SwitchAll.h +++ b/cpp/src/command_classes/SwitchAll.h @@ -32,38 +32,62 @@ namespace OpenZWave { - class ValueList; - - /** \brief Implements COMMAND_CLASS_SWITCH_ALL (0x27), a Z-Wave device command class. - * \ingroup CommandClass - */ - class SwitchAll: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new SwitchAll( _homeId, _nodeId ); } - virtual ~SwitchAll(){} + namespace CC + { - static uint8 const StaticGetCommandClassId(){ return 0x27; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_SWITCH_ALL"; } + /** \brief Implements COMMAND_CLASS_SWITCH_ALL (0x27), a Z-Wave device command class. + * \ingroup CommandClass + */ + class SwitchAll: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new SwitchAll(_homeId, _nodeId); + } + virtual ~SwitchAll() + { + } - static void On( Driver* _driver, uint8 const _nodeId ); - static void Off( Driver* _driver, uint8 const _nodeId ); + static uint8 const StaticGetCommandClassId() + { + return 0x27; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_SWITCH_ALL"; + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool SetValue( Value const& _value ); + static void On(Driver* _driver, uint8 const _nodeId); + static void Off(Driver* _driver, uint8 const _nodeId); - protected: - virtual void CreateVars( uint8 const _instance ); + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool SetValue(Internal::VC::Value const& _value) override; - private: - SwitchAll( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} - }; + protected: + virtual void CreateVars(uint8 const _instance) override; + private: + SwitchAll(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + } + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/SwitchBinary.cpp b/cpp/src/command_classes/SwitchBinary.cpp index a6e9eca799..1333b8439c 100644 --- a/cpp/src/command_classes/SwitchBinary.cpp +++ b/cpp/src/command_classes/SwitchBinary.cpp @@ -39,267 +39,236 @@ #include "value_classes/ValueBool.h" #include "value_classes/ValueByte.h" -using namespace OpenZWave; - -enum SwitchBinaryCmd +namespace OpenZWave { - SwitchBinaryCmd_Set = 0x01, - SwitchBinaryCmd_Get = 0x02, - SwitchBinaryCmd_Report = 0x03 -}; + namespace Internal + { + namespace CC + { -enum SwitchBinaryIndex -{ - SwitchBinaryIndex_Level = 0, - SwitchBinaryIndex_TargetState, - SwitchBinaryIndex_Duration -}; + enum SwitchBinaryCmd + { + SwitchBinaryCmd_Set = 0x01, + SwitchBinaryCmd_Get = 0x02, + SwitchBinaryCmd_Report = 0x03 + }; //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool SwitchBinary::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _requestFlags & RequestFlag_Dynamic ) - { - return RequestValue( _requestFlags, 0, _instance, _queue ); - } + bool SwitchBinary::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_requestFlags & RequestFlag_Dynamic) + { + return RequestValue(_requestFlags, 0, _instance, _queue); + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool SwitchBinary::RequestValue -( - uint32 const _requestFlags, - uint16 const _dummy1, // = 0 (not used) - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Msg* msg = new Msg( "SwitchBinaryCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( SwitchBinaryCmd_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "SwitchBinaryCmd_Get Not Supported on this node"); - } - return false; -} + bool SwitchBinary::RequestValue(uint32 const _requestFlags, uint16 const _dummy1, // = 0 (not used) + uint8 const _instance, Driver::MsgQueue const _queue) + { + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Msg* msg = new Msg("SwitchBinaryCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(SwitchBinaryCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "SwitchBinaryCmd_Get Not Supported on this node"); + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool SwitchBinary::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if (SwitchBinaryCmd_Report == (SwitchBinaryCmd)_data[0]) - { - Log::Write( LogLevel_Info, GetNodeId(), "Received SwitchBinary report from node %d: level=%s", GetNodeId(), _data[1] ? "On" : "Off" ); + bool SwitchBinary::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) + { + if (SwitchBinaryCmd_Report == (SwitchBinaryCmd) _data[0]) + { + Log::Write(LogLevel_Info, GetNodeId(), "Received SwitchBinary report from node %d: level=%s", GetNodeId(), _data[1] ? "On" : "Off"); - // data[1] => Switch state - if( ValueBool* value = static_cast( GetValue( _instance, SwitchBinaryIndex_Level ) ) ) - { - value->OnValueRefreshed( _data[1] != 0 ); - value->Release(); - } + // data[1] => Switch state + if (Internal::VC::ValueBool* value = static_cast(GetValue(_instance, ValueID_Index_SwitchBinary::Level))) + { + value->OnValueRefreshed(_data[1] != 0); + value->Release(); + } - if ( GetVersion() >= 2) { + if (GetVersion() >= 2) + { - // data[2] => target state - if( ValueBool* value = static_cast( GetValue( _instance, SwitchBinaryIndex_TargetState ) ) ) - { - value->OnValueRefreshed( _data[2] != 0 ); - value->Release(); - } - - // data[3] might be duration - if (_length > 3) { - if ( ValueByte* value = static_cast( GetValue( _instance, SwitchBinaryIndex_Duration ) ) ) - { - value->OnValueRefreshed( _data[3] ); - value->Release(); - } - } - } + // data[2] => target state + if (Internal::VC::ValueBool* value = static_cast(GetValue(_instance, ValueID_Index_SwitchBinary::TargetState))) + { + value->OnValueRefreshed(_data[2] != 0); + value->Release(); + } + + // data[3] might be duration + if (_length > 3) + { + if (Internal::VC::ValueByte* value = static_cast(GetValue(_instance, ValueID_Index_SwitchBinary::Duration))) + { + value->OnValueRefreshed(_data[3]); + value->Release(); + } + } + } - return true; - } + return true; + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Set the state of the switch //----------------------------------------------------------------------------- -bool SwitchBinary::SetValue -( - Value const& _value -) -{ - bool res = false; - uint8 instance = _value.GetID().GetInstance(); - - switch( _value.GetID().GetIndex() ) - { - case SwitchBinaryIndex_Level: - { - if( ValueBool* value = static_cast( GetValue( instance, SwitchBinaryIndex_Level ) ) ) - { - res = SetState( instance, (static_cast(&_value))->GetValue() ); - value->Release(); - } - break; - } - case SwitchBinaryIndex_Duration: - { - if( ValueByte* value = static_cast( GetValue( instance, SwitchBinaryIndex_Duration ) ) ) + bool SwitchBinary::SetValue(Internal::VC::Value const& _value) { - value->OnValueRefreshed( (static_cast(&_value))->GetValue() ); - value->Release(); - } - res = true; - break; - } - - } + bool res = false; + uint8 instance = _value.GetID().GetInstance(); + + switch (_value.GetID().GetIndex()) + { + case ValueID_Index_SwitchBinary::Level: + { + if (Internal::VC::ValueBool* value = static_cast(GetValue(instance, ValueID_Index_SwitchBinary::Level))) + { + res = SetState(instance, (static_cast(&_value))->GetValue()); + value->Release(); + } + break; + } + case ValueID_Index_SwitchBinary::Duration: + { + if (Internal::VC::ValueByte* value = static_cast(GetValue(instance, ValueID_Index_SwitchBinary::Duration))) + { + value->OnValueRefreshed((static_cast(&_value))->GetValue()); + value->Release(); + } + res = true; + break; + } - return res; -} + } + + return res; + } //----------------------------------------------------------------------------- // // Update class values based in BASIC mapping //----------------------------------------------------------------------------- -void SwitchBinary::SetValueBasic -( - uint8 const _instance, - uint8 const _value -) -{ - // Send a request for new value to synchronize it with the BASIC set/report. - // In case the device is sleeping, we set the value anyway so the BASIC set/report - // stays in sync with it. We must be careful mapping the uint8 BASIC value - // into a class specific value. - // When the device wakes up, the real requested value will be retrieved. - RequestValue( 0, 0, _instance, Driver::MsgQueue_Send ); - if( Node* node = GetNodeUnsafe() ) - { - if( WakeUp* wakeUp = static_cast( node->GetCommandClass( WakeUp::StaticGetCommandClassId() ) ) ) - { - if( !wakeUp->IsAwake() ) + void SwitchBinary::SetValueBasic(uint8 const _instance, uint8 const _value) { - if( ValueBool* value = static_cast( GetValue( _instance, 0 ) ) ) + // Send a request for new value to synchronize it with the BASIC set/report. + // In case the device is sleeping, we set the value anyway so the BASIC set/report + // stays in sync with it. We must be careful mapping the uint8 BASIC value + // into a class specific value. + // When the device wakes up, the real requested value will be retrieved. + RequestValue(0, 0, _instance, Driver::MsgQueue_Send); + if (Node* node = GetNodeUnsafe()) { - value->OnValueRefreshed( _value != 0 ); - value->Release(); + if (Internal::CC::WakeUp* wakeUp = static_cast(node->GetCommandClass(Internal::CC::WakeUp::StaticGetCommandClassId()))) + { + if (!wakeUp->IsAwake()) + { + if (Internal::VC::ValueBool* value = static_cast(GetValue(_instance, 0))) + { + value->OnValueRefreshed(_value != 0); + value->Release(); + } + } + } } } - } - } -} //----------------------------------------------------------------------------- // // Set a new state for the switch //----------------------------------------------------------------------------- -bool SwitchBinary::SetState -( - uint8 const _instance, - bool const _state -) -{ - uint8 const nodeId = GetNodeId(); - uint8 const targetValue = _state ? 0xff : 0; + bool SwitchBinary::SetState(uint8 const _instance, bool const _state) + { + uint8 const nodeId = GetNodeId(); + uint8 const targetValue = _state ? 0xff : 0; - Log::Write( LogLevel_Info, nodeId, "SwitchBinary::Set - Setting to %s", _state ? "On" : "Off"); - Msg* msg = new Msg( "SwitchBinaryCmd_Set", nodeId, REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->SetInstance( this, _instance ); - msg->Append( nodeId ); - - if( GetVersion() >= 2 ) - { - ValueByte* durationValue = static_cast( GetValue( _instance, SwitchBinaryIndex_Duration ) ); - uint8 duration = durationValue->GetValue(); - durationValue->Release(); - if( duration == 0xff ) - { - Log::Write( LogLevel_Info, GetNodeId(), " Duration: Default" ); - } - else if( duration >= 0x80 ) - { - Log::Write( LogLevel_Info, GetNodeId(), " Duration: %d minutes", duration - 0x7f ); - } - else - { - Log::Write( LogLevel_Info, GetNodeId(), " Duration: %d seconds", duration ); - } + Log::Write(LogLevel_Info, nodeId, "SwitchBinary::Set - Setting to %s", _state ? "On" : "Off"); + Msg* msg = new Msg("SwitchBinaryCmd_Set", nodeId, REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->SetInstance(this, _instance); + msg->Append(nodeId); - msg->Append( 4 ); - msg->Append( GetCommandClassId() ); - msg->Append( SwitchBinaryCmd_Set ); - msg->Append( targetValue ); - msg->Append( duration ); - } - else - { - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( SwitchBinaryCmd_Set ); - msg->Append( targetValue ); - } + if (GetVersion() >= 2) + { + Internal::VC::ValueByte* durationValue = static_cast(GetValue(_instance, ValueID_Index_SwitchBinary::Duration)); + uint8 duration = durationValue->GetValue(); + durationValue->Release(); + if (duration == 0xff) + { + Log::Write(LogLevel_Info, GetNodeId(), " Duration: Default"); + } + else if (duration >= 0x80) + { + Log::Write(LogLevel_Info, GetNodeId(), " Duration: %d minutes", duration - 0x7f); + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), " Duration: %d seconds", duration); + } - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - return true; -} + msg->Append(4); + msg->Append(GetCommandClassId()); + msg->Append(SwitchBinaryCmd_Set); + msg->Append(targetValue); + msg->Append(duration); + } + else + { + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(SwitchBinaryCmd_Set); + msg->Append(targetValue); + } + + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return true; + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void SwitchBinary::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - switch( GetVersion() ) - { - case 2: + void SwitchBinary::CreateVars(uint8 const _instance) { - node->CreateValueByte( ValueID::ValueGenre_System, GetCommandClassId(), _instance, SwitchBinaryIndex_Duration, "Transition Duration", "", false, false, 0xff, 0 ); - node->CreateValueBool( ValueID::ValueGenre_System, GetCommandClassId(), _instance, SwitchBinaryIndex_TargetState, "Target State", "", true, false, true, 0 ); - // Fall through to version 1 - } - case 1: - { - node->CreateValueBool( ValueID::ValueGenre_User, GetCommandClassId(), _instance, SwitchBinaryIndex_Level, "Switch", "", false, false, false, 0 ); - break; + if (Node* node = GetNodeUnsafe()) + { + if (GetVersion() >= 2) + { + node->CreateValueByte(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_SwitchBinary::Duration, "Transition Duration", "", false, false, 0xff, 0); + node->CreateValueBool(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_SwitchBinary::TargetState, "Target State", "", true, false, true, 0); + } + node->CreateValueBool(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_SwitchBinary::Level, "Switch", "", false, false, false, 0); + } } - } - } -} + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/SwitchBinary.h b/cpp/src/command_classes/SwitchBinary.h index c686bd78cc..ff4fdb0104 100644 --- a/cpp/src/command_classes/SwitchBinary.h +++ b/cpp/src/command_classes/SwitchBinary.h @@ -32,39 +32,66 @@ namespace OpenZWave { - class ValueBool; - - /** \brief Implements COMMAND_CLASS_SWITCH_BINARY (0x25), a Z-Wave device command class. - * \ingroup CommandClass - */ - class SwitchBinary: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new SwitchBinary( _homeId, _nodeId ); } - virtual ~SwitchBinary(){} + namespace CC + { + + /** \brief Implements COMMAND_CLASS_SWITCH_BINARY (0x25), a Z-Wave device command class. + * \ingroup CommandClass + */ + class SwitchBinary: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new SwitchBinary(_homeId, _nodeId); + } + virtual ~SwitchBinary() + { + } - static uint8 const StaticGetCommandClassId(){ return 0x25; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_SWITCH_BINARY"; } + static uint8 const StaticGetCommandClassId() + { + return 0x25; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_SWITCH_BINARY"; + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool SetValue( Value const& _value ); - virtual void SetValueBasic( uint8 const _instance, uint8 const _value ); - bool SetState( uint8 const _instance, bool const _state ); + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool SetValue(Internal::VC::Value const& _value) override; + virtual void SetValueBasic(uint8 const _instance, uint8 const _value) override; + bool SetState(uint8 const _instance, bool const _state); - virtual uint8 GetMaxVersion(){ return 2; } - - protected: - virtual void CreateVars( uint8 const _instance ); + virtual uint8 GetMaxVersion() override + { + return 2; + } - private: - SwitchBinary( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} - }; + protected: + virtual void CreateVars(uint8 const _instance) override; + private: + SwitchBinary(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + } + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/SwitchMultilevel.cpp b/cpp/src/command_classes/SwitchMultilevel.cpp index 998829b7ac..8cee7be7e3 100644 --- a/cpp/src/command_classes/SwitchMultilevel.cpp +++ b/cpp/src/command_classes/SwitchMultilevel.cpp @@ -38,655 +38,576 @@ #include "value_classes/ValueButton.h" #include "value_classes/ValueByte.h" -using namespace OpenZWave; - -enum SwitchMultilevelCmd -{ - SwitchMultilevelCmd_Set = 0x01, - SwitchMultilevelCmd_Get = 0x02, - SwitchMultilevelCmd_Report = 0x03, - SwitchMultilevelCmd_StartLevelChange = 0x04, - SwitchMultilevelCmd_StopLevelChange = 0x05, - SwitchMultilevelCmd_SupportedGet = 0x06, - SwitchMultilevelCmd_SupportedReport = 0x07 -}; - -enum SwitchMultilevelIndex -{ - SwitchMultilevelIndex_Level = 0, - SwitchMultilevelIndex_Bright, - SwitchMultilevelIndex_Dim, - SwitchMultilevelIndex_IgnoreStartLevel, - SwitchMultilevelIndex_StartLevel, - SwitchMultilevelIndex_Duration, - SwitchMultilevelIndex_Step, - SwitchMultilevelIndex_Inc, - SwitchMultilevelIndex_Dec, - SwitchMultilevelIndex_TargetValue -}; - -static uint8 c_directionParams[] = +namespace OpenZWave { - 0x00, - 0x40, - 0x00, - 0x40 -}; + namespace Internal + { + namespace CC + { -static char const* c_directionDebugLabels[] = -{ - "Up", - "Down", - "Inc", - "Dec" -}; + enum SwitchMultilevelCmd + { + SwitchMultilevelCmd_Set = 0x01, + SwitchMultilevelCmd_Get = 0x02, + SwitchMultilevelCmd_Report = 0x03, + SwitchMultilevelCmd_StartLevelChange = 0x04, + SwitchMultilevelCmd_StopLevelChange = 0x05, + SwitchMultilevelCmd_SupportedGet = 0x06, + SwitchMultilevelCmd_SupportedReport = 0x07 + }; -static char const* c_switchLabelsPos[] = -{ - "Undefined", - "On", - "Up", - "Open", - "Clockwise", - "Right", - "Forward", - "Push" -}; - -static char const* c_switchLabelsNeg[] = -{ - "Undefined", - "Off", - "Down", - "Close", - "Counter-Clockwise", - "Left", - "Reverse", - "Pull" -}; + static uint8 c_directionParams[] = + { 0x00, 0x40, 0x00, 0x40 }; + + static char const* c_directionDebugLabels[] = + { "Up", "Down", "Inc", "Dec" }; + + static char const* c_switchLabelsPos[] = + { "Undefined", "On", "Up", "Open", "Clockwise", "Right", "Forward", "Push" }; + + static char const* c_switchLabelsNeg[] = + { "Undefined", "Off", "Down", "Close", "Counter-Clockwise", "Left", "Reverse", "Pull" }; //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool SwitchMultilevel::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _requestFlags & RequestFlag_Dynamic ) - { - return RequestValue( _requestFlags, 0, _instance, _queue ); - } + bool SwitchMultilevel::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_requestFlags & RequestFlag_Dynamic) + { + return RequestValue(_requestFlags, 0, _instance, _queue); + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool SwitchMultilevel::RequestValue -( - uint32 const _requestFlags, - uint16 const _index, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _index == SwitchMultilevelIndex_Level ) - { - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Msg* msg = new Msg( "SwitchMultilevelCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( SwitchMultilevelCmd_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "SwitchMultilevelCmd_Get Not Supported on this node"); - } - } - return false; -} - -bool SwitchMultilevel::HandleIncomingMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if ( SwitchMultilevelCmd_Set == (SwitchMultilevelCmd)_data[0] ) - { - Log::Write( LogLevel_Info, GetNodeId(), "Received SwitchMultiLevel Set: level=%d", _data[1] ); - return true; - } - else if ( SwitchMultilevelCmd_StartLevelChange == (SwitchMultilevelCmd)_data[0] ) - { - Log::Write( LogLevel_Info, GetNodeId(), "Received SwitchMultiLevel StartLevelChange: level=%d", _data[1] ); + bool SwitchMultilevel::RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_index == ValueID_Index_SwitchMultiLevel::Level) + { + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Msg* msg = new Msg("SwitchMultilevelCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(SwitchMultilevelCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "SwitchMultilevelCmd_Get Not Supported on this node"); + } + } + return false; + } - } - else if ( SwitchMultilevelCmd_StopLevelChange == (SwitchMultilevelCmd)_data[0] ) - { - Log::Write( LogLevel_Info, GetNodeId(), "Received SwitchMultiLevel StopLevelChange: level=%d", _data[1] ); + bool SwitchMultilevel::HandleIncomingMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) + { + if (SwitchMultilevelCmd_Set == (SwitchMultilevelCmd) _data[0]) + { + Log::Write(LogLevel_Info, GetNodeId(), "Received SwitchMultiLevel Set: level=%d", _data[1]); + return true; + } + else if (SwitchMultilevelCmd_StartLevelChange == (SwitchMultilevelCmd) _data[0]) + { + Log::Write(LogLevel_Info, GetNodeId(), "Received SwitchMultiLevel StartLevelChange: level=%d", _data[1]); - } + } + else if (SwitchMultilevelCmd_StopLevelChange == (SwitchMultilevelCmd) _data[0]) + { + Log::Write(LogLevel_Info, GetNodeId(), "Received SwitchMultiLevel StopLevelChange: level=%d", _data[1]); - return true; -} + } + return true; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool SwitchMultilevel::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if( SwitchMultilevelCmd_Report == (SwitchMultilevelCmd)_data[0] ) - { - Log::Write( LogLevel_Info, GetNodeId(), "Received SwitchMultiLevel report: level=%d", _data[1] ); - - if( ValueByte* value = static_cast( GetValue( _instance, SwitchMultilevelIndex_Level ) ) ) - { - value->OnValueRefreshed( _data[1] ); - value->Release(); - } - - if( GetVersion() >= 4) { - - // data[2] => target value - if( ValueByte* value = static_cast( GetValue( _instance, SwitchMultilevelIndex_TargetValue ) ) ) + bool SwitchMultilevel::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) { - value->OnValueRefreshed( _data[2]); - value->Release(); - } - - // data[3] might be duration - if(_length > 3) { - if( ValueByte* value = static_cast( GetValue( _instance, SwitchMultilevelIndex_Duration ) ) ) + if (SwitchMultilevelCmd_Report == (SwitchMultilevelCmd) _data[0]) { - value->OnValueRefreshed( _data[3] ); - value->Release(); + Log::Write(LogLevel_Info, GetNodeId(), "Received SwitchMultiLevel report: level=%d", _data[1]); + + if (Internal::VC::ValueByte* value = static_cast(GetValue(_instance, ValueID_Index_SwitchMultiLevel::Level))) + { + value->OnValueRefreshed(_data[1]); + value->Release(); + } + + if (GetVersion() >= 4) + { + + // data[2] => target value + if (Internal::VC::ValueByte* value = static_cast(GetValue(_instance, ValueID_Index_SwitchMultiLevel::TargetValue))) + { + value->OnValueRefreshed(_data[2]); + value->Release(); + } + + // data[3] might be duration + if (_length > 3) + { + if (Internal::VC::ValueByte* value = static_cast(GetValue(_instance, ValueID_Index_SwitchMultiLevel::Duration))) + { + value->OnValueRefreshed(_data[3]); + value->Release(); + } + } + } + + return true; } - } - } - - return true; - } - - if( SwitchMultilevelCmd_SupportedReport == (SwitchMultilevelCmd)_data[0] ) - { - uint8 switchType1 = _data[1] & 0x1f; - uint8 switchType2 = _data[2] & 0x1f; - uint8 switchtype1label = switchType1; - uint8 switchtype2label = switchType2; - if (switchtype1label > 7) /* size of c_switchLabelsPos, c_switchLabelsNeg */ - { - Log::Write (LogLevel_Warning, GetNodeId(), "switchtype1label Value was greater than range. Setting to Invalid"); - switchtype1label = 0; - } - if (switchtype2label > 7) /* sizeof c_switchLabelsPos, c_switchLabelsNeg */ - { - Log::Write (LogLevel_Warning, GetNodeId(), "switchtype2label Value was greater than range. Setting to Invalid"); - switchtype2label = 0; - } - - - Log::Write( LogLevel_Info, GetNodeId(), "Received SwitchMultiLevel supported report: Switch1=%s/%s, Switch2=%s/%s", c_switchLabelsPos[switchtype1label], c_switchLabelsNeg[switchtype1label], c_switchLabelsPos[switchtype2label], c_switchLabelsNeg[switchtype2label] ); - ClearStaticRequest( StaticRequest_Version ); - - // Set the labels on the values - ValueButton* button; - if( switchType1 ) - { - if( NULL != ( button = static_cast( GetValue( _instance, SwitchMultilevelIndex_Bright ) ) ) ) - { - button->SetLabel( c_switchLabelsPos[switchtype1label] ); - button->Release(); - } - if( NULL != ( button = static_cast( GetValue( _instance, SwitchMultilevelIndex_Dim ) ) ) ) - { - button->SetLabel( c_switchLabelsNeg[switchtype1label] ); - button->Release(); - } - } + if (SwitchMultilevelCmd_SupportedReport == (SwitchMultilevelCmd) _data[0]) + { + uint8 switchType1 = _data[1] & 0x1f; + uint8 switchType2 = _data[2] & 0x1f; + uint8 switchtype1label = switchType1; + uint8 switchtype2label = switchType2; + if (switchtype1label > 7) /* size of c_switchLabelsPos, c_switchLabelsNeg */ + { + Log::Write(LogLevel_Warning, GetNodeId(), "switchtype1label Value was greater than range. Setting to Invalid"); + switchtype1label = 0; + } + if (switchtype2label > 7) /* sizeof c_switchLabelsPos, c_switchLabelsNeg */ + { + Log::Write(LogLevel_Warning, GetNodeId(), "switchtype2label Value was greater than range. Setting to Invalid"); + switchtype2label = 0; + } + + Log::Write(LogLevel_Info, GetNodeId(), "Received SwitchMultiLevel supported report: Switch1=%s/%s, Switch2=%s/%s", c_switchLabelsPos[switchtype1label], c_switchLabelsNeg[switchtype1label], c_switchLabelsPos[switchtype2label], c_switchLabelsNeg[switchtype2label]); + ClearStaticRequest(StaticRequest_Version); + + // Set the labels on the values + Internal::VC::ValueButton* button; + + if (switchType1) + { + if ( NULL != (button = static_cast(GetValue(_instance, ValueID_Index_SwitchMultiLevel::Bright)))) + { + button->SetLabel(c_switchLabelsPos[switchtype1label]); + button->Release(); + } + if ( NULL != (button = static_cast(GetValue(_instance, ValueID_Index_SwitchMultiLevel::Dim)))) + { + button->SetLabel(c_switchLabelsNeg[switchtype1label]); + button->Release(); + } + } + + if (switchType2) + { + if ( NULL != (button = static_cast(GetValue(_instance, ValueID_Index_SwitchMultiLevel::Inc)))) + { + button->SetLabel(c_switchLabelsPos[switchtype2label]); + button->Release(); + } + if ( NULL != (button = static_cast(GetValue(_instance, ValueID_Index_SwitchMultiLevel::Dec)))) + { + button->SetLabel(c_switchLabelsNeg[switchtype2label]); + button->Release(); + } + } + return true; + } - if( switchType2 ) - { - if( NULL != ( button = static_cast( GetValue( _instance, SwitchMultilevelIndex_Inc ) ) ) ) - { - button->SetLabel( c_switchLabelsPos[switchtype2label] ); - button->Release(); + return false; } - if( NULL != ( button = static_cast( GetValue( _instance, SwitchMultilevelIndex_Dec ) ) ) ) - { - button->SetLabel( c_switchLabelsNeg[switchtype2label] ); - button->Release(); - } - } - return true; - } - - return false; -} //----------------------------------------------------------------------------- // // Set the command class version //----------------------------------------------------------------------------- -void SwitchMultilevel::SetVersion -( - uint8 const _version -) -{ - CommandClass::SetVersion( _version ); + void SwitchMultilevel::SetVersion(uint8 const _version) + { + CommandClass::SetVersion(_version); - if( _version >= 3 ) - { - // Request the supported switch types - Msg* msg = new Msg( "SwitchMultilevelCmd_SupportedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( SwitchMultilevelCmd_SupportedGet ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - - // Set the request flag again - it will be cleared when we get a - // response to the SwitchMultilevelCmd_SupportedGet message. - SetStaticRequest( StaticRequest_Version ); - } -} + if (_version >= 3) + { + // Request the supported switch types + Msg* msg = new Msg("SwitchMultilevelCmd_SupportedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(SwitchMultilevelCmd_SupportedGet); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + + // Set the request flag again - it will be cleared when we get a + // response to the SwitchMultilevelCmd_SupportedGet message. + SetStaticRequest(StaticRequest_Version); + } + } //----------------------------------------------------------------------------- // // Set the level on a device //----------------------------------------------------------------------------- -bool SwitchMultilevel::SetValue -( - Value const& _value -) -{ - bool res = false; - uint8 instance = _value.GetID().GetInstance(); - - switch( _value.GetID().GetIndex() ) - { - case SwitchMultilevelIndex_Level: - { - // Level - if( ValueByte* value = static_cast( GetValue( instance, SwitchMultilevelIndex_Level ) ) ) - { - res = SetLevel( instance, (static_cast(&_value))->GetValue() ); - value->Release(); - } - break; - } - case SwitchMultilevelIndex_Bright: - { - // Bright - if( ValueButton* button = static_cast( GetValue( instance, SwitchMultilevelIndex_Bright ) ) ) - { - if( button->IsPressed() ) - { - res = StartLevelChange( instance, SwitchMultilevelDirection_Up ); - } - else - { - res = StopLevelChange( instance ); - } - button->Release(); - } - break; - } - case SwitchMultilevelIndex_Dim: - { - // Dim - if( ValueButton* button = static_cast( GetValue( instance, SwitchMultilevelIndex_Dim ) ) ) - { - if( button->IsPressed() ) - { - res = StartLevelChange( instance, SwitchMultilevelDirection_Down ); - } - else - { - res = StopLevelChange( instance ); - } - button->Release(); - } - break; - } - case SwitchMultilevelIndex_IgnoreStartLevel: - { - if( ValueBool* value = static_cast( GetValue( instance, SwitchMultilevelIndex_IgnoreStartLevel ) ) ) + bool SwitchMultilevel::SetValue(Internal::VC::Value const& _value) { - value->OnValueRefreshed( (static_cast( &_value))->GetValue() ); - value->Release(); - } - res = true; - break; - } - case SwitchMultilevelIndex_StartLevel: - { - if( ValueByte* value = static_cast( GetValue( instance, SwitchMultilevelIndex_StartLevel ) ) ) - { - value->OnValueRefreshed( (static_cast( &_value))->GetValue() ); - value->Release(); - } - res = true; - break; - } - case SwitchMultilevelIndex_Duration: - { - if( ValueByte* value = static_cast( GetValue( instance, SwitchMultilevelIndex_Duration ) ) ) - { - value->OnValueRefreshed( (static_cast( &_value))->GetValue() ); - value->Release(); - } - res = true; - break; - } - case SwitchMultilevelIndex_Step: - { - if( ValueByte* value = static_cast( GetValue( instance, SwitchMultilevelIndex_Step ) ) ) - { - value->OnValueRefreshed( (static_cast( &_value))->GetValue() ); - value->Release(); - } - res = true; - break; - } - case SwitchMultilevelIndex_Inc: - { - // Inc - if( ValueButton* button = static_cast( GetValue( instance, SwitchMultilevelIndex_Inc ) ) ) - { - if( button->IsPressed() ) - { - res = StartLevelChange( instance, SwitchMultilevelDirection_Inc ); - } - else - { - res = StopLevelChange( instance ); - } - button->Release(); - } - break; - } - case SwitchMultilevelIndex_Dec: - { - // Dec - if( ValueButton* button = static_cast( GetValue( instance, SwitchMultilevelIndex_Dec ) ) ) - { - if( button->IsPressed() ) - { - res = StartLevelChange( instance, SwitchMultilevelDirection_Dec ); - } - else + bool res = false; + uint8 instance = _value.GetID().GetInstance(); + + switch (_value.GetID().GetIndex()) { - res = StopLevelChange( instance ); + case ValueID_Index_SwitchMultiLevel::Level: + { + // Level + if (Internal::VC::ValueByte* value = static_cast(GetValue(instance, ValueID_Index_SwitchMultiLevel::Level))) + { + res = SetLevel(instance, (static_cast(&_value))->GetValue()); + value->Release(); + } + break; + } + case ValueID_Index_SwitchMultiLevel::Bright: + { + // Bright + if (Internal::VC::ValueButton* button = static_cast(GetValue(instance, ValueID_Index_SwitchMultiLevel::Bright))) + { + if (button->IsPressed()) + { + res = StartLevelChange(instance, SwitchMultilevelDirection_Up); + } + else + { + res = StopLevelChange(instance); + } + button->Release(); + } + break; + } + case ValueID_Index_SwitchMultiLevel::Dim: + { + // Dim + if (Internal::VC::ValueButton* button = static_cast(GetValue(instance, ValueID_Index_SwitchMultiLevel::Dim))) + { + if (button->IsPressed()) + { + res = StartLevelChange(instance, SwitchMultilevelDirection_Down); + } + else + { + res = StopLevelChange(instance); + } + button->Release(); + } + break; + } + case ValueID_Index_SwitchMultiLevel::IgnoreStartLevel: + { + if (Internal::VC::ValueBool* value = static_cast(GetValue(instance, ValueID_Index_SwitchMultiLevel::IgnoreStartLevel))) + { + value->OnValueRefreshed((static_cast(&_value))->GetValue()); + value->Release(); + } + res = true; + break; + } + case ValueID_Index_SwitchMultiLevel::StartLevel: + { + if (Internal::VC::ValueByte* value = static_cast(GetValue(instance, ValueID_Index_SwitchMultiLevel::StartLevel))) + { + value->OnValueRefreshed((static_cast(&_value))->GetValue()); + value->Release(); + } + res = true; + break; + } + case ValueID_Index_SwitchMultiLevel::Duration: + { + if (Internal::VC::ValueByte* value = static_cast(GetValue(instance, ValueID_Index_SwitchMultiLevel::Duration))) + { + value->OnValueRefreshed((static_cast(&_value))->GetValue()); + value->Release(); + } + res = true; + break; + } + case ValueID_Index_SwitchMultiLevel::Step: + { + if (Internal::VC::ValueByte* value = static_cast(GetValue(instance, ValueID_Index_SwitchMultiLevel::Step))) + { + value->OnValueRefreshed((static_cast(&_value))->GetValue()); + value->Release(); + } + res = true; + break; + } + case ValueID_Index_SwitchMultiLevel::Inc: + { + // Inc + if (Internal::VC::ValueButton* button = static_cast(GetValue(instance, ValueID_Index_SwitchMultiLevel::Inc))) + { + if (button->IsPressed()) + { + res = StartLevelChange(instance, SwitchMultilevelDirection_Inc); + } + else + { + res = StopLevelChange(instance); + } + button->Release(); + } + break; + } + case ValueID_Index_SwitchMultiLevel::Dec: + { + // Dec + if (Internal::VC::ValueButton* button = static_cast(GetValue(instance, ValueID_Index_SwitchMultiLevel::Dec))) + { + if (button->IsPressed()) + { + res = StartLevelChange(instance, SwitchMultilevelDirection_Dec); + } + else + { + res = StopLevelChange(instance); + } + button->Release(); + } + break; + } } - button->Release(); - } - break; - } - } - return res; -} + return res; + } //----------------------------------------------------------------------------- // // Update class values based in BASIC mapping //----------------------------------------------------------------------------- -void SwitchMultilevel::SetValueBasic -( - uint8 const _instance, - uint8 const _value -) -{ - // Send a request for new value to synchronize it with the BASIC set/report. - // In case the device is sleeping, we set the value anyway so the BASIC set/report - // stays in sync with it. We must be careful mapping the uint8 BASIC value - // into a class specific value. - // When the device wakes up, the real requested value will be retrieved. - RequestValue( 0, 0, _instance, Driver::MsgQueue_Send ); - if( Node* node = GetNodeUnsafe() ) - { - if( WakeUp* wakeUp = static_cast( node->GetCommandClass( WakeUp::StaticGetCommandClassId() ) ) ) - { - if( !wakeUp->IsAwake() ) + void SwitchMultilevel::SetValueBasic(uint8 const _instance, uint8 const _value) { - if( ValueByte* value = static_cast( GetValue( _instance, SwitchMultilevelIndex_Level ) ) ) + // Send a request for new value to synchronize it with the BASIC set/report. + // In case the device is sleeping, we set the value anyway so the BASIC set/report + // stays in sync with it. We must be careful mapping the uint8 BASIC value + // into a class specific value. + // When the device wakes up, the real requested value will be retrieved. + RequestValue(0, 0, _instance, Driver::MsgQueue_Send); + if (Node* node = GetNodeUnsafe()) { - value->OnValueRefreshed( _value != 0 ); - value->Release(); + if (Internal::CC::WakeUp* wakeUp = static_cast(node->GetCommandClass(Internal::CC::WakeUp::StaticGetCommandClassId()))) + { + if (!wakeUp->IsAwake()) + { + if (Internal::VC::ValueByte* value = static_cast(GetValue(_instance, ValueID_Index_SwitchMultiLevel::Level))) + { + value->OnValueRefreshed(_value != 0); + value->Release(); + } + } + } } } - } - } -} //----------------------------------------------------------------------------- // // Set a new level for the switch //----------------------------------------------------------------------------- -bool SwitchMultilevel::SetLevel -( - uint8 const _instance, - uint8 const _level -) -{ - Log::Write( LogLevel_Info, GetNodeId(), "SwitchMultilevel::Set - Setting to level %d", _level ); - Msg* msg = new Msg( "SwitchMultilevelCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); + bool SwitchMultilevel::SetLevel(uint8 const _instance, uint8 const _level) + { + Log::Write(LogLevel_Info, GetNodeId(), "SwitchMultilevel::Set - Setting to level %d", _level); + Msg* msg = new Msg("SwitchMultilevelCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); - if( GetVersion() >= 2 ) - { - ValueByte* durationValue = static_cast( GetValue( _instance, SwitchMultilevelIndex_Duration ) ); - uint8 duration = durationValue->GetValue(); - durationValue->Release(); - if( duration == 0xff ) - { - Log::Write( LogLevel_Info, GetNodeId(), " Duration: Default" ); - } - else if( duration >= 0x80 ) - { - Log::Write( LogLevel_Info, GetNodeId(), " Duration: %d minutes", duration - 0x7f ); - } - else - { - Log::Write( LogLevel_Info, GetNodeId(), " Duration: %d seconds", duration ); - } - - msg->Append( 4 ); - msg->Append( GetCommandClassId() ); - msg->Append( SwitchMultilevelCmd_Set ); - msg->Append( _level ); - msg->Append( duration ); - } - else - { - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( SwitchMultilevelCmd_Set ); - msg->Append( _level ); - } + if (GetVersion() >= 2) + { + Internal::VC::ValueByte* durationValue = static_cast(GetValue(_instance, ValueID_Index_SwitchMultiLevel::Duration)); + uint8 duration = durationValue->GetValue(); + durationValue->Release(); + if (duration == 0xff) + { + Log::Write(LogLevel_Info, GetNodeId(), " Duration: Default"); + } + else if (duration >= 0x80) + { + Log::Write(LogLevel_Info, GetNodeId(), " Duration: %d minutes", duration - 0x7f); + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), " Duration: %d seconds", duration); + } + + msg->Append(4); + msg->Append(GetCommandClassId()); + msg->Append(SwitchMultilevelCmd_Set); + msg->Append(_level); + msg->Append(duration); + } + else + { + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(SwitchMultilevelCmd_Set); + msg->Append(_level); + } - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - return true; -} + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return true; + } //----------------------------------------------------------------------------- // // Start the level changing //----------------------------------------------------------------------------- -bool SwitchMultilevel::StartLevelChange -( - uint8 const _instance, - SwitchMultilevelDirection const _direction -) -{ - Log::Write( LogLevel_Info, GetNodeId(), "SwitchMultilevel::StartLevelChange - Starting a level change" ); + bool SwitchMultilevel::StartLevelChange(uint8 const _instance, SwitchMultilevelDirection const _direction) + { + Log::Write(LogLevel_Info, GetNodeId(), "SwitchMultilevel::StartLevelChange - Starting a level change"); - uint8 length = 4; - if (_direction > 3) /* size of c_directionParams, c_directionDebugLabels */ - { - Log::Write (LogLevel_Warning, GetNodeId(), "_direction Value was greater than range. Dropping"); - return false; - } - uint8 direction = c_directionParams[_direction]; - Log::Write( LogLevel_Info, GetNodeId(), " Direction: %s", c_directionDebugLabels[_direction] ); + uint8 length = 4; + if (_direction > 3) /* size of c_directionParams, c_directionDebugLabels */ + { + Log::Write(LogLevel_Warning, GetNodeId(), "_direction Value was greater than range. Dropping"); + return false; + } + uint8 direction = c_directionParams[_direction]; + Log::Write(LogLevel_Info, GetNodeId(), " Direction: %s", c_directionDebugLabels[_direction]); - if( ValueBool* ignoreStartLevel = static_cast( GetValue( _instance, SwitchMultilevelIndex_IgnoreStartLevel ) ) ) - { - if( ignoreStartLevel->GetValue() ) - { - // Set the ignore start level flag - direction |= 0x20; - } - ignoreStartLevel->Release(); - } - Log::Write( LogLevel_Info, GetNodeId(), " Ignore Start Level: %s", (direction & 0x20) ? "True" : "False" ); - - uint8 startLevel = 0; - if( ValueByte* startLevelValue = static_cast( GetValue( _instance, SwitchMultilevelIndex_StartLevel ) ) ) - { - startLevel = startLevelValue->GetValue(); - startLevelValue->Release(); - } - Log::Write( LogLevel_Info, GetNodeId(), " Start Level: %d", startLevel ); + if (Internal::VC::ValueBool* ignoreStartLevel = static_cast(GetValue(_instance, ValueID_Index_SwitchMultiLevel::IgnoreStartLevel))) + { + if (ignoreStartLevel->GetValue()) + { + // Set the ignore start level flag + direction |= 0x20; + } + ignoreStartLevel->Release(); + } + Log::Write(LogLevel_Info, GetNodeId(), " Ignore Start Level: %s", (direction & 0x20) ? "True" : "False"); - uint8 duration = 0; - if( ValueByte* durationValue = static_cast( GetValue( _instance, SwitchMultilevelIndex_Duration ) ) ) - { - length = 5; - duration = durationValue->GetValue(); - durationValue->Release(); - Log::Write( LogLevel_Info, GetNodeId(), " Duration: %d", duration ); - } - - uint8 step = 0; - if( ( SwitchMultilevelDirection_Inc == _direction ) || ( SwitchMultilevelDirection_Dec == _direction ) ) - { - if( ValueByte* stepValue = static_cast( GetValue( _instance, SwitchMultilevelIndex_Step ) ) ) - { - length = 6; - step = stepValue->GetValue(); - stepValue->Release(); - Log::Write( LogLevel_Info, GetNodeId(), " Step Size: %d", step ); - } - } - - Msg* msg = new Msg( "SwitchMultilevelCmd_StartLevelChange", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( length ); - msg->Append( GetCommandClassId() ); - msg->Append( SwitchMultilevelCmd_StartLevelChange ); - if (GetVersion() == 2) { - direction &= 0x60; - } else if (GetVersion() >= 3) { - /* we don't support secondary switch, so we mask that out as well */ - direction &= 0xE0; - } - - msg->Append( direction ); - msg->Append( startLevel ); - - if( length >= 5 ) - { - msg->Append( duration ); - } + uint8 startLevel = 0; + if (Internal::VC::ValueByte* startLevelValue = static_cast(GetValue(_instance, ValueID_Index_SwitchMultiLevel::StartLevel))) + { + startLevel = startLevelValue->GetValue(); + startLevelValue->Release(); + } + Log::Write(LogLevel_Info, GetNodeId(), " Start Level: %d", startLevel); - if( length == 6 ) - { - msg->Append( step ); - } + uint8 duration = 0; + if (Internal::VC::ValueByte* durationValue = static_cast(GetValue(_instance, ValueID_Index_SwitchMultiLevel::Duration))) + { + length = 5; + duration = durationValue->GetValue(); + durationValue->Release(); + Log::Write(LogLevel_Info, GetNodeId(), " Duration: %d", duration); + } + + uint8 step = 0; + if ((SwitchMultilevelDirection_Inc == _direction) || (SwitchMultilevelDirection_Dec == _direction)) + { + if (Internal::VC::ValueByte* stepValue = static_cast(GetValue(_instance, ValueID_Index_SwitchMultiLevel::Step))) + { + length = 6; + step = stepValue->GetValue(); + stepValue->Release(); + Log::Write(LogLevel_Info, GetNodeId(), " Step Size: %d", step); + } + } + + Msg* msg = new Msg("SwitchMultilevelCmd_StartLevelChange", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(length); + msg->Append(GetCommandClassId()); + msg->Append(SwitchMultilevelCmd_StartLevelChange); + if (GetVersion() == 2) + { + direction &= 0x60; + } + else if (GetVersion() >= 3) + { + /* we don't support secondary switch, so we mask that out as well */ + direction &= 0xE0; + } + + msg->Append(direction); + msg->Append(startLevel); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - return true; -} + if (length >= 5) + { + msg->Append(duration); + } + + if (length == 6) + { + msg->Append(step); + } + + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + /* get a updated Level Value from the Device */ + RequestValue(0, ValueID_Index_SwitchMultiLevel::Level, _instance, Driver::MsgQueue_Send); + return true; + } //----------------------------------------------------------------------------- // // Stop the level changing //----------------------------------------------------------------------------- -bool SwitchMultilevel::StopLevelChange -( - uint8 const _instance -) -{ - Log::Write( LogLevel_Info, GetNodeId(), "SwitchMultilevel::StopLevelChange - Stopping the level change" ); - Msg* msg = new Msg( "SwitchMultilevelCmd_StopLevelChange", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( SwitchMultilevelCmd_StopLevelChange ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - return true; -} + bool SwitchMultilevel::StopLevelChange(uint8 const _instance) + { + Log::Write(LogLevel_Info, GetNodeId(), "SwitchMultilevel::StopLevelChange - Stopping the level change"); + Msg* msg = new Msg("SwitchMultilevelCmd_StopLevelChange", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(SwitchMultilevelCmd_StopLevelChange); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + + /* get a updated Level Value from the Device */ + RequestValue(0, ValueID_Index_SwitchMultiLevel::Level, _instance, Driver::MsgQueue_Send); + return true; + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void SwitchMultilevel::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - switch( GetVersion() ) - { - case 4: - { - node->CreateValueByte( ValueID::ValueGenre_System, GetCommandClassId(), _instance, SwitchMultilevelIndex_TargetValue, "Target Value", "", true, false, 0, 0 ); - // Fall through to version 3 - } - case 3: + void SwitchMultilevel::CreateVars(uint8 const _instance) { - node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, SwitchMultilevelIndex_Step, "Step Size", "", false, false, 0, 0 ); - node->CreateValueButton( ValueID::ValueGenre_User, GetCommandClassId(), _instance, SwitchMultilevelIndex_Inc, "Inc", 0 ); - node->CreateValueButton( ValueID::ValueGenre_User, GetCommandClassId(), _instance, SwitchMultilevelIndex_Dec, "Dec", 0 ); - // Fall through to version 2 - } - case 2: - { - node->CreateValueByte( ValueID::ValueGenre_System, GetCommandClassId(), _instance, SwitchMultilevelIndex_Duration, "Dimming Duration", "", false, false, 0xff, 0 ); - // Fall through to version 1 - } - case 1: - { - node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, SwitchMultilevelIndex_Level, "Level", "", false, false, 0, 0 ); - node->CreateValueButton( ValueID::ValueGenre_User, GetCommandClassId(), _instance, SwitchMultilevelIndex_Bright, "Bright", 0 ); - node->CreateValueButton( ValueID::ValueGenre_User, GetCommandClassId(), _instance, SwitchMultilevelIndex_Dim, "Dim", 0 ); - node->CreateValueBool( ValueID::ValueGenre_System, GetCommandClassId(), _instance, SwitchMultilevelIndex_IgnoreStartLevel, "Ignore Start Level", "", false, false, true, 0 ); - node->CreateValueByte( ValueID::ValueGenre_System, GetCommandClassId(), _instance, SwitchMultilevelIndex_StartLevel, "Start Level", "", false, false, 0, 0 ); - break; + if (Node* node = GetNodeUnsafe()) + { + if (GetVersion() >= 4) + { + node->CreateValueByte(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_SwitchMultiLevel::TargetValue, "Target Value", "", true, false, 0, 0); + } + if (GetVersion() >= 3) + { + node->CreateValueByte(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_SwitchMultiLevel::Step, "Step Size", "", false, false, 0, 0); + node->CreateValueButton(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_SwitchMultiLevel::Inc, "Inc", 0); + node->CreateValueButton(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_SwitchMultiLevel::Dec, "Dec", 0); + } + if (GetVersion() >= 2) + { + node->CreateValueByte(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_SwitchMultiLevel::Duration, "Dimming Duration", "", false, false, 0xff, 0); + } + node->CreateValueByte(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_SwitchMultiLevel::Level, "Level", "", false, false, 0, 0); + node->CreateValueButton(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_SwitchMultiLevel::Bright, "Bright", 0); + node->CreateValueButton(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_SwitchMultiLevel::Dim, "Dim", 0); + node->CreateValueBool(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_SwitchMultiLevel::IgnoreStartLevel, "Ignore Start Level", "", false, false, true, 0); + node->CreateValueByte(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_SwitchMultiLevel::StartLevel, "Start Level", "", false, false, 0, 0); + } } - } - } -} - - + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/SwitchMultilevel.h b/cpp/src/command_classes/SwitchMultilevel.h index 8b52133c63..9c784fcb39 100644 --- a/cpp/src/command_classes/SwitchMultilevel.h +++ b/cpp/src/command_classes/SwitchMultilevel.h @@ -32,54 +32,79 @@ namespace OpenZWave { - class ValueBool; - class ValueButton; - class ValueByte; - - /** \brief Implements COMMAND_CLASS_SWITCH_MULTILEVEL (0x26), a Z-Wave device command class. - * \ingroup CommandClass - */ - class SwitchMultilevel: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new SwitchMultilevel( _homeId, _nodeId ); } - virtual ~SwitchMultilevel(){} + namespace CC + { - static uint8 const StaticGetCommandClassId(){ return 0x26; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_SWITCH_MULTILEVEL"; } + /** \brief Implements COMMAND_CLASS_SWITCH_MULTILEVEL (0x26), a Z-Wave device command class. + * \ingroup CommandClass + */ + class SwitchMultilevel: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new SwitchMultilevel(_homeId, _nodeId); + } + virtual ~SwitchMultilevel() + { + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool HandleIncomingMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool SetValue( Value const& _value ); - virtual void SetValueBasic( uint8 const _instance, uint8 const _value ); - virtual void SetVersion( uint8 const _version ); + static uint8 const StaticGetCommandClassId() + { + return 0x26; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_SWITCH_MULTILEVEL"; + } - virtual uint8 GetMaxVersion(){ return 4; } + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool HandleIncomingMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool SetValue(Internal::VC::Value const& _value) override; + virtual void SetValueBasic(uint8 const _instance, uint8 const _value) override; + virtual void SetVersion(uint8 const _version) override; - protected: - virtual void CreateVars( uint8 const _instance ); + virtual uint8 GetMaxVersion() override + { + return 4; + } - private: - enum SwitchMultilevelDirection - { - SwitchMultilevelDirection_Up = 0, - SwitchMultilevelDirection_Down, - SwitchMultilevelDirection_Inc, - SwitchMultilevelDirection_Dec - }; + protected: + virtual void CreateVars(uint8 const _instance) override; - SwitchMultilevel( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} + private: + enum SwitchMultilevelDirection + { + SwitchMultilevelDirection_Up = 0, + SwitchMultilevelDirection_Down, + SwitchMultilevelDirection_Inc, + SwitchMultilevelDirection_Dec + }; - bool SetLevel( uint8 const _instance, uint8 const _level ); - bool StartLevelChange( uint8 const _instance, SwitchMultilevelDirection const _direction ); - bool StopLevelChange( uint8 const _instance ); - }; + SwitchMultilevel(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + } + bool SetLevel(uint8 const _instance, uint8 const _level); + bool StartLevelChange(uint8 const _instance, SwitchMultilevelDirection const _direction); + bool StopLevelChange(uint8 const _instance); + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/SwitchToggleBinary.cpp b/cpp/src/command_classes/SwitchToggleBinary.cpp index 860e2dea4c..7498328663 100644 --- a/cpp/src/command_classes/SwitchToggleBinary.cpp +++ b/cpp/src/command_classes/SwitchToggleBinary.cpp @@ -35,123 +35,112 @@ #include "value_classes/ValueBool.h" -using namespace OpenZWave; - -enum SwitchToggleBinaryCmd +namespace OpenZWave { - SwitchToggleBinaryCmd_Set = 0x01, - SwitchToggleBinaryCmd_Get = 0x02, - SwitchToggleBinaryCmd_Report = 0x03 -}; + namespace Internal + { + namespace CC + { + + enum SwitchToggleBinaryCmd + { + SwitchToggleBinaryCmd_Set = 0x01, + SwitchToggleBinaryCmd_Get = 0x02, + SwitchToggleBinaryCmd_Report = 0x03 + }; //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool SwitchToggleBinary::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _requestFlags & RequestFlag_Dynamic ) - { - return RequestValue( _requestFlags, 0, _instance, _queue ); - } + bool SwitchToggleBinary::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_requestFlags & RequestFlag_Dynamic) + { + return RequestValue(_requestFlags, 0, _instance, _queue); + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool SwitchToggleBinary::RequestValue -( - uint32 const _requestFlags, - uint16 const _dummy1, // = 0 (not used) - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Msg* msg = new Msg( "SwitchToggleBinaryCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( SwitchToggleBinaryCmd_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "SwitchToggleBinaryCmd_Get Not Supported on this node"); - } - return false; -} + bool SwitchToggleBinary::RequestValue(uint32 const _requestFlags, uint16 const _dummy1, // = 0 (not used) + uint8 const _instance, Driver::MsgQueue const _queue) + { + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Msg* msg = new Msg("SwitchToggleBinaryCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(SwitchToggleBinaryCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "SwitchToggleBinaryCmd_Get Not Supported on this node"); + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool SwitchToggleBinary::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if( SwitchToggleBinaryCmd_Report == (SwitchToggleBinaryCmd)_data[0] ) - { - Log::Write( LogLevel_Info, GetNodeId(), "Received SwitchToggleBinary report: %s", _data[1] ? "On" : "Off" ); + bool SwitchToggleBinary::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) + { + if (SwitchToggleBinaryCmd_Report == (SwitchToggleBinaryCmd) _data[0]) + { + Log::Write(LogLevel_Info, GetNodeId(), "Received SwitchToggleBinary report: %s", _data[1] ? "On" : "Off"); - if( ValueBool* value = static_cast( GetValue( _instance, 0 ) ) ) - { - value->OnValueRefreshed( _data[1] != 0 ); - value->Release(); - } - return true; - } + if (Internal::VC::ValueBool* value = static_cast(GetValue(_instance, ValueID_Index_SwitchToggleBinary::ToggleSwitch))) + { + value->OnValueRefreshed(_data[1] != 0); + value->Release(); + } + return true; + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Toggle the state of the switch //----------------------------------------------------------------------------- -bool SwitchToggleBinary::SetValue -( - Value const& _value -) -{ - Log::Write( LogLevel_Info, GetNodeId(), "SwitchToggleBinary::Set - Toggling the state" ); - Msg* msg = new Msg( "SwitchToggleBinaryCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->SetInstance( this, _value.GetID().GetInstance() ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( SwitchToggleBinaryCmd_Set ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - return true; -} + bool SwitchToggleBinary::SetValue(Internal::VC::Value const& _value) + { + Log::Write(LogLevel_Info, GetNodeId(), "SwitchToggleBinary::Set - Toggling the state"); + Msg* msg = new Msg("SwitchToggleBinaryCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->SetInstance(this, _value.GetID().GetInstance()); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(SwitchToggleBinaryCmd_Set); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return true; + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void SwitchToggleBinary::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - node->CreateValueBool( ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, "Toggle Switch", "", false, false, false, 0 ); - } -} - + void SwitchToggleBinary::CreateVars(uint8 const _instance) + { + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueBool(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_SwitchToggleBinary::ToggleSwitch, "Toggle Switch", "", false, false, false, 0); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/SwitchToggleBinary.h b/cpp/src/command_classes/SwitchToggleBinary.h index 6634e1cfc2..3d1e7c9a93 100644 --- a/cpp/src/command_classes/SwitchToggleBinary.h +++ b/cpp/src/command_classes/SwitchToggleBinary.h @@ -32,35 +32,59 @@ namespace OpenZWave { - class ValueBool; - - /** \brief Implements COMMAND_CLASS_SWITCH_TOGGLE_BINARY (0x28), a Z-Wave device command class. - * \ingroup CommandClass - */ - class SwitchToggleBinary: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new SwitchToggleBinary( _homeId, _nodeId ); } - virtual ~SwitchToggleBinary(){} + namespace CC + { - static uint8 const StaticGetCommandClassId(){ return 0x28; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_SWITCH_TOGGLE_BINARY"; } + /** \brief Implements COMMAND_CLASS_SWITCH_TOGGLE_BINARY (0x28), a Z-Wave device command class. + * \ingroup CommandClass + */ + class SwitchToggleBinary: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new SwitchToggleBinary(_homeId, _nodeId); + } + virtual ~SwitchToggleBinary() + { + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool SetValue( Value const& _value ); + static uint8 const StaticGetCommandClassId() + { + return 0x28; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_SWITCH_TOGGLE_BINARY"; + } - protected: - virtual void CreateVars( uint8 const _instance ); + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool SetValue(Internal::VC::Value const& _value) override; - private: - SwitchToggleBinary( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} - }; + protected: + virtual void CreateVars(uint8 const _instance) override; + private: + SwitchToggleBinary(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + } + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/SwitchToggleMultilevel.cpp b/cpp/src/command_classes/SwitchToggleMultilevel.cpp index 65010d6e57..122bbce1a3 100644 --- a/cpp/src/command_classes/SwitchToggleMultilevel.cpp +++ b/cpp/src/command_classes/SwitchToggleMultilevel.cpp @@ -35,167 +35,149 @@ #include "value_classes/ValueByte.h" -using namespace OpenZWave; - -enum SwitchToggleMultilevelCmd +namespace OpenZWave { - SwitchToggleMultilevelCmd_Set = 0x01, - SwitchToggleMultilevelCmd_Get = 0x02, - SwitchToggleMultilevelCmd_Report = 0x03, - SwitchToggleMultilevelCmd_StartLevelChange = 0x04, - SwitchToggleMultilevelCmd_StopLevelChange = 0x05 -}; + namespace Internal + { + namespace CC + { + enum SwitchToggleMultilevelCmd + { + SwitchToggleMultilevelCmd_Set = 0x01, + SwitchToggleMultilevelCmd_Get = 0x02, + SwitchToggleMultilevelCmd_Report = 0x03, + SwitchToggleMultilevelCmd_StartLevelChange = 0x04, + SwitchToggleMultilevelCmd_StopLevelChange = 0x05 + }; //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool SwitchToggleMultilevel::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _requestFlags & RequestFlag_Dynamic ) - { - return RequestValue( _requestFlags, 0, _instance, _queue ); - } + bool SwitchToggleMultilevel::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_requestFlags & RequestFlag_Dynamic) + { + return RequestValue(_requestFlags, 0, _instance, _queue); + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool SwitchToggleMultilevel::RequestValue -( - uint32 const _requestFlags, - uint16 const _dummy1, // = 0 (not used) - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Msg* msg = new Msg( "SwitchToggleMultilevelCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( SwitchToggleMultilevelCmd_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "SwitchToggleMultilevelCmd_Get Not Supported on this node"); - } - return false; -} + bool SwitchToggleMultilevel::RequestValue(uint32 const _requestFlags, uint16 const _dummy1, // = 0 (not used) + uint8 const _instance, Driver::MsgQueue const _queue) + { + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Msg* msg = new Msg("SwitchToggleMultilevelCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(SwitchToggleMultilevelCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "SwitchToggleMultilevelCmd_Get Not Supported on this node"); + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool SwitchToggleMultilevel::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if( SwitchToggleMultilevelCmd_Report == (SwitchToggleMultilevelCmd)_data[0] ) - { - Log::Write( LogLevel_Info, GetNodeId(), "Received SwitchToggleMultiLevel report: level=%d", _data[1] ); + bool SwitchToggleMultilevel::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) + { + if (SwitchToggleMultilevelCmd_Report == (SwitchToggleMultilevelCmd) _data[0]) + { + Log::Write(LogLevel_Info, GetNodeId(), "Received SwitchToggleMultiLevel report: level=%d", _data[1]); - if( ValueByte* value = static_cast( GetValue( _instance, 0 ) ) ) - { - value->OnValueRefreshed( _data[1] ); - value->Release(); - } - return true; - } + if (Internal::VC::ValueByte* value = static_cast(GetValue(_instance, ValueID_Index_SwitchToggleMultilevel::Level))) + { + value->OnValueRefreshed(_data[1]); + value->Release(); + } + return true; + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Toggle the state of the switch //----------------------------------------------------------------------------- -bool SwitchToggleMultilevel::SetValue -( - Value const& _value -) -{ - Log::Write( LogLevel_Info, GetNodeId(), "SwitchToggleMultilevel::Set - Toggling the state" ); - Msg* msg = new Msg( "SwitchToggleMultilevelCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->SetInstance( this, _value.GetID().GetInstance() ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( SwitchToggleMultilevelCmd_Set ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - return true; -} + bool SwitchToggleMultilevel::SetValue(Internal::VC::Value const& _value) + { + Log::Write(LogLevel_Info, GetNodeId(), "SwitchToggleMultilevel::Set - Toggling the state"); + Msg* msg = new Msg("SwitchToggleMultilevelCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->SetInstance(this, _value.GetID().GetInstance()); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(SwitchToggleMultilevelCmd_Set); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return true; + } //----------------------------------------------------------------------------- // // Start the level changing //----------------------------------------------------------------------------- -void SwitchToggleMultilevel::StartLevelChange -( - SwitchToggleMultilevelDirection const _direction, - bool const _bIgnoreStartLevel, - bool const _bRollover -) -{ - uint8 param = (uint8)_direction; - param |= ( _bIgnoreStartLevel ? 0x20 : 0x00 ); - param |= ( _bRollover ? 0x80 : 0x00 ); + void SwitchToggleMultilevel::StartLevelChange(SwitchToggleMultilevelDirection const _direction, bool const _bIgnoreStartLevel, bool const _bRollover) + { + uint8 param = (uint8) _direction; + param |= (_bIgnoreStartLevel ? 0x20 : 0x00); + param |= (_bRollover ? 0x80 : 0x00); - Log::Write( LogLevel_Info, GetNodeId(), "SwitchMultilevel::StartLevelChange - Starting a level change, Direction=%d, IgnoreStartLevel=%s and rollover=%s", (_direction==SwitchToggleMultilevelDirection_Up) ? "Up" : "Down", _bIgnoreStartLevel ? "True" : "False", _bRollover ? "True" : "False" ); - Msg* msg = new Msg( "SwitchToggleMultilevelCmd_StartLevelChange", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( SwitchToggleMultilevelCmd_StartLevelChange ); - msg->Append( param ); - msg->Append( GetDriver()->GetTransmitOptions() ); -} + Log::Write(LogLevel_Info, GetNodeId(), "SwitchMultilevel::StartLevelChange - Starting a level change, Direction=%d, IgnoreStartLevel=%s and rollover=%s", (_direction == SwitchToggleMultilevelDirection_Up) ? "Up" : "Down", _bIgnoreStartLevel ? "True" : "False", _bRollover ? "True" : "False"); + Msg* msg = new Msg("SwitchToggleMultilevelCmd_StartLevelChange", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(SwitchToggleMultilevelCmd_StartLevelChange); + msg->Append(param); + msg->Append(GetDriver()->GetTransmitOptions()); + } //----------------------------------------------------------------------------- // // Stop the level changing //----------------------------------------------------------------------------- -void SwitchToggleMultilevel::StopLevelChange -( -) -{ - Log::Write( LogLevel_Info, GetNodeId(), "SwitchToggleMultilevel::StopLevelChange - Stopping the level change" ); - Msg* msg = new Msg( "SwitchToggleMultilevelCmd_StopLevelChange", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( SwitchToggleMultilevelCmd_StopLevelChange ); - msg->Append( GetDriver()->GetTransmitOptions() ); -} + void SwitchToggleMultilevel::StopLevelChange() + { + Log::Write(LogLevel_Info, GetNodeId(), "SwitchToggleMultilevel::StopLevelChange - Stopping the level change"); + Msg* msg = new Msg("SwitchToggleMultilevelCmd_StopLevelChange", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(SwitchToggleMultilevelCmd_StopLevelChange); + msg->Append(GetDriver()->GetTransmitOptions()); + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void SwitchToggleMultilevel::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, "Level", "", false, false, 0, 0 ); - } -} + void SwitchToggleMultilevel::CreateVars(uint8 const _instance) + { + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueByte(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_SwitchToggleMultilevel::Level, "Level", "", false, false, 0, 0); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/SwitchToggleMultilevel.h b/cpp/src/command_classes/SwitchToggleMultilevel.h index eeedd6c048..a55cf080d5 100644 --- a/cpp/src/command_classes/SwitchToggleMultilevel.h +++ b/cpp/src/command_classes/SwitchToggleMultilevel.h @@ -32,44 +32,68 @@ namespace OpenZWave { - class ValueByte; - - /** \brief Implements COMMAND_CLASS_SWITCH_TOGGLE_MULTILEVEL (0x29), a Z-Wave device command class. - * \ingroup CommandClass - */ - class SwitchToggleMultilevel: public CommandClass + namespace Internal { - public: - enum SwitchToggleMultilevelDirection + namespace CC { - SwitchToggleMultilevelDirection_Up = 0x00, - SwitchToggleMultilevelDirection_Down = 0x40 - }; - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new SwitchToggleMultilevel( _homeId, _nodeId ); } - virtual ~SwitchToggleMultilevel(){} + /** \brief Implements COMMAND_CLASS_SWITCH_TOGGLE_MULTILEVEL (0x29), a Z-Wave device command class. + * \ingroup CommandClass + */ + class SwitchToggleMultilevel: public CommandClass + { + public: + enum SwitchToggleMultilevelDirection + { + SwitchToggleMultilevelDirection_Up = 0x00, + SwitchToggleMultilevelDirection_Down = 0x40 + }; - static uint8 const StaticGetCommandClassId(){ return 0x29; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_SWITCH_TOGGLE_MULTILEVEL"; } + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new SwitchToggleMultilevel(_homeId, _nodeId); + } + virtual ~SwitchToggleMultilevel() + { + } - void StartLevelChange( SwitchToggleMultilevelDirection const _direction, bool const _bIgnoreStartLevel, bool const _bRollover ); - void StopLevelChange(); + static uint8 const StaticGetCommandClassId() + { + return 0x29; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_SWITCH_TOGGLE_MULTILEVEL"; + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool SetValue( Value const& _value ); + void StartLevelChange(SwitchToggleMultilevelDirection const _direction, bool const _bIgnoreStartLevel, bool const _bRollover); + void StopLevelChange(); - protected: - virtual void CreateVars( uint8 const _instance ); + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool SetValue(Internal::VC::Value const& _value) override; - private: - SwitchToggleMultilevel( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} - }; + protected: + virtual void CreateVars(uint8 const _instance) override; + private: + SwitchToggleMultilevel(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + } + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/ThermostatFanMode.cpp b/cpp/src/command_classes/ThermostatFanMode.cpp index 8c3e65f0bd..8c080af4d0 100644 --- a/cpp/src/command_classes/ThermostatFanMode.cpp +++ b/cpp/src/command_classes/ThermostatFanMode.cpp @@ -38,322 +38,297 @@ #include "tinyxml.h" -using namespace OpenZWave; - -enum ThermostatFanModeCmd -{ - ThermostatFanModeCmd_Set = 0x01, - ThermostatFanModeCmd_Get = 0x02, - ThermostatFanModeCmd_Report = 0x03, - ThermostatFanModeCmd_SupportedGet = 0x04, - ThermostatFanModeCmd_SupportedReport = 0x05 -}; - -static string const c_modeName[] = +namespace OpenZWave { - "Auto Low", - "On Low", - "Auto High", - "On High", - "Unknown 4", - "Unknown 5", - "Circulate", - "Unknown" -}; + namespace Internal + { + namespace CC + { + + enum ThermostatFanModeCmd + { + ThermostatFanModeCmd_Set = 0x01, + ThermostatFanModeCmd_Get = 0x02, + ThermostatFanModeCmd_Report = 0x03, + ThermostatFanModeCmd_SupportedGet = 0x04, + ThermostatFanModeCmd_SupportedReport = 0x05 + }; + + static std::string const c_modeName[] = + { "Auto Low", "On Low", "Auto High", "On High", "Unknown 4", "Unknown 5", "Circulate", "Unknown" }; //----------------------------------------------------------------------------- // // Read the supported modes //----------------------------------------------------------------------------- -void ThermostatFanMode::ReadXML -( - TiXmlElement const* _ccElement -) -{ - CommandClass::ReadXML( _ccElement ); - - if( GetNodeUnsafe() ) - { - vector supportedModes; - - TiXmlElement const* supportedModesElement = _ccElement->FirstChildElement( "SupportedModes" ); - if( supportedModesElement ) - { - TiXmlElement const* modeElement = supportedModesElement->FirstChildElement(); - while( modeElement ) + void ThermostatFanMode::ReadXML(TiXmlElement const* _ccElement) { - char const* str = modeElement->Value(); - if( str && !strcmp( str, "Mode" ) ) + CommandClass::ReadXML(_ccElement); + + if (GetNodeUnsafe()) { - int index; - if( TIXML_SUCCESS == modeElement->QueryIntAttribute( "index", &index ) ) + vector supportedModes; + + TiXmlElement const* supportedModesElement = _ccElement->FirstChildElement("SupportedModes"); + if (supportedModesElement) { - if (index > 6) /* size of c_modeName excluding Invalid */ + TiXmlElement const* modeElement = supportedModesElement->FirstChildElement(); + while (modeElement) { - Log::Write (LogLevel_Warning, GetNodeId(), "index Value in XML was greater than range. Setting to Invalid"); - index = 7; + char const* str = modeElement->Value(); + if (str && !strcmp(str, "Mode")) + { + int index; + if (TIXML_SUCCESS == modeElement->QueryIntAttribute("index", &index)) + { + if (index > 6) /* size of c_modeName excluding Invalid */ + { + Log::Write(LogLevel_Warning, GetNodeId(), "index Value in XML was greater than range. Setting to Invalid"); + index = 7; + } + Internal::VC::ValueList::Item item; + item.m_value = index; + item.m_label = c_modeName[index]; + supportedModes.push_back(item); + } + } + + modeElement = modeElement->NextSiblingElement(); } - ValueList::Item item; - item.m_value = index; - item.m_label = c_modeName[index]; - supportedModes.push_back( item ); } - } - modeElement = modeElement->NextSiblingElement(); + if (!supportedModes.empty()) + { + m_supportedModes = supportedModes; + ClearStaticRequest(StaticRequest_Values); + CreateVars(1); + } + } } - } - - if( !supportedModes.empty() ) - { - m_supportedModes = supportedModes; - ClearStaticRequest( StaticRequest_Values ); - CreateVars( 1 ); - } - } -} //----------------------------------------------------------------------------- // // Save the supported modes //----------------------------------------------------------------------------- -void ThermostatFanMode::WriteXML -( - TiXmlElement* _ccElement -) -{ - CommandClass::WriteXML( _ccElement ); + void ThermostatFanMode::WriteXML(TiXmlElement* _ccElement) + { + CommandClass::WriteXML(_ccElement); - if( GetNodeUnsafe() ) - { - TiXmlElement* supportedModesElement = new TiXmlElement( "SupportedModes" ); - _ccElement->LinkEndChild( supportedModesElement ); + if (GetNodeUnsafe()) + { + TiXmlElement* supportedModesElement = new TiXmlElement("SupportedModes"); + _ccElement->LinkEndChild(supportedModesElement); - for( vector::iterator it = m_supportedModes.begin(); it != m_supportedModes.end(); ++it ) - { - ValueList::Item const& item = *it; + for (vector::iterator it = m_supportedModes.begin(); it != m_supportedModes.end(); ++it) + { + Internal::VC::ValueList::Item const& item = *it; - TiXmlElement* modeElement = new TiXmlElement( "Mode" ); - supportedModesElement->LinkEndChild( modeElement ); + TiXmlElement* modeElement = new TiXmlElement("Mode"); + supportedModesElement->LinkEndChild(modeElement); - char str[8]; - snprintf( str, 8, "%d", item.m_value ); - modeElement->SetAttribute( "index", str ); - modeElement->SetAttribute( "label", item.m_label.c_str() ); - } - } -} + char str[8]; + snprintf(str, 8, "%d", item.m_value); + modeElement->SetAttribute("index", str); + modeElement->SetAttribute("label", item.m_label.c_str()); + } + } + } //----------------------------------------------------------------------------- // // Get the static thermostat fan mode details from the device //----------------------------------------------------------------------------- -bool ThermostatFanMode::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - bool requests = false; - if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) ) - { - // Request the supported modes - requests |= RequestValue( _requestFlags, ThermostatFanModeCmd_SupportedGet, _instance, _queue ); - } + bool ThermostatFanMode::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + bool requests = false; + if ((_requestFlags & RequestFlag_Static) && HasStaticRequest(StaticRequest_Values)) + { + // Request the supported modes + requests |= RequestValue(_requestFlags, ThermostatFanModeCmd_SupportedGet, _instance, _queue); + } - if( _requestFlags & RequestFlag_Dynamic ) - { - // Request the current fan mode - requests |= RequestValue( _requestFlags, ThermostatFanModeCmd_Get, _instance, _queue ); - } + if (_requestFlags & RequestFlag_Dynamic) + { + // Request the current fan mode + requests |= RequestValue(_requestFlags, ThermostatFanModeCmd_Get, _instance, _queue); + } - return requests; -} + return requests; + } //----------------------------------------------------------------------------- // // Get the thermostat fan mode details from the device //----------------------------------------------------------------------------- -bool ThermostatFanMode::RequestValue -( - uint32 const _requestFlags, - uint16 const _getTypeEnum, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _getTypeEnum == ThermostatFanModeCmd_SupportedGet ) - { - // Request the supported modes - Msg* msg = new Msg( "ThermostatFanModeCmd_SupportedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( ThermostatFanModeCmd_SupportedGet ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } - - if( _getTypeEnum == ThermostatFanModeCmd_Get || _getTypeEnum == 0 ) - { - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - // Request the current fan mode - Msg* msg = new Msg( "ThermostatFanModeCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( ThermostatFanModeCmd_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "ThermostatFanModeCmd_Get Not Supported on this node"); - } - } - return false; -} + bool ThermostatFanMode::RequestValue(uint32 const _requestFlags, uint16 const _getTypeEnum, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_getTypeEnum == ThermostatFanModeCmd_SupportedGet) + { + // Request the supported modes + Msg* msg = new Msg("ThermostatFanModeCmd_SupportedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(ThermostatFanModeCmd_SupportedGet); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + + if (_getTypeEnum == ThermostatFanModeCmd_Get || _getTypeEnum == 0) + { + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + // Request the current fan mode + Msg* msg = new Msg("ThermostatFanModeCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(ThermostatFanModeCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "ThermostatFanModeCmd_Get Not Supported on this node"); + } + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool ThermostatFanMode::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if( ThermostatFanModeCmd_Report == (ThermostatFanModeCmd)_data[0] ) - { - bool validMode = false; - uint8 mode = (int32)_data[1]; - - for (vector::iterator it = m_supportedModes.begin(); it != m_supportedModes.end(); ++it ) - { - ValueList::Item const& item = *it; - if (item.m_value == mode) { - validMode = true; - break; - } - } - if( validMode ) - { - // We have received the thermostat mode from the Z-Wave device - if( ValueList* valueList = static_cast( GetValue( _instance, 0 ) ) ) - { - valueList->OnValueRefreshed( (int32)_data[1] ); - if (valueList->GetItem()) - Log::Write( LogLevel_Info, GetNodeId(), "Received thermostat fan mode: %s", valueList->GetItem()->m_label.c_str() ); - else - Log::Write( LogLevel_Info, GetNodeId(), "Received thermostat fan mode: %d", _data[1]); - valueList->Release(); - } - else - { - Log::Write( LogLevel_Info, GetNodeId(), "Received thermostat fan mode: index %d", mode ); - } - } - else - { - Log::Write( LogLevel_Info, GetNodeId(), "Received unknown thermostat fan mode: %d", mode ); - } - return true; - } - - if( ThermostatFanModeCmd_SupportedReport == (ThermostatFanModeCmd)_data[0] ) - { - // We have received the supported thermostat fan modes from the Z-Wave device - Log::Write( LogLevel_Info, GetNodeId(), "Received supported thermostat fan modes" ); - - m_supportedModes.clear(); - for( uint32 i=1; i<_length-1; ++i ) - { - for( int32 bit=0; bit<8; ++bit ) + bool ThermostatFanMode::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) { - if( ( _data[i] & (1<= (sizeof(c_modeName)/sizeof(*c_modeName) -1)) + for (vector::iterator it = m_supportedModes.begin(); it != m_supportedModes.end(); ++it) { - Log::Write( LogLevel_Info, GetNodeId(), "Received unknown fan mode: 0x%x", item.m_value); + Internal::VC::ValueList::Item const& item = *it; + if (item.m_value == mode) + { + validMode = true; + break; + } + } + if (validMode) + { + // We have received the thermostat mode from the Z-Wave device + if (Internal::VC::ValueList* valueList = static_cast(GetValue(_instance, ValueID_Index_ThermostatFanMode::FanMode))) + { + valueList->OnValueRefreshed((int32) _data[1]); + if (valueList->GetItem()) + Log::Write(LogLevel_Info, GetNodeId(), "Received thermostat fan mode: %s", valueList->GetItem()->m_label.c_str()); + else + Log::Write(LogLevel_Info, GetNodeId(), "Received thermostat fan mode: %d", _data[1]); + valueList->Release(); + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "Received thermostat fan mode: index %d", mode); + } } else { - item.m_label = c_modeName[item.m_value]; - m_supportedModes.push_back( item ); - - Log::Write( LogLevel_Info, GetNodeId(), " Added fan mode: %s", c_modeName[item.m_value].c_str() ); + Log::Write(LogLevel_Info, GetNodeId(), "Received unknown thermostat fan mode: %d", mode); } + return true; } - } - } - ClearStaticRequest( StaticRequest_Values ); - CreateVars( _instance ); - return true; - } + if (ThermostatFanModeCmd_SupportedReport == (ThermostatFanModeCmd) _data[0]) + { + // We have received the supported thermostat fan modes from the Z-Wave device + Log::Write(LogLevel_Info, GetNodeId(), "Received supported thermostat fan modes"); - return false; -} + m_supportedModes.clear(); + for (uint32 i = 1; i < _length - 1; ++i) + { + for (int32 bit = 0; bit < 8; ++bit) + { + if ((_data[i] & (1 << bit)) != 0) + { + Internal::VC::ValueList::Item item; + item.m_value = (int32) ((i - 1) << 3) + bit; + + /* Minus 1 here as the Unknown Entry is our addition */ + if ((size_t) item.m_value >= (sizeof(c_modeName) / sizeof(*c_modeName) - 1)) + { + Log::Write(LogLevel_Info, GetNodeId(), "Received unknown fan mode: 0x%x", item.m_value); + } + else + { + item.m_label = c_modeName[item.m_value]; + m_supportedModes.push_back(item); + + Log::Write(LogLevel_Info, GetNodeId(), " Added fan mode: %s", c_modeName[item.m_value].c_str()); + } + } + } + } + + ClearStaticRequest(StaticRequest_Values); + CreateVars(_instance); + return true; + } + + return false; + } //----------------------------------------------------------------------------- // // Set the device's thermostat fan mode //----------------------------------------------------------------------------- -bool ThermostatFanMode::SetValue -( - Value const& _value -) -{ - if( ValueID::ValueType_List == _value.GetID().GetType() ) - { - ValueList const* value = static_cast(&_value); - if (value->GetItem() == NULL) - return false; - - uint8 state = (uint8)value->GetItem()->m_value; - - Msg* msg = new Msg( "ThermostatFanModeCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->SetInstance( this, _value.GetID().GetInstance() ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( ThermostatFanModeCmd_Set ); - msg->Append( state ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - return true; - } - - return false; -} + bool ThermostatFanMode::SetValue(Internal::VC::Value const& _value) + { + if (ValueID::ValueType_List == _value.GetID().GetType()) + { + Internal::VC::ValueList const* value = static_cast(&_value); + if (value->GetItem() == NULL) + return false; + + uint8 state = (uint8) value->GetItem()->m_value; + + Msg* msg = new Msg("ThermostatFanModeCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->SetInstance(this, _value.GetID().GetInstance()); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(ThermostatFanModeCmd_Set); + msg->Append(state); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return true; + } + + return false; + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void ThermostatFanMode::CreateVars -( - uint8 const _instance -) -{ - if( m_supportedModes.empty() ) - { - return; - } + void ThermostatFanMode::CreateVars(uint8 const _instance) + { + if (m_supportedModes.empty()) + { + return; + } - if( Node* node = GetNodeUnsafe() ) - { - node->CreateValueList( ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, "Fan Mode", "", false, false, 1, m_supportedModes, m_supportedModes[0].m_value, 0 ); - } -} + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueList(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_ThermostatFanMode::FanMode, "Fan Mode", "", false, false, 1, m_supportedModes, m_supportedModes[0].m_value, 0); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/ThermostatFanMode.h b/cpp/src/command_classes/ThermostatFanMode.h index 81bc45152e..a9e8ab4c96 100644 --- a/cpp/src/command_classes/ThermostatFanMode.h +++ b/cpp/src/command_classes/ThermostatFanMode.h @@ -35,44 +35,65 @@ namespace OpenZWave { - class ValueList; - - /** \brief Implements COMMAND_CLASS_THERMOSTAT_FAN_MODE (0x44), a Z-Wave device command class. - * \ingroup CommandClass - */ - class ThermostatFanMode: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new ThermostatFanMode( _homeId, _nodeId ); } - virtual ~ThermostatFanMode(){} + namespace CC + { + + /** \brief Implements COMMAND_CLASS_THERMOSTAT_FAN_MODE (0x44), a Z-Wave device command class. + * \ingroup CommandClass + */ + class ThermostatFanMode: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new ThermostatFanMode(_homeId, _nodeId); + } + virtual ~ThermostatFanMode() + { + } - static uint8 const StaticGetCommandClassId(){ return 0x44; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_THERMOSTAT_FAN_MODE"; } + static uint8 const StaticGetCommandClassId() + { + return 0x44; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_THERMOSTAT_FAN_MODE"; + } - // From CommandClass - virtual void ReadXML( TiXmlElement const* _ccElement ); - virtual void WriteXML( TiXmlElement* _ccElement ); - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _getTypeEnum, uint8 const _dummy, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool SetValue( Value const& _value ); + // From CommandClass + virtual void ReadXML(TiXmlElement const* _ccElement) override; + virtual void WriteXML(TiXmlElement* _ccElement) override; + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _getTypeEnum, uint8 const _dummy, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool SetValue(Internal::VC::Value const& _value) override; - protected: - virtual void CreateVars( uint8 const _instance ); + protected: + virtual void CreateVars(uint8 const _instance) override; - private: - ThermostatFanMode( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){ SetStaticRequest( StaticRequest_Values ); } - - vector m_supportedModes; - }; + private: + ThermostatFanMode(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + SetStaticRequest(StaticRequest_Values); + } + vector m_supportedModes; + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif - - - - diff --git a/cpp/src/command_classes/ThermostatFanState.cpp b/cpp/src/command_classes/ThermostatFanState.cpp index 269d37ea71..7e7af160b2 100644 --- a/cpp/src/command_classes/ThermostatFanState.cpp +++ b/cpp/src/command_classes/ThermostatFanState.cpp @@ -35,124 +35,101 @@ #include "value_classes/ValueString.h" -using namespace OpenZWave; - -enum ThermostatFanStateCmd +namespace OpenZWave { - ThermostatFanStateCmd_Get = 0x02, - ThermostatFanStateCmd_Report = 0x03 -}; + namespace Internal + { + namespace CC + { -static char const* c_stateName[] = -{ - "Idle", - "Running", - "Running High", - "State 03", // Undefined states. May be used in the future. - "State 04", - "State 05", - "State 06", - "State 07", - "State 08", - "State 09", - "State 10", - "State 11", - "State 12", - "State 13", - "State 14", - "State 15", -}; + enum ThermostatFanStateCmd + { + ThermostatFanStateCmd_Get = 0x02, + ThermostatFanStateCmd_Report = 0x03 + }; + + static char const* c_stateName[] = + { "Idle", "Running", "Running High", "State 03", // Undefined states. May be used in the future. + "State 04", "State 05", "State 06", "State 07", "State 08", "State 09", "State 10", "State 11", "State 12", "State 13", "State 14", "State 15", }; //----------------------------------------------------------------------------- // // Get the static thermostat mode details from the device //----------------------------------------------------------------------------- -bool ThermostatFanState::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _requestFlags & RequestFlag_Dynamic ) - { - // Request the current state - return RequestValue( _requestFlags, 0, _instance, _queue ); - } - return false; -} + bool ThermostatFanState::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_requestFlags & RequestFlag_Dynamic) + { + // Request the current state + return RequestValue(_requestFlags, 0, _instance, _queue); + } + return false; + } //----------------------------------------------------------------------------- // // Get the thermostat fan state details from the device //----------------------------------------------------------------------------- -bool ThermostatFanState::RequestValue -( - uint32 const _requestFlags, - uint16 const _dummy1, // = 0 (not used) - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - // Request the current state - Msg* msg = new Msg( "ThermostatFanStateCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( ThermostatFanStateCmd_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "ThermostatFanStateCmd_Get Not Supported on this node"); - } - return false; -} + bool ThermostatFanState::RequestValue(uint32 const _requestFlags, uint16 const _dummy1, // = 0 (not used) + uint8 const _instance, Driver::MsgQueue const _queue) + { + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + // Request the current state + Msg* msg = new Msg("ThermostatFanStateCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(ThermostatFanStateCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "ThermostatFanStateCmd_Get Not Supported on this node"); + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool ThermostatFanState::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if( ThermostatFanStateCmd_Report == (ThermostatFanStateCmd)_data[0] ) - { - // We have received the thermostat fan state from the Z-Wave device - if( ValueString* valueString = static_cast( GetValue( _instance, 0 ) ) ) - { - /* No need bounds checking as the state can only be a single byte - No larger than our Char array anyway */ - uint8 state = (_data[1]&0x0f); + bool ThermostatFanState::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) + { + if (ThermostatFanStateCmd_Report == (ThermostatFanStateCmd) _data[0]) + { + // We have received the thermostat fan state from the Z-Wave device + if (Internal::VC::ValueString* valueString = static_cast(GetValue(_instance, ValueID_Index_ThermostatFanState::FanState))) + { + /* No need bounds checking as the state can only be a single byte - No larger than our Char array anyway */ + uint8 state = (_data[1] & 0x0f); - valueString->OnValueRefreshed( c_stateName[state] ); - valueString->Release(); - Log::Write( LogLevel_Info, GetNodeId(), "Received thermostat fan state: %s", valueString->GetValue().c_str() ); - } - return true; - } + valueString->OnValueRefreshed(c_stateName[state]); + valueString->Release(); + Log::Write(LogLevel_Info, GetNodeId(), "Received thermostat fan state: %s", valueString->GetValue().c_str()); + } + return true; + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void ThermostatFanState::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - node->CreateValueString( ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, "Fan State", "", true, false, c_stateName[0], 0 ); - } -} + void ThermostatFanState::CreateVars(uint8 const _instance) + { + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueString(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_ThermostatFanState::FanState, "Fan State", "", true, false, c_stateName[0], 0); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/ThermostatFanState.h b/cpp/src/command_classes/ThermostatFanState.h index 853cc5a656..03efdba1ce 100644 --- a/cpp/src/command_classes/ThermostatFanState.h +++ b/cpp/src/command_classes/ThermostatFanState.h @@ -35,38 +35,59 @@ namespace OpenZWave { - class ValueString; - - /** \brief Implements COMMAND_CLASS_THERMOSTAT_FAN_STATE (0x45), a Z-Wave device command class. - * \ingroup CommandClass - */ - class ThermostatFanState: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new ThermostatFanState( _homeId, _nodeId ); } - virtual ~ThermostatFanState(){} + namespace CC + { - static uint8 const StaticGetCommandClassId(){ return 0x45; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_THERMOSTAT_FAN_STATE"; } + /** \brief Implements COMMAND_CLASS_THERMOSTAT_FAN_STATE (0x45), a Z-Wave device command class. + * \ingroup CommandClass + */ + class ThermostatFanState: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new ThermostatFanState(_homeId, _nodeId); + } + virtual ~ThermostatFanState() + { + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); + static uint8 const StaticGetCommandClassId() + { + return 0x45; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_THERMOSTAT_FAN_STATE"; + } - protected: - virtual void CreateVars( uint8 const _instance ); + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; - private: - ThermostatFanState( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} - }; + protected: + virtual void CreateVars(uint8 const _instance) override; + private: + ThermostatFanState(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + } + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif - - - diff --git a/cpp/src/command_classes/ThermostatMode.cpp b/cpp/src/command_classes/ThermostatMode.cpp index 084a91eb3c..834879beb6 100644 --- a/cpp/src/command_classes/ThermostatMode.cpp +++ b/cpp/src/command_classes/ThermostatMode.cpp @@ -37,420 +37,370 @@ #include "tinyxml.h" -using namespace OpenZWave; - -enum ThermostatModeCmd -{ - ThermostatModeCmd_Set = 0x01, - ThermostatModeCmd_Get = 0x02, - ThermostatModeCmd_Report = 0x03, - ThermostatModeCmd_SupportedGet = 0x04, - ThermostatModeCmd_SupportedReport = 0x05 -}; - -enum +namespace OpenZWave { - ThermostatMode_Off = 0, - ThermostatMode_Heat, - ThermostatMode_Cool, - ThermostatMode_Auto, - ThermostatMode_Auxiliary, - ThermostatMode_Resume_On, - ThermostatMode_Fan, - ThermostatMode_Furnance, - ThermostatMode_Dry, - ThermostatMode_Moist, - ThermostatMode_AutoChangeover, - ThermostatMode_HeatingEcon, - ThermostatMode_CoolingEcon, - ThermostatMode_Away, - ThermostatMode_Reserved0E = 0x0E, - ThermostatMode_FullPower, - ThermostatMode_Reserved10 = 0x10, - ThermostatMode_Reserved11, - ThermostatMode_Reserved12, - ThermostatMode_Reserved13, - ThermostatMode_Reserved14, - ThermostatMode_Reserved15, - ThermostatMode_Reserved16, - ThermostatMode_Reserved17, - ThermostatMode_Reserved18, - ThermostatMode_Reserved19, - ThermostatMode_Reserved1A, - ThermostatMode_Reserved1B, - ThermostatMode_Reserved1C, - ThermostatMode_Reserved1D, - ThermostatMode_Reserved1E, - ThermostatMode_ManufacturerSpecific = 0x1F, - ThermostatMode_Count, -}; - -static char const* c_modeName[] = -{ - "Off", - "Heat", - "Cool", - "Auto", - "Aux Heat", - "Resume", - "Fan Only", - "Furnace", - "Dry Air", - "Moist Air", - "Auto Changeover", - "Heat Econ", - "Cool Econ", - "Away", - "Unknown", - "Full Power", - "Unknown", - "Unknown", - "Unknown", - "Unknown", - "Unknown", - "Unknown", - "Unknown", - "Unknown", - "Unknown", - "Unknown", - "Unknown", - "Unknown", - "Unknown", - "Unknown", - "Unknown", - "Manufacturer Specific" -}; + namespace Internal + { + namespace CC + { + + enum ThermostatModeCmd + { + ThermostatModeCmd_Set = 0x01, + ThermostatModeCmd_Get = 0x02, + ThermostatModeCmd_Report = 0x03, + ThermostatModeCmd_SupportedGet = 0x04, + ThermostatModeCmd_SupportedReport = 0x05 + }; + + enum + { + ThermostatMode_Off = 0, + ThermostatMode_Heat, + ThermostatMode_Cool, + ThermostatMode_Auto, + ThermostatMode_Auxiliary, + ThermostatMode_Resume_On, + ThermostatMode_Fan, + ThermostatMode_Furnance, + ThermostatMode_Dry, + ThermostatMode_Moist, + ThermostatMode_AutoChangeover, + ThermostatMode_HeatingEcon, + ThermostatMode_CoolingEcon, + ThermostatMode_Away, + ThermostatMode_Reserved0E = 0x0E, + ThermostatMode_FullPower, + ThermostatMode_Reserved10 = 0x10, + ThermostatMode_Reserved11, + ThermostatMode_Reserved12, + ThermostatMode_Reserved13, + ThermostatMode_Reserved14, + ThermostatMode_Reserved15, + ThermostatMode_Reserved16, + ThermostatMode_Reserved17, + ThermostatMode_Reserved18, + ThermostatMode_Reserved19, + ThermostatMode_Reserved1A, + ThermostatMode_Reserved1B, + ThermostatMode_Reserved1C, + ThermostatMode_Reserved1D, + ThermostatMode_Reserved1E, + ThermostatMode_ManufacturerSpecific = 0x1F, + ThermostatMode_Count, + }; + + static char const* c_modeName[] = + { "Off", "Heat", "Cool", "Auto", "Aux Heat", "Resume", "Fan Only", "Furnace", "Dry Air", "Moist Air", "Auto Changeover", "Heat Econ", "Cool Econ", "Away", "Unknown", "Full Power", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Manufacturer Specific" }; //----------------------------------------------------------------------------- // // Read the supported modes //----------------------------------------------------------------------------- -void ThermostatMode::ReadXML -( - TiXmlElement const* _ccElement -) -{ - CommandClass::ReadXML( _ccElement ); - - if( GetNodeUnsafe() ) - { - vector supportedModes; - - TiXmlElement const* supportedModesElement = _ccElement->FirstChildElement( "SupportedModes" ); - if( supportedModesElement ) - { - TiXmlElement const* modeElement = supportedModesElement->FirstChildElement(); - while( modeElement ) + void ThermostatMode::ReadXML(TiXmlElement const* _ccElement) { - char const* str = modeElement->Value(); - if( str && !strcmp( str, "Mode" ) ) + CommandClass::ReadXML(_ccElement); + + if (GetNodeUnsafe()) { - int index; - if( TIXML_SUCCESS == modeElement->QueryIntAttribute( "index", &index ) ) + vector supportedModes; + + TiXmlElement const* supportedModesElement = _ccElement->FirstChildElement("SupportedModes"); + if (supportedModesElement) { - if (index > ThermostatMode_Count) + TiXmlElement const* modeElement = supportedModesElement->FirstChildElement(); + while (modeElement) { - Log::Write (LogLevel_Warning, GetNodeId(), "index Value in XML was greater than range. Setting to Invalid"); - index = ThermostatMode_Count+1; + char const* str = modeElement->Value(); + if (str && !strcmp(str, "Mode")) + { + int index; + if (TIXML_SUCCESS == modeElement->QueryIntAttribute("index", &index)) + { + if (index > ThermostatMode_Count) + { + Log::Write(LogLevel_Warning, GetNodeId(), "index Value in XML was greater than range. Setting to Invalid"); + index = ThermostatMode_Count + 1; + } + Internal::VC::ValueList::Item item; + item.m_value = index; + item.m_label = c_modeName[index]; + supportedModes.push_back(item); + } + } + + modeElement = modeElement->NextSiblingElement(); } - ValueList::Item item; - item.m_value = index; - item.m_label = c_modeName[index]; - supportedModes.push_back( item ); } - } - modeElement = modeElement->NextSiblingElement(); + if (!supportedModes.empty()) + { + m_supportedModes = supportedModes; + ClearStaticRequest(StaticRequest_Values); + CreateVars(1); + } + } } - } - - if( !supportedModes.empty() ) - { - m_supportedModes = supportedModes; - ClearStaticRequest( StaticRequest_Values ); - CreateVars( 1 ); - } - } -} //----------------------------------------------------------------------------- // // Save the supported modes //----------------------------------------------------------------------------- -void ThermostatMode::WriteXML -( - TiXmlElement* _ccElement -) -{ - CommandClass::WriteXML( _ccElement ); - - if( m_supportedModes.empty() ) - { - return; - } + void ThermostatMode::WriteXML(TiXmlElement* _ccElement) + { + CommandClass::WriteXML(_ccElement); + if (m_supportedModes.empty()) + { + return; + } - if( GetNodeUnsafe() ) - { - TiXmlElement* supportedModesElement = new TiXmlElement( "SupportedModes" ); - _ccElement->LinkEndChild( supportedModesElement ); + if (GetNodeUnsafe()) + { + TiXmlElement* supportedModesElement = new TiXmlElement("SupportedModes"); + _ccElement->LinkEndChild(supportedModesElement); - for( vector::iterator it = m_supportedModes.begin(); it != m_supportedModes.end(); ++it ) - { - ValueList::Item const& item = *it; + for (vector::iterator it = m_supportedModes.begin(); it != m_supportedModes.end(); ++it) + { + Internal::VC::ValueList::Item const& item = *it; - TiXmlElement* modeElement = new TiXmlElement( "Mode" ); - supportedModesElement->LinkEndChild( modeElement ); + TiXmlElement* modeElement = new TiXmlElement("Mode"); + supportedModesElement->LinkEndChild(modeElement); - char str[8]; - snprintf( str, 8, "%d", item.m_value ); - modeElement->SetAttribute( "index", str ); - modeElement->SetAttribute( "label", item.m_label.c_str() ); - } - } -} + char str[8]; + snprintf(str, 8, "%d", item.m_value); + modeElement->SetAttribute("index", str); + modeElement->SetAttribute("label", item.m_label.c_str()); + } + } + } //----------------------------------------------------------------------------- // // Get the static thermostat mode details from the device //----------------------------------------------------------------------------- -bool ThermostatMode::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - bool requests = false; - if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) ) - { - // request supported mode list - requests |= RequestValue( _requestFlags, ThermostatModeCmd_SupportedGet, _instance, _queue ); - } + bool ThermostatMode::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + bool requests = false; + if ((_requestFlags & RequestFlag_Static) && HasStaticRequest(StaticRequest_Values)) + { + // request supported mode list + requests |= RequestValue(_requestFlags, ThermostatModeCmd_SupportedGet, _instance, _queue); + } - if( _requestFlags & RequestFlag_Dynamic ) - { - // Request the current mode - requests |= RequestValue( _requestFlags, 0, _instance, _queue ); - } + if (_requestFlags & RequestFlag_Dynamic) + { + // Request the current mode + requests |= RequestValue(_requestFlags, 0, _instance, _queue); + } - return requests; -} + return requests; + } //----------------------------------------------------------------------------- // // Get the static thermostat mode details from the device //----------------------------------------------------------------------------- -bool ThermostatMode::RequestValue -( - uint32 const _requestFlags, - uint16 const _getTypeEnum, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _getTypeEnum == ThermostatModeCmd_SupportedGet ) - { - // Request the supported modes - Msg* msg = new Msg( "ThermostatModeCmd_SupportedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( ThermostatModeCmd_SupportedGet ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } - - if( _getTypeEnum == 0 ) // get current mode - { - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - // Request the current mode - Msg* msg = new Msg( "ThermostatModeCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( ThermostatModeCmd_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "ThermostatModeCmd_Get Not Supported on this node"); - - } - } - return false; -} + bool ThermostatMode::RequestValue(uint32 const _requestFlags, uint16 const _getTypeEnum, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_getTypeEnum == ThermostatModeCmd_SupportedGet) + { + // Request the supported modes + Msg* msg = new Msg("ThermostatModeCmd_SupportedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(ThermostatModeCmd_SupportedGet); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + + if (_getTypeEnum == 0) // get current mode + { + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + // Request the current mode + Msg* msg = new Msg("ThermostatModeCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(ThermostatModeCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "ThermostatModeCmd_Get Not Supported on this node"); + + } + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool ThermostatMode::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if( ThermostatModeCmd_Report == (ThermostatModeCmd)_data[0] ) - { - uint8 mode = _data[1]&0x1f; - bool validMode = false; - for (vector::iterator it = m_supportedModes.begin(); it != m_supportedModes.end(); ++it ) - { - ValueList::Item const& item = *it; - if (item.m_value == mode) { - validMode = true; - break; - } - } - - if( validMode ) - { - // We have received the thermostat mode from the Z-Wave device - if( ValueList* valueList = static_cast( GetValue( _instance, 0 ) ) ) - { - valueList->OnValueRefreshed( mode ); - if (valueList->GetItem()) - Log::Write( LogLevel_Info, GetNodeId(), "Received thermostat mode: %s", valueList->GetItem()->m_label.c_str() ); - else - Log::Write( LogLevel_Info, GetNodeId(), "Received thermostat mode: %d", mode); - valueList->Release(); - } - else - { - Log::Write( LogLevel_Info, GetNodeId(), "Received thermostat mode: index %d", mode ); - } - } - else - { - Log::Write( LogLevel_Info, GetNodeId(), "Received unknown thermostat mode: index %d", mode ); - } - return true; - } - - if( ThermostatModeCmd_SupportedReport == (ThermostatModeCmd)_data[0] ) - { - // We have received the supported thermostat modes from the Z-Wave device - // these values are used to populate m_supportedModes which, in turn, is used to "seed" the values - // for each m_modes instance - Log::Write( LogLevel_Info, GetNodeId(), "Received supported thermostat modes" ); - - m_supportedModes.clear(); - for( uint32 i=1; i<_length-1; ++i ) - { - for( int32 bit=0; bit<8; ++bit ) + bool ThermostatMode::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) { - if( ( _data[i] & (1<= (sizeof(c_modeName)/sizeof(*c_modeName) -1)) + uint8 mode = _data[1] & 0x1f; + bool validMode = false; + for (vector::iterator it = m_supportedModes.begin(); it != m_supportedModes.end(); ++it) { - Log::Write( LogLevel_Info, GetNodeId(), "Received unknown thermostat mode: 0x%x", item.m_value); + Internal::VC::ValueList::Item const& item = *it; + if (item.m_value == mode) + { + validMode = true; + break; + } + } + + if (validMode) + { + // We have received the thermostat mode from the Z-Wave device + if (Internal::VC::ValueList* valueList = static_cast(GetValue(_instance, ValueID_Index_ThermostatMode::Mode))) + { + valueList->OnValueRefreshed(mode); + if (valueList->GetItem()) + Log::Write(LogLevel_Info, GetNodeId(), "Received thermostat mode: %s", valueList->GetItem()->m_label.c_str()); + else + Log::Write(LogLevel_Info, GetNodeId(), "Received thermostat mode: %d", mode); + valueList->Release(); + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "Received thermostat mode: index %d", mode); + } } else { - item.m_label = c_modeName[item.m_value]; - m_supportedModes.push_back( item ); + Log::Write(LogLevel_Info, GetNodeId(), "Received unknown thermostat mode: index %d", mode); + } + return true; + } - Log::Write( LogLevel_Info, GetNodeId(), " Added mode: %s", c_modeName[item.m_value] ); + if (ThermostatModeCmd_SupportedReport == (ThermostatModeCmd) _data[0]) + { + // We have received the supported thermostat modes from the Z-Wave device + // these values are used to populate m_supportedModes which, in turn, is used to "seed" the values + // for each m_modes instance + Log::Write(LogLevel_Info, GetNodeId(), "Received supported thermostat modes"); + + m_supportedModes.clear(); + for (uint32 i = 1; i < _length - 1; ++i) + { + for (int32 bit = 0; bit < 8; ++bit) + { + if ((_data[i] & (1 << bit)) != 0) + { + Internal::VC::ValueList::Item item; + item.m_value = (int32) ((i - 1) << 3) + bit; + /* minus 1 in the sizeof calc here, as the Unknown entry is our addition */ + if ((size_t) item.m_value >= (sizeof(c_modeName) / sizeof(*c_modeName) - 1)) + { + Log::Write(LogLevel_Info, GetNodeId(), "Received unknown thermostat mode: 0x%x", item.m_value); + } + else + { + item.m_label = c_modeName[item.m_value]; + m_supportedModes.push_back(item); + + Log::Write(LogLevel_Info, GetNodeId(), " Added mode: %s", c_modeName[item.m_value]); + } + } + } } + ClearStaticRequest(StaticRequest_Values); + CreateVars(_instance); + return true; } - } - } - ClearStaticRequest( StaticRequest_Values ); - CreateVars( _instance ); - return true; - } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Set the device's thermostat mode //----------------------------------------------------------------------------- -bool ThermostatMode::SetValue -( - Value const& _value -) -{ - if( ValueID::ValueType_List == _value.GetID().GetType() ) - { - ValueList const* value = static_cast(&_value); - if (value->GetItem() == NULL) - return false; - uint8 state = (uint8)value->GetItem()->m_value; - - Msg* msg = new Msg( "ThermostatModeCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->SetInstance( this, _value.GetID().GetInstance() ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( ThermostatModeCmd_Set ); - msg->Append( state ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - return true; - } - - return false; -} + bool ThermostatMode::SetValue(Internal::VC::Value const& _value) + { + if (ValueID::ValueType_List == _value.GetID().GetType()) + { + Internal::VC::ValueList const* value = static_cast(&_value); + if (value->GetItem() == NULL) + return false; + uint8 state = (uint8) value->GetItem()->m_value; + + Msg* msg = new Msg("ThermostatModeCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->SetInstance(this, _value.GetID().GetInstance()); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(ThermostatModeCmd_Set); + msg->Append(state); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return true; + } + + return false; + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void ThermostatMode::CreateVars -( - uint8 const _instance -) -{ - // There are number of ways to get here...each needs to be handled differently: - // QueryStage_ProtocolInfo: - // Don't know what's supported yet, so do nothing - // QueryStage_NodeInfo: - // Need to create the instance so the values can be read from the xml file - // QueryStage_Static: - // Need to create the instance (processing SupportedReport) if it doesn't exist - // If it does, populate with the appropriate values - // other - // Only create the instance if there are supportedModes - - if( Node* node = GetNodeUnsafe() ) - { - Node::QueryStage qs = node->GetCurrentQueryStage(); - if( qs == Node::QueryStage_ProtocolInfo || m_supportedModes.empty() ) - { - // this call is from QueryStage_ProtocolInfo, - // so just return (don't know which modes are supported yet) - return; - } - - // identify the lowest supported mode as the "default" (or default to 0 if no supported modes identified yet) - int32 defaultValue = 0; - if( !m_supportedModes.empty() ) - { - defaultValue = m_supportedModes[0].m_value; - } - - if( qs == Node::QueryStage_Static ) - { - // This instance might already have been created (in NodeInfo, in preparation for loading the values - // from zwcfg xml file). So, if the instance already exists, we delete its value and add a new one below - if( ValueList* valueList = static_cast( GetValue( _instance, 0 ) ) ) + void ThermostatMode::CreateVars(uint8 const _instance) { - node->RemoveValueList( valueList ); - valueList->Release(); - } - } + // There are number of ways to get here...each needs to be handled differently: + // QueryStage_ProtocolInfo: + // Don't know what's supported yet, so do nothing + // QueryStage_NodeInfo: + // Need to create the instance so the values can be read from the xml file + // QueryStage_Static: + // Need to create the instance (processing SupportedReport) if it doesn't exist + // If it does, populate with the appropriate values + // other + // Only create the instance if there are supportedModes + + if (Node* node = GetNodeUnsafe()) + { + Node::QueryStage qs = node->GetCurrentQueryStage(); + if (qs == Node::QueryStage_ProtocolInfo || m_supportedModes.empty()) + { + // this call is from QueryStage_ProtocolInfo, + // so just return (don't know which modes are supported yet) + return; + } + + // identify the lowest supported mode as the "default" (or default to 0 if no supported modes identified yet) + int32 defaultValue = 0; + if (!m_supportedModes.empty()) + { + defaultValue = m_supportedModes[0].m_value; + } - node->CreateValueList( ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, "Mode", "", false, false, 1, m_supportedModes, defaultValue, 0 ); - } -} + if (qs == Node::QueryStage_Static) + { + // This instance might already have been created (in NodeInfo, in preparation for loading the values + // from zwcfg xml file). So, if the instance already exists, we delete its value and add a new one below + if (Internal::VC::ValueList* valueList = static_cast(GetValue(_instance, 0))) + { + node->RemoveValueList(valueList); + valueList->Release(); + } + } + + node->CreateValueList(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_ThermostatMode::Mode, "Mode", "", false, false, 1, m_supportedModes, defaultValue, 0); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/ThermostatMode.h b/cpp/src/command_classes/ThermostatMode.h index 48bdabb680..2401b2dd19 100644 --- a/cpp/src/command_classes/ThermostatMode.h +++ b/cpp/src/command_classes/ThermostatMode.h @@ -35,44 +35,69 @@ namespace OpenZWave { - class ValueList; - - /** \brief Implements COMMAND_CLASS_THERMOSTAT_MODE (0x40), a Z-Wave device command class. - * \ingroup CommandClass - */ - class ThermostatMode: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new ThermostatMode( _homeId, _nodeId ); } - virtual ~ThermostatMode(){} + namespace CC + { - static uint8 const StaticGetCommandClassId(){ return 0x40; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_THERMOSTAT_MODE"; } + /** \brief Implements COMMAND_CLASS_THERMOSTAT_MODE (0x40), a Z-Wave device command class. + * \ingroup CommandClass + */ + class ThermostatMode: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new ThermostatMode(_homeId, _nodeId); + } + virtual ~ThermostatMode() + { + } - // From CommandClass - virtual void ReadXML( TiXmlElement const* _ccElement ); - virtual void WriteXML( TiXmlElement* _ccElement ); - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _getTypeEnum, uint8 const _dummy, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool SetValue( Value const& _value ); - virtual uint8 GetMaxVersion(){ return 3; } + static uint8 const StaticGetCommandClassId() + { + return 0x40; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_THERMOSTAT_MODE"; + } - protected: - virtual void CreateVars( uint8 const _instance ); + // From CommandClass + virtual void ReadXML(TiXmlElement const* _ccElement) override; + virtual void WriteXML(TiXmlElement* _ccElement) override; + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _getTypeEnum, uint8 const _dummy, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool SetValue(Internal::VC::Value const& _value) override; + virtual uint8 GetMaxVersion() override + { + return 3; + } - private: - ThermostatMode( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){ SetStaticRequest( StaticRequest_Values ); } + protected: + virtual void CreateVars(uint8 const _instance) override; - vector m_supportedModes; - }; + private: + ThermostatMode(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + SetStaticRequest(StaticRequest_Values); + } + vector m_supportedModes; + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif - - - diff --git a/cpp/src/command_classes/ThermostatOperatingState.cpp b/cpp/src/command_classes/ThermostatOperatingState.cpp index 0f7d2fc436..9091ae5708 100644 --- a/cpp/src/command_classes/ThermostatOperatingState.cpp +++ b/cpp/src/command_classes/ThermostatOperatingState.cpp @@ -35,120 +35,97 @@ #include "value_classes/ValueString.h" -using namespace OpenZWave; - -enum ThermostatOperatingStateCmd +namespace OpenZWave { - ThermostatOperatingStateCmd_Get = 0x02, - ThermostatOperatingStateCmd_Report = 0x03 -}; + namespace Internal + { + namespace CC + { -static char const* c_stateName[] = -{ - "Idle", - "Heating", - "Cooling", - "Fan Only", - "Pending Heat", - "Pending Cool", - "Vent / Economizer", - "State 07", // Undefined states. May be used in the future. - "State 08", - "State 09", - "State 10", - "State 11", - "State 12", - "State 13", - "State 14", - "State 15" -}; + enum ThermostatOperatingStateCmd + { + ThermostatOperatingStateCmd_Get = 0x02, + ThermostatOperatingStateCmd_Report = 0x03 + }; + + static char const* c_stateName[] = + { "Idle", "Heating", "Cooling", "Fan Only", "Pending Heat", "Pending Cool", "Vent / Economizer", "State 07", // Undefined states. May be used in the future. + "State 08", "State 09", "State 10", "State 11", "State 12", "State 13", "State 14", "State 15" }; //----------------------------------------------------------------------------- // // Get the static thermostat mode details from the device //----------------------------------------------------------------------------- -bool ThermostatOperatingState::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _requestFlags & RequestFlag_Dynamic ) - { - return RequestValue( _requestFlags, 0, _instance, _queue ); - } - return false; -} + bool ThermostatOperatingState::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_requestFlags & RequestFlag_Dynamic) + { + return RequestValue(_requestFlags, 0, _instance, _queue); + } + return false; + } //----------------------------------------------------------------------------- // // Get a thermostat mode value from the device //----------------------------------------------------------------------------- -bool ThermostatOperatingState::RequestValue -( - uint32 const _requestFlags, - uint16 const _dummy1, // = 0 (not used) - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Msg* msg = new Msg( "ThermostatOperatingStateCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( ThermostatOperatingStateCmd_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "ThermostatOperatingStateCmd_Get Not Supported on this node"); - } - return false; -} + bool ThermostatOperatingState::RequestValue(uint32 const _requestFlags, uint16 const _dummy1, // = 0 (not used) + uint8 const _instance, Driver::MsgQueue const _queue) + { + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Msg* msg = new Msg("ThermostatOperatingStateCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(ThermostatOperatingStateCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "ThermostatOperatingStateCmd_Get Not Supported on this node"); + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool ThermostatOperatingState::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if( ThermostatOperatingStateCmd_Report == (ThermostatOperatingStateCmd)_data[0] ) - { - // We have received the thermostat operating state from the Z-Wave device - if( ValueString* valueString = static_cast( GetValue( _instance, 0 ) ) ) - { - /* no need bounds checking on c_stateName here, as it can only be 1 Byte anyway */ - valueString->OnValueRefreshed( c_stateName[_data[1]&0x0f] ); - valueString->Release(); - Log::Write( LogLevel_Info, GetNodeId(), "Received thermostat operating state: %s", valueString->GetValue().c_str() ); - } - return true; - } + bool ThermostatOperatingState::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) + { + if (ThermostatOperatingStateCmd_Report == (ThermostatOperatingStateCmd) _data[0]) + { + // We have received the thermostat operating state from the Z-Wave device + if (Internal::VC::ValueString* valueString = static_cast(GetValue(_instance, ValueID_Index_ThermostatOperatingState::OperatingState))) + { + /* no need bounds checking on c_stateName here, as it can only be 1 Byte anyway */ + valueString->OnValueRefreshed(c_stateName[_data[1] & 0x0f]); + valueString->Release(); + Log::Write(LogLevel_Info, GetNodeId(), "Received thermostat operating state: %s", valueString->GetValue().c_str()); + } + return true; + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void ThermostatOperatingState::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - node->CreateValueString( ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, "Operating State", "", true, false, c_stateName[0], 0 ); - } -} + void ThermostatOperatingState::CreateVars(uint8 const _instance) + { + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueString(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_ThermostatOperatingState::OperatingState, "Operating State", "", true, false, c_stateName[0], 0); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/ThermostatOperatingState.h b/cpp/src/command_classes/ThermostatOperatingState.h index c160e41a4b..2fbb1a30cc 100644 --- a/cpp/src/command_classes/ThermostatOperatingState.h +++ b/cpp/src/command_classes/ThermostatOperatingState.h @@ -35,38 +35,59 @@ namespace OpenZWave { - class ValueString; - - /** \brief Implements COMMAND_CLASS_THERMOSTAT_OPERATING_STATE (0x42), a Z-Wave device command class. - * \ingroup CommandClass - */ - class ThermostatOperatingState: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new ThermostatOperatingState( _homeId, _nodeId ); } - virtual ~ThermostatOperatingState(){} + namespace CC + { - static uint8 const StaticGetCommandClassId(){ return 0x42; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_THERMOSTAT_OPERATING_STATE"; } + /** \brief Implements COMMAND_CLASS_THERMOSTAT_OPERATING_STATE (0x42), a Z-Wave device command class. + * \ingroup CommandClass + */ + class ThermostatOperatingState: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new ThermostatOperatingState(_homeId, _nodeId); + } + virtual ~ThermostatOperatingState() + { + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); + static uint8 const StaticGetCommandClassId() + { + return 0x42; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_THERMOSTAT_OPERATING_STATE"; + } - protected: - virtual void CreateVars( uint8 const _instance ); + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; - private: - ThermostatOperatingState( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} - }; + protected: + virtual void CreateVars(uint8 const _instance) override; + private: + ThermostatOperatingState(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + } + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif - - - diff --git a/cpp/src/command_classes/ThermostatSetpoint.cpp b/cpp/src/command_classes/ThermostatSetpoint.cpp index dfb809703e..3f9887fc71 100644 --- a/cpp/src/command_classes/ThermostatSetpoint.cpp +++ b/cpp/src/command_classes/ThermostatSetpoint.cpp @@ -37,324 +37,267 @@ #include "tinyxml.h" -using namespace OpenZWave; - -enum ThermostatSetpointCmd +namespace OpenZWave { - ThermostatSetpointCmd_Set = 0x01, - ThermostatSetpointCmd_Get = 0x02, - ThermostatSetpointCmd_Report = 0x03, - ThermostatSetpointCmd_SupportedGet = 0x04, - ThermostatSetpointCmd_SupportedReport = 0x05, - ThermostatSetpointCmd_CapabilitiesGet = 0x09, - ThermostatSetpointCmd_CapabilitiesReport = 0x0A -}; + namespace Internal + { + namespace CC + { -enum -{ - ThermostatSetpoint_Unused0 = 0, - ThermostatSetpoint_Heating1, - ThermostatSetpoint_Cooling1, - ThermostatSetpoint_Unused3, - ThermostatSetpoint_Unused4, - ThermostatSetpoint_Unused5, - ThermostatSetpoint_Unused6, - ThermostatSetpoint_Furnace, - ThermostatSetpoint_DryAir, - ThermostatSetpoint_MoistAir, - ThermostatSetpoint_AutoChangeover, - ThermostatSetpoint_HeatingEcon, - ThermostatSetpoint_CoolingEcon, - ThermostatSetpoint_AwayHeating, - ThermostatSetpoint_CoolingHeating, - ThermostatSetpoint_Count, + enum ThermostatSetpointCmd + { + ThermostatSetpointCmd_Set = 0x01, + ThermostatSetpointCmd_Get = 0x02, + ThermostatSetpointCmd_Report = 0x03, + ThermostatSetpointCmd_SupportedGet = 0x04, + ThermostatSetpointCmd_SupportedReport = 0x05, + ThermostatSetpointCmd_CapabilitiesGet = 0x09, + ThermostatSetpointCmd_CapabilitiesReport = 0x0A + }; - ThermostatSetpoint_Minimum = 100, - ThermostatSetpoint_Maximum = 200 -}; +#define ThermostatSetpoint_Count (ValueID_Index_ThermostatSetpoint::CoolingHeating + 1) - -static char const* c_setpointName[] = -{ - "Unused 0", - "Heating 1", - "Cooling 1", - "Unused 3", - "Unused 4", - "Unused 5", - "Unused 6", - "Furnace", - "Dry Air", - "Moist Air", - "Auto Changeover", - "Heating Econ", - "Cooling Econ", - "Away Heating", - "Away Cooling", - "Full Power" -}; + static char const* c_setpointName[] = + { "Unused 0", "Heating 1", "Cooling 1", "Unused 3", "Unused 4", "Unused 5", "Unused 6", "Furnace", "Dry Air", "Moist Air", "Auto Changeover", "Heating Econ", "Cooling Econ", "Away Heating", "Away Cooling", "Full Power" }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -ThermostatSetpoint::ThermostatSetpoint -( - uint32 const _homeId, - uint8 const _nodeId -): - CommandClass( _homeId, _nodeId ) -{ - m_com.EnableFlag(COMPAT_FLAG_TSSP_BASE, 1); - m_com.EnableFlag(COMPAT_FLAG_TSSP_ALTTYPEINTERPRETATION, true); - SetStaticRequest( StaticRequest_Values ); -} + ThermostatSetpoint::ThermostatSetpoint(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + m_com.EnableFlag(COMPAT_FLAG_TSSP_BASE, 1); + m_com.EnableFlag(COMPAT_FLAG_TSSP_ALTTYPEINTERPRETATION, true); + SetStaticRequest(StaticRequest_Values); + } //----------------------------------------------------------------------------- // // Get the static thermostat setpoint details from the device //----------------------------------------------------------------------------- -bool ThermostatSetpoint::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - bool requests = false; - if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) ) - { - requests |= RequestValue( _requestFlags, 0xff, _instance, _queue ); - } + bool ThermostatSetpoint::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + bool requests = false; + if ((_requestFlags & RequestFlag_Static) && HasStaticRequest(StaticRequest_Values)) + { + requests |= RequestValue(_requestFlags, 0xff, _instance, _queue); + } - if( _requestFlags & RequestFlag_Session ) - { - for( uint8 i=0; i // Request current state from the device //----------------------------------------------------------------------------- -bool ThermostatSetpoint::RequestValue -( - uint32 const _requestFlags, - uint16 const _setPointIndex, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _setPointIndex == 0xff ) // check for supportedget - { - // Request the supported setpoints - Msg* msg = new Msg( "ThermostatSetpointCmd_SupportedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( ThermostatSetpointCmd_SupportedGet ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } - if ( !m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Log::Write( LogLevel_Info, GetNodeId(), "ThermostatSetpointCmd_Get Not Supported on this node"); - return false; - } - Value* value = GetValue( 1, _setPointIndex ); - if( value != NULL ) - { - value->Release(); - // Request the setpoint value - Msg* msg = new Msg( "ThermostatSetpointCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( ThermostatSetpointCmd_Get ); - msg->Append( (_setPointIndex & 0xFF) ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } - return false; -} + bool ThermostatSetpoint::RequestValue(uint32 const _requestFlags, uint16 const _setPointIndex, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_setPointIndex == 0xff) // check for supportedget + { + // Request the supported setpoints + Msg* msg = new Msg("ThermostatSetpointCmd_SupportedGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(ThermostatSetpointCmd_SupportedGet); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + if (!m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Log::Write(LogLevel_Info, GetNodeId(), "ThermostatSetpointCmd_Get Not Supported on this node"); + return false; + } + Internal::VC::Value* value = GetValue(1, _setPointIndex); + if (value != NULL) + { + value->Release(); + // Request the setpoint value + Msg* msg = new Msg("ThermostatSetpointCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(ThermostatSetpointCmd_Get); + msg->Append((_setPointIndex & 0xFF)); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool ThermostatSetpoint::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if( ThermostatSetpointCmd_Report == (ThermostatSetpointCmd)_data[0] ) - { - // We have received a thermostat setpoint value from the Z-Wave device - if( ValueDecimal* value = static_cast( GetValue( _instance, _data[1] ) ) ) - { - uint8 scale; - uint8 precision = 0; - string temperature = ExtractValue( &_data[2], &scale, &precision ); - - value->SetUnits( scale ? "F" : "C" ); - value->OnValueRefreshed( temperature ); - if( value->GetPrecision() != precision ) + bool ThermostatSetpoint::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) { - value->SetPrecision( precision ); - } - value->Release(); + if (ThermostatSetpointCmd_Report == (ThermostatSetpointCmd) _data[0]) + { + // We have received a thermostat setpoint value from the Z-Wave device + if (Internal::VC::ValueDecimal* value = static_cast(GetValue(_instance, _data[1]))) + { + uint8 scale; + uint8 precision = 0; + string temperature = ExtractValue(&_data[2], &scale, &precision); - Log::Write( LogLevel_Info, GetNodeId(), "Received thermostat setpoint report: Setpoint %s = %s%s", value->GetLabel().c_str(), value->GetValue().c_str(), value->GetUnits().c_str() ); - } - return true; - } + value->SetUnits(scale ? "F" : "C"); + value->OnValueRefreshed(temperature); + if (value->GetPrecision() != precision) + { + value->SetPrecision(precision); + } + value->Release(); - else if( ThermostatSetpointCmd_SupportedReport == (ThermostatSetpointCmd)_data[0] ) - { - if( Node* node = GetNodeUnsafe() ) - { - // We have received the supported thermostat setpoints from the Z-Wave device - Log::Write( LogLevel_Info, GetNodeId(), "Received supported thermostat setpoints" ); + Log::Write(LogLevel_Info, GetNodeId(), "Received thermostat setpoint report: Setpoint %s = %s%s", value->GetLabel().c_str(), value->GetValue().c_str(), value->GetUnits().c_str()); + } + return true; + } - // Parse the data for the supported setpoints - for( uint32 i=1; i<_length-1; ++i ) - { - for( int32 bit=0; bit<8; ++bit ) + else if (ThermostatSetpointCmd_SupportedReport == (ThermostatSetpointCmd) _data[0]) { - if( ( _data[i] & (1<= 3) + // We have received the supported thermostat setpoints from the Z-Wave device + Log::Write(LogLevel_Info, GetNodeId(), "Received supported thermostat setpoints"); + + // Parse the data for the supported setpoints + for (uint32 i = 1; i < _length - 1; ++i) { - // Request the supported setpoints - Msg* msg = new Msg( "ThermostatSetpointCmd_CapabilitesGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( ThermostatSetpointCmd_CapabilitiesGet ); - uint8 type = ((i-1)<<3) + bit; - if ( m_com.GetFlagBool(COMPAT_FLAG_TSSP_ALTTYPEINTERPRETATION) == false ) + for (int32 bit = 0; bit < 8; ++bit) { - // for interpretation A the setpoint identifier makes a jump of 4 after the 2nd bit ... wtf @ zensys - if ( type > 2 ) + if ((_data[i] & (1 << bit)) != 0) { - type += 4; + if (GetVersion() >= 3) + { + // Request the supported setpoints + Msg* msg = new Msg("ThermostatSetpointCmd_CapabilitesGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(ThermostatSetpointCmd_CapabilitiesGet); + uint8 type = ((i - 1) << 3) + bit; + if (m_com.GetFlagBool(COMPAT_FLAG_TSSP_ALTTYPEINTERPRETATION) == false) + { + // for interpretation A the setpoint identifier makes a jump of 4 after the 2nd bit ... wtf @ zensys + if (type > 2) + { + type += 4; + } + } + msg->Append(type); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, OpenZWave::Driver::MsgQueue_Query); + } + + uint8 type = ((i - 1) << 3) + bit; + if (m_com.GetFlagBool(COMPAT_FLAG_TSSP_ALTTYPEINTERPRETATION) == false) + { + // for interpretation A the setpoint identifier makes a jump of 4 after the 2nd bit ... wtf @ zensys + if (type > 2) + { + type += 4; + } + } + int32 index = (int32) type + m_com.GetFlagByte(COMPAT_FLAG_TSSP_BASE); + // Add supported setpoint + if (index < ThermostatSetpoint_Count) + { + string setpointName = c_setpointName[index]; + + node->CreateValueDecimal(ValueID::ValueGenre_User, GetCommandClassId(), _instance, index, setpointName, "C", false, false, "0.0", 0); + Log::Write(LogLevel_Info, GetNodeId(), " Added setpoint: %s", setpointName.c_str()); + } } } - msg->Append(type); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, OpenZWave::Driver::MsgQueue_Query ); } + } - uint8 type = ((i-1)<<3) + bit; - if ( m_com.GetFlagBool(COMPAT_FLAG_TSSP_ALTTYPEINTERPRETATION) == false ) - { - // for interpretation A the setpoint identifier makes a jump of 4 after the 2nd bit ... wtf @ zensys - if ( type > 2 ) - { - type += 4; - } - } - int32 index = (int32)type + m_com.GetFlagByte(COMPAT_FLAG_TSSP_BASE); + ClearStaticRequest(StaticRequest_Values); + return true; + } + else if (ThermostatSetpointCmd_CapabilitiesReport == (ThermostatSetpointCmd) _data[0]) + { + if (Node* node = GetNodeUnsafe()) + { + // We have received the capabilities for supported setpoint Type + uint8 scale; + uint8 precision = 0; + uint8 size = _data[2] & 0x07; + string minValue = ExtractValue(&_data[2], &scale, &precision); + string maxValue = ExtractValue(&_data[2 + size + 1], &scale, &precision); + + Log::Write(LogLevel_Info, GetNodeId(), "Received capabilities of thermostat setpoint type %d, min %s max %s", (int) _data[1], minValue.c_str(), maxValue.c_str()); + + uint8 index = _data[1]; // Add supported setpoint - if( index < ThermostatSetpoint_Count ) + if (index < ThermostatSetpoint_Count) { string setpointName = c_setpointName[index]; - node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, index, setpointName, "C", false, false, "0.0", 0 ); - Log::Write( LogLevel_Info, GetNodeId(), " Added setpoint: %s", setpointName.c_str() ); + node->CreateValueDecimal(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_ThermostatSetpoint::Unused_0_Minimum + index, setpointName + "_minimum", "C", false, false, minValue, 0); + node->CreateValueDecimal(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_ThermostatSetpoint::Unused_0_Maximum + index, setpointName + "_maximum", "C", false, false, maxValue, 0); + Log::Write(LogLevel_Info, GetNodeId(), " Added setpoint: %s", setpointName.c_str()); } + } } - } - } - ClearStaticRequest( StaticRequest_Values ); - return true; - } - else if( ThermostatSetpointCmd_CapabilitiesReport == (ThermostatSetpointCmd)_data[0] ) - { - if( Node* node = GetNodeUnsafe() ) - { - // We have received the capabilites for supported setpoint Type - uint8 scale; - uint8 precision = 0; - uint8 size = _data[2] & 0x07; - string minValue = ExtractValue( &_data[2], &scale, &precision ); - string maxValue = ExtractValue( &_data[2+size+1], &scale, &precision ); - - Log::Write( LogLevel_Info, GetNodeId(), "Received capabilites of thermostat setpoint type %d, min %s max %s" , (int)_data[1], minValue.c_str(), maxValue.c_str()); - - uint8 index = _data[1]; - // Add supported setpoint - if( index < ThermostatSetpoint_Count ) - { - string setpointName = c_setpointName[index]; - - node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, ThermostatSetpoint_Minimum + index, setpointName + "_minimum", "C", false, false, minValue, 0 ); - node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, ThermostatSetpoint_Maximum + index, setpointName + "_maximum", "C", false, false, maxValue, 0 ); - Log::Write( LogLevel_Info, GetNodeId(), " Added setpoint: %s", setpointName.c_str() ); + return false; } - } - } - - return false; -} - //----------------------------------------------------------------------------- // // Set a thermostat setpoint temperature //----------------------------------------------------------------------------- -bool ThermostatSetpoint::SetValue -( - Value const& _value -) -{ - if( ValueID::ValueType_Decimal == _value.GetID().GetType() ) - { - ValueDecimal const* value = static_cast(&_value); - uint8 scale = strcmp( "C", value->GetUnits().c_str() ) ? 1 : 0; + bool ThermostatSetpoint::SetValue(Internal::VC::Value const& _value) + { + if (ValueID::ValueType_Decimal == _value.GetID().GetType()) + { + Internal::VC::ValueDecimal const* value = static_cast(&_value); + uint8 scale = strcmp("C", value->GetUnits().c_str()) ? 1 : 0; - Msg* msg = new Msg( "ThermostatSetpointCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->SetInstance( this, _value.GetID().GetInstance() ); - msg->Append( GetNodeId() ); - msg->Append( 4 + GetAppendValueSize( value->GetValue() ) ); - msg->Append( GetCommandClassId() ); - msg->Append( ThermostatSetpointCmd_Set ); - msg->Append( (uint8_t)(value->GetID().GetIndex() & 0xFF) ); - AppendValue( msg, value->GetValue(), scale ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - return true; - } + Msg* msg = new Msg("ThermostatSetpointCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->SetInstance(this, _value.GetID().GetInstance()); + msg->Append(GetNodeId()); + msg->Append(4 + GetAppendValueSize(value->GetValue())); + msg->Append(GetCommandClassId()); + msg->Append(ThermostatSetpointCmd_Set); + msg->Append((uint8_t) (value->GetID().GetIndex() & 0xFF)); + AppendValue(msg, value->GetValue(), scale); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return true; + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void ThermostatSetpoint::CreateVars -( - uint8 const _instance, - uint8 const _index -) -{ - if( Node* node = GetNodeUnsafe() ) - { - node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, _index, "Setpoint", "C", false, false, "0.0", 0 ); - } -} + void ThermostatSetpoint::CreateVars(uint8 const _instance, uint8 const _index) + { + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueDecimal(ValueID::ValueGenre_User, GetCommandClassId(), _instance, _index, "Setpoint", "C", false, false, "0.0", 0); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/ThermostatSetpoint.h b/cpp/src/command_classes/ThermostatSetpoint.h index dde217ee37..6b7db36417 100644 --- a/cpp/src/command_classes/ThermostatSetpoint.h +++ b/cpp/src/command_classes/ThermostatSetpoint.h @@ -34,39 +34,61 @@ namespace OpenZWave { - class ValueDecimal; - - /** \brief Implements COMMAND_CLASS_THERMOSTAT_SETPOINT (0x43), a Z-Wave device command class. - * \ingroup CommandClass - */ - class ThermostatSetpoint: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new ThermostatSetpoint( _homeId, _nodeId ); } - virtual ~ThermostatSetpoint(){} + namespace CC + { - static uint8 const StaticGetCommandClassId(){ return 0x43; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_THERMOSTAT_SETPOINT"; } + /** \brief Implements COMMAND_CLASS_THERMOSTAT_SETPOINT (0x43), a Z-Wave device command class. + * \ingroup CommandClass + */ + class ThermostatSetpoint: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new ThermostatSetpoint(_homeId, _nodeId); + } + virtual ~ThermostatSetpoint() + { + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _setPointIndex, uint8 const _dummy, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool SetValue( Value const& _value ); - virtual uint8 GetMaxVersion(){ return 3; } + static uint8 const StaticGetCommandClassId() + { + return 0x43; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_THERMOSTAT_SETPOINT"; + } - public: - virtual void CreateVars( uint8 const _instance, uint8 const _index ); + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _setPointIndex, uint8 const _dummy, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool SetValue(Internal::VC::Value const& _value) override; + virtual uint8 GetMaxVersion() override + { + return 3; + } - private: - ThermostatSetpoint( uint32 const _homeId, uint8 const _nodeId ); - }; + protected: + virtual void CreateVars(uint8 const _instance, uint8 const _index) override; + private: + ThermostatSetpoint(uint32 const _homeId, uint8 const _nodeId); + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif - - diff --git a/cpp/src/command_classes/TimeParameters.cpp b/cpp/src/command_classes/TimeParameters.cpp index 3780345cca..b06188c3b8 100644 --- a/cpp/src/command_classes/TimeParameters.cpp +++ b/cpp/src/command_classes/TimeParameters.cpp @@ -38,205 +38,180 @@ #include "value_classes/ValueButton.h" #include "value_classes/ValueString.h" -using namespace OpenZWave; - -enum TimeParametersCmd -{ - TimeParametersCmd_Set = 0x01, - TimeParametersCmd_Get = 0x02, - TimeParametersCmd_Report = 0x03 -}; - -enum +namespace OpenZWave { - TimeParametersIndex_Date = 0, - TimeParametersIndex_Time, - TimeParametersIndex_Set, - TimeParametersIndex_Refresh -}; + namespace Internal + { + namespace CC + { + enum TimeParametersCmd + { + TimeParametersCmd_Set = 0x01, + TimeParametersCmd_Get = 0x02, + TimeParametersCmd_Report = 0x03 + }; //----------------------------------------------------------------------------- -// +// // Constructor //----------------------------------------------------------------------------- -TimeParameters::TimeParameters -( - uint32 const _homeId, - uint8 const _nodeId -): - CommandClass( _homeId, _nodeId ) -{ - SetStaticRequest( StaticRequest_Values ); -} - + TimeParameters::TimeParameters(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + SetStaticRequest(StaticRequest_Values); + } //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool TimeParameters::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) ) - { - return RequestValue( _requestFlags, 0, _instance, _queue ); - } + bool TimeParameters::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + if ((_requestFlags & RequestFlag_Static) && HasStaticRequest(StaticRequest_Values)) + { + return RequestValue(_requestFlags, 0, _instance, _queue); + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool TimeParameters::RequestValue -( - uint32 const _requestFlags, - uint16 const _dummy1, // = 0 (not used) - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Msg* msg = new Msg( "TimeParametersCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( TimeParametersCmd_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "TimeParametersCmd_Get Not Supported on this node"); - } - return false; -} + bool TimeParameters::RequestValue(uint32 const _requestFlags, uint16 const _dummy1, // = 0 (not used) + uint8 const _instance, Driver::MsgQueue const _queue) + { + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Msg* msg = new Msg("TimeParametersCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(TimeParametersCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "TimeParametersCmd_Get Not Supported on this node"); + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool TimeParameters::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if (TimeParametersCmd_Report == (TimeParametersCmd)_data[0]) - { - uint16 year = (_data[1] << 8) + (_data[2] & 0xFF); - uint8 month = (_data[3] & 0x0F); - uint8 day = (_data[4] & 0x1F); - uint8 hour = (_data[5] & 0x1F); - uint8 minute = (_data[6] & 0x3F); - uint8 second = (_data[7] & 0x3F); - - Log::Write( LogLevel_Info, GetNodeId(), "Received TimeParameters report: %02d/%02d/%04d %02d:%02d:%02d", (int)day, (int)month, (int)year, (int)hour, (int)minute, (int)second); - if( ValueString* value = static_cast( GetValue( _instance, TimeParametersIndex_Date ) ) ) - { - char msg[512]; - snprintf(msg, sizeof(msg), "%02d/%02d/%04d", (int)day, (int)month, (int)year); - value->OnValueRefreshed( msg ); - value->Release(); - } - if( ValueString* value = static_cast( GetValue( _instance, TimeParametersIndex_Time ) ) ) - { - char msg[512]; - snprintf(msg, sizeof(msg), "%02d:%02d:%02d", (int)hour, (int)minute, (int)second); - value->OnValueRefreshed( msg ); - value->Release(); - } - ClearStaticRequest( StaticRequest_Values ); - return true; - } - - return false; -} + bool TimeParameters::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) + { + if (TimeParametersCmd_Report == (TimeParametersCmd) _data[0]) + { + uint16 year = (_data[1] << 8) + (_data[2] & 0xFF); + uint8 month = (_data[3] & 0x0F); + uint8 day = (_data[4] & 0x1F); + uint8 hour = (_data[5] & 0x1F); + uint8 minute = (_data[6] & 0x3F); + uint8 second = (_data[7] & 0x3F); + + Log::Write(LogLevel_Info, GetNodeId(), "Received TimeParameters report: %02d/%02d/%04d %02d:%02d:%02d", (int) day, (int) month, (int) year, (int) hour, (int) minute, (int) second); + if (Internal::VC::ValueString* value = static_cast(GetValue(_instance, ValueID_Index_TimeParameters::Date))) + { + char msg[512]; + snprintf(msg, sizeof(msg), "%02d/%02d/%04d", (int) day, (int) month, (int) year); + value->OnValueRefreshed(msg); + value->Release(); + } + if (Internal::VC::ValueString* value = static_cast(GetValue(_instance, ValueID_Index_TimeParameters::Time))) + { + char msg[512]; + snprintf(msg, sizeof(msg), "%02d:%02d:%02d", (int) hour, (int) minute, (int) second); + value->OnValueRefreshed(msg); + value->Release(); + } + ClearStaticRequest(StaticRequest_Values); + return true; + } + + return false; + } //----------------------------------------------------------------------------- // // Set a value in the Z-Wave device //----------------------------------------------------------------------------- -bool TimeParameters::SetValue -( - Value const& _value -) -{ - bool ret = false; - - uint8 instance = _value.GetID().GetInstance(); - - if ( (ValueID::ValueType_Button == _value.GetID().GetType()) && (_value.GetID().GetIndex() == TimeParametersIndex_Set) ) - { - time_t rawtime; - struct tm *timeinfo; - time(&rawtime); - // use threadsafe verion of localtime. Reported by nihilus, 2019-04 - // https://www.gnu.org/software/libc/manual/html_node/Broken_002ddown-Time.html#Broken_002ddown-Time - struct tm xtm; - memset(&xtm, 0, sizeof(xtm)); - timeinfo = localtime_r( &rawtime, &xtm); - - Msg* msg = new Msg( "TimeParametersCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, instance ); - msg->Append( GetNodeId() ); - msg->Append( 9 ); - msg->Append( GetCommandClassId() ); - msg->Append( TimeParametersCmd_Set ); - /* Year 1 */ - msg->Append( ((timeinfo->tm_year + 1900)>> 8) & 0xFF); - /* Year 2 */ - msg->Append( ((timeinfo->tm_year + 1900) & 0xFF)); - /* Month */ - msg->Append( (timeinfo->tm_mon & 0x0F)+1); - /* Day */ - msg->Append( (timeinfo->tm_mday & 0x1F)); - /* Hour */ - msg->Append( (timeinfo->tm_hour & 0x1F)); - /* Minute */ - msg->Append( (timeinfo->tm_min & 0x3F)); - /* Second */ - msg->Append( (timeinfo->tm_sec & 0x3F)); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - - - /* Refresh after we send updated date/time */ - SetStaticRequest( StaticRequest_Values ); - ret = RequestValue( RequestFlag_Static, 0, instance, Driver::MsgQueue_Query ); - } - if ( (ValueID::ValueType_Button == _value.GetID().GetType()) && (_value.GetID().GetIndex() == TimeParametersIndex_Refresh) ) - { - SetStaticRequest( StaticRequest_Values ); - ret = RequestValue( RequestFlag_Static, 0, instance, Driver::MsgQueue_Query ); - } - - return ret; -} + bool TimeParameters::SetValue(Internal::VC::Value const& _value) + { + bool ret = false; + + uint8 instance = _value.GetID().GetInstance(); + + if ((ValueID::ValueType_Button == _value.GetID().GetType()) && (_value.GetID().GetIndex() == ValueID_Index_TimeParameters::Set)) + { + time_t rawtime; + struct tm *timeinfo; + time(&rawtime); + // use threadsafe verion of localtime. Reported by nihilus, 2019-04 + // https://www.gnu.org/software/libc/manual/html_node/Broken_002ddown-Time.html#Broken_002ddown-Time + struct tm xtm; + memset(&xtm, 0, sizeof(xtm)); + timeinfo = localtime_r(&rawtime, &xtm); + + Msg* msg = new Msg("TimeParametersCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, instance); + msg->Append(GetNodeId()); + msg->Append(9); + msg->Append(GetCommandClassId()); + msg->Append(TimeParametersCmd_Set); + /* Year 1 */ + msg->Append(((timeinfo->tm_year + 1900) >> 8) & 0xFF); + /* Year 2 */ + msg->Append(((timeinfo->tm_year + 1900) & 0xFF)); + /* Month */ + msg->Append((timeinfo->tm_mon & 0x0F) + 1); + /* Day */ + msg->Append((timeinfo->tm_mday & 0x1F)); + /* Hour */ + msg->Append((timeinfo->tm_hour & 0x1F)); + /* Minute */ + msg->Append((timeinfo->tm_min & 0x3F)); + /* Second */ + msg->Append((timeinfo->tm_sec & 0x3F)); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + + /* Refresh after we send updated date/time */ + SetStaticRequest(StaticRequest_Values); + ret = RequestValue(RequestFlag_Static, 0, instance, Driver::MsgQueue_Query); + } + if ((ValueID::ValueType_Button == _value.GetID().GetType()) && (_value.GetID().GetIndex() == ValueID_Index_TimeParameters::Refresh)) + { + SetStaticRequest(StaticRequest_Values); + ret = RequestValue(RequestFlag_Static, 0, instance, Driver::MsgQueue_Query); + } + + return ret; + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void TimeParameters::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - node->CreateValueString( ValueID::ValueGenre_System, GetCommandClassId(), _instance, TimeParametersIndex_Date, "Date", "", true, false, "", 0 ); - node->CreateValueString( ValueID::ValueGenre_System, GetCommandClassId(), _instance, TimeParametersIndex_Time, "Time", "", true, false, "", 0 ); - node->CreateValueButton( ValueID::ValueGenre_System, GetCommandClassId(), _instance, TimeParametersIndex_Set, "Set Date/Time", 0); - node->CreateValueButton( ValueID::ValueGenre_System, GetCommandClassId(), _instance, TimeParametersIndex_Refresh, "Refresh Date/Time", 0); - - } -} + void TimeParameters::CreateVars(uint8 const _instance) + { + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueString(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_TimeParameters::Date, "Date", "", true, false, "", 0); + node->CreateValueString(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_TimeParameters::Time, "Time", "", true, false, "", 0); + node->CreateValueButton(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_TimeParameters::Set, "Set Date/Time", 0); + node->CreateValueButton(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_TimeParameters::Refresh, "Refresh Date/Time", 0); + + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/TimeParameters.h b/cpp/src/command_classes/TimeParameters.h index 1d2f10d3c1..85a826ba90 100644 --- a/cpp/src/command_classes/TimeParameters.h +++ b/cpp/src/command_classes/TimeParameters.h @@ -32,36 +32,56 @@ namespace OpenZWave { - class ValueByte; - class ValueList; - - /** \brief Implements COMMAND_CLASS_TIME_PARAMETERS (0x8B), a Z-Wave device command class. - * \ingroup CommandClass - */ - class TimeParameters: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new TimeParameters( _homeId, _nodeId ); } - virtual ~TimeParameters(){} + namespace CC + { - static uint8 const StaticGetCommandClassId(){ return 0x8B; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_TIME_PARAMETERS"; } + /** \brief Implements COMMAND_CLASS_TIME_PARAMETERS (0x8B), a Z-Wave device command class. + * \ingroup CommandClass + */ + class TimeParameters: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new TimeParameters(_homeId, _nodeId); + } + virtual ~TimeParameters() + { + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool SetValue( Value const& _value ); + static uint8 const StaticGetCommandClassId() + { + return 0x8B; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_TIME_PARAMETERS"; + } - protected: - virtual void CreateVars( uint8 const _instance ); + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool SetValue(Internal::VC::Value const& _value) override; - private: - TimeParameters( uint32 const _homeId, uint8 const _nodeId ); - }; + protected: + virtual void CreateVars(uint8 const _instance) override; + private: + TimeParameters(uint32 const _homeId, uint8 const _nodeId); + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/UserCode.cpp b/cpp/src/command_classes/UserCode.cpp index dab0067314..1f619f2ef7 100644 --- a/cpp/src/command_classes/UserCode.cpp +++ b/cpp/src/command_classes/UserCode.cpp @@ -37,662 +37,390 @@ #include "value_classes/ValueString.h" #include "value_classes/ValueRaw.h" -using namespace OpenZWave; - -enum UserCodeCmd -{ - UserCodeCmd_Set = 0x01, - UserCodeCmd_Get = 0x02, - UserCodeCmd_Report = 0x03, - UserNumberCmd_Get = 0x04, - UserNumberCmd_Report = 0x05 -}; - -enum +namespace OpenZWave { - UserCodeIndex_Pos_1 = 1, - UserCodeIndex_Pos_2 = 2, - UserCodeIndex_Pos_3 = 3, - UserCodeIndex_Pos_4 = 4, - UserCodeIndex_Pos_5 = 5, - UserCodeIndex_Pos_6 = 6, - UserCodeIndex_Pos_7 = 7, - UserCodeIndex_Pos_8 = 8, - UserCodeIndex_Pos_9 = 9, - UserCodeIndex_Pos_10 = 10, - UserCodeIndex_Pos_11 = 11, - UserCodeIndex_Pos_12 = 12, - UserCodeIndex_Pos_13 = 13, - UserCodeIndex_Pos_14 = 14, - UserCodeIndex_Pos_15 = 15, - UserCodeIndex_Pos_16 = 16, - UserCodeIndex_Pos_17 = 17, - UserCodeIndex_Pos_18 = 18, - UserCodeIndex_Pos_19 = 19, - UserCodeIndex_Pos_20 = 20, - UserCodeIndex_Pos_21 = 21, - UserCodeIndex_Pos_22 = 22, - UserCodeIndex_Pos_23 = 23, - UserCodeIndex_Pos_24 = 24, - UserCodeIndex_Pos_25 = 25, - UserCodeIndex_Pos_26 = 26, - UserCodeIndex_Pos_27 = 27, - UserCodeIndex_Pos_28 = 28, - UserCodeIndex_Pos_29 = 29, - UserCodeIndex_Pos_30 = 30, - UserCodeIndex_Pos_31 = 31, - UserCodeIndex_Pos_32 = 32, - UserCodeIndex_Pos_33 = 33, - UserCodeIndex_Pos_34 = 34, - UserCodeIndex_Pos_35 = 35, - UserCodeIndex_Pos_36 = 36, - UserCodeIndex_Pos_37 = 37, - UserCodeIndex_Pos_38 = 38, - UserCodeIndex_Pos_39 = 39, - UserCodeIndex_Pos_40 = 40, - UserCodeIndex_Pos_41 = 41, - UserCodeIndex_Pos_42 = 42, - UserCodeIndex_Pos_43 = 43, - UserCodeIndex_Pos_44 = 44, - UserCodeIndex_Pos_45 = 45, - UserCodeIndex_Pos_46 = 46, - UserCodeIndex_Pos_47 = 47, - UserCodeIndex_Pos_48 = 48, - UserCodeIndex_Pos_49 = 49, - UserCodeIndex_Pos_50 = 50, - UserCodeIndex_Pos_51 = 51, - UserCodeIndex_Pos_52 = 52, - UserCodeIndex_Pos_53 = 53, - UserCodeIndex_Pos_54 = 54, - UserCodeIndex_Pos_55 = 55, - UserCodeIndex_Pos_56 = 56, - UserCodeIndex_Pos_57 = 57, - UserCodeIndex_Pos_58 = 58, - UserCodeIndex_Pos_59 = 59, - UserCodeIndex_Pos_60 = 60, - UserCodeIndex_Pos_61 = 61, - UserCodeIndex_Pos_62 = 62, - UserCodeIndex_Pos_63 = 63, - UserCodeIndex_Pos_64 = 64, - UserCodeIndex_Pos_65 = 65, - UserCodeIndex_Pos_66 = 66, - UserCodeIndex_Pos_67 = 67, - UserCodeIndex_Pos_68 = 68, - UserCodeIndex_Pos_69 = 69, - UserCodeIndex_Pos_70 = 70, - UserCodeIndex_Pos_71 = 71, - UserCodeIndex_Pos_72 = 72, - UserCodeIndex_Pos_73 = 73, - UserCodeIndex_Pos_74 = 74, - UserCodeIndex_Pos_75 = 75, - UserCodeIndex_Pos_76 = 76, - UserCodeIndex_Pos_77 = 77, - UserCodeIndex_Pos_78 = 78, - UserCodeIndex_Pos_79 = 79, - UserCodeIndex_Pos_80 = 80, - UserCodeIndex_Pos_81 = 81, - UserCodeIndex_Pos_82 = 82, - UserCodeIndex_Pos_83 = 83, - UserCodeIndex_Pos_84 = 84, - UserCodeIndex_Pos_85 = 85, - UserCodeIndex_Pos_86 = 86, - UserCodeIndex_Pos_87 = 87, - UserCodeIndex_Pos_88 = 88, - UserCodeIndex_Pos_89 = 89, - UserCodeIndex_Pos_90 = 90, - UserCodeIndex_Pos_91 = 91, - UserCodeIndex_Pos_92 = 92, - UserCodeIndex_Pos_93 = 93, - UserCodeIndex_Pos_94 = 94, - UserCodeIndex_Pos_95 = 95, - UserCodeIndex_Pos_96 = 96, - UserCodeIndex_Pos_97 = 97, - UserCodeIndex_Pos_98 = 98, - UserCodeIndex_Pos_99 = 99, - UserCodeIndex_Pos_100 = 100, - UserCodeIndex_Pos_101 = 101, - UserCodeIndex_Pos_102 = 102, - UserCodeIndex_Pos_103 = 103, - UserCodeIndex_Pos_104 = 104, - UserCodeIndex_Pos_105 = 105, - UserCodeIndex_Pos_106 = 106, - UserCodeIndex_Pos_107 = 107, - UserCodeIndex_Pos_108 = 108, - UserCodeIndex_Pos_109 = 109, - UserCodeIndex_Pos_110 = 110, - UserCodeIndex_Pos_111 = 111, - UserCodeIndex_Pos_112 = 112, - UserCodeIndex_Pos_113 = 113, - UserCodeIndex_Pos_114 = 114, - UserCodeIndex_Pos_115 = 115, - UserCodeIndex_Pos_116 = 116, - UserCodeIndex_Pos_117 = 117, - UserCodeIndex_Pos_118 = 118, - UserCodeIndex_Pos_119 = 119, - UserCodeIndex_Pos_120 = 120, - UserCodeIndex_Pos_121 = 121, - UserCodeIndex_Pos_122 = 122, - UserCodeIndex_Pos_123 = 123, - UserCodeIndex_Pos_124 = 124, - UserCodeIndex_Pos_125 = 125, - UserCodeIndex_Pos_126 = 126, - UserCodeIndex_Pos_127 = 127, - UserCodeIndex_Pos_128 = 128, - UserCodeIndex_Pos_129 = 129, - UserCodeIndex_Pos_130 = 130, - UserCodeIndex_Pos_131 = 131, - UserCodeIndex_Pos_132 = 132, - UserCodeIndex_Pos_133 = 133, - UserCodeIndex_Pos_134 = 134, - UserCodeIndex_Pos_135 = 135, - UserCodeIndex_Pos_136 = 136, - UserCodeIndex_Pos_137 = 137, - UserCodeIndex_Pos_138 = 138, - UserCodeIndex_Pos_139 = 139, - UserCodeIndex_Pos_140 = 140, - UserCodeIndex_Pos_141 = 141, - UserCodeIndex_Pos_142 = 142, - UserCodeIndex_Pos_143 = 143, - UserCodeIndex_Pos_144 = 144, - UserCodeIndex_Pos_145 = 145, - UserCodeIndex_Pos_146 = 146, - UserCodeIndex_Pos_147 = 147, - UserCodeIndex_Pos_148 = 148, - UserCodeIndex_Pos_149 = 149, - UserCodeIndex_Pos_150 = 150, - UserCodeIndex_Pos_151 = 151, - UserCodeIndex_Pos_152 = 152, - UserCodeIndex_Pos_153 = 153, - UserCodeIndex_Pos_154 = 154, - UserCodeIndex_Pos_155 = 155, - UserCodeIndex_Pos_156 = 156, - UserCodeIndex_Pos_157 = 157, - UserCodeIndex_Pos_158 = 158, - UserCodeIndex_Pos_159 = 159, - UserCodeIndex_Pos_160 = 160, - UserCodeIndex_Pos_161 = 161, - UserCodeIndex_Pos_162 = 162, - UserCodeIndex_Pos_163 = 163, - UserCodeIndex_Pos_164 = 164, - UserCodeIndex_Pos_165 = 165, - UserCodeIndex_Pos_166 = 166, - UserCodeIndex_Pos_167 = 167, - UserCodeIndex_Pos_168 = 168, - UserCodeIndex_Pos_169 = 169, - UserCodeIndex_Pos_170 = 170, - UserCodeIndex_Pos_171 = 171, - UserCodeIndex_Pos_172 = 172, - UserCodeIndex_Pos_173 = 173, - UserCodeIndex_Pos_174 = 174, - UserCodeIndex_Pos_175 = 175, - UserCodeIndex_Pos_176 = 176, - UserCodeIndex_Pos_177 = 177, - UserCodeIndex_Pos_178 = 178, - UserCodeIndex_Pos_179 = 179, - UserCodeIndex_Pos_180 = 180, - UserCodeIndex_Pos_181 = 181, - UserCodeIndex_Pos_182 = 182, - UserCodeIndex_Pos_183 = 183, - UserCodeIndex_Pos_184 = 184, - UserCodeIndex_Pos_185 = 185, - UserCodeIndex_Pos_186 = 186, - UserCodeIndex_Pos_187 = 187, - UserCodeIndex_Pos_188 = 188, - UserCodeIndex_Pos_189 = 189, - UserCodeIndex_Pos_190 = 190, - UserCodeIndex_Pos_191 = 191, - UserCodeIndex_Pos_192 = 192, - UserCodeIndex_Pos_193 = 193, - UserCodeIndex_Pos_194 = 194, - UserCodeIndex_Pos_195 = 195, - UserCodeIndex_Pos_196 = 196, - UserCodeIndex_Pos_197 = 197, - UserCodeIndex_Pos_198 = 198, - UserCodeIndex_Pos_199 = 199, - UserCodeIndex_Pos_200 = 200, - UserCodeIndex_Pos_201 = 201, - UserCodeIndex_Pos_202 = 202, - UserCodeIndex_Pos_203 = 203, - UserCodeIndex_Pos_204 = 204, - UserCodeIndex_Pos_205 = 205, - UserCodeIndex_Pos_206 = 206, - UserCodeIndex_Pos_207 = 207, - UserCodeIndex_Pos_208 = 208, - UserCodeIndex_Pos_209 = 209, - UserCodeIndex_Pos_210 = 210, - UserCodeIndex_Pos_211 = 211, - UserCodeIndex_Pos_212 = 212, - UserCodeIndex_Pos_213 = 213, - UserCodeIndex_Pos_214 = 214, - UserCodeIndex_Pos_215 = 215, - UserCodeIndex_Pos_216 = 216, - UserCodeIndex_Pos_217 = 217, - UserCodeIndex_Pos_218 = 218, - UserCodeIndex_Pos_219 = 219, - UserCodeIndex_Pos_220 = 220, - UserCodeIndex_Pos_221 = 221, - UserCodeIndex_Pos_222 = 222, - UserCodeIndex_Pos_223 = 223, - UserCodeIndex_Pos_224 = 224, - UserCodeIndex_Pos_225 = 225, - UserCodeIndex_Pos_226 = 226, - UserCodeIndex_Pos_227 = 227, - UserCodeIndex_Pos_228 = 228, - UserCodeIndex_Pos_229 = 229, - UserCodeIndex_Pos_230 = 230, - UserCodeIndex_Pos_231 = 231, - UserCodeIndex_Pos_232 = 232, - UserCodeIndex_Pos_233 = 233, - UserCodeIndex_Pos_234 = 234, - UserCodeIndex_Pos_235 = 235, - UserCodeIndex_Pos_236 = 236, - UserCodeIndex_Pos_237 = 237, - UserCodeIndex_Pos_238 = 238, - UserCodeIndex_Pos_239 = 239, - UserCodeIndex_Pos_240 = 240, - UserCodeIndex_Pos_241 = 241, - UserCodeIndex_Pos_242 = 242, - UserCodeIndex_Pos_243 = 243, - UserCodeIndex_Pos_244 = 244, - UserCodeIndex_Pos_245 = 245, - UserCodeIndex_Pos_246 = 246, - UserCodeIndex_Pos_247 = 247, - UserCodeIndex_Pos_248 = 248, - UserCodeIndex_Pos_249 = 249, - UserCodeIndex_Pos_250 = 250, - UserCodeIndex_Pos_251 = 251, - UserCodeIndex_Pos_252 = 252, - UserCodeIndex_Pos_253 = 253, - UserCodeIndex_Pos_254 = 254, - UserCodeIndex_Refresh = 255, - UserCodeIndex_RemoveCode = 256, - UserCodeIndex_Count = 257, - UserCodeIndex_RawValue = 258, - UserCodeIndex_RawValueIndex = 259 -}; + namespace Internal + { + namespace CC + { + enum UserCodeCmd + { + UserCodeCmd_Set = 0x01, + UserCodeCmd_Get = 0x02, + UserCodeCmd_Report = 0x03, + UserNumberCmd_Get = 0x04, + UserNumberCmd_Report = 0x05 + }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -UserCode::UserCode -( - uint32 const _homeId, - uint8 const _nodeId -): - CommandClass( _homeId, _nodeId ), - m_queryAll( false ), - m_currentCode( 0 ), - m_refreshUserCodes(false) -{ - m_com.EnableFlag(COMPAT_FLAG_UC_EXPOSERAWVALUE, false); - m_dom.EnableFlag(STATE_FLAG_USERCODE_COUNT, 0); - SetStaticRequest( StaticRequest_Values ); - Options::Get()->GetOptionAsBool("RefreshAllUserCodes", &m_refreshUserCodes ); + UserCode::UserCode(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId), m_queryAll(false), m_currentCode(0), m_refreshUserCodes(false) + { + m_com.EnableFlag(COMPAT_FLAG_UC_EXPOSERAWVALUE, false); + m_dom.EnableFlag(STATE_FLAG_USERCODE_COUNT, 0); + SetStaticRequest(StaticRequest_Values); + Options::Get()->GetOptionAsBool("RefreshAllUserCodes", &m_refreshUserCodes); -} + } //----------------------------------------------------------------------------- // // Nothing to do for UserCode //----------------------------------------------------------------------------- -bool UserCode::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - bool requests = false; - if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) ) - { - requests |= RequestValue( _requestFlags, UserCodeIndex_Count, _instance, _queue ); - } + bool UserCode::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + bool requests = false; + if ((_requestFlags & RequestFlag_Static) && HasStaticRequest(StaticRequest_Values)) + { + requests |= RequestValue(_requestFlags, ValueID_Index_UserCode::Count, _instance, _queue); + } - if( _requestFlags & RequestFlag_Session ) - { - if( m_dom.GetFlagByte(STATE_FLAG_USERCODE_COUNT) > 0 ) - { - m_queryAll = true; - m_currentCode = 1; - requests |= RequestValue( _requestFlags, m_currentCode, _instance, _queue ); - } - } + if (_requestFlags & RequestFlag_Session) + { + if (m_dom.GetFlagByte(STATE_FLAG_USERCODE_COUNT) > 0) + { + m_queryAll = true; + m_currentCode = 1; + requests |= RequestValue(_requestFlags, m_currentCode, _instance, _queue); + } + } - return requests; -} + return requests; + } //----------------------------------------------------------------------------- // // Nothing to do for UserCode //----------------------------------------------------------------------------- -bool UserCode::RequestValue -( - uint32 const _requestFlags, - uint16 const _userCodeIdx, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _instance != 1 ) - { - // This command class doesn't work with multiple instances - return false; - } - if ( !m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Log::Write( LogLevel_Info, GetNodeId(), "UserNumberCmd_Get Not Supported on this node"); - return false; - } - if( _userCodeIdx == UserCodeIndex_Count ) - { - // Get number of supported user codes. - Msg* msg = new Msg( "UserNumberCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( UserNumberCmd_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } - if (_userCodeIdx == 0) - { - Log::Write( LogLevel_Warning, GetNodeId(), "UserCodeCmd_Get with Index 0 not Supported"); - return false; - } - if (_userCodeIdx > m_dom.GetFlagByte(STATE_FLAG_USERCODE_COUNT)) - { - Log::Write( LogLevel_Warning, GetNodeId(), "UserCodeCmd_Get with index %d is greater than max UserCodes", _userCodeIdx); - return false; - } - Msg* msg = new Msg( "UserCodeCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( UserCodeCmd_Get ); - msg->Append( (_userCodeIdx & 0xFF) ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; -} + bool UserCode::RequestValue(uint32 const _requestFlags, uint16 const _userCodeIdx, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_instance != 1) + { + // This command class doesn't work with multiple instances + return false; + } + if (!m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Log::Write(LogLevel_Info, GetNodeId(), "UserNumberCmd_Get Not Supported on this node"); + return false; + } + if (_userCodeIdx == ValueID_Index_UserCode::Count) + { + // Get number of supported user codes. + Msg* msg = new Msg("UserNumberCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(UserNumberCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + if (_userCodeIdx == 0) + { + Log::Write(LogLevel_Warning, GetNodeId(), "UserCodeCmd_Get with Index 0 not Supported"); + return false; + } + if (_userCodeIdx > m_dom.GetFlagByte(STATE_FLAG_USERCODE_COUNT)) + { + Log::Write(LogLevel_Warning, GetNodeId(), "UserCodeCmd_Get with index %d is greater than max UserCodes", _userCodeIdx); + return false; + } + Msg* msg = new Msg("UserCodeCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(UserCodeCmd_Get); + msg->Append((_userCodeIdx & 0xFF)); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool UserCode::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if( UserNumberCmd_Report == (UserCodeCmd)_data[0] ) - { - m_dom.SetFlagByte(STATE_FLAG_USERCODE_COUNT, _data[1]); - ClearStaticRequest( StaticRequest_Values ); - if( _data[1] == 0 ) - { - Log::Write( LogLevel_Info, GetNodeId(), "Received User Number report from node %d: Not supported", GetNodeId() ); - } - else - { - Log::Write( LogLevel_Info, GetNodeId(), "Received User Number report from node %d: Supported Codes %d (%d)", GetNodeId(), _data[1], _data[1] ); - } + bool UserCode::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) + { + if (UserNumberCmd_Report == (UserCodeCmd) _data[0]) + { + m_dom.SetFlagByte(STATE_FLAG_USERCODE_COUNT, _data[1]); + ClearStaticRequest(StaticRequest_Values); + if (_data[1] == 0) + { + Log::Write(LogLevel_Info, GetNodeId(), "Received User Number report from node %d: Not supported", GetNodeId()); + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "Received User Number report from node %d: Supported Codes %d (%d)", GetNodeId(), _data[1], _data[1]); + } - if( ValueShort* value = static_cast( GetValue( _instance, UserCodeIndex_Count ) ) ) - { - value->OnValueRefreshed( _data[1] ); - value->Release(); - } + if (Internal::VC::ValueShort* value = static_cast(GetValue(_instance, ValueID_Index_UserCode::Count))) + { + value->OnValueRefreshed(_data[1]); + value->Release(); + } - if( Node* node = GetNodeUnsafe() ) - { - string data; + if (Node* node = GetNodeUnsafe()) + { + string data; - for( uint16 i = 0; i <= m_dom.GetFlagByte(STATE_FLAG_USERCODE_COUNT); i++ ) - { - char str[16]; - if (i == 0) - { - snprintf( str, sizeof(str), "Enrollment Code"); - node->CreateValueString( ValueID::ValueGenre_User, GetCommandClassId(), _instance, i, str, "", true, false, data, 0 ); + for (uint16 i = 0; i <= m_dom.GetFlagByte(STATE_FLAG_USERCODE_COUNT); i++) + { + char str[16]; + if (i == 0) + { + snprintf(str, sizeof(str), "Enrollment Code"); + node->CreateValueString(ValueID::ValueGenre_User, GetCommandClassId(), _instance, i, str, "", true, false, data, 0); + } + else + { + snprintf(str, sizeof(str), "Code %d:", i); + node->CreateValueString(ValueID::ValueGenre_User, GetCommandClassId(), _instance, i, str, "", false, false, data, 0); + } + m_userCode[i].status = UserCode_Available; + /* silly compilers */ + for (int j = 0; j < 10; j++) + m_userCode[i].usercode[j] = 0; + } + if (m_com.GetFlagBool(COMPAT_FLAG_UC_EXPOSERAWVALUE)) + { + node->CreateValueRaw(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_UserCode::RawValue, "Raw UserCode", "", false, false, 0, 0, 0); + node->CreateValueShort(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_UserCode::RawValueIndex, "Raw UserCode Index", "", false, false, 0, 0); + } + } + return true; } - else + else if (UserCodeCmd_Report == (UserCodeCmd) _data[0]) { - snprintf( str, sizeof(str), "Code %d:", i); - node->CreateValueString( ValueID::ValueGenre_User, GetCommandClassId(), _instance, i, str, "", false, false, data, 0 ); - } - m_userCode[i].status = UserCode_Available; - /* silly compilers */ - for (int j = 0; j < 10; j++) - m_userCode[i].usercode[i] = 0; - } - if (m_com.GetFlagBool(COMPAT_FLAG_UC_EXPOSERAWVALUE)) { - node->CreateValueRaw( ValueID::ValueGenre_User, GetCommandClassId(), _instance, UserCodeIndex_RawValue, "Raw UserCode", "", false, false, 0, 0, 0); - node->CreateValueShort( ValueID::ValueGenre_User, GetCommandClassId(), _instance, UserCodeIndex_RawValueIndex, "Raw UserCode Index", "", false, false, 0, 0); - } - } - return true; - } - else if( UserCodeCmd_Report == (UserCodeCmd)_data[0] ) - { - int i = _data[1]; - Log::Write( LogLevel_Info, GetNodeId(), "Received User Code Report from node %d for User Code %d (%s)", GetNodeId(), i, CodeStatus( _data[2] ).c_str() ); + int i = _data[1]; + Log::Write(LogLevel_Info, GetNodeId(), "Received User Code Report from node %d for User Code %d (%s)", GetNodeId(), i, CodeStatus(_data[2]).c_str()); - int8 size = _length - 4; - if( size > 10 ) - { - Log::Write( LogLevel_Warning, GetNodeId(), "User Code length %d is larger then maximum 10", size ); - size = 10; - } - m_userCode[i].status = (UserCodeStatus)_data[2]; - memcpy(&m_userCode[i].usercode, &_data[3], size); - if( ValueString* value = static_cast( GetValue( _instance, i ) ) ) - { - string data; - /* Max UserCode Length is 10 */ - Log::Write( LogLevel_Info, GetNodeId(), "User Code Packet is %d", size ); - data.assign((const char*)&_data[3], size); - value->OnValueRefreshed( data ); - value->Release(); - } - if (m_com.GetFlagBool(COMPAT_FLAG_UC_EXPOSERAWVALUE)) { - if( ValueShort* value = static_cast( GetValue( _instance, UserCodeIndex_RawValueIndex ) ) ) { - value->OnValueRefreshed(i); - value->Release(); - } - if( ValueRaw* value = static_cast( GetValue( _instance, UserCodeIndex_RawValue ) ) ) { - value->OnValueRefreshed(&_data[3], (_length - 4)); - value->Release(); - } - } + int8 size = _length - 4; + if (size > 10) + { + Log::Write(LogLevel_Warning, GetNodeId(), "User Code length %d is larger then maximum 10", size); + size = 10; + } + m_userCode[i].status = (UserCodeStatus) _data[2]; + memcpy(&m_userCode[i].usercode, &_data[3], size); + if (Internal::VC::ValueString* value = static_cast(GetValue(_instance, i))) + { + string data; + /* Max UserCode Length is 10 */ + Log::Write(LogLevel_Info, GetNodeId(), "User Code Packet is %d", size); + data.assign((const char*) &_data[3], size); + value->OnValueRefreshed(data); + value->Release(); + } + if (m_com.GetFlagBool(COMPAT_FLAG_UC_EXPOSERAWVALUE)) + { + if (Internal::VC::ValueShort* value = static_cast(GetValue(_instance, ValueID_Index_UserCode::RawValueIndex))) + { + value->OnValueRefreshed(i); + value->Release(); + } + if (Internal::VC::ValueRaw* value = static_cast(GetValue(_instance, ValueID_Index_UserCode::RawValue))) + { + value->OnValueRefreshed(&_data[3], (_length - 4)); + value->Release(); + } + } - if( m_queryAll && i == m_currentCode ) - { + if (m_queryAll && i == m_currentCode) + { - if (m_refreshUserCodes || (_data[2] != UserCode_Available)) { - if( ++i <= m_dom.GetFlagByte(STATE_FLAG_USERCODE_COUNT) ) - { - m_currentCode = i; - RequestValue( 0, m_currentCode, _instance, Driver::MsgQueue_Query ); - } - else - { - m_queryAll = false; - /* we might have reset this as part of the RefreshValues Button Value */ - Options::Get()->GetOptionAsBool("RefreshAllUserCodes", &m_refreshUserCodes ); + if (m_refreshUserCodes || (_data[2] != UserCode_Available)) + { + if (++i <= m_dom.GetFlagByte(STATE_FLAG_USERCODE_COUNT)) + { + m_currentCode = i; + RequestValue(0, m_currentCode, _instance, Driver::MsgQueue_Query); + } + else + { + m_queryAll = false; + /* we might have reset this as part of the RefreshValues Button Value */ + Options::Get()->GetOptionAsBool("RefreshAllUserCodes", &m_refreshUserCodes); + } + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "Not Requesting additional UserCode Slots as RefreshAllUserCodes is false, and slot %d is available", i); + m_queryAll = false; + } + } + return true; } - } else { - Log::Write( LogLevel_Info, GetNodeId(), "Not Requesting additional UserCode Slots as RefreshAllUserCodes is false, and slot %d is available", i); - m_queryAll = false; - } - } - return true; - } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Set a User Code value //----------------------------------------------------------------------------- -bool UserCode::SetValue -( - Value const& _value -) -{ - if( (ValueID::ValueType_String == _value.GetID().GetType()) && (_value.GetID().GetIndex() < UserCodeIndex_Refresh) ) - { - ValueString const* value = static_cast(&_value); - string s = value->GetValue(); - if (s.length() < 4) { - Log::Write( LogLevel_Warning, GetNodeId(), "UserCode is smaller than 4 digits", value->GetID().GetIndex()); - return false; - } - if (s.length() > 10) { - Log::Write( LogLevel_Warning, GetNodeId(), "UserCode is larger than 10 digits", value->GetID().GetIndex()); - return false; - } - uint8 len = (uint8_t)(s.length() & 0xFF); - if (value->GetID().GetIndex() == 0 || value->GetID().GetIndex() > m_dom.GetFlagByte(STATE_FLAG_USERCODE_COUNT)) { - Log::Write( LogLevel_Warning, GetNodeId(), "Index %d is out of range of UserCodeCount", value->GetID().GetIndex()); - return false; - } - + bool UserCode::SetValue(Internal::VC::Value const& _value) + { + if ((ValueID::ValueType_String == _value.GetID().GetType()) && (_value.GetID().GetIndex() < ValueID_Index_UserCode::Refresh)) + { + Internal::VC::ValueString const* value = static_cast(&_value); + string s = value->GetValue(); + if (s.length() < 4) + { + Log::Write(LogLevel_Warning, GetNodeId(), "UserCode is smaller than 4 digits", value->GetID().GetIndex()); + return false; + } + if (s.length() > 10) + { + Log::Write(LogLevel_Warning, GetNodeId(), "UserCode is larger than 10 digits", value->GetID().GetIndex()); + return false; + } + uint8 len = (uint8_t) (s.length() & 0xFF); + if (value->GetID().GetIndex() == 0 || value->GetID().GetIndex() > m_dom.GetFlagByte(STATE_FLAG_USERCODE_COUNT)) + { + Log::Write(LogLevel_Warning, GetNodeId(), "Index %d is out of range of UserCodeCount", value->GetID().GetIndex()); + return false; + } - Msg* msg = new Msg( "UserCodeCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->SetInstance( this, _value.GetID().GetInstance() ); - msg->Append( GetNodeId() ); - msg->Append( 4 + len ); - msg->Append( GetCommandClassId() ); - msg->Append( UserCodeCmd_Set ); - msg->Append( (uint8_t)(value->GetID().GetIndex() & 0xFF) ); - msg->Append( UserCode_Occupied ); - for( uint8 i = 0; i < len; i++ ) - { - msg->Append( s[i] ); - } - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); + Msg* msg = new Msg("UserCodeCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->SetInstance(this, _value.GetID().GetInstance()); + msg->Append(GetNodeId()); + msg->Append(4 + len); + msg->Append(GetCommandClassId()); + msg->Append(UserCodeCmd_Set); + msg->Append((uint8_t) (value->GetID().GetIndex() & 0xFF)); + msg->Append(UserCode_Occupied); + for (uint8 i = 0; i < len; i++) + { + msg->Append(s[i]); + } + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); - return true; - } - if ( (ValueID::ValueType_Button == _value.GetID().GetType()) && (_value.GetID().GetIndex() == UserCodeIndex_Refresh) ) - { - m_refreshUserCodes = true; - m_currentCode = 1; - m_queryAll = true; - RequestValue( 0, m_currentCode, _value.GetID().GetInstance(), Driver::MsgQueue_Query ); - return true; - } - if ( (ValueID::ValueType_Short == _value.GetID().GetType()) && (_value.GetID().GetIndex() == UserCodeIndex_RemoveCode) ) - { - ValueShort const* value = static_cast(&_value); - uint8_t index = (uint8_t)(value->GetValue() & 0xFF); - if (index == 0 || index > m_dom.GetFlagByte(STATE_FLAG_USERCODE_COUNT)) { - Log::Write( LogLevel_Warning, GetNodeId(), "Index %d is out of range of UserCodeCount", index); - return false; - } - Msg* msg = new Msg( "UserCodeCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->SetInstance( this, _value.GetID().GetInstance() ); - msg->Append( GetNodeId() ); - msg->Append( 8 ); - msg->Append( GetCommandClassId() ); - msg->Append( UserCodeCmd_Set ); - msg->Append( index ); - msg->Append( UserCode_Available ); - for( uint8 i = 0; i < 4; i++ ) - { - msg->Append( 0 ); - } - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); + return true; + } + if ((ValueID::ValueType_Button == _value.GetID().GetType()) && (_value.GetID().GetIndex() == ValueID_Index_UserCode::Refresh)) + { + m_refreshUserCodes = true; + m_currentCode = 1; + m_queryAll = true; + RequestValue(0, m_currentCode, _value.GetID().GetInstance(), Driver::MsgQueue_Query); + return true; + } + if ((ValueID::ValueType_Short == _value.GetID().GetType()) && (_value.GetID().GetIndex() == ValueID_Index_UserCode::RemoveCode)) + { + Internal::VC::ValueShort const* value = static_cast(&_value); + uint8_t index = (uint8_t) (value->GetValue() & 0xFF); + if (index == 0 || index > m_dom.GetFlagByte(STATE_FLAG_USERCODE_COUNT)) + { + Log::Write(LogLevel_Warning, GetNodeId(), "Index %d is out of range of UserCodeCount", index); + return false; + } + Msg* msg = new Msg("UserCodeCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->SetInstance(this, _value.GetID().GetInstance()); + msg->Append(GetNodeId()); + msg->Append(8); + msg->Append(GetCommandClassId()); + msg->Append(UserCodeCmd_Set); + msg->Append(index); + msg->Append(UserCode_Available); + for (uint8 i = 0; i < 4; i++) + { + msg->Append(0); + } + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); - RequestValue(0, index, _value.GetID().GetInstance(), Driver::MsgQueue_Send); + RequestValue(0, index, _value.GetID().GetInstance(), Driver::MsgQueue_Send); #if 0 - /* Reset Our Local Copy here */ - - if( ValueString* oldvalue = static_cast( GetValue( _value.GetID().GetInstance(), index ) ) ) - { - string data; - oldvalue->OnValueRefreshed( data ); - oldvalue->Release(); - } + /* Reset Our Local Copy here */ + + if( ValueString* oldvalue = static_cast( GetValue( _value.GetID().GetInstance(), index ) ) ) + { + string data; + oldvalue->OnValueRefreshed( data ); + oldvalue->Release(); + } #endif - return false; - } - if ( (ValueID::ValueType_Short == _value.GetID().GetType()) && (_value.GetID().GetIndex() == UserCodeIndex_RawValueIndex) ) - { - ValueShort const* value = static_cast(&_value); - uint16 index = value->GetValue(); - if (index == 0 || index > m_dom.GetFlagByte(STATE_FLAG_USERCODE_COUNT)) { - Log::Write( LogLevel_Warning, GetNodeId(), "Index %d is out of range of UserCodeCount", index); - return false; - } - if( ValueRaw* oldvalue = static_cast( GetValue( _value.GetID().GetInstance(), UserCodeIndex_RawValue ) ) ) - { - oldvalue->OnValueRefreshed((const uint8*)&m_userCode[index].usercode, 10); - oldvalue->Release(); - } - return false; - } - if ( (ValueID::ValueType_Raw == _value.GetID().GetType()) && (_value.GetID().GetIndex() == UserCodeIndex_RawValue) ) - { - ValueRaw const* value = static_cast(&_value); - uint16 index = 0; - if( ValueShort* valueindex = static_cast( GetValue( _value.GetID().GetInstance(), UserCodeIndex_RawValueIndex ) ) ) - { - index = valueindex->GetValue(); - } - if (index == 0 || index > m_dom.GetFlagByte(STATE_FLAG_USERCODE_COUNT)) { - Log::Write( LogLevel_Warning, GetNodeId(), "Index %d is out of range of UserCodeCount", index); - return false; - } - uint8 *s = value->GetValue(); - uint8 len = value->GetLength(); + return false; + } + if ((ValueID::ValueType_Short == _value.GetID().GetType()) && (_value.GetID().GetIndex() == ValueID_Index_UserCode::RawValueIndex)) + { + Internal::VC::ValueShort const* value = static_cast(&_value); + uint16 index = value->GetValue(); + if (index == 0 || index > m_dom.GetFlagByte(STATE_FLAG_USERCODE_COUNT)) + { + Log::Write(LogLevel_Warning, GetNodeId(), "Index %d is out of range of UserCodeCount", index); + return false; + } + if (Internal::VC::ValueRaw* oldvalue = static_cast(GetValue(_value.GetID().GetInstance(), ValueID_Index_UserCode::RawValue))) + { + oldvalue->OnValueRefreshed((const uint8*) &m_userCode[index].usercode, 10); + oldvalue->Release(); + } + return false; + } + if ((ValueID::ValueType_Raw == _value.GetID().GetType()) && (_value.GetID().GetIndex() == ValueID_Index_UserCode::RawValue)) + { + Internal::VC::ValueRaw const* value = static_cast(&_value); + uint16 index = 0; + if (Internal::VC::ValueShort* valueindex = static_cast(GetValue(_value.GetID().GetInstance(), ValueID_Index_UserCode::RawValueIndex))) + { + index = valueindex->GetValue(); + } + if (index == 0 || index > m_dom.GetFlagByte(STATE_FLAG_USERCODE_COUNT)) + { + Log::Write(LogLevel_Warning, GetNodeId(), "Index %d is out of range of UserCodeCount", index); + return false; + } + uint8 *s = value->GetValue(); + uint8 len = value->GetLength(); - Msg* msg = new Msg( "UserCodeCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->SetInstance( this, _value.GetID().GetInstance() ); - msg->Append( GetNodeId() ); - msg->Append( 4 + len ); - msg->Append( GetCommandClassId() ); - msg->Append( UserCodeCmd_Set ); - msg->Append( (uint8_t)(index & 0xFF) ); - msg->Append( UserCode_Occupied ); - for( uint8 i = 0; i < len; i++ ) - { - msg->Append( s[i] ); - } - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - RequestValue(0, index, _value.GetID().GetInstance(), Driver::MsgQueue_Send); + Msg* msg = new Msg("UserCodeCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->SetInstance(this, _value.GetID().GetInstance()); + msg->Append(GetNodeId()); + msg->Append(4 + len); + msg->Append(GetCommandClassId()); + msg->Append(UserCodeCmd_Set); + msg->Append((uint8_t) (index & 0xFF)); + msg->Append(UserCode_Occupied); + for (uint8 i = 0; i < len; i++) + { + msg->Append(s[i]); + } + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + RequestValue(0, index, _value.GetID().GetInstance(), Driver::MsgQueue_Send); + + return false; + } - return false; - } - - - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void UserCode::CreateVars -( - uint8 const _instance + void UserCode::CreateVars(uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - node->CreateValueShort( ValueID::ValueGenre_System, GetCommandClassId(), _instance, UserCodeIndex_Count, "Code Count", "", true, false, 0, 0 ); - node->CreateValueButton( ValueID::ValueGenre_System, GetCommandClassId(), _instance, UserCodeIndex_Refresh, "Refresh All UserCodes", 0); - node->CreateValueShort( ValueID::ValueGenre_System, GetCommandClassId(), _instance, UserCodeIndex_RemoveCode, "Remove User Code", "", false, true, 0, 0); - } -} + ) + { + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueShort(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_UserCode::Count, "Code Count", "", true, false, 0, 0); + node->CreateValueButton(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_UserCode::Refresh, "Refresh All UserCodes", 0); + node->CreateValueShort(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_UserCode::RemoveCode, "Remove User Code", "", false, true, 0, 0); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/UserCode.h b/cpp/src/command_classes/UserCode.h index 175bbd3af7..ad8a06313c 100644 --- a/cpp/src/command_classes/UserCode.h +++ b/cpp/src/command_classes/UserCode.h @@ -32,84 +32,106 @@ namespace OpenZWave { - /** \brief Implements COMMAND_CLASS_USER_CODE (0x63), a Z-Wave device command class. - * \ingroup CommandClass - */ - class UserCode: public CommandClass + namespace Internal { - private: - enum UserCodeStatus + namespace CC { - UserCode_Available = 0x00, - UserCode_Occupied = 0x01, - UserCode_Reserved = 0x02, - UserCode_NotAvailable = 0xfe, - UserCode_Unset = 0xff - }; - struct UserCodeEntry { - UserCodeStatus status; - uint8 usercode[10]; - }; - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new UserCode( _homeId, _nodeId ); } - virtual ~UserCode(){} + /** \brief Implements COMMAND_CLASS_USER_CODE (0x63), a Z-Wave device command class. + * \ingroup CommandClass + */ + class UserCode: public CommandClass + { + private: + enum UserCodeStatus + { + UserCode_Available = 0x00, + UserCode_Occupied = 0x01, + UserCode_Reserved = 0x02, + UserCode_NotAvailable = 0xfe, + UserCode_Unset = 0xff + }; + struct UserCodeEntry + { + UserCodeStatus status; + uint8 usercode[10]; + }; + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new UserCode(_homeId, _nodeId); + } + virtual ~UserCode() + { + } - static uint8 const StaticGetCommandClassId(){ return 0x63; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_USER_CODE"; } + static uint8 const StaticGetCommandClassId() + { + return 0x63; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_USER_CODE"; + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool SetValue( Value const& _value ); + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool SetValue(Internal::VC::Value const& _value) override; - protected: - virtual void CreateVars( uint8 const _instance ); + protected: + virtual void CreateVars(uint8 const _instance) override; - private: - UserCode( uint32 const _homeId, uint8 const _nodeId ); + private: + UserCode(uint32 const _homeId, uint8 const _nodeId); - string CodeStatus( uint8 const _byte ) - { - switch( _byte ) - { - case UserCode_Available: - { - return "Available"; - } - case UserCode_Occupied: - { - return "Occupied"; - } - case UserCode_Reserved: - { - return "Reserved"; - } - case UserCode_NotAvailable: - { - return "Not Available"; - } - case UserCode_Unset: - { - return "Unset"; - } - default: - { - return "Unknown"; - } - } - } - - bool m_queryAll; // True while we are requesting all the user codes. - uint16 m_currentCode; - std::map m_userCode; - bool m_refreshUserCodes; - }; + string CodeStatus(uint8 const _byte) + { + switch (_byte) + { + case UserCode_Available: + { + return "Available"; + } + case UserCode_Occupied: + { + return "Occupied"; + } + case UserCode_Reserved: + { + return "Reserved"; + } + case UserCode_NotAvailable: + { + return "Not Available"; + } + case UserCode_Unset: + { + return "Unset"; + } + default: + { + return "Unknown"; + } + } + } + bool m_queryAll; // True while we are requesting all the user codes. + uint16 m_currentCode; + std::map m_userCode; + bool m_refreshUserCodes; + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif - diff --git a/cpp/src/command_classes/Version.cpp b/cpp/src/command_classes/Version.cpp index 6438af4a74..331a3ccc36 100644 --- a/cpp/src/command_classes/Version.cpp +++ b/cpp/src/command_classes/Version.cpp @@ -37,192 +37,183 @@ #include "tinyxml.h" -using namespace OpenZWave; - -enum VersionCmd +namespace OpenZWave { - VersionCmd_Get = 0x11, - VersionCmd_Report = 0x12, - VersionCmd_CommandClassGet = 0x13, - VersionCmd_CommandClassReport = 0x14 -}; + namespace Internal + { + namespace CC + { -enum -{ - VersionIndex_Library = 0, - VersionIndex_Protocol, - VersionIndex_Application -}; + enum VersionCmd + { + VersionCmd_Get = 0x11, + VersionCmd_Report = 0x12, + VersionCmd_CommandClassGet = 0x13, + VersionCmd_CommandClassReport = 0x14 + }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -Version::Version -( - uint32 const _homeId, - uint8 const _nodeId -): - CommandClass( _homeId, _nodeId ) -{ - m_com.EnableFlag(COMPAT_FLAG_VERSION_GETCLASSVERSION, true); - SetStaticRequest( StaticRequest_Values ); -} + Version::Version(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + m_com.EnableFlag(COMPAT_FLAG_VERSION_GETCLASSVERSION, true); + SetStaticRequest(StaticRequest_Values); + } //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool Version::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) ) - { - return RequestValue( _requestFlags, 0, _instance, _queue ); - } + bool Version::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + if ((_requestFlags & RequestFlag_Static) && HasStaticRequest(StaticRequest_Values)) + { + return RequestValue(_requestFlags, 0, _instance, _queue); + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool Version::RequestValue -( - uint32 const _requestFlags, - uint16 const _dummy1, // = 0 - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _instance != 1 ) - { - // This command class doesn't work with multiple instances - return false; - } - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Msg* msg = new Msg( "VersionCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( VersionCmd_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "VersionCmd_Get Not Supported on this node"); - } - return false; -} + bool Version::RequestValue(uint32 const _requestFlags, uint16 const _dummy1, // = 0 + uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_instance != 1) + { + // This command class doesn't work with multiple instances + return false; + } + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Msg* msg = new Msg("VersionCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(VersionCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "VersionCmd_Get Not Supported on this node"); + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool Version::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if( Node* node = GetNodeUnsafe() ) - { - if( VersionCmd_Report == (VersionCmd)_data[0] ) - { - char library[8]; - char protocol[16]; - char application[16]; - - snprintf( library, sizeof(library), "%d", _data[1] ); - snprintf( protocol, sizeof(protocol), "%d.%.2d", _data[2], _data[3] ); - snprintf( application, sizeof(application), "%d.%.2d", _data[4], _data[5] ); - - Log::Write( LogLevel_Info, GetNodeId(), "Received Version report from node %d: Library=%s, Protocol=%s, Application=%s", GetNodeId(), library, protocol, application ); - ClearStaticRequest( StaticRequest_Values ); - - if( ValueString* libraryValue = static_cast( GetValue( _instance, VersionIndex_Library ) ) ) - { - libraryValue->OnValueRefreshed( library ); - libraryValue->Release(); - } - if( ValueString* protocolValue = static_cast( GetValue( _instance, VersionIndex_Protocol ) ) ) + bool Version::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) { - protocolValue->OnValueRefreshed( protocol ); - protocolValue->Release(); + if (Node* node = GetNodeUnsafe()) + { + if (VersionCmd_Report == (VersionCmd) _data[0]) + { + char library[8]; + char protocol[16]; + char application[16]; + + snprintf(library, sizeof(library), "%d", _data[1]); + snprintf(protocol, sizeof(protocol), "%d.%.2d", _data[2], _data[3]); + snprintf(application, sizeof(application), "%d.%.2d", _data[4], _data[5]); + + Log::Write(LogLevel_Info, GetNodeId(), "Received Version report from node %d: Library=%s, Protocol=%s, Application=%s", GetNodeId(), library, protocol, application); + ClearStaticRequest(StaticRequest_Values); + + if (Internal::VC::ValueString* libraryValue = static_cast(GetValue(_instance, ValueID_Index_Version::Library))) + { + libraryValue->OnValueRefreshed(library); + libraryValue->Release(); + } + if (Internal::VC::ValueString* protocolValue = static_cast(GetValue(_instance, ValueID_Index_Version::Protocol))) + { + protocolValue->OnValueRefreshed(protocol); + protocolValue->Release(); + } + if (Internal::VC::ValueString* applicationValue = static_cast(GetValue(_instance, ValueID_Index_Version::Application))) + { + applicationValue->OnValueRefreshed(application); + applicationValue->Release(); + } + + return true; + } + + if (VersionCmd_CommandClassReport == (VersionCmd) _data[0]) + { + if (CommandClass* pCommandClass = node->GetCommandClass(_data[1])) + { + Log::Write(LogLevel_Info, GetNodeId(), "Received CommandClass Version report from node %d: CommandClass=%s, Version=%d", GetNodeId(), pCommandClass->GetCommandClassName().c_str(), _data[2]); + pCommandClass->ClearStaticRequest(StaticRequest_Version); + /* some devices advertise CommandClasses, but return version as 0. In General this means + * that the device doesn't actually support the CommandClass. So lets Remove it + */ + + if (_data[2] > 0) + { + pCommandClass->SetVersion(_data[2]); + } + else + { + Log::Write(LogLevel_Warning, GetNodeId(), "CommandClass Version is 0, Removing CommandClass %s", pCommandClass->GetCommandClassName().c_str()); + GetNodeUnsafe()->RemoveCommandClass(_data[2]); + } + } + + return true; + } + } + + return false; } - if( ValueString* applicationValue = static_cast( GetValue( _instance, VersionIndex_Application ) ) ) - { - applicationValue->OnValueRefreshed( application ); - applicationValue->Release(); - } - - return true; - } - - if (VersionCmd_CommandClassReport == (VersionCmd)_data[0]) - { - if( CommandClass* pCommandClass = node->GetCommandClass( _data[1] ) ) - { - Log::Write( LogLevel_Info, GetNodeId(), "Received Command Class Version report from node %d: CommandClass=%s, Version=%d", GetNodeId(), pCommandClass->GetCommandClassName().c_str(), _data[2] ); - pCommandClass->ClearStaticRequest( StaticRequest_Version ); - pCommandClass->SetVersion( _data[2] ); - } - - return true; - } - } - - return false; -} //----------------------------------------------------------------------------- // // Request the version of a command class used by the device //----------------------------------------------------------------------------- -bool Version::RequestCommandClassVersion -( - CommandClass const* _commandClass -) -{ - if( m_com.GetFlagBool(COMPAT_FLAG_VERSION_GETCLASSVERSION) ) - { - if( _commandClass->HasStaticRequest( StaticRequest_Version ) ) - { - Msg* msg = new Msg( "VersionCmd_CommandClassGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( 3 ); - msg->Append( GetCommandClassId() ); - msg->Append( VersionCmd_CommandClassGet ); - msg->Append( _commandClass->GetCommandClassId() ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - return true; - } - } - - return false; -} + bool Version::RequestCommandClassVersion(CommandClass const* _commandClass) + { + if (m_com.GetFlagBool(COMPAT_FLAG_VERSION_GETCLASSVERSION)) + { + if (_commandClass->HasStaticRequest(StaticRequest_Version)) + { + Msg* msg = new Msg("VersionCmd_CommandClassGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(3); + msg->Append(GetCommandClassId()); + msg->Append(VersionCmd_CommandClassGet); + msg->Append(_commandClass->GetCommandClassId()); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); + return true; + } + } + + return false; + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void Version::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - node->CreateValueString( ValueID::ValueGenre_System, GetCommandClassId(), _instance, VersionIndex_Library, "Library Version", "", true, false, "Unknown", 0 ); - node->CreateValueString( ValueID::ValueGenre_System, GetCommandClassId(), _instance, VersionIndex_Protocol, "Protocol Version", "", true, false, "Unknown", 0 ); - node->CreateValueString( ValueID::ValueGenre_System, GetCommandClassId(), _instance, VersionIndex_Application, "Application Version", "", true, false, "Unknown", 0 ); - } -} + void Version::CreateVars(uint8 const _instance) + { + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueString(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_Version::Library, "Library Version", "", true, false, "Unknown", 0); + node->CreateValueString(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_Version::Protocol, "Protocol Version", "", true, false, "Unknown", 0); + node->CreateValueString(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_Version::Application, "Application Version", "", true, false, "Unknown", 0); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/Version.h b/cpp/src/command_classes/Version.h index 14d0fb59b2..52d8b8036d 100644 --- a/cpp/src/command_classes/Version.h +++ b/cpp/src/command_classes/Version.h @@ -32,36 +32,57 @@ namespace OpenZWave { - class ValueString; - - /** \brief Implements COMMAND_CLASS_VERSION (0x86), a Z-Wave device command class. - * \ingroup CommandClass - */ - class Version: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Version( _homeId, _nodeId ); } - virtual ~Version(){} + namespace CC + { - static uint8 const StaticGetCommandClassId(){ return 0x86; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_VERSION"; } + /** \brief Implements COMMAND_CLASS_VERSION (0x86), a Z-Wave device command class. + * \ingroup CommandClass + */ + class Version: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new Version(_homeId, _nodeId); + } + virtual ~Version() + { + } - bool RequestCommandClassVersion( CommandClass const* _commandClass ); + static uint8 const StaticGetCommandClassId() + { + return 0x86; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_VERSION"; + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); + bool RequestCommandClassVersion(CommandClass const* _commandClass); - protected: - virtual void CreateVars( uint8 const _instance ); + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; - private: - Version( uint32 const _homeId, uint8 const _nodeId ); - }; + protected: + virtual void CreateVars(uint8 const _instance) override; + private: + Version(uint32 const _homeId, uint8 const _nodeId); + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/command_classes/WakeUp.cpp b/cpp/src/command_classes/WakeUp.cpp index c1b4ea31a8..ace54201c4 100644 --- a/cpp/src/command_classes/WakeUp.cpp +++ b/cpp/src/command_classes/WakeUp.cpp @@ -41,503 +41,458 @@ #include "tinyxml.h" -using namespace OpenZWave; - -enum WakeUpCmd +namespace OpenZWave { - WakeUpCmd_IntervalSet = 0x04, - WakeUpCmd_IntervalGet = 0x05, - WakeUpCmd_IntervalReport = 0x06, - WakeUpCmd_Notification = 0x07, - WakeUpCmd_NoMoreInformation = 0x08, - WakeUpCmd_IntervalCapabilitiesGet = 0x09, - WakeUpCmd_IntervalCapabilitiesReport = 0x0A -}; + namespace Internal + { + namespace CC + { + enum WakeUpCmd + { + WakeUpCmd_IntervalSet = 0x04, + WakeUpCmd_IntervalGet = 0x05, + WakeUpCmd_IntervalReport = 0x06, + WakeUpCmd_Notification = 0x07, + WakeUpCmd_NoMoreInformation = 0x08, + WakeUpCmd_IntervalCapabilitiesGet = 0x09, + WakeUpCmd_IntervalCapabilitiesReport = 0x0A + }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -WakeUp::WakeUp -( - uint32 const _homeId, - uint8 const _nodeId -): -CommandClass( _homeId, _nodeId ), -m_mutex( new Mutex() ), -m_awake( true ), -m_pollRequired( false ) -{ - Timer::SetDriver(GetDriver()); - Options::Get()->GetOptionAsBool("AssumeAwake", &m_awake); - m_com.EnableFlag(COMPAT_FLAG_WAKEUP_DELAYNMI, 0); - SetStaticRequest( StaticRequest_Values ); -} + WakeUp::WakeUp(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId), m_mutex(new Internal::Platform::Mutex()), m_awake(true), m_pollRequired(false) + { + Timer::SetDriver(GetDriver()); + Options::Get()->GetOptionAsBool("AssumeAwake", &m_awake); + m_com.EnableFlag(COMPAT_FLAG_WAKEUP_DELAYNMI, 0); + SetStaticRequest(StaticRequest_Values); + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -WakeUp::~WakeUp -( -) -{ - m_mutex->Release(); - while( !m_pendingQueue.empty() ) - { - Driver::MsgQueueItem const& item = m_pendingQueue.front(); - if( Driver::MsgQueueCmd_SendMsg == item.m_command ) - { - delete item.m_msg; - } - else if( Driver::MsgQueueCmd_Controller == item.m_command ) - { - delete item.m_cci; - } - m_pendingQueue.pop_front(); - } -} + WakeUp::~WakeUp() + { + m_mutex->Release(); + while (!m_pendingQueue.empty()) + { + Driver::MsgQueueItem const& item = m_pendingQueue.front(); + if (Driver::MsgQueueCmd_SendMsg == item.m_command) + { + delete item.m_msg; + } + else if (Driver::MsgQueueCmd_Controller == item.m_command) + { + delete item.m_cci; + } + m_pendingQueue.pop_front(); + } + } //----------------------------------------------------------------------------- // // Starts the process of requesting node state from a sleeping device //----------------------------------------------------------------------------- -void WakeUp::Init -( -) -{ - // Request the wake up interval. When we receive the response, we - // can send a set interval message with the same interval, but with - // the target node id set to that of the controller. This will ensure - // that the controller will receive the wake-up notifications from - // the device. Once this is done, we can request the rest of the node - // state. - RequestState( CommandClass::RequestFlag_Session, 1, Driver::MsgQueue_WakeUp ); -} + void WakeUp::Init() + { + // Request the wake up interval. When we receive the response, we + // can send a set interval message with the same interval, but with + // the target node id set to that of the controller. This will ensure + // that the controller will receive the wake-up notifications from + // the device. Once this is done, we can request the rest of the node + // state. + RequestState(CommandClass::RequestFlag_Session, 1, Driver::MsgQueue_WakeUp); + } //----------------------------------------------------------------------------- // // Nothing to do for wakeup //----------------------------------------------------------------------------- -bool WakeUp::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - bool requests = false; - if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) ) - { - if( GetVersion() > 1 ) - { - requests |= RequestValue( _requestFlags, WakeUpCmd_IntervalCapabilitiesGet, _instance, _queue ); - } - } - if( _requestFlags & RequestFlag_Session ) - { - Node* node = GetNodeUnsafe(); - if( node != NULL && !node->IsController() ) - { - requests |= RequestValue( _requestFlags, 0, _instance, _queue ); - } - } - - return requests; -} + bool WakeUp::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + bool requests = false; + if ((_requestFlags & RequestFlag_Static) && HasStaticRequest(StaticRequest_Values)) + { + if (GetVersion() > 1) + { + requests |= RequestValue(_requestFlags, WakeUpCmd_IntervalCapabilitiesGet, _instance, _queue); + } + } + if (_requestFlags & RequestFlag_Session) + { + Node* node = GetNodeUnsafe(); + if (node != NULL && !node->IsController()) + { + requests |= RequestValue(_requestFlags, 0, _instance, _queue); + } + } + + return requests; + } //----------------------------------------------------------------------------- // // Nothing to do for wakeup //----------------------------------------------------------------------------- -bool WakeUp::RequestValue -( - uint32 const _requestFlags, - uint16 const _getTypeEnum, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( _instance != 1 ) - { - // This command class doesn't work with multiple instances - return false; - } - - if( _getTypeEnum == WakeUpCmd_IntervalCapabilitiesGet ) - { - Msg* msg = new Msg( "WakeUpCmd_IntervalCapabilityGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( WakeUpCmd_IntervalCapabilitiesGet ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - } - + bool WakeUp::RequestValue(uint32 const _requestFlags, uint16 const _getTypeEnum, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_instance != 1) + { + // This command class doesn't work with multiple instances + return false; + } + + if (_getTypeEnum == WakeUpCmd_IntervalCapabilitiesGet) + { + Msg* msg = new Msg("WakeUpCmd_IntervalCapabilityGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(WakeUpCmd_IntervalCapabilitiesGet); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + } + + if (_getTypeEnum == 0) + { + // We won't get a response until the device next wakes up + Msg* msg = new Msg("WakeUpCmd_IntervalGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(WakeUpCmd_IntervalGet); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } - if( _getTypeEnum == 0 ) - { - // We won't get a response until the device next wakes up - Msg* msg = new Msg( "WakeUpCmd_IntervalGet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( WakeUpCmd_IntervalGet ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } - - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool WakeUp::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if( WakeUpCmd_IntervalReport == (WakeUpCmd)_data[0] ) - { - if( ValueInt* value = static_cast( GetValue( _instance, 0 ) ) ) - { - // some interval reports received are validly formatted (proper checksum, etc.) but only have length - // of 3 (0x84 (classid), 0x06 (IntervalReport), 0x00). Not sure what this means - if( _length < 6 ) + bool WakeUp::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) { - Log::Write( LogLevel_Warning, "" ); - Log::Write( LogLevel_Warning, GetNodeId(), "Unusual response: WakeUpCmd_IntervalReport with len = %d. Ignored.", _length ); - value->Release(); + if (WakeUpCmd_IntervalReport == (WakeUpCmd) _data[0]) + { + if (Internal::VC::ValueInt* value = static_cast(GetValue(_instance, ValueID_Index_WakeUp::Interval))) + { + // some interval reports received are validly formatted (proper checksum, etc.) but only have length + // of 3 (0x84 (classid), 0x06 (IntervalReport), 0x00). Not sure what this means + if (_length < 6) + { + Log::Write(LogLevel_Warning, ""); + Log::Write(LogLevel_Warning, GetNodeId(), "Unusual response: WakeUpCmd_IntervalReport with len = %d. Ignored.", _length); + value->Release(); + return false; + } + + uint32 interval = ((uint32) _data[1]) << 16; + interval |= (((uint32) _data[2]) << 8); + interval |= (uint32) _data[3]; + + uint8 targetNodeId = _data[4]; + + Log::Write(LogLevel_Info, GetNodeId(), "Received Wakeup Interval report from node %d: Interval=%d, Target Node=%d", GetNodeId(), interval, targetNodeId); + + value->OnValueRefreshed((int32) interval); + + // Ensure that the target node for wake-up notifications is the controller + // but only if node is not a listening device. Hybrid devices that can be + // powered by other then batteries shouldn't do this. + Node *node = GetNodeUnsafe(); + if (GetDriver()->GetControllerNodeId() != targetNodeId && ((node) && (!node->IsListeningDevice()))) + { + SetValue(*value); + } + value->Release(); + } + return true; + } + else if (WakeUpCmd_Notification == (WakeUpCmd) _data[0]) + { + // The device is awake. + Log::Write(LogLevel_Info, GetNodeId(), "Received Wakeup Notification from node %d", GetNodeId()); + SetAwake(true); + return true; + } + else if (WakeUpCmd_IntervalCapabilitiesReport == (WakeUpCmd) _data[0]) + { + uint32 mininterval = (((uint32) _data[1]) << 16) | (((uint32) _data[2]) << 8) | ((uint32) _data[3]); + uint32 maxinterval = (((uint32) _data[4]) << 16) | (((uint32) _data[5]) << 8) | ((uint32) _data[6]); + uint32 definterval = (((uint32) _data[7]) << 16) | (((uint32) _data[8]) << 8) | ((uint32) _data[9]); + uint32 stepinterval = (((uint32) _data[10]) << 16) | (((uint32) _data[11]) << 8) | ((uint32) _data[12]); + Log::Write(LogLevel_Info, GetNodeId(), "Received Wakeup Interval Capability report from node %d: Min Interval=%d, Max Interval=%d, Default Interval=%d, Interval Step=%d", GetNodeId(), mininterval, maxinterval, definterval, stepinterval); + if (Internal::VC::ValueInt* value = static_cast(GetValue(_instance, ValueID_Index_WakeUp::Min_Interval))) + { + value->OnValueRefreshed((int32) mininterval); + value->Release(); + } + if (Internal::VC::ValueInt* value = static_cast(GetValue(_instance, ValueID_Index_WakeUp::Max_Interval))) + { + value->OnValueRefreshed((int32) maxinterval); + value->Release(); + } + if (Internal::VC::ValueInt* value = static_cast(GetValue(_instance, ValueID_Index_WakeUp::Default_Interval))) + { + value->OnValueRefreshed((int32) definterval); + value->Release(); + } + if (Internal::VC::ValueInt* value = static_cast(GetValue(_instance, ValueID_Index_WakeUp::Interval_Step))) + { + value->OnValueRefreshed((int32) stepinterval); + value->Release(); + } + ClearStaticRequest(StaticRequest_Values); + return true; + } + return false; } - uint32 interval = ((uint32)_data[1]) << 16; - interval |= (((uint32)_data[2]) << 8); - interval |= (uint32)_data[3]; - - uint8 targetNodeId = _data[4]; - - Log::Write( LogLevel_Info, GetNodeId(), "Received Wakeup Interval report from node %d: Interval=%d, Target Node=%d", GetNodeId(), interval, targetNodeId ); - - value->OnValueRefreshed( (int32)interval ); - - // Ensure that the target node for wake-up notifications is the controller - // but only if node is not a listening device. Hybrid devices that can be - // powered by other then batteries shouldn't do this. - Node *node = GetNodeUnsafe(); - if( GetDriver()->GetControllerNodeId() != targetNodeId && ((node) && (!node->IsListeningDevice())) ) - { - SetValue( *value ); - } - value->Release(); - } - return true; - } - else if( WakeUpCmd_Notification == (WakeUpCmd)_data[0] ) - { - // The device is awake. - Log::Write( LogLevel_Info, GetNodeId(), "Received Wakeup Notification from node %d", GetNodeId() ); - SetAwake( true ); - return true; - } - else if( WakeUpCmd_IntervalCapabilitiesReport == (WakeUpCmd)_data[0] ) - { - uint32 mininterval = (((uint32)_data[1]) << 16) | (((uint32)_data[2]) << 8) | ((uint32)_data[3]); - uint32 maxinterval = (((uint32)_data[4]) << 16) | (((uint32)_data[5]) << 8) | ((uint32)_data[6]); - uint32 definterval = (((uint32)_data[7]) << 16) | (((uint32)_data[8]) << 8) | ((uint32)_data[9]); - uint32 stepinterval = (((uint32)_data[10]) << 16) | (((uint32)_data[11]) << 8) | ((uint32)_data[12]); - Log::Write( LogLevel_Info, GetNodeId(), "Received Wakeup Interval Capability report from node %d: Min Interval=%d, Max Interval=%d, Default Interval=%d, Interval Step=%d", GetNodeId(), mininterval, maxinterval, definterval, stepinterval ); - if( ValueInt* value = static_cast( GetValue( _instance, 1 ) ) ) - { - value->OnValueRefreshed( (int32)mininterval ); - value->Release(); - } - if( ValueInt* value = static_cast( GetValue( _instance, 2 ) ) ) - { - value->OnValueRefreshed( (int32)maxinterval ); - value->Release(); - } - if( ValueInt* value = static_cast( GetValue( _instance, 3 ) ) ) - { - value->OnValueRefreshed( (int32)definterval ); - value->Release(); - } - if( ValueInt* value = static_cast( GetValue( _instance, 4 ) ) ) - { - value->OnValueRefreshed( (int32)stepinterval ); - value->Release(); - } - ClearStaticRequest( StaticRequest_Values ); - return true; - } - - return false; -} - //----------------------------------------------------------------------------- // // Set the device's wakeup interval //----------------------------------------------------------------------------- -bool WakeUp::SetValue -( - Value const& _value -) -{ - if( ValueID::ValueType_Int == _value.GetID().GetType() ) - { - ValueInt const* value = static_cast(&_value); - - Msg* msg = new Msg( "WakeUpCmd_IntervalSet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->Append( GetNodeId() ); + bool WakeUp::SetValue(Internal::VC::Value const& _value) + { + if (ValueID::ValueType_Int == _value.GetID().GetType()) + { + Internal::VC::ValueInt const* value = static_cast(&_value); + + Msg* msg = new Msg("WakeUpCmd_IntervalSet", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->Append(GetNodeId()); + + if (GetNodeUnsafe()->GetCommandClass(MultiCmd::StaticGetCommandClassId())) + { + msg->Append(10); + msg->Append(MultiCmd::StaticGetCommandClassId()); + msg->Append(MultiCmd::MultiCmdCmd_Encap); + msg->Append(1); + } + + int32 interval = value->GetValue(); + + msg->Append(6); // length of command bytes following + msg->Append(GetCommandClassId()); + msg->Append(WakeUpCmd_IntervalSet); + msg->Append((uint8) ((interval >> 16) & 0xff)); + msg->Append((uint8) ((interval >> 8) & 0xff)); + msg->Append((uint8) (interval & 0xff)); + msg->Append(GetDriver()->GetControllerNodeId()); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_WakeUp); + return true; + } - if( GetNodeUnsafe()->GetCommandClass( MultiCmd::StaticGetCommandClassId() ) ) - { - msg->Append( 10 ); - msg->Append( MultiCmd::StaticGetCommandClassId() ); - msg->Append( MultiCmd::MultiCmdCmd_Encap ); - msg->Append( 1 ); - } - - int32 interval = value->GetValue(); - - msg->Append( 6 ); // length of command bytes following - msg->Append( GetCommandClassId() ); - msg->Append( WakeUpCmd_IntervalSet ); - msg->Append( (uint8)(( interval >> 16 ) & 0xff) ); - msg->Append( (uint8)(( interval >> 8 ) & 0xff) ); - msg->Append( (uint8)( interval & 0xff ) ); - msg->Append( GetDriver()->GetControllerNodeId() ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_WakeUp ); - return true; - } - - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Set the command class version //----------------------------------------------------------------------------- -void WakeUp::SetVersion -( - uint8 const _version -) -{ - CommandClass::SetVersion( _version ); - CreateVars( 1 ); -} + void WakeUp::SetVersion(uint8 const _version) + { + CommandClass::SetVersion(_version); + CreateVars(1); + } //----------------------------------------------------------------------------- // // Set whether the device is likely to be awake //----------------------------------------------------------------------------- -void WakeUp::SetAwake -( - bool _state -) -{ - if( m_awake != _state ) - { - /* we do the call on RefreshValuesOnWakeup here, so any duplicates in the wakeup Queue are handled appropriately - * - */ - if ( m_awake == false ) { - Node* node = GetNodeUnsafe(); - if (node) - node->RefreshValuesOnWakeup(); - } - - m_awake = _state; - Log::Write( LogLevel_Info, GetNodeId(), " Node %d has been marked as %s", GetNodeId(), m_awake ? "awake" : "asleep" ); - Notification* notification = new Notification( Notification::Type_Notification ); - notification->SetHomeAndNodeIds( GetHomeId(), GetNodeId() ); - notification->SetNotification( m_awake ? Notification::Code_Awake : Notification::Code_Sleep ); - GetDriver()->QueueNotification( notification ); - - } - - if( m_awake ) - { - // If the device is marked for polling, request the current state - Node* node = GetNodeUnsafe(); - if( m_pollRequired ) - { - if( node != NULL ) + void WakeUp::SetAwake(bool _state) { - node->SetQueryStage( Node::QueryStage_Dynamic ); + if (m_awake != _state) + { + /* we do the call on RefreshValuesOnWakeup here, so any duplicates in the wakeup Queue are handled appropriately + * + */ + if (m_awake == false) + { + Node* node = GetNodeUnsafe(); + if (node) + node->RefreshValuesOnWakeup(); + } + + m_awake = _state; + Log::Write(LogLevel_Info, GetNodeId(), " Node %d has been marked as %s", GetNodeId(), m_awake ? "awake" : "asleep"); + Notification* notification = new Notification(Notification::Type_Notification); + notification->SetHomeAndNodeIds(GetHomeId(), GetNodeId()); + notification->SetNotification(m_awake ? Notification::Code_Awake : Notification::Code_Sleep); + GetDriver()->QueueNotification(notification); + + } + + if (m_awake) + { + // If the device is marked for polling, request the current state + Node* node = GetNodeUnsafe(); + if (m_pollRequired) + { + if (node != NULL) + { + node->SetQueryStage(Node::QueryStage_Dynamic); + } + m_pollRequired = false; + } + // Send all pending messages + SendPending(); + + } } - m_pollRequired = false; - } - // Send all pending messages - SendPending(); - - - } -} //----------------------------------------------------------------------------- // // Add a Z-Wave message to the queue //----------------------------------------------------------------------------- -void WakeUp::QueueMsg -( - Driver::MsgQueueItem const& _item -) -{ - m_mutex->Lock(); - - // See if there is already a copy of this message in the queue. If so, - // we delete it. This is to prevent duplicates building up if the - // device does not wake up very often. Deleting the original and - // adding the copy to the end avoids problems with the order of - // commands such as on and off. - list::iterator it = m_pendingQueue.begin(); - while( it != m_pendingQueue.end() ) - { - Driver::MsgQueueItem const& item = *it; - if( item == _item ) - { - // Duplicate found - if( Driver::MsgQueueCmd_SendMsg == item.m_command ) + void WakeUp::QueueMsg(Driver::MsgQueueItem const& _item) { - delete item.m_msg; + m_mutex->Lock(); + + // See if there is already a copy of this message in the queue. If so, + // we delete it. This is to prevent duplicates building up if the + // device does not wake up very often. Deleting the original and + // adding the copy to the end avoids problems with the order of + // commands such as on and off. + list::iterator it = m_pendingQueue.begin(); + while (it != m_pendingQueue.end()) + { + Driver::MsgQueueItem const& item = *it; + if (item == _item) + { + // Duplicate found + if (Driver::MsgQueueCmd_SendMsg == item.m_command) + { + delete item.m_msg; + } + else if (Driver::MsgQueueCmd_Controller == item.m_command) + { + delete item.m_cci; + } + m_pendingQueue.erase(it++); + } + else + { + ++it; + } + } + /* make sure the SendAttempts is reset to 0 */ + if (_item.m_command == Driver::MsgQueueCmd_SendMsg) + _item.m_msg->SetSendAttempts(0); + + m_pendingQueue.push_back(_item); + m_mutex->Unlock(); } - else if( Driver::MsgQueueCmd_Controller == item.m_command ) - { - delete item.m_cci; - } - m_pendingQueue.erase( it++ ); - } - else - { - ++it; - } - } - /* make sure the SendAttempts is reset to 0 */ - if (_item.m_command == Driver::MsgQueueCmd_SendMsg) - _item.m_msg->SetSendAttempts(0); - - m_pendingQueue.push_back( _item ); - m_mutex->Unlock(); -} //----------------------------------------------------------------------------- // // The device is awake, so send all the pending messages //----------------------------------------------------------------------------- -void WakeUp::SendPending -( -) -{ - m_awake = true; - bool reloading = false; - m_mutex->Lock(); - list::iterator it = m_pendingQueue.begin(); - while( it != m_pendingQueue.end() ) - { - Driver::MsgQueueItem const& item = *it; - if( Driver::MsgQueueCmd_SendMsg == item.m_command ) - { - GetDriver()->SendMsg( item.m_msg, Driver::MsgQueue_WakeUp ); - } - else if( Driver::MsgQueueCmd_QueryStageComplete == item.m_command ) - { - GetDriver()->SendQueryStageComplete( item.m_nodeId, item.m_queryStage ); - } - else if( Driver::MsgQueueCmd_Controller == item.m_command ) - { - GetDriver()->BeginControllerCommand( item.m_cci->m_controllerCommand, item.m_cci->m_controllerCallback, item.m_cci->m_controllerCallbackContext, item.m_cci->m_highPower, item.m_cci->m_controllerCommandNode, item.m_cci->m_controllerCommandArg ); - delete item.m_cci; - } - else if ( Driver::MsgQueueCmd_ReloadNode == item.m_command ) - { - GetDriver()->ReloadNode(item.m_nodeId); - reloading = true; - } - it = m_pendingQueue.erase( it ); - } - m_mutex->Unlock(); - - // Send the device back to sleep, unless we have outstanding queries. - bool sendToSleep = m_awake; - Node* node = GetNodeUnsafe(); - if( node != NULL ) - { - if( !node->AllQueriesCompleted() ) - { - sendToSleep = false; - } - } - - /* if we are reloading, the QueryStage_Complete will take care of sending the device back to sleep */ - if( sendToSleep && !reloading ) - { - if( m_com.GetFlagInt(COMPAT_FLAG_WAKEUP_DELAYNMI) == 0 ) { - SendNoMoreInfo(1); - - } else { - Log::Write( LogLevel_Info, GetNodeId(), " Node %d has delayed sleep of %dms", GetNodeId(), m_com.GetFlagInt(COMPAT_FLAG_WAKEUP_DELAYNMI) ); - TimerThread::TimerCallback callback = bind(&WakeUp::SendNoMoreInfo, this, 1); - TimerSetEvent(m_com.GetFlagInt(COMPAT_FLAG_WAKEUP_DELAYNMI), callback, 1); - } - } -} + void WakeUp::SendPending() + { + m_awake = true; + bool reloading = false; + m_mutex->Lock(); + list::iterator it = m_pendingQueue.begin(); + while (it != m_pendingQueue.end()) + { + Driver::MsgQueueItem const& item = *it; + if (Driver::MsgQueueCmd_SendMsg == item.m_command) + { + GetDriver()->SendMsg(item.m_msg, Driver::MsgQueue_WakeUp); + } + else if (Driver::MsgQueueCmd_QueryStageComplete == item.m_command) + { + GetDriver()->SendQueryStageComplete(item.m_nodeId, item.m_queryStage); + } + else if (Driver::MsgQueueCmd_Controller == item.m_command) + { + GetDriver()->BeginControllerCommand(item.m_cci->m_controllerCommand, item.m_cci->m_controllerCallback, item.m_cci->m_controllerCallbackContext, item.m_cci->m_highPower, item.m_cci->m_controllerCommandNode, item.m_cci->m_controllerCommandArg); + delete item.m_cci; + } + else if (Driver::MsgQueueCmd_ReloadNode == item.m_command) + { + GetDriver()->ReloadNode(item.m_nodeId); + reloading = true; + } + it = m_pendingQueue.erase(it); + } + m_mutex->Unlock(); + + // Send the device back to sleep, unless we have outstanding queries. + bool sendToSleep = m_awake; + Node* node = GetNodeUnsafe(); + if (node != NULL) + { + if (!node->AllQueriesCompleted()) + { + sendToSleep = false; + } + } + + /* if we are reloading, the QueryStage_Complete will take care of sending the device back to sleep */ + if (sendToSleep && !reloading) + { + if (m_com.GetFlagInt(COMPAT_FLAG_WAKEUP_DELAYNMI) == 0) + { + SendNoMoreInfo(1); + + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), " Node %d has delayed sleep of %dms", GetNodeId(), m_com.GetFlagInt(COMPAT_FLAG_WAKEUP_DELAYNMI)); + TimerThread::TimerCallback callback = bind(&WakeUp::SendNoMoreInfo, this, 1); + TimerSetEvent(m_com.GetFlagInt(COMPAT_FLAG_WAKEUP_DELAYNMI), callback, 1); + } + } + } //----------------------------------------------------------------------------- // // Send a no more information message //----------------------------------------------------------------------------- -void WakeUp::SendNoMoreInfo -( - uint32 id -) -{ - Msg* msg = new Msg( "WakeUpCmd_NoMoreInformation", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( WakeUpCmd_NoMoreInformation ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_WakeUp ); -} + void WakeUp::SendNoMoreInfo(uint32 id) + { + Msg* msg = new Msg("WakeUpCmd_NoMoreInformation", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(WakeUpCmd_NoMoreInformation); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, Driver::MsgQueue_WakeUp); + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void WakeUp::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - if( !node->IsController() ) // We don't add the interval value for controllers, because they don't appear to ever wake up on their own. - { - switch( GetVersion() ) - { - case 1: + void WakeUp::CreateVars(uint8 const _instance) { - node->CreateValueInt( ValueID::ValueGenre_System, GetCommandClassId(), _instance, 0, "Wake-up Interval", "Seconds", false, false, 3600, 0 ); - break; - } - case 2: - { - node->CreateValueInt( ValueID::ValueGenre_System, GetCommandClassId(), _instance, 1, "Minimum Wake-up Interval", "Seconds", true, false, 0, 0 ); - node->CreateValueInt( ValueID::ValueGenre_System, GetCommandClassId(), _instance, 2, "Maximum Wake-up Interval", "Seconds", true, false, 0, 0 ); - node->CreateValueInt( ValueID::ValueGenre_System, GetCommandClassId(), _instance, 3, "Default Wake-up Interval", "Seconds", true, false, 0, 0 ); - node->CreateValueInt( ValueID::ValueGenre_System, GetCommandClassId(), _instance, 4, "Wake-up Interval Step", "Seconds", true, false, 0, 0 ); - break; - } + if (Node* node = GetNodeUnsafe()) + { + if (!node->IsController()) // We don't add the interval value for controllers, because they don't appear to ever wake up on their own. + { + if (GetVersion() >= 2) + { + node->CreateValueInt(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_WakeUp::Min_Interval, "Minimum Wake-up Interval", "Seconds", true, false, 0, 0); + node->CreateValueInt(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_WakeUp::Max_Interval, "Maximum Wake-up Interval", "Seconds", true, false, 0, 0); + node->CreateValueInt(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_WakeUp::Default_Interval, "Default Wake-up Interval", "Seconds", true, false, 0, 0); + node->CreateValueInt(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_WakeUp::Interval_Step, "Wake-up Interval Step", "Seconds", true, false, 0, 0); + } + node->CreateValueInt(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_WakeUp::Interval, "Wake-up Interval", "Seconds", false, false, 3600, 0); + } + } } - } - } -} + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/WakeUp.h b/cpp/src/command_classes/WakeUp.h index 727a610ec0..534ef0ab55 100644 --- a/cpp/src/command_classes/WakeUp.h +++ b/cpp/src/command_classes/WakeUp.h @@ -35,60 +35,90 @@ namespace OpenZWave { - class Msg; - class ValueInt; - class Mutex; - - /** \brief Implements COMMAND_CLASS_WAKE_UP (0x84), a Z-Wave device command class. - * \ingroup CommandClass - */ - class WakeUp: public CommandClass, private Timer - { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new WakeUp( _homeId, _nodeId ); } - virtual ~WakeUp(); - - static uint8 const StaticGetCommandClassId(){ return 0x84; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_WAKE_UP"; } - - void Init(); // Starts the process of requesting node state from a sleeping device. - void QueueMsg( Driver::MsgQueueItem const& _item ); - - /** \brief Send all pending messages followed by a no more information message. */ - void SendPending(); - - /** \brief Send a no more information message. */ - void SendNoMoreInfo(uint32 id); - - bool IsAwake()const{ return m_awake; } - void SetAwake( bool _state ); - void SetPollRequired(){ m_pollRequired = true; } - - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual bool SetValue( Value const& _value ); - virtual void SetVersion( uint8 const _version ); - - virtual uint8 GetMaxVersion(){ return 2; } - - protected: - virtual void CreateVars( uint8 const _instance ); - - private: - WakeUp( uint32 const _homeId, uint8 const _nodeId ); - - Mutex* m_mutex; // Serialize access to the pending queue - list m_pendingQueue; // Messages waiting to be sent when the device wakes up - bool m_awake; - bool m_pollRequired; - }; + namespace Internal + { + namespace Platform + { + class Mutex; + } + namespace CC + { + + /** \brief Implements COMMAND_CLASS_WAKE_UP (0x84), a Z-Wave device command class. + * \ingroup CommandClass + */ + class WakeUp: public CommandClass, private Timer + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new WakeUp(_homeId, _nodeId); + } + virtual ~WakeUp(); + + static uint8 const StaticGetCommandClassId() + { + return 0x84; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_WAKE_UP"; + } + + void Init(); // Starts the process of requesting node state from a sleeping device. + void QueueMsg(Driver::MsgQueueItem const& _item); + + /** \brief Send all pending messages followed by a no more information message. */ + void SendPending(); + + /** \brief Send a no more information message. */ + void SendNoMoreInfo(uint32 id); + + bool IsAwake() const + { + return m_awake; + } + void SetAwake(bool _state); + void SetPollRequired() + { + m_pollRequired = true; + } + + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + virtual bool SetValue(Internal::VC::Value const& _value) override; + virtual void SetVersion(uint8 const _version) override; + + virtual uint8 GetMaxVersion() override + { + return 2; + } + + protected: + virtual void CreateVars(uint8 const _instance) override; + + private: + WakeUp(uint32 const _homeId, uint8 const _nodeId); + + Internal::Platform::Mutex* m_mutex; // Serialize access to the pending queue + list m_pendingQueue; // Messages waiting to be sent when the device wakes up + bool m_awake; + bool m_pollRequired; + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif - diff --git a/cpp/src/command_classes/ZWavePlusInfo.cpp b/cpp/src/command_classes/ZWavePlusInfo.cpp index 9fbd50b334..feda29fe1c 100644 --- a/cpp/src/command_classes/ZWavePlusInfo.cpp +++ b/cpp/src/command_classes/ZWavePlusInfo.cpp @@ -37,158 +37,134 @@ #include "value_classes/ValueShort.h" #include "value_classes/ValueList.h" -using namespace OpenZWave; - -enum ZWavePlusInfoCmdEnum -{ - ZWavePlusInfoCmd_Get = 0x01, - ZWavePlusInfoCmd_Report -}; - -enum +namespace OpenZWave { - ZWavePlusInfoIndex_Version = 0x00, - ZWavePlusInfoIndex_InstallerIcon, - ZWavePlusInfoIndex_UserIcon, -}; - + namespace Internal + { + namespace CC + { + enum ZWavePlusInfoCmdEnum + { + ZWavePlusInfoCmd_Get = 0x01, + ZWavePlusInfoCmd_Report + }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -ZWavePlusInfo::ZWavePlusInfo -( - uint32 const _homeId, - uint8 const _nodeId -): - CommandClass( _homeId, _nodeId ) -{ - SetStaticRequest( StaticRequest_Values ); -} + ZWavePlusInfo::ZWavePlusInfo(uint32 const _homeId, uint8 const _nodeId) : + CommandClass(_homeId, _nodeId) + { + SetStaticRequest(StaticRequest_Values); + } //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- -bool ZWavePlusInfo::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if (_requestFlags & RequestFlag_Static) - { - return RequestValue( _requestFlags, 0, _instance, _queue ); - } + bool ZWavePlusInfo::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) + { + if (_requestFlags & RequestFlag_Static) + { + return RequestValue(_requestFlags, 0, _instance, _queue); + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- -bool ZWavePlusInfo::RequestValue -( - uint32 const _requestFlags, - uint16 const _dummy1, // = 0 (not used) - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if ( m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED) ) - { - Msg* msg = new Msg( "ZWavePlusInfoCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( ZWavePlusInfoCmd_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "ZWavePlusInfoCmd_Get Not Supported on this node"); - } - return false; -} - + bool ZWavePlusInfo::RequestValue(uint32 const _requestFlags, uint16 const _dummy1, // = 0 (not used) + uint8 const _instance, Driver::MsgQueue const _queue) + { + if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) + { + Msg* msg = new Msg("ZWavePlusInfoCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); + msg->SetInstance(this, _instance); + msg->Append(GetNodeId()); + msg->Append(2); + msg->Append(GetCommandClassId()); + msg->Append(ZWavePlusInfoCmd_Get); + msg->Append(GetDriver()->GetTransmitOptions()); + GetDriver()->SendMsg(msg, _queue); + return true; + } + else + { + Log::Write(LogLevel_Info, GetNodeId(), "ZWavePlusInfoCmd_Get Not Supported on this node"); + } + return false; + } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- -bool ZWavePlusInfo::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if( ZWavePlusInfoCmd_Report == _data[0] ) - { - uint8 version = _data[1]; - uint8 role = _data[2]; - uint8 nodeType = _data[3]; - uint16 installerIcon = (_data[4]<< 8) | _data[5]; - uint16 deviceType = (_data[6]<< 8) | _data[7]; - - /* Only set the role, NodeType and DeviceType on Instance 1 Reports. The other instances - * Just have unique Icons for each endpoint */ - if (_instance == 1) { - if( Node* node = GetNodeUnsafe() ) + bool ZWavePlusInfo::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 + ) { - node->SetPlusDeviceClasses( role, nodeType, deviceType ); - } + if (ZWavePlusInfoCmd_Report == _data[0]) + { + uint8 version = _data[1]; + uint8 role = _data[2]; + uint8 nodeType = _data[3]; + uint16 installerIcon = (_data[4] << 8) | _data[5]; + uint16 deviceType = (_data[6] << 8) | _data[7]; + + /* Only set the role, NodeType and DeviceType on Instance 1 Reports. The other instances + * Just have unique Icons for each endpoint */ + if (_instance == 1) + { + if (Node* node = GetNodeUnsafe()) + { + node->SetPlusDeviceClasses(role, nodeType, deviceType); + } // ClearStaticRequest( StaticRequest_Values ); - } - ValueByte* value; - if( (value = static_cast( GetValue( _instance, ZWavePlusInfoIndex_Version ) )) ) - { - value->OnValueRefreshed( version ); - value->Release(); - } - - ValueShort* svalue; - if( (svalue = static_cast( GetValue( _instance, ZWavePlusInfoIndex_InstallerIcon ) )) ) - { - svalue->OnValueRefreshed( installerIcon ); - svalue->Release(); - } - - if( (svalue = static_cast( GetValue( _instance, ZWavePlusInfoIndex_UserIcon ) )) ) - { - svalue->OnValueRefreshed( deviceType ); - svalue->Release(); - } - - - - - return true; - } - return false; -} + } + Internal::VC::ValueByte* value; + if ((value = static_cast(GetValue(_instance, ValueID_Index_ZWavePlusInfo::Version)))) + { + value->OnValueRefreshed(version); + value->Release(); + } + + Internal::VC::ValueShort* svalue; + if ((svalue = static_cast(GetValue(_instance, ValueID_Index_ZWavePlusInfo::InstallerIcon)))) + { + svalue->OnValueRefreshed(installerIcon); + svalue->Release(); + } + + if ((svalue = static_cast(GetValue(_instance, ValueID_Index_ZWavePlusInfo::UserIcon)))) + { + svalue->OnValueRefreshed(deviceType); + svalue->Release(); + } + + return true; + } + return false; + } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- -void ZWavePlusInfo::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - node->CreateValueByte( ValueID::ValueGenre_System, GetCommandClassId(), _instance, ZWavePlusInfoIndex_Version, "ZWave+ Version", "", true, false, 0, 0 ); - node->CreateValueShort( ValueID::ValueGenre_System, GetCommandClassId(), _instance, ZWavePlusInfoIndex_InstallerIcon, "InstallerIcon", "", true, false, 0, 0 ); - node->CreateValueShort( ValueID::ValueGenre_System, GetCommandClassId(), _instance, ZWavePlusInfoIndex_UserIcon, "UserIcon", "", true, false, 0, 0 ); - - } -} + void ZWavePlusInfo::CreateVars(uint8 const _instance) + { + if (Node* node = GetNodeUnsafe()) + { + node->CreateValueByte(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_ZWavePlusInfo::Version, "ZWave+ Version", "", true, false, 0, 0); + node->CreateValueShort(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_ZWavePlusInfo::InstallerIcon, "InstallerIcon", "", true, false, 0, 0); + node->CreateValueShort(ValueID::ValueGenre_System, GetCommandClassId(), _instance, ValueID_Index_ZWavePlusInfo::UserIcon, "UserIcon", "", true, false, 0, 0); + } + } + } // namespace CC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/command_classes/ZWavePlusInfo.h b/cpp/src/command_classes/ZWavePlusInfo.h index f0e38dbfc5..3ab08aa5ef 100644 --- a/cpp/src/command_classes/ZWavePlusInfo.h +++ b/cpp/src/command_classes/ZWavePlusInfo.h @@ -32,30 +32,54 @@ namespace OpenZWave { - /** \brief Implements COMMAND_CLASS_ZWAVEPLUS_INFO (0x5E), a Z-Wave device command class. - * \ingroup CommandClass - */ - class ZWavePlusInfo: public CommandClass + namespace Internal { - public: - static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new ZWavePlusInfo( _homeId, _nodeId ); } - virtual ~ZWavePlusInfo(){} + namespace CC + { - static uint8 const StaticGetCommandClassId(){ return 0x5E; } - static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_ZWAVEPLUS_INFO"; } + /** \brief Implements COMMAND_CLASS_ZWAVEPLUS_INFO (0x5E), a Z-Wave device command class. + * \ingroup CommandClass + */ + class ZWavePlusInfo: public CommandClass + { + public: + static CommandClass* Create(uint32 const _homeId, uint8 const _nodeId) + { + return new ZWavePlusInfo(_homeId, _nodeId); + } + virtual ~ZWavePlusInfo() + { + } - // From CommandClass - virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual bool RequestValue( uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue ); - virtual uint8 const GetCommandClassId()const{ return StaticGetCommandClassId(); } - virtual string const GetCommandClassName()const{ return StaticGetCommandClassName(); } - virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); - virtual void CreateVars( uint8 const _instance ); + static uint8 const StaticGetCommandClassId() + { + return 0x5E; + } + static string const StaticGetCommandClassName() + { + return "COMMAND_CLASS_ZWAVEPLUS_INFO"; + } - private: - ZWavePlusInfo( uint32 const _homeId, uint8 const _nodeId ); - }; + // From CommandClass + virtual bool RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual bool RequestValue(uint32 const _requestFlags, uint16 const _index, uint8 const _instance, Driver::MsgQueue const _queue) override; + virtual uint8 const GetCommandClassId() const override + { + return StaticGetCommandClassId(); + } + virtual string const GetCommandClassName() const override + { + return StaticGetCommandClassName(); + } + virtual bool HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance = 1) override; + protected: + virtual void CreateVars(uint8 const _instance) override; + private: + ZWavePlusInfo(uint32 const _homeId, uint8 const _nodeId); + }; + } // namespace CC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/platform/Controller.cpp b/cpp/src/platform/Controller.cpp index f7c47e246c..2bc95b1233 100644 --- a/cpp/src/platform/Controller.cpp +++ b/cpp/src/platform/Controller.cpp @@ -28,41 +28,41 @@ #include "Driver.h" #include "platform/Controller.h" -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { //----------------------------------------------------------------------------- // // Queues up the controller's initialization commands. //----------------------------------------------------------------------------- -void Controller::PlayInitSequence -( - Driver* _driver -) -{ - _driver->SendMsg( new Msg( "FUNC_ID_ZW_GET_VERSION", 0xff, REQUEST, FUNC_ID_ZW_GET_VERSION, false ), Driver::MsgQueue_Command ); - _driver->SendMsg( new Msg( "FUNC_ID_ZW_MEMORY_GET_ID", 0xff, REQUEST, FUNC_ID_ZW_MEMORY_GET_ID, false ), Driver::MsgQueue_Command ); - _driver->SendMsg( new Msg( "FUNC_ID_ZW_GET_CONTROLLER_CAPABILITIES", 0xff, REQUEST, FUNC_ID_ZW_GET_CONTROLLER_CAPABILITIES, false ), Driver::MsgQueue_Command ); - _driver->SendMsg( new Msg( "FUNC_ID_SERIAL_API_GET_CAPABILITIES", 0xff, REQUEST, FUNC_ID_SERIAL_API_GET_CAPABILITIES, false ), Driver::MsgQueue_Command ); - _driver->SendMsg( new Msg( "FUNC_ID_ZW_GET_SUC_NODE_ID", 0xff, REQUEST, FUNC_ID_ZW_GET_SUC_NODE_ID, false ), Driver::MsgQueue_Command ); - // FUNC_ID_ZW_GET_VIRTUAL_NODES & FUNC_ID_SERIAL_API_GET_INIT_DATA has moved into the handler for FUNC_ID_SERIAL_API_GET_CAPABILITIES -} + void Controller::PlayInitSequence(Driver* _driver) + { + _driver->SendMsg(new Msg("FUNC_ID_ZW_GET_VERSION", 0xff, REQUEST, FUNC_ID_ZW_GET_VERSION, false), Driver::MsgQueue_Command); + _driver->SendMsg(new Msg("FUNC_ID_ZW_MEMORY_GET_ID", 0xff, REQUEST, FUNC_ID_ZW_MEMORY_GET_ID, false), Driver::MsgQueue_Command); + _driver->SendMsg(new Msg("FUNC_ID_ZW_GET_CONTROLLER_CAPABILITIES", 0xff, REQUEST, FUNC_ID_ZW_GET_CONTROLLER_CAPABILITIES, false), Driver::MsgQueue_Command); + _driver->SendMsg(new Msg("FUNC_ID_SERIAL_API_GET_CAPABILITIES", 0xff, REQUEST, FUNC_ID_SERIAL_API_GET_CAPABILITIES, false), Driver::MsgQueue_Command); + _driver->SendMsg(new Msg("FUNC_ID_ZW_GET_SUC_NODE_ID", 0xff, REQUEST, FUNC_ID_ZW_GET_SUC_NODE_ID, false), Driver::MsgQueue_Command); + // FUNC_ID_ZW_GET_VIRTUAL_NODES & FUNC_ID_SERIAL_API_GET_INIT_DATA has moved into the handler for FUNC_ID_SERIAL_API_GET_CAPABILITIES + } //----------------------------------------------------------------------------- // // Read from a controller //----------------------------------------------------------------------------- -uint32 Controller::Read -( - uint8* _buffer, - uint32 _length -) -{ - // Fetch the data from the ring buffer (which is an all or nothing read) - if( Get( _buffer, _length ) ) - { - return _length; - } - - return 0; -} + uint32 Controller::Read(uint8* _buffer, uint32 _length) + { + // Fetch the data from the ring buffer (which is an all or nothing read) + if (Get(_buffer, _length)) + { + return _length; + } + return 0; + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/Controller.h b/cpp/src/platform/Controller.h index 89221eacb4..6c5b85cd36 100644 --- a/cpp/src/platform/Controller.h +++ b/cpp/src/platform/Controller.h @@ -36,82 +36,91 @@ namespace OpenZWave { - class Driver; - - /** \defgroup Platform Platform Abstraction Support - * - * These files abstract differences in platforms that OZW supports - * - */ - - /** \brief Represents a USB Controller - * \ingroup Platform - * - * Controller is derived from Stream rather than containing one, so that - * we can use its Wait abilities without having to duplicate them here. - * The stream is used for input. Buffering of output is handled by the OS. - */ - - class Controller: public Stream + namespace Internal { - - public: - /** - * Consructor. - * Creates the controller object. - */ - Controller():Stream( 2048 ){} - - /** - * Destructor. - * Destroys the controller object. - */ - virtual ~Controller(){} - - /** - * Queues a set of Z-Wave messages in the correct order needed to initialize the Controller implementation. - * @param Pointer to the driver object that will handle the messages. - * @see Driver::Init - */ - void PlayInitSequence( Driver* _driver ); - - /** - * Open a controller. - * Attempts to open a controller and initialize it with the specified paramters. - * @param _controllerName The name of the port to open. For example, ttyS1 on Linux, or \\.\COM2 in Windows. - * @see Close, Read, Write - */ - virtual bool Open( string const& _controllerName ) = 0; - - /** - * Close a controller. - * Closes the controller. - * @return True if the controller was closed successfully, or false if the controller was already closed, or an error occurred. - * @see Open - */ - virtual bool Close() = 0; - - /** - * Write to a controller. - * Attempts to write data to an open controller. - * @param _buffer Pointer to a block of memory containing the data to be written. - * @param _length Length in bytes of the data. - * @return The number of bytes written. - * @see Read, Open, Close - */ - virtual uint32 Write( uint8* _buffer, uint32 _length ) = 0; - - /** - * Read from a controller. - * Attempts to read data from an open controller. - * @param _buffer Pointer to a block of memory large enough to hold the requested data. - * @param _length Length in bytes of the data to be read. - * @return The number of bytes read. - * @see Write, Open, Close - */ - uint32 Read( uint8* _buffer, uint32 _length ); - }; - + namespace Platform + { + + /** \defgroup Platform Platform Abstraction Support + * + * These files abstract differences in platforms that OZW supports + * + */ + + /** \brief Represents a USB Controller + * \ingroup Platform + * + * Controller is derived from Stream rather than containing one, so that + * we can use its Wait abilities without having to duplicate them here. + * The stream is used for input. Buffering of output is handled by the OS. + */ + + class Controller: public Stream + { + + public: + /** + * Consructor. + * Creates the controller object. + */ + Controller() : + Stream(2048) + { + } + + /** + * Destructor. + * Destroys the controller object. + */ + virtual ~Controller() + { + } + + /** + * Queues a set of Z-Wave messages in the correct order needed to initialize the Controller implementation. + * @param Pointer to the driver object that will handle the messages. + * @see Driver::Init + */ + void PlayInitSequence(Driver* _driver); + + /** + * Open a controller. + * Attempts to open a controller and initialize it with the specified paramters. + * @param _controllerName The name of the port to open. For example, ttyS1 on Linux, or \\.\COM2 in Windows. + * @see Close, Read, Write + */ + virtual bool Open(string const& _controllerName) = 0; + + /** + * Close a controller. + * Closes the controller. + * @return True if the controller was closed successfully, or false if the controller was already closed, or an error occurred. + * @see Open + */ + virtual bool Close() = 0; + + /** + * Write to a controller. + * Attempts to write data to an open controller. + * @param _buffer Pointer to a block of memory containing the data to be written. + * @param _length Length in bytes of the data. + * @return The number of bytes written. + * @see Read, Open, Close + */ + virtual uint32 Write(uint8* _buffer, uint32 _length) = 0; + + /** + * Read from a controller. + * Attempts to read data from an open controller. + * @param _buffer Pointer to a block of memory large enough to hold the requested data. + * @param _length Length in bytes of the data to be read. + * @return The number of bytes read. + * @see Write, Open, Close + */ + uint32 Read(uint8* _buffer, uint32 _length); + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_Controller_H diff --git a/cpp/src/platform/DNS.cpp b/cpp/src/platform/DNS.cpp index df1115288f..6fc6109456 100644 --- a/cpp/src/platform/DNS.cpp +++ b/cpp/src/platform/DNS.cpp @@ -36,28 +36,29 @@ #include "platform/unix/DNSImpl.h" // Platform-specific implementation of a DNS Operations #endif -using namespace OpenZWave; - -DNS::DNS -( -) -{ - this->m_pImpl = new DNSImpl(); -} -DNS::~DNS -( -) +namespace OpenZWave { - delete this->m_pImpl; -} + namespace Internal + { + namespace Platform + { -bool DNS::LookupTxT -( -string lookup, -string &result -) -{ - bool ret = this->m_pImpl->LookupTxT(lookup, result); - status = this->m_pImpl->status; - return ret; -} + DNS::DNS() : + status(DNSError_None) + { + this->m_pImpl = new DNSImpl(); + } + DNS::~DNS() + { + delete this->m_pImpl; + } + + bool DNS::LookupTxT(string lookup, string &result) + { + bool ret = this->m_pImpl->LookupTxT(lookup, result); + status = this->m_pImpl->status; + return ret; + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/DNS.h b/cpp/src/platform/DNS.h index 32b26a1f17..f5c76ae58e 100644 --- a/cpp/src/platform/DNS.h +++ b/cpp/src/platform/DNS.h @@ -33,46 +33,50 @@ #include "Defs.h" #include "platform/Log.h" - namespace OpenZWave { - class DNSImpl; - - /** \brief Return codes for DNS lookups - * \ingroup Platform - */ - enum DNSError + namespace Internal { - DNSError_None = 0, - DNSError_NotFound, /**< No Record Exists - There for no Config File exists */ - DNSError_DomainError, /**< Domain didn't resolve etc */ - DNSError_InternalError /**< A Internal Error Occured */ - }; + namespace Platform + { + class DNSImpl; + /** \brief Return codes for DNS lookups + * \ingroup Platform + */ + enum DNSError + { + DNSError_None = 0, + DNSError_NotFound, /**< No Record Exists - There for no Config File exists */ + DNSError_DomainError, /**< Domain didn't resolve etc */ + DNSError_InternalError /**< A Internal Error Occured */ + }; - /** \brief Implements platform-independent DNS lookup Operations. - * \ingroup Platform - */ - class DNS - { - public: - DNS(); - ~DNS(); - /** - * \brief Starts a DNS lookup for a TXT record - * - * This function will lookup the TXT record for a address - * - * \param lookup the DNS address to lookup - * \param result the result of the lookup request, or empty if the lookup failed. - * - * \return success/failure of the Lookup request + /** \brief Implements platform-independent DNS lookup Operations. + * \ingroup Platform */ - bool LookupTxT(string lookup, string &result); - DNSError status; - private: - DNSImpl *m_pImpl; - }; -} + class DNS + { + public: + DNS(); + ~DNS(); + /** + * \brief Starts a DNS lookup for a TXT record + * + * This function will lookup the TXT record for a address + * + * \param lookup the DNS address to lookup + * \param result the result of the lookup request, or empty if the lookup failed. + * + * \return success/failure of the Lookup request + */ + bool LookupTxT(string lookup, string &result); + DNSError status; + private: + DNSImpl *m_pImpl; + }; + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave #endif diff --git a/cpp/src/platform/Event.cpp b/cpp/src/platform/Event.cpp index 76cb4ea2cd..249efd743d 100644 --- a/cpp/src/platform/Event.cpp +++ b/cpp/src/platform/Event.cpp @@ -36,74 +36,68 @@ #include "platform/unix/EventImpl.h" // Platform-specific implementation of an event #endif -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -Event::Event -( -): - m_pImpl( new EventImpl() ) -{ -} + Event::Event() : + m_pImpl(new EventImpl()) + { + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -Event::~Event -( -) -{ - delete m_pImpl; -} + Event::~Event() + { + delete m_pImpl; + } //----------------------------------------------------------------------------- // // Set the event to signalled //----------------------------------------------------------------------------- -void Event::Set -( -) -{ - m_pImpl->Set(); - Notify(); // Notify any watchers that the event is now set -} + void Event::Set() + { + m_pImpl->Set(); + Notify(); // Notify any watchers that the event is now set + } //----------------------------------------------------------------------------- // // Set the event to not signalled //----------------------------------------------------------------------------- -void Event::Reset -( -) -{ - m_pImpl->Reset(); -} + void Event::Reset() + { + m_pImpl->Reset(); + } //----------------------------------------------------------------------------- // // Test whether the event is set //----------------------------------------------------------------------------- -bool Event::IsSignalled -( -) -{ - return m_pImpl->IsSignalled(); -} + bool Event::IsSignalled() + { + return m_pImpl->IsSignalled(); + } //----------------------------------------------------------------------------- // // Wait for the event to become signalled //----------------------------------------------------------------------------- -bool Event::Wait -( - int32 const _timeout -) -{ - return m_pImpl->Wait( _timeout ); -} - + bool Event::Wait(int32 const _timeout) + { + return m_pImpl->Wait(_timeout); + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/Event.h b/cpp/src/platform/Event.h index a026608d73..6e963dde49 100644 --- a/cpp/src/platform/Event.h +++ b/cpp/src/platform/Event.h @@ -32,60 +32,65 @@ namespace OpenZWave { - class EventImpl; - - /** \brief Platform-independent definition of event objects. - * \ingroup Platform - */ - class Event: public Wait + namespace Internal { - friend class SerialControllerImpl; - friend class Wait; + namespace Platform + { + class EventImpl; - public: - /** - * Constructor. - * Creates a cross-platform event object equivalent to the Windows manual-reset event - */ - Event(); + /** \brief Platform-independent definition of event objects. + * \ingroup Platform + */ + class Event: public Wait + { + friend class SerialControllerImpl; + friend class Wait; - /** - * Set the event to signalled. - * \see Reset, Wait - */ - void Set(); + public: + /** + * Constructor. + * Creates a cross-platform event object equivalent to the Windows manual-reset event + */ + Event(); - /** - * Set the event to not signalled. - * \see Set, Wait - */ - void Reset(); + /** + * Set the event to signalled. + * \see Reset, Wait + */ + void Set(); - protected: - /** - * Used by the Wait class to test whether the event is set. - */ - virtual bool IsSignalled(); + /** + * Set the event to not signalled. + * \see Set, Wait + */ + void Reset(); - /** - * Used by the Wait::Multiple method. - * returns true if the event signalled, false if it timed out - */ - bool Wait( int32 _timeout ); + protected: + /** + * Used by the Wait class to test whether the event is set. + */ + virtual bool IsSignalled(); - /** - * Destructor. - * Destroys the event object. - */ - ~Event(); + /** + * Used by the Wait::Multiple method. + * returns true if the event signalled, false if it timed out + */ + bool Wait(int32 _timeout); - private: - Event( Event const& ); // prevent copy - Event& operator = ( Event const& ); // prevent assignment + /** + * Destructor. + * Destroys the event object. + */ + ~Event(); - EventImpl* m_pImpl; // Pointer to an object that encapsulates the platform-specific implementation of a event. - }; + private: + Event(Event const&); // prevent copy + Event& operator =(Event const&); // prevent assignment + EventImpl* m_pImpl; // Pointer to an object that encapsulates the platform-specific implementation of a event. + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_Event_H diff --git a/cpp/src/platform/FileOps.cpp b/cpp/src/platform/FileOps.cpp index a6d12f99c2..add41a38d7 100644 --- a/cpp/src/platform/FileOps.cpp +++ b/cpp/src/platform/FileOps.cpp @@ -36,162 +36,142 @@ #include "platform/unix/FileOpsImpl.h" // Platform-specific implementation of a File Operations #endif -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { -FileOps* FileOps::s_instance = NULL; -FileOpsImpl* FileOps::m_pImpl = NULL; + FileOps* FileOps::s_instance = NULL; + FileOpsImpl* FileOps::m_pImpl = NULL; //----------------------------------------------------------------------------- // // Static creation of the singleton //----------------------------------------------------------------------------- -FileOps* FileOps::Create -( -) -{ - if( s_instance == NULL ) - { - s_instance = new FileOps(); - } - return s_instance; -} + FileOps* FileOps::Create() + { + if (s_instance == NULL) + { + s_instance = new FileOps(); + } + return s_instance; + } //----------------------------------------------------------------------------- // // Static method to destroy the fileops singleton. //----------------------------------------------------------------------------- -void FileOps::Destroy -( -) -{ - delete s_instance; - s_instance = NULL; -} + void FileOps::Destroy() + { + delete s_instance; + s_instance = NULL; + } //----------------------------------------------------------------------------- // // Static method to check for existance of a folder //----------------------------------------------------------------------------- -bool FileOps::FolderExists -( - const string &_folderName -) -{ - if( s_instance != NULL ) - { - return s_instance->m_pImpl->FolderExists( _folderName ); - } - return false; -} - -/** - * FileExists. Check for the existance of a file. - * \param string. file name. - * \return Bool value indicating existance. - */ -bool FileOps::FileExists -( - const string &_fileName -) -{ - if( s_instance != NULL ) - { - return s_instance->m_pImpl->FileExists( _fileName ); - } - return false; -} - -/** - * FileWriteable. Check if we can write to a file. - * \param string. file name. - * \return Bool value indicating write permissions. - */ -bool FileOps::FileWriteable -( - const string &_fileName -) -{ - if( s_instance != NULL ) - { - return s_instance->m_pImpl->FileWriteable( _fileName ); - } - return false; -} - -/** - * FileRotate. Rotate a File - * \param string. file name. - * \return Bool value indicating write permissions. - */ -bool FileOps::FileRotate -( - const string &_fileName -) -{ - if( s_instance != NULL ) - { - return s_instance->m_pImpl->FileRotate( _fileName ); - } - return false; -} - -/** - * FileCopy. Copy a File - * \param string. source file name. - * \param string. destination file name - * \return Bool value indicating success. - */ -bool FileOps::FileCopy -( - const string &_fileName, - const string &_destfileName -) -{ - - if( s_instance != NULL ) - { - return s_instance->m_pImpl->FileCopy( _fileName, _destfileName ); - } - return false; -} - -/** - * FolderCreate. Create a Folder - * \param string. folder name - * \return Bool value indicating success. - */ -bool FileOps::FolderCreate -( - const string &_folderName -) -{ - - if( s_instance != NULL ) - { - return s_instance->m_pImpl->FolderCreate( _folderName); - } - return false; -} - + bool FileOps::FolderExists(const string &_folderName) + { + if (s_instance != NULL) + { + return s_instance->m_pImpl->FolderExists(_folderName); + } + return false; + } + + /** + * FileExists. Check for the existance of a file. + * \param string. file name. + * \return Bool value indicating existance. + */ + bool FileOps::FileExists(const string &_fileName) + { + if (s_instance != NULL) + { + return s_instance->m_pImpl->FileExists(_fileName); + } + return false; + } + + /** + * FileWriteable. Check if we can write to a file. + * \param string. file name. + * \return Bool value indicating write permissions. + */ + bool FileOps::FileWriteable(const string &_fileName) + { + if (s_instance != NULL) + { + return s_instance->m_pImpl->FileWriteable(_fileName); + } + return false; + } + + /** + * FileRotate. Rotate a File + * \param string. file name. + * \return Bool value indicating write permissions. + */ + bool FileOps::FileRotate(const string &_fileName) + { + if (s_instance != NULL) + { + return s_instance->m_pImpl->FileRotate(_fileName); + } + return false; + } + + /** + * FileCopy. Copy a File + * \param string. source file name. + * \param string. destination file name + * \return Bool value indicating success. + */ + bool FileOps::FileCopy(const string &_fileName, const string &_destfileName) + { + + if (s_instance != NULL) + { + return s_instance->m_pImpl->FileCopy(_fileName, _destfileName); + } + return false; + } + + /** + * FolderCreate. Create a Folder + * \param string. folder name + * \return Bool value indicating success. + */ + bool FileOps::FolderCreate(const string &_folderName) + { + + if (s_instance != NULL) + { + return s_instance->m_pImpl->FolderCreate(_folderName); + } + return false; + } //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -FileOps::FileOps -( -) -{ - m_pImpl = new FileOpsImpl(); -} + FileOps::FileOps() + { + m_pImpl = new FileOpsImpl(); + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -FileOps::~FileOps -( -) -{ - delete m_pImpl; -} + FileOps::~FileOps() + { + delete m_pImpl; + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/FileOps.h b/cpp/src/platform/FileOps.h index 106b5e6f1c..bad4b62898 100644 --- a/cpp/src/platform/FileOps.h +++ b/cpp/src/platform/FileOps.h @@ -34,80 +34,83 @@ namespace OpenZWave { - class FileOpsImpl; - - /** \brief Implements platform-independent File Operations. - * \ingroup Platform - */ - class FileOps + namespace Internal { - public: - /** - * Create a FileOps cross-platform singleton. - * \return a pointer to the file operations object. - * \see Destroy. - */ - static FileOps* Create(); - - /** - * Destroys the FileOps singleton. - * \see Create. - */ - static void Destroy(); - - /** - * FolderExists. Check for the existence of a folder. - * \param string. Folder name. - * \return Bool value indicating existence. - */ - static bool FolderExists( const string &_folderName ); - - /** - * FileExists. Check for the existence of a file. - * \param string. file name. - * \return Bool value indicating existence. - */ - static bool FileExists( const string &_fileName ); - - /** - * FileWriteable. Check if we can write to a file. - * \param string. file name. - * \return Bool value indicating write permissions. - */ - static bool FileWriteable( const string &_fileName ); - - /** - * FileRotate. Rotate a File - * \param string. file name. - * \return Bool value indicating write permissions. - */ - static bool FileRotate( const string &_fileName ); - - /** - * FileCopy. Copy a File - * \param string. source file name. - * \param string. destination file name - * \return Bool value indicating success. - */ - static bool FileCopy( const string &_fileName, const string &_destinationfile ); - - /** - * FolderCreate. Create a Folder - * \param string. folder name - * \return Bool value indicating success. - */ - static bool FolderCreate( const string &_folderName); - - - - private: - FileOps(); - ~FileOps(); - - static FileOpsImpl* m_pImpl; // Pointer to an object that encapsulates the platform-specific implementation of the FileOps. - static FileOps* s_instance; - }; - + namespace Platform + { + class FileOpsImpl; + + /** \brief Implements platform-independent File Operations. + * \ingroup Platform + */ + class FileOps + { + public: + /** + * Create a FileOps cross-platform singleton. + * \return a pointer to the file operations object. + * \see Destroy. + */ + static FileOps* Create(); + + /** + * Destroys the FileOps singleton. + * \see Create. + */ + static void Destroy(); + + /** + * FolderExists. Check for the existence of a folder. + * \param string. Folder name. + * \return Bool value indicating existence. + */ + static bool FolderExists(const string &_folderName); + + /** + * FileExists. Check for the existence of a file. + * \param string. file name. + * \return Bool value indicating existence. + */ + static bool FileExists(const string &_fileName); + + /** + * FileWriteable. Check if we can write to a file. + * \param string. file name. + * \return Bool value indicating write permissions. + */ + static bool FileWriteable(const string &_fileName); + + /** + * FileRotate. Rotate a File + * \param string. file name. + * \return Bool value indicating write permissions. + */ + static bool FileRotate(const string &_fileName); + + /** + * FileCopy. Copy a File + * \param string. source file name. + * \param string. destination file name + * \return Bool value indicating success. + */ + static bool FileCopy(const string &_fileName, const string &_destinationfile); + + /** + * FolderCreate. Create a Folder + * \param string. folder name + * \return Bool value indicating success. + */ + static bool FolderCreate(const string &_folderName); + + private: + FileOps(); + ~FileOps(); + + static FileOpsImpl* m_pImpl; // Pointer to an object that encapsulates the platform-specific implementation of the FileOps. + static FileOps* s_instance; + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_FileOps_H diff --git a/cpp/src/platform/HidController.cpp b/cpp/src/platform/HidController.cpp index 93fe50c4d3..19a5e49f5e 100644 --- a/cpp/src/platform/HidController.cpp +++ b/cpp/src/platform/HidController.cpp @@ -25,16 +25,15 @@ // //----------------------------------------------------------------------------- -#ifdef USE_HID - #include "Msg.h" #include "platform/Thread.h" #include "platform/Event.h" #include "platform/Log.h" #include "platform/TimeStamp.h" #include "platform/HidController.h" -#include "hidapi.h" +#ifdef USE_HID +#include "hidapi.h" #define CHECK_HIDAPI_RESULT(RESULT, ERRORLABEL) if (RESULT < 0) goto ERRORLABEL #define PACKET_BUFFER_LENGTH 256 @@ -44,501 +43,509 @@ #define INPUT_REPORT_LENGTH 0x5 #define OUTPUT_REPORT_LENGTH 0x0 -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -HidController::HidController -( -): - m_hHidController( NULL ), - m_thread( NULL ), - m_vendorId( 0x1b5f ), // Wayne Dalton - m_productId( 0x01 ), // ControlThink ThinkStick - m_serialNumber( "" ), - m_hidControllerName( "" ), - m_bOpen( false ) -{ -} + HidController::HidController + ( + ): + m_hHidController( NULL ), + m_thread( NULL ), + m_vendorId( 0x1b5f ),// Wayne Dalton + m_productId( 0x01 ),// ControlThink ThinkStick + m_serialNumber( "" ), + m_hidControllerName( "" ), + m_bOpen( false ) + { + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -HidController::~HidController -( -) -{ -} + HidController::~HidController + ( + ) + { + } //----------------------------------------------------------------------------- // // Set the USB vendor ID search value. The HID port must be closed for the setting to be accepted. //----------------------------------------------------------------------------- -bool HidController::SetVendorId -( - uint32 const _vendorId -) -{ - if( m_bOpen ) - { - return false; - } + bool HidController::SetVendorId + ( + uint32 const _vendorId + ) + { + if( m_bOpen ) + { + return false; + } - m_vendorId = _vendorId; - return true; -} + m_vendorId = _vendorId; + return true; + } //----------------------------------------------------------------------------- // // Set the USB product ID search value. The HID port must be closed for the setting to be accepted. //----------------------------------------------------------------------------- -bool HidController::SetProductId -( - uint32 const _productId -) -{ - if( m_bOpen ) - { - return false; - } + bool HidController::SetProductId + ( + uint32 const _productId + ) + { + if( m_bOpen ) + { + return false; + } - m_productId = _productId; - return true; -} + m_productId = _productId; + return true; + } //----------------------------------------------------------------------------- // // Set the USB serial number search value. The HID port must be closed for the setting to be accepted. //----------------------------------------------------------------------------- -bool HidController::SetSerialNumber -( - string const& _serialNumber -) -{ - if( m_bOpen ) - { - return false; - } + bool HidController::SetSerialNumber + ( + string const& _serialNumber + ) + { + if( m_bOpen ) + { + return false; + } - m_serialNumber = _serialNumber; - return true; -} + m_serialNumber = _serialNumber; + return true; + } //----------------------------------------------------------------------------- // // Open and configure a HID port //----------------------------------------------------------------------------- -bool HidController::Open -( - string const& _hidControllerName -) -{ - if( m_bOpen ) - { - return false; - } + bool HidController::Open + ( + string const& _hidControllerName + ) + { + if( m_bOpen ) + { + return false; + } - m_hidControllerName = _hidControllerName; + m_hidControllerName = _hidControllerName; - // Try to init the serial port - if( !Init( 1 ) ) - { - // Failed. We bail to allow the app a chance to take over, rather than retry - // automatically. Automatic retries only occur after a successful init. - return false; - } + // Try to init the serial port + if( !Init( 1 ) ) + { + // Failed. We bail to allow the app a chance to take over, rather than retry + // automatically. Automatic retries only occur after a successful init. + return false; + } - m_thread = new Thread( "HidController" ); + m_thread = new Thread( "HidController" ); - // Start the read thread - m_thread->Start( ThreadEntryPoint, this ); - return true; -} + // Start the read thread + m_thread->Start( ThreadEntryPoint, this ); + return true; + } //----------------------------------------------------------------------------- // // Close a HID port //----------------------------------------------------------------------------- -bool HidController::Close -( -) -{ - if( m_thread ) - { - m_thread->Stop(); - m_thread->Release(); - m_thread = NULL; - } + bool HidController::Close + ( + ) + { + if( m_thread ) + { + m_thread->Stop(); + m_thread->Release(); + m_thread = NULL; + } - hid_close( m_hHidController ); - m_hHidController = NULL; + hid_close( m_hHidController ); + m_hHidController = NULL; - m_bOpen = false; - hid_exit(); - return true; -} + m_bOpen = false; + hid_exit(); + return true; + } //----------------------------------------------------------------------------- // // Entry point of the thread for receiving data from the HID port //----------------------------------------------------------------------------- -void HidController::ThreadEntryPoint -( - Event* _exitEvent, - void* _context -) -{ - HidController* hc = (HidController*)_context; - if( hc ) - { - hc->ThreadProc( _exitEvent ); - } -} + void HidController::ThreadEntryPoint + ( + Event* _exitEvent, + void* _context + ) + { + HidController* hc = (HidController*)_context; + if( hc ) + { + hc->ThreadProc( _exitEvent ); + } + } //----------------------------------------------------------------------------- // // Handle receiving data //----------------------------------------------------------------------------- -void HidController::ThreadProc -( - Event* _exitEvent -) -{ - uint32 attempts = 0; - while( true ) - { - // Init must have been called successfully during Open, so we - // don't do it again until the end of the loop - if( m_hHidController ) - { - // Enter read loop. Call will only return if - // an exit is requested or an error occurs - Read(); - - // Reset the attempts, so we get a rapid retry for temporary errors - attempts = 0; - } - - if( attempts < 25 ) - { - // Retry every 5 seconds for the first two minutes... - if( Wait::Single( _exitEvent, 5000 ) >= 0 ) + void HidController::ThreadProc + ( + Event* _exitEvent + ) { - // Exit signalled. - break; - } - } - else - { - // ...retry every 30 seconds after that - if( Wait::Single( _exitEvent, 30000 ) >= 0 ) - { - // Exit signalled. - break; + uint32 attempts = 0; + while( true ) + { + // Init must have been called successfully during Open, so we + // don't do it again until the end of the loop + if( m_hHidController ) + { + // Enter read loop. Call will only return if + // an exit is requested or an error occurs + Read(); + + // Reset the attempts, so we get a rapid retry for temporary errors + attempts = 0; + } + + if( attempts < 25 ) + { + // Retry every 5 seconds for the first two minutes... + if( Wait::Single( _exitEvent, 5000 ) >= 0 ) + { + // Exit signalled. + break; + } + } + else + { + // ...retry every 30 seconds after that + if( Wait::Single( _exitEvent, 30000 ) >= 0 ) + { + // Exit signalled. + break; + } + } + + Init( ++attempts ); + } } - } - - Init( ++attempts ); - } -} //----------------------------------------------------------------------------- // // Open the HID port //----------------------------------------------------------------------------- -bool HidController::Init -( - uint32 const _attempts -) -{ - // HIDAPI result - int hidApiResult; - const uint8 dataOutEnableZwave[3] = { 0x02, 0x01, 0x04 }; - - hid_init(); - Log::Write( LogLevel_Info, " Open HID port %s", m_hidControllerName.c_str() ); - m_hHidController = hid_open(m_vendorId, m_productId, NULL); - if (!m_hHidController) - { - Log::Write( LogLevel_Error, "Cannot find specified HID port with VID:%04hx and PID:0x%04hx.", m_vendorId, m_productId ); - - // Enumerate connected HIDs for debugging purposes - // Note: most OS intentionally hide keyboard/mouse devices from HID access - struct hid_device_info *devices, *currentDevice; - devices = hid_enumerate(0x0, 0x0); - currentDevice = devices; - - Log::Write( LogLevel_Error, "Enumerating connected HIDs:" ); - while (currentDevice) - { - Log::Write( LogLevel_Error, "\tVID:%04hx\tPID:0x%04hx\tSN:%ls\tMfg:%ls\tProd:%ls\tPath:%s", - currentDevice->vendor_id, - currentDevice->product_id, - currentDevice->serial_number, - currentDevice->manufacturer_string, - currentDevice->product_string, - currentDevice->path); - currentDevice = currentDevice->next; - } - hid_free_enumeration(devices); - - goto HidOpenFailure; - } - - wchar_t hidInfoString[255]; - hidInfoString[0] = 0x0000; - Log::Write( LogLevel_Info, " Found HID ZWave controller:"); - Log::Write( LogLevel_Info, " Vendor ID: 0x%04hx", m_vendorId); - Log::Write( LogLevel_Info, " Product ID: 0x%04hx", m_productId); - - hidApiResult = hid_get_manufacturer_string(m_hHidController, hidInfoString, 255); - if (hidApiResult < 0) - { - Log::Write( LogLevel_Info, " Manufacturer: <>", hidApiResult ); - } - else - { - Log::Write( LogLevel_Info, " Manufacturer: %ls", hidInfoString ); - } + bool HidController::Init + ( + uint32 const _attempts + ) + { + // HIDAPI result + int hidApiResult; + const uint8 dataOutEnableZwave[3] = + { 0x02, 0x01, 0x04}; + + hid_init(); + Log::Write( LogLevel_Info, " Open HID port %s", m_hidControllerName.c_str() ); + m_hHidController = hid_open(m_vendorId, m_productId, NULL); + if (!m_hHidController) + { + Log::Write( LogLevel_Error, "Cannot find specified HID port with VID:%04hx and PID:0x%04hx.", m_vendorId, m_productId ); + + // Enumerate connected HIDs for debugging purposes + // Note: most OS intentionally hide keyboard/mouse devices from HID access + struct hid_device_info *devices, *currentDevice; + devices = hid_enumerate(0x0, 0x0); + currentDevice = devices; + + Log::Write( LogLevel_Error, "Enumerating connected HIDs:" ); + while (currentDevice) + { + Log::Write( LogLevel_Error, "\tVID:%04hx\tPID:0x%04hx\tSN:%ls\tMfg:%ls\tProd:%ls\tPath:%s", + currentDevice->vendor_id, + currentDevice->product_id, + currentDevice->serial_number, + currentDevice->manufacturer_string, + currentDevice->product_string, + currentDevice->path); + currentDevice = currentDevice->next; + } + hid_free_enumeration(devices); + + goto HidOpenFailure; + } - hidApiResult = hid_get_product_string(m_hHidController, hidInfoString, 255); - if (hidApiResult < 0) - { - Log::Write( LogLevel_Info, " Product name: <>", hidApiResult ); - } - else - { - Log::Write( LogLevel_Info, " Product name: %ls", hidInfoString ); - } + wchar_t hidInfoString[255]; + hidInfoString[0] = 0x0000; + Log::Write( LogLevel_Info, " Found HID ZWave controller:"); + Log::Write( LogLevel_Info, " Vendor ID: 0x%04hx", m_vendorId); + Log::Write( LogLevel_Info, " Product ID: 0x%04hx", m_productId); - hidApiResult = hid_get_serial_number_string(m_hHidController, hidInfoString, 255); - if (hidApiResult < 0) - { - Log::Write( LogLevel_Warning, "Serial #: <>", hidApiResult ); - } - else - { - size_t serialLength = wcslen(hidInfoString); - char* serialHex = new char[serialLength + 1]; - memset(serialHex, 0, serialLength + 1); - for (size_t i = 0; i < serialLength; ++i) - { - snprintf(&serialHex[i], serialLength - i + 1, "%hx", (unsigned short)(hidInfoString[i] & 0x0f)); - } - Log::Write( LogLevel_Info, " Serial #: %ls --> %s", hidInfoString, serialHex ); - delete [] serialHex; - } - Log::Write( LogLevel_Info, "" ); - - // Turn on ZWave data via a short series of feature reports - uint8 dataIn[FEATURE_REPORT_LENGTH]; - - // Get Report ID 2 - // Not sure what the result is for, we don't use it so far - hidApiResult = GetFeatureReport(FEATURE_REPORT_LENGTH, 0x02, dataIn ); - CHECK_HIDAPI_RESULT(hidApiResult, HidOpenFailure); - - // Send Report ID 2 - 1 byte "0x04" - // Enables ZWave packet reports on ID 4 (tx) and ID 5 (rx) - hidApiResult = SendFeatureReport(0x3, dataOutEnableZwave); - CHECK_HIDAPI_RESULT(hidApiResult, HidOpenFailure); - - // Get Report ID 2 - // Not sure what the result is for, we don't use it so far - hidApiResult = GetFeatureReport(FEATURE_REPORT_LENGTH, 0x02, dataIn ); - CHECK_HIDAPI_RESULT(hidApiResult, HidOpenFailure); - - // Ensure that reads for input reports are blocked. - // Input report data is polled in Wait() to check if there are feature - // reports waiting to be retrieved that contain ZWave rx packets. - hidApiResult = hid_set_nonblocking(m_hHidController, 0); - CHECK_HIDAPI_RESULT(hidApiResult, HidOpenFailure); - - // Open successful - m_bOpen = true; - return true; - -HidOpenFailure: - Log::Write( LogLevel_Error, "Failed to open HID port %s", m_hidControllerName.c_str() ); - const wchar_t* errString = hid_error(m_hHidController); - Log::Write( LogLevel_Error, "HIDAPI ERROR STRING (if any): %ls", errString); - hid_close(m_hHidController); - m_hHidController = NULL; - return false; -} + hidApiResult = hid_get_manufacturer_string(m_hHidController, hidInfoString, 255); + if (hidApiResult < 0) + { + Log::Write( LogLevel_Info, " Manufacturer: <>", hidApiResult ); + } + else + { + Log::Write( LogLevel_Info, " Manufacturer: %ls", hidInfoString ); + } + + hidApiResult = hid_get_product_string(m_hHidController, hidInfoString, 255); + if (hidApiResult < 0) + { + Log::Write( LogLevel_Info, " Product name: <>", hidApiResult ); + } + else + { + Log::Write( LogLevel_Info, " Product name: %ls", hidInfoString ); + } + + hidApiResult = hid_get_serial_number_string(m_hHidController, hidInfoString, 255); + if (hidApiResult < 0) + { + Log::Write( LogLevel_Warning, "Serial #: <>", hidApiResult ); + } + else + { + size_t serialLength = wcslen(hidInfoString); + char* serialHex = new char[serialLength + 1]; + memset(serialHex, 0, serialLength + 1); + for (size_t i = 0; i < serialLength; ++i) + { + snprintf(&serialHex[i], serialLength - i + 1, "%hx", (unsigned short)(hidInfoString[i] & 0x0f)); + } + Log::Write( LogLevel_Info, " Serial #: %ls --> %s", hidInfoString, serialHex ); + delete [] serialHex; + } + Log::Write( LogLevel_Info, "" ); + + // Turn on ZWave data via a short series of feature reports + uint8 dataIn[FEATURE_REPORT_LENGTH]; + + // Get Report ID 2 + // Not sure what the result is for, we don't use it so far + hidApiResult = GetFeatureReport(FEATURE_REPORT_LENGTH, 0x02, dataIn ); + CHECK_HIDAPI_RESULT(hidApiResult, HidOpenFailure); + + // Send Report ID 2 - 1 byte "0x04" + // Enables ZWave packet reports on ID 4 (tx) and ID 5 (rx) + hidApiResult = SendFeatureReport(0x3, dataOutEnableZwave); + CHECK_HIDAPI_RESULT(hidApiResult, HidOpenFailure); + + // Get Report ID 2 + // Not sure what the result is for, we don't use it so far + hidApiResult = GetFeatureReport(FEATURE_REPORT_LENGTH, 0x02, dataIn ); + CHECK_HIDAPI_RESULT(hidApiResult, HidOpenFailure); + + // Ensure that reads for input reports are blocked. + // Input report data is polled in Wait() to check if there are feature + // reports waiting to be retrieved that contain ZWave rx packets. + hidApiResult = hid_set_nonblocking(m_hHidController, 0); + CHECK_HIDAPI_RESULT(hidApiResult, HidOpenFailure); + + // Open successful + m_bOpen = true; + return true; + + HidOpenFailure: + Log::Write( LogLevel_Error, "Failed to open HID port %s", m_hidControllerName.c_str() ); + const wchar_t* errString = hid_error(m_hHidController); + Log::Write( LogLevel_Error, "HIDAPI ERROR STRING (if any): %ls", errString); + hid_close(m_hHidController); + m_hHidController = NULL; + return false; + } //----------------------------------------------------------------------------- // // Read data from the HID port //----------------------------------------------------------------------------- -void HidController::Read -( -) -{ - uint8 buffer[FEATURE_REPORT_LENGTH]; - int bytesRead = 0; - uint8 inputReport[INPUT_REPORT_LENGTH]; - TimeStamp readTimer; - - while( true ) - { - // Rx feature report buffer should contain - // [0] - 0x05 (rx feature report ID) - // [1] - length of rx data (or 0x00 and no further bytes if no rx data waiting) - // [2]... - rx data - // We poll this waiting for data. - bytesRead = GetFeatureReport(FEATURE_REPORT_LENGTH, 0x5, buffer); - CHECK_HIDAPI_RESULT(bytesRead, HidPortError); - if( bytesRead >= 2 ) - { - - if( buffer[1] > 0 ) + void HidController::Read + ( + ) { - string tmp = ""; - for (int i = 0; i < buffer[1]; i++) + uint8 buffer[FEATURE_REPORT_LENGTH]; + int bytesRead = 0; + uint8 inputReport[INPUT_REPORT_LENGTH]; + TimeStamp readTimer; + + while( true ) { - char bstr[16]; - snprintf( bstr, sizeof(bstr), "0x%.2x ", buffer[2+i] ); - tmp += bstr; + // Rx feature report buffer should contain + // [0] - 0x05 (rx feature report ID) + // [1] - length of rx data (or 0x00 and no further bytes if no rx data waiting) + // [2]... - rx data + // We poll this waiting for data. + bytesRead = GetFeatureReport(FEATURE_REPORT_LENGTH, 0x5, buffer); + CHECK_HIDAPI_RESULT(bytesRead, HidPortError); + if( bytesRead >= 2 ) + { + + if( buffer[1] > 0 ) + { + string tmp = ""; + for (int i = 0; i < buffer[1]; i++) + { + char bstr[16]; + snprintf( bstr, sizeof(bstr), "0x%.2x ", buffer[2+i] ); + tmp += bstr; + } + Log::Write( LogLevel_Detail, "hid report read=%d ID=%d len=%d %s", bytesRead, buffer[0], buffer[1], tmp.c_str() ); + } + + if( buffer[1] > 0 ) + { + Put( &buffer[2], buffer[1] ); + } + } + if( readTimer.TimeRemaining() <= 0 ) + { + // Hang a hid_read to acknowledge receipt. Seems the response is conveying + // transaction status. + // Wayne-Dalton input report data is structured as follows (best guess): + // [0] 0x03 - input report ID + // [1] 0x01 - ??? never changes + // [2] 0xNN - if 0x01, no feature reports waiting + // if 0x02, feature report ID 0x05 is waiting to be retrieved + // [3,4] 0xNNNN - Number of ZWave messages? + + int hidApiResult = hid_read( m_hHidController, inputReport, INPUT_REPORT_LENGTH ); + //if( hidApiResult != 0 ) + //{ + // string tmp = ""; + // for( int i = 0; i < INPUT_REPORT_LENGTH; i++ ) + // { + // char bstr[16]; + // snprintf(bstr, sizeof(bstr), "%02x ", inputReport[i] ); + // tmp += bstr; + // } + // Log::Write( LogLevel_Detail, "hid read %d %s", hidApiResult, tmp.c_str() ); + //} + + if( hidApiResult == -1 ) + { + const wchar_t* errString = hid_error(m_hHidController); + Log::Write( LogLevel_Warning, "Error: HID port returned error reading input bytes: 0x%08hx, HIDAPI error string: %ls", hidApiResult, errString ); + } + readTimer.SetTime( 100 ); + } + m_thread->Sleep(10); } - Log::Write( LogLevel_Detail, "hid report read=%d ID=%d len=%d %s", bytesRead, buffer[0], buffer[1], tmp.c_str() ); - } - if( buffer[1] > 0 ) - { - Put( &buffer[2], buffer[1] ); - } - } - if( readTimer.TimeRemaining() <= 0 ) - { - // Hang a hid_read to acknowledge receipt. Seems the response is conveying - // transaction status. - // Wayne-Dalton input report data is structured as follows (best guess): - // [0] 0x03 - input report ID - // [1] 0x01 - ??? never changes - // [2] 0xNN - if 0x01, no feature reports waiting - // if 0x02, feature report ID 0x05 is waiting to be retrieved - // [3,4] 0xNNNN - Number of ZWave messages? - - int hidApiResult = hid_read( m_hHidController, inputReport, INPUT_REPORT_LENGTH ); - //if( hidApiResult != 0 ) - //{ - // string tmp = ""; - // for( int i = 0; i < INPUT_REPORT_LENGTH; i++ ) - // { - // char bstr[16]; - // snprintf(bstr, sizeof(bstr), "%02x ", inputReport[i] ); - // tmp += bstr; - // } - // Log::Write( LogLevel_Detail, "hid read %d %s", hidApiResult, tmp.c_str() ); - //} - - if( hidApiResult == -1 ) - { - const wchar_t* errString = hid_error(m_hHidController); - Log::Write( LogLevel_Warning, "Error: HID port returned error reading input bytes: 0x%08hx, HIDAPI error string: %ls", hidApiResult, errString ); + HidPortError: + Log::Write( LogLevel_Warning, "Error: HID port returned error reading rest of packet: 0x%08hx, HIDAPI error string:", bytesRead ); + Log::Write( LogLevel_Warning, "%ls", hid_error(m_hHidController)); } - readTimer.SetTime( 100 ); - } - m_thread->Sleep(10); - } - -HidPortError: - Log::Write( LogLevel_Warning, "Error: HID port returned error reading rest of packet: 0x%08hx, HIDAPI error string:", bytesRead ); - Log::Write( LogLevel_Warning, "%ls", hid_error(m_hHidController)); -} //----------------------------------------------------------------------------- // // Send data to the HID port //----------------------------------------------------------------------------- -uint32 HidController::Write -( - uint8* _buffer, - uint32 _length -) -{ - if( !m_bOpen ) - { - //Error - Log::Write( LogLevel_Warning, "Error: HID port must be opened before writing" ); - return 0; - } + uint32 HidController::Write + ( + uint8* _buffer, + uint32 _length + ) + { + if( !m_bOpen ) + { + //Error + Log::Write( LogLevel_Warning, "Error: HID port must be opened before writing" ); + return 0; + } - if ( FEATURE_REPORT_LENGTH - 2 < _length) - { - //Error - Log::Write( LogLevel_Info, "Error: Write buffer length %d exceeded feature report data capacity %d", _length, FEATURE_REPORT_LENGTH - 2 ); - return 0; - } - - // transmit buffer should be arranged: - // byte 0 - 0x04 (tx feature report) - // byte 1 - length of tx data - // byte 2.... - tx data - uint8 hidBuffer[FEATURE_REPORT_LENGTH]; - memset(hidBuffer, 0, FEATURE_REPORT_LENGTH); - hidBuffer[0] = 0x4; - hidBuffer[1] = (uint8)_length; - memcpy(&hidBuffer[2], _buffer, _length); - - Log::Write( LogLevel_Debug, " HidController::Write (sent to controller)" ); - LogData(_buffer, _length, " Write: "); - - int bytesSent = SendFeatureReport(FEATURE_REPORT_LENGTH, hidBuffer); - if (bytesSent < 2) - { - //Error - const wchar_t* errString = hid_error(m_hHidController); - Log::Write( LogLevel_Warning, "Error: HID port returned error sending bytes: 0x%08hx, HIDAPI error string: %ls", bytesSent, errString ); - return 0; - } + if ( FEATURE_REPORT_LENGTH - 2 < _length) + { + //Error + Log::Write( LogLevel_Info, "Error: Write buffer length %d exceeded feature report data capacity %d", _length, FEATURE_REPORT_LENGTH - 2 ); + return 0; + } + + // transmit buffer should be arranged: + // byte 0 - 0x04 (tx feature report) + // byte 1 - length of tx data + // byte 2.... - tx data + uint8 hidBuffer[FEATURE_REPORT_LENGTH]; + memset(hidBuffer, 0, FEATURE_REPORT_LENGTH); + hidBuffer[0] = 0x4; + hidBuffer[1] = (uint8)_length; + memcpy(&hidBuffer[2], _buffer, _length); + + Log::Write( LogLevel_Debug, " HidController::Write (sent to controller)" ); + LogData(_buffer, _length, " Write: "); + + int bytesSent = SendFeatureReport(FEATURE_REPORT_LENGTH, hidBuffer); + if (bytesSent < 2) + { + //Error + const wchar_t* errString = hid_error(m_hHidController); + Log::Write( LogLevel_Warning, "Error: HID port returned error sending bytes: 0x%08hx, HIDAPI error string: %ls", bytesSent, errString ); + return 0; + } - return (uint32)bytesSent - 2; -} + return (uint32)bytesSent - 2; + } //----------------------------------------------------------------------------- // // Read bytes from the specified HID feature report //----------------------------------------------------------------------------- -int HidController::GetFeatureReport -( - uint32 _length, - uint8 _reportId, - uint8* _buffer -) -{ - int result; - _buffer[0] = _reportId; - result = hid_get_feature_report(m_hHidController, _buffer, _length); - if (result < 0) - { - Log::Write( LogLevel_Info, "Error: HID GetFeatureReport on ID 0x%hx returned (0x%.8x)", _reportId, result ); - } - return result; -} + int HidController::GetFeatureReport + ( + uint32 _length, + uint8 _reportId, + uint8* _buffer + ) + { + int result; + _buffer[0] = _reportId; + result = hid_get_feature_report(m_hHidController, _buffer, _length); + if (result < 0) + { + Log::Write( LogLevel_Info, "Error: HID GetFeatureReport on ID 0x%hx returned (0x%.8x)", _reportId, result ); + } + return result; + } //----------------------------------------------------------------------------- // // Write bytes to the specified HID feature report //----------------------------------------------------------------------------- -int HidController::SendFeatureReport -( - uint32 _length, - const uint8* _data -) -{ - int result; - - result = hid_send_feature_report(m_hHidController, _data, _length); - if (result < 0) - { - Log::Write( LogLevel_Info, "Error: HID SendFeatureReport on ID 0x%hx returned (0x%.8x)", _data[0], result ); - } - return result; -} + int HidController::SendFeatureReport + ( + uint32 _length, + const uint8* _data + ) + { + int result; + result = hid_send_feature_report(m_hHidController, _data, _length); + if (result < 0) + { + Log::Write( LogLevel_Info, "Error: HID SendFeatureReport on ID 0x%hx returned (0x%.8x)", _data[0], result ); + } + return result; + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave #endif /* USE_HID */ diff --git a/cpp/src/platform/HidController.h b/cpp/src/platform/HidController.h index 4e6de28872..c908bc3564 100644 --- a/cpp/src/platform/HidController.h +++ b/cpp/src/platform/HidController.h @@ -32,6 +32,7 @@ #include "Defs.h" #include "platform/Controller.h" +#ifdef USE_HID struct hid_device_; @@ -39,117 +40,124 @@ typedef struct hid_device_ hid_device; namespace OpenZWave { - class Driver; - class Msg; - class Thread; - class Event; - - - /** \brief Interface for controllers that implement a HID emulation - * \ingroup Platform - */ - class HidController: public Controller + namespace Internal { - public: - /** - * Constructor. - * Creates an object that represents a HID port. - */ - HidController(); - - /** - * Destructor. - * Destroys the HID port object. - */ - virtual ~HidController(); - - /** - * Set the USB vendor ID search value. The HID port must be closed for the setting to be accepted. - * @param _baud Vendor ID value to match when enumerating USB HID devices. - * @return True if the vendor ID value was accepted. - * @see Open, Close - */ - bool SetVendorId( uint32 const _vendorId ); - - /** - * Set the USB product ID search value. The HID port must be closed for the setting to be accepted. - * @param _parity Product ID value to match when enumerating USB HID devices. - * @return True if the product ID value was accepted. - * @see Open, Close - */ - bool SetProductId( uint32 const _productId ); - - /** - * Set the USB serial number search value. The HID port must be closed for the setting to be accepted. - * @param _parity Serial number string to match when enumerating USB HID devices. If empty, any serial number will be accepted. - * @return True if the serial number value was accepted. - * @see Open, Close - */ - bool SetSerialNumber( string const& _serialNumber ); - - /** - * Open a HID port. - * Attempts to open a HID port and initialize it with the specified parameters. - * @param _HidControllerName The name of the port to open. For example, ttyS1 on Linux, or \\.\COM2 in Windows. - * @return True if the port was opened and configured successfully. - * @see Close, Read, Write - */ - bool Open( string const& _hidControllerName ); - - /** - * Close a HID port. - * Closes the HID port. - * @return True if the port was closed successfully, or false if the port was already closed, or an error occurred. - * @see Open - */ - bool Close(); - - /** - * Write to a HID port. - * Attempts to write data to an open HID port. - * @param _buffer Pointer to a block of memory containing the data to be written. - * @param _length Length in bytes of the data. - * @return The number of bytes written. - * @see Read, Open, Close - */ - uint32 Write( uint8* _buffer, uint32 _length ); - - private: - bool Init( uint32 const _attempts ); - void Read(); - - // helpers for internal use only - - /** - * Read bytes from the specified HID feature report - * @param _buffer Buffer array for receiving the feature report bytes. - * @param _length Length of the buffer array. - * @param _reportId ID of the report to read. - * @return Actual number of bytes retrieved, or -1 on error. - */ - int GetFeatureReport( uint32 _length, uint8 _reportId, uint8* _buffer ); - - /** - * Write bytes to the specified HID feature report - * @param _data Bytes to be written to the feature report. - * @param _length Length of bytes to be written. - * @return Actal number of bytes written, or -1 on error. - */ - int SendFeatureReport( uint32 _length, const uint8* _data ); - - static void ThreadEntryPoint( Event* _exitEvent, void* _context ); - void ThreadProc( Event* _exitEvent ); - - hid_device* m_hHidController; - Thread* m_thread; - uint32 m_vendorId; - uint32 m_productId; - string m_serialNumber; - string m_hidControllerName; - bool m_bOpen; - }; - + namespace Platform + { + + class Driver; + class Msg; + class Thread; + class Event; + + /** \brief Interface for controllers that implement a HID emulation + * \ingroup Platform + */ + class HidController: public Controller + { + public: + /** + * Constructor. + * Creates an object that represents a HID port. + */ + HidController(); + + /** + * Destructor. + * Destroys the HID port object. + */ + virtual ~HidController(); + + /** + * Set the USB vendor ID search value. The HID port must be closed for the setting to be accepted. + * @param _baud Vendor ID value to match when enumerating USB HID devices. + * @return True if the vendor ID value was accepted. + * @see Open, Close + */ + bool SetVendorId( uint32 const _vendorId ); + + /** + * Set the USB product ID search value. The HID port must be closed for the setting to be accepted. + * @param _parity Product ID value to match when enumerating USB HID devices. + * @return True if the product ID value was accepted. + * @see Open, Close + */ + bool SetProductId( uint32 const _productId ); + + /** + * Set the USB serial number search value. The HID port must be closed for the setting to be accepted. + * @param _parity Serial number string to match when enumerating USB HID devices. If empty, any serial number will be accepted. + * @return True if the serial number value was accepted. + * @see Open, Close + */ + bool SetSerialNumber( string const& _serialNumber ); + + /** + * Open a HID port. + * Attempts to open a HID port and initialize it with the specified parameters. + * @param _HidControllerName The name of the port to open. For example, ttyS1 on Linux, or \\.\COM2 in Windows. + * @return True if the port was opened and configured successfully. + * @see Close, Read, Write + */ + bool Open( string const& _hidControllerName ); + + /** + * Close a HID port. + * Closes the HID port. + * @return True if the port was closed successfully, or false if the port was already closed, or an error occurred. + * @see Open + */ + bool Close(); + + /** + * Write to a HID port. + * Attempts to write data to an open HID port. + * @param _buffer Pointer to a block of memory containing the data to be written. + * @param _length Length in bytes of the data. + * @return The number of bytes written. + * @see Read, Open, Close + */ + uint32 Write( uint8* _buffer, uint32 _length ); + + private: + bool Init( uint32 const _attempts ); + void Read(); + + // helpers for internal use only + + /** + * Read bytes from the specified HID feature report + * @param _buffer Buffer array for receiving the feature report bytes. + * @param _length Length of the buffer array. + * @param _reportId ID of the report to read. + * @return Actual number of bytes retrieved, or -1 on error. + */ + int GetFeatureReport( uint32 _length, uint8 _reportId, uint8* _buffer ); + + /** + * Write bytes to the specified HID feature report + * @param _data Bytes to be written to the feature report. + * @param _length Length of bytes to be written. + * @return Actal number of bytes written, or -1 on error. + */ + int SendFeatureReport( uint32 _length, const uint8* _data ); + + static void ThreadEntryPoint( Event* _exitEvent, void* _context ); + void ThreadProc( Event* _exitEvent ); + + hid_device* m_hHidController; + Thread* m_thread; + uint32 m_vendorId; + uint32 m_productId; + string m_serialNumber; + string m_hidControllerName; + bool m_bOpen; + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave +#endif + #endif //_HidController_H diff --git a/cpp/src/platform/HttpClient.cpp b/cpp/src/platform/HttpClient.cpp index d5fa9ff15d..2fc3fff698 100644 --- a/cpp/src/platform/HttpClient.cpp +++ b/cpp/src/platform/HttpClient.cpp @@ -41,7 +41,7 @@ # include # define SOCKET_ERROR (-1) # define INVALID_SOCKET (SOCKET)(~0) - typedef intptr_t SOCKET; +typedef intptr_t SOCKET; #endif #include @@ -55,7 +55,6 @@ #include #include - #ifdef MINIHTTP_USE_POLARSSL # include "polarssl/net.h" # include "polarssl/ssl.h" @@ -84,1442 +83,1258 @@ namespace OpenZWave { -namespace SimpleHTTPClient -{ + namespace Internal + { + namespace Platform + { #ifdef MINIHTTP_USE_POLARSSL // ------------------------ SSL STUFF ------------------------- -bool HasSSL -( -) -{ - return true; -} - -struct SSLCtx -{ - SSLCtx - ( - ): - _inited(0) - { - entropy_init(&entropy); - x509_crt_init(&cacert); - memset(&ssl, 0, sizeof(ssl_context)); - } - ~SSLCtx - ( - ) - { - entropy_free(&entropy); - x509_crt_free(&cacert); - ssl_free(&ssl); - if(_inited & 1) - ctr_drbg_free(&ctr_drbg); - if(_inited & 2) - ssl_free(&ssl); - } - bool init - ( - ) - { - const char *pers = "minihttp"; - const size_t perslen = strlen(pers); - - int err = ctr_drbg_init(&ctr_drbg, entropy_func, &entropy, (unsigned char *)pers, perslen); - if(err) - { - traceprint("SSLCtx::init(): ctr_drbg_init() returned %d\n", err); - return false; - } - _inited |= 1; - - err = ssl_init(&ssl); - if(err) - { - traceprint("SSLCtx::init(): ssl_init() returned %d\n", err); - return false; - } - _inited |= 2; - - return true; - } - void reset - ( - ) - { - ssl_session_reset(&ssl); - } - entropy_context entropy; - ctr_drbg_context ctr_drbg; - ssl_context ssl; - x509_crt cacert; - -private: - unsigned _inited; -}; - + bool HasSSL + ( + ) + { + return true; + } + + struct SSLCtx + { + SSLCtx + ( + ): + _inited(0) + { + entropy_init(&entropy); + x509_crt_init(&cacert); + memset(&ssl, 0, sizeof(ssl_context)); + } + ~SSLCtx + ( + ) + { + entropy_free(&entropy); + x509_crt_free(&cacert); + ssl_free(&ssl); + if(_inited & 1) + ctr_drbg_free(&ctr_drbg); + if(_inited & 2) + ssl_free(&ssl); + } + bool init + ( + ) + { + const char *pers = "minihttp"; + const size_t perslen = strlen(pers); + + int err = ctr_drbg_init(&ctr_drbg, entropy_func, &entropy, (unsigned char *)pers, perslen); + if(err) + { + traceprint("SSLCtx::init(): ctr_drbg_init() returned %d\n", err); + return false; + } + _inited |= 1; + + err = ssl_init(&ssl); + if(err) + { + traceprint("SSLCtx::init(): ssl_init() returned %d\n", err); + return false; + } + _inited |= 2; + + return true; + } + void reset + ( + ) + { + ssl_session_reset(&ssl); + } + entropy_context entropy; + ctr_drbg_context ctr_drbg; + ssl_context ssl; + x509_crt cacert; + + private: + unsigned _inited; + }; // ------------------------------------------------------------ #else // MINIHTTP_USE_POLARSSL -bool HasSSL -( -) -{ - return false; -} + bool HasSSL() + { + return false; + } #endif // MINIHTTP_USE_POLARSSL #define DEFAULT_BUFSIZE 4096 -inline int _GetError -( -) -{ + inline int _GetError() + { #ifdef _WIN32 - return WSAGetLastError(); + return WSAGetLastError(); #else - return errno; + return errno; #endif -} + } -inline std::string _GetErrorStr -( -int e -) -{ - std::string ret; + inline std::string _GetErrorStr(int e) + { + std::string ret; #ifdef WINRT - LPTSTR s = (LPTSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 512); - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, e, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), s, 512, NULL ); - char buffer[1024]; - wcstombs(buffer, s, sizeof(buffer)); - HeapFree(GetProcessHeap(), 0, s); - ret = buffer; + LPTSTR s = (LPTSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 512); + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, e, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), s, 512, NULL ); + char buffer[1024]; + wcstombs(buffer, s, sizeof(buffer)); + HeapFree(GetProcessHeap(), 0, s); + ret = buffer; #elif _WIN32 - LPTSTR s; - ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, e, 0, (LPTSTR)&s, 0, NULL); - if(s) - ret = s; - ::LocalFree(s); + LPTSTR s; + ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, e, 0, (LPTSTR)&s, 0, NULL); + if(s) + ret = s; + ::LocalFree(s); #else - const char *s = strerror(e); - if(s) - ret = s; + const char *s = strerror(e); + if (s) + ret = s; #endif - return ret; -} + return ret; + } -bool InitNetwork -( -) -{ + bool InitNetwork() + { #ifdef _WIN32 - WSADATA wsadata; - if(WSAStartup(MAKEWORD(2,2), &wsadata)) - { - traceprint("WSAStartup ERROR: %s", _GetErrorStr(_GetError()).c_str()); - return false; - } + WSADATA wsadata; + if(WSAStartup(MAKEWORD(2,2), &wsadata)) + { + traceprint("WSAStartup ERROR: %s", _GetErrorStr(_GetError()).c_str()); + return false; + } #endif - return true; -} + return true; + } -void StopNetwork -( -) -{ + void StopNetwork() + { #ifdef _WIN32 - WSACleanup(); + WSACleanup(); #endif -} - -static bool _Resolve -( -const char *host, -unsigned int port, -struct sockaddr_in *addr -) -{ - char port_str[16]; - sprintf(port_str, "%u", port); - - struct addrinfo hnt, *res = 0; - memset(&hnt, 0, sizeof(hnt)); - hnt.ai_family = AF_INET; - hnt.ai_socktype = SOCK_STREAM; - if (getaddrinfo(host, port_str, &hnt, &res)) - { - traceprint("RESOLVE ERROR: %s", _GetErrorStr(_GetError()).c_str()); - return false; - } - if (res) - { - if (res->ai_family != AF_INET) - { - traceprint("RESOLVE WTF: %s", _GetErrorStr(_GetError()).c_str()); - freeaddrinfo(res); - return false; - } - memcpy(addr, res->ai_addr, res->ai_addrlen); - freeaddrinfo(res); - return true; - } - return false; -} + } + + static bool _Resolve(const char *host, unsigned int port, struct sockaddr_in *addr) + { + char port_str[16]; + sprintf(port_str, "%u", port); + + struct addrinfo hnt, *res = 0; + memset(&hnt, 0, sizeof(hnt)); + hnt.ai_family = AF_INET; + hnt.ai_socktype = SOCK_STREAM; + if (getaddrinfo(host, port_str, &hnt, &res)) + { + traceprint("RESOLVE ERROR: %s", _GetErrorStr(_GetError()).c_str()); + return false; + } + if (res) + { + if (res->ai_family != AF_INET) + { + traceprint("RESOLVE WTF: %s", _GetErrorStr(_GetError()).c_str()); + freeaddrinfo(res); + return false; + } + memcpy(addr, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); + return true; + } + return false; + } // FIXME: this does currently not handle links like: // http://example.com/index.html#pos -bool SplitURI -( -const std::string& uri, -std::string& protocol, -std::string& host, -std::string& file, -int& port, -bool& useSSL -) -{ - const char *p = uri.c_str(); - const char *sl = strstr(p, "//"); - unsigned int offs = 0; - if(sl) - { - size_t colon = uri.find(':'); - size_t firstslash = uri.find('/'); - if(colon < firstslash) - protocol = uri.substr(0, colon); - if(strncmp(p, "http://", 7) == 0) - { - useSSL = false; - offs = 7; - } - else if(strncmp(p, "https://", 8) == 0) - { - useSSL = true; - offs = 8; - } - else - return false; - - p = sl + 2; - } - - sl = strchr(p, '/'); - if(!sl) - { - host = p; - file = "/"; - } - else - { - host = uri.substr(offs, sl - p); - file = sl; - } - - port = -1; - size_t colon = host.find(':'); - if(colon != std::string::npos) - { - port = atoi(host.c_str() + colon); - host.erase(port); - } - - return true; -} - -void URLEncode -( -const std::string& s, -std::string& enc -) -{ - const size_t len = s.length(); - char buf[3]; - buf[0] = '%'; - for(size_t i = 0; i < len; i++) - { - const unsigned char c = s[i]; - // from https://www.ietf.org/rfc/rfc1738.txt, page 3 - // with some changes for compatibility - if(isalnum(c) || c == '-' || c == '_' || c == '.' || c == ',') - enc += (char)c; - else if(c == ' ') - enc += '+'; - else - { - unsigned nib = (c >> 4) & 0xf; - buf[1] = nib < 10 ? '0' + nib : 'a' + (nib-10); - nib = c & 0xf; - buf[2] = nib < 10 ? '0' + nib : 'a' + (nib-10); - enc.append(&buf[0], 3); - } - } -} - -static bool _SetNonBlocking -( -SOCKET s, -bool nonblock -) -{ - if(!SOCKETVALID(s)) - return false; + bool SplitURI(const std::string& uri, std::string& protocol, std::string& host, std::string& file, int& port, bool& useSSL) + { + const char *p = uri.c_str(); + const char *sl = strstr(p, "//"); + unsigned int offs = 0; + if (sl) + { + size_t colon = uri.find(':'); + size_t firstslash = uri.find('/'); + if (colon < firstslash) + protocol = uri.substr(0, colon); + if (strncmp(p, "http://", 7) == 0) + { + useSSL = false; + offs = 7; + } + else if (strncmp(p, "https://", 8) == 0) + { + useSSL = true; + offs = 8; + } + else + return false; + + p = sl + 2; + } + + sl = strchr(p, '/'); + if (!sl) + { + host = p; + file = "/"; + } + else + { + host = uri.substr(offs, sl - p); + file = sl; + } + + port = -1; + size_t colon = host.find(':'); + if (colon != std::string::npos) + { + port = atoi(host.c_str() + colon); + host.erase(port); + } + + return true; + } + + void URLEncode(const std::string& s, std::string& enc) + { + const size_t len = s.length(); + char buf[3]; + buf[0] = '%'; + for (size_t i = 0; i < len; i++) + { + const unsigned char c = s[i]; + // from https://www.ietf.org/rfc/rfc1738.txt, page 3 + // with some changes for compatibility + if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == ',') + enc += (char) c; + else if (c == ' ') + enc += '+'; + else + { + unsigned nib = (c >> 4) & 0xf; + buf[1] = nib < 10 ? '0' + nib : 'a' + (nib - 10); + nib = c & 0xf; + buf[2] = nib < 10 ? '0' + nib : 'a' + (nib - 10); + enc.append(&buf[0], 3); + } + } + } + + static bool _SetNonBlocking(SOCKET s, bool nonblock) + { + if (!SOCKETVALID(s)) + return false; #ifdef MINIHTTP_USE_POLARSSL - if(nonblock) - return net_set_nonblock(s) == 0; - else - return net_set_block(s) == 0; + if(nonblock) + return net_set_nonblock(s) == 0; + else + return net_set_block(s) == 0; #elif defined(_WIN32) - ULONG tmp = !!nonblock; - if(::ioctlsocket(s, FIONBIO, &tmp) == SOCKET_ERROR) - return false; + ULONG tmp = !!nonblock; + if(::ioctlsocket(s, FIONBIO, &tmp) == SOCKET_ERROR) + return false; #else - int tmp = ::fcntl(s, F_GETFL); - if(tmp < 0) - return false; - if(::fcntl(s, F_SETFL, nonblock ? (tmp|O_NONBLOCK) : (tmp|=~O_NONBLOCK)) < 0) - return false; + int tmp = ::fcntl(s, F_GETFL); + if (tmp < 0) + return false; + if (::fcntl(s, F_SETFL, nonblock ? (tmp | O_NONBLOCK) : (tmp |= ~O_NONBLOCK)) < 0) + return false; #endif - return true; -} - -TcpSocket::TcpSocket -( -): -_inbuf(NULL), -_readptr(NULL), -_writeptr(NULL), -_inbufSize(0), -_writeSize(0), -_recvSize(0), -_lastport(0), -_nonblocking(false), -_s(INVALID_SOCKET), -_sslctx(NULL) -{ -} + return true; + } -TcpSocket::~TcpSocket -( -) -{ - close(); - if(_inbuf) - free(_inbuf); -} - -bool TcpSocket::isOpen -( -) -{ - return SOCKETVALID(_s); -} + TcpSocket::TcpSocket() : + _inbuf(NULL), _readptr(NULL), _writeptr(NULL), _inbufSize(0), _writeSize(0), _recvSize(0), _lastport(0), _nonblocking(false), _s(INVALID_SOCKET), _sslctx(NULL) + { + } -void TcpSocket::close -( -) -{ - if(!SOCKETVALID(_s)) - return; + TcpSocket::~TcpSocket() + { + close(); + if (_inbuf) + free(_inbuf); + } + + bool TcpSocket::isOpen() + { + return SOCKETVALID(_s); + } + + void TcpSocket::close() + { + if (!SOCKETVALID(_s)) + return; - traceprint("TcpSocket::close\n"); + traceprint("TcpSocket::close\n"); - _OnCloseInternal(); + _OnCloseInternal(); #ifdef MINIHTTP_USE_POLARSSL - if(_sslctx) - ((SSLCtx*)_sslctx)->reset(); - net_close(_s); - shutdownSSL(); + if(_sslctx) + ((SSLCtx*)_sslctx)->reset(); + net_close(_s); + shutdownSSL(); #else # ifdef _WIN32 - ::closesocket((SOCKET)_s); + ::closesocket((SOCKET)_s); # else - ::close(_s); + ::close(_s); # endif #endif - _s = INVALID_SOCKET; - _recvSize = 0; -} - -void TcpSocket::_OnCloseInternal -( -) -{ - _OnClose(); -} - -bool TcpSocket::SetNonBlocking -( -bool nonblock -) -{ - _nonblocking = nonblock; - return _SetNonBlocking(_s, nonblock); -} - -void TcpSocket::SetBufsizeIn -( -unsigned int s -) -{ - if(s < 512) - s = 512; - if(s != _inbufSize) - _inbuf = (char*)realloc(_inbuf, s); - _inbufSize = s; - _writeSize = s - 1; - _readptr = _writeptr = _inbuf; -} - -static bool _openSocket -( -SOCKET *ps, -const char *host, -unsigned port -) -{ + _s = INVALID_SOCKET; + _recvSize = 0; + } + + void TcpSocket::_OnCloseInternal() + { + _OnClose(); + } + + bool TcpSocket::SetNonBlocking(bool nonblock) + { + _nonblocking = nonblock; + return _SetNonBlocking(_s, nonblock); + } + + void TcpSocket::SetBufsizeIn(unsigned int s) + { + if (s < 512) + s = 512; + if (s != _inbufSize) + _inbuf = (char*) realloc(_inbuf, s); + _inbufSize = s; + _writeSize = s - 1; + _readptr = _writeptr = _inbuf; + } + + static bool _openSocket(SOCKET *ps, const char *host, unsigned port) + { #ifdef MINIHTTP_USE_POLARSSL - int s; - int err = net_connect(&s, host, port); - if(err) - { - traceprint("open_ssl: net_connect(%s, %u) returned %d\n", host, port, err); - return false; - } + int s; + int err = net_connect(&s, host, port); + if(err) + { + traceprint("open_ssl: net_connect(%s, %u) returned %d\n", host, port, err); + return false; + } #else - sockaddr_in addr; - if(!_Resolve(host, port, &addr)) - { - traceprint("RESOLV ERROR: %s\n", _GetErrorStr(_GetError()).c_str()); - return false; - } - - SOCKET s = socket(AF_INET, SOCK_STREAM, 0); - - if(!SOCKETVALID(s)) - { - traceprint("SOCKET ERROR: %s\n", _GetErrorStr(_GetError()).c_str()); - return false; - } - - if (::connect(s, (sockaddr*)&addr, sizeof(sockaddr))) - { - traceprint("CONNECT ERROR: %s\n", _GetErrorStr(_GetError()).c_str()); - return false; - } + sockaddr_in addr; + if (!_Resolve(host, port, &addr)) + { + traceprint("RESOLV ERROR: %s\n", _GetErrorStr(_GetError()).c_str()); + return false; + } + + SOCKET s = socket(AF_INET, SOCK_STREAM, 0); + + if (!SOCKETVALID(s)) + { + traceprint("SOCKET ERROR: %s\n", _GetErrorStr(_GetError()).c_str()); + return false; + } + + if (::connect(s, (sockaddr*) &addr, sizeof(sockaddr))) + { + traceprint("CONNECT ERROR: %s\n", _GetErrorStr(_GetError()).c_str()); + return false; + } #endif - *ps = s; - return true; -} + *ps = s; + return true; + } #ifdef MINIHTTP_USE_POLARSSL -void traceprint_ssl -( -void *ctx, -int level, -const char *str -) -{ - (void)ctx; - printf("ssl: [%d] %s\n", level, str); -} -static bool _openSSL -( -void *ps, -SSLCtx *ctx -) -{ - ssl_set_endpoint(&ctx->ssl, SSL_IS_CLIENT); - ssl_set_authmode(&ctx->ssl, SSL_VERIFY_OPTIONAL); - ssl_set_ca_chain(&ctx->ssl, &ctx->cacert, NULL, NULL); - - /* SSLv3 is deprecated, set minimum to TLS 1.0 */ - ssl_set_min_version(&ctx->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1); - - // The following is removed from newer polarssl versions + void traceprint_ssl + ( + void *ctx, + int level, + const char *str + ) + { + (void)ctx; + printf("ssl: [%d] %s\n", level, str); + } + static bool _openSSL + ( + void *ps, + SSLCtx *ctx + ) + { + ssl_set_endpoint(&ctx->ssl, SSL_IS_CLIENT); + ssl_set_authmode(&ctx->ssl, SSL_VERIFY_OPTIONAL); + ssl_set_ca_chain(&ctx->ssl, &ctx->cacert, NULL, NULL); + + /* SSLv3 is deprecated, set minimum to TLS 1.0 */ + ssl_set_min_version(&ctx->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1); + + // The following is removed from newer polarssl versions #ifdef SSL_ARC4_DISABLED - /* RC4 is deprecated, disable it */ - ssl_set_arc4_support(&ctx->ssl, SSL_ARC4_DISABLED ); + /* RC4 is deprecated, disable it */ + ssl_set_arc4_support(&ctx->ssl, SSL_ARC4_DISABLED ); #endif - ssl_set_rng(&ctx->ssl, ctr_drbg_random, &ctx->ctr_drbg); - ssl_set_dbg(&ctx->ssl, traceprint_ssl, NULL); - //ssl_set_ciphersuites( &ctx->ssl, ssl_default_ciphersuites); // FIXME - ssl_set_bio(&ctx->ssl, net_recv, ps, net_send, ps); - - traceprint("SSL handshake now...\n"); - int err; - while( (err = ssl_handshake(&ctx->ssl)) ) - { - if(err != POLARSSL_ERR_NET_WANT_READ && err != POLARSSL_ERR_NET_WANT_WRITE) - { - traceprint("open_ssl: ssl_handshake returned -0x%x\n\n", -err); - return false; - } - } - traceprint("SSL handshake done\n"); - return true; -} + ssl_set_rng(&ctx->ssl, ctr_drbg_random, &ctx->ctr_drbg); + ssl_set_dbg(&ctx->ssl, traceprint_ssl, NULL); + //ssl_set_ciphersuites( &ctx->ssl, ssl_default_ciphersuites); // FIXME + ssl_set_bio(&ctx->ssl, net_recv, ps, net_send, ps); + + traceprint("SSL handshake now...\n"); + int err; + while( (err = ssl_handshake(&ctx->ssl)) ) + { + if(err != POLARSSL_ERR_NET_WANT_READ && err != POLARSSL_ERR_NET_WANT_WRITE) + { + traceprint("open_ssl: ssl_handshake returned -0x%x\n\n", -err); + return false; + } + } + traceprint("SSL handshake done\n"); + return true; + } #endif -bool TcpSocket::open -( -const char *host, -unsigned int port -) -{ - if(isOpen()) - { - if( (host && host != _host) || (port && port != _lastport) ) - close(); - // ... and continue connecting to new host/port - else - return true; // still connected, to same host and port. - } - - if(host) - _host = host; - else - host = _host.c_str(); - - if(port) - _lastport = port; - else - { - port = _lastport; - if(!port) - return false; - } - - traceprint("TcpSocket::open(): host = [%s], port = %d\n", host, port); - - assert(!SOCKETVALID(_s)); - - _recvSize = 0; - - { - SOCKET s; - if(!_openSocket(&s, host, port)) - return false; - _s = s; + bool TcpSocket::open(const char *host, unsigned int port) + { + if (isOpen()) + { + if ((host && host != _host) || (port && port != _lastport)) + close(); + // ... and continue connecting to new host/port + else + return true; // still connected, to same host and port. + } + + if (host) + _host = host; + else + host = _host.c_str(); + + if (port) + _lastport = port; + else + { + port = _lastport; + if (!port) + return false; + } + + traceprint("TcpSocket::open(): host = [%s], port = %d\n", host, port); + + assert(!SOCKETVALID(_s)); + + _recvSize = 0; + + { + SOCKET s; + if (!_openSocket(&s, host, port)) + return false; + _s = s; #ifdef SO_NOSIGPIPE - // Don't fire SIGPIPE when trying to write to a closed socket - { - int set = 1; - setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int)); - } + // Don't fire SIGPIPE when trying to write to a closed socket + { + int set = 1; + setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (void *) &set, sizeof(int)); + } #endif - } + } - _SetNonBlocking(_s, _nonblocking); // restore setting if it was set in invalid state. static call because _s is intentionally still invalid here. + _SetNonBlocking(_s, _nonblocking); // restore setting if it was set in invalid state. static call because _s is intentionally still invalid here. #ifdef MINIHTTP_USE_POLARSSL - if(_sslctx) - { - traceprint("TcpSocket::open(): SSL requested...\n"); - if(!_openSSL(&_s, (SSLCtx*)_sslctx)) - { - close(); - return false; - } - } + if(_sslctx) + { + traceprint("TcpSocket::open(): SSL requested...\n"); + if(!_openSSL(&_s, (SSLCtx*)_sslctx)) + { + close(); + return false; + } + } #endif - _OnOpen(); + _OnOpen(); - return true; -} + return true; + } #ifdef MINIHTTP_USE_POLARSSL -void TcpSocket::shutdownSSL -( -) -{ - delete ((SSLCtx*)_sslctx); - _sslctx = NULL; -} - -bool TcpSocket::initSSL -( -const char *certs -) -{ - SSLCtx *ctx = (SSLCtx*)_sslctx; - if(ctx) - ctx->reset(); - else - { - ctx = new SSLCtx(); - _sslctx = ctx; - if(!ctx->init()) - { - shutdownSSL(); - return false; - } - } - - if(certs) - { - int err = x509_crt_parse(&ctx->cacert, (const unsigned char*)certs, strlen(certs)); - if(err) - { - shutdownSSL(); - traceprint("x509_crt_parse() returned %d\n", err); - return false; - } - } - - return true; -} - -SSLResult TcpSocket::verifySSL -( -) -{ - if(!_sslctx) - return SSLR_NO_SSL; - - SSLCtx *ctx = (SSLCtx*)_sslctx; - unsigned r = SSLR_OK; - int res = ssl_get_verify_result(&ctx->ssl); - if(res) - { - if(res & BADCERT_EXPIRED) - r |= SSLR_CERT_EXPIRED; - - if(res & BADCERT_REVOKED) - r |= SSLR_CERT_REVOKED; - - if(res & BADCERT_CN_MISMATCH) - r |= SSLR_CERT_CN_MISMATCH; - - if(res & BADCERT_NOT_TRUSTED) - r |= SSLR_CERT_NOT_TRUSTED; - - if(res & BADCERT_MISSING) - r |= SSLR_CERT_MISSING; - - if(res & BADCERT_SKIP_VERIFY) - r |= SSLR_CERT_SKIP_VERIFY; - - if(res & BADCERT_FUTURE) - r |= SSLR_CERT_FUTURE; - - // More than just this? - if(res & (BADCERT_SKIP_VERIFY | SSLR_CERT_NOT_TRUSTED)) - r |= SSLR_FAIL; - } - - return (SSLResult)r; -} + void TcpSocket::shutdownSSL + ( + ) + { + delete ((SSLCtx*)_sslctx); + _sslctx = NULL; + } + + bool TcpSocket::initSSL + ( + const char *certs + ) + { + SSLCtx *ctx = (SSLCtx*)_sslctx; + if(ctx) + ctx->reset(); + else + { + ctx = new SSLCtx(); + _sslctx = ctx; + if(!ctx->init()) + { + shutdownSSL(); + return false; + } + } + + if(certs) + { + int err = x509_crt_parse(&ctx->cacert, (const unsigned char*)certs, strlen(certs)); + if(err) + { + shutdownSSL(); + traceprint("x509_crt_parse() returned %d\n", err); + return false; + } + } + + return true; + } + + SSLResult TcpSocket::verifySSL + ( + ) + { + if(!_sslctx) + return SSLR_NO_SSL; + + SSLCtx *ctx = (SSLCtx*)_sslctx; + unsigned r = SSLR_OK; + int res = ssl_get_verify_result(&ctx->ssl); + if(res) + { + if(res & BADCERT_EXPIRED) + r |= SSLR_CERT_EXPIRED; + + if(res & BADCERT_REVOKED) + r |= SSLR_CERT_REVOKED; + + if(res & BADCERT_CN_MISMATCH) + r |= SSLR_CERT_CN_MISMATCH; + + if(res & BADCERT_NOT_TRUSTED) + r |= SSLR_CERT_NOT_TRUSTED; + + if(res & BADCERT_MISSING) + r |= SSLR_CERT_MISSING; + + if(res & BADCERT_SKIP_VERIFY) + r |= SSLR_CERT_SKIP_VERIFY; + + if(res & BADCERT_FUTURE) + r |= SSLR_CERT_FUTURE; + + // More than just this? + if(res & (BADCERT_SKIP_VERIFY | SSLR_CERT_NOT_TRUSTED)) + r |= SSLR_FAIL; + } + + return (SSLResult)r; + } #else // MINIHTTP_USE_POLARSSL -void TcpSocket::shutdownSSL -( -) -{ -} - -bool TcpSocket::initSSL -( -const char *certs -) -{ - traceprint("initSSL: Compiled without SSL support!"); - return false; -} - -SSLResult TcpSocket::verifySSL -( -) -{ - return SSLR_NO_SSL; -} + void TcpSocket::shutdownSSL() + { + } + + bool TcpSocket::initSSL(const char *certs) + { + traceprint("initSSL: Compiled without SSL support!"); + return false; + } + + SSLResult TcpSocket::verifySSL() + { + return SSLR_NO_SSL; + } #endif -bool TcpSocket::SendBytes -( -const void *str, -unsigned int len -) -{ - if(!len) - return true; - if(!SOCKETVALID(_s)) - return false; - //traceprint("SEND: '%s'\n", str); - - unsigned written = 0; - while(true) // FIXME: buffer bytes to an internal queue instead? - { - int ret = _writeBytes((const unsigned char*)str + written, len - written); - if(ret > 0) - { - assert((unsigned)ret <= len); - written += (unsigned)ret; - if(written >= len) - break; - } - else if(ret < 0) - { + bool TcpSocket::SendBytes(const void *str, unsigned int len) + { + if (!len) + return true; + if (!SOCKETVALID(_s)) + return false; + //traceprint("SEND: '%s'\n", str); + + unsigned written = 0; + while (true) // FIXME: buffer bytes to an internal queue instead? + { + int ret = _writeBytes((const unsigned char*) str + written, len - written); + if (ret > 0) + { + assert((unsigned )ret <= len); + written += (unsigned) ret; + if (written >= len) + break; + } + else if (ret < 0) + { #ifdef _DEBUG - int err = ret == -1 ? _GetError() : ret; - traceprint("SendBytes: error %d: %s\n", err, _GetErrorStr(err).c_str()); + int err = ret == -1 ? _GetError() : ret; + traceprint("SendBytes: error %d: %s\n", err, _GetErrorStr(err).c_str()); #endif - close(); - return false; - } - // and if ret == 0, keep trying. - } - - assert(written == len); - return true; -} - -int TcpSocket::_writeBytes -( -const unsigned char *buf, -size_t len -) -{ - int ret = 0; + close(); + return false; + } + // and if ret == 0, keep trying. + } + + assert(written == len); + return true; + } + + int TcpSocket::_writeBytes(const unsigned char *buf, size_t len) + { + int ret = 0; #ifdef MINIHTTP_USE_POLARSSL - int err; - if(_sslctx) - err = ssl_write(&((SSLCtx*)_sslctx)->ssl, buf, len); - else - err = net_send(&_s, buf, len); - - switch(err) - { - case POLARSSL_ERR_NET_WANT_WRITE: - ret = 0; // FIXME: Nothing written, try later? - default: - ret = err; - } + int err; + if(_sslctx) + err = ssl_write(&((SSLCtx*)_sslctx)->ssl, buf, len); + else + err = net_send(&_s, buf, len); + + switch(err) + { + case POLARSSL_ERR_NET_WANT_WRITE: + ret = 0; // FIXME: Nothing written, try later? + default: + ret = err; + } #else - int flags = 0; - #ifdef MSG_NOSIGNAL - flags |= MSG_NOSIGNAL; - #endif - return ::send(_s, (const char*)buf, len, flags); + int flags = 0; +#ifdef MSG_NOSIGNAL + flags |= MSG_NOSIGNAL; +#endif + return ::send(_s, (const char*) buf, len, flags); #endif - return ret; -} - -void TcpSocket::_ShiftBuffer -( -) -{ - size_t by = _readptr - _inbuf; - memmove(_inbuf, _readptr, by); - _readptr = _inbuf; - _writeptr = _inbuf + by; - _writeSize = _inbufSize - by - 1; -} - -void TcpSocket::_OnData -( -) -{ - _OnRecv(_readptr, _recvSize); -} - -int TcpSocket::_readBytes -( -unsigned char *buf, -size_t maxlen -) -{ + return ret; + } + + void TcpSocket::_ShiftBuffer() + { + size_t by = _readptr - _inbuf; + memmove(_inbuf, _readptr, by); + _readptr = _inbuf; + _writeptr = _inbuf + by; + _writeSize = _inbufSize - by - 1; + } + + void TcpSocket::_OnData() + { + _OnRecv(_readptr, _recvSize); + } + + int TcpSocket::_readBytes(unsigned char *buf, size_t maxlen) + { #ifdef MINIHTTP_USE_POLARSSL - if(_sslctx) - return ssl_read(&((SSLCtx*)_sslctx)->ssl, buf, maxlen); - else - return net_recv(&_s, buf, maxlen); + if(_sslctx) + return ssl_read(&((SSLCtx*)_sslctx)->ssl, buf, maxlen); + else + return net_recv(&_s, buf, maxlen); #else - return recv(_s, (char*)buf, maxlen, 0); // last char is used as string terminator + return recv(_s, (char*) buf, maxlen, 0); // last char is used as string terminator #endif -} - -bool TcpSocket::update -( -) -{ - if(!_OnUpdate()) - return false; - - if(!isOpen()) - return false; - - if(!_inbuf) - SetBufsizeIn(DEFAULT_BUFSIZE); - - int bytes = _readBytes((unsigned char*)_writeptr, _writeSize); - //traceprint("TcpSocket::update: _readBytes() result %d\n", bytes); - if(bytes > 0) // we received something - { - _inbuf[bytes] = 0; - _recvSize = bytes; - - // reset pointers for next read - _writeSize = _inbufSize - 1; - _readptr = _writeptr = _inbuf; - - _OnData(); - } - else if(bytes == 0) // remote has closed the connection - { - close(); - } - else // whoops, error? - { - // Possible that the error is returned directly (in that case, < -1, or -1 is returned and the error has to be retrieved seperately. - // But in the latter case, error numbers may be positive (at least on windows...) - int err = bytes == -1 ? _GetError() : bytes; - switch(err) - { - case EWOULDBLOCK: + } + + bool TcpSocket::update() + { + if (!_OnUpdate()) + return false; + + if (!isOpen()) + return false; + + if (!_inbuf) + SetBufsizeIn(DEFAULT_BUFSIZE); + + int bytes = _readBytes((unsigned char*) _writeptr, _writeSize); + //traceprint("TcpSocket::update: _readBytes() result %d\n", bytes); + if (bytes > 0) // we received something + { + _inbuf[bytes] = 0; + _recvSize = bytes; + + // reset pointers for next read + _writeSize = _inbufSize - 1; + _readptr = _writeptr = _inbuf; + + _OnData(); + } + else if (bytes == 0) // remote has closed the connection + { + close(); + } + else // whoops, error? + { + // Possible that the error is returned directly (in that case, < -1, or -1 is returned and the error has to be retrieved seperately. + // But in the latter case, error numbers may be positive (at least on windows...) + int err = bytes == -1 ? _GetError() : bytes; + switch (err) + { + case EWOULDBLOCK: #if defined(EAGAIN) && (EWOULDBLOCK != EAGAIN) - case EAGAIN: // linux man pages say this can also happen instead of EWOULDBLOCK + case EAGAIN: // linux man pages say this can also happen instead of EWOULDBLOCK #endif - return false; + return false; #ifdef MINIHTTP_USE_POLARSSL - case POLARSSL_ERR_NET_WANT_READ: - break; // Try again later + case POLARSSL_ERR_NET_WANT_READ: + break; // Try again later #endif - default: - traceprint("SOCKET UPDATE ERROR: (%d): %s\n", err, _GetErrorStr(err).c_str()); - case ECONNRESET: - case ENOTCONN: - case ETIMEDOUT: + default: + traceprint("SOCKET UPDATE ERROR: (%d): %s\n", err, _GetErrorStr(err).c_str()) + ; + case ECONNRESET: + case ENOTCONN: + case ETIMEDOUT: #ifdef _WIN32 - case WSAECONNABORTED: - case WSAESHUTDOWN: + case WSAECONNABORTED: + case WSAESHUTDOWN: #endif - close(); - break; - } - } - return true; -} - + close(); + break; + } + } + return true; + } // ========================== // ===== HTTP SPECIFIC ====== // ========================== #ifdef MINIHTTP_SUPPORT_HTTP - -POST& POST::add -( -const char *key, -const char *value -) -{ - if(!empty()) - data += '&'; - URLEncode(key, data); - data += '='; - URLEncode(value, data); - return *this; -} - - -HttpSocket::HttpSocket -( -): -TcpSocket(), -_user_agent("OpenZWave"), -_accept_encoding(), -_tmpHdr(), -_keep_alive(0), -_remaining(0), -_contentLen(0), -_status(0), -_inProgress(false), -_chunkedTransfer(false), -_mustClose(true), -_followRedir(true), -_alwaysHandle(false), -_filename(), -_pFile(NULL) -{ -} - -HttpSocket::~HttpSocket -( -) -{ -} - -void HttpSocket::_OnOpen -( -) -{ - TcpSocket::_OnOpen(); - _chunkedTransfer = false; - _mustClose = true; -} - -void HttpSocket::_OnCloseInternal -( -) -{ - if(!IsRedirecting() || _alwaysHandle) - _OnClose(); -} - -bool HttpSocket::_OnUpdate -( -) -{ - if(!TcpSocket::_OnUpdate()) - return false; - - if(_inProgress && !_chunkedTransfer && !_remaining && _status) - _FinishRequest(); - - //traceprint("HttpSocket::_OnUpdate, Q = %d\n", (unsigned)_requestQ.size()); - - // initiate transfer if queue is not empty, but the socket somehow forgot to proceed - if(_requestQ.size() && !_remaining && !_chunkedTransfer && !_inProgress) - _DequeueMore(); - - return true; -} - -bool HttpSocket::Download -( -const std::string& url, -const char *extraRequest, -void *user, -const POST *post -) -{ - if (_filename.length() == 0) { - traceprint("No Filename Set\n"); - return false; - } - Request req; - req.user = user; - if(post) - req.post = *post; - SplitURI(url, req.protocol, req.host, req.resource, req.port, req.useSSL); - if(IsRedirecting() && req.host.empty()) // if we're following a redirection to the same host, the server is likely to omit its hostname - req.host = _curRequest.host; - if(req.port < 0) - req.port = req.useSSL ? 443 : 80; - if(extraRequest) - req.extraGetHeaders = extraRequest; - return SendRequest(req, false); -} - - -bool HttpSocket::_Redirect -( -std::string loc, -bool forceGET -) -{ - traceprint("Following HTTP redirect to: %s\n", loc.c_str()); - if(loc.empty()) - return false; - - Request req; - req.user = _curRequest.user; - req.useSSL = _curRequest.useSSL; - if(!forceGET) - req.post = _curRequest.post; - SplitURI(loc, req.protocol, req.host, req.resource, req.port, req.useSSL); - if(req.protocol.empty()) // assume local resource - { - req.host = _curRequest.host; - req.resource = loc; - } - if(req.host.empty()) - req.host = _curRequest.host; - if(req.port < 0) - req.port = _curRequest.port; - req.extraGetHeaders = _curRequest.extraGetHeaders; - return SendRequest(req, false); -} - -bool HttpSocket::SendRequest -( -const std::string what, -const char *extraRequest, -void *user -) -{ - Request req(what, _host, _lastport, user); - if(extraRequest) - req.extraGetHeaders = extraRequest; - return SendRequest(req, false); -} - -bool HttpSocket::QueueRequest -( -const std::string what, -const char *extraRequest, -void *user -) -{ - Request req(what, _host, _lastport, user); - if(extraRequest) - req.extraGetHeaders = extraRequest; - return SendRequest(req, true); -} - -bool HttpSocket::SendRequest -( -Request& req, -bool enqueue -) -{ - if(req.host.empty() || !req.port) - return false; - - const bool post = !req.post.empty(); - - std::stringstream r; - const char *crlf = "\r\n"; - r << (post ? "POST " : "GET ") << req.resource << " HTTP/1.1" << crlf; - r << "Host: " << req.host << crlf; - if(_keep_alive) - { - r << "Connection: Keep-Alive" << crlf; - r << "Keep-Alive: " << _keep_alive << crlf; - } - else - r << "Connection: close" << crlf; - - if(_user_agent.length()) - r << "User-Agent: " << _user_agent << crlf; - - if(_accept_encoding.length()) - r << "Accept-Encoding: " << _accept_encoding << crlf; - - if(post) - { - r << "Content-Length: " << req.post.length() << crlf; - r << "Content-Type: application/x-www-form-urlencoded" << crlf; - } - - if(req.extraGetHeaders.length()) - { - r << req.extraGetHeaders; - if(req.extraGetHeaders.compare(req.extraGetHeaders.length() - 2, std::string::npos, crlf)) - r << crlf; - } - - r << crlf; // header terminator - - // FIXME: appending this to the 'header' field is probably not a good idea - if(post) - r << req.post.str(); - - req.header = r.str(); - - return _EnqueueOrSend(req, enqueue); -} - -bool HttpSocket::_EnqueueOrSend -( -const Request& req, -bool forceQueue -) -{ - traceprint("HttpSocket::_EnqueueOrSend, forceQueue = %d\n", forceQueue); - if(_inProgress || forceQueue) // do not send while receiving other data - { - traceprint("HTTP: Transfer pending; putting into queue. Now %u waiting.\n", (unsigned int)_requestQ.size()); - _requestQ.push(req); - return true; - } - // ok, we can send directly - traceprint("HTTP: Open request for immediate send.\n"); - if(!_OpenRequest(req)) - return false; - bool sent = SendBytes(req.header.c_str(), req.header.length()); - _inProgress = sent; - return sent; -} + POST& POST::add(const char *key, const char *value) + { + if (!empty()) + data += '&'; + URLEncode(key, data); + data += '='; + URLEncode(value, data); + return *this; + } + + HttpSocket::HttpSocket() : + TcpSocket(), _user_agent("OpenZWave"), _accept_encoding(), _tmpHdr(), _keep_alive(0), _remaining(0), _contentLen(0), _status(0), _inProgress(false), _chunkedTransfer(false), _mustClose(true), _followRedir(true), _alwaysHandle(false), _filename(), _pFile(NULL) + { + } + + HttpSocket::~HttpSocket() + { + } + + void HttpSocket::_OnOpen() + { + TcpSocket::_OnOpen(); + _chunkedTransfer = false; + _mustClose = true; + } + + void HttpSocket::_OnCloseInternal() + { + if (!IsRedirecting() || _alwaysHandle) + _OnClose(); + } + + bool HttpSocket::_OnUpdate() + { + if (!TcpSocket::_OnUpdate()) + return false; + + if (_inProgress && !_chunkedTransfer && !_remaining && _status) + _FinishRequest(); + + //traceprint("HttpSocket::_OnUpdate, Q = %d\n", (unsigned)_requestQ.size()); + + // initiate transfer if queue is not empty, but the socket somehow forgot to proceed + if (_requestQ.size() && !_remaining && !_chunkedTransfer && !_inProgress) + _DequeueMore(); + + return true; + } + + bool HttpSocket::Download(const std::string& url, const char *extraRequest, void *user, const POST *post) + { + if (_filename.length() == 0) + { + traceprint("No Filename Set\n"); + return false; + } + Request req; + req.user = user; + if (post) + req.post = *post; + SplitURI(url, req.protocol, req.host, req.resource, req.port, req.useSSL); + if (IsRedirecting() && req.host.empty()) // if we're following a redirection to the same host, the server is likely to omit its hostname + req.host = _curRequest.host; + if (req.port < 0) + req.port = req.useSSL ? 443 : 80; + if (extraRequest) + req.extraGetHeaders = extraRequest; + return SendRequest(req, false); + } + + bool HttpSocket::_Redirect(std::string loc, bool forceGET) + { + traceprint("Following HTTP redirect to: %s\n", loc.c_str()); + if (loc.empty()) + return false; + + Request req; + req.user = _curRequest.user; + req.useSSL = _curRequest.useSSL; + if (!forceGET) + req.post = _curRequest.post; + SplitURI(loc, req.protocol, req.host, req.resource, req.port, req.useSSL); + if (req.protocol.empty()) // assume local resource + { + req.host = _curRequest.host; + req.resource = loc; + } + if (req.host.empty()) + req.host = _curRequest.host; + if (req.port < 0) + req.port = _curRequest.port; + req.extraGetHeaders = _curRequest.extraGetHeaders; + return SendRequest(req, false); + } + + bool HttpSocket::SendRequest(const std::string what, const char *extraRequest, void *user) + { + Request req(what, _host, _lastport, user); + if (extraRequest) + req.extraGetHeaders = extraRequest; + return SendRequest(req, false); + } + + bool HttpSocket::QueueRequest(const std::string what, const char *extraRequest, void *user) + { + Request req(what, _host, _lastport, user); + if (extraRequest) + req.extraGetHeaders = extraRequest; + return SendRequest(req, true); + } + + bool HttpSocket::SendRequest(Request& req, bool enqueue) + { + if (req.host.empty() || !req.port) + return false; + + const bool post = !req.post.empty(); + + std::stringstream r; + const char *crlf = "\r\n"; + r << (post ? "POST " : "GET ") << req.resource << " HTTP/1.1" << crlf; + r << "Host: " << req.host << crlf; + if (_keep_alive) + { + r << "Connection: Keep-Alive" << crlf; + r << "Keep-Alive: " << _keep_alive << crlf; + } + else + r << "Connection: close" << crlf; + + if (_user_agent.length()) + r << "User-Agent: " << _user_agent << crlf; + + if (_accept_encoding.length()) + r << "Accept-Encoding: " << _accept_encoding << crlf; + + if (post) + { + r << "Content-Length: " << req.post.length() << crlf; + r << "Content-Type: application/x-www-form-urlencoded" << crlf; + } + + if (req.extraGetHeaders.length()) + { + r << req.extraGetHeaders; + if (req.extraGetHeaders.compare(req.extraGetHeaders.length() - 2, std::string::npos, crlf)) + r << crlf; + } + + r << crlf; // header terminator + + // FIXME: appending this to the 'header' field is probably not a good idea + if (post) + r << req.post.str(); + + req.header = r.str(); + + return _EnqueueOrSend(req, enqueue); + } + + bool HttpSocket::_EnqueueOrSend(const Request& req, bool forceQueue) + { + traceprint("HttpSocket::_EnqueueOrSend, forceQueue = %d\n", forceQueue); + if (_inProgress || forceQueue) // do not send while receiving other data + { + traceprint("HTTP: Transfer pending; putting into queue. Now %u waiting.\n", (unsigned int)_requestQ.size()); + _requestQ.push(req); + return true; + } + // ok, we can send directly + traceprint("HTTP: Open request for immediate send.\n"); + if (!_OpenRequest(req)) + return false; + bool sent = SendBytes(req.header.c_str(), req.header.length()); + _inProgress = sent; + return sent; + } // called whenever a request is finished completely and the socket checks for more things to send -void HttpSocket::_DequeueMore -( -) -{ - traceprint("HttpSocket::_DequeueMore, Q = %u\n", (unsigned)_requestQ.size()); - _FinishRequest(); // In case this was not done yet. - - // _inProgress is known to be false here - if(_requestQ.size()) // still have other requests queued? - if(_EnqueueOrSend(_requestQ.front(), false)) // could we send? - _requestQ.pop(); // if so, we are done with this request - - // otherwise, we are done for now. socket is kept alive for future sends. Nothing to do. -} - -bool HttpSocket::_OpenRequest -( -const Request& req -) -{ - if(_inProgress) - { - traceprint("HttpSocket::_OpenRequest(): _inProgress == true, should not be called."); - return false; - } - if(req.useSSL && !hasSSL()) - { - traceprint("HttpSocket::_OpenRequest(): Is an SSL connection, but SSL was not inited, doing that now\n"); - if(!initSSL(NULL)) // FIXME: supply cert list? - { - traceprint("FAILED to init SSL"); - return false; - } - } - if(!open(req.host.c_str(), req.port)) - return false; - _inProgress = true; - _curRequest = req; - _status = 0; - return true; -} - -void HttpSocket::_FinishRequest -( -) -{ - traceprint("HttpSocket::_FinishRequest\n"); - if(_inProgress) - { - traceprint("... in progress. redirecting = %d\n", IsRedirecting()); - if(!IsRedirecting() || _alwaysHandle) - _OnRequestDone(); // notify about finished request - _inProgress = false; - _hdrs.clear(); - if(_mustClose) - close(); - } -} - -void HttpSocket::_ProcessChunk -( -) -{ - if(!_chunkedTransfer) - return; - - unsigned int chunksize = -1; - - while(true) - { - // less data required until chunk end than received, means the new chunk starts somewhere in the middle - // of the received data block. finish this chunk first. - if(_remaining) - { - if(_remaining <= _recvSize) // it contains the rest of the chunk, including CRLF - { - _OnRecvInternal(_readptr, _remaining - 2); // implicitly skip CRLF - _readptr += _remaining; - _recvSize -= _remaining; - _remaining = 0; // done with this one. - if(!chunksize) // and if chunksize was 0, we are done with all chunks. - break; - } - else // buffer did not yet arrive completely - { - _OnRecvInternal(_readptr, _recvSize); - _remaining -= _recvSize; - _recvSize = 0; // done with the whole buffer, but not with the chunk - return; // nothing else to do here - } - } - - // each chunk identifier ends with CRLF. - // if we don't find that, we hit the corner case that the chunk identifier was not fully received. - // in that case, adjust the buffer and wait for the rest of the data to be appended - char *term = strstr(_readptr, "\r\n"); - if(!term) - { - if(_recvSize) // if there is still something queued, move it to the left of the buffer and append on next read - _ShiftBuffer(); - return; - } - term += 2; // skip CRLF - - // when we are here, the (next) chunk header was completely received. - chunksize = strtoul(_readptr, NULL, 16); - _remaining = chunksize + 2; // the http protocol specifies that each chunk has a trailing CRLF - _recvSize -= (term - _readptr); - _readptr = term; - } - - if(!chunksize) // this was the last chunk, no further data expected unless requested - { - _chunkedTransfer = false; - _DequeueMore(); - if(_recvSize) - traceprint("_ProcessChunk: There are %u bytes left in the buffer, huh?\n", _recvSize); - if(_mustClose) - close(); - } -} - -void HttpSocket::_ParseHeaderFields -( -const char *s, -size_t size -) -{ - // Key: Value data\r\n - - const char * const maxs = s + size; - while(s < maxs) - { - while(isspace(*s)) - { - ++s; - if(s >= maxs) - return; - } - const char * const colon = strchr(s, ':'); - if(!colon) - return; - const char *valEnd = strchr(colon, '\n'); // last char of val data - if(!valEnd) - return; - while(valEnd[-1] == '\n' || valEnd[-1] == '\r') // skip backwards if necessary - --valEnd; - const char *val = colon + 1; // value starts after ':' ... - while(isspace(*val) && val < valEnd) // skip spaces after the colon - ++val; - std::string key(s, colon - s); - key = ToLower(key); - std::string valstr(val, valEnd - val); - _hdrs[key] = valstr; - traceprint("HDR: %s: %s\n", key.c_str(), valstr.c_str()); - s = valEnd; - } -} - -const char *HttpSocket::Hdr -( -const char *h -) const -{ - std::map::const_iterator it = _hdrs.find(h); - return it == _hdrs.end() ? NULL : it->second.c_str(); -} - -static int safeatoi -( -const char *s -) -{ - return s ? atoi(s) : 0; -} - -bool HttpSocket::_HandleStatus -( -) -{ - _remaining = _contentLen = safeatoi(Hdr("content-length")); - - const char *encoding = Hdr("transfer-encoding"); - _chunkedTransfer = encoding && !STRNICMP(encoding, "chunked", 7); - - const char *conn = Hdr("connection"); // if its not keep-alive, server will close it, so we can too - _mustClose = !conn || STRNICMP(conn, "keep-alive", 10); - - const bool success = IsSuccess(); - - if(!(_chunkedTransfer || _contentLen) && success) - traceprint("_ParseHeader: Not chunked transfer and content-length==0, this will go fail"); - - traceprint("Got HTTP Status %d\n", _status); - - if(success) - return true; - - bool forceGET = false; - switch(_status) - { - case 303: - forceGET = true; // As per spec, continue with a GET request - case 301: - case 302: - case 307: - case 308: - if(_followRedir) - if(const char *loc = Hdr("location")) - _Redirect(loc, forceGET); - return false; - - default: - return false; - } -} - -bool HttpSocket::IsRedirecting -( -) -const -{ - switch(_status) - { - case 301: - case 302: - case 303: - case 307: - case 308: - return true; - } - return false; -} - -bool HttpSocket::IsSuccess -( -) const -{ - const unsigned s = _status; - return s >= 200 && s <= 205; -} - - - -void HttpSocket::_ParseHeader -( -) -{ - _tmpHdr += _inbuf; - const char *hptr = _tmpHdr.c_str(); - - if((_recvSize >= 5 || _tmpHdr.size() >= 5) && memcmp("HTTP/", hptr, 5)) - { - traceprint("_ParseHeader: not HTTP stream\n"); - return; - } - - const char *hdrend = strstr(hptr, "\r\n\r\n"); - if(!hdrend) - { - traceprint("_ParseHeader: could not find end-of-header marker, or incomplete buf; delaying.\n"); - return; - } - - //traceprint(hptr); - - hptr = strchr(hptr + 5, ' '); // skip "HTTP/", already known - if(!hptr) - return; // WTF? - ++hptr; // number behind first space is the status code - _status = atoi(hptr); - - // Default values - _chunkedTransfer = false; - _contentLen = 0; // yet unknown - - hptr = strstr(hptr, "\r\n"); - _ParseHeaderFields(hptr + 2, hdrend - hptr); - - // FIXME: return value indicates success. - // Bail out on non-success, or at least make it so that _OnRecv() is not called. - // (Unless an override bool is given that even non-successful answers get their data delivered!) - _HandleStatus(); - - // get ready - _readptr = strstr(_inbuf, "\r\n\r\n") + 4; // skip double newline. must have been found in hptr earlier. - _recvSize -= (_readptr - _inbuf); // skip the header part - _tmpHdr.clear(); -} + void HttpSocket::_DequeueMore() + { + traceprint("HttpSocket::_DequeueMore, Q = %u\n", (unsigned)_requestQ.size()); + _FinishRequest(); // In case this was not done yet. + + // _inProgress is known to be false here + if (_requestQ.size()) // still have other requests queued? + if (_EnqueueOrSend(_requestQ.front(), false)) // could we send? + _requestQ.pop(); // if so, we are done with this request + + // otherwise, we are done for now. socket is kept alive for future sends. Nothing to do. + } + + bool HttpSocket::_OpenRequest(const Request& req) + { + if (_inProgress) + { + traceprint("HttpSocket::_OpenRequest(): _inProgress == true, should not be called."); + return false; + } + if (req.useSSL && !hasSSL()) + { + traceprint("HttpSocket::_OpenRequest(): Is an SSL connection, but SSL was not inited, doing that now\n"); + if (!initSSL(NULL)) // FIXME: supply cert list? + { + traceprint("FAILED to init SSL"); + return false; + } + } + if (!open(req.host.c_str(), req.port)) + return false; + _inProgress = true; + _curRequest = req; + _status = 0; + return true; + } + + void HttpSocket::_FinishRequest() + { + traceprint("HttpSocket::_FinishRequest\n"); + if (_inProgress) + { + traceprint("... in progress. redirecting = %d\n", IsRedirecting()); + if (!IsRedirecting() || _alwaysHandle) + _OnRequestDone(); // notify about finished request + _inProgress = false; + _hdrs.clear(); + if (_mustClose) + close(); + } + } + + void HttpSocket::_ProcessChunk() + { + if (!_chunkedTransfer) + return; + + unsigned int chunksize = -1; + + while (true) + { + // less data required until chunk end than received, means the new chunk starts somewhere in the middle + // of the received data block. finish this chunk first. + if (_remaining) + { + if (_remaining <= _recvSize) // it contains the rest of the chunk, including CRLF + { + _OnRecvInternal(_readptr, _remaining - 2); // implicitly skip CRLF + _readptr += _remaining; + _recvSize -= _remaining; + _remaining = 0; // done with this one. + if (!chunksize) // and if chunksize was 0, we are done with all chunks. + break; + } + else // buffer did not yet arrive completely + { + _OnRecvInternal(_readptr, _recvSize); + _remaining -= _recvSize; + _recvSize = 0; // done with the whole buffer, but not with the chunk + return; // nothing else to do here + } + } + + // each chunk identifier ends with CRLF. + // if we don't find that, we hit the corner case that the chunk identifier was not fully received. + // in that case, adjust the buffer and wait for the rest of the data to be appended + char *term = strstr(_readptr, "\r\n"); + if (!term) + { + if (_recvSize) // if there is still something queued, move it to the left of the buffer and append on next read + _ShiftBuffer(); + return; + } + term += 2; // skip CRLF + + // when we are here, the (next) chunk header was completely received. + chunksize = strtoul(_readptr, NULL, 16); + _remaining = chunksize + 2; // the http protocol specifies that each chunk has a trailing CRLF + _recvSize -= (term - _readptr); + _readptr = term; + } + + if (!chunksize) // this was the last chunk, no further data expected unless requested + { + _chunkedTransfer = false; + _DequeueMore(); + if (_recvSize) + traceprint("_ProcessChunk: There are %u bytes left in the buffer, huh?\n", _recvSize); + if (_mustClose) + close(); + } + } + + void HttpSocket::_ParseHeaderFields(const char *s, size_t size) + { + // Key: Value data\r\n + + const char * const maxs = s + size; + while (s < maxs) + { + while (isspace(*s)) + { + ++s; + if (s >= maxs) + return; + } + const char * const colon = strchr(s, ':'); + if (!colon) + return; + const char *valEnd = strchr(colon, '\n'); // last char of val data + if (!valEnd) + return; + while (valEnd[-1] == '\n' || valEnd[-1] == '\r') // skip backwards if necessary + --valEnd; + const char *val = colon + 1; // value starts after ':' ... + while (isspace(*val) && val < valEnd) // skip spaces after the colon + ++val; + std::string key(s, colon - s); + key = ToLower(key); + std::string valstr(val, valEnd - val); + _hdrs[key] = valstr; + traceprint("HDR: %s: %s\n", key.c_str(), valstr.c_str()); + s = valEnd; + } + } + + const char *HttpSocket::Hdr(const char *h) const + { + std::map::const_iterator it = _hdrs.find(h); + return it == _hdrs.end() ? NULL : it->second.c_str(); + } + + static int safeatoi(const char *s) + { + return s ? atoi(s) : 0; + } + + bool HttpSocket::_HandleStatus() + { + _remaining = _contentLen = safeatoi(Hdr("content-length")); + + const char *encoding = Hdr("transfer-encoding"); + _chunkedTransfer = encoding && !STRNICMP(encoding, "chunked", 7); + + const char *conn = Hdr("connection"); // if its not keep-alive, server will close it, so we can too + _mustClose = !conn || STRNICMP(conn, "keep-alive", 10); + + const bool success = IsSuccess(); + + if (!(_chunkedTransfer || _contentLen) && success) + traceprint("_ParseHeader: Not chunked transfer and content-length==0, this will go fail"); + + traceprint("Got HTTP Status %d\n", _status); + + if (success) + return true; + + bool forceGET = false; + switch (_status) + { + case 303: + forceGET = true; // As per spec, continue with a GET request + case 301: + case 302: + case 307: + case 308: + if (_followRedir) + if (const char *loc = Hdr("location")) + _Redirect(loc, forceGET); + return false; + + default: + return false; + } + } + + bool HttpSocket::IsRedirecting() const + { + switch (_status) + { + case 301: + case 302: + case 303: + case 307: + case 308: + return true; + } + return false; + } + + bool HttpSocket::IsSuccess() const + { + const unsigned s = _status; + return s >= 200 && s <= 205; + } + + void HttpSocket::_ParseHeader() + { + _tmpHdr += _inbuf; + const char *hptr = _tmpHdr.c_str(); + + if ((_recvSize >= 5 || _tmpHdr.size() >= 5) && memcmp("HTTP/", hptr, 5)) + { + traceprint("_ParseHeader: not HTTP stream\n"); + return; + } + + const char *hdrend = strstr(hptr, "\r\n\r\n"); + if (!hdrend) + { + traceprint("_ParseHeader: could not find end-of-header marker, or incomplete buf; delaying.\n"); + return; + } + + //traceprint(hptr); + + hptr = strchr(hptr + 5, ' '); // skip "HTTP/", already known + if (!hptr) + return; // WTF? + ++hptr; // number behind first space is the status code + _status = atoi(hptr); + + // Default values + _chunkedTransfer = false; + _contentLen = 0; // yet unknown + + hptr = strstr(hptr, "\r\n"); + _ParseHeaderFields(hptr + 2, hdrend - hptr); + + // FIXME: return value indicates success. + // Bail out on non-success, or at least make it so that _OnRecv() is not called. + // (Unless an override bool is given that even non-successful answers get their data delivered!) + _HandleStatus(); + + // get ready + _readptr = strstr(_inbuf, "\r\n\r\n") + 4; // skip double newline. must have been found in hptr earlier. + _recvSize -= (_readptr - _inbuf); // skip the header part + _tmpHdr.clear(); + } // generic http header parsing -void HttpSocket::_OnData -( -) -{ - if(!(_chunkedTransfer || (_remaining && _recvSize))) - _ParseHeader(); - - if(_chunkedTransfer) - { - _ProcessChunk(); // first, try to finish one or more chunks - } - else if(_remaining && _recvSize) // something remaining? if so, we got a header earlier, but not all data - { - _remaining -= _recvSize; - _OnRecvInternal(_readptr, _recvSize); - - if(int(_remaining) < 0) - { - traceprint("_OnRecv: _remaining wrap-around, huh??\n"); - _remaining = 0; - } - if(!_remaining) // received last block? - { - if(_mustClose) - close(); - else - _DequeueMore(); - } - - // nothing else to do here. - } - - // otherwise, the server sent just the header, with the data following in the next packet -} - -void HttpSocket::_OnRecv(void *buf, unsigned int size) - { - if(!size) - return; - - if (!_pFile) { - _pFile = fopen( _filename.c_str(), "w" ); - } - if (!_pFile) { - Log::Write(LogLevel_Error, "Failed to open file %s: %s", _filename.c_str(), strerror(errno)); - return; - } - - fwrite(buf, size, 1, _pFile ); - } - - -void HttpSocket::_OnClose -( -) -{ - if(!ExpectMoreData()) - _FinishRequest(); - if (_pFile) { - fclose(_pFile); - _pFile = NULL; - } -} - -void HttpSocket::_OnRecvInternal -( -void *buf, -unsigned int size -) -{ - if(IsSuccess() || _alwaysHandle) - _OnRecv(buf, size); -} + void HttpSocket::_OnData() + { + if (!(_chunkedTransfer || (_remaining && _recvSize))) + _ParseHeader(); + + if (_chunkedTransfer) + { + _ProcessChunk(); // first, try to finish one or more chunks + } + else if (_remaining && _recvSize) // something remaining? if so, we got a header earlier, but not all data + { + _remaining -= _recvSize; + _OnRecvInternal(_readptr, _recvSize); + + if (int(_remaining) < 0) + { + traceprint("_OnRecv: _remaining wrap-around, huh??\n"); + _remaining = 0; + } + if (!_remaining) // received last block? + { + if (_mustClose) + close(); + else + _DequeueMore(); + } + + // nothing else to do here. + } + + // otherwise, the server sent just the header, with the data following in the next packet + } + + void HttpSocket::_OnRecv(void *buf, unsigned int size) + { + if (!size) + return; + + if (!_pFile) + { + _pFile = fopen(_filename.c_str(), "w"); + } + if (!_pFile) + { + Log::Write(LogLevel_Error, "Failed to open file %s: %s", _filename.c_str(), strerror(errno)); + return; + } + + fwrite(buf, size, 1, _pFile); + } + + void HttpSocket::_OnClose() + { + if (!ExpectMoreData()) + _FinishRequest(); + if (_pFile) + { + fclose(_pFile); + _pFile = NULL; + } + } + + void HttpSocket::_OnRecvInternal(void *buf, unsigned int size) + { + if (IsSuccess() || _alwaysHandle) + _OnRecv(buf, size); + } #endif @@ -1528,66 +1343,53 @@ unsigned int size // =========================== #ifdef MINIHTTP_SUPPORT_SOCKET_SET -SocketSet::~SocketSet -( -) -{ - deleteAll(); -} - -void SocketSet::deleteAll -( -) -{ - for(Store::iterator it = _store.begin(); it != _store.end(); ++it) - delete it->first; - _store.clear(); -} - -bool SocketSet::update -( -) -{ - bool interesting = false; - Store::iterator it = _store.begin(); - for( ; it != _store.end(); ) - { - TcpSocket *sock = it->first; - SocketSetData& sdata = it->second; - interesting = sock->update() || interesting; - if(sdata.deleteWhenDone && !sock->isOpen() && !sock->HasPendingTask()) - { - traceprint("Delete socket\n"); - delete sock; - _store.erase(it++); - } - else - ++it; - } - return interesting; -} - -void SocketSet::remove -( -TcpSocket *s -) -{ - _store.erase(s); -} - -void SocketSet::add -( -TcpSocket *s, -bool deleteWhenDone -) -{ - s->SetNonBlocking(true); - SocketSetData sdata; - sdata.deleteWhenDone = deleteWhenDone; - _store[s] = sdata; -} + SocketSet::~SocketSet() + { + deleteAll(); + } + + void SocketSet::deleteAll() + { + for (Store::iterator it = _store.begin(); it != _store.end(); ++it) + delete it->first; + _store.clear(); + } + + bool SocketSet::update() + { + bool interesting = false; + Store::iterator it = _store.begin(); + for (; it != _store.end();) + { + TcpSocket *sock = it->first; + SocketSetData& sdata = it->second; + interesting = sock->update() || interesting; + if (sdata.deleteWhenDone && !sock->isOpen() && !sock->HasPendingTask()) + { + traceprint("Delete socket\n"); + delete sock; + _store.erase(it++); + } + else + ++it; + } + return interesting; + } + + void SocketSet::remove(TcpSocket *s) + { + _store.erase(s); + } + + void SocketSet::add(TcpSocket *s, bool deleteWhenDone) + { + s->SetNonBlocking(true); + SocketSetData sdata; + sdata.deleteWhenDone = deleteWhenDone; + _store[s] = sdata; + } #endif - -} // namespace HttpClient + } // namespace Platform + } // namespace Internal } // namespace OpenZWave diff --git a/cpp/src/platform/HttpClient.h b/cpp/src/platform/HttpClient.h index 4c667c73d4..005eabd24b 100644 --- a/cpp/src/platform/HttpClient.h +++ b/cpp/src/platform/HttpClient.h @@ -28,10 +28,10 @@ // Original License Text: /* This program is free software. It comes without any warranty, to -* the extent permitted by applicable law. You can redistribute it -* and/or modify it under the terms of the Do What The Fuck You Want -* To Public License, Version 2, as published by Sam Hocevar. -* See http://sam.zoy.org/wtfpl/COPYING for more details. */ + * the extent permitted by applicable law. You can redistribute it + * and/or modify it under the terms of the Do What The Fuck You Want + * To Public License, Version 2, as published by Sam Hocevar. + * See http://sam.zoy.org/wtfpl/COPYING for more details. */ #ifndef MINIHTTPSOCKET_H #define MINIHTTPSOCKET_H @@ -47,297 +47,374 @@ #include #include - namespace OpenZWave { -/** \defgroup SimpleHttpClient Basic HTTP(s) Client - * - * a Basic HTTP Client for talking to webservers - */ - -namespace SimpleHTTPClient -{ - -/** \brief Initialize the Network for HTTP requests - * \ingroup SimpleHttpClient - * - * Initializes the Network for HTTP requests - * - * \returns success/failure - */ -bool InitNetwork(); - -/** \brief Stop the Network for HTTP requests - * \ingroup SimpleHttpClient - * - * Stops the Network for HTTP requests and releases resources associated with it - */ -void StopNetwork(); - -/** \brief Indicates if we support HTTPS requests - * \ingroup SimpleHttpClient - * - * Indicates if we support HTTPS requests - * - * \returns success/failure - * \todo SSL is not actually implemented yet. - */ -bool HasSSL(); - -/** \brief Split a URL into its different parts/ports etc - * \ingroup SimpleHttpClient - * - * Split a URL Into the different parts/ports - * - * \param uri the URL to parse - * \param host the Hostname of the URL - * \param file the directory/file name of the URL - * \param port the port number of the URL, or 80 if not specified - * - * \returns success/failure - */ -bool SplitURI(const std::string& uri, std::string& host, std::string& file, int& port); - -/** \brief Encode a String suitable for sending as a URL request (eg Get) - * \ingroup SimpleHttpClient - * - * Encode a String so it can be sent as part of a URL request - * - * \param s the string to encode - * \param enc the encoded version of the string that is returned - * - */ -void URLEncode(const std::string& s, std::string& enc); - -/** \brief Result Codes for SSL operations - * \ingroup SimpleHttpClient - * - */ -enum SSLResult -{ - SSLR_OK = 0x0, /**< No Error */ - SSLR_NO_SSL = 0x1, /**< SSL Is not required */ - SSLR_FAIL = 0x2, /**< Internal SSL Engine Failure */ - SSLR_CERT_EXPIRED = 0x4, /**< SSL Certificate has expired */ - SSLR_CERT_REVOKED = 0x8, /**< SSL Certificate is revoked */ - SSLR_CERT_CN_MISMATCH = 0x10, /**< SSL CN Name does not match Hostname */ - SSLR_CERT_NOT_TRUSTED = 0x20, /**< SSL Certificate is not trusted */ - SSLR_CERT_MISSING = 0x40, /**< SSL Certificate is missing */ - SSLR_CERT_SKIP_VERIFY = 0x80, /**< SSL Certificate Verification is disabled */ - SSLR_CERT_FUTURE = 0x100, /**< SSL Certificate is valid in the future */ - - _SSLR_FORCE32BIT = 0x7fffffff -}; - -/** \brief a TCP Socket that can optionally be protected via SSL - * \ingroup SimpleHttpClient - * - * This represents a TCP Socket that can be encrypted via SSL and - * is used to connect to a TCP Server (in this case, a HTTP(s) Server - */ -class TcpSocket -{ -public: - TcpSocket(); - virtual ~TcpSocket(); - - virtual bool HasPendingTask() const { return false; } - - bool open(const char *addr = NULL, unsigned int port = 0); - void close(); - bool update(); // returns true if something interesting happened (incoming data, closed connection, etc) - - bool isOpen(void); - - void SetBufsizeIn(unsigned int s); - bool SetNonBlocking(bool nonblock); - unsigned int GetBufSize() { return _inbufSize; } - const char *GetHost(void) { return _host.c_str(); } - bool SendBytes(const void *buf, unsigned int len); - - // SSL related - bool initSSL(const char *certs); - bool hasSSL() const { return !!_sslctx; } - void shutdownSSL(); - SSLResult verifySSL(); - -protected: - virtual void _OnCloseInternal(); - virtual void _OnData(); // data received callback. Internal, should only be overloaded to call _OnRecv() - - virtual void _OnRecv(void *buf, unsigned int size) = 0; - virtual void _OnClose() {}; // close callback - virtual void _OnOpen() {} // called when opened - virtual bool _OnUpdate() { return true; } // called before reading from the socket - - void _ShiftBuffer(); - - char *_inbuf; - char *_readptr; // part of inbuf, optionally skipped header - char *_writeptr; // passed to recv(). usually equal to _inbuf, but may point inside the buffer in case of a partial transfer. - - unsigned int _inbufSize; // size of internal buffer - unsigned int _writeSize; // how many bytes can be written to _writeptr; - unsigned int _recvSize; // incoming size, max _inbufSize - 1 - - unsigned int _lastport; // port used in last open() call - - bool _nonblocking; // Default true. If false, the current thread is blocked while waiting for input. + /** \defgroup SimpleHttpClient Basic HTTP(s) Client + * + * a Basic HTTP Client for talking to webservers + */ + + namespace Internal + { + namespace Platform + { + /** \brief Initialize the Network for HTTP requests + * \ingroup SimpleHttpClient + * + * Initializes the Network for HTTP requests + * + * \returns success/failure + */ + bool InitNetwork(); + + /** \brief Stop the Network for HTTP requests + * \ingroup SimpleHttpClient + * + * Stops the Network for HTTP requests and releases resources associated with it + */ + void StopNetwork(); + + /** \brief Indicates if we support HTTPS requests + * \ingroup SimpleHttpClient + * + * Indicates if we support HTTPS requests + * + * \returns success/failure + * \todo SSL is not actually implemented yet. + */ + bool HasSSL(); + + /** \brief Split a URL into its different parts/ports etc + * \ingroup SimpleHttpClient + * + * Split a URL Into the different parts/ports + * + * \param uri the URL to parse + * \param host the Hostname of the URL + * \param file the directory/file name of the URL + * \param port the port number of the URL, or 80 if not specified + * + * \returns success/failure + */ + bool SplitURI(const std::string& uri, std::string& host, std::string& file, int& port); + + /** \brief Encode a String suitable for sending as a URL request (eg Get) + * \ingroup SimpleHttpClient + * + * Encode a String so it can be sent as part of a URL request + * + * \param s the string to encode + * \param enc the encoded version of the string that is returned + * + */ + void URLEncode(const std::string& s, std::string& enc); + + /** \brief Result Codes for SSL operations + * \ingroup SimpleHttpClient + * + */ + enum SSLResult + { + SSLR_OK = 0x0, /**< No Error */ + SSLR_NO_SSL = 0x1, /**< SSL Is not required */ + SSLR_FAIL = 0x2, /**< Internal SSL Engine Failure */ + SSLR_CERT_EXPIRED = 0x4, /**< SSL Certificate has expired */ + SSLR_CERT_REVOKED = 0x8, /**< SSL Certificate is revoked */ + SSLR_CERT_CN_MISMATCH = 0x10, /**< SSL CN Name does not match Hostname */ + SSLR_CERT_NOT_TRUSTED = 0x20, /**< SSL Certificate is not trusted */ + SSLR_CERT_MISSING = 0x40, /**< SSL Certificate is missing */ + SSLR_CERT_SKIP_VERIFY = 0x80, /**< SSL Certificate Verification is disabled */ + SSLR_CERT_FUTURE = 0x100, /**< SSL Certificate is valid in the future */ + + _SSLR_FORCE32BIT = 0x7fffffff + }; + + /** \brief a TCP Socket that can optionally be protected via SSL + * \ingroup SimpleHttpClient + * + * This represents a TCP Socket that can be encrypted via SSL and + * is used to connect to a TCP Server (in this case, a HTTP(s) Server + */ + class TcpSocket + { + public: + TcpSocket(); + virtual ~TcpSocket(); + + virtual bool HasPendingTask() const + { + return false; + } + + bool open(const char *addr = NULL, unsigned int port = 0); + void close(); + bool update(); // returns true if something interesting happened (incoming data, closed connection, etc) + + bool isOpen(void); + + void SetBufsizeIn(unsigned int s); + bool SetNonBlocking(bool nonblock); + unsigned int GetBufSize() + { + return _inbufSize; + } + const char *GetHost(void) + { + return _host.c_str(); + } + bool SendBytes(const void *buf, unsigned int len); + + // SSL related + bool initSSL(const char *certs); + bool hasSSL() const + { + return !!_sslctx; + } + void shutdownSSL(); + SSLResult verifySSL(); + + protected: + virtual void _OnCloseInternal(); + virtual void _OnData(); // data received callback. Internal, should only be overloaded to call _OnRecv() + + virtual void _OnRecv(void *buf, unsigned int size) = 0; + virtual void _OnClose() + { + } + ; // close callback + virtual void _OnOpen() + { + } // called when opened + virtual bool _OnUpdate() + { + return true; + } // called before reading from the socket + + void _ShiftBuffer(); + + char *_inbuf; + char *_readptr; // part of inbuf, optionally skipped header + char *_writeptr; // passed to recv(). usually equal to _inbuf, but may point inside the buffer in case of a partial transfer. + + unsigned int _inbufSize; // size of internal buffer + unsigned int _writeSize; // how many bytes can be written to _writeptr; + unsigned int _recvSize; // incoming size, max _inbufSize - 1 + + unsigned int _lastport; // port used in last open() call + + bool _nonblocking; // Default true. If false, the current thread is blocked while waiting for input. #ifdef _WIN32 - intptr_t _s; // socket handle. really an int, but to be sure its 64 bit compatible as it seems required on windows, we use this. + intptr_t _s; // socket handle. really an int, but to be sure its 64 bit compatible as it seems required on windows, we use this. #else - long _s; + long _s; #endif - std::string _host; + std::string _host; -private: - int _writeBytes(const unsigned char *buf, size_t len); - int _readBytes(unsigned char *buf, size_t maxlen); - void *_sslctx; -}; + private: + int _writeBytes(const unsigned char *buf, size_t len); + int _readBytes(unsigned char *buf, size_t maxlen); + void *_sslctx; + }; #ifdef MINIHTTP_SUPPORT_HTTP -enum HttpCode -{ - HTTP_OK = 200, - HTTP_NOTFOUND = 404, -}; - -/** \brief This class is used for Posting data to a HTTP(s) server - * \ingroup SimpleHttpClient - * - * Post some data to a HTTP(s) server - * - */ -class POST -{ -public: - void reserve(size_t res) { data.reserve(res); } - POST& add(const char *key, const char *value); - const char *c_str() const { return data.c_str(); } - const std::string& str() const { return data; } - bool empty() const { return data.empty(); } - size_t length() const { return data.length(); } -private: - std::string data; -}; - -/** \brief Main class for making a HTTP request to a HTTP(s) server - * \ingroup SimpleHttpClient - * - * Make a request to a HTTP Server - * - */ -struct Request -{ - Request() : port(80), user(NULL) {} - Request(const std::string& h, const std::string& res, int p = 80, void *u = NULL) - : host(h), resource(res), port(80), user(u), useSSL(false) {} - - std::string protocol; - std::string host; - std::string header; // set by socket - std::string resource; - std::string extraGetHeaders; - int port; - void *user; - bool useSSL; - POST post; // if this is empty, it's a GET request, otherwise a POST request -}; - -/** \brief a Socket that speaks HTTP protocol. - * \ingroup SimpleHttpClient - * - * Talk to a HTTP(s) server - * - */ -class HttpSocket : public OpenZWave::SimpleHTTPClient::TcpSocket -{ -public: - - HttpSocket(); - virtual ~HttpSocket(); - - virtual bool HasPendingTask() const - { - return ExpectMoreData() || _requestQ.size(); - } - - void SetKeepAlive(unsigned int secs) { _keep_alive = secs; } - void SetUserAgent(const std::string &s) { _user_agent = s; } - void SetAcceptEncoding(const std::string& s) { _accept_encoding = s; } - void SetFollowRedirect(bool follow) { _followRedir = follow; } - void SetAlwaysHandle(bool h) { _alwaysHandle = h; } - void SetDownloadFile(std::string filename) { _filename = filename; } - - bool Download(const std::string& url, const char *extraRequest = NULL, void *user = NULL, const POST *post = NULL); - bool SendRequest(Request& what, bool enqueue); - bool SendRequest(const std::string what, const char *extraRequest = NULL, void *user = NULL); - bool QueueRequest(const std::string what, const char *extraRequest = NULL, void *user = NULL); - - unsigned int GetRemaining() const { return _remaining; } - - unsigned int GetStatusCode() const { return _status; } - unsigned int GetContentLen() const { return _contentLen; } - bool ChunkedTransfer() const { return _chunkedTransfer; } - bool ExpectMoreData() const { return _remaining || _chunkedTransfer; } - - const Request &GetCurrentRequest() const { return _curRequest; } - const char *Hdr(const char *h) const; - - bool IsRedirecting() const; - bool IsSuccess() const; - -protected: - virtual void _OnCloseInternal(); - virtual void _OnClose(); - virtual void _OnData(); // data received callback. Internal, should only be overloaded to call _OnRecv() - virtual void _OnRecv(void *buf, unsigned int size); - virtual void _OnOpen(); // called when opene - virtual bool _OnUpdate(); // called before reading from the socket - - // new ones: - virtual void _OnRequestDone() {} - - bool _Redirect(std::string loc, bool forceGET); - - void _ProcessChunk(); - bool _EnqueueOrSend(const Request& req, bool forceQueue = false); - void _DequeueMore(); - bool _OpenRequest(const Request& req); - void _ParseHeader(); - void _ParseHeaderFields(const char *s, size_t size); - bool _HandleStatus(); // Returns whether the processed request was successful, or not - void _FinishRequest(); - void _OnRecvInternal(void *buf, unsigned int size); - - std::string _user_agent; - std::string _accept_encoding; // Default empty. - std::string _tmpHdr; // used to save the http header if the incoming buffer was not large enough - - unsigned int _keep_alive; // http related - unsigned int _remaining; // http "Content-Length: X" - already recvd. 0 if ready for next packet. - // For chunked transfer encoding, this holds the remaining size of the current chunk - unsigned int _contentLen; // as reported by server - unsigned int _status; // http status code, HTTP_OK if things are good - - std::queue _requestQ; - std::map _hdrs; // Maps HTTP header fields to their values - - Request _curRequest; - - bool _inProgress; - bool _chunkedTransfer; - bool _mustClose; // keep-alive specified, or not - bool _followRedir; // Default true. Follow 3xx redirects if this is set. - bool _alwaysHandle; // Also deliver to _OnRecv() if a non-success code was received. - std::string _filename; - FILE* _pFile; -}; - + enum HttpCode + { + HTTP_OK = 200, + HTTP_NOTFOUND = 404, + }; + + /** \brief This class is used for Posting data to a HTTP(s) server + * \ingroup SimpleHttpClient + * + * Post some data to a HTTP(s) server + * + */ + class POST + { + public: + void reserve(size_t res) + { + data.reserve(res); + } + POST& add(const char *key, const char *value); + const char *c_str() const + { + return data.c_str(); + } + const std::string& str() const + { + return data; + } + bool empty() const + { + return data.empty(); + } + size_t length() const + { + return data.length(); + } + private: + std::string data; + }; + + /** \brief Main class for making a HTTP request to a HTTP(s) server + * \ingroup SimpleHttpClient + * + * Make a request to a HTTP Server + * + */ + struct Request + { + Request() : + port(80), user(NULL) + { + } + Request(const std::string& h, const std::string& res, int p = 80, void *u = NULL) : + host(h), resource(res), port(80), user(u), useSSL(false) + { + } + + std::string protocol; + std::string host; + std::string header; // set by socket + std::string resource; + std::string extraGetHeaders; + int port; + void *user; + bool useSSL; + POST post; // if this is empty, it's a GET request, otherwise a POST request + }; + + /** \brief a Socket that speaks HTTP protocol. + * \ingroup SimpleHttpClient + * + * Talk to a HTTP(s) server + * + */ + class HttpSocket: public OpenZWave::Internal::Platform::TcpSocket + { + public: + + HttpSocket(); + virtual ~HttpSocket(); + + virtual bool HasPendingTask() const + { + return ExpectMoreData() || _requestQ.size(); + } + + void SetKeepAlive(unsigned int secs) + { + _keep_alive = secs; + } + void SetUserAgent(const std::string &s) + { + _user_agent = s; + } + void SetAcceptEncoding(const std::string& s) + { + _accept_encoding = s; + } + void SetFollowRedirect(bool follow) + { + _followRedir = follow; + } + void SetAlwaysHandle(bool h) + { + _alwaysHandle = h; + } + void SetDownloadFile(std::string filename) + { + _filename = filename; + } + + bool Download(const std::string& url, const char *extraRequest = NULL, void *user = NULL, const POST *post = NULL); + bool SendRequest(Request& what, bool enqueue); + bool SendRequest(const std::string what, const char *extraRequest = NULL, void *user = NULL); + bool QueueRequest(const std::string what, const char *extraRequest = NULL, void *user = NULL); + + unsigned int GetRemaining() const + { + return _remaining; + } + + unsigned int GetStatusCode() const + { + return _status; + } + unsigned int GetContentLen() const + { + return _contentLen; + } + bool ChunkedTransfer() const + { + return _chunkedTransfer; + } + bool ExpectMoreData() const + { + return _remaining || _chunkedTransfer; + } + + const Request &GetCurrentRequest() const + { + return _curRequest; + } + const char *Hdr(const char *h) const; + + bool IsRedirecting() const; + bool IsSuccess() const; + + protected: + virtual void _OnCloseInternal(); + virtual void _OnClose(); + virtual void _OnData(); // data received callback. Internal, should only be overloaded to call _OnRecv() + virtual void _OnRecv(void *buf, unsigned int size); + virtual void _OnOpen(); // called when opene + virtual bool _OnUpdate(); // called before reading from the socket + + // new ones: + virtual void _OnRequestDone() + { + } + + bool _Redirect(std::string loc, bool forceGET); + + void _ProcessChunk(); + bool _EnqueueOrSend(const Request& req, bool forceQueue = false); + void _DequeueMore(); + bool _OpenRequest(const Request& req); + void _ParseHeader(); + void _ParseHeaderFields(const char *s, size_t size); + bool _HandleStatus(); // Returns whether the processed request was successful, or not + void _FinishRequest(); + void _OnRecvInternal(void *buf, unsigned int size); + + std::string _user_agent; + std::string _accept_encoding; // Default empty. + std::string _tmpHdr; // used to save the http header if the incoming buffer was not large enough + + unsigned int _keep_alive; // http related + unsigned int _remaining; // http "Content-Length: X" - already recvd. 0 if ready for next packet. + // For chunked transfer encoding, this holds the remaining size of the current chunk + unsigned int _contentLen; // as reported by server + unsigned int _status; // http status code, HTTP_OK if things are good + + std::queue _requestQ; + std::map _hdrs; // Maps HTTP header fields to their values + + Request _curRequest; + + bool _inProgress; + bool _chunkedTransfer; + bool _mustClose; // keep-alive specified, or not + bool _followRedir; // Default true. Follow 3xx redirects if this is set. + bool _alwaysHandle; // Also deliver to _OnRecv() if a non-success code was received. + std::string _filename; + FILE* _pFile; + }; #endif @@ -345,40 +422,42 @@ class HttpSocket : public OpenZWave::SimpleHTTPClient::TcpSocket #ifdef MINIHTTP_SUPPORT_SOCKET_SET -/** \brief Support Multiple TCP Socket connections - * \ingroup SimpleHttpClient - * - * to Support multiple TCP Socket Connections - * - */ -class SocketSet -{ -public: - virtual ~SocketSet(); - void deleteAll(); - bool update(); - void add(TcpSocket *s, bool deleteWhenDone = true); - bool has(TcpSocket *s); - void remove(TcpSocket *s); - inline size_t size() { return _store.size(); } + /** \brief Support Multiple TCP Socket connections + * \ingroup SimpleHttpClient + * + * to Support multiple TCP Socket Connections + * + */ + class SocketSet + { + public: + virtual ~SocketSet(); + void deleteAll(); + bool update(); + void add(TcpSocket *s, bool deleteWhenDone = true); + bool has(TcpSocket *s); + void remove(TcpSocket *s); + inline size_t size() + { + return _store.size(); + } //protected: - struct SocketSetData - { - bool deleteWhenDone; - // To be extended - }; + struct SocketSetData + { + bool deleteWhenDone; + // To be extended + }; - typedef std::map Store; + typedef std::map Store; - Store _store; -}; + Store _store; + }; #endif - -} // end HttpClient namespace -} // end openzwave namespace - + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave #endif diff --git a/cpp/src/platform/Log.cpp b/cpp/src/platform/Log.cpp index 610e1f5700..02cd82f1ed 100644 --- a/cpp/src/platform/Log.cpp +++ b/cpp/src/platform/Log.cpp @@ -39,54 +39,43 @@ #include "platform/unix/LogImpl.h" // Platform-specific implementation of a log #endif - using namespace OpenZWave; char const *OpenZWave::LogLevelString[] = -{ - "Invalid", /**< Invalid Log Level Status - Used to Indicate error from Importing bad Options.xml */ - "None", /**< LogLevel_None Disable all logging */ - "Always", /**< LogLevel_Always These messages should always be shown */ - "Fatal", /**< LogLevel_Fatal A likely fatal issue in the library */ - "Error", /**< LogLevel_Error A serious issue with the library or the network */ - "Warning", /**< LogLevel_Warning A minor issue from which the library should be able to recover */ - "Alert", /**< LogLevel_Alert Something unexpected by the library about which the controlling application should be aware */ - "Info", /**< LogLevel_Info Everything's working fine...these messages provide streamlined feedback on each message */ - "Detail", /**< LogLevel_Detail Detailed information on the progress of each message */ - "Debug", /**< LogLevel_Debug Very detailed information on progress that will create a huge log file quickly - But this level (as others) can be queued and sent to the log only on an error or warning */ - "StreamDetail", /**< LogLevel_StreamDetail Will include low-level byte transfers from controller to buffer to application and back */ - "Internal" /**< LogLevel_Internal Used only within the log class (uses existing timestamp, etc.) */ +{ "Invalid", /**< Invalid Log Level Status - Used to Indicate error from Importing bad Options.xml */ +"None", /**< LogLevel_None Disable all logging */ +"Always", /**< LogLevel_Always These messages should always be shown */ +"Fatal", /**< LogLevel_Fatal A likely fatal issue in the library */ +"Error", /**< LogLevel_Error A serious issue with the library or the network */ +"Warning", /**< LogLevel_Warning A minor issue from which the library should be able to recover */ +"Alert", /**< LogLevel_Alert Something unexpected by the library about which the controlling application should be aware */ +"Info", /**< LogLevel_Info Everything's working fine...these messages provide streamlined feedback on each message */ +"Detail", /**< LogLevel_Detail Detailed information on the progress of each message */ +"Debug", /**< LogLevel_Debug Very detailed information on progress that will create a huge log file quickly + But this level (as others) can be queued and sent to the log only on an error or warning */ +"StreamDetail", /**< LogLevel_StreamDetail Will include low-level byte transfers from controller to buffer to application and back */ +"Internal" /**< LogLevel_Internal Used only within the log class (uses existing timestamp, etc.) */ }; - - Log* Log::s_instance = NULL; -i_LogImpl* Log::m_pImpl = NULL; -bool Log::s_customLogger = false; +std::vector Log::m_pImpls; static bool s_dologging; //----------------------------------------------------------------------------- // // Static creation of the singleton //----------------------------------------------------------------------------- -Log* Log::Create -( - string const& _filename, - bool const _bAppend, - bool const _bConsoleOutput, - LogLevel const _saveLevel, - LogLevel const _queueLevel, - LogLevel const _dumpTrigger -) +Log* Log::Create(string const& _filename, bool const _bAppend, bool const _bConsoleOutput, LogLevel const _saveLevel, LogLevel const _queueLevel, LogLevel const _dumpTrigger) { - if( NULL == s_instance ) + if ( NULL == s_instance) { - s_instance = new Log( _filename, _bAppend, _bConsoleOutput, _saveLevel, _queueLevel, _dumpTrigger ); + s_instance = new Log(_filename, _bAppend, _bConsoleOutput, _saveLevel, _queueLevel, _dumpTrigger); s_dologging = true; // default logging to true so no change to what people experience now - } else { + } + else + { Log::Destroy(); - s_instance = new Log( _filename, _bAppend, _bConsoleOutput, _saveLevel, _queueLevel, _dumpTrigger ); + s_instance = new Log(_filename, _bAppend, _bConsoleOutput, _saveLevel, _queueLevel, _dumpTrigger); s_dologging = true; // default logging to true so no change to what people experience now } @@ -98,29 +87,27 @@ Log* Log::Create // Static creation of the singleton //----------------------------------------------------------------------------- /* It isn't clear this is ever called or used. If no one complains, consider - deleting this code in April 2012. -Log* Log::Create -( - i_LogImpl *LogClass -) -{ - if (NULL == s_instance ) - { - s_instance = new Log( "" ); - s_dologging = true; - } - SetLoggingClass( LogClass ); - return s_instance; -} -*/ + deleting this code in April 2012. + Log* Log::Create + ( + i_LogImpl *LogClass + ) + { + if (NULL == s_instance ) + { + s_instance = new Log( "" ); + s_dologging = true; + } + SetLoggingClass( LogClass ); + return s_instance; + } + */ //----------------------------------------------------------------------------- // // Static method to destroy the logging singleton. //----------------------------------------------------------------------------- -void Log::Destroy -( -) +void Log::Destroy() { delete s_instance; s_instance = NULL; @@ -130,15 +117,16 @@ void Log::Destroy // // Set log class //----------------------------------------------------------------------------- -bool Log::SetLoggingClass -( - i_LogImpl *LogClass -) +bool Log::SetLoggingClass(i_LogImpl *LogClass, bool Append) { - if (!s_customLogger) - delete m_pImpl; - m_pImpl = LogClass; - s_customLogger = true; + if (!Append) { + for (std::vector::iterator it = s_instance->m_pImpls.begin(); it != s_instance->m_pImpls.end();) { + i_LogImpl *lc = *it; + delete lc; + it = s_instance->m_pImpls.erase(it); + } + } + s_instance->m_pImpls.push_back(LogClass); return true; } @@ -152,40 +140,32 @@ bool Log::SetLoggingClass // Console output? Yes // Append to an existing log? No (overwrite) //----------------------------------------------------------------------------- -void Log::SetLoggingState -( - bool _dologging -) +void Log::SetLoggingState(bool _dologging) { bool prevLogging = s_dologging; s_dologging = _dologging; - if (!prevLogging && s_dologging) Log::Write(LogLevel_Always, "Logging started\n\n"); + if (!prevLogging && s_dologging) + Log::Write(LogLevel_Always, "Logging started\n\n"); } //----------------------------------------------------------------------------- // // Set flag to actually write to log or skip it //----------------------------------------------------------------------------- -void Log::SetLoggingState -( - LogLevel _saveLevel, - LogLevel _queueLevel, - LogLevel _dumpTrigger -) +void Log::SetLoggingState(LogLevel _saveLevel, LogLevel _queueLevel, LogLevel _dumpTrigger) { // parameter checking: // _queueLevel cannot be less than or equal to _saveLevel (where lower ordinals are more severe conditions) // _dumpTrigger cannot be greater than or equal to _queueLevel - if( _queueLevel <= _saveLevel ) - Log::Write( LogLevel_Warning, "Only lower priority messages may be queued for error-driven display." ); - if( _dumpTrigger >= _queueLevel ) - Log::Write( LogLevel_Warning, "The trigger for dumping queued messages must be a higher-priority message than the level that is queued." ); + if (_queueLevel <= _saveLevel) + Log::Write(LogLevel_Warning, "Only lower priority messages may be queued for error-driven display."); + if (_dumpTrigger >= _queueLevel) + Log::Write(LogLevel_Warning, "The trigger for dumping queued messages must be a higher-priority message than the level that is queued."); bool prevLogging = s_dologging; // s_dologging is true if any messages are to be saved in file or queue - if( (_saveLevel > LogLevel_Always) || - (_queueLevel > LogLevel_Always) ) + if ((_saveLevel > LogLevel_Always) || (_queueLevel > LogLevel_Always)) { s_dologging = true; } @@ -194,23 +174,23 @@ void Log::SetLoggingState s_dologging = false; } - if( s_instance && s_dologging && s_instance->m_pImpl ) + if (s_instance && s_dologging && (s_instance->m_pImpls.size() > 0)) { s_instance->m_logMutex->Lock(); - s_instance->m_pImpl->SetLoggingState( _saveLevel, _queueLevel, _dumpTrigger ); + for (std::vector::iterator it = s_instance->m_pImpls.begin(); it != s_instance->m_pImpls.end(); it++) + (*it)->SetLoggingState(_saveLevel, _queueLevel, _dumpTrigger); s_instance->m_logMutex->Unlock(); } - if (!prevLogging && s_dologging) Log::Write(LogLevel_Always, "Logging started\n\n"); + if (!prevLogging && s_dologging) + Log::Write(LogLevel_Always, "Logging started\n\n"); } //----------------------------------------------------------------------------- // // Return a flag to indicate whether logging is enabled //----------------------------------------------------------------------------- -bool Log::GetLoggingState -( -) +bool Log::GetLoggingState() { return s_dologging; } @@ -219,20 +199,16 @@ bool Log::GetLoggingState // // Write to the log //----------------------------------------------------------------------------- -void Log::Write -( - LogLevel _level, - char const* _format, - ... -) +void Log::Write(LogLevel _level, char const* _format, ...) { - if( s_instance && s_dologging && s_instance->m_pImpl ) + if (s_instance && s_dologging && (s_instance->m_pImpls.size() > 0)) { s_instance->m_logMutex->Lock(); // double locks if recursive va_list args; - va_start( args, _format ); - s_instance->m_pImpl->Write( _level, 0, _format, args ); - va_end( args ); + va_start(args, _format); + for (std::vector::iterator it = s_instance->m_pImpls.begin(); it != s_instance->m_pImpls.end(); it++) + (*it)->Write(_level, 0, _format, args); + va_end(args); s_instance->m_logMutex->Unlock(); } } @@ -241,23 +217,18 @@ void Log::Write // // Write to the log //----------------------------------------------------------------------------- -void Log::Write -( - LogLevel _level, - uint8 const _nodeId, - char const* _format, - ... -) +void Log::Write(LogLevel _level, uint8 const _nodeId, char const* _format, ...) { - if( s_instance && s_dologging && s_instance->m_pImpl ) + if (s_instance && s_dologging && (s_instance->m_pImpls.size() > 0)) { - if( _level != LogLevel_Internal ) + if (_level != LogLevel_Internal) s_instance->m_logMutex->Lock(); va_list args; - va_start( args, _format ); - s_instance->m_pImpl->Write( _level, _nodeId, _format, args ); - va_end( args ); - if( _level != LogLevel_Internal ) + va_start(args, _format); + for (std::vector::iterator it = s_instance->m_pImpls.begin(); it != s_instance->m_pImpls.end(); it++) + (*it)->Write(_level, _nodeId, _format, args); + va_end(args); + if (_level != LogLevel_Internal) s_instance->m_logMutex->Unlock(); } } @@ -266,14 +237,13 @@ void Log::Write // // Send queued messages to the log (and empty the queue) //----------------------------------------------------------------------------- -void Log::QueueDump -( -) +void Log::QueueDump() { - if( s_instance && s_dologging && s_instance->m_pImpl ) + if (s_instance && s_dologging && (s_instance->m_pImpls.size() > 0)) { s_instance->m_logMutex->Lock(); - s_instance->m_pImpl->QueueDump(); + for (std::vector::iterator it = s_instance->m_pImpls.begin(); it !=s_instance->m_pImpls.end(); it++) + (*it)->QueueDump(); s_instance->m_logMutex->Unlock(); } } @@ -282,14 +252,13 @@ void Log::QueueDump // // Empty the queued message queue //----------------------------------------------------------------------------- -void Log::QueueClear -( -) +void Log::QueueClear() { - if( s_instance && s_dologging && s_instance->m_pImpl ) + if (s_instance && s_dologging && (s_instance->m_pImpls.size() > 0)) { s_instance->m_logMutex->Lock(); - s_instance->m_pImpl->QueueClear(); + for (std::vector::iterator it = s_instance->m_pImpls.begin(); it !=s_instance->m_pImpls.end(); it++) + (*it)->QueueClear(); s_instance->m_logMutex->Unlock(); } } @@ -298,15 +267,13 @@ void Log::QueueClear // // Change the name of the log file (will start writing a new file) //----------------------------------------------------------------------------- -void Log::SetLogFileName -( - const string &_filename -) +void Log::SetLogFileName(const string &_filename) { - if( s_instance && s_dologging && s_instance->m_pImpl ) + if (s_instance && s_dologging && (s_instance->m_pImpls.size() > 0)) { s_instance->m_logMutex->Lock(); - s_instance->m_pImpl->SetLogFileName( _filename ); + for (std::vector::iterator it = s_instance->m_pImpls.begin(); it !=s_instance->m_pImpls.end(); it++) + (*it)->SetLogFileName(_filename); s_instance->m_logMutex->Unlock(); } } @@ -315,34 +282,25 @@ void Log::SetLogFileName // // Constructor //----------------------------------------------------------------------------- -Log::Log -( - string const& _filename, - bool const _bAppend, - bool const _bConsoleOutput, - LogLevel const _saveLevel, - LogLevel const _queueLevel, - LogLevel const _dumpTrigger -): - m_logMutex( new Mutex() ) +Log::Log(string const& _filename, bool const _bAppend, bool const _bConsoleOutput, LogLevel const _saveLevel, LogLevel const _queueLevel, LogLevel const _dumpTrigger) : + m_logMutex(new Internal::Platform::Mutex()) { - if (NULL == m_pImpl) { - s_customLogger = false; - m_pImpl = new LogImpl( _filename, _bAppend, _bConsoleOutput, _saveLevel, _queueLevel, _dumpTrigger ); - } + if (m_pImpls.size() == 0) + { + m_pImpls.push_back(new Internal::Platform::LogImpl(_filename, _bAppend, _bConsoleOutput, _saveLevel, _queueLevel, _dumpTrigger)); + } } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -Log::~Log -( -) +Log::~Log() { m_logMutex->Release(); - if (!s_customLogger) { - delete m_pImpl; - m_pImpl = NULL; + for (std::vector::iterator it = s_instance->m_pImpls.begin(); it != s_instance->m_pImpls.end();) { + i_LogImpl *lc = *it; + delete lc; + it = s_instance->m_pImpls.erase(it); } } diff --git a/cpp/src/platform/Log.h b/cpp/src/platform/Log.h index 271e8446f5..78ba5a03fb 100644 --- a/cpp/src/platform/Log.h +++ b/cpp/src/platform/Log.h @@ -30,13 +30,18 @@ #include #include +#include #include "Defs.h" - - namespace OpenZWave { - class Mutex; + namespace Internal + { + namespace Platform + { + class Mutex; + } + } extern char const *LogLevelString[]; /** \brief Various LogLevels available to the Application @@ -46,19 +51,19 @@ namespace OpenZWave */ enum LogLevel { - LogLevel_Invalid, /**< Invalid Log Status */ - LogLevel_None, /**< Disable all logging */ - LogLevel_Always, /**< These messages should always be shown */ - LogLevel_Fatal, /**< A likely fatal issue in the library */ - LogLevel_Error, /**< A serious issue with the library or the network */ - LogLevel_Warning, /**< A minor issue from which the library should be able to recover */ - LogLevel_Alert, /**< Something unexpected by the library about which the controlling application should be aware */ - LogLevel_Info, /**< Everything is working fine...these messages provide streamlined feedback on each message */ - LogLevel_Detail, /**< Detailed information on the progress of each message */ - LogLevel_Debug, /**< Very detailed information on progress that will create a huge log file quickly - But this level (as others) can be queued and sent to the log only on an error or warning */ - LogLevel_StreamDetail, /**< Will include low-level byte transfers from controller to buffer to application and back */ - LogLevel_Internal /**< Used only within the log class (uses existing timestamp, etc.) */ + LogLevel_Invalid, /**< Invalid Log Status */ + LogLevel_None, /**< Disable all logging */ + LogLevel_Always, /**< These messages should always be shown */ + LogLevel_Fatal, /**< A likely fatal issue in the library */ + LogLevel_Error, /**< A serious issue with the library or the network */ + LogLevel_Warning, /**< A minor issue from which the library should be able to recover */ + LogLevel_Alert, /**< Something unexpected by the library about which the controlling application should be aware */ + LogLevel_Info, /**< Everything is working fine...these messages provide streamlined feedback on each message */ + LogLevel_Detail, /**< Detailed information on the progress of each message */ + LogLevel_Debug, /**< Very detailed information on progress that will create a huge log file quickly + But this level (as others) can be queued and sent to the log only on an error or warning */ + LogLevel_StreamDetail, /**< Will include low-level byte transfers from controller to buffer to application and back */ + LogLevel_Internal /**< Used only within the log class (uses existing timestamp, etc.) */ }; /** \brief A Abstract class to create a Custom Logging Method @@ -69,135 +74,142 @@ namespace OpenZWave */ class i_LogImpl { - public: - i_LogImpl() { } ; - virtual ~i_LogImpl() { } ; - virtual void Write( LogLevel _level, uint8 const _nodeId, char const* _format, va_list _args ) = 0; - virtual void QueueDump() = 0; - virtual void QueueClear() = 0; - virtual void SetLoggingState( LogLevel _saveLevel, LogLevel _queueLevel, LogLevel _dumpTrigger ) = 0; - virtual void SetLogFileName( const string &_filename ) = 0; + public: + i_LogImpl() + { + } + ; + virtual ~i_LogImpl() + { + } + ; + virtual void Write(LogLevel _level, uint8 const _nodeId, char const* _format, va_list _args) = 0; + virtual void QueueDump() = 0; + virtual void QueueClear() = 0; + virtual void SetLoggingState(LogLevel _saveLevel, LogLevel _queueLevel, LogLevel _dumpTrigger) = 0; + virtual void SetLogFileName(const string &_filename) = 0; }; /** \brief Implements a platform-independent log...written to the console and, optionally, a file. * \ingroup Platform */ - class Log + class OPENZWAVE_EXPORT Log { - public: - /** \brief Create a log. - * - * Creates the cross-platform logging singleton. - * Any previous log will be cleared. - * \return a pointer to the logging object. - * \see Destroy, Write - */ - static Log* Create( string const& _filename, bool const _bAppend, bool const _bConsoleOutput, LogLevel const _saveLevel, LogLevel const _queueLevel, LogLevel const _dumpTrigger ); - - /** \brief Create a log. - * - * Creates the cross-platform logging singleton. - * Any previous log will be cleared. - * \param LogClass a Logging Class that inherits the i_LogImpl Class to use to Log - * \return a pointer to the logging object. - * \see Destroy, Write - */ - - static Log* Create( i_LogImpl *LogClass ); - - /** \brief Destroys the log. - * - * Destroys the logging singleton. The log can no longer - * be written to without another call to Create. - * \see Create, Write - */ - static void Destroy(); - - /** - * \brief Set the Logging Implementation Class to replace the standard File/Console logging - * - * \param LogClass A Logging Class that inherits the i_LogImpl Class used to Log to - * \return Bool Value indicating success or failure - */ - static bool SetLoggingClass(i_LogImpl *LogClass ); - - /** \brief Enable or disable library logging (retained for backward compatibility) - * - * \param _dologging If true, logging is enabled; if false, disabled - */ - static void SetLoggingState(bool _dologging); - - /**\brief Enable or disable library logging. - * - * To disable, set _saveLevel and _queueLevel to LogLevel_None. - * - * \param _saveLevel LogLevel of messages to write in real-time - * \param _queueLevel LogLevel of messages to queue to be dumped in case of an error - * \param _dumpTrigger LogLevel of message that triggers a queue dump (probably LogLevel_Error or LogLevel_Warning) - */ - static void SetLoggingState( LogLevel _saveLevel, LogLevel _queueLevel, LogLevel _dumpTrigger ); - - /**\brief Determine whether logging is enabled or not (retained for backward compatibility) - * - * \param _dologging If true, logging is enabled; if false, disabled - */ - static bool GetLoggingState(); - - /**\brief Obtain the various logging levels. - * - * \param _saveLevel LogLevel of messages to write in real-time - * \param _queueLevel LogLevel of messages to queue to be dumped in case of an error - * \param _dumpTrigger LogLevel of message that triggers a queue dump (probably LogLevel_Error or LogLevel_Warning) - */ - static void GetLoggingState( LogLevel* _saveLevel, LogLevel* _queueLevel, LogLevel* _dumpTrigger ); - - /** \brief Change the log file name. - * - * This will start a new log file (or potentially start appending - * information to an existing one. Developers might want to use this function, together with a timer - * in the controlling application, to create timestamped log file names. - * \param _filename Name of the new (or existing) file to use for log output. - */ - static void SetLogFileName( const string &_filename ); - - /**\brief Write an entry to the log. - * - * Writes a formatted string to the log. - * \param _level Specifies the type of log message (Error, Warning, Debug, etc.) - * \param _format. A string formatted in the same manner as used with printf etc. - * \param ... a variable number of arguments, to be included in the formatted string. - * \see Create, Destroy - */ - static void Write( LogLevel _level, char const* _format, ... ); - - /**\brief Write an entry to the log. - * - * Writes a formatted string to the log. - * \param _level Specifies the type of log message (Error, Warning, Debug, etc.) - * \param _nodeId Node Id this entry is about. - * \param _format. A string formatted in the same manner as used with printf etc. - * \param ... a variable number of arguments, to be included in the formatted string. - * \see Create, Destroy - */ - static void Write( LogLevel _level, uint8 const _nodeId, char const* _format, ... ); - - /** \brief Send the queued log messages to the log output. - */ - static void QueueDump(); - - /** - * Clear the log message queue - */ - static void QueueClear(); - - private: - Log( string const& _filename, bool const _bAppend, bool const _bConsoleOutput, LogLevel _saveLevel, LogLevel _queueLevel, LogLevel _dumpTrigger ); - ~Log(); - - static i_LogImpl* m_pImpl; /**< Pointer to an object that encapsulates the platform-specific logging implementation. */ - static Log* s_instance; - static bool s_customLogger; - Mutex* m_logMutex; + public: + /** \brief Create a log. + * + * Creates the cross-platform logging singleton. + * Any previous log will be cleared. + * \return a pointer to the logging object. + * \see Destroy, Write + */ + static Log* Create(string const& _filename, bool const _bAppend, bool const _bConsoleOutput, LogLevel const _saveLevel, LogLevel const _queueLevel, LogLevel const _dumpTrigger); + + /** \brief Create a log. + * + * Creates the cross-platform logging singleton. + * Any previous log will be cleared. + * \param LogClass a Logging Class that inherits the i_LogImpl Class to use to Log + * \return a pointer to the logging object. + * \see Destroy, Write + */ + + static Log* Create(i_LogImpl *LogClass); + + /** \brief Destroys the log. + * + * Destroys the logging singleton. The log can no longer + * be written to without another call to Create. + * \see Create, Write + */ + static void Destroy(); + + /** + * \brief Set the Logging Implementation Class to replace the standard File/Console logging + * + * \param LogClass A Logging Class that inherits the i_LogImpl Class used to Log to + * \param Append if this new Logging Class should be appended to the list of Logging Implementations, + * or replace the existing Logging Class + * \return Bool Value indicating success or failure + */ + static bool SetLoggingClass(i_LogImpl *LogClass, bool Append = false); + + /** \brief Enable or disable library logging (retained for backward compatibility) + * + * \param _dologging If true, logging is enabled; if false, disabled + */ + static void SetLoggingState(bool _dologging); + + /**\brief Enable or disable library logging. + * + * To disable, set _saveLevel and _queueLevel to LogLevel_None. + * + * \param _saveLevel LogLevel of messages to write in real-time + * \param _queueLevel LogLevel of messages to queue to be dumped in case of an error + * \param _dumpTrigger LogLevel of message that triggers a queue dump (probably LogLevel_Error or LogLevel_Warning) + */ + static void SetLoggingState(LogLevel _saveLevel, LogLevel _queueLevel, LogLevel _dumpTrigger); + + /**\brief Determine whether logging is enabled or not (retained for backward compatibility) + * + * \param _dologging If true, logging is enabled; if false, disabled + */ + static bool GetLoggingState(); + + /**\brief Obtain the various logging levels. + * + * \param _saveLevel LogLevel of messages to write in real-time + * \param _queueLevel LogLevel of messages to queue to be dumped in case of an error + * \param _dumpTrigger LogLevel of message that triggers a queue dump (probably LogLevel_Error or LogLevel_Warning) + */ + static void GetLoggingState(LogLevel* _saveLevel, LogLevel* _queueLevel, LogLevel* _dumpTrigger); + + /** \brief Change the log file name. + * + * This will start a new log file (or potentially start appending + * information to an existing one. Developers might want to use this function, together with a timer + * in the controlling application, to create timestamped log file names. + * \param _filename Name of the new (or existing) file to use for log output. + */ + static void SetLogFileName(const string &_filename); + + /**\brief Write an entry to the log. + * + * Writes a formatted string to the log. + * \param _level Specifies the type of log message (Error, Warning, Debug, etc.) + * \param _format. A string formatted in the same manner as used with printf etc. + * \param ... a variable number of arguments, to be included in the formatted string. + * \see Create, Destroy + */ + static void Write(LogLevel _level, char const* _format, ...); + + /**\brief Write an entry to the log. + * + * Writes a formatted string to the log. + * \param _level Specifies the type of log message (Error, Warning, Debug, etc.) + * \param _nodeId Node Id this entry is about. + * \param _format. A string formatted in the same manner as used with printf etc. + * \param ... a variable number of arguments, to be included in the formatted string. + * \see Create, Destroy + */ + static void Write(LogLevel _level, uint8 const _nodeId, char const* _format, ...); + + /** \brief Send the queued log messages to the log output. + */ + static void QueueDump(); + + /** + * Clear the log message queue + */ + static void QueueClear(); + + private: + Log(string const& _filename, bool const _bAppend, bool const _bConsoleOutput, LogLevel _saveLevel, LogLevel _queueLevel, LogLevel _dumpTrigger); + ~Log(); + + static std::vector m_pImpls; /**< Pointer to an object that encapsulates the platform-specific logging implementation. */ + static Log* s_instance; + Internal::Platform::Mutex* m_logMutex; }; } // namespace OpenZWave diff --git a/cpp/src/platform/Mutex.cpp b/cpp/src/platform/Mutex.cpp index 7bca12fa6b..ea0c2a9fae 100644 --- a/cpp/src/platform/Mutex.cpp +++ b/cpp/src/platform/Mutex.cpp @@ -36,68 +36,64 @@ #include "platform/unix/MutexImpl.h" // Platform-specific implementation of a mutex #endif - -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -Mutex::Mutex -( -): - m_pImpl( new MutexImpl() ) -{ -} + Mutex::Mutex() : + m_pImpl(new MutexImpl()) + { + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -Mutex::~Mutex -( -) -{ - delete m_pImpl; -} + Mutex::~Mutex() + { + delete m_pImpl; + } //----------------------------------------------------------------------------- // // Lock the mutex //----------------------------------------------------------------------------- -bool Mutex::Lock -( - bool const _bWait // = true; -) -{ - return m_pImpl->Lock( _bWait ); -} + bool Mutex::Lock(bool const _bWait // = true; + ) + { + return m_pImpl->Lock(_bWait); + } //----------------------------------------------------------------------------- // // Release our lock on the mutex //----------------------------------------------------------------------------- -void Mutex::Unlock -( -) -{ - m_pImpl->Unlock(); + void Mutex::Unlock() + { + m_pImpl->Unlock(); - if( IsSignalled() ) - { - // The mutex has no owners, so notify the watchers - Notify(); - } -} + if (IsSignalled()) + { + // The mutex has no owners, so notify the watchers + Notify(); + } + } //----------------------------------------------------------------------------- // // Test whether the event is set //----------------------------------------------------------------------------- -bool Mutex::IsSignalled -( -) -{ - return m_pImpl->IsSignalled(); -} - + bool Mutex::IsSignalled() + { + return m_pImpl->IsSignalled(); + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/Mutex.h b/cpp/src/platform/Mutex.h index d445af847e..d938193b79 100644 --- a/cpp/src/platform/Mutex.h +++ b/cpp/src/platform/Mutex.h @@ -32,57 +32,62 @@ namespace OpenZWave { - class MutexImpl; - - /** \brief Implements a platform-independent mutex--for serializing access to a shared resource. - * \ingroup Platform - */ - class Mutex: public Wait + namespace Internal { - public: - /** - * Constructor. - * Creates a mutex object that can be used to serialize access to a shared resource. - */ - Mutex(); + namespace Platform + { + class MutexImpl; - /** - * Lock the mutex. - * Attempts to lock the mutex. - * There must be a matching call to Release for every call to Lock. - * \param _bWait Defaults to true. Set this argument to false if the method should return - * immediately, even if the lock is not available. - * \return True if the lock was obtained. - * \see Unlock - */ - bool Lock( bool const _bWait = true ); + /** \brief Implements a platform-independent mutex--for serializing access to a shared resource. + * \ingroup Platform + */ + class Mutex: public Wait + { + public: + /** + * Constructor. + * Creates a mutex object that can be used to serialize access to a shared resource. + */ + Mutex(); - /** - * Releases the lock on the mutex. - * There must be a matching call to Release for every call to Lock. - * \see Lock - */ - void Unlock(); + /** + * Lock the mutex. + * Attempts to lock the mutex. + * There must be a matching call to Release for every call to Lock. + * \param _bWait Defaults to true. Set this argument to false if the method should return + * immediately, even if the lock is not available. + * \return True if the lock was obtained. + * \see Unlock + */ + bool Lock(bool const _bWait = true); - /** - * Used by the Wait class to test whether the mutex is free. - */ - virtual bool IsSignalled(); - protected: + /** + * Releases the lock on the mutex. + * There must be a matching call to Release for every call to Lock. + * \see Lock + */ + void Unlock(); - /** - * Destructor. - * Destroys the mutex object. - */ - ~Mutex(); + /** + * Used by the Wait class to test whether the mutex is free. + */ + virtual bool IsSignalled(); + protected: - private: - Mutex( Mutex const& ); // prevent copy - Mutex& operator = ( Mutex const& ); // prevent assignment + /** + * Destructor. + * Destroys the mutex object. + */ + ~Mutex(); - MutexImpl* m_pImpl; // Pointer to an object that encapsulates the platform-specific implementation of a mutex. - }; + private: + Mutex(Mutex const&); // prevent copy + Mutex& operator =(Mutex const&); // prevent assignment + MutexImpl* m_pImpl; // Pointer to an object that encapsulates the platform-specific implementation of a mutex. + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_Mutex_H diff --git a/cpp/src/platform/Ref.h b/cpp/src/platform/Ref.h index ce36772f8e..21ad382cae 100644 --- a/cpp/src/platform/Ref.h +++ b/cpp/src/platform/Ref.h @@ -34,58 +34,72 @@ namespace OpenZWave { - /** - * Provides reference counting for objects. - * Any class wishing to include reference counting should be derived from Ref. - * Derived classes must declare their destructor as protected virtual. - * On construction, the reference count is set to one. Calls to AddRef increment - * the count. Calls to Release decrement the count. When the count reaches - * zero, the object is deleted. - * \ingroup Platform - */ - class Ref + namespace Internal { - public: - /** - * Initializes the RefCount to one. The object - * can only be deleted through a call to Release. - * \see AddRef, Release - */ - Ref(){ m_refs = 1; } - - /** - * Increases the reference count of the object. - * Every call to AddRef requires a matching call - * to Release before the object will be deleted. - * \see Release - */ - void AddRef(){ ++m_refs; } - - /** - * Removes a reference to an object. - * If this was the last reference to the message, the - * object is deleted. - * \see AddRef - */ - int32 Release() + namespace Platform { - if( 0 >= ( --m_refs ) ) + /** + * Provides reference counting for objects. + * Any class wishing to include reference counting should be derived from Ref. + * Derived classes must declare their destructor as protected virtual. + * On construction, the reference count is set to one. Calls to AddRef increment + * the count. Calls to Release decrement the count. When the count reaches + * zero, the object is deleted. + * \ingroup Platform + */ + class Ref { - delete this; - return 0; - } - return m_refs; - } + public: + /** + * Initializes the RefCount to one. The object + * can only be deleted through a call to Release. + * \see AddRef, Release + */ + Ref() + { + m_refs = 1; + } + + /** + * Increases the reference count of the object. + * Every call to AddRef requires a matching call + * to Release before the object will be deleted. + * \see Release + */ + void AddRef() + { + ++m_refs; + } - protected: - virtual ~Ref(){} + /** + * Removes a reference to an object. + * If this was the last reference to the message, the + * object is deleted. + * \see AddRef + */ + int32 Release() + { + if (0 >= (--m_refs)) + { + delete this; + return 0; + } + return m_refs; + } - private: - // Reference counting - int32 m_refs; + protected: + virtual ~Ref() + { + } - }; // class Ref + private: + // Reference counting + int32 m_refs; + }; + // class Ref + }// namespace Platform + } // namespace Internal } // namespace OpenZWave #endif // _Ref_H diff --git a/cpp/src/platform/SerialController.cpp b/cpp/src/platform/SerialController.cpp index 18dff8c5c3..32920d0e93 100644 --- a/cpp/src/platform/SerialController.cpp +++ b/cpp/src/platform/SerialController.cpp @@ -39,149 +39,128 @@ #include "platform/unix/SerialControllerImpl.h" // Platform-specific implementation of a serial port #endif -using namespace OpenZWave; - +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -SerialController::SerialController -( -): - m_baud ( 115200 ), - m_parity ( SerialController::Parity_None ), - m_stopBits ( SerialController::StopBits_One ), - m_bOpen( false ) -{ - m_pImpl = new SerialControllerImpl( this ); -} + SerialController::SerialController() : + m_baud(115200), m_parity(SerialController::Parity_None), m_stopBits(SerialController::StopBits_One), m_bOpen(false) + { + m_pImpl = new SerialControllerImpl(this); + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -SerialController::~SerialController -( -) -{ - delete m_pImpl; -} + SerialController::~SerialController() + { + delete m_pImpl; + } //----------------------------------------------------------------------------- // // Set the serial port baud rate. // The serial port must be closed for the setting to be accepted. //----------------------------------------------------------------------------- -bool SerialController::SetBaud -( - uint32 const _baud -) -{ - if( m_bOpen ) - { - return false; - } + bool SerialController::SetBaud(uint32 const _baud) + { + if (m_bOpen) + { + return false; + } - m_baud = _baud; - return true; -} + m_baud = _baud; + return true; + } //----------------------------------------------------------------------------- // // Set the serial port parity. // The serial port must be closed for the setting to be accepted. //----------------------------------------------------------------------------- -bool SerialController::SetParity -( - Parity const _parity -) -{ - if( m_bOpen ) - { - return false; - } + bool SerialController::SetParity(Parity const _parity) + { + if (m_bOpen) + { + return false; + } - m_parity = _parity; - return true; -} + m_parity = _parity; + return true; + } //----------------------------------------------------------------------------- // // Set the serial port stop bits. // The serial port must be closed for the setting to be accepted. //----------------------------------------------------------------------------- -bool SerialController::SetStopBits -( - StopBits const _stopBits -) -{ - if( m_bOpen ) - { - return false; - } + bool SerialController::SetStopBits(StopBits const _stopBits) + { + if (m_bOpen) + { + return false; + } - m_stopBits = _stopBits; - return true; -} + m_stopBits = _stopBits; + return true; + } //----------------------------------------------------------------------------- // // Open and configure a serial port //----------------------------------------------------------------------------- -bool SerialController::Open -( - string const& _serialControllerName -) -{ - if( m_bOpen ) - { - return false; - } + bool SerialController::Open(string const& _serialControllerName) + { + if (m_bOpen) + { + return false; + } - m_serialControllerName = _serialControllerName; - m_bOpen = m_pImpl->Open(); - return m_bOpen; -} + m_serialControllerName = _serialControllerName; + m_bOpen = m_pImpl->Open(); + return m_bOpen; + } //----------------------------------------------------------------------------- // // Close a serial port //----------------------------------------------------------------------------- -bool SerialController::Close -( -) -{ - if( !m_bOpen ) - { - return false; - } + bool SerialController::Close() + { + if (!m_bOpen) + { + return false; + } - m_pImpl->Close(); - m_bOpen = false; - return true; -} + m_pImpl->Close(); + m_bOpen = false; + return true; + } //----------------------------------------------------------------------------- // // Write data to an open serial port //----------------------------------------------------------------------------- -uint32 SerialController::Write -( - uint8* _buffer, - uint32 _length -) -{ - if( !m_bOpen ) - { - return 0; - } - - Log::Write( LogLevel_StreamDetail, " SerialController::Write (sent to controller)" ); - LogData(_buffer, _length, " Write: "); - - return( m_pImpl->Write( _buffer, _length ) ); -} - - - + uint32 SerialController::Write(uint8* _buffer, uint32 _length) + { + if (!m_bOpen) + { + return 0; + } + + Log::Write(LogLevel_StreamDetail, " SerialController::Write (sent to controller)"); + LogData(_buffer, _length, " Write: "); + + return (m_pImpl->Write(_buffer, _length)); + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/SerialController.h b/cpp/src/platform/SerialController.h index 0222244787..81e64343f0 100644 --- a/cpp/src/platform/SerialController.h +++ b/cpp/src/platform/SerialController.h @@ -34,107 +34,113 @@ namespace OpenZWave { - class Driver; - class Msg; - class SerialControllerImpl; - - /** \brief Interface for controllers that implement a Serial Interface (USB Serial Port Emulation) - * \ingroup Platform - */ - class SerialController: public Controller + namespace Internal { - friend class SerialControllerImpl; - - public: - enum Parity - { - Parity_None = 0, - Parity_Odd, - Parity_Even, - Parity_Mark, - Parity_Space - }; - - enum StopBits + namespace Platform { - StopBits_One = 0, - StopBits_OneAndAHalf = 1, - StopBits_Two = 2 - }; - - /** - * Constructor. - * Creates an object that represents a serial port. - */ - SerialController(); - - /** - * Destructor. - * Destroys the serial port object. - */ - virtual ~SerialController(); - - /** - * Set the serial port baud rate. The serial port must be closed for the setting to be accepted. - * @param _baud Integer containing the expected baud-rate of the serial connection. Most Z-Wave interfaces run at 115200 baud. - * @return True if the baud value was accepted. - * @see Open, Close - */ - bool SetBaud( uint32 const _baud ); - - /** - * Set the serial port parity. The serial port must be closed for the setting to be accepted. - * @param _parity Parity enum value indicating the serial data's expected type of parity bits, if any. - * @return True if the parity value was accepted. - * @see Open, Close - */ - bool SetParity( Parity const _parity ); - - /** - * Set the serial port stop bits. The serial port must be closed for the setting to be accepted. - * @param _stopBits StopBits enum value indicating the serial data's expected number of stop-bits. - * @return True if the stop bits value was accepted. - * @see Open, Close - */ - bool SetStopBits( StopBits const _stopBits ); - - /** - * Open a serial port. - * Attempts to open a serial port and initialize it with the specified parameters. - * @param _SerialControllerName The name of the port to open. For example, ttyS1 on Linux, or \\.\COM2 in Windows. - * @return True if the port was opened and configured successfully. - * @see Close, Read, Write - */ - bool Open( string const& _SerialControllerName ); - - /** - * Close a serial port. - * Closes the serial port. - * @return True if the port was closed successfully, or false if the port was already closed, or an error occurred. - * @see Open - */ - bool Close(); - - /** - * Write to a serial port. - * Attempts to write data to an open serial port. - * @param _buffer Pointer to a block of memory containing the data to be written. - * @param _length Length in bytes of the data. - * @return The number of bytes written. - * @see Read, Open, Close - */ - uint32 Write( uint8* _buffer, uint32 _length ); - - private: - uint32 m_baud; - SerialController::Parity m_parity; - SerialController::StopBits m_stopBits; - string m_serialControllerName; - - SerialControllerImpl* m_pImpl; // Pointer to an object that encapsulates the platform-specific implementation of the serial port. - bool m_bOpen; - }; +// class Driver; +// class Msg; + class SerialControllerImpl; + + /** \brief Interface for controllers that implement a Serial Interface (USB Serial Port Emulation) + * \ingroup Platform + */ + class SerialController: public Controller + { + friend class SerialControllerImpl; + + public: + enum Parity + { + Parity_None = 0, + Parity_Odd, + Parity_Even, + Parity_Mark, + Parity_Space + }; + + enum StopBits + { + StopBits_One = 0, + StopBits_OneAndAHalf = 1, + StopBits_Two = 2 + }; + + /** + * Constructor. + * Creates an object that represents a serial port. + */ + SerialController(); + + /** + * Destructor. + * Destroys the serial port object. + */ + virtual ~SerialController(); + + /** + * Set the serial port baud rate. The serial port must be closed for the setting to be accepted. + * @param _baud Integer containing the expected baud-rate of the serial connection. Most Z-Wave interfaces run at 115200 baud. + * @return True if the baud value was accepted. + * @see Open, Close + */ + bool SetBaud(uint32 const _baud); + + /** + * Set the serial port parity. The serial port must be closed for the setting to be accepted. + * @param _parity Parity enum value indicating the serial data's expected type of parity bits, if any. + * @return True if the parity value was accepted. + * @see Open, Close + */ + bool SetParity(Parity const _parity); + + /** + * Set the serial port stop bits. The serial port must be closed for the setting to be accepted. + * @param _stopBits StopBits enum value indicating the serial data's expected number of stop-bits. + * @return True if the stop bits value was accepted. + * @see Open, Close + */ + bool SetStopBits(StopBits const _stopBits); + + /** + * Open a serial port. + * Attempts to open a serial port and initialize it with the specified parameters. + * @param _SerialControllerName The name of the port to open. For example, ttyS1 on Linux, or \\.\COM2 in Windows. + * @return True if the port was opened and configured successfully. + * @see Close, Read, Write + */ + bool Open(string const& _SerialControllerName); + + /** + * Close a serial port. + * Closes the serial port. + * @return True if the port was closed successfully, or false if the port was already closed, or an error occurred. + * @see Open + */ + bool Close(); + + /** + * Write to a serial port. + * Attempts to write data to an open serial port. + * @param _buffer Pointer to a block of memory containing the data to be written. + * @param _length Length in bytes of the data. + * @return The number of bytes written. + * @see Read, Open, Close + */ + uint32 Write(uint8* _buffer, uint32 _length); + + private: + uint32 m_baud; + SerialController::Parity m_parity; + SerialController::StopBits m_stopBits; + string m_serialControllerName; + + OpenZWave::Internal::Platform::SerialControllerImpl* m_pImpl; // Pointer to an object that encapsulates the platform-specific implementation of the serial port. + bool m_bOpen; + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_SerialController_H diff --git a/cpp/src/platform/Stream.cpp b/cpp/src/platform/Stream.cpp index d461cd375e..4bd254beff 100644 --- a/cpp/src/platform/Stream.cpp +++ b/cpp/src/platform/Stream.cpp @@ -33,197 +33,176 @@ #include -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -Stream::Stream -( - uint32 _bufferSize -): - m_bufferSize( _bufferSize ), - m_signalSize(1), - m_dataSize(0), - m_head(0), - m_tail(0), - m_mutex( new Mutex() ) -{ - m_buffer = new uint8[m_bufferSize]; - memset(m_buffer, 0x00, m_bufferSize); -} + Stream::Stream(uint32 _bufferSize) : + m_bufferSize(_bufferSize), m_signalSize(1), m_dataSize(0), m_head(0), m_tail(0), m_mutex(new Mutex()) + { + m_buffer = new uint8[m_bufferSize]; + memset(m_buffer, 0x00, m_bufferSize); + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -Stream::~Stream -( -) -{ - m_mutex->Release(); - delete [] m_buffer; -} + Stream::~Stream() + { + m_mutex->Release(); + delete[] m_buffer; + } //----------------------------------------------------------------------------- // // Set the amount of data that must be in the buffer for to to be signalled //----------------------------------------------------------------------------- -void Stream::SetSignalThreshold -( - uint32 _size -) -{ - m_signalSize = _size; - if( IsSignalled() ) - { - // We have more data than we are waiting for, so notify the watchers - Notify(); - } -} + void Stream::SetSignalThreshold(uint32 _size) + { + m_signalSize = _size; + if (IsSignalled()) + { + // We have more data than we are waiting for, so notify the watchers + Notify(); + } + } //----------------------------------------------------------------------------- // // Remove data from the buffer //----------------------------------------------------------------------------- -bool Stream::Get -( - uint8* _buffer, - uint32 _size -) -{ - if( m_dataSize < _size ) - { - // There is not enough data in the buffer to fulfill the request - Log::Write( LogLevel_Error, "ERROR: Not enough data in stream buffer"); - return false; - } - - m_mutex->Lock(); - if( (m_tail + _size) > m_bufferSize ) - { - // We will have to wrap around - uint32 block1 = m_bufferSize - m_tail; - uint32 block2 = _size - block1; - - memcpy( _buffer, &m_buffer[m_tail], block1 ); - memcpy( &_buffer[block1], m_buffer, block2 ); - m_tail = block2; - } - else - { - // Requested data is in a contiguous block - memcpy( _buffer, &m_buffer[m_tail], _size ); - m_tail += _size; - } - - LogData( _buffer, _size, " Read (buffer->application): "); - - m_dataSize -= _size; - m_mutex->Unlock(); - return true; -} + bool Stream::Get(uint8* _buffer, uint32 _size) + { + if (m_dataSize < _size) + { + // There is not enough data in the buffer to fulfill the request + Log::Write(LogLevel_Error, "ERROR: Not enough data in stream buffer"); + return false; + } + + m_mutex->Lock(); + if ((m_tail + _size) > m_bufferSize) + { + // We will have to wrap around + uint32 block1 = m_bufferSize - m_tail; + uint32 block2 = _size - block1; + + memcpy(_buffer, &m_buffer[m_tail], block1); + memcpy(&_buffer[block1], m_buffer, block2); + m_tail = block2; + } + else + { + // Requested data is in a contiguous block + memcpy(_buffer, &m_buffer[m_tail], _size); + m_tail += _size; + } + + LogData(_buffer, _size, " Read (buffer->application): "); + + m_dataSize -= _size; + m_mutex->Unlock(); + return true; + } //----------------------------------------------------------------------------- // // Add data to the buffer //----------------------------------------------------------------------------- -bool Stream::Put -( - uint8* _buffer, - uint32 _size -) -{ - if( (m_bufferSize-m_dataSize) < _size ) - { - // There is not enough space left in the buffer for the data - Log::Write( LogLevel_Error, "ERROR: Not enough space in stream buffer"); - return false; - } - - m_mutex->Lock(); - if( (m_head + _size) > m_bufferSize ) - { - // We will have to wrap around - uint32 block1 = m_bufferSize - m_head; - uint32 block2 = _size - block1; - - memcpy( &m_buffer[m_head], _buffer, block1 ); - memcpy( m_buffer, &_buffer[block1], block2 ); - uint8 * logpos = m_buffer + m_head; - m_head = block2; - LogData( logpos, block1, " Read (controller->buffer): "); - LogData( m_buffer, block2, " Read (controller->buffer): "); - } - else - { - // There is enough space before we reach the end of the buffer - memcpy( &m_buffer[m_head], _buffer, _size ); - m_head += _size; - LogData(m_buffer+m_head-_size, _size, " Read (controller->buffer): "); - } - - m_dataSize += _size; - - if( IsSignalled() ) - { - // We now have more data than we are waiting for, so notify the watchers - Notify(); - } - - m_mutex->Unlock(); - return true; -} + bool Stream::Put(uint8* _buffer, uint32 _size) + { + if ((m_bufferSize - m_dataSize) < _size) + { + // There is not enough space left in the buffer for the data + Log::Write(LogLevel_Error, "ERROR: Not enough space in stream buffer"); + return false; + } + + m_mutex->Lock(); + if ((m_head + _size) > m_bufferSize) + { + // We will have to wrap around + uint32 block1 = m_bufferSize - m_head; + uint32 block2 = _size - block1; + + memcpy(&m_buffer[m_head], _buffer, block1); + memcpy(m_buffer, &_buffer[block1], block2); + uint8 * logpos = m_buffer + m_head; + m_head = block2; + LogData(logpos, block1, " Read (controller->buffer): "); + LogData(m_buffer, block2, " Read (controller->buffer): "); + } + else + { + // There is enough space before we reach the end of the buffer + memcpy(&m_buffer[m_head], _buffer, _size); + m_head += _size; + LogData(m_buffer + m_head - _size, _size, " Read (controller->buffer): "); + } + + m_dataSize += _size; + + if (IsSignalled()) + { + // We now have more data than we are waiting for, so notify the watchers + Notify(); + } + + m_mutex->Unlock(); + return true; + } //----------------------------------------------------------------------------- // // Empty the data buffer //----------------------------------------------------------------------------- -void Stream::Purge -( -) -{ - m_tail = 0; - m_head = 0; - m_dataSize = 0; -} + void Stream::Purge() + { + m_tail = 0; + m_head = 0; + m_dataSize = 0; + } //----------------------------------------------------------------------------- // // Test whether there is enough data to be signalled //----------------------------------------------------------------------------- -bool Stream::IsSignalled -( -) -{ - return( m_dataSize >= m_signalSize ); -} + bool Stream::IsSignalled() + { + return (m_dataSize >= m_signalSize); + } //----------------------------------------------------------------------------- // // Format the stream buffer data for log output //----------------------------------------------------------------------------- -void Stream::LogData -( - uint8* _buffer, - uint32 _length, - const string &_function -) -{ - if( !_length ) return; - - string str = ""; - for( uint32 i=0; i<_length; ++i ) - { - if( i ) - { - str += ", "; - } - - char byteStr[8]; - snprintf( byteStr, sizeof(byteStr), "0x%.2x", _buffer[i] ); - str += byteStr; - } - Log::Write( LogLevel_StreamDetail, "%s%s", _function.c_str(), str.c_str() ); -} + void Stream::LogData(uint8* _buffer, uint32 _length, const string &_function) + { + if (!_length) + return; + + string str = ""; + for (uint32 i = 0; i < _length; ++i) + { + if (i) + { + str += ", "; + } + + char byteStr[8]; + snprintf(byteStr, sizeof(byteStr), "0x%.2x", _buffer[i]); + str += byteStr; + } + Log::Write(LogLevel_StreamDetail, "%s%s", _function.c_str(), str.c_str()); + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/Stream.h b/cpp/src/platform/Stream.h index 1e7965d48d..67146309a7 100644 --- a/cpp/src/platform/Stream.h +++ b/cpp/src/platform/Stream.h @@ -35,101 +35,108 @@ namespace OpenZWave { - class Mutex; - - /** \brief Platform-independent definition of a circular buffer. - * \ingroup Platform - */ - class Stream: public Wait + namespace Internal { - friend class Wait; - - public: - /** - * Constructor. - * Creates a cross-platform ring buffer object - */ - Stream( uint32 _bufferSize ); - - /** - * Set the number of bytes the buffer must contain before it becomes signalled. - * Once the threshold is set, the application can use Wait::Single or Wait::Multiple - * to wait until the buffer has been filled with the desired amount of data. - * \param _size the amount of data in bytes that the buffer must contain for it to become signalled. - * \see Wait::Single, Wait::Multiple - */ - void SetSignalThreshold( uint32 _size ); - - - /** - * Copies the requested amount of data from the stream, removing it from the stream as it does so. - * If there is insufficient data available, the method returns false, and no data is transferred. - * \param _buffer pointer to a block of memory that will be filled with the stream data. - * \param _size the amount of data in bytes to copy from the stream. - * \return true if all the requested data has been copied. False if there was not enough data in - * the stream. - * \see GetDataSize, Put - */ - bool Get( uint8* _buffer, uint32 _size ); - - /** - * Copies the requested amount of data from the buffer into the stream. - * If there is insufficient room available in the stream's circular buffer, and no data is transferred. - * \param _buffer pointer to a block of memory that will be copied into the stream. - * \param _size the amount of data in bytes to copy to the stream. - * \return true if all the requested data has been copied. False if there was not enough space in - * the stream's circular buffer. - * \see Get, GetDataSize - */ - bool Put( uint8* _buffer, uint32 _size ); - - /** - * Returns the amount of data in bytes that is stored in the stream. - * \return the number of bytes of data in the stream. - * \see Get, GetDataSize - */ - uint32 GetDataSize()const{ return m_dataSize; } - - /** - * Empties the stream bytes held in the buffer. - * This is called when the library gets out of sync with the controller and sends a "NAK" - * to the controller. - */ - void Purge(); - - protected: - /** - * Formats stream buffer data for output to the log. - * \param _buffer pointer to the stream buffer "head" location - * \param _size number of valid bytes currently in the buffer - * \param _function string containing text to display before the data - */ - void LogData( uint8* _buffer, uint32 _size, const string &_function ); - - /** - * Used by the Wait class to test whether the buffer contains sufficient data. - */ - virtual bool IsSignalled(); - - /** - * Destructor. - * Destroys the ring buffer object. - */ - ~Stream(); - - private: - Stream( Stream const& ); // prevent copy - Stream& operator = ( Stream const& ); // prevent assignment - - uint8* m_buffer; - uint32 m_bufferSize; - uint32 m_signalSize; - uint32 m_dataSize; - uint32 m_head; - uint32 m_tail; - Mutex* m_mutex; - }; - + namespace Platform + { + class Mutex; + + /** \brief Platform-independent definition of a circular buffer. + * \ingroup Platform + */ + class Stream: public Wait + { + friend class Wait; + + public: + /** + * Constructor. + * Creates a cross-platform ring buffer object + */ + Stream(uint32 _bufferSize); + + /** + * Set the number of bytes the buffer must contain before it becomes signalled. + * Once the threshold is set, the application can use Wait::Single or Wait::Multiple + * to wait until the buffer has been filled with the desired amount of data. + * \param _size the amount of data in bytes that the buffer must contain for it to become signalled. + * \see Wait::Single, Wait::Multiple + */ + void SetSignalThreshold(uint32 _size); + + /** + * Copies the requested amount of data from the stream, removing it from the stream as it does so. + * If there is insufficient data available, the method returns false, and no data is transferred. + * \param _buffer pointer to a block of memory that will be filled with the stream data. + * \param _size the amount of data in bytes to copy from the stream. + * \return true if all the requested data has been copied. False if there was not enough data in + * the stream. + * \see GetDataSize, Put + */ + bool Get(uint8* _buffer, uint32 _size); + + /** + * Copies the requested amount of data from the buffer into the stream. + * If there is insufficient room available in the stream's circular buffer, and no data is transferred. + * \param _buffer pointer to a block of memory that will be copied into the stream. + * \param _size the amount of data in bytes to copy to the stream. + * \return true if all the requested data has been copied. False if there was not enough space in + * the stream's circular buffer. + * \see Get, GetDataSize + */ + bool Put(uint8* _buffer, uint32 _size); + + /** + * Returns the amount of data in bytes that is stored in the stream. + * \return the number of bytes of data in the stream. + * \see Get, GetDataSize + */ + uint32 GetDataSize() const + { + return m_dataSize; + } + + /** + * Empties the stream bytes held in the buffer. + * This is called when the library gets out of sync with the controller and sends a "NAK" + * to the controller. + */ + void Purge(); + + protected: + /** + * Formats stream buffer data for output to the log. + * \param _buffer pointer to the stream buffer "head" location + * \param _size number of valid bytes currently in the buffer + * \param _function string containing text to display before the data + */ + void LogData(uint8* _buffer, uint32 _size, const string &_function); + + /** + * Used by the Wait class to test whether the buffer contains sufficient data. + */ + virtual bool IsSignalled(); + + /** + * Destructor. + * Destroys the ring buffer object. + */ + ~Stream(); + + private: + Stream(Stream const&); // prevent copy + Stream& operator =(Stream const&); // prevent assignment + + uint8* m_buffer; + uint32 m_bufferSize; + uint32 m_signalSize; + uint32 m_dataSize; + uint32 m_head; + uint32 m_tail; + Mutex* m_mutex; + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_Event_H diff --git a/cpp/src/platform/Thread.cpp b/cpp/src/platform/Thread.cpp index 45009f7004..dced88a1fb 100644 --- a/cpp/src/platform/Thread.cpp +++ b/cpp/src/platform/Thread.cpp @@ -37,89 +37,79 @@ #include "platform/unix/ThreadImpl.h" // Platform-specific implementation of a thread #endif -using namespace OpenZWave; - +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -Thread::Thread -( - string const& _name -) -{ - m_exitEvent = new Event(); - m_pImpl = new ThreadImpl( this, _name ); -} + Thread::Thread(string const& _name) + { + m_exitEvent = new Event(); + m_pImpl = new ThreadImpl(this, _name); + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -Thread::~Thread -( -) -{ - delete m_pImpl; - m_exitEvent->Release(); -} + Thread::~Thread() + { + delete m_pImpl; + m_exitEvent->Release(); + } //----------------------------------------------------------------------------- // // Start a function running on this thread //----------------------------------------------------------------------------- -bool Thread::Start -( - pfnThreadProc_t _pfnThreadProc, - void* _context -) -{ - return( m_pImpl->Start( _pfnThreadProc, m_exitEvent, _context ) ); -} + bool Thread::Start(pfnThreadProc_t _pfnThreadProc, void* _context) + { + return (m_pImpl->Start(_pfnThreadProc, m_exitEvent, _context)); + } //----------------------------------------------------------------------------- // // Stop a function running on this thread //----------------------------------------------------------------------------- -bool Thread::Stop -( -) -{ - int32 timeout = 2000; // Give the thread 2 seconds to exit - m_exitEvent->Set(); + bool Thread::Stop() + { + int32 timeout = 2000; // Give the thread 2 seconds to exit + m_exitEvent->Set(); - if( Wait::Single( this, timeout ) < 0 ) - { - // Timed out - m_pImpl->Terminate(); - return false; - } + if (Wait::Single(this, timeout) < 0) + { + // Timed out + m_pImpl->Terminate(); + return false; + } - return true; -} + return true; + } //----------------------------------------------------------------------------- // // Causes the thread to sleep for the specified number of milliseconds. //----------------------------------------------------------------------------- -void Thread::Sleep -( - uint32 _milliseconds -) -{ - return( m_pImpl->Sleep( _milliseconds ) ); -} + void Thread::Sleep(uint32 _milliseconds) + { + return (m_pImpl->Sleep(_milliseconds)); + } //----------------------------------------------------------------------------- // // Test whether the event is set //----------------------------------------------------------------------------- -bool Thread::IsSignalled -( -) -{ - return m_pImpl->IsSignalled(); -} - + bool Thread::IsSignalled() + { + return m_pImpl->IsSignalled(); + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/Thread.h b/cpp/src/platform/Thread.h index 5213b3d438..66033d45ab 100644 --- a/cpp/src/platform/Thread.h +++ b/cpp/src/platform/Thread.h @@ -34,68 +34,73 @@ namespace OpenZWave { - class ThreadImpl; - class Event; - - /** \brief Implements a platform-independent thread management class. - * \ingroup Platform - */ - class Thread: public Wait + namespace Internal { - public: - typedef void (*pfnThreadProc_t)( Event* _exitEvent, void* _context ); + namespace Platform + { + class ThreadImpl; + class Event; - /** - * Constructor. - * Creates a thread object that can be used to serialize access to a shared resource. - */ - Thread( string const& _name ); + /** \brief Implements a platform-independent thread management class. + * \ingroup Platform + */ + class Thread: public Wait + { + public: + typedef void (*pfnThreadProc_t)(Event* _exitEvent, void* _context); - /** - * Start running a function on this thread. - * Attempts to start a function running on this thread. The call will fail if another - * function is already running. - * \param _pThreadProc pointer to the function to be run. The function must take a - * single void pointer as its only argument, and return void. On entry, the pointer - * will be set to the context provided to this Start method. - * \param _context pointer allowing any relevant data to be passed to the thread function. - * \return True if the function was successfully started. - * \see Stop, IsRunning - */ - bool Start( pfnThreadProc_t _pfnThreadProc, void* _context ); + /** + * Constructor. + * Creates a thread object that can be used to serialize access to a shared resource. + */ + Thread(string const& _name); - /** - * Stop a function running on this thread. - * Attempts to stop a function running on this thread. The call will fail if no - * function is running. - * \return True if the function was successfully stopped. - * \see Start, IsRunning - */ - bool Stop(); + /** + * Start running a function on this thread. + * Attempts to start a function running on this thread. The call will fail if another + * function is already running. + * \param _pThreadProc pointer to the function to be run. The function must take a + * single void pointer as its only argument, and return void. On entry, the pointer + * will be set to the context provided to this Start method. + * \param _context pointer allowing any relevant data to be passed to the thread function. + * \return True if the function was successfully started. + * \see Stop, IsRunning + */ + bool Start(pfnThreadProc_t _pfnThreadProc, void* _context); - /** - * Causes the thread to sleep for the specified number of milliseconds. - * \param _millisecs Number of milliseconds to sleep. - */ - void Sleep( uint32 _millisecs ); + /** + * Stop a function running on this thread. + * Attempts to stop a function running on this thread. The call will fail if no + * function is running. + * \return True if the function was successfully stopped. + * \see Start, IsRunning + */ + bool Stop(); - protected: - /** - * Used by the Wait class to test whether the thread has been completed. - */ - virtual bool IsSignalled(); + /** + * Causes the thread to sleep for the specified number of milliseconds. + * \param _millisecs Number of milliseconds to sleep. + */ + void Sleep(uint32 _millisecs); - /** - * Destructor. - * Destroys the Thread object. - */ - virtual ~Thread(); + protected: + /** + * Used by the Wait class to test whether the thread has been completed. + */ + virtual bool IsSignalled(); - private: - ThreadImpl* m_pImpl; // Pointer to an object that encapsulates the platform-specific implementation of a thread. - Event* m_exitEvent; - }; + /** + * Destructor. + * Destroys the Thread object. + */ + virtual ~Thread(); + private: + ThreadImpl* m_pImpl; // Pointer to an object that encapsulates the platform-specific implementation of a thread. + Event* m_exitEvent; + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_Thread_H diff --git a/cpp/src/platform/TimeStamp.cpp b/cpp/src/platform/TimeStamp.cpp index 5937aa5fdb..80aaf88e6d 100644 --- a/cpp/src/platform/TimeStamp.cpp +++ b/cpp/src/platform/TimeStamp.cpp @@ -37,72 +37,67 @@ #include "platform/unix/TimeStampImpl.h" // Platform-specific implementation of a TimeStamp #endif -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -TimeStamp::TimeStamp -( -): - m_pImpl( new TimeStampImpl() ) -{ -} + TimeStamp::TimeStamp() : + m_pImpl(new TimeStampImpl()) + { + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -TimeStamp::~TimeStamp -( -) -{ - delete m_pImpl; -} + TimeStamp::~TimeStamp() + { + delete m_pImpl; + } //----------------------------------------------------------------------------- // // Sets the timestamp to now, plus an offset in milliseconds //----------------------------------------------------------------------------- -void TimeStamp::SetTime -( - int32 _milliseconds // = 0 -) -{ - m_pImpl->SetTime( _milliseconds ); -} + void TimeStamp::SetTime(int32 _milliseconds // = 0 + ) + { + m_pImpl->SetTime(_milliseconds); + } //----------------------------------------------------------------------------- // // Gets the difference between now and the timestamp time in milliseconds //----------------------------------------------------------------------------- -int32 TimeStamp::TimeRemaining -( -) -{ - return m_pImpl->TimeRemaining(); -} + int32 TimeStamp::TimeRemaining() + { + return m_pImpl->TimeRemaining(); + } //----------------------------------------------------------------------------- // // Return object as a string //----------------------------------------------------------------------------- -string TimeStamp::GetAsString -( -) -{ - return m_pImpl->GetAsString(); -} + std::string TimeStamp::GetAsString() + { + return m_pImpl->GetAsString(); + } //----------------------------------------------------------------------------- // // Overload the subtract operator to get the difference between two // timestamps in milliseconds //----------------------------------------------------------------------------- -int32 TimeStamp::operator- -( - TimeStamp const& _other -) -{ - return (int32)(m_pImpl - _other.m_pImpl); -} + int32 TimeStamp::operator-(TimeStamp const& _other) + { + return (int32) (m_pImpl - _other.m_pImpl); + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/TimeStamp.h b/cpp/src/platform/TimeStamp.h index ea8138d0d6..d5ffd57cc9 100644 --- a/cpp/src/platform/TimeStamp.h +++ b/cpp/src/platform/TimeStamp.h @@ -32,60 +32,65 @@ namespace OpenZWave { - class TimeStampImpl; - - /** \brief Implements a platform-independent TimeStamp. - * \ingroup Platform - */ - class OPENZWAVE_EXPORT TimeStamp + namespace Internal { - public: - /** - * Constructor. - * Creates a TimeStamp object. - */ - TimeStamp(); + namespace Platform + { + class TimeStampImpl; - /** - * Destructor. - * Destroys the TimeStamp object. - */ - ~TimeStamp(); + /** \brief Implements a platform-independent TimeStamp. + * \ingroup Platform + */ + class OPENZWAVE_EXPORT TimeStamp + { + public: + /** + * Constructor. + * Creates a TimeStamp object. + */ + TimeStamp(); - /** - * SetTime. Sets the timestamp to now, plus the offset in milliseconds. - * \param _milliseconds optional positive or negative offset from - * now in milliseconds. Defaults to zero. - */ - void SetTime( int32 _milliseconds = 0 ); + /** + * Destructor. + * Destroys the TimeStamp object. + */ + ~TimeStamp(); - /** - * TimeRemaining. Gets the difference between now and the timestamp - * time in milliseconds. - * \return milliseconds remaining until we reach the timestamp. The - * return value is negative if the timestamp is in the past. - */ - int32 TimeRemaining(); + /** + * SetTime. Sets the timestamp to now, plus the offset in milliseconds. + * \param _milliseconds optional positive or negative offset from + * now in milliseconds. Defaults to zero. + */ + void SetTime(int32 _milliseconds = 0); - /** - * Return as a string for output. - * \return string - */ - string GetAsString(); + /** + * TimeRemaining. Gets the difference between now and the timestamp + * time in milliseconds. + * \return milliseconds remaining until we reach the timestamp. The + * return value is negative if the timestamp is in the past. + */ + int32 TimeRemaining(); - /** - * Overload the subtract operator to get the difference between - * two timestamps in milliseconds. - */ - int32 operator- ( TimeStamp const& _other ); + /** + * Return as a string for output. + * \return string + */ + string GetAsString(); - private: - TimeStamp( TimeStamp const& ); // prevent copy - TimeStamp& operator = ( TimeStamp const& ); // prevent assignment + /** + * Overload the subtract operator to get the difference between + * two timestamps in milliseconds. + */ + int32 operator-(TimeStamp const& _other); - TimeStampImpl* m_pImpl; // Pointer to an object that encapsulates the platform-specific implementation of the TimeStamp. - }; + private: + TimeStamp(TimeStamp const&); // prevent copy + TimeStamp& operator =(TimeStamp const&); // prevent assignment + TimeStampImpl* m_pImpl; // Pointer to an object that encapsulates the platform-specific implementation of the TimeStamp. + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_TimeStamp_H diff --git a/cpp/src/platform/Wait.cpp b/cpp/src/platform/Wait.cpp index c4233a8c49..aebb7ed317 100644 --- a/cpp/src/platform/Wait.cpp +++ b/cpp/src/platform/Wait.cpp @@ -39,147 +39,132 @@ #include "platform/unix/WaitImpl.h" // Platform-specific implementation of a Wait object #endif -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { -void WaitMultipleCallback( void* _context ); + void WaitMultipleCallback(void* _context); //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -Wait::Wait -( -) -{ - m_pImpl = new WaitImpl( this ); -} + Wait::Wait() + { + m_pImpl = new WaitImpl(this); + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -Wait::~Wait -( -) -{ - delete m_pImpl; -} + Wait::~Wait() + { + delete m_pImpl; + } //----------------------------------------------------------------------------- // // Add a watcher to our object. //----------------------------------------------------------------------------- -void Wait::AddWatcher -( - pfnWaitNotification_t _callback, - void* _context -) -{ - if( !_callback ) - { - assert(0); - return; - } + void Wait::AddWatcher(pfnWaitNotification_t _callback, void* _context) + { + if (!_callback) + { + assert(0); + return; + } - // Add a ref so our object cannot disappear while being watched - AddRef(); + // Add a ref so our object cannot disappear while being watched + AddRef(); - // Add the watcher (platform specific code required here for thread safety) - m_pImpl->AddWatcher( _callback, _context ); -} + // Add the watcher (platform specific code required here for thread safety) + m_pImpl->AddWatcher(_callback, _context); + } //----------------------------------------------------------------------------- // // Remove a watcher from our object. //----------------------------------------------------------------------------- -void Wait::RemoveWatcher -( - pfnWaitNotification_t _callback, - void* _context -) -{ - if( m_pImpl->RemoveWatcher( _callback, _context ) ) - { - Release(); - } -} + void Wait::RemoveWatcher(pfnWaitNotification_t _callback, void* _context) + { + if (m_pImpl->RemoveWatcher(_callback, _context)) + { + Release(); + } + } //----------------------------------------------------------------------------- // // Notify all the watchers that the object has become signalled //----------------------------------------------------------------------------- -void Wait::Notify -( -) -{ - m_pImpl->Notify(); -} + void Wait::Notify() + { + m_pImpl->Notify(); + } //----------------------------------------------------------------------------- // // Wait for one of multiple objects to become signalled. //----------------------------------------------------------------------------- -int32 Wait::Multiple -( - Wait** _objects, - uint32 _numObjects, - int32 _timeout // = -1 -) -{ - uint32 i; + int32 Wait::Multiple(Wait** _objects, uint32 _numObjects, int32 _timeout // = -1 + ) + { + uint32 i; - // Create an event that will be set when any of the objects in the list becomes signalled. - Event* waitEvent = new Event(); + // Create an event that will be set when any of the objects in the list becomes signalled. + Event* waitEvent = new Event(); - // Add a watcher to each object in the list, passing in the event as the context. - for( i=0; i<_numObjects; ++i ) - { + // Add a watcher to each object in the list, passing in the event as the context. + for (i = 0; i < _numObjects; ++i) + { // Log::Write( LogLevel_Info, "Wait::Multiple - Object %p %d", _objects[i], _objects[i]->IsSignalled()); - _objects[i]->AddWatcher( WaitMultipleCallback, waitEvent ); - } - - int32 res = -1; // Default to timeout result - string str = ""; - if( waitEvent->Wait( _timeout ) ) - { - // An object was signalled. Run through the list - // and see which one it was. - for( i=0; i<_numObjects; ++i ) - { - if( _objects[i]->IsSignalled() ) - { - if( res == -1 ) - res = (int32)i; - char buf[15]; - snprintf(buf, sizeof(buf), "%d, ", i); - str += buf; - } - } - } + _objects[i]->AddWatcher(WaitMultipleCallback, waitEvent); + } + + int32 res = -1; // Default to timeout result + string str = ""; + if (waitEvent->Wait(_timeout)) + { + // An object was signalled. Run through the list + // and see which one it was. + for (i = 0; i < _numObjects; ++i) + { + if (_objects[i]->IsSignalled()) + { + if (res == -1) + res = (int32) i; + char buf[15]; + snprintf(buf, sizeof(buf), "%d, ", i); + str += buf; + } + } + } // Log::Write( LogLevel_Debug, "Wait::Multiple res=%d num=%d >%s", res, _numObjects, str.c_str() ); - // Remove the watchers - for( i=0; i<_numObjects; ++i ) - { - _objects[i]->RemoveWatcher( WaitMultipleCallback, waitEvent ); - } - - // We're done with the event now - waitEvent->Release(); - return res; -} + // Remove the watchers + for (i = 0; i < _numObjects; ++i) + { + _objects[i]->RemoveWatcher(WaitMultipleCallback, waitEvent); + } + // We're done with the event now + waitEvent->Release(); + return res; + } //----------------------------------------------------------------------------- // // Callback handler for the watchers added during WaitImpl::Multiple //----------------------------------------------------------------------------- -void WaitMultipleCallback -( - void* _context -) -{ - Event* waitEvent = (Event*)_context; - waitEvent->Set(); -} - + void WaitMultipleCallback(void* _context) + { + Event* waitEvent = (Event*) _context; + waitEvent->Set(); + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/Wait.h b/cpp/src/platform/Wait.h index 1b3bfec806..ce9fb2638a 100644 --- a/cpp/src/platform/Wait.h +++ b/cpp/src/platform/Wait.h @@ -34,80 +34,88 @@ namespace OpenZWave { - class WaitImpl; - - /** \brief Platform-independent definition of Wait objects. - * \ingroup Platform - */ - class Wait: public Ref + namespace Internal { - friend class WaitImpl; - friend class ThreadImpl; - - public: - enum + namespace Platform { - Timeout_Immediate = 0, - Timeout_Infinite = -1 - }; - - typedef void (*pfnWaitNotification_t)( void* _context ); - - /** - * Add a watcher to our object. The watcher will be triggered - * by the derived class, when it enters a certain state. - * \param _callback pointer to the function that will be called when the wait is over. - * \param _context pointer to custom data that will be sent with the callback. - */ - void AddWatcher( pfnWaitNotification_t _callback, void* _context ); - - /** - * Remove a watcher from our object. Both the _callback and _context pointers - * must match those used in a previous call to AddWatcher. - * \param _callback pointer to the function that will be called when the wait is over. - * \param _context pointer to custom data that will be sent with the callback. - */ - void RemoveWatcher( pfnWaitNotification_t _callback, void* _context ); - - /** - * Wait for a single object to become signalled. - * \param _object pointer to the object to wait on. - * \param _timeout optional maximum time to wait. Defaults to -1, which means wait forever. - * \return zero if the object was signalled, -1 if the wait timed out. - */ - static int32 Single( Wait* _object, int32 _timeout = -1 ){ return Multiple( &_object, 1, _timeout ); } - - /** - * Wait for one of multiple objects to become signalled. If more than one object is in - * a signalled state, the lowest array index will be returned. - * \param _objects array of pointers to objects to wait on. - * \param _numObjects number of objects in the array. - * \param _timeout optional maximum time to wait. Defaults to -1, which means wait forever. - * \return index into the array of the object that was signalled, -1 if the wait timed out. - */ - static int32 Multiple( Wait** _objects, uint32 _numObjects, int32 _timeout = -1 ); - - protected: - Wait(); - virtual ~Wait(); - - /** - * Notify the watchers that the object is signalled. - */ - void Notify(); - - /** - * Test whether an object is signalled. - */ - virtual bool IsSignalled() = 0; - - private: - Wait( Wait const& ); // prevent copy - Wait& operator = ( Wait const& ); // prevent assignment - - WaitImpl* m_pImpl; // Pointer to an object that encapsulates the platform-specific implementation of a Wait object. - }; - + class WaitImpl; + + /** \brief Platform-independent definition of Wait objects. + * \ingroup Platform + */ + class Wait: public Ref + { + friend class WaitImpl; + friend class ThreadImpl; + + public: + enum + { + Timeout_Immediate = 0, + Timeout_Infinite = -1 + }; + + typedef void (*pfnWaitNotification_t)(void* _context); + + /** + * Add a watcher to our object. The watcher will be triggered + * by the derived class, when it enters a certain state. + * \param _callback pointer to the function that will be called when the wait is over. + * \param _context pointer to custom data that will be sent with the callback. + */ + void AddWatcher(pfnWaitNotification_t _callback, void* _context); + + /** + * Remove a watcher from our object. Both the _callback and _context pointers + * must match those used in a previous call to AddWatcher. + * \param _callback pointer to the function that will be called when the wait is over. + * \param _context pointer to custom data that will be sent with the callback. + */ + void RemoveWatcher(pfnWaitNotification_t _callback, void* _context); + + /** + * Wait for a single object to become signalled. + * \param _object pointer to the object to wait on. + * \param _timeout optional maximum time to wait. Defaults to -1, which means wait forever. + * \return zero if the object was signalled, -1 if the wait timed out. + */ + static int32 Single(Wait* _object, int32 _timeout = -1) + { + return Multiple(&_object, 1, _timeout); + } + + /** + * Wait for one of multiple objects to become signalled. If more than one object is in + * a signalled state, the lowest array index will be returned. + * \param _objects array of pointers to objects to wait on. + * \param _numObjects number of objects in the array. + * \param _timeout optional maximum time to wait. Defaults to -1, which means wait forever. + * \return index into the array of the object that was signalled, -1 if the wait timed out. + */ + static int32 Multiple(Wait** _objects, uint32 _numObjects, int32 _timeout = -1); + + protected: + Wait(); + virtual ~Wait(); + + /** + * Notify the watchers that the object is signalled. + */ + void Notify(); + + /** + * Test whether an object is signalled. + */ + virtual bool IsSignalled() = 0; + + private: + Wait(Wait const&); // prevent copy + Wait& operator =(Wait const&); // prevent assignment + + WaitImpl* m_pImpl; // Pointer to an object that encapsulates the platform-specific implementation of a Wait object. + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_Wait_H diff --git a/cpp/src/platform/unix/DNSImpl.cpp b/cpp/src/platform/unix/DNSImpl.cpp index 96128bd728..534b5da808 100644 --- a/cpp/src/platform/unix/DNSImpl.cpp +++ b/cpp/src/platform/unix/DNSImpl.cpp @@ -33,94 +33,94 @@ #include "DNSImpl.h" - - -using namespace OpenZWave; - -DNSImpl::DNSImpl -( -) -{ - res_init(); -} - -DNSImpl::~DNSImpl -( -) +namespace OpenZWave { + namespace Internal + { + namespace Platform + { -} + DNSImpl::DNSImpl() : + status(DNSError_None) + { + res_init(); + } -bool DNSImpl::LookupTxT -( -string lookup, -string &result -) -{ + DNSImpl::~DNSImpl() + { + } - int response; - unsigned char query_buffer[1024]; - ns_msg nsMsg; - ns_rr rr; - const unsigned char *p, *start; - unsigned char l; - int rrlen; + bool DNSImpl::LookupTxT(string lookup, string &result) + { - char outb[1025]; + int response; + unsigned char query_buffer[1024]; + ns_msg nsMsg; + ns_rr rr; + const unsigned char *p, *start; + unsigned char l; + int rrlen; + char outb[1025]; #ifdef __APPLE_CC__ - response= res_query(lookup.c_str(), ns_c_in, ns_t_txt, query_buffer, sizeof(query_buffer)); + response = res_query(lookup.c_str(), ns_c_in, ns_t_txt, query_buffer, sizeof(query_buffer)); #else - response= res_query(lookup.c_str(), C_IN, ns_t_txt, query_buffer, sizeof(query_buffer)); + response= res_query(lookup.c_str(), C_IN, ns_t_txt, query_buffer, sizeof(query_buffer)); #endif - if (response < 0) { - Log::Write(LogLevel_Warning, "Error looking up txt Record: %s - %s", lookup.c_str(), hstrerror(h_errno)); - switch (h_errno) { - case HOST_NOT_FOUND: - status = DNSError_NotFound; - break; - case NO_DATA: - status = DNSError_NotFound; - break; - case NO_RECOVERY: - status = DNSError_InternalError; - break; - case TRY_AGAIN: - status = DNSError_InternalError; - break; - default: - status = DNSError_InternalError; - break; - - } - return false; - } - - ns_initparse(query_buffer, response, &nsMsg); - - ns_parserr(&nsMsg, ns_s_an, 0, &rr); - - p = start = ns_rr_rdata(rr); - rrlen = ns_rr_rdlen(rr); - if (rrlen > 1024) { - status = DNSError_InternalError; - return false; - } - while(p < start + rrlen) - { - l = *p; - p++; - if(p + l > start + rrlen) - { - break; - } - memcpy(outb, p, l); - outb[l] = 0; - p += l; - } - result = outb; - status = DNSError_None; - return true; -} + if (response < 0) + { + Log::Write(LogLevel_Warning, "Error looking up txt Record: %s - %s", lookup.c_str(), hstrerror(h_errno)); + switch (h_errno) + { + case HOST_NOT_FOUND: + status = DNSError_NotFound; + break; + case NO_DATA: + status = DNSError_NotFound; + break; + case NO_RECOVERY: + status = DNSError_InternalError; + break; + case TRY_AGAIN: + status = DNSError_InternalError; + break; + default: + status = DNSError_InternalError; + break; + + } + return false; + } + + ns_initparse(query_buffer, response, &nsMsg); + + ns_parserr(&nsMsg, ns_s_an, 0, &rr); + + p = start = ns_rr_rdata(rr); + rrlen = ns_rr_rdlen(rr); + if (rrlen > 1024) + { + status = DNSError_InternalError; + return false; + } + while (p < start + rrlen) + { + l = *p; + p++; + if (p + l > start + rrlen) + { + break; + } + memcpy(outb, p, l); + outb[l] = 0; + p += l; + } + result = outb; + status = DNSError_None; + return true; + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/unix/DNSImpl.h b/cpp/src/platform/unix/DNSImpl.h index f94b2361a8..ae7f2ae60e 100644 --- a/cpp/src/platform/unix/DNSImpl.h +++ b/cpp/src/platform/unix/DNSImpl.h @@ -33,14 +33,20 @@ namespace OpenZWave { - class DNSImpl { - public: - DNSImpl(); - virtual ~DNSImpl(); - virtual bool LookupTxT(string, string &); - DNSError status; - private: - - }; -} + namespace Internal + { + namespace Platform + { + class DNSImpl + { + public: + DNSImpl(); + virtual ~DNSImpl(); + virtual bool LookupTxT(string, string &); + DNSError status; + private: + }; + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave #endif diff --git a/cpp/src/platform/unix/EventImpl.cpp b/cpp/src/platform/unix/EventImpl.cpp index 6b8f94830b..86952ca874 100644 --- a/cpp/src/platform/unix/EventImpl.cpp +++ b/cpp/src/platform/unix/EventImpl.cpp @@ -31,234 +31,226 @@ #include #include -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -EventImpl::EventImpl -( -): - m_manualReset( true ), - m_isSignaled( false ), - m_waitingThreads( 0 ) -{ - pthread_mutexattr_t ma; - pthread_mutexattr_init( &ma ); - pthread_mutexattr_settype( &ma, PTHREAD_MUTEX_ERRORCHECK ); - pthread_mutex_init( &m_lock, &ma ); - pthread_mutexattr_destroy( &ma ); - - pthread_condattr_t ca; - pthread_condattr_init( &ca ); + EventImpl::EventImpl() : + m_manualReset(true), m_isSignaled(false), m_waitingThreads(0) + { + pthread_mutexattr_t ma; + pthread_mutexattr_init(&ma); + pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK); + pthread_mutex_init(&m_lock, &ma); + pthread_mutexattr_destroy(&ma); + + pthread_condattr_t ca; + pthread_condattr_init(&ca); #ifndef __NetBSD__ - pthread_condattr_setpshared( &ca, PTHREAD_PROCESS_PRIVATE ); + pthread_condattr_setpshared(&ca, PTHREAD_PROCESS_PRIVATE); #endif - pthread_cond_init( &m_condition, &ca ); - pthread_condattr_destroy( &ca ); -} + pthread_cond_init(&m_condition, &ca); + pthread_condattr_destroy(&ca); + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -EventImpl::~EventImpl -( -) -{ - pthread_mutex_destroy( &m_lock ); - pthread_cond_destroy( &m_condition ); -} + EventImpl::~EventImpl() + { + pthread_mutex_destroy(&m_lock); + pthread_cond_destroy(&m_condition); + } //----------------------------------------------------------------------------- // // Set the event to signalled //----------------------------------------------------------------------------- -void EventImpl::Set -( -) -{ - int err = pthread_mutex_lock( &m_lock ); - if( err != 0 ) - { - fprintf(stderr, "EventImpl::Set lock error %d (%d)\n", errno, err ); - assert( 0 ); - } - if( m_manualReset ) - { - m_isSignaled = true; - err = pthread_cond_broadcast( &m_condition ); - if( err != 0 ) - { - fprintf(stderr, "EventImpl::Set cond broadcast error %d (%d)\n", errno, err ); - assert( 0 ); - } - } - else - { - if( !m_waitingThreads ) - { - m_isSignaled = true; - } - else - { - err = pthread_cond_signal( &m_condition ); - if( err != 0 ) + void EventImpl::Set() { - fprintf(stderr, "EventImpl::Set cond signal error %d (%d)\n", errno, err ); - assert( 0 ); + int err = pthread_mutex_lock(&m_lock); + if (err != 0) + { + fprintf(stderr, "EventImpl::Set lock error %d (%d)\n", errno, err); + assert(0); + } + if (m_manualReset) + { + m_isSignaled = true; + err = pthread_cond_broadcast(&m_condition); + if (err != 0) + { + fprintf(stderr, "EventImpl::Set cond broadcast error %d (%d)\n", errno, err); + assert(0); + } + } + else + { + if (!m_waitingThreads) + { + m_isSignaled = true; + } + else + { + err = pthread_cond_signal(&m_condition); + if (err != 0) + { + fprintf(stderr, "EventImpl::Set cond signal error %d (%d)\n", errno, err); + assert(0); + } + } + } + err = pthread_mutex_unlock(&m_lock); + if (err != 0) + { + fprintf(stderr, "EventImpl::Set unlock error %d (%d)\n", errno, err); + assert(0); + } } - } - } - err = pthread_mutex_unlock( &m_lock ); - if( err != 0 ) - { - fprintf(stderr, "EventImpl::Set unlock error %d (%d)\n", errno, err ); - assert( 0 ); - } -} //----------------------------------------------------------------------------- // // Set the event to not signalled //----------------------------------------------------------------------------- -void EventImpl::Reset -( -) -{ - int err = pthread_mutex_lock ( &m_lock ); - if( err != 0 ) - { - fprintf(stderr, "EventImpl::Reset lock error %d (%d)\n", errno, err ); - assert( 0 ); - } - m_isSignaled = false; - err = pthread_mutex_unlock( &m_lock ); - if( err != 0 ) - { - fprintf(stderr, "EventImpl::Reset unlock error %d (%d)\n", errno, err ); - assert( 0 ); - } -} + void EventImpl::Reset() + { + int err = pthread_mutex_lock(&m_lock); + if (err != 0) + { + fprintf(stderr, "EventImpl::Reset lock error %d (%d)\n", errno, err); + assert(0); + } + m_isSignaled = false; + err = pthread_mutex_unlock(&m_lock); + if (err != 0) + { + fprintf(stderr, "EventImpl::Reset unlock error %d (%d)\n", errno, err); + assert(0); + } + } //----------------------------------------------------------------------------- // // Test whether the event is set //----------------------------------------------------------------------------- -bool EventImpl::IsSignalled -( -) -{ - return m_isSignaled; -} + bool EventImpl::IsSignalled() + { + return m_isSignaled; + } //----------------------------------------------------------------------------- // // Wait for the event to become signalled //----------------------------------------------------------------------------- -bool EventImpl::Wait -( - int32 const _timeout /* milliseconds */ -) -{ - bool result = true; + bool EventImpl::Wait(int32 const _timeout /* milliseconds */ + ) + { + bool result = true; - int err = pthread_mutex_lock( &m_lock ); - if( err != 0 ) - { - fprintf(stderr, "EventImpl::Wait lock error %d (%d)\n", errno, err ); - assert( 0 ); - } - if( m_isSignaled ) - { - if ( !m_manualReset ) - { - m_isSignaled = false; - } - } - else - { - ++m_waitingThreads; - if( _timeout == 0 ) - { - result = m_isSignaled; - } - else if( _timeout > 0 ) - { - struct timeval now; - struct timespec abstime; + int err = pthread_mutex_lock(&m_lock); + if (err != 0) + { + fprintf(stderr, "EventImpl::Wait lock error %d (%d)\n", errno, err); + assert(0); + } + if (m_isSignaled) + { + if (!m_manualReset) + { + m_isSignaled = false; + } + } + else + { + ++m_waitingThreads; + if (_timeout == 0) + { + result = m_isSignaled; + } + else if (_timeout > 0) + { + struct timeval now; + struct timespec abstime; - gettimeofday(&now, NULL); - - abstime.tv_sec = now.tv_sec + (_timeout / 1000); + gettimeofday(&now, NULL); - // Now add the remainder of our timeout to the microseconds part of 'now' - now.tv_usec += (_timeout % 1000) * 1000; + abstime.tv_sec = now.tv_sec + (_timeout / 1000); - // Careful now! Did it wrap? - while( now.tv_usec >= ( 1000 * 1000 ) ) - { - // Yes it did so bump our seconds and subtract - now.tv_usec -= (1000 * 1000); - abstime.tv_sec++; - } - - abstime.tv_nsec = now.tv_usec * 1000; - - while( !m_isSignaled ) - { - int oldstate; - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); + // Now add the remainder of our timeout to the microseconds part of 'now' + now.tv_usec += (_timeout % 1000) * 1000; - err = pthread_cond_timedwait( &m_condition, &m_lock, &abstime ); + // Careful now! Did it wrap? + while (now.tv_usec >= (1000 * 1000)) + { + // Yes it did so bump our seconds and subtract + now.tv_usec -= (1000 * 1000); + abstime.tv_sec++; + } - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); + abstime.tv_nsec = now.tv_usec * 1000; - if( err == ETIMEDOUT ) - { - result = false; - break; - } - else - if( err == 0 ) - { - result = true; + while (!m_isSignaled) + { + int oldstate; + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); + + err = pthread_cond_timedwait(&m_condition, &m_lock, &abstime); + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); + + if (err == ETIMEDOUT) + { + result = false; + break; + } + else if (err == 0) + { + result = true; + } + else + { + fprintf(stderr, "EventImpl::Wait cond timedwait error %d (%d)\n", errno, err); + assert(0); + } + } } else { - fprintf(stderr, "EventImpl::Wait cond timedwait error %d (%d)\n", errno, err ); - assert( 0 ); - } - } - } - else - { - while( !m_isSignaled ) - { - int oldstate; - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); + while (!m_isSignaled) + { + int oldstate; + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); + + err = pthread_cond_wait(&m_condition, &m_lock); - err = pthread_cond_wait( &m_condition, &m_lock ); + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); + if (err != 0) + { + fprintf(stderr, "EventImpl::Wait cond wait error %d (%d)\n", errno, err); + assert(0); + } + } + } + --m_waitingThreads; + } - if( err != 0 ) + err = pthread_mutex_unlock(&m_lock); + if (err != 0) { - fprintf(stderr, "EventImpl::Wait cond wait error %d (%d)\n", errno, err ); - assert( 0 ); + fprintf(stderr, "EventImpl::Wait unlock error %d (%d)\n", errno, err); + assert(0); } + return result; } - } - --m_waitingThreads; - } - - err = pthread_mutex_unlock( &m_lock ); - if( err != 0 ) - { - fprintf(stderr, "EventImpl::Wait unlock error %d (%d)\n", errno, err ); - assert( 0 ); - } - return result; -} - + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/unix/EventImpl.h b/cpp/src/platform/unix/EventImpl.h index 4fb6ce5ef0..634d3a7be6 100644 --- a/cpp/src/platform/unix/EventImpl.h +++ b/cpp/src/platform/unix/EventImpl.h @@ -33,29 +33,35 @@ namespace OpenZWave { - class EventImpl + namespace Internal { - private: - friend class Event; - friend class SocketImpl; - friend class Wait; - - EventImpl(); - ~EventImpl(); - - void Set(); - void Reset(); - - bool Wait( int32 _timeout ); // The wait method is to be used only by the Wait::Multiple method - bool IsSignalled(); - - pthread_mutex_t m_lock; - pthread_cond_t m_condition; - bool m_manualReset; - bool m_isSignaled; - unsigned int m_waitingThreads; - }; + namespace Platform + { + class EventImpl + { + private: + friend class Event; + friend class SocketImpl; + friend class Wait; + + EventImpl(); + ~EventImpl(); + + void Set(); + void Reset(); + + bool Wait(int32 _timeout); // The wait method is to be used only by the Wait::Multiple method + bool IsSignalled(); + + pthread_mutex_t m_lock; + pthread_cond_t m_condition; + bool m_manualReset; + bool m_isSignaled; + unsigned int m_waitingThreads; + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_EventImpl_H diff --git a/cpp/src/platform/unix/FileOpsImpl.cpp b/cpp/src/platform/unix/FileOpsImpl.cpp index 4d8d849c92..fad9a0283d 100644 --- a/cpp/src/platform/unix/FileOpsImpl.cpp +++ b/cpp/src/platform/unix/FileOpsImpl.cpp @@ -39,151 +39,142 @@ #include "FileOpsImpl.h" #include "Utils.h" -using namespace OpenZWave; -using std::ios_base; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { + using std::ios_base; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -FileOpsImpl::FileOpsImpl -( -) -{ -} + FileOpsImpl::FileOpsImpl() + { + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -FileOpsImpl::~FileOpsImpl -( -) -{ -} + FileOpsImpl::~FileOpsImpl() + { + } //----------------------------------------------------------------------------- // // Determine if a folder exists //----------------------------------------------------------------------------- -bool FileOpsImpl::FolderExists -( - const string _folderName -) -{ - DIR *dirp = opendir( _folderName.c_str() ); - if( dirp != NULL ) - { - closedir( dirp ); - return true; - } - else - return false; -} - -bool FileOpsImpl::FileExists -( - const string _filename -) -{ - struct stat buffer; - return (stat (_filename.c_str(), &buffer) == 0); -} - -bool FileOpsImpl::FileWriteable -( - const string _filename -) -{ - if (!FileExists(_filename)) { - string fn = ozwdirname(_filename); - return (access(fn.c_str(), W_OK|F_OK) == 0); - } - - return (access(_filename.c_str(), W_OK|F_OK) == 0); - -} - -bool FileOpsImpl::FileRotate -( - const string _filename -) -{ - int i = 1; - string newFile; - /* find a filename not used yet */ - newFile = _filename; - newFile.append(".").append(intToString(i)); - while (FileExists(newFile)) { - i++; - newFile = _filename; - newFile.append(".").append(intToString(i)); - } - /* copy the file */ - if (!FileCopy(_filename, newFile)) { - Log::Write(LogLevel_Warning, "File Rotate Failed: %s -> %s", _filename.c_str(), newFile.c_str()); - return false; - } - - /* remove the old file */ - if ( remove(_filename.c_str())) { - Log::Write(LogLevel_Warning, "File Removal failed: %s", _filename.c_str()); - return false; - } - return true; -} - - -bool FileOpsImpl::FileCopy -( - const string _sourcefile, - const string _destfile -) -{ - - if (!FileExists(_sourcefile)) { - Log::Write(LogLevel_Warning, "Source File %s doesn't exist in FileCopy", _sourcefile.c_str()); - return false; - } - if (FileExists(_destfile)) { - Log::Write(LogLevel_Warning, "Destination File %s exists in FileCopy", _destfile.c_str()); - return false; - } - - /* make sure the Destination Folder Exists */ - if (!FolderExists(ozwdirname(_destfile))) { - Log::Write(LogLevel_Warning, "Destination Folder %s Doesn't Exist", ozwdirname(_destfile).c_str()); - return false; - } - - - std::ifstream in(_sourcefile.c_str(), ios_base::in | ios_base::binary); - std::ofstream out(_destfile.c_str(), ios_base::out | ios_base::binary); - char buf[COPY_BUF_SIZE]; - - do { - in.read(&buf[0], COPY_BUF_SIZE); - out.write(&buf[0], in.gcount()); - } while (in.gcount() > 0); - in.close(); - out.close(); - return true; -} - -bool FileOpsImpl::FolderCreate -( - const string _dirname -) -{ - if (FolderExists(_dirname)) { - Log::Write(LogLevel_Warning, "Folder %s Exists for FolderCreate", _dirname.c_str()); - return false; - } - int ret = mkdir(_dirname.c_str(), 0777); - if (ret == 0) - return true; - Log::Write(LogLevel_Warning, "Create Directory Failed: %s - %s", _dirname.c_str(), strerror(errno)); - return false; -} - + bool FileOpsImpl::FolderExists(const string _folderName) + { + DIR *dirp = opendir(_folderName.c_str()); + if (dirp != NULL) + { + closedir(dirp); + return true; + } + else + return false; + } + + bool FileOpsImpl::FileExists(const string _filename) + { + struct stat buffer; + return (stat(_filename.c_str(), &buffer) == 0); + } + + bool FileOpsImpl::FileWriteable(const string _filename) + { + if (!FileExists(_filename)) + { + string fn = ozwdirname(_filename); + return (access(fn.c_str(), W_OK | F_OK) == 0); + } + + return (access(_filename.c_str(), W_OK | F_OK) == 0); + + } + + bool FileOpsImpl::FileRotate(const string _filename) + { + int i = 1; + string newFile; + /* find a filename not used yet */ + newFile = _filename; + newFile.append(".").append(intToString(i)); + while (FileExists(newFile)) + { + i++; + newFile = _filename; + newFile.append(".").append(intToString(i)); + } + /* copy the file */ + if (!FileCopy(_filename, newFile)) + { + Log::Write(LogLevel_Warning, "File Rotate Failed: %s -> %s", _filename.c_str(), newFile.c_str()); + return false; + } + + /* remove the old file */ + if (remove(_filename.c_str())) + { + Log::Write(LogLevel_Warning, "File Removal failed: %s", _filename.c_str()); + return false; + } + return true; + } + + bool FileOpsImpl::FileCopy(const string _sourcefile, const string _destfile) + { + + if (!FileExists(_sourcefile)) + { + Log::Write(LogLevel_Warning, "Source File %s doesn't exist in FileCopy", _sourcefile.c_str()); + return false; + } + if (FileExists(_destfile)) + { + Log::Write(LogLevel_Warning, "Destination File %s exists in FileCopy", _destfile.c_str()); + return false; + } + + /* make sure the Destination Folder Exists */ + if (!FolderExists(ozwdirname(_destfile))) + { + Log::Write(LogLevel_Warning, "Destination Folder %s Doesn't Exist", ozwdirname(_destfile).c_str()); + return false; + } + + std::ifstream in(_sourcefile.c_str(), ios_base::in | ios_base::binary); + std::ofstream out(_destfile.c_str(), ios_base::out | ios_base::binary); + char buf[COPY_BUF_SIZE]; + + do + { + in.read(&buf[0], COPY_BUF_SIZE); + out.write(&buf[0], in.gcount()); + } while (in.gcount() > 0); + in.close(); + out.close(); + return true; + } + + bool FileOpsImpl::FolderCreate(const string _dirname) + { + if (FolderExists(_dirname)) + { + Log::Write(LogLevel_Warning, "Folder %s Exists for FolderCreate", _dirname.c_str()); + return false; + } + int ret = mkdir(_dirname.c_str(), 0777); + if (ret == 0) + return true; + Log::Write(LogLevel_Warning, "Create Directory Failed: %s - %s", _dirname.c_str(), strerror(errno)); + return false; + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/unix/FileOpsImpl.h b/cpp/src/platform/unix/FileOpsImpl.h index 8089daaff7..25741209d6 100644 --- a/cpp/src/platform/unix/FileOpsImpl.h +++ b/cpp/src/platform/unix/FileOpsImpl.h @@ -37,23 +37,29 @@ namespace OpenZWave { - class FileOpsImpl + namespace Internal { - friend class FileOps; + namespace Platform + { - private: - FileOpsImpl(); - ~FileOpsImpl(); + class FileOpsImpl + { + friend class FileOps; - bool FolderExists( const string _filename ); - bool FileExists( const string _filename ); - bool FileWriteable ( const string _filename ); - bool FileRotate ( const string _filename ); - bool FileCopy (const string, const string); - bool FolderCreate( const string _dirname); + private: + FileOpsImpl(); + ~FileOpsImpl(); - }; + bool FolderExists(const string _filename); + bool FileExists(const string _filename); + bool FileWriteable(const string _filename); + bool FileRotate(const string _filename); + bool FileCopy(const string, const string); + bool FolderCreate(const string _dirname); + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_FileOpsImpl_H diff --git a/cpp/src/platform/unix/LogImpl.cpp b/cpp/src/platform/unix/LogImpl.cpp index fb6706c1a9..c3ac442968 100644 --- a/cpp/src/platform/unix/LogImpl.cpp +++ b/cpp/src/platform/unix/LogImpl.cpp @@ -32,319 +32,312 @@ #include "Defs.h" #include "LogImpl.h" -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -LogImpl::LogImpl -( - string const& _filename, - bool const _bAppendLog, - bool const _bConsoleOutput, - LogLevel const _saveLevel, - LogLevel const _queueLevel, - LogLevel const _dumpTrigger -): -m_filename( _filename ), // name of log file -m_bConsoleOutput( _bConsoleOutput ), // true to provide a copy of output to console -m_bAppendLog( _bAppendLog ), // true to append (and not overwrite) any existing log -m_saveLevel( _saveLevel ), // level of messages to log to file -m_queueLevel( _queueLevel ), // level of messages to log to queue -m_dumpTrigger( _dumpTrigger ), // dump queued messages when this level is seen -pFile( NULL ) -{ - if (!m_filename.empty()) { - if ( !m_bAppendLog ) - { - this->pFile = fopen( m_filename.c_str(), "w" ); - } else { - this->pFile = fopen( m_filename.c_str(), "a" ); - } - if( this->pFile == NULL ) - { - std::cerr << "Could Not Open OZW Log File." << std::endl; - } else { - setlinebuf(this->pFile); - } - } - setlinebuf(stdout); // To prevent buffering and lock contention issues -} + LogImpl::LogImpl(string const& _filename, bool const _bAppendLog, bool const _bConsoleOutput, LogLevel const _saveLevel, LogLevel const _queueLevel, LogLevel const _dumpTrigger) : + m_filename(_filename), // name of log file + m_bConsoleOutput(_bConsoleOutput), // true to provide a copy of output to console + m_bAppendLog(_bAppendLog), // true to append (and not overwrite) any existing log + m_saveLevel(_saveLevel), // level of messages to log to file + m_queueLevel(_queueLevel), // level of messages to log to queue + m_dumpTrigger(_dumpTrigger), // dump queued messages when this level is seen + pFile( NULL) + { + if (!m_filename.empty()) + { + if (!m_bAppendLog) + { + this->pFile = fopen(m_filename.c_str(), "w"); + } + else + { + this->pFile = fopen(m_filename.c_str(), "a"); + } + if (this->pFile == NULL) + { + std::cerr << "Could Not Open OZW Log File." << std::endl; + } + else + { + setlinebuf(this->pFile); + } + } + setlinebuf(stdout); // To prevent buffering and lock contention issues + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -LogImpl::~LogImpl -( -) -{ - if (this->pFile) - fclose( this->pFile ); -} - -unsigned int LogImpl::toEscapeCode(LogLevel _level) { - unsigned int code; - - switch (_level) { - case LogLevel_Debug: code = 34; break; // 34=blue - case LogLevel_Detail: code = 34; break; // 34=blue - case LogLevel_Info: code = 39; break; // 39=white - case LogLevel_Alert: code = 33; break; // 33=orange - case LogLevel_Warning: code = 33; break; // 31=red - case LogLevel_Error: code = 31; break; - case LogLevel_Fatal: code = 95; break; - case LogLevel_Always: code = 32; break; // 95=magenta - default: code = 39; break; // 39=white (reset to default) - } + LogImpl::~LogImpl() + { + if (this->pFile) + fclose(this->pFile); + } - return code; -} + unsigned int LogImpl::toEscapeCode(LogLevel _level) + { + unsigned int code = 39; + switch (_level) + { + case LogLevel_Internal: + case LogLevel_StreamDetail: + code = 97; + break; // 97=bright white + case LogLevel_Debug: + code = 36; + break; // 36=cyan + case LogLevel_Detail: + code = 94; + break; // 94=bright blue + case LogLevel_Info: + code = 39; + break; // 39=white + case LogLevel_Alert: + code = 93; + break; // 93=bright yellow + case LogLevel_Warning: + code = 33; + break; // 33=yellow + case LogLevel_Error: + code = 31; + break; // 31=red + case LogLevel_Fatal: + code = 95; + break; // 95=bright magenta + case LogLevel_Always: + code = 32; + break; // 32=green + case LogLevel_Invalid: + case LogLevel_None: + code = 39; + break; // 39=white (reset to default) + } + return code; + } //----------------------------------------------------------------------------- // // Write to the log //----------------------------------------------------------------------------- -void LogImpl::Write -( - LogLevel _logLevel, - uint8 const _nodeId, - char const* _format, - va_list _args -) -{ - // create a timestamp string - string timeStr = GetTimeStampString(); - string nodeStr = GetNodeString( _nodeId ); - string loglevelStr = GetLogLevelString(_logLevel); + void LogImpl::Write(LogLevel _logLevel, uint8 const _nodeId, char const* _format, va_list _args) + { + // create a timestamp string + string timeStr = GetTimeStampString(); + string nodeStr = GetNodeString(_nodeId); + string loglevelStr = GetLogLevelString(_logLevel); - // handle this message - if( (_logLevel <= m_queueLevel) || (_logLevel == LogLevel_Internal) ) // we're going to do something with this message... - { - char lineBuf[1024] = {0}; - //int lineLen = 0; - if( _format != NULL && _format[0] != '\0' ) - { - va_list saveargs; - va_copy( saveargs, _args ); + // handle this message + if ((_logLevel <= m_queueLevel) || (_logLevel == LogLevel_Internal)) // we're going to do something with this message... + { + char lineBuf[1024] = + { 0 }; + //int lineLen = 0; + if (_format != NULL && _format[0] != '\0') + { + va_list saveargs; + va_copy(saveargs, _args); - vsnprintf( lineBuf, sizeof(lineBuf), _format, _args ); - va_end( saveargs ); - } + vsnprintf(lineBuf, sizeof(lineBuf), _format, _args); + va_end(saveargs); + } - // should this message be saved to file (and possibly written to console?) - if( (_logLevel <= m_saveLevel) || (_logLevel == LogLevel_Internal) ) - { - std::string outBuf; + // should this message be saved to file (and possibly written to console?) + if ((_logLevel <= m_saveLevel) || (_logLevel == LogLevel_Internal)) + { + std::string outBuf; - if ( this->pFile != NULL || m_bConsoleOutput ) - { - if( _logLevel != LogLevel_Internal ) // don't add a second timestamp to display of queued messages - { - outBuf.append(timeStr); - outBuf.append(loglevelStr); - outBuf.append(nodeStr); - outBuf.append(lineBuf); - outBuf.append("\n"); + if (this->pFile != NULL || m_bConsoleOutput) + { + if (_logLevel != LogLevel_Internal) // don't add a second timestamp to display of queued messages + { + outBuf.append(timeStr); + outBuf.append(loglevelStr); + outBuf.append(nodeStr); + outBuf.append(lineBuf); + outBuf.append("\n"); - } + } - // print message to file (and possibly screen) - if( this->pFile != NULL ) - { - fputs( outBuf.c_str(), pFile ); - } - if( m_bConsoleOutput ) - { - fprintf(stdout,"\x1B[%02um", toEscapeCode(_logLevel)); - fputs( outBuf.c_str(), stdout ); - fprintf(stdout, "\x1b[39m"); - /* always return to normal */ - fprintf(stdout,"\x1B[%02um", toEscapeCode(LogLevel_Info)); - } - } - } + // print message to file (and possibly screen) + if (this->pFile != NULL) + { + fputs(outBuf.c_str(), pFile); + } + if (m_bConsoleOutput) + { + fprintf(stdout, "\x1B[%02um", toEscapeCode(_logLevel)); + fputs(outBuf.c_str(), stdout); + fprintf(stdout, "\x1b[39m"); + /* always return to normal */ + fprintf(stdout, "\x1B[%02um", toEscapeCode(LogLevel_Info)); + } + } + } - if( _logLevel != LogLevel_Internal ) - { - char queueBuf[1024]; - string threadStr = GetThreadId(); - snprintf( queueBuf, sizeof(queueBuf), "%s%s%s", timeStr.c_str(), threadStr.c_str(), lineBuf ); - Queue( queueBuf ); - } - } + if (_logLevel != LogLevel_Internal) + { + char queueBuf[1024]; + string threadStr = GetThreadId(); + snprintf(queueBuf, sizeof(queueBuf), "%s%s%s", timeStr.c_str(), threadStr.c_str(), lineBuf); + Queue(queueBuf); + } + } - // now check to see if the _dumpTrigger has been hit - if( (_logLevel <= m_dumpTrigger) && (_logLevel != LogLevel_Internal) && (_logLevel != LogLevel_Always) ) - QueueDump(); -} + // now check to see if the _dumpTrigger has been hit + if ((_logLevel <= m_dumpTrigger) && (_logLevel != LogLevel_Internal) && (_logLevel != LogLevel_Always)) + QueueDump(); + } //----------------------------------------------------------------------------- // // Write to the log queue //----------------------------------------------------------------------------- -void LogImpl::Queue -( - char const* _buffer -) -{ - string bufStr = _buffer; - m_logQueue.push_back( bufStr ); + void LogImpl::Queue(char const* _buffer) + { + string bufStr = _buffer; + m_logQueue.push_back(bufStr); - // rudimentary queue size management - if( m_logQueue.size() > 500 ) - { - m_logQueue.pop_front(); - } -} + // rudimentary queue size management + if (m_logQueue.size() > 500) + { + m_logQueue.pop_front(); + } + } //----------------------------------------------------------------------------- // // Dump the LogQueue to output device //----------------------------------------------------------------------------- -void LogImpl::QueueDump -( -) -{ - Log::Write( LogLevel_Always, "" ); - Log::Write( LogLevel_Always, "Dumping queued log messages"); - Log::Write( LogLevel_Always, "" ); - list::iterator it = m_logQueue.begin(); - while( it != m_logQueue.end() ) - { - string strTemp = *it; - Log::Write( LogLevel_Internal, strTemp.c_str() ); - it++; - } - m_logQueue.clear(); - Log::Write( LogLevel_Always, "" ); - Log::Write( LogLevel_Always, "End of queued log message dump"); - Log::Write( LogLevel_Always, "" ); -} + void LogImpl::QueueDump() + { + Log::Write(LogLevel_Always, ""); + Log::Write(LogLevel_Always, "Dumping queued log messages"); + Log::Write(LogLevel_Always, ""); + list::iterator it = m_logQueue.begin(); + while (it != m_logQueue.end()) + { + string strTemp = *it; + Log::Write(LogLevel_Internal, strTemp.c_str()); + it++; + } + m_logQueue.clear(); + Log::Write(LogLevel_Always, ""); + Log::Write(LogLevel_Always, "End of queued log message dump"); + Log::Write(LogLevel_Always, ""); + } //----------------------------------------------------------------------------- // // Clear the LogQueue //----------------------------------------------------------------------------- -void LogImpl::QueueClear -( -) -{ - m_logQueue.clear(); -} + void LogImpl::QueueClear() + { + m_logQueue.clear(); + } //----------------------------------------------------------------------------- // // Sets the various log state variables //----------------------------------------------------------------------------- -void LogImpl::SetLoggingState -( - LogLevel _saveLevel, - LogLevel _queueLevel, - LogLevel _dumpTrigger -) -{ - m_saveLevel = _saveLevel; - m_queueLevel = _queueLevel; - m_dumpTrigger = _dumpTrigger; -} + void LogImpl::SetLoggingState(LogLevel _saveLevel, LogLevel _queueLevel, LogLevel _dumpTrigger) + { + m_saveLevel = _saveLevel; + m_queueLevel = _queueLevel; + m_dumpTrigger = _dumpTrigger; + } //----------------------------------------------------------------------------- // // Generate a string with formatted current time //----------------------------------------------------------------------------- -string LogImpl::GetTimeStampString -( -) -{ - // Get a timestamp - struct timeval tv; - gettimeofday(&tv, NULL); - // use threadsafe verion of localtime. Reported by nihilus, 2019-04 - // https://www.gnu.org/software/libc/manual/html_node/Broken_002ddown-Time.html#Broken_002ddown-Time - struct tm *tm, xtm; - memset(&xtm, 0, sizeof(xtm)); - tm = localtime_r( &tv.tv_sec, &xtm); + std::string LogImpl::GetTimeStampString() + { + // Get a timestamp + struct timeval tv; + gettimeofday(&tv, NULL); + // use threadsafe verion of localtime. Reported by nihilus, 2019-04 + // https://www.gnu.org/software/libc/manual/html_node/Broken_002ddown-Time.html#Broken_002ddown-Time + struct tm *tm, xtm; + memset(&xtm, 0, sizeof(xtm)); + tm = localtime_r(&tv.tv_sec, &xtm); - // create a time stamp string for the log message - char buf[100]; - snprintf( buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d.%03d ", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, - tm->tm_hour, tm->tm_min, tm->tm_sec, (int)tv.tv_usec / 1000 ); - string str = buf; - return str; -} + // create a time stamp string for the log message + char buf[100]; + snprintf(buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d.%03d ", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int) tv.tv_usec / 1000); + string str = buf; + return str; + } //----------------------------------------------------------------------------- // // Generate a string with formatted node id //----------------------------------------------------------------------------- -string LogImpl::GetNodeString -( - uint8 const _nodeId -) -{ - if( _nodeId == 0 ) - { - return ""; - } - else - if( _nodeId == 255 ) // should make distinction between broadcast and controller better for SwitchAll broadcast - { - return "contrlr, "; - } - else - { - char buf[20]; - snprintf( buf, sizeof(buf), "Node%03d, ", _nodeId ); - return buf; - } -} + std::string LogImpl::GetNodeString(uint8 const _nodeId) + { + if (_nodeId == 0) + { + return ""; + } + else if (_nodeId == 255) // should make distinction between broadcast and controller better for SwitchAll broadcast + { + return "contrlr, "; + } + else + { + char buf[20]; + snprintf(buf, sizeof(buf), "Node%03d, ", _nodeId); + return buf; + } + } //----------------------------------------------------------------------------- // // Generate a string with formatted thread id //----------------------------------------------------------------------------- -string LogImpl::GetThreadId -( -) -{ - char buf[20]; - snprintf( buf, sizeof(buf), "%08lx ", (long unsigned int)pthread_self() ); - string str = buf; - return str; -} + std::string LogImpl::GetThreadId() + { + char buf[20]; + snprintf(buf, sizeof(buf), "%08lx ", (long unsigned int) pthread_self()); + string str = buf; + return str; + } //----------------------------------------------------------------------------- // // Provide a new log file name (applicable to future writes) //----------------------------------------------------------------------------- -void LogImpl::SetLogFileName -( - const string &_filename -) -{ - m_filename = _filename; -} - + void LogImpl::SetLogFileName(const string &_filename) + { + m_filename = _filename; + } //----------------------------------------------------------------------------- // // Provide a new log file name (applicable to future writes) //----------------------------------------------------------------------------- -string LogImpl::GetLogLevelString -( - LogLevel _level -) -{ - if ((_level >= LogLevel_None) && (_level <= LogLevel_Internal)) { - char buf[20]; - snprintf( buf, sizeof(buf), "%s, ", LogLevelString[_level] ); - return buf; - } - else - return "Unknown, "; -} + std::string LogImpl::GetLogLevelString(LogLevel _level) + { + if ((_level >= LogLevel_None) && (_level <= LogLevel_Internal)) + { + char buf[20]; + snprintf(buf, sizeof(buf), "%s, ", LogLevelString[_level]); + return buf; + } + else + return "Unknown, "; + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/unix/LogImpl.h b/cpp/src/platform/unix/LogImpl.h index 149707292d..6c9ee0fc55 100644 --- a/cpp/src/platform/unix/LogImpl.h +++ b/cpp/src/platform/unix/LogImpl.h @@ -37,38 +37,43 @@ namespace OpenZWave { - class LogImpl : public i_LogImpl + namespace Internal { - private: - friend class Log; + namespace Platform + { - LogImpl( string const& _filename, bool const _bAppendLog, bool const _bConsoleOutput, LogLevel const _saveLevel, LogLevel const _queueLevel, LogLevel const _dumpTrigger ); - ~LogImpl(); + class LogImpl: public i_LogImpl + { + private: + friend class OpenZWave::Log; - void Write( LogLevel _level, uint8 const _nodeId, char const* _format, va_list _args ); - void Queue( char const* _buffer ); - void QueueDump(); - void QueueClear(); - void SetLoggingState( LogLevel _saveLevel, LogLevel _queueLevel, LogLevel _dumpTrigger ); - void SetLogFileName( const string &_filename ); + LogImpl(string const& _filename, bool const _bAppendLog, bool const _bConsoleOutput, LogLevel const _saveLevel, LogLevel const _queueLevel, LogLevel const _dumpTrigger); + ~LogImpl(); - string GetTimeStampString(); - string GetNodeString( uint8 const _nodeId ); - string GetThreadId(); - string GetLogLevelString(LogLevel _level); - unsigned int toEscapeCode(LogLevel _level); + void Write(LogLevel _level, uint8 const _nodeId, char const* _format, va_list _args); + void Queue(char const* _buffer); + void QueueDump(); + void QueueClear(); + void SetLoggingState(LogLevel _saveLevel, LogLevel _queueLevel, LogLevel _dumpTrigger); + void SetLogFileName(const string &_filename); + string GetTimeStampString(); + string GetNodeString(uint8 const _nodeId); + string GetThreadId(); + string GetLogLevelString(LogLevel _level); + unsigned int toEscapeCode(LogLevel _level); - string m_filename; /**< filename specified by user (default is ozw_log.txt) */ - bool m_bConsoleOutput; /**< if true, send log output to console as well as to the file */ - bool m_bAppendLog; /**< if true, the log file should be appended to any with the same name */ - list m_logQueue; /**< list of queued log messages */ - LogLevel m_saveLevel; - LogLevel m_queueLevel; - LogLevel m_dumpTrigger; - FILE* pFile; - }; - + string m_filename; /**< filename specified by user (default is ozw_log.txt) */ + bool m_bConsoleOutput; /**< if true, send log output to console as well as to the file */ + bool m_bAppendLog; /**< if true, the log file should be appended to any with the same name */ + list m_logQueue; /**< list of queued log messages */ + LogLevel m_saveLevel; + LogLevel m_queueLevel; + LogLevel m_dumpTrigger; + FILE* pFile; + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_LogImpl_H diff --git a/cpp/src/platform/unix/MutexImpl.cpp b/cpp/src/platform/unix/MutexImpl.cpp index f37da08bf6..a8a1274dcb 100644 --- a/cpp/src/platform/unix/MutexImpl.cpp +++ b/cpp/src/platform/unix/MutexImpl.cpp @@ -33,115 +33,113 @@ #include #include -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -MutexImpl::MutexImpl -( -): - m_lockCount( 0 ) -{ - pthread_mutexattr_t ma; + MutexImpl::MutexImpl() : + m_lockCount(0) + { + pthread_mutexattr_t ma; - pthread_mutexattr_init ( &ma ); - pthread_mutexattr_settype( &ma, PTHREAD_MUTEX_RECURSIVE ); - int err = pthread_mutex_init( &m_criticalSection, &ma ); - if( err != 0 ) - { - Log::Write(LogLevel_Error, "MutexImpl::MutexImpl error %d (%d)\n", errno, err ); - } - pthread_mutexattr_destroy( &ma ); -} + pthread_mutexattr_init(&ma); + pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_RECURSIVE); + int err = pthread_mutex_init(&m_criticalSection, &ma); + if (err != 0) + { + Log::Write(LogLevel_Error, "MutexImpl::MutexImpl error %d (%d)\n", errno, err); + } + pthread_mutexattr_destroy(&ma); + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -MutexImpl::~MutexImpl -( -) -{ - if (m_lockCount != 0) { - Log::Write(LogLevel_Error, "MutexImpl:~MutexImpl: - Destroying a Locked Mutex: %d", m_lockCount); - } - pthread_mutex_destroy( &m_criticalSection ); -} + MutexImpl::~MutexImpl() + { + if (m_lockCount != 0) + { + Log::Write(LogLevel_Error, "MutexImpl:~MutexImpl: - Destroying a Locked Mutex: %d", m_lockCount); + } + pthread_mutex_destroy(&m_criticalSection); + } //----------------------------------------------------------------------------- // // Lock the mutex //----------------------------------------------------------------------------- -bool MutexImpl::Lock -( - bool const _bWait -) -{ - if (m_lockCount < 0) { - Log::Write(LogLevel_Error, "MutexImpl:Lock - Lock is Negative: %d", m_lockCount); - m_lockCount = 0; - } + bool MutexImpl::Lock(bool const _bWait) + { + if (m_lockCount < 0) + { + Log::Write(LogLevel_Error, "MutexImpl:Lock - Lock is Negative: %d", m_lockCount); + m_lockCount = 0; + } - if( _bWait ) - { - // We will wait for the lock - int err = pthread_mutex_lock( &m_criticalSection ); - if( err == 0 ) - { - ++m_lockCount; - return true; - } - Log::Write(LogLevel_Error, "MutexImpl::Lock failed with error: %d (%d)", errno, err); - return false; - } + if (_bWait) + { + // We will wait for the lock + int err = pthread_mutex_lock(&m_criticalSection); + if (err == 0) + { + ++m_lockCount; + return true; + } + Log::Write(LogLevel_Error, "MutexImpl::Lock failed with error: %d (%d)", errno, err); + return false; + } - // Returns immediately, even if the lock was not available. - if( pthread_mutex_trylock( &m_criticalSection ) ) - { - return false; - } - - ++m_lockCount; - return true; -} + // Returns immediately, even if the lock was not available. + if (pthread_mutex_trylock(&m_criticalSection)) + { + return false; + } + + ++m_lockCount; + return true; + } //----------------------------------------------------------------------------- // // Release our lock on the mutex //----------------------------------------------------------------------------- -void MutexImpl::Unlock -( -) -{ - if(m_lockCount < 0 ) - { - // No locks - we have a mismatched lock/release pair - Log::Write(LogLevel_Error, "MutexImpl:Unlock - Lock is Negative - MisMatched Lock/Release Pair: %d", m_lockCount); - /* reset the lockCount to 0 */ - m_lockCount = 0; - } - else - { - --m_lockCount; - } - /* try to unlock Regardless of the lockCount */ - int err = pthread_mutex_unlock( &m_criticalSection ); - if( err != 0 ) - { - Log::Write(LogLevel_Error, "MutexImpl::UnLock failed with error: %d (%d)\n", errno, err); - } -} + void MutexImpl::Unlock() + { + if (m_lockCount < 0) + { + // No locks - we have a mismatched lock/release pair + Log::Write(LogLevel_Error, "MutexImpl:Unlock - Lock is Negative - MisMatched Lock/Release Pair: %d", m_lockCount); + /* reset the lockCount to 0 */ + m_lockCount = 0; + } + else + { + --m_lockCount; + } + /* try to unlock Regardless of the lockCount */ + int err = pthread_mutex_unlock(&m_criticalSection); + if (err != 0) + { + Log::Write(LogLevel_Error, "MutexImpl::UnLock failed with error: %d (%d)\n", errno, err); + } + } //----------------------------------------------------------------------------- // // Test whether the mutex is free //----------------------------------------------------------------------------- -bool MutexImpl::IsSignalled -( -) -{ - return( 0 == m_lockCount ); -} - + bool MutexImpl::IsSignalled() + { + return (0 == m_lockCount); + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/unix/MutexImpl.h b/cpp/src/platform/unix/MutexImpl.h index 816d402ac1..b5694d47af 100644 --- a/cpp/src/platform/unix/MutexImpl.h +++ b/cpp/src/platform/unix/MutexImpl.h @@ -33,23 +33,28 @@ namespace OpenZWave { - class MutexImpl + namespace Internal { - private: - friend class Mutex; - - MutexImpl(); - ~MutexImpl(); - - bool Lock( bool const _bWait = true ); - void Unlock(); - - bool IsSignalled(); - - int32 m_lockCount; // Keep track of the locks (there can be more than one if they occur on the same thread. - pthread_mutex_t m_criticalSection; - }; - + namespace Platform + { + class MutexImpl + { + private: + friend class Mutex; + + MutexImpl(); + ~MutexImpl(); + + bool Lock(bool const _bWait = true); + void Unlock(); + + bool IsSignalled(); + + int32 m_lockCount; // Keep track of the locks (there can be more than one if they occur on the same thread. + pthread_mutex_t m_criticalSection; + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_MutexIF_H diff --git a/cpp/src/platform/unix/SerialControllerImpl.cpp b/cpp/src/platform/unix/SerialControllerImpl.cpp index 55e2450982..beaf658979 100644 --- a/cpp/src/platform/unix/SerialControllerImpl.cpp +++ b/cpp/src/platform/unix/SerialControllerImpl.cpp @@ -43,338 +43,318 @@ cfsetspeed(struct termios *tios, speed_t speed) } #endif -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -SerialControllerImpl::SerialControllerImpl -( - SerialController* _owner -): - m_owner( _owner ), - m_hSerialController( -1 ) -{ -} + SerialControllerImpl::SerialControllerImpl(SerialController* _owner) : + m_owner(_owner), m_hSerialController(-1), m_pThread( NULL) + { + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -SerialControllerImpl::~SerialControllerImpl -( -) -{ - flock(m_hSerialController, LOCK_UN); - if(m_hSerialController >= 0) - close( m_hSerialController ); -} + SerialControllerImpl::~SerialControllerImpl() + { + flock(m_hSerialController, LOCK_UN); + if (m_hSerialController >= 0) + close(m_hSerialController); + } //----------------------------------------------------------------------------- // // Open the serial port //----------------------------------------------------------------------------- -bool SerialControllerImpl::Open -( -) -{ - // Try to init the serial port - if( !Init( 1 ) ) - { - // Failed. We bail to allow the app a chance to take over, rather than retry - // automatically. Automatic retries only occur after a successful init. - return false; - } + bool SerialControllerImpl::Open() + { + // Try to init the serial port + if (!Init(1)) + { + // Failed. We bail to allow the app a chance to take over, rather than retry + // automatically. Automatic retries only occur after a successful init. + return false; + } - // Start the read thread - m_pThread = new Thread( "SerialController" ); - m_pThread->Start( SerialReadThreadEntryPoint, this ); + // Start the read thread + m_pThread = new Thread("SerialController"); + m_pThread->Start(SerialReadThreadEntryPoint, this); - return true; -} + return true; + } //----------------------------------------------------------------------------- // // Close the serial port //----------------------------------------------------------------------------- -void SerialControllerImpl::Close -( -) -{ - if( m_pThread ) - { - m_pThread->Stop(); - m_pThread->Release(); - m_pThread = NULL; - } - close( m_hSerialController ); - m_hSerialController = -1; -} + void SerialControllerImpl::Close() + { + if (m_pThread) + { + m_pThread->Stop(); + m_pThread->Release(); + m_pThread = NULL; + } + close(m_hSerialController); + m_hSerialController = -1; + } //----------------------------------------------------------------------------- // // Entry point of the thread for receiving data from the serial port //----------------------------------------------------------------------------- -void SerialControllerImpl::SerialReadThreadEntryPoint -( - Event* _exitEvent, - void* _context -) -{ - SerialControllerImpl* impl = (SerialControllerImpl*)_context; - if( impl ) - { - impl->ReadThreadProc( _exitEvent ); - } -} + void SerialControllerImpl::SerialReadThreadEntryPoint(Event* _exitEvent, void* _context) + { + SerialControllerImpl* impl = (SerialControllerImpl*) _context; + if (impl) + { + impl->ReadThreadProc(_exitEvent); + } + } //----------------------------------------------------------------------------- // // Handle receiving data //----------------------------------------------------------------------------- -void SerialControllerImpl::ReadThreadProc -( - Event* _exitEvent -) -{ - uint32 attempts = 0; - while( !_exitEvent->IsSignalled() ) - { - // Init must have been called successfully during Open, so we - // don't do it again until the end of the loop - if( -1 != m_hSerialController ) - { - // Enter read loop. Call will only return if - // an exit is requested or an error occurs - Read(_exitEvent); + void SerialControllerImpl::ReadThreadProc(Event* _exitEvent) + { + uint32 attempts = 0; + while (!_exitEvent->IsSignalled()) + { + // Init must have been called successfully during Open, so we + // don't do it again until the end of the loop + if (-1 != m_hSerialController) + { + // Enter read loop. Call will only return if + // an exit is requested or an error occurs + Read(_exitEvent); - // Reset the attempts, so we get a rapid retry for temporary errors - attempts = 0; - } + // Reset the attempts, so we get a rapid retry for temporary errors + attempts = 0; + } - if( attempts < 25 ) - { - // Retry every 5 seconds for the first two minutes... - if( Wait::Single( _exitEvent, 5000 ) >= 0 ) - { - // Exit signalled. - break; - } - } - else - { - // ...retry every 30 seconds after that - if( Wait::Single( _exitEvent, 30000 ) >= 0 ) - { - // Exit signalled. - break; - } - } + if (attempts < 25) + { + // Retry every 5 seconds for the first two minutes... + if (Wait::Single(_exitEvent, 5000) >= 0) + { + // Exit signalled. + break; + } + } + else + { + // ...retry every 30 seconds after that + if (Wait::Single(_exitEvent, 30000) >= 0) + { + // Exit signalled. + break; + } + } - Init( ++attempts ); - } -} + Init(++attempts); + } + } //----------------------------------------------------------------------------- // // Initialize the serial port //----------------------------------------------------------------------------- -bool SerialControllerImpl::Init -( - uint32 const _attempts -) -{ - - string device = m_owner->m_serialControllerName; - - Log::Write( LogLevel_Info, "Trying to open serial port %s (attempt %d)", device.c_str(), _attempts ); - + bool SerialControllerImpl::Init(uint32 const _attempts) + { + + string device = m_owner->m_serialControllerName; + + Log::Write(LogLevel_Info, "Trying to open serial port %s (attempt %d)", device.c_str(), _attempts); + #ifdef __NetBSD__ - m_hSerialController = open( device.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK); + m_hSerialController = open( device.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK); #else - m_hSerialController = open( device.c_str(), O_RDWR | O_NOCTTY, 0 ); + m_hSerialController = open(device.c_str(), O_RDWR | O_NOCTTY, 0); #endif - if( -1 == m_hSerialController ) - { - //Error - Log::Write( LogLevel_Error, "ERROR: Cannot open serial port %s. Error code %d", device.c_str(), errno ); - goto SerialOpenFailure; - } + if (-1 == m_hSerialController) + { + //Error + Log::Write(LogLevel_Error, "ERROR: Cannot open serial port %s. Error code %d", device.c_str(), errno); + goto SerialOpenFailure; + } - if( flock( m_hSerialController, LOCK_EX | LOCK_NB) == -1 ) - { - Log::Write( LogLevel_Error, "ERROR: Cannot get exclusive lock for serial port %s. Error code %d", device.c_str(), errno ); - } + if (flock(m_hSerialController, LOCK_EX | LOCK_NB) == -1) + { + Log::Write(LogLevel_Error, "ERROR: Cannot get exclusive lock for serial port %s. Error code %d", device.c_str(), errno); + } - int bits; - bits = 0; - ioctl( m_hSerialController, TIOCMSET, &bits ); + int bits; + bits = 0; + ioctl(m_hSerialController, TIOCMSET, &bits); - // Configure the serial device parameters - // Build on the current configuration - struct termios tios; + // Configure the serial device parameters + // Build on the current configuration + struct termios tios; - bzero( &tios, sizeof(tios) ); - tcgetattr( m_hSerialController, &tios ); - switch( m_owner->m_parity ) - { - case SerialController::Parity_None: - tios.c_iflag = IGNPAR; - break; - case SerialController::Parity_Odd: - tios.c_iflag = INPCK; - tios.c_cflag = PARENB | PARODD; - break; - default: - Log::Write( LogLevel_Error, "ERROR: Parity not supported" ); - goto SerialOpenFailure; - } - switch( m_owner->m_stopBits ) - { - case SerialController::StopBits_One: - break; // default - case SerialController::StopBits_Two: - tios.c_cflag |= CSTOPB; - break; - default: - Log::Write( LogLevel_Error, "ERROR: Stopbits not supported" ); - goto SerialOpenFailure; - } - tios.c_iflag |= IGNBRK; - tios.c_cflag |= CS8 | CREAD | CLOCAL; - tios.c_oflag = 0; - tios.c_lflag = 0; - for( int i = 0; i < NCCS; i++ ) - tios.c_cc[i] = 0; - tios.c_cc[VMIN] = 0; - tios.c_cc[VTIME] = 1; - switch( m_owner->m_baud ) - { - case 300: - cfsetspeed( &tios, B300 ); - break; - case 1200: - cfsetspeed( &tios, B1200 ); - break; - case 2400: - cfsetspeed( &tios, B2400 ); - break; - case 4800: - cfsetspeed( &tios, B4800 ); - break; - case 9600: - cfsetspeed( &tios, B9600 ); - break; - case 19200: - cfsetspeed( &tios, B19200 ); - break; - case 38400: - cfsetspeed( &tios, B38400 ); - break; - case 57600: - cfsetspeed( &tios, B57600 ); - break; + bzero(&tios, sizeof(tios)); + tcgetattr(m_hSerialController, &tios); + switch (m_owner->m_parity) + { + case SerialController::Parity_None: + tios.c_iflag = IGNPAR; + break; + case SerialController::Parity_Odd: + tios.c_iflag = INPCK; + tios.c_cflag = PARENB | PARODD; + break; + default: + Log::Write(LogLevel_Error, "ERROR: Parity not supported"); + goto SerialOpenFailure; + } + switch (m_owner->m_stopBits) + { + case SerialController::StopBits_One: + break; // default + case SerialController::StopBits_Two: + tios.c_cflag |= CSTOPB; + break; + default: + Log::Write(LogLevel_Error, "ERROR: Stopbits not supported"); + goto SerialOpenFailure; + } + tios.c_iflag |= IGNBRK; + tios.c_cflag |= CS8 | CREAD | CLOCAL; + tios.c_oflag = 0; + tios.c_lflag = 0; + for (int i = 0; i < NCCS; i++) + tios.c_cc[i] = 0; + tios.c_cc[VMIN] = 0; + tios.c_cc[VTIME] = 1; + switch (m_owner->m_baud) + { + case 300: + cfsetspeed(&tios, B300); + break; + case 1200: + cfsetspeed(&tios, B1200); + break; + case 2400: + cfsetspeed(&tios, B2400); + break; + case 4800: + cfsetspeed(&tios, B4800); + break; + case 9600: + cfsetspeed(&tios, B9600); + break; + case 19200: + cfsetspeed(&tios, B19200); + break; + case 38400: + cfsetspeed(&tios, B38400); + break; + case 57600: + cfsetspeed(&tios, B57600); + break; #ifdef DARWIN - case 76800: - cfsetspeed( &tios, B76800 ); - break; + case 76800: + cfsetspeed( &tios, B76800 ); + break; #endif - case 115200: - cfsetspeed( &tios, B115200 ); - break; - case 230400: - cfsetspeed( &tios, B230400 ); - break; - default: - Log::Write( LogLevel_Error, "Baud rate not supported" ); - goto SerialOpenFailure; - } - if ( tcsetattr( m_hSerialController, TCSANOW, &tios ) == -1 ) - { - // Error. Clean up and exit - Log::Write( LogLevel_Error, "ERROR: Failed to set serial port parameters" ); - goto SerialOpenFailure; - } + case 115200: + cfsetspeed(&tios, B115200); + break; + case 230400: + cfsetspeed(&tios, B230400); + break; + default: + Log::Write(LogLevel_Error, "Baud rate not supported"); + goto SerialOpenFailure; + } + if (tcsetattr(m_hSerialController, TCSANOW, &tios) == -1) + { + // Error. Clean up and exit + Log::Write(LogLevel_Error, "ERROR: Failed to set serial port parameters"); + goto SerialOpenFailure; + } - tcflush( m_hSerialController, TCIOFLUSH ); + tcflush(m_hSerialController, TCIOFLUSH); - // Open successful - Log::Write( LogLevel_Info, "Serial port %s opened (attempt %d)", device.c_str(), _attempts ); - return true; + // Open successful + Log::Write(LogLevel_Info, "Serial port %s opened (attempt %d)", device.c_str(), _attempts); + return true; -SerialOpenFailure: - Log::Write( LogLevel_Error, "ERROR: Failed to open serial port %s", device.c_str() ); - if(m_hSerialController >= 0) - { - close( m_hSerialController ); - m_hSerialController = -1; - } - return false; -} + SerialOpenFailure: Log::Write(LogLevel_Error, "ERROR: Failed to open serial port %s", device.c_str()); + if (m_hSerialController >= 0) + { + close(m_hSerialController); + m_hSerialController = -1; + } + return false; + } //----------------------------------------------------------------------------- // // Read data from the serial port //----------------------------------------------------------------------------- -void SerialControllerImpl::Read -( - Event* _exitEvent -) -{ - uint8 buffer[256]; + void SerialControllerImpl::Read(Event* _exitEvent) + { + uint8 buffer[256]; - while( !_exitEvent->IsSignalled() ) - { - int32 bytesRead; - int err; + while (!_exitEvent->IsSignalled()) + { + int32 bytesRead; + int err; - do - { - bytesRead = read( m_hSerialController, buffer, sizeof(buffer) ); - if( bytesRead > 0 ) - m_owner->Put( buffer, bytesRead ); - } while( bytesRead > 0 ); + do + { + bytesRead = read(m_hSerialController, buffer, sizeof(buffer)); + if (bytesRead > 0) + m_owner->Put(buffer, bytesRead); + } while (bytesRead > 0); - do - { - struct timeval *whenp; - fd_set rds, eds; - int oldstate; - - FD_ZERO( &rds ); - FD_SET( m_hSerialController, &rds ); - FD_ZERO( &eds ); - FD_SET( m_hSerialController, &eds ); - whenp = NULL; - - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); - err = select( m_hSerialController + 1, &rds, NULL, &eds, whenp ); - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); - } while( err <= 0 ); - } -} + do + { + struct timeval *whenp; + fd_set rds, eds; + int oldstate; + + FD_ZERO(&rds); + FD_SET(m_hSerialController, &rds); + FD_ZERO(&eds); + FD_SET(m_hSerialController, &eds); + whenp = NULL; + + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); + err = select(m_hSerialController + 1, &rds, NULL, &eds, whenp); + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); + } while (err <= 0); + } + } //----------------------------------------------------------------------------- // // Send data to the serial port //----------------------------------------------------------------------------- -uint32 SerialControllerImpl::Write -( - uint8* _buffer, - uint32 _length -) -{ - if( -1 == m_hSerialController ) - { - //Error - Log::Write( LogLevel_Error, "ERROR: Serial port must be opened before writing" ); - return 0; - } - - // Write the data - uint32 bytesWritten; - bytesWritten = write( m_hSerialController, _buffer, _length); - return bytesWritten; -} + uint32 SerialControllerImpl::Write(uint8* _buffer, uint32 _length) + { + if (-1 == m_hSerialController) + { + //Error + Log::Write(LogLevel_Error, "ERROR: Serial port must be opened before writing"); + return 0; + } + + // Write the data + uint32 bytesWritten; + bytesWritten = write(m_hSerialController, _buffer, _length); + return bytesWritten; + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/unix/SerialControllerImpl.h b/cpp/src/platform/unix/SerialControllerImpl.h index 093905a5aa..ac59d5fc41 100644 --- a/cpp/src/platform/unix/SerialControllerImpl.h +++ b/cpp/src/platform/unix/SerialControllerImpl.h @@ -42,32 +42,37 @@ namespace OpenZWave { - class SerialControllerImpl + namespace Internal { - public: - void ReadThreadProc( Event* _exitEvent ); + namespace Platform + { + class SerialControllerImpl + { + public: + void ReadThreadProc(Event* _exitEvent); - private: - friend class SerialController; + private: + friend class SerialController; - SerialControllerImpl( SerialController* _owner ); - ~SerialControllerImpl(); + SerialControllerImpl(SerialController* _owner); + ~SerialControllerImpl(); - bool Open(); - void Close(); + bool Open(); + void Close(); - uint32 Write( uint8* _buffer, uint32 _length ); + uint32 Write(uint8* _buffer, uint32 _length); - bool Init( uint32 const _attempts ); - void Read(Event* _exitEvent); + bool Init(uint32 const _attempts); + void Read(Event* _exitEvent); - SerialController* m_owner; - int m_hSerialController; - Thread* m_pThread; - - static void SerialReadThreadEntryPoint( Event* _exitEvent, void* _content ); - }; + SerialController* m_owner; + int m_hSerialController; + Thread* m_pThread; + static void SerialReadThreadEntryPoint(Event* _exitEvent, void* _content); + }; + } // namespace platform + } // namespace Internal } // namespace OpenZWave #endif //_SerialControllerImpl_H diff --git a/cpp/src/platform/unix/ThreadImpl.cpp b/cpp/src/platform/unix/ThreadImpl.cpp index 4ef5744c45..82b44beb72 100644 --- a/cpp/src/platform/unix/ThreadImpl.cpp +++ b/cpp/src/platform/unix/ThreadImpl.cpp @@ -35,152 +35,140 @@ #define pthread_yield pthread_yield_np #endif -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -ThreadImpl::ThreadImpl -( - Thread* _owner, - string const& _tname -): - m_owner( _owner ), + ThreadImpl::ThreadImpl(Thread* _owner, string const& _tname) : + m_owner(_owner), // m_hThread( NULL ), /* p_thread_t isn't a pointer in Linux, so can't do this */ - m_bIsRunning( false ), - m_name( _tname ) -{ -} + m_bIsRunning(false), m_name(_tname) + { + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -ThreadImpl::~ThreadImpl -( -) -{ -} + ThreadImpl::~ThreadImpl() + { + } //----------------------------------------------------------------------------- // // Start a function running on this thread //----------------------------------------------------------------------------- -bool ThreadImpl::Start -( - Thread::pfnThreadProc_t _pfnThreadProc, - Event* _exitEvent, - void* _pContext -) -{ - pthread_attr_t ta; - - pthread_attr_init( &ta ); - pthread_attr_setstacksize ( &ta, 0 ); - pthread_attr_setdetachstate ( &ta, PTHREAD_CREATE_JOINABLE ); - - // Create a thread to run the specified function - m_pfnThreadProc = _pfnThreadProc; - m_pContext = _pContext; - m_exitEvent = _exitEvent; - m_exitEvent->Reset(); - - pthread_create ( &m_hThread, &ta, ThreadImpl::ThreadProc, this ); - string threadname("OZW-"); - threadname.append(m_name); -#if !defined(__APPLE_CC__) && !defined(__FreeBSD__) - pthread_setname_np( m_hThread, threadname.c_str() ); + bool ThreadImpl::Start(Thread::pfnThreadProc_t _pfnThreadProc, Event* _exitEvent, void* _pContext) + { + pthread_attr_t ta; + + pthread_attr_init(&ta); + pthread_attr_setstacksize(&ta, 0); + pthread_attr_setdetachstate(&ta, PTHREAD_CREATE_JOINABLE); + + // Create a thread to run the specified function + m_pfnThreadProc = _pfnThreadProc; + m_pContext = _pContext; + m_exitEvent = _exitEvent; + m_exitEvent->Reset(); + + pthread_create(&m_hThread, &ta, ThreadImpl::ThreadProc, this); + string threadname("OZW-"); + threadname.append(m_name); +#if !defined(__APPLE_CC__) && !defined(__FreeBSD__) && !defined(__NetBSD__) + pthread_setname_np( m_hThread, threadname.c_str() ); +#elif defined(__NetBSD__) + if ( threadname.length() > PTHREAD_MAX_NAMELEN_NP ) + threadname.resize( PTHREAD_MAX_NAMELEN_NP ); + pthread_setname_np( m_hThread, "%s", (void *)threadname.c_str() ); #endif - //fprintf(stderr, "thread %s starting %08x\n", m_name.c_str(), m_hThread); - //fflush(stderr); + //fprintf(stderr, "thread %s starting %08x\n", m_name.c_str(), m_hThread); + //fflush(stderr); - pthread_attr_destroy ( &ta ); - return true; -} + pthread_attr_destroy(&ta); + return true; + } //----------------------------------------------------------------------------- // // End this thread //----------------------------------------------------------------------------- -bool ThreadImpl::Terminate -( -) -{ - void* data = NULL; + bool ThreadImpl::Terminate() + { + void* data = NULL; - //fprintf(stderr, "thread %s stopping %08x running %d\n", m_name.c_str(), m_hThread, m_bIsRunning ); - //fflush(stderr); - if( !m_bIsRunning ) - { - return false; - } + //fprintf(stderr, "thread %s stopping %08x running %d\n", m_name.c_str(), m_hThread, m_bIsRunning ); + //fflush(stderr); + if (!m_bIsRunning) + { + return false; + } - // This will kill an app that doesn't catch and ignore it. - // We need to find another way to interrupt select. - // thread_kill( m_hThread, SIGALRM ); + // This will kill an app that doesn't catch and ignore it. + // We need to find another way to interrupt select. + // thread_kill( m_hThread, SIGALRM ); - //m_hThread = NULL; - m_bIsRunning = false; - pthread_cancel( m_hThread ); - pthread_join( m_hThread, &data ); + //m_hThread = NULL; + m_bIsRunning = false; + pthread_cancel(m_hThread); + pthread_join(m_hThread, &data); - return true; -} + return true; + } //----------------------------------------------------------------------------- // // Cause thread to sleep for the specified number of milliseconds //----------------------------------------------------------------------------- -void ThreadImpl::Sleep -( - uint32 _millisecs -) -{ - usleep( _millisecs*1000 ); -} + void ThreadImpl::Sleep(uint32 _millisecs) + { + usleep(_millisecs * 1000); + } //----------------------------------------------------------------------------- // // Test whether the thread has completed //----------------------------------------------------------------------------- -bool ThreadImpl::IsSignalled -( -) -{ - return !m_bIsRunning; -} + bool ThreadImpl::IsSignalled() + { + return !m_bIsRunning; + } //----------------------------------------------------------------------------- // // Entry point for running a function on this thread //----------------------------------------------------------------------------- -void *ThreadImpl::ThreadProc -( - void* _pArg -) -{ - ThreadImpl* pImpl = (ThreadImpl*)_pArg; - //fprintf(stderr, "thread %s run begin %08x running %d\n", pImpl->m_name.c_str(), pImpl->m_hThread, pImpl->m_bIsRunning ); - //fflush(stderr); - pImpl->Run(); - //fprintf(stderr, "thread %s run end %08x running %d\n", pImpl->m_name.c_str(), pImpl->m_hThread, pImpl->m_bIsRunning ); - //fflush(stderr); - return 0; -} + void *ThreadImpl::ThreadProc(void* _pArg) + { + ThreadImpl* pImpl = (ThreadImpl*) _pArg; + //fprintf(stderr, "thread %s run begin %08x running %d\n", pImpl->m_name.c_str(), pImpl->m_hThread, pImpl->m_bIsRunning ); + //fflush(stderr); + pImpl->Run(); + //fprintf(stderr, "thread %s run end %08x running %d\n", pImpl->m_name.c_str(), pImpl->m_hThread, pImpl->m_bIsRunning ); + //fflush(stderr); + return 0; + } //----------------------------------------------------------------------------- // // Entry point for running a function on this thread //----------------------------------------------------------------------------- -void ThreadImpl::Run -( -) -{ - m_bIsRunning = true; - m_pfnThreadProc( m_exitEvent, m_pContext ); - m_bIsRunning = false; - - // Let any watchers know that the thread has finished running - m_owner->Notify(); -} + void ThreadImpl::Run() + { + m_bIsRunning = true; + m_pfnThreadProc(m_exitEvent, m_pContext); + m_bIsRunning = false; + + // Let any watchers know that the thread has finished running + m_owner->Notify(); + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/unix/ThreadImpl.h b/cpp/src/platform/unix/ThreadImpl.h index 96e8f845e4..e0da4de28d 100644 --- a/cpp/src/platform/unix/ThreadImpl.h +++ b/cpp/src/platform/unix/ThreadImpl.h @@ -35,33 +35,40 @@ namespace OpenZWave { - class Thread; - class Event; - - class ThreadImpl - { - private: - friend class Thread; + namespace Internal + { + namespace Platform + { - ThreadImpl( Thread* _owner, string const& _tname ); - ~ThreadImpl(); + class Thread; + class Event; - bool Start( Thread::pfnThreadProc_t _pfnThreadProc, Event* _exitEvent, void* _context ); - void Sleep( uint32 _millisecs ); - bool IsSignalled(); - bool Terminate(); + class ThreadImpl + { + private: + friend class Thread; - void Run(); - static void* ThreadProc( void *parg); + ThreadImpl(Thread* _owner, string const& _tname); + ~ThreadImpl(); - Thread* m_owner; - Event* m_exitEvent; - pthread_t m_hThread; - Thread::pfnThreadProc_t m_pfnThreadProc; - void* m_pContext; - bool m_bIsRunning; - string m_name; - }; + bool Start(Thread::pfnThreadProc_t _pfnThreadProc, Event* _exitEvent, void* _context); + void Sleep(uint32 _millisecs); + bool IsSignalled(); + bool Terminate(); + + void Run(); + static void* ThreadProc(void *parg); + + Thread* m_owner; + Event* m_exitEvent; + pthread_t m_hThread; + Thread::pfnThreadProc_t m_pfnThreadProc; + void* m_pContext; + bool m_bIsRunning; + string m_name; + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_ThreadImpl_H diff --git a/cpp/src/platform/unix/TimeStampImpl.cpp b/cpp/src/platform/unix/TimeStampImpl.cpp index b8588e0e42..34045893cf 100644 --- a/cpp/src/platform/unix/TimeStampImpl.cpp +++ b/cpp/src/platform/unix/TimeStampImpl.cpp @@ -30,115 +30,108 @@ #include "Defs.h" #include "TimeStampImpl.h" -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -TimeStampImpl::TimeStampImpl -( -) -{ - SetTime(0); -} + TimeStampImpl::TimeStampImpl() + { + SetTime(0); + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -TimeStampImpl::~TimeStampImpl -( -) -{ -} + TimeStampImpl::~TimeStampImpl() + { + } //----------------------------------------------------------------------------- // // Sets the timestamp to now, plus an offset in milliseconds //----------------------------------------------------------------------------- -void TimeStampImpl::SetTime -( - int32 _milliseconds // = 0 -) -{ - struct timeval now; - gettimeofday(&now, NULL); - - m_stamp.tv_sec = now.tv_sec + (_milliseconds / 1000); - - // Now add the remainder of our timeout to the microseconds part of 'now' - now.tv_usec += ((_milliseconds % 1000) * 1000); - - // Careful now! Did it wrap? - if(now.tv_usec >= 1000000) - { - // Yes it did so bump our seconds and modulo - now.tv_usec %= 1000000; - m_stamp.tv_sec++; - } - - m_stamp.tv_nsec = now.tv_usec * 1000; -} + void TimeStampImpl::SetTime(int32 _milliseconds // = 0 + ) + { + struct timeval now; + gettimeofday(&now, NULL); + + m_stamp.tv_sec = now.tv_sec + (_milliseconds / 1000); + + // Now add the remainder of our timeout to the microseconds part of 'now' + now.tv_usec += ((_milliseconds % 1000) * 1000); + + // Careful now! Did it wrap? + if (now.tv_usec >= 1000000) + { + // Yes it did so bump our seconds and modulo + now.tv_usec %= 1000000; + m_stamp.tv_sec++; + } + + m_stamp.tv_nsec = now.tv_usec * 1000; + } //----------------------------------------------------------------------------- // // Gets the difference between now and the timestamp time in milliseconds //----------------------------------------------------------------------------- -int32 TimeStampImpl::TimeRemaining -( -) -{ - int32 diff; - - struct timeval now; - gettimeofday(&now, NULL); - - // Seconds - diff = (int32)((m_stamp.tv_sec - now.tv_sec)*1000); - - // Milliseconds - diff += (((m_stamp.tv_nsec/1000)-now.tv_usec)/1000); - - return diff; -} + int32 TimeStampImpl::TimeRemaining() + { + int32 diff; + + struct timeval now; + gettimeofday(&now, NULL); + + // Seconds + diff = (int32) ((m_stamp.tv_sec - now.tv_sec) * 1000); + + // Milliseconds + diff += (((m_stamp.tv_nsec / 1000) - now.tv_usec) / 1000); + + return diff; + } //----------------------------------------------------------------------------- // // Return a string representation //----------------------------------------------------------------------------- -string TimeStampImpl::GetAsString -( -) -{ - char str[100]; - // use threadsafe verion of localtime. Reported by nihilus, 2019-04 - // https://www.gnu.org/software/libc/manual/html_node/Broken_002ddown-Time.html#Broken_002ddown-Time - struct tm *tm, xtm; - memset(&xtm, 0, sizeof(xtm)); - tm = localtime_r( &m_stamp.tv_sec, &xtm); - - snprintf( str, sizeof(str), "%04d-%02d-%02d %02d:%02d:%02d:%03d ", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, - tm->tm_hour, tm->tm_min, tm->tm_sec, (int)(m_stamp.tv_nsec / (1000*1000)) ); - return str; -} + std::string TimeStampImpl::GetAsString() + { + char str[100]; + // use threadsafe verion of localtime. Reported by nihilus, 2019-04 + // https://www.gnu.org/software/libc/manual/html_node/Broken_002ddown-Time.html#Broken_002ddown-Time + struct tm *tm, xtm; + memset(&xtm, 0, sizeof(xtm)); + tm = localtime_r(&m_stamp.tv_sec, &xtm); + + snprintf(str, sizeof(str), "%04d-%02d-%02d %02d:%02d:%02d:%03d ", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, (int) (m_stamp.tv_nsec / (1000 * 1000))); + return str; + } //----------------------------------------------------------------------------- // // Overload the subtract operator to get the difference between two // timestamps in milliseconds //----------------------------------------------------------------------------- -int32 TimeStampImpl::operator- -( - TimeStampImpl const& _other -) -{ - // Seconds - int32 diff = (int32)((m_stamp.tv_sec-_other.m_stamp.tv_sec)*1000); - - // Milliseconds - diff += ((m_stamp.tv_nsec - _other.m_stamp.tv_nsec)/1000000); - - return diff; -} + int32 TimeStampImpl::operator-(TimeStampImpl const& _other) + { + // Seconds + int32 diff = (int32) ((m_stamp.tv_sec - _other.m_stamp.tv_sec) * 1000); + + // Milliseconds + diff += ((m_stamp.tv_nsec - _other.m_stamp.tv_nsec) / 1000000); + + return diff; + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/unix/TimeStampImpl.h b/cpp/src/platform/unix/TimeStampImpl.h index f7a8fecefe..d798fec7e7 100644 --- a/cpp/src/platform/unix/TimeStampImpl.h +++ b/cpp/src/platform/unix/TimeStampImpl.h @@ -35,56 +35,61 @@ namespace OpenZWave { - /** \brief Windows implementation of a timestamp. - */ - class TimeStampImpl + namespace Internal { - public: - /** - * Constructor. - * Creates a TimeStampImpl object. - */ - TimeStampImpl(); + namespace Platform + { + /** \brief Windows implementation of a timestamp. + */ + class TimeStampImpl + { + public: + /** + * Constructor. + * Creates a TimeStampImpl object. + */ + TimeStampImpl(); - /** - * Destructor. - * Destroys the TimeStampImpl object. - */ - ~TimeStampImpl(); + /** + * Destructor. + * Destroys the TimeStampImpl object. + */ + ~TimeStampImpl(); - /** - * SetTime. Sets the timestamp to now, plus the offset in milliseconds. - * \param _milliseconds positive or negative offset from - * now in milliseconds. - */ - void SetTime( int32 _milliseconds ); + /** + * SetTime. Sets the timestamp to now, plus the offset in milliseconds. + * \param _milliseconds positive or negative offset from + * now in milliseconds. + */ + void SetTime(int32 _milliseconds); - /** - * TimeRemaining. Gets the difference between now and the timestamp - * time in milliseconds. - * \return milliseconds remaining until we reach the timestamp. The - * return value is negative if the timestamp is in the past. - */ - int32 TimeRemaining(); + /** + * TimeRemaining. Gets the difference between now and the timestamp + * time in milliseconds. + * \return milliseconds remaining until we reach the timestamp. The + * return value is negative if the timestamp is in the past. + */ + int32 TimeRemaining(); - /** - * Return as as string - */ - string GetAsString(); + /** + * Return as as string + */ + string GetAsString(); - /** - * Overload the subtract operator to get the difference between - * two timestamps in milliseconds. - */ - int32 operator- ( TimeStampImpl const& _other ); + /** + * Overload the subtract operator to get the difference between + * two timestamps in milliseconds. + */ + int32 operator-(TimeStampImpl const& _other); - private: - TimeStampImpl( TimeStampImpl const& ); // prevent copy - TimeStampImpl& operator = ( TimeStampImpl const& ); // prevent assignment - - struct timespec m_stamp; - }; + private: + TimeStampImpl(TimeStampImpl const&); // prevent copy + TimeStampImpl& operator =(TimeStampImpl const&); // prevent assignment + struct timespec m_stamp; + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_TimeStampImpl_H diff --git a/cpp/src/platform/unix/WaitImpl.cpp b/cpp/src/platform/unix/WaitImpl.cpp index 6c7fa2278e..7011249331 100644 --- a/cpp/src/platform/unix/WaitImpl.cpp +++ b/cpp/src/platform/unix/WaitImpl.cpp @@ -34,129 +34,122 @@ #include #include -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -WaitImpl::WaitImpl -( - Wait* _owner -): - m_owner( _owner ) -{ - pthread_mutexattr_t ma; - pthread_mutexattr_init ( &ma ); - pthread_mutexattr_settype( &ma, PTHREAD_MUTEX_RECURSIVE ); - pthread_mutex_init( &m_criticalSection, &ma ); - pthread_mutexattr_destroy( &ma ); -} + WaitImpl::WaitImpl(Wait* _owner) : + m_owner(_owner) + { + pthread_mutexattr_t ma; + pthread_mutexattr_init(&ma); + pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&m_criticalSection, &ma); + pthread_mutexattr_destroy(&ma); + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -WaitImpl::~WaitImpl -( -) -{ - pthread_mutex_destroy( &m_criticalSection ); -} + WaitImpl::~WaitImpl() + { + pthread_mutex_destroy(&m_criticalSection); + } //----------------------------------------------------------------------------- // // Add a watcher to our object. //----------------------------------------------------------------------------- -void WaitImpl::AddWatcher -( - Wait::pfnWaitNotification_t _callback, - void* _context -) -{ - // Add the watcher to our list - Watcher watcher; - watcher.m_callback = _callback; - watcher.m_context = _context; - int err; - - if( (err = pthread_mutex_lock( &m_criticalSection )) != 0 ) - { - fprintf(stderr, "WaitImpl::AddWatcher lock error %s\n", strerror(err) ); - assert( 0 ); - } - m_watchers.push_back( watcher ); - if( (err = pthread_mutex_unlock( &m_criticalSection )) != 0 ) - { - fprintf(stderr, "WaitImpl::AddWatcher unlock error %s\n", strerror(err) ); - assert( 0 ); - } + void WaitImpl::AddWatcher(Wait::pfnWaitNotification_t _callback, void* _context) + { + // Add the watcher to our list + Watcher watcher; + watcher.m_callback = _callback; + watcher.m_context = _context; + int err; - // If the object is already in a signalled state, notify the watcher immediately - if( m_owner->IsSignalled() ) - { - _callback( _context ); - } -} + if ((err = pthread_mutex_lock(&m_criticalSection)) != 0) + { + fprintf(stderr, "WaitImpl::AddWatcher lock error %s\n", strerror(err)); + assert(0); + } + m_watchers.push_back(watcher); + if ((err = pthread_mutex_unlock(&m_criticalSection)) != 0) + { + fprintf(stderr, "WaitImpl::AddWatcher unlock error %s\n", strerror(err)); + assert(0); + } + + // If the object is already in a signalled state, notify the watcher immediately + if (m_owner->IsSignalled()) + { + _callback(_context); + } + } //----------------------------------------------------------------------------- // // Remove a watcher from our object. //----------------------------------------------------------------------------- -bool WaitImpl::RemoveWatcher -( - Wait::pfnWaitNotification_t _callback, - void* _context -) -{ - bool res = false; + bool WaitImpl::RemoveWatcher(Wait::pfnWaitNotification_t _callback, void* _context) + { + bool res = false; - if( pthread_mutex_lock( &m_criticalSection ) != 0 ) - { - fprintf(stderr, "WaitImpl::RemoveWatcher lock error %d\n", errno ); - assert( 0 ); - } + if (pthread_mutex_lock(&m_criticalSection) != 0) + { + fprintf(stderr, "WaitImpl::RemoveWatcher lock error %d\n", errno); + assert(0); + } - for( list::iterator it=m_watchers.begin(); it!=m_watchers.end(); ++it ) - { - Watcher const& watcher = *it; - if( ( watcher.m_callback == _callback ) && ( watcher.m_context == _context ) ) - { - m_watchers.erase( it ); - res = true; - break; - } - } + for (list::iterator it = m_watchers.begin(); it != m_watchers.end(); ++it) + { + Watcher const& watcher = *it; + if ((watcher.m_callback == _callback) && (watcher.m_context == _context)) + { + m_watchers.erase(it); + res = true; + break; + } + } - if( pthread_mutex_unlock( &m_criticalSection ) != 0 ) - { - fprintf(stderr, "WaitImpl::RemoveWatcher unlock error %d\n", errno ); - assert( 0 ); - } - return res; -} + if (pthread_mutex_unlock(&m_criticalSection) != 0) + { + fprintf(stderr, "WaitImpl::RemoveWatcher unlock error %d\n", errno); + assert(0); + } + return res; + } //----------------------------------------------------------------------------- // // Notify all the watchers that the object has become signalled //----------------------------------------------------------------------------- -void WaitImpl::Notify -( -) -{ - if( pthread_mutex_lock( &m_criticalSection ) != 0 ) - { - fprintf(stderr, "WaitImpl::Notify lock error %d\n", errno ); - assert( 0 ); - } - for( list::iterator it=m_watchers.begin(); it!=m_watchers.end(); ++it ) - { - Watcher const& watcher = *it; - watcher.m_callback( watcher.m_context ); - } - if( pthread_mutex_unlock( &m_criticalSection ) != 0 ) - { - fprintf(stderr, "WaitImpl::Notify unlock error %d\n", errno ); - assert( 0 ); - } -} + void WaitImpl::Notify() + { + if (pthread_mutex_lock(&m_criticalSection) != 0) + { + fprintf(stderr, "WaitImpl::Notify lock error %d\n", errno); + assert(0); + } + for (list::iterator it = m_watchers.begin(); it != m_watchers.end(); ++it) + { + Watcher const& watcher = *it; + watcher.m_callback(watcher.m_context); + } + if (pthread_mutex_unlock(&m_criticalSection) != 0) + { + fprintf(stderr, "WaitImpl::Notify unlock error %d\n", errno); + assert(0); + } + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/unix/WaitImpl.h b/cpp/src/platform/unix/WaitImpl.h index 58c4e025bb..6257a84137 100644 --- a/cpp/src/platform/unix/WaitImpl.h +++ b/cpp/src/platform/unix/WaitImpl.h @@ -38,36 +38,41 @@ namespace OpenZWave { - /** \brief Windows specific implementation of Wait objects. - */ - class WaitImpl + namespace Internal { - private: - friend class Wait; - - WaitImpl( Wait* _owner ); - virtual ~WaitImpl(); + namespace Platform + { + /** \brief Windows specific implementation of Wait objects. + */ + class WaitImpl + { + private: + friend class Wait; - void AddWatcher( Wait::pfnWaitNotification_t _callback, void* _context ); - bool RemoveWatcher( Wait::pfnWaitNotification_t _callback, void* _context ); - void Notify(); + WaitImpl(Wait* _owner); + virtual ~WaitImpl(); - static int32 Multiple( Wait** _objects, uint32 _numObjects, int32 _timeout = -1 ); + void AddWatcher(Wait::pfnWaitNotification_t _callback, void* _context); + bool RemoveWatcher(Wait::pfnWaitNotification_t _callback, void* _context); + void Notify(); - WaitImpl( Wait const& ); // prevent copy - WaitImpl& operator = ( WaitImpl const& ); // prevent assignment + static int32 Multiple(Wait** _objects, uint32 _numObjects, int32 _timeout = -1); - struct Watcher - { - Wait::pfnWaitNotification_t m_callback; - void* m_context; - }; + WaitImpl(Wait const&); // prevent copy + WaitImpl& operator =(WaitImpl const&); // prevent assignment - list m_watchers; - Wait* m_owner; - pthread_mutex_t m_criticalSection; - }; + struct Watcher + { + Wait::pfnWaitNotification_t m_callback; + void* m_context; + }; + list m_watchers; + Wait* m_owner; + pthread_mutex_t m_criticalSection; + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_WaitImpl_H diff --git a/cpp/src/platform/winRT/DNSImpl.cpp b/cpp/src/platform/winRT/DNSImpl.cpp index b92be1b2b7..5dd53bdbc9 100644 --- a/cpp/src/platform/winRT/DNSImpl.cpp +++ b/cpp/src/platform/winRT/DNSImpl.cpp @@ -32,54 +32,55 @@ #include "DNSImpl.h" - - -using namespace OpenZWave; - -DNSImpl::DNSImpl -( -) +namespace OpenZWave { + namespace Internal + { + namespace Platform + { -} + DNSImpl::DNSImpl() + { -DNSImpl::~DNSImpl -( -) -{ + } -} + DNSImpl::~DNSImpl() + { -bool DNSImpl::LookupTxT -( -string lookup, -string &result -) -{ + } + + bool DNSImpl::LookupTxT(string lookup, string &result) + { #if 0 - PDNS_RECORD qr, rp; - DNS_STATUS rc; + PDNS_RECORD qr, rp; + DNS_STATUS rc; - rc = DnsQuery(lookup.c_str(), DNS_TYPE_TEXT, DNS_QUERY_STANDARD, NULL, &qr, NULL); - if (rc != ERROR_SUCCESS) { - Log::Write(LogLevel_Warning, "Error looking up txt Record: %s - %d", lookup.c_str(), rc); - status = DNSError_InternaError; - return false; - } + rc = DnsQuery(lookup.c_str(), DNS_TYPE_TEXT, DNS_QUERY_STANDARD, NULL, &qr, NULL); + if (rc != ERROR_SUCCESS) + { + Log::Write(LogLevel_Warning, "Error looking up txt Record: %s - %d", lookup.c_str(), rc); + status = DNSError_InternaError; + return false; + } - for (rp = qr; rp != NULL; rp = rp->pNext) { - if (rp->wType == DNS_TYPE_TEXT) { - result = rp->Data.TXT.pStringArray[0]; - status = DNSError_None; - break; - } - } + for (rp = qr; rp != NULL; rp = rp->pNext) + { + if (rp->wType == DNS_TYPE_TEXT) + { + result = rp->Data.TXT.pStringArray[0]; + status = DNSError_None; + break; + } + } - DnsRecordListFree(qr, DnsFreeRecordList); + DnsRecordListFree(qr, DnsFreeRecordList); - return true; + return true; #endif - Log::Write(LogLevel_Error, "DNS Lookups Not Implemented on WinRT Platform"); - status = DNSError_InternalError; - return false; -} + Log::Write(LogLevel_Error, "DNS Lookups Not Implemented on WinRT Platform"); + status = DNSError_InternalError; + return false; + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/winRT/DNSImpl.h b/cpp/src/platform/winRT/DNSImpl.h index f78ac97c78..3175b6f2ef 100644 --- a/cpp/src/platform/winRT/DNSImpl.h +++ b/cpp/src/platform/winRT/DNSImpl.h @@ -33,14 +33,22 @@ namespace OpenZWave { - class DNSImpl { - public: - DNSImpl(); - virtual ~DNSImpl(); - virtual bool LookupTxT(string, string &); - DNSError status; - private: + namespace Internal + { + namespace Platform + { - }; -} + class DNSImpl + { + public: + DNSImpl(); + virtual ~DNSImpl(); + virtual bool LookupTxT(string, string &); + DNSError status; + private: + + }; + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave #endif diff --git a/cpp/src/platform/winRT/EventImpl.cpp b/cpp/src/platform/winRT/EventImpl.cpp index 2acfc6a21a..4e537f2590 100644 --- a/cpp/src/platform/winRT/EventImpl.cpp +++ b/cpp/src/platform/winRT/EventImpl.cpp @@ -30,73 +30,67 @@ #include "Defs.h" #include "EventImpl.h" -using namespace OpenZWave; - +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -EventImpl::EventImpl -( -) -{ - // Create a manual reset event - m_hEvent = ::CreateEventEx( NULL, NULL, CREATE_EVENT_MANUAL_RESET, SYNCHRONIZE | EVENT_MODIFY_STATE ); -} + EventImpl::EventImpl() + { + // Create a manual reset event + m_hEvent = ::CreateEventEx( NULL, NULL, CREATE_EVENT_MANUAL_RESET, SYNCHRONIZE | EVENT_MODIFY_STATE); + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -EventImpl::~EventImpl -( -) -{ - ::CloseHandle( m_hEvent ); -} + EventImpl::~EventImpl() + { + ::CloseHandle(m_hEvent); + } //----------------------------------------------------------------------------- // // Set the event to signalled //----------------------------------------------------------------------------- -void EventImpl::Set -( -) -{ - ::SetEvent( m_hEvent ); -} + void EventImpl::Set() + { + ::SetEvent(m_hEvent); + } //----------------------------------------------------------------------------- // // Set the event to not signalled //----------------------------------------------------------------------------- -void EventImpl::Reset -( -) -{ - ::ResetEvent( m_hEvent ); -} + void EventImpl::Reset() + { + ::ResetEvent(m_hEvent); + } //----------------------------------------------------------------------------- // // Test whether the event is set //----------------------------------------------------------------------------- -bool EventImpl::IsSignalled -( -) -{ - return( WAIT_OBJECT_0 == WaitForSingleObjectEx( m_hEvent, 0, FALSE) ); -} + bool EventImpl::IsSignalled() + { + return (WAIT_OBJECT_0 == WaitForSingleObjectEx(m_hEvent, 0, FALSE)); + } //----------------------------------------------------------------------------- // // Wait for the event to become signalled //----------------------------------------------------------------------------- -bool EventImpl::Wait -( - int32 const _timeout -) -{ - return( WAIT_TIMEOUT != ::WaitForSingleObjectEx( m_hEvent, (DWORD)_timeout, FALSE ) ); -} + bool EventImpl::Wait(int32 const _timeout) + { + return (WAIT_TIMEOUT != ::WaitForSingleObjectEx(m_hEvent, (DWORD) _timeout, FALSE)); + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/winRT/EventImpl.h b/cpp/src/platform/winRT/EventImpl.h index ec26b49fdb..900e39a7c2 100644 --- a/cpp/src/platform/winRT/EventImpl.h +++ b/cpp/src/platform/winRT/EventImpl.h @@ -33,27 +33,33 @@ namespace OpenZWave { - /** \brief Windows-specific implementation of the Event class. - */ - class EventImpl + namespace Internal { - private: - friend class Event; - friend class SocketImpl; - friend class Wait; + namespace Platform + { - EventImpl(); - ~EventImpl(); + /** \brief Windows-specific implementation of the Event class. + */ + class EventImpl + { + private: + friend class Event; + friend class SocketImpl; + friend class Wait; - void Set(); - void Reset(); + EventImpl(); + ~EventImpl(); - bool Wait( int32 _timeout ); // The wait method is to be used only by the Wait::Multiple method - bool IsSignalled(); + void Set(); + void Reset(); - HANDLE m_hEvent; - }; + bool Wait(int32 _timeout); // The wait method is to be used only by the Wait::Multiple method + bool IsSignalled(); + HANDLE m_hEvent; + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_EventImpl_H diff --git a/cpp/src/platform/winRT/FileOpsImpl.cpp b/cpp/src/platform/winRT/FileOpsImpl.cpp index eaf2b7b795..f57b4cfed5 100644 --- a/cpp/src/platform/winRT/FileOpsImpl.cpp +++ b/cpp/src/platform/winRT/FileOpsImpl.cpp @@ -30,159 +30,155 @@ #include "FileOpsImpl.h" #include "Utils.h" -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -FileOpsImpl::FileOpsImpl -( -) -{ -} + FileOpsImpl::FileOpsImpl() + { + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -FileOpsImpl::~FileOpsImpl -( -) -{ -} + FileOpsImpl::~FileOpsImpl() + { + } //----------------------------------------------------------------------------- // // Determine if a folder exists and is accessible by the calling App //----------------------------------------------------------------------------- -bool FileOpsImpl::FolderExists( - const string &_folderName -) -{ - WIN32_FILE_ATTRIBUTE_DATA fad = { 0 }; - wstring wFolderName(_folderName.begin(), _folderName.end()); - - if (0 == GetFileAttributesEx(wFolderName.c_str(), GetFileExInfoStandard, &fad)) - return false; - - return (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)? true: false; -} - -bool FileOpsImpl::FileExists -( - const string _filename - ) -{ - WIN32_FILE_ATTRIBUTE_DATA fad = { 0 }; - wstring wFileName(_filename.begin(), _filename.end()); - - if (0 == GetFileAttributesEx(wFileName.c_str(), GetFileExInfoStandard, &fad)) - return false; - - return (fad.dwFileAttributes != INVALID_FILE_ATTRIBUTES && - !(fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)); -} - -bool FileOpsImpl::FileWriteable -( - const string _filename - ) -{ - WIN32_FILE_ATTRIBUTE_DATA fad = { 0 }; - - - if (!FileExists(_filename)) { - /* check if the directory is writtable */ - wstring wFileName(ozwdirname(_filename).begin(), ozwdirname(_filename).end()); - - if (0 == GetFileAttributesEx(wFileName.c_str(), GetFileExInfoStandard, &fad)) - return false; - } - else { - wstring wFileName(_filename.begin(), _filename.end()); - - if (0 == GetFileAttributesEx(wFileName.c_str(), GetFileExInfoStandard, &fad)) - return false; - } - - return (fad.dwFileAttributes != INVALID_FILE_ATTRIBUTES && - !(fad.dwFileAttributes & FILE_ATTRIBUTE_READONLY)); - -} - -bool FileOpsImpl::FileRotate -( - const string _filename - ) -{ - int i = 1; - string newFile; - /* find a filename not used yet */ - newFile = _filename; - newFile.append(".").append(intToString(i)); - while (FileExists(newFile)) { - i++; - newFile = _filename; - newFile.append(".").append(intToString(i)); - } - /* copy the file */ - if (!FileCopy(_filename, newFile)) { - Log::Write(LogLevel_Warning, "File Rotate Failed: %s -> %s", _filename.c_str(), newFile.c_str()); - return false; - } - /* remove the old file */ - if (DeleteFileA(_filename.c_str()) == 0) { - Log::Write(LogLevel_Warning, "File Removal failed: %s", _filename.c_str()); - return false; - } - return true; -} - - -bool FileOpsImpl::FileCopy -( - const string _sourcefile, - const string _destfile - ) -{ - - if (!FileExists(_sourcefile)) { - Log::Write(LogLevel_Warning, "Source File %s doesn't exist in FileCopy", _sourcefile.c_str()); - return false; - } - if (FileExists(_destfile)) { - Log::Write(LogLevel_Warning, "Destination File %s exists in FileCopy", _destfile.c_str()); - return false; - } - - /* make sure the Destination Folder Exists */ - if (!FolderExists(ozwdirname(_destfile))) { - Log::Write(LogLevel_Warning, "Destination Folder %s Doesn't Exist", ozwdirname(_destfile)); - return false; - } - wstring wSrcFileName(_sourcefile.begin(), _sourcefile.end()); - wstring wDstFileName(_destfile.begin(), _destfile.end()); - - if (CopyFile2(wSrcFileName.c_str(), wDstFileName.c_str(), FALSE) == 0) { - Log::Write(LogLevel_Warning, "CopyFile Failed %s - %s", _sourcefile.c_str(), _destfile.c_str()); - return false; - } - return true; -} - -bool FileOpsImpl::FolderCreate -( - const string _dirname - ) -{ - if (FolderExists(_dirname)) { - Log::Write(LogLevel_Warning, "Folder %s Exists for FolderCreate", _dirname.c_str()); - return false; - } - if (CreateDirectoryA(_dirname.c_str(), NULL) == 0) { - Log::Write(LogLevel_Warning, "Create Directory Failed: %s", _dirname.c_str()); - return false; - } - return true; -} + bool FileOpsImpl::FolderExists(const string &_folderName) + { + WIN32_FILE_ATTRIBUTE_DATA fad = + { 0 }; + wstring wFolderName(_folderName.begin(), _folderName.end()); + + if (0 == GetFileAttributesEx(wFolderName.c_str(), GetFileExInfoStandard, &fad)) + return false; + + return (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? true : false; + } + + bool FileOpsImpl::FileExists(const string _filename) + { + WIN32_FILE_ATTRIBUTE_DATA fad = + { 0 }; + wstring wFileName(_filename.begin(), _filename.end()); + + if (0 == GetFileAttributesEx(wFileName.c_str(), GetFileExInfoStandard, &fad)) + return false; + + return (fad.dwFileAttributes != INVALID_FILE_ATTRIBUTES && !(fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)); + } + + bool FileOpsImpl::FileWriteable(const string _filename) + { + WIN32_FILE_ATTRIBUTE_DATA fad = + { 0 }; + + if (!FileExists(_filename)) + { + /* check if the directory is writtable */ + wstring wFileName(ozwdirname(_filename).begin(), ozwdirname(_filename).end()); + + if (0 == GetFileAttributesEx(wFileName.c_str(), GetFileExInfoStandard, &fad)) + return false; + } + else + { + wstring wFileName(_filename.begin(), _filename.end()); + + if (0 == GetFileAttributesEx(wFileName.c_str(), GetFileExInfoStandard, &fad)) + return false; + } + + return (fad.dwFileAttributes != INVALID_FILE_ATTRIBUTES && !(fad.dwFileAttributes & FILE_ATTRIBUTE_READONLY)); + + } + + bool FileOpsImpl::FileRotate(const string _filename) + { + int i = 1; + string newFile; + /* find a filename not used yet */ + newFile = _filename; + newFile.append(".").append(intToString(i)); + while (FileExists(newFile)) + { + i++; + newFile = _filename; + newFile.append(".").append(intToString(i)); + } + /* copy the file */ + if (!FileCopy(_filename, newFile)) + { + Log::Write(LogLevel_Warning, "File Rotate Failed: %s -> %s", _filename.c_str(), newFile.c_str()); + return false; + } + /* remove the old file */ + if (DeleteFileA(_filename.c_str()) == 0) + { + Log::Write(LogLevel_Warning, "File Removal failed: %s", _filename.c_str()); + return false; + } + return true; + } + + bool FileOpsImpl::FileCopy(const string _sourcefile, const string _destfile) + { + + if (!FileExists(_sourcefile)) + { + Log::Write(LogLevel_Warning, "Source File %s doesn't exist in FileCopy", _sourcefile.c_str()); + return false; + } + if (FileExists(_destfile)) + { + Log::Write(LogLevel_Warning, "Destination File %s exists in FileCopy", _destfile.c_str()); + return false; + } + + /* make sure the Destination Folder Exists */ + if (!FolderExists(ozwdirname(_destfile))) + { + Log::Write(LogLevel_Warning, "Destination Folder %s Doesn't Exist", ozwdirname(_destfile)); + return false; + } + wstring wSrcFileName(_sourcefile.begin(), _sourcefile.end()); + wstring wDstFileName(_destfile.begin(), _destfile.end()); + + if (CopyFile2(wSrcFileName.c_str(), wDstFileName.c_str(), FALSE) == 0) + { + Log::Write(LogLevel_Warning, "CopyFile Failed %s - %s", _sourcefile.c_str(), _destfile.c_str()); + return false; + } + return true; + } + + bool FileOpsImpl::FolderCreate(const string _dirname) + { + if (FolderExists(_dirname)) + { + Log::Write(LogLevel_Warning, "Folder %s Exists for FolderCreate", _dirname.c_str()); + return false; + } + if (CreateDirectoryA(_dirname.c_str(), NULL) == 0) + { + Log::Write(LogLevel_Warning, "Create Directory Failed: %s", _dirname.c_str()); + return false; + } + return true; + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/winRT/FileOpsImpl.h b/cpp/src/platform/winRT/FileOpsImpl.h index a192abf3d6..7fe13b9cc7 100644 --- a/cpp/src/platform/winRT/FileOpsImpl.h +++ b/cpp/src/platform/winRT/FileOpsImpl.h @@ -35,23 +35,29 @@ namespace OpenZWave { - class FileOpsImpl + namespace Internal { - friend class FileOps; + namespace Platform + { - private: - FileOpsImpl(); - ~FileOpsImpl(); + class FileOpsImpl + { + friend class FileOps; - bool FolderExists( const string &_filename ); - bool FileExists(const string _filename); - bool FileWriteable(const string _filename); - bool FileRotate(const string _filename); - bool FileCopy(const string, const string); - bool FolderCreate(const string _dirname); + private: + FileOpsImpl(); + ~FileOpsImpl(); - }; + bool FolderExists(const string &_filename); + bool FileExists(const string _filename); + bool FileWriteable(const string _filename); + bool FileRotate(const string _filename); + bool FileCopy(const string, const string); + bool FolderCreate(const string _dirname); + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_FileOpsImpl_H diff --git a/cpp/src/platform/winRT/HidControllerWinRT.cpp b/cpp/src/platform/winRT/HidControllerWinRT.cpp index 6e9c30e047..bbeb41bf44 100644 --- a/cpp/src/platform/winRT/HidControllerWinRT.cpp +++ b/cpp/src/platform/winRT/HidControllerWinRT.cpp @@ -33,14 +33,20 @@ #include #include -using namespace Windows::Devices::Enumeration; -using namespace Windows::Devices::HumanInterfaceDevice; -using namespace Windows::Devices::Usb; -using namespace Windows::Foundation; -using namespace Windows::Storage::Streams; -using namespace Platform; -using namespace Concurrency; -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { + + using namespace Windows::Devices::Enumeration; + using namespace Windows::Devices::HumanInterfaceDevice; + using namespace Windows::Devices::Usb; + using namespace Windows::Foundation; + using namespace Windows::Storage::Streams; + using namespace Platform; + using namespace Concurrency; #define AQS_FORMAT L"System.Devices.InterfaceClassGuid:=\"{4D1E55B2-F16F-11CF-88CB-001111000030}\" AND System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#True AND System.DeviceInterface.Hid.VendorId:=%04d AND System.DeviceInterface.Hid.ProductId:=%04d" #define AQS_LENGTH 300 @@ -49,228 +55,217 @@ using namespace OpenZWave; // // Constructor //----------------------------------------------------------------------------- -HidController::HidController() : - m_vendorId(0x1b5f), // Wayne Dalton - m_productId(0x01), // ControlThink ThinkStick - m_serialNumber(""), - m_hidControllerName(""), - m_bOpen(false) -{ -} + HidController::HidController() : + m_vendorId(0x1b5f), // Wayne Dalton + m_productId(0x01), // ControlThink ThinkStick + m_serialNumber(""), m_hidControllerName(""), m_bOpen(false) + { + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -HidController::~HidController() -{ - if (m_device != nullptr) - { - m_device->InputReportReceived -= m_inputReportEventToken; - } -} + HidController::~HidController() + { + if (m_device != nullptr) + { + m_device->InputReportReceived -= m_inputReportEventToken; + } + } //----------------------------------------------------------------------------- // // Set the USB vendor ID search value. The HID port must be closed for the setting to be accepted. //----------------------------------------------------------------------------- -bool HidController::SetVendorId -( -uint32 const _vendorId -) -{ - if (m_bOpen) - { - return false; - } + bool HidController::SetVendorId(uint32 const _vendorId) + { + if (m_bOpen) + { + return false; + } - m_vendorId = _vendorId; - return true; -} + m_vendorId = _vendorId; + return true; + } //----------------------------------------------------------------------------- // // Set the USB product ID search value. The HID port must be closed for the setting to be accepted. //----------------------------------------------------------------------------- -bool HidController::SetProductId (uint32 const _productId) -{ - if (m_bOpen) - { - return false; - } + bool HidController::SetProductId(uint32 const _productId) + { + if (m_bOpen) + { + return false; + } - m_productId = _productId; - return true; -} + m_productId = _productId; + return true; + } //----------------------------------------------------------------------------- // // Set the USB serial number search value. The HID port must be closed for the setting to be accepted. //----------------------------------------------------------------------------- -bool HidController::SetSerialNumber (string const& _serialNumber) -{ - if (m_bOpen) - { - return false; - } + bool HidController::SetSerialNumber(string const& _serialNumber) + { + if (m_bOpen) + { + return false; + } - m_serialNumber = _serialNumber; - return true; -} + m_serialNumber = _serialNumber; + return true; + } //----------------------------------------------------------------------------- // // Open and configure a HID port //----------------------------------------------------------------------------- -bool HidController::Open(string const& _hidControllerName) -{ - if (m_bOpen) - { - return false; - } + bool HidController::Open(string const& _hidControllerName) + { + if (m_bOpen) + { + return false; + } - m_hidControllerName = _hidControllerName; + m_hidControllerName = _hidControllerName; - bool success = false; - try - { - create_task(Init()).then([&success, this](bool initResult) - { - success = initResult; - if (success && m_device != nullptr) - { - m_inputReportEventToken = m_device->InputReportReceived += ref new TypedEventHandler - ([this](HidDevice ^sender, HidInputReportReceivedEventArgs ^args) + bool success = false; + try { - auto reader = DataReader::FromBuffer(args->Report->Data); - uint32 bufferSize = reader->UnconsumedBufferLength; - std::vector data(bufferSize); + create_task(Init()).then([&success, this](bool initResult) + { + success = initResult; + if (success && m_device != nullptr) + { + m_inputReportEventToken = m_device->InputReportReceived += ref new TypedEventHandler + ([this](HidDevice ^sender, HidInputReportReceivedEventArgs ^args) + { + auto reader = DataReader::FromBuffer(args->Report->Data); + uint32 bufferSize = reader->UnconsumedBufferLength; + std::vector data(bufferSize); - if (!data.empty()) - { - reader->ReadBytes(::Platform::ArrayReference(&data[0], bufferSize)); - Put(&data[0], bufferSize); - } - }); - } + if (!data.empty()) + { + reader->ReadBytes(::Platform::ArrayReference(&data[0], bufferSize)); + Put(&data[0], bufferSize); + } + }); + } - }).wait(); - } - catch (Platform::Exception^ ex) - { - } + }).wait(); + } + catch (::Platform::Exception^ ex) + { + } - return success; -} + return success; + } //----------------------------------------------------------------------------- // // Close a HID port //----------------------------------------------------------------------------- -bool HidController::Close() -{ - if (m_device != nullptr) - { - m_device->InputReportReceived -= m_inputReportEventToken; - delete m_device; - m_device = nullptr; - } - return true; -} + bool HidController::Close() + { + if (m_device != nullptr) + { + m_device->InputReportReceived -= m_inputReportEventToken; + delete m_device; + m_device = nullptr; + } + return true; + } //----------------------------------------------------------------------------- // // Open the HID port //----------------------------------------------------------------------------- -task HidController::Init() -{ - // Yields the same as API above w/o the usage page and usage Id filters - wchar_t buffer[AQS_LENGTH]; - swprintf_s(buffer, AQS_FORMAT, m_vendorId, m_productId); - auto selector = ref new String(buffer); + task HidController::Init() + { + // Yields the same as API above w/o the usage page and usage Id filters + wchar_t buffer[AQS_LENGTH]; + swprintf_s(buffer, AQS_FORMAT, m_vendorId, m_productId); + auto selector = ref new ::Platform::String(buffer); - return create_task(Windows::Devices::Enumeration::DeviceInformation::FindAllAsync(selector)) - .then([this](DeviceInformationCollection ^ devices) -> String ^ - { - String ^deviceId = L""; - for (auto iterator = devices->First(); iterator->HasCurrent; iterator->MoveNext()) - { - // Not sure how to differentiate when there are multiple things returned. - // Just return first matching ID for now - deviceId = iterator->Current->Id; - break; - } - return deviceId; + return create_task(Windows::Devices::Enumeration::DeviceInformation::FindAllAsync(selector)) + .then([this](DeviceInformationCollection ^ devices) -> ::Platform::String ^ + { + ::Platform::String ^deviceId = L""; + for (auto iterator = devices->First(); iterator->HasCurrent; iterator->MoveNext()) + { + // Not sure how to differentiate when there are multiple things returned. + // Just return first matching ID for now + deviceId = iterator->Current->Id; + break; + } + return deviceId; - }).then([this](String ^deviceId) -> IAsyncOperation ^ - { - return HidDevice::FromIdAsync(deviceId, Windows::Storage::FileAccessMode::Read); + }).then([this](::Platform::String ^deviceId) -> IAsyncOperation ^ + { + return HidDevice::FromIdAsync(deviceId, Windows::Storage::FileAccessMode::Read); - }).then([this](task deviceTask) -> bool - { - try - { - m_device = deviceTask.get(); + }).then([this](task deviceTask) -> bool + { + try + { + m_device = deviceTask.get(); - if (m_device == nullptr) - { - return false; - } + if (m_device == nullptr) + { + return false; + } - // Send Report ID 2 - 1 byte "0x04" - // Enables ZWave packet reports on ID 4 (tx) and ID 5 (rx) - uint8 data = 0x04; - SendFeatureReport(&data, 1, 2); + // Send Report ID 2 - 1 byte "0x04" + // Enables ZWave packet reports on ID 4 (tx) and ID 5 (rx) + uint8 data = 0x04; + SendFeatureReport(&data, 1, 2); - return true; - } - catch (Platform::Exception^ ex) - { - return false; + return true; + } + catch (::Platform::Exception^ ex) + { + return false; + } + }); } - }); -} //----------------------------------------------------------------------------- // // Send data to the HID port //----------------------------------------------------------------------------- -uint32 HidController::Write -( - uint8* _buffer, - uint32 _length -) -{ - // report Id 0x04 is tx feature report - return SendFeatureReport(_buffer, _length, 0x04); -} + uint32 HidController::Write(uint8* _buffer, uint32 _length) + { + // report Id 0x04 is tx feature report + return SendFeatureReport(_buffer, _length, 0x04); + } //----------------------------------------------------------------------------- // // Send a feature report with the specified data and report ID //----------------------------------------------------------------------------- -uint32 HidController::SendFeatureReport -( - uint8* _buffer, - uint32 _length, - unsigned short reportId -) -{ - auto featureReport = m_device->CreateFeatureReport(); - auto dataWriter = ref new DataWriter(); + uint32 HidController::SendFeatureReport(uint8* _buffer, uint32 _length, unsigned short reportId) + { + auto featureReport = m_device->CreateFeatureReport(); + auto dataWriter = ref new DataWriter(); - auto array = ref new Array(_buffer, _length); - dataWriter->WriteBytes(ArrayReference(_buffer, _length)); + auto array = ref new ::Platform::Array(_buffer, _length); + dataWriter->WriteBytes(::Platform::ArrayReference < uint8 > (_buffer, _length)); - featureReport->Data = dataWriter->DetachBuffer(); + featureReport->Data = dataWriter->DetachBuffer(); - uint32 bytesWritten = 0; - try - { - bytesWritten = create_task(m_device->SendFeatureReportAsync(featureReport)).get(); - } - catch (Platform::Exception^) - { - } - return bytesWritten; -} + uint32 bytesWritten = 0; + try + { + bytesWritten = create_task(m_device->SendFeatureReportAsync(featureReport)).get(); + } + catch (::Platform::Exception^) + { + } + return bytesWritten; + } + } // namespace Platform +} // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/winRT/HidControllerWinRT.h b/cpp/src/platform/winRT/HidControllerWinRT.h index 399552e001..fc0f37ad75 100644 --- a/cpp/src/platform/winRT/HidControllerWinRT.h +++ b/cpp/src/platform/winRT/HidControllerWinRT.h @@ -37,88 +37,94 @@ namespace OpenZWave { - class HidController : public Controller + namespace Internal { - public: - - /** - * Constructor. - * Creates an object that represents a HID port. - */ - HidController(); - - /** - * Destructor. - * Destroys the HID port object. - */ - virtual ~HidController(); - - /** - * Set the USB vendor ID search value. The HID port must be closed for the setting to be accepted. - * @param _baud Vendor ID value to match when enumerating USB HID devices. - * @return True if the vendor ID value was accepted. - * @see Open, Close - */ - bool SetVendorId(uint32 const _vendorId); - - /** - * Set the USB product ID search value. The HID port must be closed for the setting to be accepted. - * @param _parity Product ID value to match when enumerating USB HID devices. - * @return True if the product ID value was accepted. - * @see Open, Close - */ - bool SetProductId(uint32 const _productId); - - /** - * Set the USB serial number search value. The HID port must be closed for the setting to be accepted. - * @param _parity Serial number string to match when enumerating USB HID devices. If empty, any serial number will be accepted. - * @return True if the serial number value was accepted. - * @see Open, Close - */ - bool SetSerialNumber(string const& _serialNumber); - - /** - * Open a HID port. - * Attempts to open a HID port and initialize it with the specified paramters. - * @param _HidControllerName The name of the port to open. For example, ttyS1 on Linux, or \\.\COM2 in Windows. - * @return True if the port was opened and configured successfully. - * @see Close, Read, Write - */ - bool Open(string const& _hidControllerName); - - /** - * Close a HID port. - * Closes the HID port. - * @return True if the port was closed successfully, or false if the port was already closed, or an error occurred. - * @see Open - */ - bool Close(); - - /** - * Write to a HID port. - * Attempts to write data to an open HID port. - * @param _buffer Pointer to a block of memory containing the data to be written. - * @param _length Length in bytes of the data. - * @return The number of bytes written. - * @see Read, Open, Close - */ - uint32 Write(uint8* _buffer, uint32 _length); - - private: - - uint32 SendFeatureReport( uint8* _buffer, uint32 _length, unsigned short reportId ); - Concurrency::task Init(); - - Windows::Devices::HumanInterfaceDevice::HidDevice ^ m_device; - Windows::Foundation::EventRegistrationToken m_inputReportEventToken; - - uint32 m_vendorId; - uint32 m_productId; - string m_serialNumber; - string m_hidControllerName; - bool m_bOpen; - }; - + namespace Platform + { + + class HidController: public Controller + { + public: + + /** + * Constructor. + * Creates an object that represents a HID port. + */ + HidController(); + + /** + * Destructor. + * Destroys the HID port object. + */ + virtual ~HidController(); + + /** + * Set the USB vendor ID search value. The HID port must be closed for the setting to be accepted. + * @param _baud Vendor ID value to match when enumerating USB HID devices. + * @return True if the vendor ID value was accepted. + * @see Open, Close + */ + bool SetVendorId(uint32 const _vendorId); + + /** + * Set the USB product ID search value. The HID port must be closed for the setting to be accepted. + * @param _parity Product ID value to match when enumerating USB HID devices. + * @return True if the product ID value was accepted. + * @see Open, Close + */ + bool SetProductId(uint32 const _productId); + + /** + * Set the USB serial number search value. The HID port must be closed for the setting to be accepted. + * @param _parity Serial number string to match when enumerating USB HID devices. If empty, any serial number will be accepted. + * @return True if the serial number value was accepted. + * @see Open, Close + */ + bool SetSerialNumber(string const& _serialNumber); + + /** + * Open a HID port. + * Attempts to open a HID port and initialize it with the specified paramters. + * @param _HidControllerName The name of the port to open. For example, ttyS1 on Linux, or \\.\COM2 in Windows. + * @return True if the port was opened and configured successfully. + * @see Close, Read, Write + */ + bool Open(string const& _hidControllerName); + + /** + * Close a HID port. + * Closes the HID port. + * @return True if the port was closed successfully, or false if the port was already closed, or an error occurred. + * @see Open + */ + bool Close(); + + /** + * Write to a HID port. + * Attempts to write data to an open HID port. + * @param _buffer Pointer to a block of memory containing the data to be written. + * @param _length Length in bytes of the data. + * @return The number of bytes written. + * @see Read, Open, Close + */ + uint32 Write(uint8* _buffer, uint32 _length); + + private: + + uint32 SendFeatureReport(uint8* _buffer, uint32 _length, unsigned short reportId); + Concurrency::task Init(); + + Windows::Devices::HumanInterfaceDevice::HidDevice ^ m_device; + Windows::Foundation::EventRegistrationToken m_inputReportEventToken; + + uint32 m_vendorId; + uint32 m_productId; + string m_serialNumber; + string m_hidControllerName; + bool m_bOpen; + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_HidControllerImpl_H diff --git a/cpp/src/platform/winRT/LogImpl.cpp b/cpp/src/platform/winRT/LogImpl.cpp index ad4d2bfe54..695df283c5 100644 --- a/cpp/src/platform/winRT/LogImpl.cpp +++ b/cpp/src/platform/winRT/LogImpl.cpp @@ -57,294 +57,259 @@ errno_t fopen_s(FILE** pFile, const char *filename, const char *mode) #endif - - -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -LogImpl::LogImpl -( - string const& _filename, - bool const _bAppendLog, - bool const _bConsoleOutput, - LogLevel const _saveLevel, - LogLevel const _queueLevel, - LogLevel const _dumpTrigger -): - m_filename( _filename ), // name of log file - m_bAppendLog( _bAppendLog ), // true to append (and not overwrite) any existing log - m_bConsoleOutput( _bConsoleOutput ), // true to provide a copy of output to console - m_saveLevel( _saveLevel ), // level of messages to log to file - m_queueLevel( _queueLevel ), // level of messages to log to queue - m_dumpTrigger( _dumpTrigger ) // dump queued messages when this level is seen -{ - string accessType; + LogImpl::LogImpl(string const& _filename, bool const _bAppendLog, bool const _bConsoleOutput, LogLevel const _saveLevel, LogLevel const _queueLevel, LogLevel const _dumpTrigger) : + m_filename(_filename), // name of log file + m_bAppendLog(_bAppendLog), // true to append (and not overwrite) any existing log + m_bConsoleOutput(_bConsoleOutput), // true to provide a copy of output to console + m_saveLevel(_saveLevel), // level of messages to log to file + m_queueLevel(_queueLevel), // level of messages to log to queue + m_dumpTrigger(_dumpTrigger) // dump queued messages when this level is seen + { + string accessType; - // create an adjusted file name and timestamp string - string timeStr = GetTimeStampString(); + // create an adjusted file name and timestamp string + string timeStr = GetTimeStampString(); - if ( m_bAppendLog ) - { - accessType = "a"; - } - else - { - accessType = "w"; - } + if (m_bAppendLog) + { + accessType = "a"; + } + else + { + accessType = "w"; + } - FILE* pFile; - if( !fopen_s( &pFile, m_filename.c_str(), accessType.c_str() ) ) - { - fprintf( pFile, "\nLogging started %s\n\n", timeStr.c_str() ); - fclose( pFile ); - } -} + FILE* pFile; + if (!fopen_s(&pFile, m_filename.c_str(), accessType.c_str())) + { + fprintf(pFile, "\nLogging started %s\n\n", timeStr.c_str()); + fclose(pFile); + } + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -LogImpl::~LogImpl -( -) -{ -} + LogImpl::~LogImpl() + { + } //----------------------------------------------------------------------------- // // Write to the log //----------------------------------------------------------------------------- -void LogImpl::Write -( - LogLevel _logLevel, - uint8 const _nodeId, - char const* _format, - va_list _args -) -{ - // create a timestamp string - string timeStr = GetTimeStampString(); - string nodeStr = GetNodeString( _nodeId ); - string logLevelStr = GetLogLevelString(_logLevel); - - // handle this message - if( (_logLevel <= m_queueLevel) || (_logLevel == LogLevel_Internal) ) // we're going to do something with this message... - { - char lineBuf[1024]; - if( !_format || ( _format[0] == 0 ) ) - { - strcpy_s( lineBuf, 1024, "" ); - } - else - { - vsprintf_s( lineBuf, sizeof(lineBuf), _format, _args ); - } - - // should this message be saved to file (and possibly written to console?) - if( (_logLevel <= m_saveLevel) || (_logLevel == LogLevel_Internal) ) - { - // save to file - FILE* pFile = NULL; - if( !fopen_s( &pFile, m_filename.c_str(), "a" ) || m_bConsoleOutput ) + void LogImpl::Write(LogLevel _logLevel, uint8 const _nodeId, char const* _format, va_list _args) { - if( _logLevel != LogLevel_Internal ) // don't add a second timestamp to display of queued messages + // create a timestamp string + string timeStr = GetTimeStampString(); + string nodeStr = GetNodeString(_nodeId); + string logLevelStr = GetLogLevelString(_logLevel); + + // handle this message + if ((_logLevel <= m_queueLevel) || (_logLevel == LogLevel_Internal)) // we're going to do something with this message... { - if( pFile != NULL ) + char lineBuf[1024]; + if (!_format || (_format[0] == 0)) { - fprintf( pFile, "%s%s%s", timeStr.c_str(), logLevelStr.c_str(), nodeStr.c_str() ); + strcpy_s(lineBuf, 1024, ""); } - if( m_bConsoleOutput ) + else { - printf( "%s%s%s", timeStr.c_str(), logLevelStr.c_str(), nodeStr.c_str() ); + vsprintf_s(lineBuf, sizeof(lineBuf), _format, _args); } - } - // print message to file (and possibly screen) - if( pFile != NULL ) - { - fprintf( pFile, "%s", lineBuf ); - fprintf( pFile, "\n" ); - fclose( pFile ); + // should this message be saved to file (and possibly written to console?) + if ((_logLevel <= m_saveLevel) || (_logLevel == LogLevel_Internal)) + { + // save to file + FILE* pFile = NULL; + if (!fopen_s(&pFile, m_filename.c_str(), "a") || m_bConsoleOutput) + { + if (_logLevel != LogLevel_Internal) // don't add a second timestamp to display of queued messages + { + if (pFile != NULL) + { + fprintf(pFile, "%s%s%s", timeStr.c_str(), logLevelStr.c_str(), nodeStr.c_str()); + } + if (m_bConsoleOutput) + { + printf("%s%s%s", timeStr.c_str(), logLevelStr.c_str(), nodeStr.c_str()); + } + } + + // print message to file (and possibly screen) + if (pFile != NULL) + { + fprintf(pFile, "%s", lineBuf); + fprintf(pFile, "\n"); + fclose(pFile); + } + if (m_bConsoleOutput) + { + printf("%s", lineBuf); + printf("\n"); + } + + } + } + + if (_logLevel != LogLevel_Internal) + { + char queueBuf[1024]; + string threadStr = GetThreadId(); + sprintf_s(queueBuf, sizeof(queueBuf), "%s%s%s", timeStr.c_str(), threadStr.c_str(), lineBuf); + Queue(queueBuf); + } } - if( m_bConsoleOutput ) + + // now check to see if the _dumpTrigger has been hit + if ((_logLevel <= m_dumpTrigger) && (_logLevel != LogLevel_Internal) && (_logLevel != LogLevel_Always)) { - printf( "%s", lineBuf ); - printf( "\n" ); + QueueDump(); } - } - } - - if( _logLevel != LogLevel_Internal ) - { - char queueBuf[1024]; - string threadStr = GetThreadId(); - sprintf_s( queueBuf, sizeof(queueBuf), "%s%s%s", timeStr.c_str(), threadStr.c_str(), lineBuf ); - Queue( queueBuf ); - } - } - - // now check to see if the _dumpTrigger has been hit - if( (_logLevel <= m_dumpTrigger) && (_logLevel != LogLevel_Internal) && (_logLevel != LogLevel_Always) ) - { - QueueDump(); - } -} //----------------------------------------------------------------------------- // // Write to the log queue //----------------------------------------------------------------------------- -void LogImpl::Queue -( - char const* _buffer -) -{ - string bufStr = _buffer; - m_logQueue.push_back( bufStr ); + void LogImpl::Queue(char const* _buffer) + { + string bufStr = _buffer; + m_logQueue.push_back(bufStr); - // rudimentary queue size management - if( m_logQueue.size() > 500 ) - { - m_logQueue.pop_front(); - } -} + // rudimentary queue size management + if (m_logQueue.size() > 500) + { + m_logQueue.pop_front(); + } + } //----------------------------------------------------------------------------- // // Dump the LogQueue to output device //----------------------------------------------------------------------------- -void LogImpl::QueueDump -( -) -{ - Log::Write( LogLevel_Internal, "\n\nDumping queued log messages\n"); - list::iterator it = m_logQueue.begin(); - while( it != m_logQueue.end() ) - { - string strTemp = *it; - Log::Write( LogLevel_Internal, strTemp.c_str() ); - ++it; - } - m_logQueue.clear(); - Log::Write( LogLevel_Internal, "\nEnd of queued log message dump\n\n"); -} + void LogImpl::QueueDump() + { + Log::Write(LogLevel_Internal, "\n\nDumping queued log messages\n"); + list::iterator it = m_logQueue.begin(); + while (it != m_logQueue.end()) + { + string strTemp = *it; + Log::Write(LogLevel_Internal, strTemp.c_str()); + ++it; + } + m_logQueue.clear(); + Log::Write(LogLevel_Internal, "\nEnd of queued log message dump\n\n"); + } //----------------------------------------------------------------------------- // // Clear the LogQueue //----------------------------------------------------------------------------- -void LogImpl::QueueClear -( -) -{ - m_logQueue.clear(); -} + void LogImpl::QueueClear() + { + m_logQueue.clear(); + } //----------------------------------------------------------------------------- // // Sets the various log state variables //----------------------------------------------------------------------------- -void LogImpl::SetLoggingState -( - LogLevel _saveLevel, - LogLevel _queueLevel, - LogLevel _dumpTrigger -) -{ - m_saveLevel = _saveLevel; - m_queueLevel = _queueLevel; - m_dumpTrigger = _dumpTrigger; -} + void LogImpl::SetLoggingState(LogLevel _saveLevel, LogLevel _queueLevel, LogLevel _dumpTrigger) + { + m_saveLevel = _saveLevel; + m_queueLevel = _queueLevel; + m_dumpTrigger = _dumpTrigger; + } //----------------------------------------------------------------------------- // // Generate a string with formatted current time //----------------------------------------------------------------------------- -string LogImpl::GetTimeStampString -( -) -{ - // Get a timestamp - SYSTEMTIME time; - ::GetLocalTime( &time ); - - // create a time stamp string for the log message - char buf[100]; - sprintf_s( buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d.%03d ", time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond, time.wMilliseconds ); - string str = buf; - return str; -} + string LogImpl::GetTimeStampString() + { + // Get a timestamp + SYSTEMTIME time; + ::GetLocalTime(&time); + + // create a time stamp string for the log message + char buf[100]; + sprintf_s(buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d.%03d ", time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond, time.wMilliseconds); + string str = buf; + return str; + } //----------------------------------------------------------------------------- // // Generate a string with formatted node id //----------------------------------------------------------------------------- -string LogImpl::GetNodeString -( - uint8 const _nodeId -) -{ - if( _nodeId == 0 ) - { - return ""; - } - else - if( _nodeId == 255 ) // should make distinction between broadcast and controller better for SwitchAll broadcast - { - return "contrlr, "; - } - else - { - char buf[20]; - snprintf( buf, sizeof(buf), "Node%03d, ", _nodeId ); - return buf; - } -} + string LogImpl::GetNodeString(uint8 const _nodeId) + { + if (_nodeId == 0) + { + return ""; + } + else if (_nodeId == 255) // should make distinction between broadcast and controller better for SwitchAll broadcast + { + return "contrlr, "; + } + else + { + char buf[20]; + snprintf(buf, sizeof(buf), "Node%03d, ", _nodeId); + return buf; + } + } //----------------------------------------------------------------------------- // // Generate a string with formatted thread id //----------------------------------------------------------------------------- -string LogImpl::GetThreadId -( -) -{ - char buf[20]; - DWORD dwThread = ::GetCurrentThreadId(); - sprintf_s( buf, sizeof(buf), "%04d ", dwThread ); - string str = buf; - return str; -} + string LogImpl::GetThreadId() + { + char buf[20]; + DWORD dwThread = ::GetCurrentThreadId(); + sprintf_s(buf, sizeof(buf), "%04d ", dwThread); + string str = buf; + return str; + } //----------------------------------------------------------------------------- // // Provide a new log file name (applicable to future writes) //----------------------------------------------------------------------------- -void LogImpl::SetLogFileName -( - const string &_filename -) -{ - m_filename = _filename; -} + void LogImpl::SetLogFileName(const string &_filename) + { + m_filename = _filename; + } //----------------------------------------------------------------------------- // // Provide a new log file name (applicable to future writes) //----------------------------------------------------------------------------- -string LogImpl::GetLogLevelString -( - LogLevel _level -) -{ - if ((_level >= LogLevel_None) && (_level <= LogLevel_Internal)) { - char buf[20]; - snprintf( buf, sizeof(buf), "%s, ", LogLevelString[_level] ); - return buf; - } - else - return "Unknown, "; -} + string LogImpl::GetLogLevelString(LogLevel _level) + { + if ((_level >= LogLevel_None) && (_level <= LogLevel_Internal)) + { + char buf[20]; + snprintf(buf, sizeof(buf), "%s, ", LogLevelString[_level]); + return buf; + } + else + return "Unknown, "; + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/winRT/LogImpl.h b/cpp/src/platform/winRT/LogImpl.h index 09363bf13d..3324485e70 100644 --- a/cpp/src/platform/winRT/LogImpl.h +++ b/cpp/src/platform/winRT/LogImpl.h @@ -35,37 +35,43 @@ namespace OpenZWave { - /** \brief Windows-specific implementation of the Log class. - */ - class LogImpl : public i_LogImpl + namespace Internal { - private: - friend class Log; + namespace Platform + { - LogImpl( string const& _filename, bool const _bAppendLog, bool const _bConsoleOutput, LogLevel const _saveLevel, LogLevel const _queueLevel, LogLevel const _dumpTrigger ); - ~LogImpl(); + /** \brief Windows-specific implementation of the Log class. + */ + class LogImpl: public i_LogImpl + { + private: + friend class OpenZWave::Log; - void Write( LogLevel _level, uint8 const _nodeId, char const* _format, va_list _args ); - void Queue( char const* _buffer ); - void QueueDump(); - void QueueClear(); - void SetLoggingState( LogLevel _saveLevel, LogLevel _queueLevel, LogLevel _dumpTrigger ); - void SetLogFileName( const string &_filename ); + LogImpl(string const& _filename, bool const _bAppendLog, bool const _bConsoleOutput, LogLevel const _saveLevel, LogLevel const _queueLevel, LogLevel const _dumpTrigger); + ~LogImpl(); - string GetTimeStampString(); - string GetNodeString( uint8 const _nodeId ); - string GetThreadId(); - string GetLogLevelString(LogLevel _level); + void Write(LogLevel _level, uint8 const _nodeId, char const* _format, va_list _args); + void Queue(char const* _buffer); + void QueueDump(); + void QueueClear(); + void SetLoggingState(LogLevel _saveLevel, LogLevel _queueLevel, LogLevel _dumpTrigger); + void SetLogFileName(const string &_filename); - string m_filename; /**< filename specified by user (default is ozw_log.txt) */ - bool m_bConsoleOutput; /**< if true, send log output to console as well as to the file */ - bool m_bAppendLog; /**< if true, the log file should be appended to any with the same name */ - list m_logQueue; /**< list of queued log messages */ - LogLevel m_saveLevel; - LogLevel m_queueLevel; - LogLevel m_dumpTrigger; - }; + string GetTimeStampString(); + string GetNodeString(uint8 const _nodeId); + string GetThreadId(); + string GetLogLevelString(LogLevel _level); + string m_filename; /**< filename specified by user (default is ozw_log.txt) */ + bool m_bConsoleOutput; /**< if true, send log output to console as well as to the file */ + bool m_bAppendLog; /**< if true, the log file should be appended to any with the same name */ + list m_logQueue; /**< list of queued log messages */ + LogLevel m_saveLevel; + LogLevel m_queueLevel; + LogLevel m_dumpTrigger; + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_LogImpl_H diff --git a/cpp/src/platform/winRT/MutexImpl.cpp b/cpp/src/platform/winRT/MutexImpl.cpp index f182c3b6db..1db9384fa2 100644 --- a/cpp/src/platform/winRT/MutexImpl.cpp +++ b/cpp/src/platform/winRT/MutexImpl.cpp @@ -28,87 +28,83 @@ #include "Defs.h" #include "MutexImpl.h" - -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -MutexImpl::MutexImpl -( -): - m_lockCount( 0 ) -{ - InitializeCriticalSectionEx( &m_criticalSection, 0, 0 ); -} + MutexImpl::MutexImpl() : + m_lockCount(0) + { + InitializeCriticalSectionEx(&m_criticalSection, 0, 0); + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -MutexImpl::~MutexImpl -( -) -{ - DeleteCriticalSection( &m_criticalSection ); -} + MutexImpl::~MutexImpl() + { + DeleteCriticalSection(&m_criticalSection); + } //----------------------------------------------------------------------------- // // Lock the mutex //----------------------------------------------------------------------------- -bool MutexImpl::Lock -( - bool const _bWait // = true; -) -{ - if( _bWait ) - { - // We will wait for the lock - EnterCriticalSection( &m_criticalSection ); - ++m_lockCount; - return true; - } + bool MutexImpl::Lock(bool const _bWait // = true; + ) + { + if (_bWait) + { + // We will wait for the lock + EnterCriticalSection(&m_criticalSection); + ++m_lockCount; + return true; + } - // Returns immediately, even if the lock was not available. - if( TryEnterCriticalSection( &m_criticalSection ) ) - { - ++m_lockCount; - return true; - } + // Returns immediately, even if the lock was not available. + if (TryEnterCriticalSection(&m_criticalSection)) + { + ++m_lockCount; + return true; + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Release our lock on the mutex //----------------------------------------------------------------------------- -void MutexImpl::Unlock -( -) -{ - if( !m_lockCount ) - { - // No locks - we have a mismatched lock/release pair - assert(0); - } - else - { - --m_lockCount; - LeaveCriticalSection( &m_criticalSection ); - } -} + void MutexImpl::Unlock() + { + if (!m_lockCount) + { + // No locks - we have a mismatched lock/release pair + assert(0); + } + else + { + --m_lockCount; + LeaveCriticalSection(&m_criticalSection); + } + } //----------------------------------------------------------------------------- // // Test whether the mutex is free //----------------------------------------------------------------------------- -bool MutexImpl::IsSignalled -( -) -{ - return( 0 == m_lockCount ); -} - + bool MutexImpl::IsSignalled() + { + return (0 == m_lockCount); + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/winRT/MutexImpl.h b/cpp/src/platform/winRT/MutexImpl.h index cee58fd3c7..ab3eb0d470 100644 --- a/cpp/src/platform/winRT/MutexImpl.h +++ b/cpp/src/platform/winRT/MutexImpl.h @@ -30,28 +30,33 @@ #include - namespace OpenZWave { - /** \brief Windows-specific implementation of the Mutex class. - */ - class MutexImpl + namespace Internal { - private: - friend class Mutex; + namespace Platform + { - MutexImpl(); - ~MutexImpl(); + /** \brief Windows-specific implementation of the Mutex class. + */ + class MutexImpl + { + private: + friend class Mutex; - bool Lock( bool const _bWait = true ); - void Unlock(); + MutexImpl(); + ~MutexImpl(); - bool IsSignalled(); + bool Lock(bool const _bWait = true); + void Unlock(); - CRITICAL_SECTION m_criticalSection; - uint32 m_lockCount; // Keep track of the locks (there can be more than one if they occur on the same thread. - }; + bool IsSignalled(); + CRITICAL_SECTION m_criticalSection; + uint32 m_lockCount; // Keep track of the locks (there can be more than one if they occur on the same thread. + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_MutexIF_H diff --git a/cpp/src/platform/winRT/SerialControllerImpl.cpp b/cpp/src/platform/winRT/SerialControllerImpl.cpp index f50f727d25..9a40848188 100644 --- a/cpp/src/platform/winRT/SerialControllerImpl.cpp +++ b/cpp/src/platform/winRT/SerialControllerImpl.cpp @@ -33,224 +33,229 @@ #include #include -using namespace OpenZWave; -using namespace Windows::Devices::SerialCommunication; -using namespace Windows::Devices::Enumeration; -using namespace Windows::Storage::Streams; -using namespace Windows::Foundation; -using namespace Concurrency; -using namespace Platform; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { + using namespace Windows::Devices::SerialCommunication; + using namespace Windows::Devices::Enumeration; + using namespace Windows::Storage::Streams; + using namespace Windows::Foundation; + using namespace Concurrency; + using namespace Platform; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -SerialControllerImpl::SerialControllerImpl( SerialController* _owner) - : m_owner( _owner ) -{ -} + SerialControllerImpl::SerialControllerImpl(SerialController* _owner) : + m_owner(_owner) + { + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -SerialControllerImpl::~SerialControllerImpl() -{ - Close(); -} + SerialControllerImpl::~SerialControllerImpl() + { + Close(); + } //----------------------------------------------------------------------------- // // Close the serial port //----------------------------------------------------------------------------- -void SerialControllerImpl::Close() -{ - // cancel read task - m_readTaskCancelationTokenSource.cancel(); -} + void SerialControllerImpl::Close() + { + // cancel read task + m_readTaskCancelationTokenSource.cancel(); + } //----------------------------------------------------------------------------- // // Open the serial port //----------------------------------------------------------------------------- -bool SerialControllerImpl::Open() -{ - Log::Write(LogLevel_Info, "Trying to open serial port %s", m_owner->m_serialControllerName.c_str()); - - try - { - auto selector = SerialDevice::GetDeviceSelector(); - - return create_task(DeviceInformation::FindAllAsync(selector)) - .then([this](DeviceInformationCollection ^ devices) -> IAsyncOperation ^ - { - wstring ourId(m_owner->m_serialControllerName.begin(), m_owner->m_serialControllerName.end()); - for (auto iterator = devices->First(); iterator->HasCurrent; iterator->MoveNext()) + bool SerialControllerImpl::Open() { - wstring currentId = iterator->Current->Id->Data(); - if (currentId.find(ourId) != wstring::npos) + Log::Write(LogLevel_Info, "Trying to open serial port %s", m_owner->m_serialControllerName.c_str()); + + try { - return SerialDevice::FromIdAsync(iterator->Current->Id); - } - } - return create_async([]() -> SerialDevice ^ { return nullptr; }); + auto selector = SerialDevice::GetDeviceSelector(); - }).then([this](SerialDevice ^ device) -> bool - { - if (device == nullptr) - { - return false; - } - m_serialDevice = device; + return create_task(DeviceInformation::FindAllAsync(selector)) + .then([this](DeviceInformationCollection ^ devices) -> IAsyncOperation ^ + { + wstring ourId(m_owner->m_serialControllerName.begin(), m_owner->m_serialControllerName.end()); + for (auto iterator = devices->First(); iterator->HasCurrent; iterator->MoveNext()) + { + wstring currentId = iterator->Current->Id->Data(); + if (currentId.find(ourId) != wstring::npos) + { + return SerialDevice::FromIdAsync(iterator->Current->Id); + } + } + return create_async([]() -> SerialDevice ^ + { return nullptr;}); - m_serialDevice->BaudRate = m_owner->m_baud; - m_serialDevice->DataBits = 8; - switch (m_owner->m_stopBits) - { - case SerialController::StopBits::StopBits_One: - { - m_serialDevice->StopBits = SerialStopBitCount::One; - break; - } - case SerialController::StopBits::StopBits_OneAndAHalf: - { - m_serialDevice->StopBits = SerialStopBitCount::OnePointFive; - break; - } - case SerialController::StopBits::StopBits_Two: - { - m_serialDevice->StopBits = SerialStopBitCount::Two; - break; - } - } + }).then([this](SerialDevice ^ device) -> bool + { + if (device == nullptr) + { + return false; + } + m_serialDevice = device; - switch (m_owner->m_parity) - { - case SerialController::Parity::Parity_Even: - { - m_serialDevice->Parity = SerialParity::Even; - break; - } - case SerialController::Parity::Parity_Mark: - { - m_serialDevice->Parity = SerialParity::Mark; - break; - } - case SerialController::Parity::Parity_None: - { - m_serialDevice->Parity = SerialParity::None; - break; - } - case SerialController::Parity::Parity_Odd: - { - m_serialDevice->Parity = SerialParity::Odd; - break; - } - case SerialController::Parity::Parity_Space: - { - m_serialDevice->Parity = SerialParity::Space; - break; - } - } + m_serialDevice->BaudRate = m_owner->m_baud; + m_serialDevice->DataBits = 8; + switch (m_owner->m_stopBits) + { + case SerialController::StopBits::StopBits_One: + { + m_serialDevice->StopBits = SerialStopBitCount::One; + break; + } + case SerialController::StopBits::StopBits_OneAndAHalf: + { + m_serialDevice->StopBits = SerialStopBitCount::OnePointFive; + break; + } + case SerialController::StopBits::StopBits_Two: + { + m_serialDevice->StopBits = SerialStopBitCount::Two; + break; + } + } - Windows::Foundation::TimeSpan timespan; - timespan.Duration = 1; - m_serialDevice->ReadTimeout = timespan; + switch (m_owner->m_parity) + { + case SerialController::Parity::Parity_Even: + { + m_serialDevice->Parity = SerialParity::Even; + break; + } + case SerialController::Parity::Parity_Mark: + { + m_serialDevice->Parity = SerialParity::Mark; + break; + } + case SerialController::Parity::Parity_None: + { + m_serialDevice->Parity = SerialParity::None; + break; + } + case SerialController::Parity::Parity_Odd: + { + m_serialDevice->Parity = SerialParity::Odd; + break; + } + case SerialController::Parity::Parity_Space: + { + m_serialDevice->Parity = SerialParity::Space; + break; + } + } - StartReadTask(); + Windows::Foundation::TimeSpan timespan; + timespan.Duration = 1; + m_serialDevice->ReadTimeout = timespan; - return true; - }).get(); - } - catch (...) - { - return false; - } -} + StartReadTask(); + + return true; + }).get(); + } + catch (...) + { + return false; + } + } //----------------------------------------------------------------------------- // // Start a background task which reads available data and passes it along to SerialController //----------------------------------------------------------------------------- -void SerialControllerImpl::StartReadTask() -{ - // Read serial data on background task - cancellation_token token = m_readTaskCancelationTokenSource.get_token(); - - create_task([token, this]() - { - uint32 readBufferLength = 512; - Buffer ^ buffer = ref new Buffer(readBufferLength); - - for (;;) + void SerialControllerImpl::StartReadTask() { - try + // Read serial data on background task + cancellation_token token = m_readTaskCancelationTokenSource.get_token(); + + create_task([token, this]() { - create_task(m_serialDevice->InputStream->ReadAsync(buffer, readBufferLength, InputStreamOptions::None)) - .then([&, this](IBuffer ^ outBuffer) + uint32 readBufferLength = 512; + Buffer ^ buffer = ref new Buffer(readBufferLength); + + for (;;) { - if (token.is_canceled()) - return; - auto reader = DataReader::FromBuffer(outBuffer); - auto bytesRead = reader->UnconsumedBufferLength; + try + { + create_task(m_serialDevice->InputStream->ReadAsync(buffer, readBufferLength, InputStreamOptions::None)) + .then([&, this](IBuffer ^ outBuffer) + { + if (token.is_canceled()) + return; + auto reader = DataReader::FromBuffer(outBuffer); + auto bytesRead = reader->UnconsumedBufferLength; - std::vector byteVector(bytesRead); - if (!byteVector.empty()) + std::vector byteVector(bytesRead); + if (!byteVector.empty()) + { + reader->ReadBytes(::Platform::ArrayReference(byteVector.data(), bytesRead)); + m_owner->Put(byteVector.data(), bytesRead); + } + }).wait(); + } + catch (::Platform::Exception^ ex) { - reader->ReadBytes(::Platform::ArrayReference(byteVector.data(), bytesRead)); - m_owner->Put(byteVector.data(), bytesRead); + if (ex->HResult == HRESULT_FROM_WIN32(ERROR_OPERATION_ABORTED)) + { + m_owner->Close(); + } } - }).wait(); - } - catch (Platform::Exception^ ex) - { - if (ex->HResult == HRESULT_FROM_WIN32(ERROR_OPERATION_ABORTED)) - { - m_owner->Close(); - } - } - if (token.is_canceled()) - { - cancel_current_task(); - } + if (token.is_canceled()) + { + cancel_current_task(); + } + } + }, token); } - }, token); -} //----------------------------------------------------------------------------- // // Send data to the serial port //----------------------------------------------------------------------------- -uint32 SerialControllerImpl::Write -( - uint8* _buffer, - uint32 _length -) -{ - uint32 retVal = 0; + uint32 SerialControllerImpl::Write(uint8* _buffer, uint32 _length) + { + uint32 retVal = 0; - if (m_serialDevice == nullptr) - { - //Error - Log::Write(LogLevel_Error, "ERROR: Serial port must be opened before writing\n"); - return 0; - } + if (m_serialDevice == nullptr) + { + //Error + Log::Write(LogLevel_Error, "ERROR: Serial port must be opened before writing\n"); + return 0; + } - DataWriter ^ writer = ref new DataWriter(); - writer->WriteBytes(ref new Platform::Array(_buffer, _length)); - try - { - auto writeTask = create_task(m_serialDevice->OutputStream->WriteAsync(writer->DetachBuffer())); + DataWriter ^ writer = ref new DataWriter(); + writer->WriteBytes(ref new ::Platform::Array(_buffer, _length)); + try + { + auto writeTask = create_task(m_serialDevice->OutputStream->WriteAsync(writer->DetachBuffer())); - // since the consumer of this function expects this to be synchronous, just wait here. - retVal = writeTask.get(); - } - catch (Platform::Exception^ ) - { - //ignore - return 0 - retVal = 0; - } + // since the consumer of this function expects this to be synchronous, just wait here. + retVal = writeTask.get(); + } + catch (::Platform::Exception^ ) + { + //ignore - return 0 + retVal = 0; + } - return retVal; -} + return retVal; + } + } // namespace Platform +} // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/winRT/SerialControllerImpl.h b/cpp/src/platform/winRT/SerialControllerImpl.h index dafe801f06..2662b9c5c1 100644 --- a/cpp/src/platform/winRT/SerialControllerImpl.h +++ b/cpp/src/platform/winRT/SerialControllerImpl.h @@ -37,26 +37,32 @@ namespace OpenZWave { - class SerialControllerImpl + namespace Internal { - private: - friend class SerialController; + namespace Platform + { - SerialControllerImpl( SerialController* _owner ); - ~SerialControllerImpl(); + class SerialControllerImpl + { + private: + friend class SerialController; - bool Open(); - void Close(); + SerialControllerImpl(SerialController* _owner); + ~SerialControllerImpl(); - uint32 Write( uint8* _buffer, uint32 _length ); - void StartReadTask(); + bool Open(); + void Close(); - Windows::Devices::SerialCommunication::SerialDevice ^ m_serialDevice; - Concurrency::cancellation_token_source m_readTaskCancelationTokenSource; + uint32 Write(uint8* _buffer, uint32 _length); + void StartReadTask(); - SerialController* m_owner; - }; + Windows::Devices::SerialCommunication::SerialDevice ^ m_serialDevice; + Concurrency::cancellation_token_source m_readTaskCancelationTokenSource; + SerialController* m_owner; + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_SerialControllerImpl_H diff --git a/cpp/src/platform/winRT/ThreadImpl.cpp b/cpp/src/platform/winRT/ThreadImpl.cpp index ed58e39156..77b683b7e3 100644 --- a/cpp/src/platform/winRT/ThreadImpl.cpp +++ b/cpp/src/platform/winRT/ThreadImpl.cpp @@ -31,118 +31,110 @@ #include "ThreadImpl.h" #include "Options.h" -using namespace OpenZWave; -using namespace Concurrency; -using namespace Windows::Foundation; -using namespace Windows::System::Threading; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { + using namespace Concurrency; + using namespace Windows::Foundation; + using namespace Windows::System::Threading; -int32 ThreadImpl::s_threadTerminateTimeout = -1; + int32 ThreadImpl::s_threadTerminateTimeout = -1; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -ThreadImpl::ThreadImpl -( - Thread* _owner, - string const& _name -): - m_owner( _owner ), - m_bIsRunning( false ), - m_name( _name ) -{ - static bool staticsInitialized = false; - if (!staticsInitialized) - { - if (Options::Get() != nullptr) - { - Options::Get()->GetOptionAsInt("ThreadTerminateTimeout", &s_threadTerminateTimeout); - } - staticsInitialized = true; - } -} + ThreadImpl::ThreadImpl(Thread* _owner, string const& _name) : + m_owner(_owner), m_bIsRunning(false), m_name(_name) + { + static bool staticsInitialized = false; + if (!staticsInitialized) + { + if (Options::Get() != nullptr) + { + Options::Get()->GetOptionAsInt("ThreadTerminateTimeout", &s_threadTerminateTimeout); + } + staticsInitialized = true; + } + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -ThreadImpl::~ThreadImpl () -{ -} + ThreadImpl::~ThreadImpl() + { + } //----------------------------------------------------------------------------- // // Start a function running on this thread //----------------------------------------------------------------------------- -bool ThreadImpl::Start -( - Thread::pfnThreadProc_t _pfnThreadProc, - Event* _exitEvent, - void* _context -) -{ - // Create a thread to run the specified function - m_pfnThreadProc = _pfnThreadProc; - m_context = _context; - m_exitEvent = _exitEvent; - m_exitEvent->Reset(); + bool ThreadImpl::Start(Thread::pfnThreadProc_t _pfnThreadProc, Event* _exitEvent, void* _context) + { + // Create a thread to run the specified function + m_pfnThreadProc = _pfnThreadProc; + m_context = _context; + m_exitEvent = _exitEvent; + m_exitEvent->Reset(); - create_task([this]() - { - m_bIsRunning = true; - try - { - m_pfnThreadProc(m_exitEvent, m_context); - } - catch (Platform::Exception^) - { - } + create_task([this]() + { + m_bIsRunning = true; + try + { + m_pfnThreadProc(m_exitEvent, m_context); + } + catch (::Platform::Exception^) + { + } - m_bIsRunning = false; - // Let any watchers know that the thread has finished running. - m_owner->Notify(); - }); - return true; -} + m_bIsRunning = false; + // Let any watchers know that the thread has finished running. + m_owner->Notify(); + }); + return true; + } //----------------------------------------------------------------------------- // // Cause thread to sleep for the specified number of milliseconds //----------------------------------------------------------------------------- -void ThreadImpl::Sleep -( - uint32 _millisecs -) -{ - ::Sleep(_millisecs); -} + void ThreadImpl::Sleep(uint32 _millisecs) + { + ::Sleep(_millisecs); + } //----------------------------------------------------------------------------- // // Force the thread to stop //----------------------------------------------------------------------------- -bool ThreadImpl::Terminate -( -) -{ - // No way to do this on WinRT, so give the thread a bit of extra time to exit on its own - if( !m_bIsRunning ) - { - return false; - } + bool ThreadImpl::Terminate() + { + // No way to do this on WinRT, so give the thread a bit of extra time to exit on its own + if (!m_bIsRunning) + { + return false; + } - if (Wait::Single(m_owner, s_threadTerminateTimeout) < 0) - { - return false; - } - return true; -} + if (Wait::Single(m_owner, s_threadTerminateTimeout) < 0) + { + return false; + } + return true; + } //----------------------------------------------------------------------------- // // Test whether the thread has completed //----------------------------------------------------------------------------- -bool ThreadImpl::IsSignalled() -{ - return !m_bIsRunning; -} \ No newline at end of file + bool ThreadImpl::IsSignalled() + { + return !m_bIsRunning; + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/winRT/ThreadImpl.h b/cpp/src/platform/winRT/ThreadImpl.h index f7bd12acb1..c904964036 100644 --- a/cpp/src/platform/winRT/ThreadImpl.h +++ b/cpp/src/platform/winRT/ThreadImpl.h @@ -35,38 +35,43 @@ namespace OpenZWave { - class Thread; - class Event; - - /** \brief Windows-specific implementation of the Thread class. - */ - class ThreadImpl + namespace Internal { - private: - friend class Thread; + namespace Platform + { + + class Thread; + class Event; - ThreadImpl( Thread* _owner, string const& _name ); - ~ThreadImpl(); + /** \brief Windows-specific implementation of the Thread class. + */ + class ThreadImpl + { + private: + friend class Thread; - bool Start( Thread::pfnThreadProc_t _pfnThreadProc, Event* _exitEvent, void* _context ); - void Sleep( uint32 _milliseconds ); - bool Terminate(); + ThreadImpl(Thread* _owner, string const& _name); + ~ThreadImpl(); - bool IsSignalled(); + bool Start(Thread::pfnThreadProc_t _pfnThreadProc, Event* _exitEvent, void* _context); + void Sleep(uint32 _milliseconds); + bool Terminate(); - void Run(); - static DWORD WINAPI ThreadProc( void* _pArg ); + bool IsSignalled(); - Thread* m_owner; - Event* m_exitEvent; - Thread::pfnThreadProc_t m_pfnThreadProc; - void* m_context; - bool m_bIsRunning; - string m_name; + void Run();static DWORD WINAPI ThreadProc( void* _pArg ); - static int32 s_threadTerminateTimeout; - }; + Thread* m_owner; + Event* m_exitEvent; + Thread::pfnThreadProc_t m_pfnThreadProc; + void* m_context; + bool m_bIsRunning; + string m_name; + static int32 s_threadTerminateTimeout; + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_ThreadImpl_H diff --git a/cpp/src/platform/winRT/TimeStampImpl.cpp b/cpp/src/platform/winRT/TimeStampImpl.cpp index 7962d9176e..dbbbbdb9a9 100644 --- a/cpp/src/platform/winRT/TimeStampImpl.cpp +++ b/cpp/src/platform/winRT/TimeStampImpl.cpp @@ -30,85 +30,80 @@ #include "Defs.h" #include "TimeStampImpl.h" -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -TimeStampImpl::TimeStampImpl -( -) -{ - SetTime(0); -} + TimeStampImpl::TimeStampImpl() + { + SetTime(0); + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -TimeStampImpl::~TimeStampImpl -( -) -{ -} + TimeStampImpl::~TimeStampImpl() + { + } //----------------------------------------------------------------------------- // // Sets the timestamp to now, plus an offset in milliseconds //----------------------------------------------------------------------------- -void TimeStampImpl::SetTime -( - int32 _milliseconds // = 0 -) -{ - int64 offset = ((int64)_milliseconds) * 10000LL; // Timestamp is stored in 100ns steps. + void TimeStampImpl::SetTime(int32 _milliseconds // = 0 + ) + { + int64 offset = ((int64) _milliseconds) * 10000LL; // Timestamp is stored in 100ns steps. - GetSystemTimeAsFileTime( (FILETIME*)&m_stamp ); - m_stamp += offset; -} + GetSystemTimeAsFileTime((FILETIME*) &m_stamp); + m_stamp += offset; + } //----------------------------------------------------------------------------- // // Gets the difference between now and the timestamp time in milliseconds //----------------------------------------------------------------------------- -int32 TimeStampImpl::TimeRemaining -( -) -{ - int64 now; - GetSystemTimeAsFileTime( (FILETIME*)&now ); + int32 TimeStampImpl::TimeRemaining() + { + int64 now; + GetSystemTimeAsFileTime((FILETIME*) &now); - return (int32)( ( m_stamp - now ) / 10000LL ); -} + return (int32) ((m_stamp - now) / 10000LL); + } //----------------------------------------------------------------------------- // // Return a string representation //----------------------------------------------------------------------------- -string TimeStampImpl::GetAsString -( -) -{ - // Convert m_stamp (FILETIME) to SYSTEMTIME for ease of use - SYSTEMTIME time; - ::FileTimeToSystemTime( (FILETIME*)&m_stamp, &time ); + string TimeStampImpl::GetAsString() + { + // Convert m_stamp (FILETIME) to SYSTEMTIME for ease of use + SYSTEMTIME time; + ::FileTimeToSystemTime((FILETIME*) &m_stamp, &time); - char buf[100]; - sprintf_s( buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d:%03d ", time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond, time.wMilliseconds ); - string str = buf; - return str; -} + char buf[100]; + sprintf_s(buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d:%03d ", time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond, time.wMilliseconds); + string str = buf; + return str; + } //----------------------------------------------------------------------------- // // Overload the subtract operator to get the difference between two // timestamps in milliseconds //----------------------------------------------------------------------------- -int32 TimeStampImpl::operator- -( - TimeStampImpl const& _other -) -{ - return (int32)( ( m_stamp - _other.m_stamp ) / 10000LL ); -} + int32 TimeStampImpl::operator-(TimeStampImpl const& _other) + { + return (int32) ((m_stamp - _other.m_stamp) / 10000LL); + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/winRT/TimeStampImpl.h b/cpp/src/platform/winRT/TimeStampImpl.h index 01905b3de7..3ff7517e91 100644 --- a/cpp/src/platform/winRT/TimeStampImpl.h +++ b/cpp/src/platform/winRT/TimeStampImpl.h @@ -32,56 +32,62 @@ namespace OpenZWave { - /** \brief Windows implementation of a timestamp. - */ - class TimeStampImpl + namespace Internal { - public: - /** - * Constructor. - * Creates a TimeStampImpl object. - */ - TimeStampImpl(); + namespace Platform + { - /** - * Destructor. - * Destroys the TimeStampImpl object. - */ - ~TimeStampImpl(); + /** \brief Windows implementation of a timestamp. + */ + class TimeStampImpl + { + public: + /** + * Constructor. + * Creates a TimeStampImpl object. + */ + TimeStampImpl(); - /** - * SetTime. Sets the timestamp to now, plus the offset in milliseconds. - * \param _milliseconds positive or negative offset from - * now in milliseconds. - */ - void SetTime( int32 _milliseconds ); + /** + * Destructor. + * Destroys the TimeStampImpl object. + */ + ~TimeStampImpl(); - /** - * TimeRemaining. Gets the difference between now and the timestamp - * time in milliseconds. - * \return milliseconds remaining until we reach the timestamp. The - * return value is negative if the timestamp is in the past. - */ - int32 TimeRemaining(); + /** + * SetTime. Sets the timestamp to now, plus the offset in milliseconds. + * \param _milliseconds positive or negative offset from + * now in milliseconds. + */ + void SetTime(int32 _milliseconds); - /** - * Return as as string - */ - string GetAsString(); + /** + * TimeRemaining. Gets the difference between now and the timestamp + * time in milliseconds. + * \return milliseconds remaining until we reach the timestamp. The + * return value is negative if the timestamp is in the past. + */ + int32 TimeRemaining(); - /** - * Overload the subtract operator to get the difference between - * two timestamps in milliseconds. - */ - int32 operator- ( TimeStampImpl const& _other ); + /** + * Return as as string + */ + string GetAsString(); - private: - TimeStampImpl( TimeStampImpl const& ); // prevent copy - TimeStampImpl& operator = ( TimeStampImpl const& ); // prevent assignment + /** + * Overload the subtract operator to get the difference between + * two timestamps in milliseconds. + */ + int32 operator-(TimeStampImpl const& _other); - int64 m_stamp; - }; + private: + TimeStampImpl(TimeStampImpl const&); // prevent copy + TimeStampImpl& operator =(TimeStampImpl const&); // prevent assignment + int64 m_stamp; + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_TimeStampImpl_H diff --git a/cpp/src/platform/winRT/WaitImpl.cpp b/cpp/src/platform/winRT/WaitImpl.cpp index a0dca0bf08..c0e6429d19 100644 --- a/cpp/src/platform/winRT/WaitImpl.cpp +++ b/cpp/src/platform/winRT/WaitImpl.cpp @@ -31,104 +31,97 @@ #include "WaitImpl.h" #include "platform/Log.h" -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -WaitImpl::WaitImpl -( - Wait* _owner -): - m_owner( _owner ) -{ - InitializeCriticalSectionEx( &m_criticalSection, 0, 0 ); -} + WaitImpl::WaitImpl(Wait* _owner) : + m_owner(_owner) + { + InitializeCriticalSectionEx(&m_criticalSection, 0, 0); + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -WaitImpl::~WaitImpl -( -) -{ - DeleteCriticalSection( &m_criticalSection ); -} + WaitImpl::~WaitImpl() + { + DeleteCriticalSection(&m_criticalSection); + } //----------------------------------------------------------------------------- // // Add a watcher to our object. //----------------------------------------------------------------------------- -void WaitImpl::AddWatcher -( - Wait::pfnWaitNotification_t _callback, - void* _context -) -{ - // Add the watcher to our list - Watcher watcher; - watcher.m_callback = _callback; - watcher.m_context = _context; + void WaitImpl::AddWatcher(Wait::pfnWaitNotification_t _callback, void* _context) + { + // Add the watcher to our list + Watcher watcher; + watcher.m_callback = _callback; + watcher.m_context = _context; - EnterCriticalSection( &m_criticalSection ); + EnterCriticalSection(&m_criticalSection); - m_watchers.push_back( watcher ); + m_watchers.push_back(watcher); - LeaveCriticalSection( &m_criticalSection ); + LeaveCriticalSection(&m_criticalSection); - // If the object is already in a signalled state, notify the watcher immediately - if( m_owner->IsSignalled() ) - { - _callback( _context ); - } + // If the object is already in a signalled state, notify the watcher immediately + if (m_owner->IsSignalled()) + { + _callback(_context); + } -} + } //----------------------------------------------------------------------------- // // Remove a watcher from our object. //----------------------------------------------------------------------------- -bool WaitImpl::RemoveWatcher -( - Wait::pfnWaitNotification_t _callback, - void* _context -) -{ - bool res = false; - EnterCriticalSection( &m_criticalSection ); + bool WaitImpl::RemoveWatcher(Wait::pfnWaitNotification_t _callback, void* _context) + { + bool res = false; + EnterCriticalSection(&m_criticalSection); - for( list::iterator it=m_watchers.begin(); it!=m_watchers.end(); ++it ) - { - Watcher const& watcher = *it; - if( ( watcher.m_callback == _callback ) && ( watcher.m_context == _context ) ) - { - m_watchers.erase( it ); - res = true; - break; - } - } + for (list::iterator it = m_watchers.begin(); it != m_watchers.end(); ++it) + { + Watcher const& watcher = *it; + if ((watcher.m_callback == _callback) && (watcher.m_context == _context)) + { + m_watchers.erase(it); + res = true; + break; + } + } - LeaveCriticalSection( &m_criticalSection ); - return res; -} + LeaveCriticalSection(&m_criticalSection); + return res; + } //----------------------------------------------------------------------------- // // Notify all the watchers that the object has become signalled //----------------------------------------------------------------------------- -void WaitImpl::Notify -( -) -{ - EnterCriticalSection( &m_criticalSection ); + void WaitImpl::Notify() + { + EnterCriticalSection(&m_criticalSection); - for( list::iterator it=m_watchers.begin(); it!=m_watchers.end(); ++it ) - { - Watcher const& watcher = *it; - watcher.m_callback( watcher.m_context ); - } + for (list::iterator it = m_watchers.begin(); it != m_watchers.end(); ++it) + { + Watcher const& watcher = *it; + watcher.m_callback(watcher.m_context); + } - LeaveCriticalSection( &m_criticalSection ); -} + LeaveCriticalSection(&m_criticalSection); + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/winRT/WaitImpl.h b/cpp/src/platform/winRT/WaitImpl.h index d92e2886cc..48f618a040 100644 --- a/cpp/src/platform/winRT/WaitImpl.h +++ b/cpp/src/platform/winRT/WaitImpl.h @@ -37,36 +37,42 @@ namespace OpenZWave { - /** \brief Windows specific implementation of Wait objects. - */ - class WaitImpl + namespace Internal { - private: - friend class Wait; + namespace Platform + { - WaitImpl( Wait* _owner ); - virtual ~WaitImpl(); + /** \brief Windows specific implementation of Wait objects. + */ + class WaitImpl + { + private: + friend class Wait; - void AddWatcher( Wait::pfnWaitNotification_t _callback, void* _context ); - bool RemoveWatcher( Wait::pfnWaitNotification_t _callback, void* _context ); - void Notify(); + WaitImpl(Wait* _owner); + virtual ~WaitImpl(); - static int32 Multiple( Wait** _objects, uint32 _numObjects, int32 _timeout = -1 ); + void AddWatcher(Wait::pfnWaitNotification_t _callback, void* _context); + bool RemoveWatcher(Wait::pfnWaitNotification_t _callback, void* _context); + void Notify(); - WaitImpl( Wait const& ); // prevent copy - WaitImpl& operator = ( WaitImpl const& ); // prevent assignment + static int32 Multiple(Wait** _objects, uint32 _numObjects, int32 _timeout = -1); - struct Watcher - { - Wait::pfnWaitNotification_t m_callback; - void* m_context; - }; + WaitImpl(Wait const&); // prevent copy + WaitImpl& operator =(WaitImpl const&); // prevent assignment - list m_watchers; - Wait* m_owner; - CRITICAL_SECTION m_criticalSection; - }; + struct Watcher + { + Wait::pfnWaitNotification_t m_callback; + void* m_context; + }; + list m_watchers; + Wait* m_owner; + CRITICAL_SECTION m_criticalSection; + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_WaitImpl_H diff --git a/cpp/src/platform/windows/DNSImpl.cpp b/cpp/src/platform/windows/DNSImpl.cpp index 46125fcb7c..1b40aa3bd4 100644 --- a/cpp/src/platform/windows/DNSImpl.cpp +++ b/cpp/src/platform/windows/DNSImpl.cpp @@ -32,50 +32,51 @@ #include "DNSImpl.h" - - -using namespace OpenZWave; - -DNSImpl::DNSImpl -( -) +namespace OpenZWave { + namespace Internal + { + namespace Platform + { -} + DNSImpl::DNSImpl() + { -DNSImpl::~DNSImpl -( -) -{ + } -} + DNSImpl::~DNSImpl() + { -bool DNSImpl::LookupTxT -( -string lookup, -string &result -) -{ + } + + bool DNSImpl::LookupTxT(string lookup, string &result) + { - PDNS_RECORD qr, rp; - DNS_STATUS rc; + PDNS_RECORD qr, rp; + DNS_STATUS rc; - rc = DnsQuery(lookup.c_str(), DNS_TYPE_TEXT, DNS_QUERY_STANDARD, NULL, &qr, NULL); - if (rc != ERROR_SUCCESS) { - Log::Write(LogLevel_Warning, "Error looking up txt Record: %s - %d", lookup.c_str(), rc); - status = DNSError_InternalError; - return false; - } + rc = DnsQuery(lookup.c_str(), DNS_TYPE_TEXT, DNS_QUERY_STANDARD, NULL, &qr, NULL); + if (rc != ERROR_SUCCESS) + { + Log::Write(LogLevel_Warning, "Error looking up txt Record: %s - %d", lookup.c_str(), rc); + status = DNSError_InternalError; + return false; + } - for (rp = qr; rp != NULL; rp = rp->pNext) { - if (rp->wType == DNS_TYPE_TEXT) { - result = rp->Data.TXT.pStringArray[0]; - status = DNSError_None; - break; - } - } + for (rp = qr; rp != NULL; rp = rp->pNext) + { + if (rp->wType == DNS_TYPE_TEXT) + { + result = rp->Data.TXT.pStringArray[0]; + status = DNSError_None; + break; + } + } - DnsRecordListFree(qr, DnsFreeRecordList); + DnsRecordListFree(qr, DnsFreeRecordList); - return true; -} + return true; + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/windows/DNSImpl.h b/cpp/src/platform/windows/DNSImpl.h index f78ac97c78..dc2cfe0706 100644 --- a/cpp/src/platform/windows/DNSImpl.h +++ b/cpp/src/platform/windows/DNSImpl.h @@ -33,14 +33,21 @@ namespace OpenZWave { - class DNSImpl { - public: - DNSImpl(); - virtual ~DNSImpl(); - virtual bool LookupTxT(string, string &); - DNSError status; - private: + namespace Internal + { + namespace Platform + { + class DNSImpl + { + public: + DNSImpl(); + virtual ~DNSImpl(); + virtual bool LookupTxT(string, string &); + DNSError status; + private: - }; -} + }; + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave #endif diff --git a/cpp/src/platform/windows/EventImpl.cpp b/cpp/src/platform/windows/EventImpl.cpp index ee5927c87a..c95a9ef898 100644 --- a/cpp/src/platform/windows/EventImpl.cpp +++ b/cpp/src/platform/windows/EventImpl.cpp @@ -30,73 +30,67 @@ #include "Defs.h" #include "EventImpl.h" -using namespace OpenZWave; - +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -EventImpl::EventImpl -( -) -{ - // Create a manual reset event - m_hEvent = ::CreateEvent( NULL, TRUE, FALSE, NULL ); -} + EventImpl::EventImpl() + { + // Create a manual reset event + m_hEvent = ::CreateEvent( NULL, TRUE, FALSE, NULL); + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -EventImpl::~EventImpl -( -) -{ - ::CloseHandle( m_hEvent ); -} + EventImpl::~EventImpl() + { + ::CloseHandle(m_hEvent); + } //----------------------------------------------------------------------------- // // Set the event to signalled //----------------------------------------------------------------------------- -void EventImpl::Set -( -) -{ - ::SetEvent( m_hEvent ); -} + void EventImpl::Set() + { + ::SetEvent(m_hEvent); + } //----------------------------------------------------------------------------- // // Set the event to not signalled //----------------------------------------------------------------------------- -void EventImpl::Reset -( -) -{ - ::ResetEvent( m_hEvent ); -} + void EventImpl::Reset() + { + ::ResetEvent(m_hEvent); + } //----------------------------------------------------------------------------- // // Test whether the event is set //----------------------------------------------------------------------------- -bool EventImpl::IsSignalled -( -) -{ - return( WAIT_OBJECT_0 == WaitForSingleObject( m_hEvent, 0 ) ); -} + bool EventImpl::IsSignalled() + { + return (WAIT_OBJECT_0 == WaitForSingleObject(m_hEvent, 0)); + } //----------------------------------------------------------------------------- // // Wait for the event to become signalled //----------------------------------------------------------------------------- -bool EventImpl::Wait -( - int32 const _timeout -) -{ - return( WAIT_TIMEOUT != ::WaitForSingleObject( m_hEvent, (DWORD)_timeout ) ); -} + bool EventImpl::Wait(int32 const _timeout) + { + return (WAIT_TIMEOUT != ::WaitForSingleObject(m_hEvent, (DWORD) _timeout)); + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/windows/EventImpl.h b/cpp/src/platform/windows/EventImpl.h index 5abd8d6f31..1cb8a2a4c2 100644 --- a/cpp/src/platform/windows/EventImpl.h +++ b/cpp/src/platform/windows/EventImpl.h @@ -33,27 +33,33 @@ namespace OpenZWave { - /** \brief Windows-specific implementation of the Event class. - */ - class EventImpl + namespace Internal { - private: - friend class Event; - friend class SocketImpl; - friend class Wait; + namespace Platform + { - EventImpl(); - ~EventImpl(); + /** \brief Windows-specific implementation of the Event class. + */ + class EventImpl + { + private: + friend class Event; + friend class SocketImpl; + friend class Wait; - void Set(); - void Reset(); + EventImpl(); + ~EventImpl(); - bool Wait( int32 _timeout ); // The wait method is to be used only by the Wait::Multiple method - bool IsSignalled(); + void Set(); + void Reset(); - HANDLE m_hEvent; - }; + bool Wait(int32 _timeout); // The wait method is to be used only by the Wait::Multiple method + bool IsSignalled(); + HANDLE m_hEvent; + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_EventImpl_H diff --git a/cpp/src/platform/windows/FileOpsImpl.cpp b/cpp/src/platform/windows/FileOpsImpl.cpp index 4f330f0121..14ac15c82b 100644 --- a/cpp/src/platform/windows/FileOpsImpl.cpp +++ b/cpp/src/platform/windows/FileOpsImpl.cpp @@ -30,144 +30,139 @@ #include "FileOpsImpl.h" #include "Utils.h" -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -FileOpsImpl::FileOpsImpl -( -) -{ -} + FileOpsImpl::FileOpsImpl() + { + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -FileOpsImpl::~FileOpsImpl -( -) -{ -} + FileOpsImpl::~FileOpsImpl() + { + } //----------------------------------------------------------------------------- // // Determine if a folder exists //----------------------------------------------------------------------------- -bool FileOpsImpl::FolderExists( - const string &_folderName -) -{ - uint32 ftype = GetFileAttributesA(_folderName.c_str()); - if( ftype == INVALID_FILE_ATTRIBUTES ) - return false; // something is wrong with _foldername path - if( ftype & FILE_ATTRIBUTE_DIRECTORY ) - return true; - - return false; -} - -bool FileOpsImpl::FileExists -( - const string _filename -) -{ - DWORD dwAttrib = GetFileAttributesA(_filename.c_str()); - - return (dwAttrib != INVALID_FILE_ATTRIBUTES && - !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); -} - -bool FileOpsImpl::FileWriteable -( - const string _filename -) -{ - DWORD dwAttrib; - if (!FileExists(_filename)) { - /* check if the directory is writtable */ - dwAttrib = GetFileAttributesA(ozwdirname(_filename).c_str()); - } else { - dwAttrib = GetFileAttributesA(_filename.c_str()); - } - - return (dwAttrib != INVALID_FILE_ATTRIBUTES && - !(dwAttrib & FILE_ATTRIBUTE_READONLY)); - -} - -bool FileOpsImpl::FileRotate -( - const string _filename -) -{ - int i = 1; - string newFile; - /* find a filename not used yet */ - newFile = _filename; - newFile.append(".").append(intToString(i)); - while (FileExists(newFile)) { - i++; - newFile = _filename; - newFile.append(".").append(intToString(i)); - } - /* copy the file */ - if (!FileCopy(_filename, newFile)) { - Log::Write(LogLevel_Warning, "File Rotate Failed: %s -> %s", _filename.c_str(), newFile.c_str()); - return false; - } - /* remove the old file */ - if (DeleteFileA(_filename.c_str()) == 0) { - Log::Write(LogLevel_Warning, "File Removal failed: %s", _filename.c_str()); - return false; - } - return true; -} - - -bool FileOpsImpl::FileCopy -( - const string _sourcefile, - const string _destfile -) -{ - - if (!FileExists(_sourcefile)) { - Log::Write(LogLevel_Warning, "Source File %s doesn't exist in FileCopy", _sourcefile.c_str()); - return false; - } - if (FileExists(_destfile)) { - Log::Write(LogLevel_Warning, "Destination File %s exists in FileCopy", _destfile.c_str()); - return false; - } - - /* make sure the Destination Folder Exists */ - if (!FolderExists(ozwdirname(_destfile))) { - Log::Write(LogLevel_Warning, "Destination Folder %s Doesn't Exist", ozwdirname(_destfile)); - return false; - } - - if (CopyFileA(_sourcefile.c_str(), _destfile.c_str(), FALSE) == 0) { - Log::Write(LogLevel_Warning, "CopyFile Failed %s - %s", _sourcefile.c_str(), _destfile.c_str()); - return false; - } - return true; -} - -bool FileOpsImpl::FolderCreate -( - const string _dirname -) -{ - if (FolderExists(_dirname)) { - Log::Write(LogLevel_Warning, "Folder %s Exists for FolderCreate", _dirname.c_str()); - return false; - } - if (CreateDirectoryA(_dirname.c_str(), NULL) ==0) { - Log::Write(LogLevel_Warning, "Create Directory Failed: %s", _dirname.c_str()); - return false; - } - return true; -} + bool FileOpsImpl::FolderExists(const string &_folderName) + { + uint32 ftype = GetFileAttributesA(_folderName.c_str()); + if (ftype == INVALID_FILE_ATTRIBUTES) + return false; // something is wrong with _foldername path + if (ftype & FILE_ATTRIBUTE_DIRECTORY) + return true; + + return false; + } + + bool FileOpsImpl::FileExists(const string _filename) + { + DWORD dwAttrib = GetFileAttributesA(_filename.c_str()); + + return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); + } + + bool FileOpsImpl::FileWriteable(const string _filename) + { + DWORD dwAttrib; + if (!FileExists(_filename)) + { + /* check if the directory is writtable */ + dwAttrib = GetFileAttributesA(ozwdirname(_filename).c_str()); + } + else + { + dwAttrib = GetFileAttributesA(_filename.c_str()); + } + + return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_READONLY)); + + } + + bool FileOpsImpl::FileRotate(const string _filename) + { + int i = 1; + string newFile; + /* find a filename not used yet */ + newFile = _filename; + newFile.append(".").append(intToString(i)); + while (FileExists(newFile)) + { + i++; + newFile = _filename; + newFile.append(".").append(intToString(i)); + } + /* copy the file */ + if (!FileCopy(_filename, newFile)) + { + Log::Write(LogLevel_Warning, "File Rotate Failed: %s -> %s", _filename.c_str(), newFile.c_str()); + return false; + } + /* remove the old file */ + if (DeleteFileA(_filename.c_str()) == 0) + { + Log::Write(LogLevel_Warning, "File Removal failed: %s", _filename.c_str()); + return false; + } + return true; + } + + bool FileOpsImpl::FileCopy(const string _sourcefile, const string _destfile) + { + + if (!FileExists(_sourcefile)) + { + Log::Write(LogLevel_Warning, "Source File %s doesn't exist in FileCopy", _sourcefile.c_str()); + return false; + } + if (FileExists(_destfile)) + { + Log::Write(LogLevel_Warning, "Destination File %s exists in FileCopy", _destfile.c_str()); + return false; + } + + /* make sure the Destination Folder Exists */ + if (!FolderExists(ozwdirname(_destfile))) + { + Log::Write(LogLevel_Warning, "Destination Folder %s Doesn't Exist", ozwdirname(_destfile)); + return false; + } + + if (CopyFileA(_sourcefile.c_str(), _destfile.c_str(), FALSE) == 0) + { + Log::Write(LogLevel_Warning, "CopyFile Failed %s - %s", _sourcefile.c_str(), _destfile.c_str()); + return false; + } + return true; + } + + bool FileOpsImpl::FolderCreate(const string _dirname) + { + if (FolderExists(_dirname)) + { + Log::Write(LogLevel_Warning, "Folder %s Exists for FolderCreate", _dirname.c_str()); + return false; + } + if (CreateDirectoryA(_dirname.c_str(), NULL) == 0) + { + Log::Write(LogLevel_Warning, "Create Directory Failed: %s", _dirname.c_str()); + return false; + } + return true; + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/windows/FileOpsImpl.h b/cpp/src/platform/windows/FileOpsImpl.h index d74e868139..ad954ae7e6 100644 --- a/cpp/src/platform/windows/FileOpsImpl.h +++ b/cpp/src/platform/windows/FileOpsImpl.h @@ -35,23 +35,29 @@ namespace OpenZWave { - class FileOpsImpl + namespace Internal { - friend class FileOps; + namespace Platform + { - private: - FileOpsImpl(); - ~FileOpsImpl(); + class FileOpsImpl + { + friend class FileOps; - bool FolderExists( const string &_filename ); - bool FileExists( const string _filename ); - bool FileWriteable ( const string _filename ); - bool FileRotate ( const string _filename ); - bool FileCopy (const string, const string); - bool FolderCreate( const string _dirname); + private: + FileOpsImpl(); + ~FileOpsImpl(); - }; + bool FolderExists(const string &_filename); + bool FileExists(const string _filename); + bool FileWriteable(const string _filename); + bool FileRotate(const string _filename); + bool FileCopy(const string, const string); + bool FolderCreate(const string _dirname); + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_FileOpsImpl_H diff --git a/cpp/src/platform/windows/LogImpl.cpp b/cpp/src/platform/windows/LogImpl.cpp index eb90b5c2b8..38cc3968c4 100644 --- a/cpp/src/platform/windows/LogImpl.cpp +++ b/cpp/src/platform/windows/LogImpl.cpp @@ -40,341 +40,322 @@ errno_t fopen_s(FILE** pFile, const char *filename, const char *mode) { - if (!pFile) - { + if (!pFile) + { #if defined(_MSC_VER) && _MSC_VER >= 1400 - _set_errno(EINVAL); + _set_errno(EINVAL); #elif defined(__MINGW64__) - _set_errno(EINVAL); + _set_errno(EINVAL); #else - errno = EINVAL; + errno = EINVAL; #endif - return EINVAL; - } + return EINVAL; + } - *pFile = fopen(filename, mode); + *pFile = fopen(filename, mode); - if (!*pFile) - { - return errno; - } + if (!*pFile) + { + return errno; + } - return 0; + return 0; } #endif - - -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -LogImpl::LogImpl -( - string const& _filename, - bool const _bAppendLog, - bool const _bConsoleOutput, - LogLevel const _saveLevel, - LogLevel const _queueLevel, - LogLevel const _dumpTrigger -): - m_filename( _filename ), // name of log file - m_bConsoleOutput( _bConsoleOutput ), // true to provide a copy of output to console - m_bAppendLog( _bAppendLog ), // true to append (and not overwrite) any existing log - m_saveLevel( _saveLevel ), // level of messages to log to file - m_queueLevel( _queueLevel ), // level of messages to log to queue - m_dumpTrigger( _dumpTrigger ) // dump queued messages when this level is seen -{ - string accessType; + LogImpl::LogImpl(string const& _filename, bool const _bAppendLog, bool const _bConsoleOutput, LogLevel const _saveLevel, LogLevel const _queueLevel, LogLevel const _dumpTrigger) : + m_filename(_filename), // name of log file + m_bConsoleOutput(_bConsoleOutput), // true to provide a copy of output to console + m_bAppendLog(_bAppendLog), // true to append (and not overwrite) any existing log + m_saveLevel(_saveLevel), // level of messages to log to file + m_queueLevel(_queueLevel), // level of messages to log to queue + m_dumpTrigger(_dumpTrigger) // dump queued messages when this level is seen + { + string accessType; - // create an adjusted file name and timestamp string - string timeStr = GetTimeStampString(); + // create an adjusted file name and timestamp string + string timeStr = GetTimeStampString(); - if ( m_bAppendLog ) - { - accessType = "a"; - } - else - { - accessType = "w"; - } + if (m_bAppendLog) + { + accessType = "a"; + } + else + { + accessType = "w"; + } - FILE* pFile; - if( !fopen_s( &pFile, _filename.c_str(), accessType.c_str() ) ) - { - fprintf( pFile, "\nLogging started %s\n\n", timeStr.c_str() ); - fclose( pFile ); - } -} + FILE* pFile; + if (!fopen_s(&pFile, _filename.c_str(), accessType.c_str())) + { + fprintf(pFile, "\nLogging started %s\n\n", timeStr.c_str()); + fclose(pFile); + } + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -LogImpl::~LogImpl -( -) -{ -} -unsigned int LogImpl::toEscapeCode(LogLevel _level) { - unsigned short code; - - switch (_level) { - case LogLevel_Debug: code = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY; break; //blue - case LogLevel_Detail: code = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY; break; //blue - case LogLevel_Info: code = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; break; // white - case LogLevel_Alert: code = FOREGROUND_RED | FOREGROUND_GREEN; break; // orange - case LogLevel_Warning: code = FOREGROUND_RED | FOREGROUND_GREEN; break; // orange - case LogLevel_Error: code = FOREGROUND_RED; break; // red - case LogLevel_Fatal: code = FOREGROUND_RED | FOREGROUND_INTENSITY; break; // light red - case LogLevel_Always: code = FOREGROUND_GREEN; break; // green - default: code = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; break; // white - } - - return (code); -} - - + LogImpl::~LogImpl() + { + } + unsigned int LogImpl::toEscapeCode(LogLevel _level) + { + unsigned short code; + switch (_level) + { + case LogLevel_Debug: + code = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY; + break; //blue + case LogLevel_Detail: + code = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY; + break; //blue + case LogLevel_Info: + code = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; + break; // white + case LogLevel_Alert: + code = FOREGROUND_RED | FOREGROUND_GREEN; + break; // orange + case LogLevel_Warning: + code = FOREGROUND_RED | FOREGROUND_GREEN; + break; // orange + case LogLevel_Error: + code = FOREGROUND_RED; + break; // red + case LogLevel_Fatal: + code = FOREGROUND_RED | FOREGROUND_INTENSITY; + break; // light red + case LogLevel_Always: + code = FOREGROUND_GREEN; + break; // green + default: + code = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; + break; // white + } + return (code); + } //----------------------------------------------------------------------------- // // Write to the log //----------------------------------------------------------------------------- -void LogImpl::Write -( - LogLevel _logLevel, - uint8 const _nodeId, - char const* _format, - va_list _args -) -{ - // create a timestamp string - string timeStr = GetTimeStampString(); - string nodeStr = GetNodeString( _nodeId ); - string logLevelStr = GetLogLevelString(_logLevel); - - // handle this message - if( (_logLevel <= m_queueLevel) || (_logLevel == LogLevel_Internal) ) // we're going to do something with this message... - { - char lineBuf[1024]; - if( !_format || ( _format[0] == 0 ) ) - { - strcpy_s( lineBuf, 1024, "" ); - } - else - { - vsprintf_s( lineBuf, sizeof(lineBuf), _format, _args ); - } - - // should this message be saved to file (and possibly written to console?) - if( (_logLevel <= m_saveLevel) || (_logLevel == LogLevel_Internal) ) - { - // save to file - FILE* pFile = NULL; - if( !fopen_s( &pFile, m_filename.c_str(), "a" ) || m_bConsoleOutput ) + void LogImpl::Write(LogLevel _logLevel, uint8 const _nodeId, char const* _format, va_list _args) { - if( _logLevel != LogLevel_Internal ) // don't add a second timestamp to display of queued messages + // create a timestamp string + string timeStr = GetTimeStampString(); + string nodeStr = GetNodeString(_nodeId); + string logLevelStr = GetLogLevelString(_logLevel); + + // handle this message + if ((_logLevel <= m_queueLevel) || (_logLevel == LogLevel_Internal)) // we're going to do something with this message... { - if( pFile != NULL ) + char lineBuf[1024]; + if (!_format || (_format[0] == 0)) { - fprintf( pFile, "%s%s%s", timeStr.c_str(), logLevelStr.c_str(), nodeStr.c_str() ); + strcpy_s(lineBuf, 1024, ""); } - if( m_bConsoleOutput ) + else { - printf( "%s%s%s", timeStr.c_str(), logLevelStr.c_str(), nodeStr.c_str() ); + vsprintf_s(lineBuf, sizeof(lineBuf), _format, _args); } - } - // print message to file (and possibly screen) - if( pFile != NULL ) - { - fprintf( pFile, "%s", lineBuf ); - fprintf( pFile, "\n" ); - fclose( pFile ); + // should this message be saved to file (and possibly written to console?) + if ((_logLevel <= m_saveLevel) || (_logLevel == LogLevel_Internal)) + { + // save to file + FILE* pFile = NULL; + if (!fopen_s(&pFile, m_filename.c_str(), "a") || m_bConsoleOutput) + { + if (_logLevel != LogLevel_Internal) // don't add a second timestamp to display of queued messages + { + if (pFile != NULL) + { + fprintf(pFile, "%s%s%s", timeStr.c_str(), logLevelStr.c_str(), nodeStr.c_str()); + } + if (m_bConsoleOutput) + { + printf("%s%s%s", timeStr.c_str(), logLevelStr.c_str(), nodeStr.c_str()); + } + } + + // print message to file (and possibly screen) + if (pFile != NULL) + { + fprintf(pFile, "%s", lineBuf); + fprintf(pFile, "\n"); + fclose(pFile); + } + if (m_bConsoleOutput) + { + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), toEscapeCode(_logLevel)); + printf("%s", lineBuf); + printf("\n"); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + } + + } + } + + if (_logLevel != LogLevel_Internal) + { + char queueBuf[1024]; + string threadStr = GetThreadId(); + sprintf_s(queueBuf, sizeof(queueBuf), "%s%s%s", timeStr.c_str(), threadStr.c_str(), lineBuf); + Queue(queueBuf); + } } - if( m_bConsoleOutput ) + + // now check to see if the _dumpTrigger has been hit + if ((_logLevel <= m_dumpTrigger) && (_logLevel != LogLevel_Internal) && (_logLevel != LogLevel_Always)) { - SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), toEscapeCode(_logLevel)); - printf( "%s", lineBuf ); - printf( "\n" ); - SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + QueueDump(); } - } - } - - if( _logLevel != LogLevel_Internal ) - { - char queueBuf[1024]; - string threadStr = GetThreadId(); - sprintf_s( queueBuf, sizeof(queueBuf), "%s%s%s", timeStr.c_str(), threadStr.c_str(), lineBuf ); - Queue( queueBuf ); - } - } - - // now check to see if the _dumpTrigger has been hit - if( (_logLevel <= m_dumpTrigger) && (_logLevel != LogLevel_Internal) && (_logLevel != LogLevel_Always) ) - { - QueueDump(); - } -} //----------------------------------------------------------------------------- // // Write to the log queue //----------------------------------------------------------------------------- -void LogImpl::Queue -( - char const* _buffer -) -{ - string bufStr = _buffer; - m_logQueue.push_back( bufStr ); + void LogImpl::Queue(char const* _buffer) + { + string bufStr = _buffer; + m_logQueue.push_back(bufStr); - // rudimentary queue size management - if( m_logQueue.size() > 500 ) - { - m_logQueue.pop_front(); - } -} + // rudimentary queue size management + if (m_logQueue.size() > 500) + { + m_logQueue.pop_front(); + } + } //----------------------------------------------------------------------------- // // Dump the LogQueue to output device //----------------------------------------------------------------------------- -void LogImpl::QueueDump -( -) -{ - Log::Write( LogLevel_Internal, "\n\nDumping queued log messages\n"); - list::iterator it = m_logQueue.begin(); - while( it != m_logQueue.end() ) - { - string strTemp = *it; - Log::Write( LogLevel_Internal, "%s", strTemp.c_str() ); - ++it; - } - m_logQueue.clear(); - Log::Write( LogLevel_Internal, "\nEnd of queued log message dump\n\n"); -} + void LogImpl::QueueDump() + { + Log::Write(LogLevel_Internal, "\n\nDumping queued log messages\n"); + list::iterator it = m_logQueue.begin(); + while (it != m_logQueue.end()) + { + string strTemp = *it; + Log::Write(LogLevel_Internal, "%s", strTemp.c_str()); + ++it; + } + m_logQueue.clear(); + Log::Write(LogLevel_Internal, "\nEnd of queued log message dump\n\n"); + } //----------------------------------------------------------------------------- // // Clear the LogQueue //----------------------------------------------------------------------------- -void LogImpl::QueueClear -( -) -{ - m_logQueue.clear(); -} + void LogImpl::QueueClear() + { + m_logQueue.clear(); + } //----------------------------------------------------------------------------- // // Sets the various log state variables //----------------------------------------------------------------------------- -void LogImpl::SetLoggingState -( - LogLevel _saveLevel, - LogLevel _queueLevel, - LogLevel _dumpTrigger -) -{ - m_saveLevel = _saveLevel; - m_queueLevel = _queueLevel; - m_dumpTrigger = _dumpTrigger; -} + void LogImpl::SetLoggingState(LogLevel _saveLevel, LogLevel _queueLevel, LogLevel _dumpTrigger) + { + m_saveLevel = _saveLevel; + m_queueLevel = _queueLevel; + m_dumpTrigger = _dumpTrigger; + } //----------------------------------------------------------------------------- // // Generate a string with formatted current time //----------------------------------------------------------------------------- -string LogImpl::GetTimeStampString -( -) -{ - // Get a timestamp - SYSTEMTIME time; - ::GetLocalTime( &time ); - - // create a time stamp string for the log message - char buf[100]; - sprintf_s( buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d.%03d ", time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond, time.wMilliseconds ); - string str = buf; - return str; -} + string LogImpl::GetTimeStampString() + { + // Get a timestamp + SYSTEMTIME time; + ::GetLocalTime(&time); + + // create a time stamp string for the log message + char buf[100]; + sprintf_s(buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d.%03d ", time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond, time.wMilliseconds); + string str = buf; + return str; + } //----------------------------------------------------------------------------- // // Generate a string with formatted node id //----------------------------------------------------------------------------- -string LogImpl::GetNodeString -( - uint8 const _nodeId -) -{ - if( _nodeId == 0 ) - { - return ""; - } - else - if( _nodeId == 255 ) // should make distinction between broadcast and controller better for SwitchAll broadcast - { - return "contrlr, "; - } - else - { - char buf[20]; - snprintf( buf, sizeof(buf), "Node%03d, ", _nodeId ); - return buf; - } -} + string LogImpl::GetNodeString(uint8 const _nodeId) + { + if (_nodeId == 0) + { + return ""; + } + else if (_nodeId == 255) // should make distinction between broadcast and controller better for SwitchAll broadcast + { + return "contrlr, "; + } + else + { + char buf[20]; + snprintf(buf, sizeof(buf), "Node%03d, ", _nodeId); + return buf; + } + } //----------------------------------------------------------------------------- // // Generate a string with formatted thread id //----------------------------------------------------------------------------- -string LogImpl::GetThreadId -( -) -{ - char buf[20]; - DWORD dwThread = ::GetCurrentThreadId(); - sprintf_s( buf, sizeof(buf), "%04d ", dwThread ); - string str = buf; - return str; -} + string LogImpl::GetThreadId() + { + char buf[20]; + DWORD dwThread = ::GetCurrentThreadId(); + sprintf_s(buf, sizeof(buf), "%04d ", dwThread); + string str = buf; + return str; + } //----------------------------------------------------------------------------- // // Provide a new log file name (applicable to future writes) //----------------------------------------------------------------------------- -void LogImpl::SetLogFileName -( - const string &_filename -) -{ - m_filename = _filename; -} + void LogImpl::SetLogFileName(const string &_filename) + { + m_filename = _filename; + } //----------------------------------------------------------------------------- // // Provide a new log file name (applicable to future writes) //----------------------------------------------------------------------------- -string LogImpl::GetLogLevelString -( - LogLevel _level -) -{ - if ((_level >= LogLevel_None) && (_level <= LogLevel_Internal)) { - char buf[20]; - snprintf( buf, sizeof(buf), "%s, ", LogLevelString[_level] ); - return buf; - } - else - return "Unknown, "; -} + string LogImpl::GetLogLevelString(LogLevel _level) + { + if ((_level >= LogLevel_None) && (_level <= LogLevel_Internal)) + { + char buf[20]; + snprintf(buf, sizeof(buf), "%s, ", LogLevelString[_level]); + return buf; + } + else + return "Unknown, "; + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/windows/LogImpl.h b/cpp/src/platform/windows/LogImpl.h index 7ad49a8d41..663a8400c6 100644 --- a/cpp/src/platform/windows/LogImpl.h +++ b/cpp/src/platform/windows/LogImpl.h @@ -35,38 +35,44 @@ namespace OpenZWave { - /** \brief Windows-specific implementation of the Log class. - */ - class LogImpl : public i_LogImpl + namespace Internal { - private: - friend class Log; + namespace Platform + { - LogImpl( string const& _filename, bool const _bAppendLog, bool const _bConsoleOutput, LogLevel const _saveLevel, LogLevel const _queueLevel, LogLevel const _dumpTrigger ); - ~LogImpl(); + /** \brief Windows-specific implementation of the Log class. + */ + class LogImpl: public i_LogImpl + { + private: + friend class OpenZWave::Log; - void Write( LogLevel _level, uint8 const _nodeId, char const* _format, va_list _args ); - void Queue( char const* _buffer ); - void QueueDump(); - void QueueClear(); - void SetLoggingState( LogLevel _saveLevel, LogLevel _queueLevel, LogLevel _dumpTrigger ); - void SetLogFileName( const string &_filename ); + LogImpl(string const& _filename, bool const _bAppendLog, bool const _bConsoleOutput, LogLevel const _saveLevel, LogLevel const _queueLevel, LogLevel const _dumpTrigger); + ~LogImpl(); - string GetTimeStampString(); - string GetNodeString( uint8 const _nodeId ); - string GetThreadId(); - string GetLogLevelString(LogLevel _level); - unsigned int toEscapeCode(LogLevel _level); + void Write(LogLevel _level, uint8 const _nodeId, char const* _format, va_list _args); + void Queue(char const* _buffer); + void QueueDump(); + void QueueClear(); + void SetLoggingState(LogLevel _saveLevel, LogLevel _queueLevel, LogLevel _dumpTrigger); + void SetLogFileName(const string &_filename); - string m_filename; /**< filename specified by user (default is ozw_log.txt) */ - bool m_bConsoleOutput; /**< if true, send log output to console as well as to the file */ - bool m_bAppendLog; /**< if true, the log file should be appended to any with the same name */ - list m_logQueue; /**< list of queued log messages */ - LogLevel m_saveLevel; - LogLevel m_queueLevel; - LogLevel m_dumpTrigger; - }; + string GetTimeStampString(); + string GetNodeString(uint8 const _nodeId); + string GetThreadId(); + string GetLogLevelString(LogLevel _level); + unsigned int toEscapeCode(LogLevel _level); + string m_filename; /**< filename specified by user (default is ozw_log.txt) */ + bool m_bConsoleOutput; /**< if true, send log output to console as well as to the file */ + bool m_bAppendLog; /**< if true, the log file should be appended to any with the same name */ + list m_logQueue; /**< list of queued log messages */ + LogLevel m_saveLevel; + LogLevel m_queueLevel; + LogLevel m_dumpTrigger; + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_LogImpl_H diff --git a/cpp/src/platform/windows/MutexImpl.cpp b/cpp/src/platform/windows/MutexImpl.cpp index aa817d70df..f5593217c8 100644 --- a/cpp/src/platform/windows/MutexImpl.cpp +++ b/cpp/src/platform/windows/MutexImpl.cpp @@ -28,87 +28,83 @@ #include "Defs.h" #include "MutexImpl.h" - -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -MutexImpl::MutexImpl -( -): - m_lockCount( 0 ) -{ - InitializeCriticalSection( &m_criticalSection ); -} + MutexImpl::MutexImpl() : + m_lockCount(0) + { + InitializeCriticalSection(&m_criticalSection); + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -MutexImpl::~MutexImpl -( -) -{ - DeleteCriticalSection( &m_criticalSection ); -} + MutexImpl::~MutexImpl() + { + DeleteCriticalSection(&m_criticalSection); + } //----------------------------------------------------------------------------- // // Lock the mutex //----------------------------------------------------------------------------- -bool MutexImpl::Lock -( - bool const _bWait // = true; -) -{ - if( _bWait ) - { - // We will wait for the lock - EnterCriticalSection( &m_criticalSection ); - ++m_lockCount; - return true; - } + bool MutexImpl::Lock(bool const _bWait // = true; + ) + { + if (_bWait) + { + // We will wait for the lock + EnterCriticalSection(&m_criticalSection); + ++m_lockCount; + return true; + } - // Returns immediately, even if the lock was not available. - if( TryEnterCriticalSection( &m_criticalSection ) ) - { - ++m_lockCount; - return true; - } + // Returns immediately, even if the lock was not available. + if (TryEnterCriticalSection(&m_criticalSection)) + { + ++m_lockCount; + return true; + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Release our lock on the mutex //----------------------------------------------------------------------------- -void MutexImpl::Unlock -( -) -{ - if( !m_lockCount ) - { - // No locks - we have a mismatched lock/release pair - assert(0); - } - else - { - --m_lockCount; - LeaveCriticalSection( &m_criticalSection ); - } -} + void MutexImpl::Unlock() + { + if (!m_lockCount) + { + // No locks - we have a mismatched lock/release pair + assert(0); + } + else + { + --m_lockCount; + LeaveCriticalSection(&m_criticalSection); + } + } //----------------------------------------------------------------------------- // // Test whether the mutex is free //----------------------------------------------------------------------------- -bool MutexImpl::IsSignalled -( -) -{ - return( 0 == m_lockCount ); -} - + bool MutexImpl::IsSignalled() + { + return (0 == m_lockCount); + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/windows/MutexImpl.h b/cpp/src/platform/windows/MutexImpl.h index 0f4f780a5a..f51bb6eba2 100644 --- a/cpp/src/platform/windows/MutexImpl.h +++ b/cpp/src/platform/windows/MutexImpl.h @@ -30,28 +30,33 @@ #include - namespace OpenZWave { - /** \brief Windows-specific implementation of the Mutex class. - */ - class MutexImpl + namespace Internal { - private: - friend class Mutex; + namespace Platform + { - MutexImpl(); - ~MutexImpl(); + /** \brief Windows-specific implementation of the Mutex class. + */ + class MutexImpl + { + private: + friend class Mutex; - bool Lock( bool const _bWait = true ); - void Unlock(); + MutexImpl(); + ~MutexImpl(); - bool IsSignalled(); + bool Lock(bool const _bWait = true); + void Unlock(); - CRITICAL_SECTION m_criticalSection; - uint32 m_lockCount; // Keep track of the locks (there can be more than one if they occur on the same thread. - }; + bool IsSignalled(); + CRITICAL_SECTION m_criticalSection; + uint32 m_lockCount; // Keep track of the locks (there can be more than one if they occur on the same thread. + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_MutexIF_H diff --git a/cpp/src/platform/windows/SerialControllerImpl.cpp b/cpp/src/platform/windows/SerialControllerImpl.cpp index 9f06c3a1ff..f81303bc1c 100644 --- a/cpp/src/platform/windows/SerialControllerImpl.cpp +++ b/cpp/src/platform/windows/SerialControllerImpl.cpp @@ -30,381 +30,360 @@ #include "platform/Log.h" -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { -DWORD WINAPI SerialReadThreadEntryPoint( void* _context ); + DWORD WINAPI SerialReadThreadEntryPoint(void* _context); //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -SerialControllerImpl::SerialControllerImpl -( - SerialController* _owner -): - m_owner( _owner ) -{ -} + SerialControllerImpl::SerialControllerImpl(SerialController* _owner) : + m_owner(_owner) + { + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -SerialControllerImpl::~SerialControllerImpl -( -) -{ - CloseHandle( m_hSerialController ); -} + SerialControllerImpl::~SerialControllerImpl() + { + CloseHandle(m_hSerialController); + } //----------------------------------------------------------------------------- // // Open the serial port //----------------------------------------------------------------------------- -bool SerialControllerImpl::Open -( -) -{ - // Try to init the serial port - if( !Init( 1 ) ) - { - // Failed. We bail to allow the app a chance to take over, rather than retry - // automatically. Automatic retries only occur after a successful init. - return false; - } + bool SerialControllerImpl::Open() + { + // Try to init the serial port + if (!Init(1)) + { + // Failed. We bail to allow the app a chance to take over, rather than retry + // automatically. Automatic retries only occur after a successful init. + return false; + } - // Create an event to trigger exiting the read thread - m_hExit = ::CreateEvent( NULL, TRUE, FALSE, NULL ); + // Create an event to trigger exiting the read thread + m_hExit = ::CreateEvent( NULL, TRUE, FALSE, NULL); - // Start the read thread - m_hThread = ::CreateThread( NULL, 0, SerialReadThreadEntryPoint, this, CREATE_SUSPENDED, NULL ); - ::ResumeThread( m_hThread ); + // Start the read thread + m_hThread = ::CreateThread( NULL, 0, SerialReadThreadEntryPoint, this, CREATE_SUSPENDED, NULL); + ::ResumeThread(m_hThread); - return true; -} + return true; + } //----------------------------------------------------------------------------- // // Close the serial port //----------------------------------------------------------------------------- -void SerialControllerImpl::Close -( -) -{ - ::SetEvent( m_hExit ); - ::WaitForSingleObject( m_hThread, INFINITE ); + void SerialControllerImpl::Close() + { + ::SetEvent(m_hExit); + ::WaitForSingleObject(m_hThread, INFINITE); - CloseHandle( m_hThread ); - m_hThread = INVALID_HANDLE_VALUE; + CloseHandle(m_hThread); + m_hThread = INVALID_HANDLE_VALUE; - CloseHandle( m_hExit ); - m_hExit = INVALID_HANDLE_VALUE; + CloseHandle(m_hExit); + m_hExit = INVALID_HANDLE_VALUE; - CloseHandle( m_hSerialController ); - m_hSerialController = INVALID_HANDLE_VALUE; -} + CloseHandle(m_hSerialController); + m_hSerialController = INVALID_HANDLE_VALUE; + } //----------------------------------------------------------------------------- // // Entry point of the thread for receiving data from the serial port //----------------------------------------------------------------------------- -DWORD WINAPI SerialReadThreadEntryPoint -( - void* _context -) -{ - SerialControllerImpl* impl = (SerialControllerImpl*)_context; - if( impl ) - { - impl->ReadThreadProc(); - } + DWORD WINAPI SerialReadThreadEntryPoint(void* _context) + { + SerialControllerImpl* impl = (SerialControllerImpl*) _context; + if (impl) + { + impl->ReadThreadProc(); + } - return 0; -} + return 0; + } //----------------------------------------------------------------------------- // // Handle receiving data //----------------------------------------------------------------------------- -void SerialControllerImpl::ReadThreadProc -( -) -{ - uint32 attempts = 0; - while( true ) - { - // Init must have been called successfully during Open, so we - // don't do it again until the end of the loop - if( INVALID_HANDLE_VALUE != m_hSerialController ) - { - // Enter read loop. Call will only return if - // an exit is requested or an error occurs - Read(); + void SerialControllerImpl::ReadThreadProc() + { + uint32 attempts = 0; + while (true) + { + // Init must have been called successfully during Open, so we + // don't do it again until the end of the loop + if (INVALID_HANDLE_VALUE != m_hSerialController) + { + // Enter read loop. Call will only return if + // an exit is requested or an error occurs + Read(); - // Reset the attempts, so we get a rapid retry for temporary errors - attempts = 0; - } + // Reset the attempts, so we get a rapid retry for temporary errors + attempts = 0; + } - if( attempts < 25 ) - { - // Retry every 5 seconds for the first two minutes... - if( WAIT_OBJECT_0 == ::WaitForSingleObject( m_hExit, 5000 ) ) - { - // Exit signalled. - break; - } - } - else - { - // ...retry every 30 seconds after that - if( WAIT_OBJECT_0 == ::WaitForSingleObject( m_hExit, 30000 ) ) - { - // Exit signalled. - break; - } - } + if (attempts < 25) + { + // Retry every 5 seconds for the first two minutes... + if (WAIT_OBJECT_0 == ::WaitForSingleObject(m_hExit, 5000)) + { + // Exit signalled. + break; + } + } + else + { + // ...retry every 30 seconds after that + if (WAIT_OBJECT_0 == ::WaitForSingleObject(m_hExit, 30000)) + { + // Exit signalled. + break; + } + } - Init( ++attempts ); - } -} + Init(++attempts); + } + } //----------------------------------------------------------------------------- // // Initialize the serial port //----------------------------------------------------------------------------- -bool SerialControllerImpl::Init -( - uint32 const _attempts -) -{ - Log::Write( LogLevel_Info, " Trying to open serial port %s (Attempt %d)", m_owner->m_serialControllerName.c_str(), _attempts ); - - m_hSerialController = CreateFileA( m_owner->m_serialControllerName.c_str(), - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, - NULL ); - - if( INVALID_HANDLE_VALUE == m_hSerialController ) - { - //Error - Log::Write( LogLevel_Error, "ERROR: Cannot open serial port %s. Error code %d\n", m_owner->m_serialControllerName.c_str(), GetLastError() ); - goto SerialOpenFailure; - } - - // Configure the serial device parameters - // Build on the current configuration - DCB dcb; - if( !GetCommState( m_hSerialController, &dcb ) ) - { - //Error. Clean up and exit - Log::Write( LogLevel_Error, "ERROR: Failed to read serial port state" ); - goto SerialOpenFailure; - } - - // Fill in the Device Control Block - dcb.BaudRate = (DWORD)m_owner->m_baud; - dcb.ByteSize = 8; - dcb.Parity = (BYTE)m_owner->m_parity; - dcb.StopBits = (BYTE)m_owner->m_stopBits; - - if( !SetCommState( m_hSerialController, &dcb) ) - { - //Error. Clean up and exit - Log::Write( LogLevel_Error, "ERROR: Failed to set serial port state" ); - goto SerialOpenFailure; - } - - // Set the timeouts for the serial port - COMMTIMEOUTS commTimeouts; - commTimeouts.ReadIntervalTimeout = MAXDWORD; - commTimeouts.ReadTotalTimeoutConstant = 0; - commTimeouts.ReadTotalTimeoutMultiplier = 0; - commTimeouts.WriteTotalTimeoutConstant = 0; - commTimeouts.WriteTotalTimeoutMultiplier = 0; - if( !SetCommTimeouts( m_hSerialController, &commTimeouts ) ) - { - // Error. Clean up and exit - Log::Write( LogLevel_Error, "ERROR: Failed to set serial port timeouts" ); - goto SerialOpenFailure; - } + bool SerialControllerImpl::Init(uint32 const _attempts) + { + Log::Write(LogLevel_Info, " Trying to open serial port %s (Attempt %d)", m_owner->m_serialControllerName.c_str(), _attempts); - // Set the serial port to signal when data is received - if( !SetCommMask( m_hSerialController, EV_RXCHAR ) ) - { - //Error. Clean up and exit - Log::Write( LogLevel_Info, "ERROR: Failed to set serial port mask" ); - goto SerialOpenFailure; - } + m_hSerialController = CreateFileA(m_owner->m_serialControllerName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, + NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, + NULL); + + if (INVALID_HANDLE_VALUE == m_hSerialController) + { + //Error + Log::Write(LogLevel_Error, "ERROR: Cannot open serial port %s. Error code %d\n", m_owner->m_serialControllerName.c_str(), GetLastError()); + goto SerialOpenFailure; + } - // Clear any residual data from the serial port - PurgeComm( m_hSerialController, PURGE_RXABORT|PURGE_RXCLEAR|PURGE_TXABORT|PURGE_TXCLEAR ); + // Configure the serial device parameters + // Build on the current configuration + DCB dcb; + if (!GetCommState(m_hSerialController, &dcb)) + { + //Error. Clean up and exit + Log::Write(LogLevel_Error, "ERROR: Failed to read serial port state"); + goto SerialOpenFailure; + } + + // Fill in the Device Control Block + dcb.BaudRate = (DWORD) m_owner->m_baud; + dcb.ByteSize = 8; + dcb.Parity = (BYTE) m_owner->m_parity; + dcb.StopBits = (BYTE) m_owner->m_stopBits; + + if (!SetCommState(m_hSerialController, &dcb)) + { + //Error. Clean up and exit + Log::Write(LogLevel_Error, "ERROR: Failed to set serial port state"); + goto SerialOpenFailure; + } + + // Set the timeouts for the serial port + COMMTIMEOUTS commTimeouts; + commTimeouts.ReadIntervalTimeout = MAXDWORD; + commTimeouts.ReadTotalTimeoutConstant = 0; + commTimeouts.ReadTotalTimeoutMultiplier = 0; + commTimeouts.WriteTotalTimeoutConstant = 0; + commTimeouts.WriteTotalTimeoutMultiplier = 0; + if (!SetCommTimeouts(m_hSerialController, &commTimeouts)) + { + // Error. Clean up and exit + Log::Write(LogLevel_Error, "ERROR: Failed to set serial port timeouts"); + goto SerialOpenFailure; + } + + // Set the serial port to signal when data is received + if (!SetCommMask(m_hSerialController, EV_RXCHAR)) + { + //Error. Clean up and exit + Log::Write(LogLevel_Info, "ERROR: Failed to set serial port mask"); + goto SerialOpenFailure; + } + + // Clear any residual data from the serial port + PurgeComm(m_hSerialController, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR); - // Open successful - Log::Write( LogLevel_Info, " Serial port %s opened (attempt %d)", m_owner->m_serialControllerName.c_str(), _attempts ); - return true; + // Open successful + Log::Write(LogLevel_Info, " Serial port %s opened (attempt %d)", m_owner->m_serialControllerName.c_str(), _attempts); + return true; -SerialOpenFailure: - Log::Write( LogLevel_Info, "ERROR: Failed to open serial port %s (attempt %d)", m_owner->m_serialControllerName.c_str(), _attempts ); - CloseHandle( m_hSerialController ); - m_hSerialController = INVALID_HANDLE_VALUE; - return false; -} + SerialOpenFailure: Log::Write(LogLevel_Info, "ERROR: Failed to open serial port %s (attempt %d)", m_owner->m_serialControllerName.c_str(), _attempts); + CloseHandle(m_hSerialController); + m_hSerialController = INVALID_HANDLE_VALUE; + return false; + } //----------------------------------------------------------------------------- // // Read data from the serial port //----------------------------------------------------------------------------- -void SerialControllerImpl::Read -( -) -{ - uint8 buffer[256]; - - OVERLAPPED overlapped; - memset( &overlapped, 0, sizeof(overlapped) ); - overlapped.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); - - while( true ) - { - // Try to read all available data from the serial port - DWORD bytesRead = 0; - do - { - if( ::ReadFile( m_hSerialController, buffer, 256, NULL, &overlapped ) ) + void SerialControllerImpl::Read() { - // Read completed - GetOverlappedResult( m_hSerialController, &overlapped, &bytesRead, TRUE ); + uint8 buffer[256]; - // Copy to the stream buffer - if( bytesRead > 0 ) - m_owner->Put( buffer, bytesRead ); - } - else - { - //Wait for the read to complete - if( ERROR_IO_PENDING == GetLastError() ) + OVERLAPPED overlapped; + memset(&overlapped, 0, sizeof(overlapped)); + overlapped.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL); + + while (true) { - // Wait for the read to complete or the - // signal that this thread should exit. - HANDLE handles[2]; - handles[0] = overlapped.hEvent; - handles[1] = m_hExit; - DWORD res = WaitForMultipleObjects( 2, handles, FALSE, INFINITE ); - - if( (WAIT_OBJECT_0+1) == res ) + // Try to read all available data from the serial port + DWORD bytesRead = 0; + do { - // Exit signalled. Cancel the read. - goto exitRead; - } - - if( WAIT_TIMEOUT == res ) + if (::ReadFile(m_hSerialController, buffer, 256, NULL, &overlapped)) + { + // Read completed + GetOverlappedResult(m_hSerialController, &overlapped, &bytesRead, TRUE); + + // Copy to the stream buffer + if (bytesRead > 0) + m_owner->Put(buffer, bytesRead); + } + else + { + //Wait for the read to complete + if (ERROR_IO_PENDING == GetLastError()) + { + // Wait for the read to complete or the + // signal that this thread should exit. + HANDLE handles[2]; + handles[0] = overlapped.hEvent; + handles[1] = m_hExit; + DWORD res = WaitForMultipleObjects(2, handles, FALSE, INFINITE); + + if ((WAIT_OBJECT_0 + 1) == res) + { + // Exit signalled. Cancel the read. + goto exitRead; + } + + if (WAIT_TIMEOUT == res) + { + // Timed out - should never happen + goto exitRead; + } + + // Read completed + GetOverlappedResult(m_hSerialController, &overlapped, &bytesRead, TRUE); + + // Copy to the stream buffer + if (bytesRead > 0) + m_owner->Put(buffer, bytesRead); + } + else + { + // An error has occurred + goto exitRead; + } + } + } while (bytesRead > 0); + + // Clear the event + ResetEvent(overlapped.hEvent); + + // Nothing available to read, so wait for the next rx char event + DWORD dwEvtMask; + if (!WaitCommEvent(m_hSerialController, &dwEvtMask, &overlapped)) { - // Timed out - should never happen - goto exitRead; + if (ERROR_IO_PENDING == GetLastError()) + { + // Wait for either some data to arrive or + // the signal that this thread should exit. + HANDLE handles[2]; + handles[0] = overlapped.hEvent; + handles[1] = m_hExit; + + DWORD res = WaitForMultipleObjects(2, handles, FALSE, INFINITE); + + if ((WAIT_OBJECT_0 + 1) == res) + { + // Exit signalled. Prevent WaitCommEvent from corrupting the + // stack by forcing it to exit. + goto exitRead; + } + + if (WAIT_TIMEOUT == res) + { + // Timed out - should never happen + goto exitRead; + } + + GetOverlappedResult(m_hSerialController, &overlapped, &bytesRead, TRUE); + } } - // Read completed - GetOverlappedResult( m_hSerialController, &overlapped, &bytesRead, TRUE ); + // Clear the event + ResetEvent(overlapped.hEvent); - // Copy to the stream buffer - if( bytesRead > 0 ) - m_owner->Put( buffer, bytesRead ); - } - else - { - // An error has occurred - goto exitRead; + // Loop back to the top to read the waiting data } + + exitRead: + // Exit event has been signalled, or an error has occurred + SetCommMask(m_hSerialController, 0); + CancelIo(m_hSerialController); + CloseHandle(overlapped.hEvent); } - } - while( bytesRead > 0 ); - - // Clear the event - ResetEvent( overlapped.hEvent ); - - // Nothing available to read, so wait for the next rx char event - DWORD dwEvtMask; - if( !WaitCommEvent( m_hSerialController, &dwEvtMask, &overlapped ) ) - { - if( ERROR_IO_PENDING == GetLastError() ) + +//----------------------------------------------------------------------------- +// +// Send data to the serial port +//----------------------------------------------------------------------------- + uint32 SerialControllerImpl::Write(uint8* _buffer, uint32 _length) { - // Wait for either some data to arrive or - // the signal that this thread should exit. - HANDLE handles[2]; - handles[0] = overlapped.hEvent; - handles[1] = m_hExit; - - DWORD res = WaitForMultipleObjects( 2, handles, FALSE, INFINITE ); - - if( (WAIT_OBJECT_0+1) == res ) + if (INVALID_HANDLE_VALUE == m_hSerialController) { - // Exit signalled. Prevent WaitCommEvent from corrupting the - // stack by forcing it to exit. - goto exitRead; + //Error + Log::Write(LogLevel_Error, "ERROR: Serial port must be opened before writing\n"); + return 0; } - if( WAIT_TIMEOUT == res ) + // Write the data + OVERLAPPED overlapped; + memset(&overlapped, 0, sizeof(overlapped)); + overlapped.hEvent = CreateEvent( NULL, FALSE, FALSE, NULL); + + DWORD bytesWritten; + if (!::WriteFile(m_hSerialController, _buffer, _length, &bytesWritten, &overlapped)) { - // Timed out - should never happen - goto exitRead; + //Wait for the write to complete + if (ERROR_IO_PENDING == GetLastError()) + { + GetOverlappedResult(m_hSerialController, &overlapped, &bytesWritten, TRUE); + } + else + { + Log::Write(LogLevel_Error, "ERROR: Serial port write (0x%.8x)", GetLastError()); + } } - GetOverlappedResult( m_hSerialController, &overlapped, &bytesRead, TRUE ); + CloseHandle(overlapped.hEvent); + return (uint32) bytesWritten; } - } - - // Clear the event - ResetEvent( overlapped.hEvent ); - - // Loop back to the top to read the waiting data - } - -exitRead: - // Exit event has been signalled, or an error has occurred - SetCommMask( m_hSerialController, 0 ); - CancelIo( m_hSerialController ); - CloseHandle( overlapped.hEvent ); -} - -//----------------------------------------------------------------------------- -// -// Send data to the serial port -//----------------------------------------------------------------------------- -uint32 SerialControllerImpl::Write -( - uint8* _buffer, - uint32 _length -) -{ - if( INVALID_HANDLE_VALUE == m_hSerialController ) - { - //Error - Log::Write( LogLevel_Error, "ERROR: Serial port must be opened before writing\n" ); - return 0; - } - - // Write the data - OVERLAPPED overlapped; - memset( &overlapped, 0, sizeof(overlapped) ); - overlapped.hEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); - - DWORD bytesWritten; - if( !::WriteFile( m_hSerialController, _buffer, _length, &bytesWritten, &overlapped ) ) - { - //Wait for the write to complete - if( ERROR_IO_PENDING == GetLastError() ) - { - GetOverlappedResult( m_hSerialController, &overlapped, &bytesWritten, TRUE ); - } - else - { - Log::Write( LogLevel_Error, "ERROR: Serial port write (0x%.8x)", GetLastError() ); - } - } - - CloseHandle( overlapped.hEvent ); - return (uint32)bytesWritten; -} + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/windows/SerialControllerImpl.h b/cpp/src/platform/windows/SerialControllerImpl.h index 1bdf8fe2f9..a62d14358d 100644 --- a/cpp/src/platform/windows/SerialControllerImpl.h +++ b/cpp/src/platform/windows/SerialControllerImpl.h @@ -35,31 +35,36 @@ namespace OpenZWave { - class SerialControllerImpl + namespace Internal { - public: - void ReadThreadProc(); + namespace Platform + { + class SerialControllerImpl + { + public: + void ReadThreadProc(); - private: - friend class SerialController; + private: + friend class SerialController; - SerialControllerImpl( SerialController* _owner ); - ~SerialControllerImpl(); + SerialControllerImpl(SerialController* _owner); + ~SerialControllerImpl(); - bool Open(); - void Close(); + bool Open(); + void Close(); - uint32 Write( uint8* _buffer, uint32 _length ); - - bool Init( uint32 const _attempts ); - void Read(); + uint32 Write(uint8* _buffer, uint32 _length); - SerialController* m_owner; - HANDLE m_hThread; - HANDLE m_hExit; - HANDLE m_hSerialController; - }; + bool Init(uint32 const _attempts); + void Read(); + SerialController* m_owner; + HANDLE m_hThread; + HANDLE m_hExit; + HANDLE m_hSerialController; + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_SerialControllerImpl_H diff --git a/cpp/src/platform/windows/ThreadImpl.cpp b/cpp/src/platform/windows/ThreadImpl.cpp index cefda2a9f5..82a5cd7140 100644 --- a/cpp/src/platform/windows/ThreadImpl.cpp +++ b/cpp/src/platform/windows/ThreadImpl.cpp @@ -30,129 +30,109 @@ #include "platform/Thread.h" #include "ThreadImpl.h" -using namespace OpenZWave; - +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -ThreadImpl::ThreadImpl -( - Thread* _owner, - string const& _name -): - m_owner( _owner ), - m_hThread( INVALID_HANDLE_VALUE ), - m_bIsRunning( false ), - m_name( _name ) -{ + ThreadImpl::ThreadImpl(Thread* _owner, string const& _name) : + m_owner(_owner), m_hThread(INVALID_HANDLE_VALUE), m_bIsRunning(false), m_name(_name) + { -} + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -ThreadImpl::~ThreadImpl -( -) -{ -} + ThreadImpl::~ThreadImpl() + { + } //----------------------------------------------------------------------------- // // Start a function running on this thread //----------------------------------------------------------------------------- -bool ThreadImpl::Start -( - Thread::pfnThreadProc_t _pfnThreadProc, - Event* _exitEvent, - void* _context -) -{ - // Create a thread to run the specified function - m_pfnThreadProc = _pfnThreadProc; - m_context = _context; - m_exitEvent = _exitEvent; - m_exitEvent->Reset(); + bool ThreadImpl::Start(Thread::pfnThreadProc_t _pfnThreadProc, Event* _exitEvent, void* _context) + { + // Create a thread to run the specified function + m_pfnThreadProc = _pfnThreadProc; + m_context = _context; + m_exitEvent = _exitEvent; + m_exitEvent->Reset(); - HANDLE hThread = ::CreateThread( NULL, 0, ThreadImpl::ThreadProc, this, CREATE_SUSPENDED, NULL ); - m_hThread = hThread; + HANDLE hThread = ::CreateThread( NULL, 0, ThreadImpl::ThreadProc, this, CREATE_SUSPENDED, NULL); + m_hThread = hThread; - ::ResumeThread( hThread ); - return true; -} + ::ResumeThread(hThread); + return true; + } //----------------------------------------------------------------------------- // // Cause thread to sleep for the specified number of milliseconds //----------------------------------------------------------------------------- -void ThreadImpl::Sleep -( - uint32 _millisecs -) -{ - ::Sleep(_millisecs); -} + void ThreadImpl::Sleep(uint32 _millisecs) + { + ::Sleep(_millisecs); + } //----------------------------------------------------------------------------- // // Force the thread to stop //----------------------------------------------------------------------------- -bool ThreadImpl::Terminate -( -) -{ - if( !m_bIsRunning ) - { - return false; - } + bool ThreadImpl::Terminate() + { + if (!m_bIsRunning) + { + return false; + } - // This can cause all sorts of trouble if the thread is holding a lock. - TerminateThread( m_hThread, 0 ); - m_hThread = INVALID_HANDLE_VALUE; - return true; -} + // This can cause all sorts of trouble if the thread is holding a lock. + TerminateThread(m_hThread, 0); + m_hThread = INVALID_HANDLE_VALUE; + return true; + } //----------------------------------------------------------------------------- // // Test whether the thread has completed //----------------------------------------------------------------------------- -bool ThreadImpl::IsSignalled -( -) -{ - return !m_bIsRunning; -} + bool ThreadImpl::IsSignalled() + { + return !m_bIsRunning; + } //----------------------------------------------------------------------------- // // Entry point for running a function on this thread //----------------------------------------------------------------------------- -DWORD WINAPI ThreadImpl::ThreadProc -( - void* _pArg -) -{ - ThreadImpl* pImpl = (ThreadImpl*)_pArg; - pImpl->Run(); - return 0; -} + DWORD WINAPI ThreadImpl::ThreadProc(void* _pArg) + { + ThreadImpl* pImpl = (ThreadImpl*) _pArg; + pImpl->Run(); + return 0; + } //----------------------------------------------------------------------------- // // Entry point for running a function on this thread //----------------------------------------------------------------------------- -void ThreadImpl::Run -( -) -{ - m_bIsRunning = true; - m_pfnThreadProc( m_exitEvent, m_context ); - m_bIsRunning = false; - - // Let any watchers know that the thread has finished running. - m_owner->Notify(); -} + void ThreadImpl::Run() + { + m_bIsRunning = true; + m_pfnThreadProc(m_exitEvent, m_context); + m_bIsRunning = false; + // Let any watchers know that the thread has finished running. + m_owner->Notify(); + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/windows/ThreadImpl.h b/cpp/src/platform/windows/ThreadImpl.h index 3de1bb2424..04a82426a1 100644 --- a/cpp/src/platform/windows/ThreadImpl.h +++ b/cpp/src/platform/windows/ThreadImpl.h @@ -34,37 +34,42 @@ namespace OpenZWave { - class Thread; - class Event; - - /** \brief Windows-specific implementation of the Thread class. - */ - class ThreadImpl + namespace Internal { - private: - friend class Thread; + namespace Platform + { + + class Thread; + class Event; - ThreadImpl( Thread* _owner, string const& _name ); - ~ThreadImpl(); + /** \brief Windows-specific implementation of the Thread class. + */ + class ThreadImpl + { + private: + friend class Thread; - bool Start( Thread::pfnThreadProc_t _pfnThreadProc, Event* _exitEvent, void* _context ); - void Sleep( uint32 _milliseconds ); - bool Terminate(); + ThreadImpl(Thread* _owner, string const& _name); + ~ThreadImpl(); - bool IsSignalled(); + bool Start(Thread::pfnThreadProc_t _pfnThreadProc, Event* _exitEvent, void* _context); + void Sleep(uint32 _milliseconds); + bool Terminate(); - void Run(); - static DWORD WINAPI ThreadProc( void* _pArg ); + bool IsSignalled(); - Thread* m_owner; - HANDLE m_hThread; - Event* m_exitEvent; - Thread::pfnThreadProc_t m_pfnThreadProc; - void* m_context; - bool m_bIsRunning; - string m_name; - }; + void Run();static DWORD WINAPI ThreadProc( void* _pArg ); + Thread* m_owner; + HANDLE m_hThread; + Event* m_exitEvent; + Thread::pfnThreadProc_t m_pfnThreadProc; + void* m_context; + bool m_bIsRunning; + string m_name; + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_ThreadImpl_H diff --git a/cpp/src/platform/windows/TimeStampImpl.cpp b/cpp/src/platform/windows/TimeStampImpl.cpp index cb21139712..34148d2177 100644 --- a/cpp/src/platform/windows/TimeStampImpl.cpp +++ b/cpp/src/platform/windows/TimeStampImpl.cpp @@ -30,85 +30,80 @@ #include "Defs.h" #include "TimeStampImpl.h" -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -TimeStampImpl::TimeStampImpl -( -) -{ - SetTime(0); -} + TimeStampImpl::TimeStampImpl() + { + SetTime(0); + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -TimeStampImpl::~TimeStampImpl -( -) -{ -} + TimeStampImpl::~TimeStampImpl() + { + } //----------------------------------------------------------------------------- // // Sets the timestamp to now, plus an offset in milliseconds //----------------------------------------------------------------------------- -void TimeStampImpl::SetTime -( - int32 _milliseconds // = 0 -) -{ - int64 offset = ((int64)_milliseconds) * 10000LL; // Timestamp is stored in 100ns steps. + void TimeStampImpl::SetTime(int32 _milliseconds // = 0 + ) + { + int64 offset = ((int64) _milliseconds) * 10000LL; // Timestamp is stored in 100ns steps. - GetSystemTimeAsFileTime( (FILETIME*)&m_stamp ); - m_stamp += offset; -} + GetSystemTimeAsFileTime((FILETIME*) &m_stamp); + m_stamp += offset; + } //----------------------------------------------------------------------------- // // Gets the difference between now and the timestamp time in milliseconds //----------------------------------------------------------------------------- -int32 TimeStampImpl::TimeRemaining -( -) -{ - int64 now; - GetSystemTimeAsFileTime( (FILETIME*)&now ); + int32 TimeStampImpl::TimeRemaining() + { + int64 now; + GetSystemTimeAsFileTime((FILETIME*) &now); - return (int32)( ( m_stamp - now ) / 10000LL ); -} + return (int32) ((m_stamp - now) / 10000LL); + } //----------------------------------------------------------------------------- // // Return a string representation //----------------------------------------------------------------------------- -string TimeStampImpl::GetAsString -( -) -{ - // Convert m_stamp (FILETIME) to SYSTEMTIME for ease of use - SYSTEMTIME time; - ::FileTimeToSystemTime( (FILETIME*)&m_stamp, &time ); + string TimeStampImpl::GetAsString() + { + // Convert m_stamp (FILETIME) to SYSTEMTIME for ease of use + SYSTEMTIME time; + ::FileTimeToSystemTime((FILETIME*) &m_stamp, &time); - char buf[100]; - sprintf_s( buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d:%03d ", time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond, time.wMilliseconds ); - string str = buf; - return str; -} + char buf[100]; + sprintf_s(buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d:%03d ", time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond, time.wMilliseconds); + string str = buf; + return str; + } //----------------------------------------------------------------------------- // // Overload the subtract operator to get the difference between two // timestamps in milliseconds //----------------------------------------------------------------------------- -int32 TimeStampImpl::operator- -( - TimeStampImpl const& _other -) -{ - return (int32)( ( m_stamp - _other.m_stamp ) / 10000LL ); -} + int32 TimeStampImpl::operator-(TimeStampImpl const& _other) + { + return (int32) ((m_stamp - _other.m_stamp) / 10000LL); + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/windows/TimeStampImpl.h b/cpp/src/platform/windows/TimeStampImpl.h index 36432b672f..83e1de05a7 100644 --- a/cpp/src/platform/windows/TimeStampImpl.h +++ b/cpp/src/platform/windows/TimeStampImpl.h @@ -32,56 +32,62 @@ namespace OpenZWave { - /** \brief Windows implementation of a timestamp. - */ - class TimeStampImpl + namespace Internal { - public: - /** - * Constructor. - * Creates a TimeStampImpl object. - */ - TimeStampImpl(); + namespace Platform + { - /** - * Destructor. - * Destroys the TimeStampImpl object. - */ - ~TimeStampImpl(); + /** \brief Windows implementation of a timestamp. + */ + class TimeStampImpl + { + public: + /** + * Constructor. + * Creates a TimeStampImpl object. + */ + TimeStampImpl(); - /** - * SetTime. Sets the timestamp to now, plus the offset in milliseconds. - * \param _milliseconds positive or negative offset from - * now in milliseconds. - */ - void SetTime( int32 _milliseconds ); + /** + * Destructor. + * Destroys the TimeStampImpl object. + */ + ~TimeStampImpl(); - /** - * TimeRemaining. Gets the difference between now and the timestamp - * time in milliseconds. - * \return milliseconds remaining until we reach the timestamp. The - * return value is negative if the timestamp is in the past. - */ - int32 TimeRemaining(); + /** + * SetTime. Sets the timestamp to now, plus the offset in milliseconds. + * \param _milliseconds positive or negative offset from + * now in milliseconds. + */ + void SetTime(int32 _milliseconds); - /** - * Return as as string - */ - string GetAsString(); + /** + * TimeRemaining. Gets the difference between now and the timestamp + * time in milliseconds. + * \return milliseconds remaining until we reach the timestamp. The + * return value is negative if the timestamp is in the past. + */ + int32 TimeRemaining(); - /** - * Overload the subtract operator to get the difference between - * two timestamps in milliseconds. - */ - int32 operator- ( TimeStampImpl const& _other ); + /** + * Return as as string + */ + string GetAsString(); - private: - TimeStampImpl( TimeStampImpl const& ); // prevent copy - TimeStampImpl& operator = ( TimeStampImpl const& ); // prevent assignment + /** + * Overload the subtract operator to get the difference between + * two timestamps in milliseconds. + */ + int32 operator-(TimeStampImpl const& _other); - int64 m_stamp; - }; + private: + TimeStampImpl(TimeStampImpl const&); // prevent copy + TimeStampImpl& operator =(TimeStampImpl const&); // prevent assignment + int64 m_stamp; + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_TimeStampImpl_H diff --git a/cpp/src/platform/windows/WaitImpl.cpp b/cpp/src/platform/windows/WaitImpl.cpp index 5c43e78a2f..dd69d63d73 100644 --- a/cpp/src/platform/windows/WaitImpl.cpp +++ b/cpp/src/platform/windows/WaitImpl.cpp @@ -31,104 +31,97 @@ #include "WaitImpl.h" #include "platform/Log.h" -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace Platform + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -WaitImpl::WaitImpl -( - Wait* _owner -): - m_owner( _owner ) -{ - InitializeCriticalSection( &m_criticalSection ); -} + WaitImpl::WaitImpl(Wait* _owner) : + m_owner(_owner) + { + InitializeCriticalSection(&m_criticalSection); + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -WaitImpl::~WaitImpl -( -) -{ - DeleteCriticalSection( &m_criticalSection ); -} + WaitImpl::~WaitImpl() + { + DeleteCriticalSection(&m_criticalSection); + } //----------------------------------------------------------------------------- // // Add a watcher to our object. //----------------------------------------------------------------------------- -void WaitImpl::AddWatcher -( - Wait::pfnWaitNotification_t _callback, - void* _context -) -{ - // Add the watcher to our list - Watcher watcher; - watcher.m_callback = _callback; - watcher.m_context = _context; - - EnterCriticalSection( &m_criticalSection ); + void WaitImpl::AddWatcher(Wait::pfnWaitNotification_t _callback, void* _context) + { + // Add the watcher to our list + Watcher watcher; + watcher.m_callback = _callback; + watcher.m_context = _context; - m_watchers.push_back( watcher ); + EnterCriticalSection(&m_criticalSection); - LeaveCriticalSection( &m_criticalSection ); + m_watchers.push_back(watcher); - // If the object is already in a signalled state, notify the watcher immediately - if( m_owner->IsSignalled() ) - { - _callback( _context ); - } + LeaveCriticalSection(&m_criticalSection); -} + // If the object is already in a signalled state, notify the watcher immediately + if (m_owner->IsSignalled()) + { + _callback(_context); + } + + } //----------------------------------------------------------------------------- // // Remove a watcher from our object. //----------------------------------------------------------------------------- -bool WaitImpl::RemoveWatcher -( - Wait::pfnWaitNotification_t _callback, - void* _context -) -{ - bool res = false; - EnterCriticalSection( &m_criticalSection ); + bool WaitImpl::RemoveWatcher(Wait::pfnWaitNotification_t _callback, void* _context) + { + bool res = false; + EnterCriticalSection(&m_criticalSection); - for( list::iterator it=m_watchers.begin(); it!=m_watchers.end(); ++it ) - { - Watcher const& watcher = *it; - if( ( watcher.m_callback == _callback ) && ( watcher.m_context == _context ) ) - { - m_watchers.erase( it ); - res = true; - break; - } - } + for (list::iterator it = m_watchers.begin(); it != m_watchers.end(); ++it) + { + Watcher const& watcher = *it; + if ((watcher.m_callback == _callback) && (watcher.m_context == _context)) + { + m_watchers.erase(it); + res = true; + break; + } + } - LeaveCriticalSection( &m_criticalSection ); - return res; -} + LeaveCriticalSection(&m_criticalSection); + return res; + } //----------------------------------------------------------------------------- // // Notify all the watchers that the object has become signalled //----------------------------------------------------------------------------- -void WaitImpl::Notify -( -) -{ - EnterCriticalSection( &m_criticalSection ); + void WaitImpl::Notify() + { + EnterCriticalSection(&m_criticalSection); - for( list::iterator it=m_watchers.begin(); it!=m_watchers.end(); ++it ) - { - Watcher const& watcher = *it; - watcher.m_callback( watcher.m_context ); - } + for (list::iterator it = m_watchers.begin(); it != m_watchers.end(); ++it) + { + Watcher const& watcher = *it; + watcher.m_callback(watcher.m_context); + } - LeaveCriticalSection( &m_criticalSection ); -} + LeaveCriticalSection(&m_criticalSection); + } + } // namespace Platform + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/platform/windows/WaitImpl.h b/cpp/src/platform/windows/WaitImpl.h index 9c612ffaef..d34c5809ea 100644 --- a/cpp/src/platform/windows/WaitImpl.h +++ b/cpp/src/platform/windows/WaitImpl.h @@ -37,36 +37,42 @@ namespace OpenZWave { - /** \brief Windows specific implementation of Wait objects. - */ - class WaitImpl + namespace Internal { - private: - friend class Wait; + namespace Platform + { - WaitImpl( Wait* _owner ); - virtual ~WaitImpl(); + /** \brief Windows specific implementation of Wait objects. + */ + class WaitImpl + { + private: + friend class Wait; - void AddWatcher( Wait::pfnWaitNotification_t _callback, void* _context ); - bool RemoveWatcher( Wait::pfnWaitNotification_t _callback, void* _context ); - void Notify(); + WaitImpl(Wait* _owner); + virtual ~WaitImpl(); - static int32 Multiple( Wait** _objects, uint32 _numObjects, int32 _timeout = -1 ); + void AddWatcher(Wait::pfnWaitNotification_t _callback, void* _context); + bool RemoveWatcher(Wait::pfnWaitNotification_t _callback, void* _context); + void Notify(); - WaitImpl( Wait const& ); // prevent copy - WaitImpl& operator = ( WaitImpl const& ); // prevent assignment + static int32 Multiple(Wait** _objects, uint32 _numObjects, int32 _timeout = -1); - struct Watcher - { - Wait::pfnWaitNotification_t m_callback; - void* m_context; - }; + WaitImpl(Wait const&); // prevent copy + WaitImpl& operator =(WaitImpl const&); // prevent assignment - list m_watchers; - Wait* m_owner; - CRITICAL_SECTION m_criticalSection; - }; + struct Watcher + { + Wait::pfnWaitNotification_t m_callback; + void* m_context; + }; + list m_watchers; + Wait* m_owner; + CRITICAL_SECTION m_criticalSection; + }; + } // namespace Platform + } // namespace Internal } // namespace OpenZWave #endif //_WaitImpl_H diff --git a/cpp/src/value_classes/Value.cpp b/cpp/src/value_classes/Value.cpp index 5fab9f43e9..6182c3274f 100644 --- a/cpp/src/value_classes/Value.cpp +++ b/cpp/src/value_classes/Value.cpp @@ -39,747 +39,649 @@ #include #include "Options.h" -using namespace OpenZWave; - -static char const* c_genreName[] = -{ - "basic", - "user", - "config", - "system", - "invalid" -}; - -static char const* c_typeName[] = +namespace OpenZWave { - "bool", - "byte", - "decimal", - "int", - "list", - "schedule", - "short", - "string", - "button", - "raw", - "bitset", - "invalid type" -}; + namespace Internal + { + namespace VC + { + + static char const* c_genreName[] = + { "basic", "user", "config", "system", "invalid" }; + + static char const* c_typeName[] = + { "bool", "byte", "decimal", "int", "list", "schedule", "short", "string", "button", "raw", "bitset", "invalid type" }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -Value::Value -( - uint32 const _homeId, - uint8 const _nodeId, - ValueID::ValueGenre const _genre, - uint8 const _commandClassId, - uint8 const _instance, - uint16 const _index, - ValueID::ValueType const _type, - string const& _label, - string const& _units, - bool const _readOnly, - bool const _writeOnly, - bool const _isSet, - uint8 const _pollIntensity -): - m_min( 0 ), - m_max( 0 ), - m_refreshTime(0), - m_verifyChanges( false ), - m_id( _homeId, _nodeId, _genre, _commandClassId, _instance, _index, _type ), - m_units( _units ), - m_readOnly( _readOnly ), - m_writeOnly( _writeOnly ), - m_isSet( _isSet ), - m_affectsLength( 0 ), - m_affects(), - m_affectsAll( false ), - m_checkChange( false ), - m_pollIntensity( _pollIntensity ) -{ - SetLabel(_label); -} + Value::Value(uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, ValueID::ValueType const _type, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, bool const _isSet, uint8 const _pollIntensity) : + m_min(0), m_max(0), m_refreshTime(0), m_verifyChanges(false), m_id(_homeId, _nodeId, _genre, _commandClassId, _instance, _index, _type), m_units(_units), m_readOnly(_readOnly), m_writeOnly(_writeOnly), m_isSet(_isSet), m_affectsLength(0), m_affects(), m_affectsAll(false), m_checkChange(false), m_pollIntensity(_pollIntensity) + { + SetLabel(_label); + } //----------------------------------------------------------------------------- // // Constructor (from XML) //----------------------------------------------------------------------------- -Value::Value -( -): - m_min( 0 ), - m_max( 0 ), - m_refreshTime(0), - m_verifyChanges( false ), - m_readOnly( false ), - m_writeOnly( false ), - m_isSet( false ), - m_affectsLength( 0 ), - m_affects(), - m_affectsAll( false ), - m_checkChange( false ), - m_pollIntensity( 0 ) -{ -} + Value::Value() : + m_min(0), m_max(0), m_refreshTime(0), m_verifyChanges(false), m_readOnly(false), m_writeOnly(false), m_isSet(false), m_affectsLength(0), m_affects(), m_affectsAll(false), m_checkChange(false), m_pollIntensity(0) + { + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -Value::~Value -( -) -{ - if( m_affectsLength > 0 ) - { - delete [] m_affects; - } -} + Value::~Value() + { + if (m_affectsLength > 0) + { + delete[] m_affects; + } + } //----------------------------------------------------------------------------- // // Apply settings from XML //----------------------------------------------------------------------------- -void Value::ReadXML -( - uint32 const _homeId, - uint8 const _nodeId, - uint8 const _commandClassId, - TiXmlElement const* _valueElement -) -{ - int intVal; + void Value::ReadXML(uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement) + { + int intVal; - ValueID::ValueGenre genre = Value::GetGenreEnumFromName( _valueElement->Attribute( "genre" ) ); - ValueID::ValueType type = Value::GetTypeEnumFromName( _valueElement->Attribute( "type" ) ); + ValueID::ValueGenre genre = Value::GetGenreEnumFromName(_valueElement->Attribute("genre")); + ValueID::ValueType type = Value::GetTypeEnumFromName(_valueElement->Attribute("type")); - uint8 instance = 1; - if( TIXML_SUCCESS == _valueElement->QueryIntAttribute( "instance", &intVal ) ) - { - instance = (uint8)intVal; - } + uint8 instance = 1; + if (TIXML_SUCCESS == _valueElement->QueryIntAttribute("instance", &intVal)) + { + instance = (uint8) intVal; + } - uint16 index = 0; - if( TIXML_SUCCESS == _valueElement->QueryIntAttribute( "index", &intVal ) ) - { - /* index is only 10 bytes in the ValueID class */ - index = (uint16)(intVal & 0x3FF); - } + uint16 index = 0; + if (TIXML_SUCCESS == _valueElement->QueryIntAttribute("index", &intVal)) + { + /* index is only 10 bytes in the ValueID class */ + index = (uint16) (intVal & 0x3FF); + } - m_id = ValueID( _homeId, _nodeId, genre, _commandClassId, instance, index, type ); + m_id = ValueID(_homeId, _nodeId, genre, _commandClassId, instance, index, type); - char const* label = _valueElement->Attribute( "label" ); - if( label ) - { - SetLabel(label); - } + char const* label = _valueElement->Attribute("label"); + if (label) + { + SetLabel(label); + } - char const* units = _valueElement->Attribute( "units" ); - if( units ) - { - m_units = units; - } + char const* units = _valueElement->Attribute("units"); + if (units) + { + m_units = units; + } - char const* readOnly = _valueElement->Attribute( "read_only" ); - if( readOnly ) - { - m_readOnly = !strcmp( readOnly, "true" ); - } + char const* readOnly = _valueElement->Attribute("read_only"); + if (readOnly) + { + m_readOnly = !strcmp(readOnly, "true"); + } - char const* writeOnly = _valueElement->Attribute( "write_only" ); - if( writeOnly ) - { - m_writeOnly = !strcmp( writeOnly, "true" ); - } + char const* writeOnly = _valueElement->Attribute("write_only"); + if (writeOnly) + { + m_writeOnly = !strcmp(writeOnly, "true"); + } - if( TIXML_SUCCESS == _valueElement->QueryIntAttribute( "poll_intensity", &intVal ) ) - { - m_pollIntensity = (uint8)intVal; - } + if (TIXML_SUCCESS == _valueElement->QueryIntAttribute("poll_intensity", &intVal)) + { + m_pollIntensity = (uint8) intVal; + } - char const* affects = _valueElement->Attribute( "affects" ); - if( affects ) - { - if ( m_affectsLength != 0 ) - { - delete [] m_affects; - } - m_affectsLength = 0; - if( !strcmp( affects, "all" ) ) - { - m_affectsAll = true; - } - else - { - size_t len = strlen( affects ); - if( len > 0 ) - { - for( size_t i = 0; i < len; i++ ) + char const* affects = _valueElement->Attribute("affects"); + if (affects) { - if( affects[i] == ',' ) + if (m_affectsLength != 0) { - m_affectsLength++; + delete[] m_affects; } - else if(affects[i] < '0' || affects[i] > '9') + m_affectsLength = 0; + if (!strcmp(affects, "all")) { - Log::Write( LogLevel_Info, "Improperly formatted affects data: \"%s\"", affects); - break; + m_affectsAll = true; } - } - m_affectsLength++; - m_affects = new uint8[m_affectsLength]; - unsigned int j = 0; - for( int i = 0; i < m_affectsLength; i++ ) - { - m_affects[i] = atoi( &affects[j] ); - while( j < len && affects[j] != ',' ) + else { - j++; + size_t len = strlen(affects); + if (len > 0) + { + for (size_t i = 0; i < len; i++) + { + if (affects[i] == ',') + { + m_affectsLength++; + } + else if (affects[i] < '0' || affects[i] > '9') + { + Log::Write(LogLevel_Info, "Improperly formatted affects data: \"%s\"", affects); + break; + } + } + m_affectsLength++; + m_affects = new uint8[m_affectsLength]; + unsigned int j = 0; + for (int i = 0; i < m_affectsLength; i++) + { + m_affects[i] = atoi(&affects[j]); + while (j < len && affects[j] != ',') + { + j++; + } + j++; + } + } } - j++; } - } - } - } - char const* verifyChanges = _valueElement->Attribute( "verify_changes" ); - if( verifyChanges ) - { - m_verifyChanges = !strcmp( verifyChanges, "true" ); - } + char const* verifyChanges = _valueElement->Attribute("verify_changes"); + if (verifyChanges) + { + m_verifyChanges = !strcmp(verifyChanges, "true"); + } - if( TIXML_SUCCESS == _valueElement->QueryIntAttribute( "min", &intVal ) ) - { - m_min = intVal; - } + if (TIXML_SUCCESS == _valueElement->QueryIntAttribute("min", &intVal)) + { + m_min = intVal; + } - if( TIXML_SUCCESS == _valueElement->QueryIntAttribute( "max", &intVal ) ) - { - m_max = intVal; - } + if (TIXML_SUCCESS == _valueElement->QueryIntAttribute("max", &intVal)) + { + m_max = intVal; + } - TiXmlElement const* helpElement = _valueElement->FirstChildElement(); - while( helpElement ) - { - char const* str = helpElement->Value(); - if( str && !strcmp( str, "Help" ) ) - { - Localization::Get()->ReadXMLVIDHelp(_commandClassId, index, -1, helpElement); - } - if (str && !strcmp( str, "Label" ) ) - { - Localization::Get()->ReadXMLVIDLabel(_commandClassId, index, -1, helpElement); - } - helpElement = helpElement->NextSiblingElement(); - } -} + TiXmlElement const* helpElement = _valueElement->FirstChildElement(); + while (helpElement) + { + char const* str = helpElement->Value(); + if (str && !strcmp(str, "Help")) + { + Localization::Get()->ReadXMLVIDHelp(m_id.GetNodeId(), _commandClassId, index, -1, helpElement); + } + if (str && !strcmp(str, "Label")) + { + Localization::Get()->ReadXMLVIDLabel(m_id.GetNodeId(), _commandClassId, index, -1, helpElement); + } + helpElement = helpElement->NextSiblingElement(); + } + } //----------------------------------------------------------------------------- // // Write ourselves to an XML document //----------------------------------------------------------------------------- -void Value::WriteXML -( - TiXmlElement* _valueElement -) -{ - char str[16]; + void Value::WriteXML(TiXmlElement* _valueElement) + { + char str[16]; - _valueElement->SetAttribute( "type", GetTypeNameFromEnum(m_id.GetType()) ); - _valueElement->SetAttribute( "genre", GetGenreNameFromEnum(m_id.GetGenre()) ); + _valueElement->SetAttribute("type", GetTypeNameFromEnum(m_id.GetType())); + _valueElement->SetAttribute("genre", GetGenreNameFromEnum(m_id.GetGenre())); - snprintf( str, sizeof(str), "%d", m_id.GetInstance() ); - _valueElement->SetAttribute( "instance", str ); + snprintf(str, sizeof(str), "%d", m_id.GetInstance()); + _valueElement->SetAttribute("instance", str); - snprintf( str, sizeof(str), "%d", (m_id.GetIndex() & 0x3FF) ); - _valueElement->SetAttribute( "index", str ); + snprintf(str, sizeof(str), "%d", (m_id.GetIndex() & 0x3FF)); + _valueElement->SetAttribute("index", str); - _valueElement->SetAttribute( "label", GetLabel().c_str() ); - _valueElement->SetAttribute( "units", m_units.c_str() ); - _valueElement->SetAttribute( "read_only", m_readOnly ? "true" : "false" ); - _valueElement->SetAttribute( "write_only", m_writeOnly ? "true" : "false" ); - _valueElement->SetAttribute( "verify_changes", m_verifyChanges ? "true" : "false" ); + _valueElement->SetAttribute("label", GetLabel().c_str()); + _valueElement->SetAttribute("units", m_units.c_str()); + _valueElement->SetAttribute("read_only", m_readOnly ? "true" : "false"); + _valueElement->SetAttribute("write_only", m_writeOnly ? "true" : "false"); + _valueElement->SetAttribute("verify_changes", m_verifyChanges ? "true" : "false"); - snprintf( str, sizeof(str), "%d", m_pollIntensity ); - _valueElement->SetAttribute( "poll_intensity", str ); + snprintf(str, sizeof(str), "%d", m_pollIntensity); + _valueElement->SetAttribute("poll_intensity", str); - snprintf( str, sizeof(str), "%d", m_min ); - _valueElement->SetAttribute( "min", str ); + snprintf(str, sizeof(str), "%d", m_min); + _valueElement->SetAttribute("min", str); - snprintf( str, sizeof(str), "%d", m_max ); - _valueElement->SetAttribute( "max", str ); + snprintf(str, sizeof(str), "%d", m_max); + _valueElement->SetAttribute("max", str); - if( m_affectsAll ) - { - _valueElement->SetAttribute( "affects", "all" ); - } - else if( m_affectsLength > 0 ) - { - string s; - for( int i = 0; i < m_affectsLength; i++ ) - { - snprintf( str, sizeof(str), "%d", m_affects[i] ); - s = s + str; - if( i + 1 < m_affectsLength ) - { - s = s + ","; - } + if (m_affectsAll) + { + _valueElement->SetAttribute("affects", "all"); + } + else if (m_affectsLength > 0) + { + string s; + for (int i = 0; i < m_affectsLength; i++) + { + snprintf(str, sizeof(str), "%d", m_affects[i]); + s = s + str; + if (i + 1 < m_affectsLength) + { + s = s + ","; + } - } - _valueElement->SetAttribute( "affects", s.c_str() ); - } - Localization::Get()->WriteXMLVIDHelp(m_id.GetCommandClassId(), m_id.GetIndex(),-1, _valueElement); -} + } + _valueElement->SetAttribute("affects", s.c_str()); + } + Localization::Get()->WriteXMLVIDHelp(m_id.GetNodeId(), m_id.GetCommandClassId(), m_id.GetIndex(), -1, _valueElement); + } //----------------------------------------------------------------------------- // // Set a new value in the device //----------------------------------------------------------------------------- -bool Value::Set -( -) -{ - // nothing to do if this is a read-only value (return false to indicate an error) - if( IsReadOnly() ) - { - return false; - } - - // retrieve the driver, node and commandclass object for this value - bool res = false; - Node* node = NULL; - if( Driver* driver = Manager::Get()->GetDriver( m_id.GetHomeId() ) ) - { - node = driver->GetNodeUnsafe( m_id.GetNodeId() ); - if( node != NULL ) - { - if( CommandClass* cc = node->GetCommandClass( m_id.GetCommandClassId() ) ) + bool Value::Set() { - Log::Write(LogLevel_Info, m_id.GetNodeId(), "Value::Set - %s - %s - %d - %d - %s", cc->GetCommandClassName().c_str(), this->GetLabel().c_str(), m_id.GetIndex(), m_id.GetInstance(), this->GetAsString().c_str()); - // flag value as set and queue a "Set Value" message for transmission to the device - res = cc->SetValue( *this ); + // nothing to do if this is a read-only value (return false to indicate an error) + if (IsReadOnly()) + { + return false; + } - if( res ) + // retrieve the driver, node and commandclass object for this value + bool res = false; + Node* node = NULL; + if (Driver* driver = Manager::Get()->GetDriver(m_id.GetHomeId())) { - if( !IsWriteOnly() ) + node = driver->GetNodeUnsafe(m_id.GetNodeId()); + if (node != NULL) { - // queue a "RequestValue" message to update the value - cc->RequestValue( 0, m_id.GetIndex(), m_id.GetInstance(), Driver::MsgQueue_Send ); - } - else - { - // There is a "bug" here in that write only values - // never send a notification about the value changing. - // For sleeping devices it may not change until the - // device wakes up at some point in the future. - // So when is the right time to change it? - if( m_affectsAll ) - { - node->RequestAllConfigParams( 0 ); - } - else if( m_affectsLength > 0 ) + if (Internal::CC::CommandClass* cc = node->GetCommandClass(m_id.GetCommandClassId())) { - for( int i = 0; i < m_affectsLength; i++ ) + Log::Write(LogLevel_Info, m_id.GetNodeId(), "Value::Set - %s - %s - %d - %d - %s", cc->GetCommandClassName().c_str(), this->GetLabel().c_str(), m_id.GetIndex(), m_id.GetInstance(), this->GetAsString().c_str()); + // flag value as set and queue a "Set Value" message for transmission to the device + res = cc->SetValue(*this); + + if (res) { - node->RequestConfigParam( m_affects[i] ); + if (!IsWriteOnly()) + { + // queue a "RequestValue" message to update the value + cc->RequestValue(0, m_id.GetIndex(), m_id.GetInstance(), Driver::MsgQueue_Send); + } + else + { + // There is a "bug" here in that write only values + // never send a notification about the value changing. + // For sleeping devices it may not change until the + // device wakes up at some point in the future. + // So when is the right time to change it? + if (m_affectsAll) + { + node->RequestAllConfigParams(0); + } + else if (m_affectsLength > 0) + { + for (int i = 0; i < m_affectsLength; i++) + { + node->RequestConfigParam(m_affects[i]); + } + } + } } } } } - } - } - } - return res; -} + return res; + } //----------------------------------------------------------------------------- // // A value in a device has been refreshed //----------------------------------------------------------------------------- -void Value::OnValueRefreshed -( -) -{ - if( IsWriteOnly() ) - { - return; - } - - if( Driver* driver = Manager::Get()->GetDriver( m_id.GetHomeId() ) ) - { - m_isSet = true; + void Value::OnValueRefreshed() + { + if (IsWriteOnly()) + { + return; + } - bool bSuppress; - Options::Get()->GetOptionAsBool( "SuppressValueRefresh", &bSuppress ); - if( !bSuppress ) - { - // Notify the watchers - Notification* notification = new Notification( Notification::Type_ValueRefreshed ); - notification->SetValueId( m_id ); - driver->QueueNotification( notification ); - } - } -} + if (Driver* driver = Manager::Get()->GetDriver(m_id.GetHomeId())) + { + m_isSet = true; + bool bSuppress; + Options::Get()->GetOptionAsBool("SuppressValueRefresh", &bSuppress); + if (!bSuppress) + { + // Notify the watchers + Notification* notification = new Notification(Notification::Type_ValueRefreshed); + notification->SetValueId(m_id); + driver->QueueNotification(notification); + } + } + } //----------------------------------------------------------------------------- // // A value in a device has changed //----------------------------------------------------------------------------- -void Value::OnValueChanged -( -) -{ - if( IsWriteOnly() ) - { - return; - } - - if( Driver* driver = Manager::Get()->GetDriver( m_id.GetHomeId() ) ) - { - m_isSet = true; - - // Notify the watchers - Notification* notification = new Notification( Notification::Type_ValueChanged ); - notification->SetValueId( m_id ); - driver->QueueNotification( notification ); - } - /* Call Back to the Command Class that this Value has changed, so we can search the - * TriggerRefreshValue vector to see if we should request any other values to be - * refreshed. - */ - Node* node = NULL; - if( Driver* driver = Manager::Get()->GetDriver( m_id.GetHomeId() ) ) - { - node = driver->GetNodeUnsafe( m_id.GetNodeId() ); - if( node != NULL ) - { - if( CommandClass* cc = node->GetCommandClass( m_id.GetCommandClassId() ) ) + void Value::OnValueChanged() { - cc->CheckForRefreshValues(this); - } - } - } + if (IsWriteOnly()) + { + return; + } + + if (Driver* driver = Manager::Get()->GetDriver(m_id.GetHomeId())) + { + m_isSet = true; + + // Notify the watchers + Notification* notification = new Notification(Notification::Type_ValueChanged); + notification->SetValueId(m_id); + driver->QueueNotification(notification); + } + /* Call Back to the Command Class that this Value has changed, so we can search the + * TriggerRefreshValue vector to see if we should request any other values to be + * refreshed. + */ + Node* node = NULL; + if (Driver* driver = Manager::Get()->GetDriver(m_id.GetHomeId())) + { + node = driver->GetNodeUnsafe(m_id.GetNodeId()); + if (node != NULL) + { + if (Internal::CC::CommandClass* cc = node->GetCommandClass(m_id.GetCommandClassId())) + { + cc->CheckForRefreshValues(this); + } + } + } -} + } //----------------------------------------------------------------------------- // // Static helper to get a genre enum from a string //----------------------------------------------------------------------------- -ValueID::ValueGenre Value::GetGenreEnumFromName -( - char const* _name -) -{ - ValueID::ValueGenre genre = ValueID::ValueGenre_System; - if( _name ) - { - for( int i=0; i<(int)ValueID::ValueGenre_Count; ++i ) - { - if( !strcmp( _name, c_genreName[i] ) ) + OpenZWave::ValueID::ValueGenre Value::GetGenreEnumFromName(char const* _name) { - genre = (ValueID::ValueGenre)i; - break; - } - } - } + ValueID::ValueGenre genre = ValueID::ValueGenre_System; + if (_name) + { + for (int i = 0; i < (int) ValueID::ValueGenre_Count; ++i) + { + if (!strcmp(_name, c_genreName[i])) + { + genre = (ValueID::ValueGenre) i; + break; + } + } + } - return genre; -} + return genre; + } //----------------------------------------------------------------------------- // // Static helper to get a genre enum as a string //----------------------------------------------------------------------------- -char const* Value::GetGenreNameFromEnum -( - ValueID::ValueGenre _genre -) -{ - return c_genreName[_genre]; -} + char const* Value::GetGenreNameFromEnum(ValueID::ValueGenre _genre) + { + return c_genreName[_genre]; + } //----------------------------------------------------------------------------- // // Static helper to get a type enum from a string //----------------------------------------------------------------------------- -ValueID::ValueType Value::GetTypeEnumFromName -( - char const* _name -) -{ - ValueID::ValueType type = ValueID::ValueType_Bool; - if( _name ) - { - for( int i=0; i<=(int)ValueID::ValueType_Max; ++i ) - { - if( !strcmp( _name, c_typeName[i] ) ) + OpenZWave::ValueID::ValueType Value::GetTypeEnumFromName(char const* _name) { - type = (ValueID::ValueType)i; - break; - } - } - } + ValueID::ValueType type = ValueID::ValueType_Bool; + if (_name) + { + for (int i = 0; i <= (int) ValueID::ValueType_Max; ++i) + { + if (!strcmp(_name, c_typeName[i])) + { + type = (ValueID::ValueType) i; + break; + } + } + } - return type; -} + return type; + } //----------------------------------------------------------------------------- // // Static helper to get a type enum as a string //----------------------------------------------------------------------------- -char const* Value::GetTypeNameFromEnum -( - ValueID::ValueType _type -) -{ - if (_type > (int)ValueID::ValueType_Max) { - Log::Write(LogLevel_Warning, "Value::GetTypeNameFromEnum is out of range: %d", (int)_type); - return c_typeName[ValueID::ValueType_Max+1]; - } + char const* Value::GetTypeNameFromEnum(ValueID::ValueType _type) + { + if (_type > (int) ValueID::ValueType_Max) + { + Log::Write(LogLevel_Warning, "Value::GetTypeNameFromEnum is out of range: %d", (int) _type); + return c_typeName[ValueID::ValueType_Max + 1]; + } - return c_typeName[_type]; -} + return c_typeName[_type]; + } //----------------------------------------------------------------------------- // // Check a refreshed value //----------------------------------------------------------------------------- -int Value::VerifyRefreshedValue -( - void* _originalValue, - void* _checkValue, - void* _newValue, - ValueID::ValueType _type, - int _originalValueLength, // = 0, - int _checkValueLength, // = 0, - int _newValueLength // = 0 -) -{ - // TODO: this is pretty rough code, but it's reused by each value type. It would be - // better if the actions were taken (m_value = _value, etc.) in this code rather than - // in the calling routine as a result of the return value. In particular, it's messy - // to be setting these values after the refesh or notification is sent. With some - // focus on the actual variable storage, we should be able to accomplish this with - // memory functions. It's really the strings that make things complicated(?). - // if this is the first read of a value, assume it is valid (and notify as a change) - if( !IsSet() ) - { - Log::Write( LogLevel_Detail, m_id.GetNodeId(), "Initial read of value" ); - Value::OnValueChanged(); - return 2; // confirmed change of value - } - else - { - switch( _type ) - { - case ValueID::ValueType_Button: // Button is stored as a bool - case ValueID::ValueType_Bool: // bool + int Value::VerifyRefreshedValue(void* _originalValue, void* _checkValue, void* _newValue, ValueID::ValueType _type, int _originalValueLength, // = 0, + int _checkValueLength, // = 0, + int _newValueLength // = 0 + ) { - Log::Write( LogLevel_Detail, m_id.GetNodeId(), "Refreshed Value: old value=%s, new value=%s, type=%s", *((bool*)_originalValue)?"true":"false", *((uint8*)_newValue)?"true":"false", GetTypeNameFromEnum(_type) ); - break; - } - case ValueID::ValueType_Byte: // byte - { - Log::Write( LogLevel_Detail, m_id.GetNodeId(), "Refreshed Value: old value=%d, new value=%d, type=%s", *((uint8*)_originalValue), *((uint8*)_newValue), GetTypeNameFromEnum(_type) ); - break; - } - case ValueID::ValueType_Decimal: // decimal is stored as a string, so treat it as a string here - case ValueID::ValueType_String: // string - { - Log::Write( LogLevel_Detail, m_id.GetNodeId(), "Refreshed Value: old value=%s, new value=%s, type=%s", ((string*)_originalValue)->c_str(), ((string*)_newValue)->c_str(), GetTypeNameFromEnum(_type) ); - break; + // TODO: this is pretty rough code, but it's reused by each value type. It would be + // better if the actions were taken (m_value = _value, etc.) in this code rather than + // in the calling routine as a result of the return value. In particular, it's messy + // to be setting these values after the refesh or notification is sent. With some + // focus on the actual variable storage, we should be able to accomplish this with + // memory functions. It's really the strings that make things complicated(?). + // if this is the first read of a value, assume it is valid (and notify as a change) + if (!IsSet()) + { + Log::Write(LogLevel_Detail, m_id.GetNodeId(), "Initial read of value"); + Value::OnValueChanged(); + return 2; // confirmed change of value + } + else + { + switch (_type) + { + case ValueID::ValueType_Button: // Button is stored as a bool + case ValueID::ValueType_Bool: // bool + { + Log::Write(LogLevel_Detail, m_id.GetNodeId(), "Refreshed Value: old value=%s, new value=%s, type=%s", *((bool*) _originalValue) ? "true" : "false", *((uint8*) _newValue) ? "true" : "false", GetTypeNameFromEnum(_type)); + break; + } + case ValueID::ValueType_Byte: // byte + { + Log::Write(LogLevel_Detail, m_id.GetNodeId(), "Refreshed Value: old value=%d, new value=%d, type=%s", *((uint8*) _originalValue), *((uint8*) _newValue), GetTypeNameFromEnum(_type)); + break; + } + case ValueID::ValueType_Decimal: // decimal is stored as a string, so treat it as a string here + case ValueID::ValueType_String: // string + { + Log::Write(LogLevel_Detail, m_id.GetNodeId(), "Refreshed Value: old value=%s, new value=%s, type=%s", ((string*) _originalValue)->c_str(), ((string*) _newValue)->c_str(), GetTypeNameFromEnum(_type)); + break; + } + case ValueID::ValueType_Short: // short + { + Log::Write(LogLevel_Detail, m_id.GetNodeId(), "Refreshed Value: old value=%d, new value=%d, type=%s", *((short*) _originalValue), *((short*) _newValue), GetTypeNameFromEnum(_type)); + break; + } + case ValueID::ValueType_List: // List Type is treated as a int32 + case ValueID::ValueType_Int: // int32 + case ValueID::ValueType_BitSet: // BitSet + { + Log::Write(LogLevel_Detail, m_id.GetNodeId(), "Refreshed Value: old value=%d, new value=%d, type=%s", *((int32*) _originalValue), *((int32*) _newValue), GetTypeNameFromEnum(_type)); + break; + } + case ValueID::ValueType_Raw: // raw + { + Log::Write(LogLevel_Detail, m_id.GetNodeId(), "Refreshed Value: old value=%x, new value=%x, type=%s", _originalValue, _newValue, GetTypeNameFromEnum(_type)); + break; + } + case ValueID::ValueType_Schedule: // Schedule Type + { + Log::Write(LogLevel_Detail, m_id.GetNodeId(), "Refreshed Value: old value=%s, new value=%s, type=%s", _originalValue, _newValue, GetTypeNameFromEnum(_type)); + /* we cant support verifyChanges yet... so always unset this */ + m_verifyChanges = false; + break; + } + } + } + m_refreshTime = time( NULL); // update value refresh time + + // check whether changes in this value should be verified (since some devices will report values that always + // change, where confirming changes is difficult or impossible) + Log::Write(LogLevel_Detail, m_id.GetNodeId(), "Changes to this value are %sverified", m_verifyChanges ? "" : "not "); + + if (!m_verifyChanges) + { + // since we're not checking changes in this value, notify ValueChanged (to be on the safe side) + Value::OnValueChanged(); + return 2; // confirmed change of value + } + + // see if the value has changed (result is used whether checking change or not) + bool bOriginalEqual = false; + switch (_type) + { + case ValueID::ValueType_Decimal: // Decimal is stored as a string + case ValueID::ValueType_String: // string + bOriginalEqual = (strcmp(((string*) _originalValue)->c_str(), ((string*) _newValue)->c_str()) == 0); + break; + case ValueID::ValueType_Short: // short + bOriginalEqual = (*((short*) _originalValue) == *((short*) _newValue)); + break; + case ValueID::ValueType_List: // List Type is treated as a int32 + case ValueID::ValueType_Int: // int + bOriginalEqual = (*((int32*) _originalValue) == *((int32*) _newValue)); + break; + case ValueID::ValueType_Byte: // uint8 + bOriginalEqual = (*((uint8*) _originalValue) == *((uint8*) _newValue)); + break; + case ValueID::ValueType_Button: // Button is stored as a bool + case ValueID::ValueType_Bool: // bool + bOriginalEqual = (*((bool*) _originalValue) == *((bool*) _newValue)); + break; + case ValueID::ValueType_Raw: // raw + bOriginalEqual = (_originalValueLength == _newValueLength); // first check length of arrays + if (bOriginalEqual) + bOriginalEqual = (memcmp(_originalValue, _newValue, _newValueLength) == 0); // if length is the same, then check content + break; + case ValueID::ValueType_Schedule: // Schedule + /* Should not get here */ + break; + case ValueID::ValueType_BitSet: // BitSet + bOriginalEqual = (((Bitfield *) _originalValue)->GetValue() == ((Bitfield *) _newValue)->GetValue()); + break; + } + + // if this is the first refresh of the value, test to see if the value has changed + if (!IsCheckingChange()) + { + if (bOriginalEqual) + { + // values are the same, so signal a refresh and return + Value::OnValueRefreshed(); + return 0; // value hasn't changed + } + + // values are different, so flag this as a verification refresh and queue it + Log::Write(LogLevel_Info, m_id.GetNodeId(), "Changed value (possible)--rechecking"); + SetCheckingChange(true); + Manager::Get()->RefreshValue(GetID()); + return 1; // value has changed (to be confirmed) + } + else // IsCheckingChange is true if this is the second read of a potentially changed value + { + // if the second read is the same as the first read, the value really changed + bool bCheckEqual = false; + switch (_type) + { + case ValueID::ValueType_Decimal: // Decimal is stored as a string + case ValueID::ValueType_String: // string + bCheckEqual = (strcmp(((string*) _checkValue)->c_str(), ((string*) _newValue)->c_str()) == 0); + break; + case ValueID::ValueType_Short: // short + bCheckEqual = (*((short*) _checkValue) == *((short*) _newValue)); + break; + case ValueID::ValueType_List: // List Type is treated as a int32 + case ValueID::ValueType_Int: // int32 + bCheckEqual = (*((int32*) _checkValue) == *((int32*) _newValue)); + break; + case ValueID::ValueType_Byte: // uint8 + bCheckEqual = (*((uint8*) _checkValue) == *((uint8*) _newValue)); + break; + case ValueID::ValueType_Button: // Button is stored as a bool + case ValueID::ValueType_Bool: // bool + bCheckEqual = (*((bool*) _checkValue) == *((bool*) _newValue)); + break; + case ValueID::ValueType_Raw: + bCheckEqual = (_checkValueLength == _newValueLength); // first check length of arrays + if (bCheckEqual) + bCheckEqual = (memcmp(_checkValue, _newValue, _newValueLength) == 0); // if length is the same, then check content + break; + case ValueID::ValueType_Schedule: + /* Should not get here */ + break; + case ValueID::ValueType_BitSet: // BitSet + bCheckEqual = (((Bitfield *) _checkValue)->GetValue() == ((Bitfield *) _newValue)->GetValue()); + ; + break; + } + if (bCheckEqual) + { + Log::Write(LogLevel_Info, m_id.GetNodeId(), "Changed value--confirmed"); + SetCheckingChange(false); + + // update the saved value and send notification + Value::OnValueChanged(); + return 2; + } + + // if the second read is the same as the original value, the first read is assumed to have been in error + // log this situation, but don't change the value or send a ValueChanged Notification + if (bOriginalEqual) + { + Log::Write(LogLevel_Info, m_id.GetNodeId(), "Spurious value change was noted."); + SetCheckingChange(false); + Value::OnValueRefreshed(); + return 0; + } + + // the second read is different than both the original value and the checked value...retry + // keep trying until we get the same value twice + Log::Write(LogLevel_Info, m_id.GetNodeId(), "Changed value (changed again)--rechecking"); + SetCheckingChange(true); + + // save a temporary copy of value and re-read value from device + Manager::Get()->RefreshValue(GetID()); + return 1; + } } - case ValueID::ValueType_Short: // short + + std::string const Value::GetHelp() const { - Log::Write( LogLevel_Detail, m_id.GetNodeId(), "Refreshed Value: old value=%d, new value=%d, type=%s", *((short*)_originalValue), *((short*)_newValue), GetTypeNameFromEnum(_type)); - break; + return Localization::Get()->GetValueHelp(m_id.GetNodeId(), m_id.GetCommandClassId(), m_id.GetIndex(), -1); } - case ValueID::ValueType_List: // List Type is treated as a int32 - case ValueID::ValueType_Int: // int32 - case ValueID::ValueType_BitSet: // BitSet + void Value::SetHelp(string const& _help, string const lang) { - Log::Write( LogLevel_Detail, m_id.GetNodeId(), "Refreshed Value: old value=%d, new value=%d, type=%s", *((int32*)_originalValue), *((int32*)_newValue), GetTypeNameFromEnum(_type) ); - break; + Localization::Get()->SetValueHelp(m_id.GetNodeId(), m_id.GetCommandClassId(), m_id.GetIndex(), -1, _help, lang); } - case ValueID::ValueType_Raw: // raw + + std::string const Value::GetLabel() const { - Log::Write( LogLevel_Detail, m_id.GetNodeId(), "Refreshed Value: old value=%x, new value=%x, type=%s", _originalValue, _newValue, GetTypeNameFromEnum(_type) ); - break; + return Localization::Get()->GetValueLabel(m_id.GetNodeId(), m_id.GetCommandClassId(), m_id.GetIndex(), -1); } - case ValueID::ValueType_Schedule: // Schedule Type + void Value::SetLabel(string const& _label, string const lang) { - Log::Write( LogLevel_Detail, m_id.GetNodeId(), "Refreshed Value: old value=%s, new value=%s, type=%s", _originalValue, _newValue, GetTypeNameFromEnum(_type) ); - /* we cant support verifyChanges yet... so always unset this */ - m_verifyChanges = false; - break; + Localization::Get()->SetValueLabel(m_id.GetNodeId(), m_id.GetCommandClassId(), m_id.GetIndex(), -1, _label, lang); } - } - } - m_refreshTime = time( NULL ); // update value refresh time - - // check whether changes in this value should be verified (since some devices will report values that always - // change, where confirming changes is difficult or impossible) - Log::Write( LogLevel_Detail, m_id.GetNodeId(), "Changes to this value are %sverified", m_verifyChanges ? "" : "not " ); - - if( !m_verifyChanges ) - { - // since we're not checking changes in this value, notify ValueChanged (to be on the safe side) - Value::OnValueChanged(); - return 2; // confirmed change of value - } - - // see if the value has changed (result is used whether checking change or not) - bool bOriginalEqual = false; - switch( _type ) - { - case ValueID::ValueType_Decimal: // Decimal is stored as a string - case ValueID::ValueType_String: // string - bOriginalEqual = ( strcmp( ((string*)_originalValue)->c_str(), ((string*)_newValue)->c_str() ) == 0 ); - break; - case ValueID::ValueType_Short: // short - bOriginalEqual = ( *((short*)_originalValue) == *((short*)_newValue) ); - break; - case ValueID::ValueType_List: // List Type is treated as a int32 - case ValueID::ValueType_Int: // int - bOriginalEqual = ( *((int32*)_originalValue) == *((int32*)_newValue) ); - break; - case ValueID::ValueType_Byte: // uint8 - bOriginalEqual = ( *((uint8*)_originalValue) == *((uint8*)_newValue) ); - break; - case ValueID::ValueType_Button: // Button is stored as a bool - case ValueID::ValueType_Bool: // bool - bOriginalEqual = ( *((bool*)_originalValue) == *((bool*)_newValue) ); - break; - case ValueID::ValueType_Raw: // raw - bOriginalEqual = ( _originalValueLength == _newValueLength ); // first check length of arrays - if(bOriginalEqual) bOriginalEqual = ( memcmp( _originalValue, _newValue, _newValueLength ) == 0 ); // if length is the same, then check content - break; - case ValueID::ValueType_Schedule: // Schedule - /* Should not get here */ - break; - case ValueID::ValueType_BitSet: // BitSet - bOriginalEqual = ( ((Bitfield *)_originalValue)->GetValue() == ((Bitfield *)_newValue)->GetValue() ); - break; - } - - // if this is the first refresh of the value, test to see if the value has changed - if( !IsCheckingChange() ) - { - if( bOriginalEqual ) - { - // values are the same, so signal a refresh and return - Value::OnValueRefreshed(); - return 0; // value hasn't changed - } - - // values are different, so flag this as a verification refresh and queue it - Log::Write( LogLevel_Info, m_id.GetNodeId(), "Changed value (possible)--rechecking" ); - SetCheckingChange( true ); - Manager::Get()->RefreshValue( GetID() ); - return 1; // value has changed (to be confirmed) - } - else // IsCheckingChange is true if this is the second read of a potentially changed value - { - // if the second read is the same as the first read, the value really changed - bool bCheckEqual = false; - switch( _type ) - { - case ValueID::ValueType_Decimal: // Decimal is stored as a string - case ValueID::ValueType_String: // string - bCheckEqual = ( strcmp( ((string*)_checkValue)->c_str(), ((string*)_newValue)->c_str() ) == 0 ); - break; - case ValueID::ValueType_Short: // short - bCheckEqual = ( *((short*)_checkValue) == *((short*)_newValue) ); - break; - case ValueID::ValueType_List: // List Type is treated as a int32 - case ValueID::ValueType_Int: // int32 - bCheckEqual = ( *((int32*)_checkValue) == *((int32*)_newValue) ); - break; - case ValueID::ValueType_Byte: // uint8 - bCheckEqual = ( *((uint8*)_checkValue) == *((uint8*)_newValue) ); - break; - case ValueID::ValueType_Button: // Button is stored as a bool - case ValueID::ValueType_Bool: // bool - bCheckEqual = ( *((bool*)_checkValue) == *((bool*)_newValue) ); - break; - case ValueID::ValueType_Raw: - bCheckEqual = ( _checkValueLength == _newValueLength ); // first check length of arrays - if (bCheckEqual) bCheckEqual = ( memcmp( _checkValue, _newValue, _newValueLength ) == 0 ); // if length is the same, then check content - break; - case ValueID::ValueType_Schedule: - /* Should not get here */ - break; - case ValueID::ValueType_BitSet: // BitSet - bCheckEqual = ( ((Bitfield *)_checkValue)->GetValue() == ((Bitfield *)_newValue)->GetValue() );; - break; - } - if( bCheckEqual ) - { - Log::Write( LogLevel_Info, m_id.GetNodeId(), "Changed value--confirmed" ); - SetCheckingChange( false ); - - // update the saved value and send notification - Value::OnValueChanged(); - return 2; - } - - // if the second read is the same as the original value, the first read is assumed to have been in error - // log this situation, but don't change the value or send a ValueChanged Notification - if( bOriginalEqual ) - { - Log::Write( LogLevel_Info, m_id.GetNodeId(), "Spurious value change was noted." ); - SetCheckingChange( false ); - Value::OnValueRefreshed(); - return 0; - } - - // the second read is different than both the original value and the checked value...retry - // keep trying until we get the same value twice - Log::Write( LogLevel_Info, m_id.GetNodeId(), "Changed value (changed again)--rechecking" ); - SetCheckingChange( true ); - - // save a temporary copy of value and re-read value from device - Manager::Get()->RefreshValue( GetID() ); - return 1; - } -} - - -string const Value::GetHelp -( -) const -{ - return Localization::Get()->GetValueHelp(m_id.GetCommandClassId(), m_id.GetIndex(), -1); -} -void Value::SetHelp -( - string const& _help, - string const lang -) -{ - Localization::Get()->SetValueHelp(m_id.GetCommandClassId(), m_id.GetIndex(), -1, _help, lang); -} - -string const Value::GetLabel -( -) const -{ - return Localization::Get()->GetValueLabel(m_id.GetCommandClassId(), m_id.GetIndex(), -1); -} -void Value::SetLabel -( - string const& _label, - string const lang -) -{ - Localization::Get()->SetValueLabel(m_id.GetCommandClassId(), m_id.GetIndex(), -1, _label, lang); -} - + } // namespace VC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/value_classes/Value.h b/cpp/src/value_classes/Value.h index b8d4687b41..4bd3d0a1ba 100644 --- a/cpp/src/value_classes/Value.h +++ b/cpp/src/value_classes/Value.h @@ -35,96 +35,160 @@ #include "Defs.h" #include "platform/Ref.h" #include "value_classes/ValueID.h" +#include "platform/Log.h" class TiXmlElement; namespace OpenZWave { - class Node; - - /** \brief Base class for values associated with a node. - * \ingroup ValueID - */ - class Value: public Ref + class Driver; + namespace Internal { - friend class Driver; - friend class ValueStore; - - public: - Value( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, ValueID::ValueType const _type, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, bool const _isset, uint8 const _pollIntensity ); - Value(); - - virtual void ReadXML( uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement ); - virtual void WriteXML( TiXmlElement* _valueElement ); - - ValueID const& GetID()const{ return m_id; } - bool IsReadOnly()const{ return m_readOnly; } - bool IsWriteOnly()const{ return m_writeOnly; } - bool IsSet()const{ return m_isSet; } - bool IsPolled()const{ return m_pollIntensity != 0; } - - string const GetLabel()const; - void SetLabel( string const& _label, string const lang=""); - - string const& GetUnits()const{ return m_units; } - void SetUnits( string const& _units ){ m_units = _units; } - - string const GetHelp()const; - void SetHelp( string const& _help, string const lang=""); - - uint8 const& GetPollIntensity()const{ return m_pollIntensity; } - void SetPollIntensity( uint8 const& _intensity ){ m_pollIntensity = _intensity; } - - int32 GetMin()const{ return m_min; } - int32 GetMax()const{ return m_max; } - - void SetChangeVerified( bool _verify ){ m_verifyChanges = _verify; } - bool GetChangeVerified() { return m_verifyChanges; } - - virtual string const GetAsString() const { return ""; } - virtual bool SetFromString( string const& ) { return false; } - - bool Set(); // For the user to change a value in a device - - // Helpers - static ValueID::ValueGenre GetGenreEnumFromName( char const* _name ); - static char const* GetGenreNameFromEnum( ValueID::ValueGenre _genre ); - static ValueID::ValueType GetTypeEnumFromName( char const* _name ); - static char const* GetTypeNameFromEnum( ValueID::ValueType _type ); - - protected: - virtual ~Value(); - -// void SetIsSet() { m_isSet = true; } // TODO: consider removing this...it's never called since m_isSet is set in ValueChanged and ValueRefreshed - bool IsCheckingChange()const{ return m_checkChange; } - void SetCheckingChange( bool _check ) { m_checkChange = _check; } - void OnValueRefreshed(); // A value in a device has been refreshed - void OnValueChanged(); // The refreshed value actually changed - int VerifyRefreshedValue( void* _originalValue, void* _checkValue, void* _newValue, ValueID::ValueType _type, int _originalValueLength = 0, int _checkValueLength = 0, int _newValueLength = 0 ); - - int32 m_min; - int32 m_max; - - time_t m_refreshTime; // time_t identifying when this value was last refreshed - bool m_verifyChanges; // if true, apparent changes are verified; otherwise, they're not - ValueID m_id; - - - private: - string m_units; - bool m_readOnly; - bool m_writeOnly; - bool m_isSet; - uint8 m_affectsLength; - uint8* m_affects; - bool m_affectsAll; - bool m_checkChange; - uint8 m_pollIntensity; - }; - + namespace VC + { + + /** \brief Base class for values associated with a node. + * \ingroup ValueID + */ + class Value: public Internal::Platform::Ref + { + friend class OpenZWave::Driver; + friend class ValueStore; + + public: + Value(uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, ValueID::ValueType const _type, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, bool const _isset, uint8 const _pollIntensity); + Value(); + + virtual void ReadXML(uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement); + virtual void WriteXML(TiXmlElement* _valueElement); + + ValueID const& GetID() const + { + return m_id; + } + bool IsReadOnly() const + { + return m_readOnly; + } + bool IsWriteOnly() const + { + return m_writeOnly; + } + bool IsSet() const + { + return m_isSet; + } + bool IsPolled() const + { + return m_pollIntensity != 0; + } + + string const GetLabel() const; + void SetLabel(string const& _label, string const lang = ""); + + string const& GetUnits() const + { + return m_units; + } + void SetUnits(string const& _units) + { + m_units = _units; + } + + string const GetHelp() const; + void SetHelp(string const& _help, string const lang = ""); + + uint8 const& GetPollIntensity() const + { + return m_pollIntensity; + } + void SetPollIntensity(uint8 const& _intensity) + { + m_pollIntensity = _intensity; + } + + int32 GetMin() const + { + return m_min; + } + int32 GetMax() const + { + return m_max; + } + + void SetChangeVerified(bool _verify) + { + m_verifyChanges = _verify; + } + bool GetChangeVerified() + { + return m_verifyChanges; + } + + virtual string const GetAsString() const + { + return ""; + } + virtual bool SetFromString(string const&) + { + return false; + } + + bool Set(); // For the user to change a value in a device + + // Helpers + static OpenZWave::ValueID::ValueGenre GetGenreEnumFromName(char const* _name); + static char const* GetGenreNameFromEnum(ValueID::ValueGenre _genre); + static OpenZWave::ValueID::ValueType GetTypeEnumFromName(char const* _name); + static char const* GetTypeNameFromEnum(ValueID::ValueType _type); +#if 0 + inline void AddRef() { + Ref::AddRef(); + Log::Write(LogLevel_Warning, "Add Ref %d - %d %s", m_refs, m_id.GetId(), __func__); + Internal::StackTraceGenerator::GetTrace(); + } + inline int32 Release() { + Log::Write(LogLevel_Warning, "Del Ref %d - %d %s", m_refs -1, m_id.GetId(), __func__); + Internal::StackTraceGenerator::GetTrace(); + return Ref::Release(); + } +#endif + protected: + virtual ~Value(); + + bool IsCheckingChange() const + { + return m_checkChange; + } + void SetCheckingChange(bool _check) + { + m_checkChange = _check; + } + void OnValueRefreshed(); // A value in a device has been refreshed + void OnValueChanged(); // The refreshed value actually changed + int VerifyRefreshedValue(void* _originalValue, void* _checkValue, void* _newValue, ValueID::ValueType _type, int _originalValueLength = 0, int _checkValueLength = 0, int _newValueLength = 0); + + int32 m_min; + int32 m_max; + + time_t m_refreshTime; // time_t identifying when this value was last refreshed + bool m_verifyChanges; // if true, apparent changes are verified; otherwise, they're not + ValueID m_id; + + private: + string m_units; + bool m_readOnly; + bool m_writeOnly; + bool m_isSet; + uint8 m_affectsLength; + uint8* m_affects; + bool m_affectsAll; + bool m_checkChange; + uint8 m_pollIntensity; + }; + } // namespace VC + } // namespace Internal } // namespace OpenZWave #endif - - diff --git a/cpp/src/value_classes/ValueBitSet.cpp b/cpp/src/value_classes/ValueBitSet.cpp index e866329de8..e94df2592c 100644 --- a/cpp/src/value_classes/ValueBitSet.cpp +++ b/cpp/src/value_classes/ValueBitSet.cpp @@ -34,393 +34,334 @@ #include "Localization.h" #include -using namespace OpenZWave; - +namespace OpenZWave +{ + namespace Internal + { + namespace VC + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -ValueBitSet::ValueBitSet -( - uint32 const _homeId, - uint8 const _nodeId, - ValueID::ValueGenre const _genre, - uint8 const _commandClassId, - uint8 const _instance, - uint16 const _index, - string const& _label, - string const& _units, - bool const _readOnly, - bool const _writeOnly, - uint32 const _value, - uint8 const _pollIntensity -): - Value( _homeId, _nodeId, _genre, _commandClassId, _instance, _index, ValueID::ValueType_Bool, _label, _units, _readOnly, _writeOnly, false, _pollIntensity ), - m_value( _value ), - m_valueCheck( false ), - m_newValue( false ), - m_BitMask(0xFFFFFFFF), - m_size(0) -{ -} + ValueBitSet::ValueBitSet(uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, uint32 const _value, uint8 const _pollIntensity) : + Value(_homeId, _nodeId, _genre, _commandClassId, _instance, _index, ValueID::ValueType_BitSet, _label, _units, _readOnly, _writeOnly, false, _pollIntensity), m_value(_value), m_valueCheck(false), m_newValue(false), m_BitMask(0xFFFFFFFF), m_size(0) + { + } -bool ValueBitSet::SetFromString -( - string const& _value -) -{ - int32 val = atoi( _value.c_str() ); - return Set( val ); -} + bool ValueBitSet::SetFromString(string const& _value) + { + int32 val = atoi(_value.c_str()); + return Set(val); + } -string const ValueBitSet::GetAsString -( -) const -{ - stringstream ss; - ss << GetValue(); - return ss.str(); -} - -string const ValueBitSet::GetAsBinaryString -( -) const -{ - uint32 n = GetValue(); - std::string r; - while(n!=0) {r=(n%2==0 ?"0":"1")+r; n/=2;} - return "0b" + r; -} - -uint32 ValueBitSet::GetValue -( -) const -{ - return m_value.GetValue(); -} -bool ValueBitSet::GetBit -( - uint8 _idx -) const -{ - if (isValidBit(_idx)) - return m_value.IsSet(_idx-1); - Log::Write(LogLevel_Warning, m_id.GetNodeId(), "GetBit Index %d is not valid with BitMask %d", _idx, m_BitMask); - return false; + std::string const ValueBitSet::GetAsString() const + { + stringstream ss; + ss << GetValue(); + return ss.str(); + } -} + std::string const ValueBitSet::GetAsBinaryString() const + { + uint32 n = GetValue(); + std::string r; + while (n != 0) + { + r = (n % 2 == 0 ? "0" : "1") + r; + n /= 2; + } + return "0b" + r; + } + uint32 ValueBitSet::GetValue() const + { + return m_value.GetValue(); + } + bool ValueBitSet::GetBit(uint8 _idx) const + { + if (isValidBit(_idx)) + return m_value.IsSet(_idx - 1); + Log::Write(LogLevel_Warning, m_id.GetNodeId(), "GetBit Index %d is not valid with BitMask %d", _idx, m_BitMask); + return false; + } //----------------------------------------------------------------------------- // // Apply settings from XML //----------------------------------------------------------------------------- -void ValueBitSet::ReadXML -( - uint32 const _homeId, - uint8 const _nodeId, - uint8 const _commandClassId, - TiXmlElement const* _valueElement -) -{ - Value::ReadXML( _homeId, _nodeId, _commandClassId, _valueElement ); - - int intVal; - if( TIXML_SUCCESS == _valueElement->QueryIntAttribute( "bitmask", &intVal ) ) - { - m_BitMask = (uint32)intVal; - } - else - { - Log::Write( LogLevel_Info, "Missing BitMask value from xml configuration: node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex() ); - } - if( TIXML_SUCCESS == _valueElement->QueryIntAttribute( "value", &intVal ) ) - { - m_value.SetValue((uint32)intVal); - } - else - { - Log::Write( LogLevel_Info, "Missing default integer value from xml configuration: node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex() ); - } - // Get size of values - int intSize; - if ( TIXML_SUCCESS == _valueElement->QueryIntAttribute( "size", &intSize ) ) - { - if( intSize == 1 || intSize == 2 || intSize == 4 ) - { - m_size = intSize; - } - else - { - Log::Write( LogLevel_Info, "Value size is invalid. Only 1, 2 & 4 supported for node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex() ); - m_size = 1; - } - } - else - { - Log::Write( LogLevel_Info, "Value list size is not set, assuming 1 bytes for node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex() ); - m_size = 1; - } - TiXmlElement const *BitSetElement = _valueElement->FirstChildElement("BitSet"); - while (BitSetElement) { - uint32 id = 0; - if( TIXML_SUCCESS == BitSetElement->QueryIntAttribute( "id", &intVal ) ) + void ValueBitSet::ReadXML(uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement) { - id = (uint32)intVal; - TiXmlElement const *BitSetLabelElement = BitSetElement->FirstChildElement("Label"); - while (BitSetLabelElement) { - char const* lang = BitSetLabelElement->Attribute( "lang" ); - Localization::Get()->SetValueItemLabel(m_id.GetCommandClassId(), m_id.GetIndex(), -1, id, BitSetLabelElement->GetText(), lang ? lang : ""); + Value::ReadXML(_homeId, _nodeId, _commandClassId, _valueElement); - BitSetLabelElement = BitSetLabelElement->NextSiblingElement("Label"); + int intVal; + if (TIXML_SUCCESS == _valueElement->QueryIntAttribute("bitmask", &intVal)) + { + m_BitMask = (uint32) intVal; + } + else + { + Log::Write(LogLevel_Info, "Missing BitMask value from xml configuration: node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex()); + } + if (TIXML_SUCCESS == _valueElement->QueryIntAttribute("value", &intVal)) + { + m_value.SetValue((uint32) intVal); + } + else + { + Log::Write(LogLevel_Info, "Missing default integer value from xml configuration: node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex()); + } + // Get size of values + int intSize; + if (TIXML_SUCCESS == _valueElement->QueryIntAttribute("size", &intSize)) + { + if (intSize == 1 || intSize == 2 || intSize == 4) + { + m_size = intSize; + } + else + { + Log::Write(LogLevel_Info, "Value size is invalid. Only 1, 2 & 4 supported for node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex()); + m_size = 1; + } + } + else + { + Log::Write(LogLevel_Info, "Value list size is not set, assuming 1 bytes for node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex()); + m_size = 1; } - TiXmlElement const *BitSetHelpElement = BitSetElement->FirstChildElement("Help"); - while (BitSetHelpElement) { - char const* lang = BitSetHelpElement->Attribute( "lang" ); - Localization::Get()->SetValueItemHelp(m_id.GetCommandClassId(), m_id.GetIndex(), -1, id, BitSetHelpElement->GetText(), lang ? lang : ""); - BitSetHelpElement = BitSetHelpElement->NextSiblingElement("Help"); + TiXmlElement const *BitSetElement = _valueElement->FirstChildElement("BitSet"); + while (BitSetElement) + { + uint32 id = 0; + if (TIXML_SUCCESS == BitSetElement->QueryIntAttribute("id", &intVal)) + { + id = (uint32) intVal; + TiXmlElement const *BitSetLabelElement = BitSetElement->FirstChildElement("Label"); + while (BitSetLabelElement) + { + char const* lang = BitSetLabelElement->Attribute("lang"); + Localization::Get()->SetValueItemLabel(m_id.GetNodeId(), m_id.GetCommandClassId(), m_id.GetIndex(), -1, id, BitSetLabelElement->GetText(), lang ? lang : ""); + + BitSetLabelElement = BitSetLabelElement->NextSiblingElement("Label"); + } + TiXmlElement const *BitSetHelpElement = BitSetElement->FirstChildElement("Help"); + while (BitSetHelpElement) + { + char const* lang = BitSetHelpElement->Attribute("lang"); + Localization::Get()->SetValueItemHelp(m_id.GetNodeId(), m_id.GetCommandClassId(), m_id.GetIndex(), -1, id, BitSetHelpElement->GetText(), lang ? lang : ""); + BitSetHelpElement = BitSetHelpElement->NextSiblingElement("Help"); + } + m_bits.push_back(id); + } + BitSetElement = BitSetElement->NextSiblingElement("BitSet"); } - m_bits.push_back(id); } - BitSetElement = BitSetElement->NextSiblingElement("BitSet"); - } -} //----------------------------------------------------------------------------- // // Write ourselves to an XML document //----------------------------------------------------------------------------- -void ValueBitSet::WriteXML -( - TiXmlElement* _valueElement -) -{ - Value::WriteXML( _valueElement ); - char str[16]; - - snprintf(str, sizeof(str), "%d", m_BitMask); - _valueElement->SetAttribute( "bitmask", str); - - snprintf( str, sizeof(str), "%d", m_value.GetValue() ); - _valueElement->SetAttribute( "value", str ); - - snprintf( str, sizeof(str), "%d", m_size ); - _valueElement->SetAttribute( "size", str ); - - TiXmlElement *helpElement = _valueElement->FirstChildElement("Help"); - if (!helpElement) { - helpElement = new TiXmlElement( "Help" ); - _valueElement->LinkEndChild( helpElement ); - } - for (std::vector::iterator it = m_bits.begin(); it != m_bits.end(); ++it) { - TiXmlElement* BitSetElement = new TiXmlElement( "BitSet" ); - BitSetElement->SetAttribute("id", *it); - _valueElement->LinkEndChild( BitSetElement ); - - TiXmlElement* BitSetLabelElement = new TiXmlElement( "Label" ); - TiXmlText* labeltextElement = new TiXmlText(Localization::Get()->GetValueItemLabel(m_id.GetCommandClassId(), m_id.GetIndex(), -1, *it).c_str()); - BitSetLabelElement->LinkEndChild( labeltextElement ); - BitSetElement->LinkEndChild( BitSetLabelElement ); - - TiXmlElement* BitSetHelpElement = new TiXmlElement( "Help" ); - TiXmlText* helptextElement = new TiXmlText(Localization::Get()->GetValueItemHelp(m_id.GetCommandClassId(), m_id.GetIndex(), -1, *it).c_str()); - BitSetHelpElement->LinkEndChild( helptextElement ); - BitSetElement->LinkEndChild( BitSetHelpElement ); - } -} + void ValueBitSet::WriteXML(TiXmlElement* _valueElement) + { + Value::WriteXML(_valueElement); + char str[16]; + + snprintf(str, sizeof(str), "%d", m_BitMask); + _valueElement->SetAttribute("bitmask", str); + + snprintf(str, sizeof(str), "%d", m_value.GetValue()); + _valueElement->SetAttribute("value", str); + + snprintf(str, sizeof(str), "%d", m_size); + _valueElement->SetAttribute("size", str); + + TiXmlElement *helpElement = _valueElement->FirstChildElement("Help"); + if (!helpElement) + { + helpElement = new TiXmlElement("Help"); + _valueElement->LinkEndChild(helpElement); + } + for (std::vector::iterator it = m_bits.begin(); it != m_bits.end(); ++it) + { + TiXmlElement* BitSetElement = new TiXmlElement("BitSet"); + BitSetElement->SetAttribute("id", *it); + _valueElement->LinkEndChild(BitSetElement); + + TiXmlElement* BitSetLabelElement = new TiXmlElement("Label"); + TiXmlText* labeltextElement = new TiXmlText(Localization::Get()->GetValueItemLabel(m_id.GetNodeId(), m_id.GetCommandClassId(), m_id.GetIndex(), -1, *it).c_str()); + BitSetLabelElement->LinkEndChild(labeltextElement); + BitSetElement->LinkEndChild(BitSetLabelElement); + + TiXmlElement* BitSetHelpElement = new TiXmlElement("Help"); + TiXmlText* helptextElement = new TiXmlText(Localization::Get()->GetValueItemHelp(m_id.GetNodeId(), m_id.GetCommandClassId(), m_id.GetIndex(), -1, *it).c_str()); + BitSetHelpElement->LinkEndChild(helptextElement); + BitSetElement->LinkEndChild(BitSetHelpElement); + } + } //----------------------------------------------------------------------------- // // Set a new value in the device //----------------------------------------------------------------------------- -bool ValueBitSet::Set -( - uint32 const _value -) -{ - if (_value & ~ m_BitMask) { - Log::Write(LogLevel_Warning, m_id.GetNodeId(), "Set: Value %d is not valid with BitMask %d", _value, m_BitMask); - return false; - } - // create a temporary copy of this value to be submitted to the Set() call and set its value to the function param - ValueBitSet* tempValue = new ValueBitSet( *this ); + bool ValueBitSet::Set(uint32 const _value) + { + if (_value & ~m_BitMask) + { + Log::Write(LogLevel_Warning, m_id.GetNodeId(), "Set: Value %d is not valid with BitMask %d", _value, m_BitMask); + return false; + } + // create a temporary copy of this value to be submitted to the Set() call and set its value to the function param + ValueBitSet* tempValue = new ValueBitSet(*this); - tempValue->m_value.SetValue(_value); + tempValue->m_value.SetValue(_value); - // Set the value in the device. - bool ret = ((Value*)tempValue)->Set(); + // Set the value in the device. + bool ret = ((Value*) tempValue)->Set(); - // clean up the temporary value - delete tempValue; + // clean up the temporary value + delete tempValue; - return ret; -} + return ret; + } -bool ValueBitSet::SetBit -( - uint8 const _idx -) -{ - /* is the bits valid */ - if (!isValidBit(_idx)) { - Log::Write(LogLevel_Warning, m_id.GetNodeId(), "SetBit: Bit %d is not valid with BitMask %d", _idx, m_BitMask); - return false; - } + bool ValueBitSet::SetBit(uint8 const _idx) + { + /* is the bits valid */ + if (!isValidBit(_idx)) + { + Log::Write(LogLevel_Warning, m_id.GetNodeId(), "SetBit: Bit %d is not valid with BitMask %d", _idx, m_BitMask); + return false; + } - // create a temporary copy of this value to be submitted to the Set() call and set its value to the function param - ValueBitSet* tempValue = new ValueBitSet( *this ); + // create a temporary copy of this value to be submitted to the Set() call and set its value to the function param + ValueBitSet* tempValue = new ValueBitSet(*this); - tempValue->m_value.Set(_idx -1); + tempValue->m_value.Set(_idx - 1); - // Set the value in the device. - bool ret = ((Value*)tempValue)->Set(); + // Set the value in the device. + bool ret = ((Value*) tempValue)->Set(); - // clean up the temporary value - delete tempValue; + // clean up the temporary value + delete tempValue; - return ret; -} -bool ValueBitSet::ClearBit -( - uint8 const _idx -) -{ + return ret; + } + bool ValueBitSet::ClearBit(uint8 const _idx) + { - /* is the bits valid */ - if (!isValidBit(_idx)) { - Log::Write(LogLevel_Warning, m_id.GetNodeId(), "ClearBit: Bit %d is not valid with BitMask %d", _idx, m_BitMask); - return false; - } + /* is the bits valid */ + if (!isValidBit(_idx)) + { + Log::Write(LogLevel_Warning, m_id.GetNodeId(), "ClearBit: Bit %d is not valid with BitMask %d", _idx, m_BitMask); + return false; + } - // create a temporary copy of this value to be submitted to the Set() call and set its value to the function param - ValueBitSet* tempValue = new ValueBitSet( *this ); - tempValue->m_value.Clear(_idx -1); + // create a temporary copy of this value to be submitted to the Set() call and set its value to the function param + ValueBitSet* tempValue = new ValueBitSet(*this); + tempValue->m_value.Clear(_idx - 1); - // Set the value in the device. - bool ret = ((Value*)tempValue)->Set(); + // Set the value in the device. + bool ret = ((Value*) tempValue)->Set(); - // clean up the temporary value - delete tempValue; + // clean up the temporary value + delete tempValue; - return ret; -} + return ret; + } -bool ValueBitSet::SetBitMask -( - uint32 _bitMask -) -{ - m_BitMask = _bitMask; - return true; -} + bool ValueBitSet::SetBitMask(uint32 _bitMask) + { + m_BitMask = _bitMask; + return true; + } -uint32 ValueBitSet::GetBitMask -( -) const -{ - return m_BitMask; -} + uint32 ValueBitSet::GetBitMask() const + { + return m_BitMask; + } -string ValueBitSet::GetBitHelp -( - uint8 _idx -) -{ - if (isValidBit(_idx)) { - return Localization::Get()->GetValueItemHelp(m_id.GetCommandClassId(), m_id.GetIndex(), -1, _idx); - } - Log::Write(LogLevel_Warning, m_id.GetNodeId(), "SetBitHelp: Bit %d is not valid with BitMask %d", _idx, m_BitMask); - return ""; -} - -bool ValueBitSet::SetBitHelp -( - uint8 _idx, - string help -) -{ - if (isValidBit(_idx)) { - Localization::Get()->SetValueItemHelp(m_id.GetCommandClassId(), m_id.GetIndex(), -1, _idx, Localization::Get()->GetSelectedLang()); - return true; - } - Log::Write(LogLevel_Warning, m_id.GetNodeId(), "SetBitHelp: Bit %d is not valid with BitMask %d", _idx, m_BitMask); - return false; -} - -bool ValueBitSet::isValidBit -( - uint8 _idx -) const -{ - if (((m_BitMask) & (1 << (_idx -1))) == 0) - return false; - return true; -} - -string ValueBitSet::GetBitLabel -( - uint8 _idx -) -{ - if (isValidBit(_idx)) { - return Localization::Get()->GetValueItemLabel(m_id.GetCommandClassId(), m_id.GetIndex(), -1, _idx); - } - Log::Write(LogLevel_Warning, m_id.GetNodeId(), "GetBitLabel: Bit %d is not valid with BitMask %d", _idx, m_BitMask); - return "Reserved"; - -} -bool ValueBitSet::SetBitLabel -( - uint8 _idx, - string label -) -{ - if (isValidBit(_idx)) { - Localization::Get()->SetValueItemLabel(m_id.GetCommandClassId(), m_id.GetIndex(), -1, _idx, label, Localization::Get()->GetSelectedLang()); - return true; - } - Log::Write(LogLevel_Warning, m_id.GetNodeId(), "SetBitLabel: Bit %d is not valid with BitMask %d", _idx, m_BitMask); - return false; - -} - -uint8 ValueBitSet::GetSize -( -) const -{ - return m_size; -} -void ValueBitSet::SetSize -( - uint8 size -) -{ - m_size = size; -} + std::string ValueBitSet::GetBitHelp(uint8 _idx) + { + if (isValidBit(_idx)) + { + return Localization::Get()->GetValueItemHelp(m_id.GetNodeId(), m_id.GetCommandClassId(), m_id.GetIndex(), -1, _idx); + } + Log::Write(LogLevel_Warning, m_id.GetNodeId(), "SetBitHelp: Bit %d is not valid with BitMask %d", _idx, m_BitMask); + return ""; + } + bool ValueBitSet::SetBitHelp(uint8 _idx, string help) + { + if (isValidBit(_idx)) + { + Localization::Get()->SetValueItemHelp(m_id.GetNodeId(), m_id.GetCommandClassId(), m_id.GetIndex(), -1, _idx, Localization::Get()->GetSelectedLang()); + return true; + } + Log::Write(LogLevel_Warning, m_id.GetNodeId(), "SetBitHelp: Bit %d is not valid with BitMask %d", _idx, m_BitMask); + return false; + } + + bool ValueBitSet::isValidBit(uint8 _idx) const + { + if (((m_BitMask) & (1 << (_idx - 1))) == 0) + return false; + return true; + } + + std::string ValueBitSet::GetBitLabel(uint8 _idx) + { + if (isValidBit(_idx)) + { + return Localization::Get()->GetValueItemLabel(m_id.GetNodeId(), m_id.GetCommandClassId(), m_id.GetIndex(), -1, _idx); + } + Log::Write(LogLevel_Warning, m_id.GetNodeId(), "GetBitLabel: Bit %d is not valid with BitMask %d", _idx, m_BitMask); + return "Reserved"; + + } + bool ValueBitSet::SetBitLabel(uint8 _idx, string label) + { + if (isValidBit(_idx)) + { + Localization::Get()->SetValueItemLabel(m_id.GetNodeId(), m_id.GetCommandClassId(), m_id.GetIndex(), -1, _idx, label, Localization::Get()->GetSelectedLang()); + return true; + } + Log::Write(LogLevel_Warning, m_id.GetNodeId(), "SetBitLabel: Bit %d is not valid with BitMask %d", _idx, m_BitMask); + return false; + + } + + uint8 ValueBitSet::GetSize() const + { + return m_size; + } + void ValueBitSet::SetSize(uint8 size) + { + m_size = size; + } //----------------------------------------------------------------------------- // // A value in a device has been refreshed //----------------------------------------------------------------------------- -void ValueBitSet::OnValueRefreshed -( - uint32 const _value -) -{ - switch( VerifyRefreshedValue( (void*) &m_value, (void*) &m_valueCheck, (void*) &_value, ValueID::ValueType_Bool) ) - { - case 0: // value hasn't changed, nothing to do - break; - case 1: // value has changed (not confirmed yet), save _value in m_valueCheck - m_valueCheck.SetValue(_value); - break; - case 2: // value has changed (confirmed), save _value in m_value - m_value.SetValue(_value); - break; - case 3: // all three values are different, so wait for next refresh to try again - break; - } -} + void ValueBitSet::OnValueRefreshed(uint32 const _value) + { + switch (VerifyRefreshedValue((void*) &m_value, (void*) &m_valueCheck, (void*) &_value, ValueID::ValueType_BitSet)) + { + case 0: // value hasn't changed, nothing to do + break; + case 1: // value has changed (not confirmed yet), save _value in m_valueCheck + m_valueCheck.SetValue(_value); + break; + case 2: // value has changed (confirmed), save _value in m_value + m_value.SetValue(_value); + break; + case 3: // all three values are different, so wait for next refresh to try again + break; + } + } + } // namespace VC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/value_classes/ValueBitSet.h b/cpp/src/value_classes/ValueBitSet.h index 2e0360e635..f4a9766d41 100644 --- a/cpp/src/value_classes/ValueBitSet.h +++ b/cpp/src/value_classes/ValueBitSet.h @@ -38,60 +38,64 @@ class TiXmlElement; namespace OpenZWave { - class Msg; - class Node; - class CommandClass; - - /** \brief BitSet value sent to/received from a node. - * \ingroup ValueID - */ - class ValueBitSet: public Value + namespace Internal { - public: - ValueBitSet( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, uint32 const _value, uint8 const _pollIntensity ); - ValueBitSet(){} - virtual ~ValueBitSet(){} - - bool Set( uint32 const _value ); - uint32 GetValue() const; - - bool SetBit( uint8 const _idx); - bool ClearBit(uint8 const _idx); - bool GetBit(uint8 _idx) const; - - bool SetBitMask(uint32 _bitMask); - uint32 GetBitMask() const; - - void OnValueRefreshed( uint32 const _value ); - - // From Value - virtual string const GetAsString() const; - virtual string const GetAsBinaryString() const; - virtual bool SetFromString( string const& _value ); - virtual void ReadXML( uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement ); - virtual void WriteXML( TiXmlElement* _valueElement ); - - string GetBitHelp(uint8 _idx); - bool SetBitHelp(uint8 _idx, string help); - string GetBitLabel(uint8 _idx); - bool SetBitLabel(uint8 _idx, string label); - - uint8 GetSize() const; - void SetSize(uint8 size); - - private: - bool isValidBit(uint8 _idx) const; - Bitfield m_value; // the current index in the m_items vector - Bitfield m_valueCheck; // the previous value (used for double-checking spurious value reads) - Bitfield m_newValue; // a new value to be set on the appropriate device - uint32 m_BitMask; // Valid Bits - uint8 m_size; // Number of bytes in size - vector m_bits; - }; - + namespace VC + { + + /** \brief BitSet value sent to/received from a node. + * \ingroup ValueID + */ + class ValueBitSet: public Value + { + public: + ValueBitSet(uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, uint32 const _value, uint8 const _pollIntensity); + ValueBitSet() + { + } + virtual ~ValueBitSet() + { + } + + bool Set(uint32 const _value); + uint32 GetValue() const; + + bool SetBit(uint8 const _idx); + bool ClearBit(uint8 const _idx); + bool GetBit(uint8 _idx) const; + + bool SetBitMask(uint32 _bitMask); + uint32 GetBitMask() const; + + void OnValueRefreshed(uint32 const _value); + + // From Value + virtual string const GetAsString() const; + virtual string const GetAsBinaryString() const; + virtual bool SetFromString(string const& _value); + virtual void ReadXML(uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement); + virtual void WriteXML(TiXmlElement* _valueElement); + + string GetBitHelp(uint8 _idx); + bool SetBitHelp(uint8 _idx, string help); + string GetBitLabel(uint8 _idx); + bool SetBitLabel(uint8 _idx, string label); + + uint8 GetSize() const; + void SetSize(uint8 size); + + private: + bool isValidBit(uint8 _idx) const; + Bitfield m_value; // the current index in the m_items vector + Bitfield m_valueCheck; // the previous value (used for double-checking spurious value reads) + Bitfield m_newValue; // a new value to be set on the appropriate device + uint32 m_BitMask; // Valid Bits + uint8 m_size; // Number of bytes in size + vector m_bits; + }; + } // namespace VC + } // namespace Internal } // namespace OpenZWave #endif - - diff --git a/cpp/src/value_classes/ValueBool.cpp b/cpp/src/value_classes/ValueBool.cpp index cadf311425..d7683d93fd 100644 --- a/cpp/src/value_classes/ValueBool.cpp +++ b/cpp/src/value_classes/ValueBool.cpp @@ -33,128 +33,103 @@ #include "Manager.h" #include -using namespace OpenZWave; - +namespace OpenZWave +{ + namespace Internal + { + namespace VC + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -ValueBool::ValueBool -( - uint32 const _homeId, - uint8 const _nodeId, - ValueID::ValueGenre const _genre, - uint8 const _commandClassId, - uint8 const _instance, - uint16 const _index, - string const& _label, - string const& _units, - bool const _readOnly, - bool const _writeOnly, - bool const _value, - uint8 const _pollIntensity -): - Value( _homeId, _nodeId, _genre, _commandClassId, _instance, _index, ValueID::ValueType_Bool, _label, _units, _readOnly, _writeOnly, false, _pollIntensity ), - m_value( _value ), - m_valueCheck( false ) -{ -} + ValueBool::ValueBool(uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, bool const _value, uint8 const _pollIntensity) : + Value(_homeId, _nodeId, _genre, _commandClassId, _instance, _index, ValueID::ValueType_Bool, _label, _units, _readOnly, _writeOnly, false, _pollIntensity), m_value(_value), m_valueCheck(false) + { + } -bool ValueBool::SetFromString -( - string const& _value -) -{ - if ( !strcasecmp( "true", _value.c_str() ) ) { - return Set( true ); - } - else if ( !strcasecmp( "false", _value.c_str() ) ) { - return Set( false ); - } - return false; -} + bool ValueBool::SetFromString(string const& _value) + { + if (!strcasecmp("true", _value.c_str())) + { + return Set(true); + } + else if (!strcasecmp("false", _value.c_str())) + { + return Set(false); + } + return false; + } //----------------------------------------------------------------------------- // // Apply settings from XML //----------------------------------------------------------------------------- -void ValueBool::ReadXML -( - uint32 const _homeId, - uint8 const _nodeId, - uint8 const _commandClassId, - TiXmlElement const* _valueElement -) -{ - Value::ReadXML( _homeId, _nodeId, _commandClassId, _valueElement ); + void ValueBool::ReadXML(uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement) + { + Value::ReadXML(_homeId, _nodeId, _commandClassId, _valueElement); - char const* str = _valueElement->Attribute( "value" ); - if( str ) - { - m_value = !strcmp( str, "True" ); - } - else - { - Log::Write( LogLevel_Info, "Missing default boolean value from xml configuration: node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex() ); - } -} + char const* str = _valueElement->Attribute("value"); + if (str) + { + m_value = !strcmp(str, "True"); + } + else + { + Log::Write(LogLevel_Info, "Missing default boolean value from xml configuration: node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex()); + } + } //----------------------------------------------------------------------------- // // Write ourselves to an XML document //----------------------------------------------------------------------------- -void ValueBool::WriteXML -( - TiXmlElement* _valueElement -) -{ - Value::WriteXML( _valueElement ); - _valueElement->SetAttribute( "value", m_value ? "True" : "False" ); -} + void ValueBool::WriteXML(TiXmlElement* _valueElement) + { + Value::WriteXML(_valueElement); + _valueElement->SetAttribute("value", m_value ? "True" : "False"); + } //----------------------------------------------------------------------------- // // Set a new value in the device //----------------------------------------------------------------------------- -bool ValueBool::Set -( - bool const _value -) -{ - // create a temporary copy of this value to be submitted to the Set() call and set its value to the function param - ValueBool* tempValue = new ValueBool( *this ); - tempValue->m_value = _value; + bool ValueBool::Set(bool const _value) + { + // create a temporary copy of this value to be submitted to the Set() call and set its value to the function param + ValueBool* tempValue = new ValueBool(*this); + tempValue->m_value = _value; - // Set the value in the device. - bool ret = ((Value*)tempValue)->Set(); + // Set the value in the device. + bool ret = ((Value*) tempValue)->Set(); - // clean up the temporary value - delete tempValue; + // clean up the temporary value + delete tempValue; - return ret; -} + return ret; + } //----------------------------------------------------------------------------- // // A value in a device has been refreshed //----------------------------------------------------------------------------- -void ValueBool::OnValueRefreshed -( - bool const _value -) -{ - switch( VerifyRefreshedValue( (void*) &m_value, (void*) &m_valueCheck, (void*) &_value, ValueID::ValueType_Bool) ) - { - case 0: // value hasn't changed, nothing to do - break; - case 1: // value has changed (not confirmed yet), save _value in m_valueCheck - m_valueCheck = _value; - break; - case 2: // value has changed (confirmed), save _value in m_value - m_value = _value; - break; - case 3: // all three values are different, so wait for next refresh to try again - break; - } -} + void ValueBool::OnValueRefreshed(bool const _value) + { + switch (VerifyRefreshedValue((void*) &m_value, (void*) &m_valueCheck, (void*) &_value, ValueID::ValueType_Bool)) + { + case 0: // value hasn't changed, nothing to do + break; + case 1: // value has changed (not confirmed yet), save _value in m_valueCheck + m_valueCheck = _value; + break; + case 2: // value has changed (confirmed), save _value in m_value + m_value = _value; + break; + case 3: // all three values are different, so wait for next refresh to try again + break; + } + } + } // namespace VC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/value_classes/ValueBool.h b/cpp/src/value_classes/ValueBool.h index 070d0d4a6b..7caf62eea4 100644 --- a/cpp/src/value_classes/ValueBool.h +++ b/cpp/src/value_classes/ValueBool.h @@ -36,39 +36,49 @@ class TiXmlElement; namespace OpenZWave { - class Msg; - class Node; - class CommandClass; - - /** \brief Boolean value sent to/received from a node. - * \ingroup ValueID - */ - class ValueBool: public Value + namespace Internal { - public: - ValueBool( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, bool const _value, uint8 const _pollIntensity ); - ValueBool(){} - virtual ~ValueBool(){} + namespace VC + { - bool Set( bool const _value ); - void OnValueRefreshed( bool const _value ); + /** \brief Boolean value sent to/received from a node. + * \ingroup ValueID + */ + class ValueBool: public Value + { + public: + ValueBool(uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, bool const _value, uint8 const _pollIntensity); + ValueBool() + { + } + virtual ~ValueBool() + { + } - // From Value - virtual string const GetAsString() const { return ( GetValue() ? "True" : "False" ); } - virtual bool SetFromString( string const& _value ); - virtual void ReadXML( uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement ); - virtual void WriteXML( TiXmlElement* _valueElement ); + bool Set(bool const _value); + void OnValueRefreshed(bool const _value); - bool GetValue()const{ return m_value; } + // From Value + virtual string const GetAsString() const + { + return (GetValue() ? "True" : "False"); + } + virtual bool SetFromString(string const& _value); + virtual void ReadXML(uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement); + virtual void WriteXML(TiXmlElement* _valueElement); - private: - bool m_value; // the current index in the m_items vector - bool m_valueCheck; // the previous value (used for double-checking spurious value reads) - }; + bool GetValue() const + { + return m_value; + } + private: + bool m_value; // the current index in the m_items vector + bool m_valueCheck; // the previous value (used for double-checking spurious value reads) + }; + } // namespace VC + } // namespace Internal } // namespace OpenZWave #endif - - diff --git a/cpp/src/value_classes/ValueButton.cpp b/cpp/src/value_classes/ValueButton.cpp index 2cb9a05727..f524ab5bd7 100644 --- a/cpp/src/value_classes/ValueButton.cpp +++ b/cpp/src/value_classes/ValueButton.cpp @@ -32,81 +32,61 @@ #include "Node.h" #include "platform/Log.h" -using namespace OpenZWave; - +namespace OpenZWave +{ + namespace Internal + { + namespace VC + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -ValueButton::ValueButton -( - uint32 const _homeId, - uint8 const _nodeId, - ValueID::ValueGenre const _genre, - uint8 const _commandClassId, - uint8 const _instance, - uint16 const _index, - string const& _label, - uint8 const _pollIntensity -): - Value( _homeId, _nodeId, _genre, _commandClassId, _instance, _index, ValueID::ValueType_Button, _label, "", false, true, true, _pollIntensity ), - m_pressed( false ) -{ -} + ValueButton::ValueButton(uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, uint8 const _pollIntensity) : + Value(_homeId, _nodeId, _genre, _commandClassId, _instance, _index, ValueID::ValueType_Button, _label, "", false, true, true, _pollIntensity), m_pressed(false) + { + } //----------------------------------------------------------------------------- // // Apply settings from XML //----------------------------------------------------------------------------- -void ValueButton::ReadXML -( - uint32 const _homeId, - uint8 const _nodeId, - uint8 const _commandClassId, - TiXmlElement const* _valueElement -) -{ - Value::ReadXML( _homeId, _nodeId, _commandClassId, _valueElement ); -} + void ValueButton::ReadXML(uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement) + { + Value::ReadXML(_homeId, _nodeId, _commandClassId, _valueElement); + } //----------------------------------------------------------------------------- // // Write ourselves to an XML document //----------------------------------------------------------------------------- -void ValueButton::WriteXML -( - TiXmlElement* _valueElement -) -{ - Value::WriteXML( _valueElement ); -} + void ValueButton::WriteXML(TiXmlElement* _valueElement) + { + Value::WriteXML(_valueElement); + } //----------------------------------------------------------------------------- // // Start an activity in a device //----------------------------------------------------------------------------- -bool ValueButton::PressButton -( -) -{ - // Set the value in the device. - m_pressed = true; - return Value::Set(); -} + bool ValueButton::PressButton() + { + // Set the value in the device. + m_pressed = true; + return Value::Set(); + } //----------------------------------------------------------------------------- // // Stop an activity in a device //----------------------------------------------------------------------------- -bool ValueButton::ReleaseButton -( -) -{ - // Set the value in the device. - m_pressed = false; - return Value::Set(); -} - - - + bool ValueButton::ReleaseButton() + { + // Set the value in the device. + m_pressed = false; + return Value::Set(); + } + } // namespace VC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/value_classes/ValueButton.h b/cpp/src/value_classes/ValueButton.h index 842a7f3b28..a4992cd737 100644 --- a/cpp/src/value_classes/ValueButton.h +++ b/cpp/src/value_classes/ValueButton.h @@ -36,38 +36,49 @@ class TiXmlElement; namespace OpenZWave { - class Msg; - class Node; - class CommandClass; - - /** \brief Button value - * \ingroup ValueID - */ - class ValueButton: public Value + namespace Internal { - public: - ValueButton( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, uint8 const _pollIntensity ); - ValueButton(): m_pressed( false ){} - virtual ~ValueButton(){} + namespace VC + { - bool PressButton(); - bool ReleaseButton(); + /** \brief Button value + * \ingroup ValueID + */ + class ValueButton: public Value + { + public: + ValueButton(uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, uint8 const _pollIntensity); + ValueButton() : + m_pressed(false) + { + } + virtual ~ValueButton() + { + } - virtual string const GetAsString() const { return ( IsPressed() ? "true" : "false" ); } + bool PressButton(); + bool ReleaseButton(); - // From Value - virtual void ReadXML( uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement ); - virtual void WriteXML( TiXmlElement* _valueElement ); + virtual string const GetAsString() const + { + return (IsPressed() ? "true" : "false"); + } - bool IsPressed()const{ return m_pressed; } + // From Value + virtual void ReadXML(uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement); + virtual void WriteXML(TiXmlElement* _valueElement); - private: - bool m_pressed; - }; + bool IsPressed() const + { + return m_pressed; + } + private: + bool m_pressed; + }; + } // namespace VC + } // namespace Internal } // namespace OpenZWave #endif - - diff --git a/cpp/src/value_classes/ValueByte.cpp b/cpp/src/value_classes/ValueByte.cpp index efab36b163..68e30d7211 100644 --- a/cpp/src/value_classes/ValueByte.cpp +++ b/cpp/src/value_classes/ValueByte.cpp @@ -33,153 +33,122 @@ #include "Manager.h" #include -using namespace OpenZWave; - +namespace OpenZWave +{ + namespace Internal + { + namespace VC + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -ValueByte::ValueByte -( - uint32 const _homeId, - uint8 const _nodeId, - ValueID::ValueGenre const _genre, - uint8 const _commandClassId, - uint8 const _instance, - uint16 const _index, - string const& _label, - string const& _units, - bool const _readOnly, - bool const _writeOnly, - uint8 const _value, - uint8 const _pollIntensity -): - Value( _homeId, _nodeId, _genre, _commandClassId, _instance, _index, ValueID::ValueType_Byte, _label, _units, _readOnly, _writeOnly, false, _pollIntensity ), - m_value( _value ), - m_valueCheck( false ) -{ - m_min = 0; - m_max = 255; -} + ValueByte::ValueByte(uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, uint8 const _value, uint8 const _pollIntensity) : + Value(_homeId, _nodeId, _genre, _commandClassId, _instance, _index, ValueID::ValueType_Byte, _label, _units, _readOnly, _writeOnly, false, _pollIntensity), m_value(_value), m_valueCheck(false) + { + m_min = 0; + m_max = 255; + } //----------------------------------------------------------------------------- // // Constructor (from XML) //----------------------------------------------------------------------------- -ValueByte::ValueByte -( -) -{ - m_min = 0; - m_max = 255; -} - -string const ValueByte::GetAsString -( -) const -{ - stringstream ss; - ss << (uint32)GetValue(); - return ss.str(); -} - -bool ValueByte::SetFromString -( - string const& _value -) -{ - uint32 val = (uint32)atoi( _value.c_str() ); - if( val < 256 ) - { - return Set( (uint8)val ); - } - return false; -} + ValueByte::ValueByte() + { + m_min = 0; + m_max = 255; + } + + std::string const ValueByte::GetAsString() const + { + stringstream ss; + ss << (uint32) GetValue(); + return ss.str(); + } + + bool ValueByte::SetFromString(string const& _value) + { + uint32 val = (uint32) atoi(_value.c_str()); + if (val < 256) + { + return Set((uint8) val); + } + return false; + } //----------------------------------------------------------------------------- // // Apply settings from XML //----------------------------------------------------------------------------- -void ValueByte::ReadXML -( - uint32 const _homeId, - uint8 const _nodeId, - uint8 const _commandClassId, - TiXmlElement const* _valueElement -) -{ - Value::ReadXML( _homeId, _nodeId, _commandClassId, _valueElement ); - - int intVal; - if( TIXML_SUCCESS == _valueElement->QueryIntAttribute( "value", &intVal ) ) - { - m_value = (uint8)intVal; - } - else - { - Log::Write( LogLevel_Info, "Missing default byte value from xml configuration: node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex() ); - } -} + void ValueByte::ReadXML(uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement) + { + Value::ReadXML(_homeId, _nodeId, _commandClassId, _valueElement); + + int intVal; + if (TIXML_SUCCESS == _valueElement->QueryIntAttribute("value", &intVal)) + { + m_value = (uint8) intVal; + } + else + { + Log::Write(LogLevel_Info, "Missing default byte value from xml configuration: node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex()); + } + } //----------------------------------------------------------------------------- // // Write ourselves to an XML document //----------------------------------------------------------------------------- -void ValueByte::WriteXML -( - TiXmlElement* _valueElement -) -{ - Value::WriteXML( _valueElement ); + void ValueByte::WriteXML(TiXmlElement* _valueElement) + { + Value::WriteXML(_valueElement); - char str[8]; - snprintf( str, sizeof(str), "%d", m_value ); - _valueElement->SetAttribute( "value", str ); -} + char str[8]; + snprintf(str, sizeof(str), "%d", m_value); + _valueElement->SetAttribute("value", str); + } //----------------------------------------------------------------------------- // // Set a new value in the device //----------------------------------------------------------------------------- -bool ValueByte::Set -( - uint8 const _value -) -{ - // create a temporary copy of this value to be submitted to the Set() call and set its value to the function param - ValueByte* tempValue = new ValueByte( *this ); - tempValue->m_value = _value; + bool ValueByte::Set(uint8 const _value) + { + // create a temporary copy of this value to be submitted to the Set() call and set its value to the function param + ValueByte* tempValue = new ValueByte(*this); + tempValue->m_value = _value; - // Set the value in the device. - bool ret = ((Value*)tempValue)->Set(); + // Set the value in the device. + bool ret = ((Value*) tempValue)->Set(); - // clean up the temporary value - delete tempValue; + // clean up the temporary value + delete tempValue; - return ret; -} + return ret; + } //----------------------------------------------------------------------------- // // A value in a device has been refreshed //----------------------------------------------------------------------------- -void ValueByte::OnValueRefreshed -( - uint8 const _value -) -{ - switch( VerifyRefreshedValue( (void*) &m_value, (void*) &m_valueCheck, (void*) &_value, ValueID::ValueType_Byte) ) - { - case 0: // value hasn't changed, nothing to do - break; - case 1: // value has changed (not confirmed yet), save _value in m_valueCheck - m_valueCheck = _value; - break; - case 2: // value has changed (confirmed), save _value in m_value - m_value = _value; - break; - case 3: // all three values are different, so wait for next refresh to try again - break; - } -} + void ValueByte::OnValueRefreshed(uint8 const _value) + { + switch (VerifyRefreshedValue((void*) &m_value, (void*) &m_valueCheck, (void*) &_value, ValueID::ValueType_Byte)) + { + case 0: // value hasn't changed, nothing to do + break; + case 1: // value has changed (not confirmed yet), save _value in m_valueCheck + m_valueCheck = _value; + break; + case 2: // value has changed (confirmed), save _value in m_value + m_value = _value; + break; + case 3: // all three values are different, so wait for next refresh to try again + break; + } + } + } // namespace VC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/value_classes/ValueByte.h b/cpp/src/value_classes/ValueByte.h index 8bbbff601a..517b04a28b 100644 --- a/cpp/src/value_classes/ValueByte.h +++ b/cpp/src/value_classes/ValueByte.h @@ -36,38 +36,44 @@ class TiXmlElement; namespace OpenZWave { - class Msg; - class Node; - - /** \brief Byte value sent to/received from a node. - * \ingroup ValueID - */ - class ValueByte: public Value + namespace Internal { - public: - ValueByte( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, uint8 const _value, uint8 const _pollIntensity ); - ValueByte(); - virtual ~ValueByte(){} + namespace VC + { - bool Set( uint8 const _value ); - void OnValueRefreshed( uint8 const _value ); + /** \brief Byte value sent to/received from a node. + * \ingroup ValueID + */ + class ValueByte: public Value + { + public: + ValueByte(uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, uint8 const _value, uint8 const _pollIntensity); + ValueByte(); + virtual ~ValueByte() + { + } - // From Value - virtual string const GetAsString() const; - virtual bool SetFromString( string const& _value ); - virtual void ReadXML( uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement ); - virtual void WriteXML( TiXmlElement* _valueElement ); + bool Set(uint8 const _value); + void OnValueRefreshed(uint8 const _value); - uint8 GetValue()const{ return m_value; } + // From Value + virtual string const GetAsString() const; + virtual bool SetFromString(string const& _value); + virtual void ReadXML(uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement); + virtual void WriteXML(TiXmlElement* _valueElement); - private: - uint8 m_value; // the current value - uint8 m_valueCheck; // the previous value (used for double-checking spurious value reads) - }; + uint8 GetValue() const + { + return m_value; + } + private: + uint8 m_value; // the current value + uint8 m_valueCheck; // the previous value (used for double-checking spurious value reads) + }; + } // namespace VC + } // namespace Internal } // namespace OpenZWave #endif - - diff --git a/cpp/src/value_classes/ValueDecimal.cpp b/cpp/src/value_classes/ValueDecimal.cpp index 298ff8ce7b..9acef6ce61 100644 --- a/cpp/src/value_classes/ValueDecimal.cpp +++ b/cpp/src/value_classes/ValueDecimal.cpp @@ -32,116 +32,90 @@ #include "Manager.h" #include -using namespace OpenZWave; - +namespace OpenZWave +{ + namespace Internal + { + namespace VC + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -ValueDecimal::ValueDecimal -( - uint32 const _homeId, - uint8 const _nodeId, - ValueID::ValueGenre const _genre, - uint8 const _commandClassId, - uint8 const _instance, - uint16 const _index, - string const& _label, - string const& _units, - bool const _readOnly, - bool const _writeOnly, - string const& _value, - uint8 const _pollIntensity -): - Value( _homeId, _nodeId, _genre, _commandClassId, _instance, _index, ValueID::ValueType_Decimal, _label, _units, _readOnly, _writeOnly, false, _pollIntensity ), - m_value( _value ), - m_valueCheck( "" ), - m_newValue( "" ), - m_precision( 0 ) -{ -} + ValueDecimal::ValueDecimal(uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, string const& _value, uint8 const _pollIntensity) : + Value(_homeId, _nodeId, _genre, _commandClassId, _instance, _index, ValueID::ValueType_Decimal, _label, _units, _readOnly, _writeOnly, false, _pollIntensity), m_value(_value), m_valueCheck(""), m_newValue(""), m_precision(0) + { + } //----------------------------------------------------------------------------- // // Apply settings from XML //----------------------------------------------------------------------------- -void ValueDecimal::ReadXML -( - uint32 const _homeId, - uint8 const _nodeId, - uint8 const _commandClassId, - TiXmlElement const* _valueElement -) -{ - Value::ReadXML( _homeId, _nodeId, _commandClassId, _valueElement ); + void ValueDecimal::ReadXML(uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement) + { + Value::ReadXML(_homeId, _nodeId, _commandClassId, _valueElement); - char const* str = _valueElement->Attribute( "value" ); - if( str ) - { - m_value = str; - } - else - { - Log::Write( LogLevel_Info, "Missing default decimal value from xml configuration: node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex() ); - } -} + char const* str = _valueElement->Attribute("value"); + if (str) + { + m_value = str; + } + else + { + Log::Write(LogLevel_Info, "Missing default decimal value from xml configuration: node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex()); + } + } //----------------------------------------------------------------------------- // // Write ourselves to an XML document //----------------------------------------------------------------------------- -void ValueDecimal::WriteXML -( - TiXmlElement* _valueElement -) -{ - Value::WriteXML( _valueElement ); - _valueElement->SetAttribute( "value", m_value.c_str() ); -} + void ValueDecimal::WriteXML(TiXmlElement* _valueElement) + { + Value::WriteXML(_valueElement); + _valueElement->SetAttribute("value", m_value.c_str()); + } //----------------------------------------------------------------------------- // // Set a new value in the device //----------------------------------------------------------------------------- -bool ValueDecimal::Set -( - string const& _value -) -{ - // create a temporary copy of this value to be submitted to the Set() call and set its value to the function param - ValueDecimal* tempValue = new ValueDecimal( *this ); - tempValue->m_value = _value; + bool ValueDecimal::Set(string const& _value) + { + // create a temporary copy of this value to be submitted to the Set() call and set its value to the function param + ValueDecimal* tempValue = new ValueDecimal(*this); + tempValue->m_value = _value; - // Set the value in the device. - bool ret = ((Value*)tempValue)->Set(); + // Set the value in the device. + bool ret = ((Value*) tempValue)->Set(); - // clean up the temporary value - delete tempValue; + // clean up the temporary value + delete tempValue; - return ret; -} + return ret; + } //----------------------------------------------------------------------------- // // A value in a device has been refreshed //----------------------------------------------------------------------------- -void ValueDecimal::OnValueRefreshed -( - string const& _value -) -{ - switch( VerifyRefreshedValue( (void*) &m_value, (void*) &m_valueCheck, (void*) &_value, ValueID::ValueType_Decimal) ) - { - case 0: // value hasn't changed, nothing to do - break; - case 1: // value has changed (not confirmed yet), save _value in m_valueCheck - m_valueCheck = _value; - break; - case 2: // value has changed (confirmed), save _value in m_value - m_value = _value; - break; - case 3: // all three values are different, so wait for next refresh to try again - break; - } -} + void ValueDecimal::OnValueRefreshed(string const& _value) + { + switch (VerifyRefreshedValue((void*) &m_value, (void*) &m_valueCheck, (void*) &_value, ValueID::ValueType_Decimal)) + { + case 0: // value hasn't changed, nothing to do + break; + case 1: // value has changed (not confirmed yet), save _value in m_valueCheck + m_valueCheck = _value; + break; + case 2: // value has changed (confirmed), save _value in m_value + m_value = _value; + break; + case 3: // all three values are different, so wait for next refresh to try again + break; + } + } + } // namespace VC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/value_classes/ValueDecimal.h b/cpp/src/value_classes/ValueDecimal.h index 832bcefbfc..8684932209 100644 --- a/cpp/src/value_classes/ValueDecimal.h +++ b/cpp/src/value_classes/ValueDecimal.h @@ -36,48 +36,65 @@ class TiXmlElement; namespace OpenZWave { - class Msg; - class Node; - - /** \brief Decimal value sent to/received from a node. - * \ingroup ValueID - */ - class ValueDecimal: public Value + namespace Internal { - friend class EnergyProduction; - friend class Meter; - friend class SensorMultilevel; - friend class ThermostatSetpoint; - - public: - ValueDecimal( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, string const& _value, uint8 const _pollIntensity ); - ValueDecimal(): m_precision( 0 ){} - virtual ~ValueDecimal(){} - - bool Set( string const& _value ); - void OnValueRefreshed( string const& _value ); - - // From Value - virtual string const GetAsString() const { return GetValue(); } - virtual bool SetFromString( string const& _value ) { return Set( _value ); } - virtual void ReadXML( uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement ); - virtual void WriteXML( TiXmlElement* _valueElement ); - - string GetValue()const{ return m_value; } - uint8 GetPrecision()const{ return m_precision; } - - private: - void SetPrecision( uint8 _precision ){ m_precision = _precision; } - - string m_value; // the current value - string m_valueCheck; // the previous value (used for double-checking spurious value reads) - string m_newValue; // a new value to be set on the appropriate device - uint8 m_precision; - }; - + namespace VC + { + + /** \brief Decimal value sent to/received from a node. + * \ingroup ValueID + */ + class ValueDecimal: public Value + { + + public: + ValueDecimal(uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, string const& _value, uint8 const _pollIntensity); + ValueDecimal() : + m_precision(0) + { + } + virtual ~ValueDecimal() + { + } + + bool Set(string const& _value); + void OnValueRefreshed(string const& _value); + + // From Value + virtual string const GetAsString() const + { + return GetValue(); + } + virtual bool SetFromString(string const& _value) + { + return Set(_value); + } + virtual void ReadXML(uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement); + virtual void WriteXML(TiXmlElement* _valueElement); + + string GetValue() const + { + return m_value; + } + uint8 GetPrecision() const + { + return m_precision; + } + void SetPrecision(uint8 _precision) + { + m_precision = _precision; + } + + private: + + string m_value; // the current value + string m_valueCheck; // the previous value (used for double-checking spurious value reads) + string m_newValue; // a new value to be set on the appropriate device + uint8 m_precision; + }; + } // namespace VC + } // namespace Internal } // namespace OpenZWave #endif - - diff --git a/cpp/src/value_classes/ValueID.cpp b/cpp/src/value_classes/ValueID.cpp new file mode 100644 index 0000000000..3154dbc3ff --- /dev/null +++ b/cpp/src/value_classes/ValueID.cpp @@ -0,0 +1,51 @@ +//----------------------------------------------------------------------------- +// +// ValueID.cpp +// +// Represents a Device Variable in OZW +// +// Copyright (c) 2019 Justin Hammond +// +// SOFTWARE NOTICE AND LICENSE +// +// This file is part of OpenZWave. +// +// OpenZWave is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, either version 3 of the License, +// or (at your option) any later version. +// +// OpenZWave is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with OpenZWave. If not, see . +// +//----------------------------------------------------------------------------- + +#include "ValueID.h" +#include "Value.h" + +namespace OpenZWave +{ + //----------------------------------------------------------------------------- + // + // Get the Genre as a String + //----------------------------------------------------------------------------- + string ValueID::GetGenreAsString() const + { + return Internal::VC::Value::GetGenreNameFromEnum(GetGenre()); + } + + //----------------------------------------------------------------------------- + // + // Get the Type as a String + //----------------------------------------------------------------------------- + string ValueID::GetTypeAsString() const + { + return Internal::VC::Value::GetTypeNameFromEnum(GetType()); + } + +}// namespace OpenZWave diff --git a/cpp/src/value_classes/ValueID.h b/cpp/src/value_classes/ValueID.h index b5460dee15..937e7673f6 100644 --- a/cpp/src/value_classes/ValueID.h +++ b/cpp/src/value_classes/ValueID.h @@ -30,19 +30,32 @@ #include #include + +#include "ValueIDIndexes.h" #include "Defs.h" class TiXmlElement; namespace OpenZWave { - /** \defgroup ValueID ValueID Support - * - * ValueID's in OZW expose device functionality to the application. Many different - * types of ValueID's are exposed, and they represent the state of a device (such as a - * switch on or off) or configuration parameters of a device. - */ + namespace Internal + { + namespace VC + { + class Value; + class ValueStore; + } + ; + } + ; + + /** \defgroup ValueID ValueID Support + * + * ValueID's in OZW expose device functionality to the application. Many different + * types of ValueID's are exposed, and they represent the state of a device (such as a + * switch on or off) or configuration parameters of a device. + */ /** \brief Provides a unique ID for a value reported by a Z-Wave device. * \ingroup ValueID @@ -59,300 +72,294 @@ namespace OpenZWave * The packing of the ID is such that a list of Values sorted by ValueID * will be in a sensible order for display to the user. */ + class OPENZWAVE_EXPORT ValueID { - friend class Manager; - friend class Driver; - friend class Node; - friend class Group; - friend class CommandClass; - friend class Value; - friend class ValueStore; - friend class Notification; - friend class ManufacturerSpecific; - - public: - /** - * Value Genres - * The classification of a value to enable low level system or configuration parameters to be filtered by the application. - * \see GetGenre - */ - enum ValueGenre - { - ValueGenre_Basic = 0, /**< The 'level' as controlled by basic commands. Usually duplicated by another command class. */ - ValueGenre_User, /**< Basic values an ordinary user would be interested in. */ - ValueGenre_Config, /**< Device-specific configuration parameters. These cannot be automatically discovered via Z-Wave, and are usually described in the user manual instead. */ - ValueGenre_System, /**< Values of significance only to users who understand the Z-Wave protocol */ - ValueGenre_Count /**< A count of the number of genres defined. Not to be used as a genre itself. */ - }; - - /** - * Value Types - * The type of data represented by the value object. - * \see GetType - */ - enum ValueType - { - ValueType_Bool = 0, /**< Boolean, true or false */ - ValueType_Byte, /**< 8-bit unsigned value */ - ValueType_Decimal, /**< Represents a non-integer value as a string, to avoid floating point accuracy issues. */ - ValueType_Int, /**< 32-bit signed value */ - ValueType_List, /**< List from which one item can be selected */ - ValueType_Schedule, /**< Complex type used with the Climate Control Schedule command class */ - ValueType_Short, /**< 16-bit signed value */ - ValueType_String, /**< Text string */ - ValueType_Button, /**< A write-only value that is the equivalent of pressing a button to send a command to a device */ - ValueType_Raw, /**< A collection of bytes */ - ValueType_BitSet, /**< A collection of Bits */ - ValueType_Max = ValueType_BitSet /**< The highest-number type defined. Not to be used as a type itself. */ - }; - - /** - * Get the Home ID of the driver that controls the node containing the value. - * \return the Home ID. - */ - uint32 GetHomeId()const + public: + /** + * Value Genres + * The classification of a value to enable low level system or configuration parameters to be filtered by the application. + * \see GetGenre + */ + enum ValueGenre + { + ValueGenre_Basic = 0, /**< The 'level' as controlled by basic commands. Usually duplicated by another command class. */ + ValueGenre_User, /**< Basic values an ordinary user would be interested in. */ + ValueGenre_Config, /**< Device-specific configuration parameters. These cannot be automatically discovered via Z-Wave, and are usually described in the user manual instead. */ + ValueGenre_System, /**< Values of significance only to users who understand the Z-Wave protocol */ + ValueGenre_Count /**< A count of the number of genres defined. Not to be used as a genre itself. */ + }; + + /** + * Value Types + * The type of data represented by the value object. + * \see GetType + */ + enum ValueType + { + ValueType_Bool = 0, /**< Boolean, true or false */ + ValueType_Byte, /**< 8-bit unsigned value */ + ValueType_Decimal, /**< Represents a non-integer value as a string, to avoid floating point accuracy issues. */ + ValueType_Int, /**< 32-bit signed value */ + ValueType_List, /**< List from which one item can be selected */ + ValueType_Schedule, /**< Complex type used with the Climate Control Schedule command class */ + ValueType_Short, /**< 16-bit signed value */ + ValueType_String, /**< Text string */ + ValueType_Button, /**< A write-only value that is the equivalent of pressing a button to send a command to a device */ + ValueType_Raw, /**< A collection of bytes */ + ValueType_BitSet, /**< A collection of Bits */ + ValueType_Max = ValueType_BitSet /**< The highest-number type defined. Not to be used as a type itself. */ + }; + + /** + * Get the Home ID of the driver that controls the node containing the value. + * \return the Home ID. + */ + uint32 GetHomeId() const { return m_homeId; } - /** - * Get the Home ID of the driver that controls the node containing the value. - * \return the node id. - */ - uint8 GetNodeId()const + /** + * Get the Home ID of the driver that controls the node containing the value. + * \return the node id. + */ + uint8 GetNodeId() const { - return( (uint8)( (m_id & 0xff000000) >> 24 ) ); + return ((uint8) ((m_id & 0xff000000) >> 24)); } - /** - * Get the genre of the value. The genre classifies a value to enable - * low-level system or configuration parameters to be filtered out by the application - * \return the value's genre. - * \see ValueGenre - */ - ValueGenre GetGenre()const + /** + * Get the genre of the value. The genre classifies a value to enable + * low-level system or configuration parameters to be filtered out by the application + * \return the value's genre. + * \see ValueGenre + */ + ValueGenre GetGenre() const { - return( (ValueGenre)( (m_id & 0x00c00000) >> 22 ) ); + return ((ValueGenre) ((m_id & 0x00c00000) >> 22)); } - /** - * Get the Z-Wave command class that created and manages this value. Knowledge of - * command classes is not required to use OpenZWave, but this information is - * exposed in case it is of interest. - * \return the value's command class. - */ - uint8 GetCommandClassId()const + /** + * Get the genre of the value as a String. The genre classifies a value to enable + * low-level system or configuration parameters to be filtered out by the application + * \return the value's genre. + * \see ValueGenre, ValueID::GetGenre + */ + string GetGenreAsString() const; + + /** + * Get the Z-Wave command class that created and manages this value. Knowledge of + * command classes is not required to use OpenZWave, but this information is + * exposed in case it is of interest. + * \return the value's command class. + */ + uint8 GetCommandClassId() const { - return( (uint8)( (m_id & 0x003fc000) >> 14 ) ); + return ((uint8) ((m_id & 0x003fc000) >> 14)); } - /** - * Get the command class instance of this value. It is possible for there to be - * multiple instances of a command class, although currently it appears that - * only the SensorMultilevel command class ever does this. Knowledge of - * instances and command classes is not required to use OpenZWave, but this - * information is exposed in case it is of interest. - * \return the instance of the value's command class. - */ - uint8 GetInstance()const + /** + * Get the command class instance of this value. It is possible for there to be + * multiple instances of a command class, although currently it appears that + * only the SensorMultilevel command class ever does this. Knowledge of + * instances and command classes is not required to use OpenZWave, but this + * information is exposed in case it is of interest. + * \return the instance of the value's command class. + */ + uint8 GetInstance() const { - return( (uint8)( ( (m_id & 0xff0) ) >> 4 ) ); + return ((uint8) (((m_id & 0xff0)) >> 4)); } - /** - * Get the value index. The index is used to identify one of multiple - * values created and managed by a command class. In the case of configurable - * parameters (handled by the configuration command class), the index is the - * same as the parameter ID. Knowledge of command classes is not required - * to use OpenZWave, but this information is exposed in case it is of interest. - * \return the value index within the command class. - */ - uint16 GetIndex()const + /** + * Get the value index. The index is used to identify one of multiple + * values created and managed by a command class. In the case of configurable + * parameters (handled by the configuration command class), the index is the + * same as the parameter ID. Knowledge of command classes is not required + * to use OpenZWave, but this information is exposed in case it is of interest. + * \return the value index within the command class. + */ + uint16 GetIndex() const { - return( (uint16)( (m_id1 & 0xFFFF0000) >> 16 ) ); + return ((uint16) ((m_id1 & 0xFFFF0000) >> 16)); } - /** - * Get the type of the value. The type describes the data held by the value - * and enables the user to select the correct value accessor method in the - * Manager class. - * \return the value's type. - * \see ValueType, Manager::GetValueAsBool, Manager::GetValueAsByte, Manager::GetValueAsFloat, Manager::GetValueAsInt, Manager::GetValueAsShort, Manager::GetValueAsString, Manager::GetValueListSelection. - */ - ValueType GetType()const + /** + * Get the type of the value. The type describes the data held by the value + * and enables the user to select the correct value accessor method in the + * Manager class. + * \return the value's type. + * \see ValueType, Manager::GetValueAsBool, Manager::GetValueAsByte, Manager::GetValueAsFloat, Manager::GetValueAsInt, Manager::GetValueAsShort, Manager::GetValueAsString, Manager::GetValueListSelection. + */ + ValueType GetType() const { - return( (ValueType)( m_id & 0x0000000f ) ); + return ((ValueType) (m_id & 0x0000000f)); } - /** - * Get a 64Bit Integer that represents this ValueID. This Integer is not guaranteed to be the same - * across restarts of OpenZWave. - * \return a uint64 integer - */ - uint64 GetId()const + /** + * Get the type of the value as a String. The type describes the data held by the value + * and enables the user to select the correct value accessor method in the + * Manager class. + * \return the value's type. + * \see ValueType, Manager::GetValueAsBool, Manager::GetValueAsByte, Manager::GetValueAsFloat, Manager::GetValueAsInt, Manager::GetValueAsShort, Manager::GetValueAsString, Manager::GetValueListSelection, ValueID::GetType + */ + string GetTypeAsString() const; + + /** + * Get a 64Bit Integer that represents this ValueID. This Integer is not guaranteed to be the same + * across restarts of OpenZWave. + * \return a uint64 integer + */ + uint64 GetId() const { - return (uint64) ( ( (uint64)m_id1 << 32 ) | m_id ); + return (uint64) (((uint64) m_id1 << 32) | m_id); } - // Comparison Operators - bool operator == ( ValueID const& _other )const{ return( ( m_homeId == _other.m_homeId ) && ( m_id == _other.m_id ) && ( m_id1 == _other.m_id1 ) ); } - bool operator != ( ValueID const& _other )const{ return( ( m_homeId != _other.m_homeId ) || ( m_id != _other.m_id ) || ( m_id1 != _other.m_id1 ) ); } - bool operator < ( ValueID const& _other )const - { - if( m_homeId == _other.m_homeId ) + // Comparison Operators + bool operator ==(ValueID const& _other) const + { + return ((m_homeId == _other.m_homeId) && (m_id == _other.m_id) && (m_id1 == _other.m_id1)); + } + bool operator !=(ValueID const& _other) const { - if( m_id == _other.m_id ) + return ((m_homeId != _other.m_homeId) || (m_id != _other.m_id) || (m_id1 != _other.m_id1)); + } + bool operator <(ValueID const& _other) const + { + if (m_homeId == _other.m_homeId) { - return( m_id1 < _other.m_id1 ); + if (m_id == _other.m_id) + { + return (m_id1 < _other.m_id1); + } + else + { + return (m_id < _other.m_id); + } } else { - return( m_id < _other.m_id ); + return (m_homeId < _other.m_homeId); } } - else - { - return( m_homeId < _other.m_homeId ); - } - } - bool operator > ( ValueID const& _other )const - { - if( m_homeId == _other.m_homeId ) + bool operator >(ValueID const& _other) const { - if( m_id == _other.m_id ) + if (m_homeId == _other.m_homeId) { - return( m_id1 > _other.m_id1 ); + if (m_id == _other.m_id) + { + return (m_id1 > _other.m_id1); + } + else + { + return (m_id > _other.m_id); + } } else { - return( m_id > _other.m_id ); + return (m_homeId > _other.m_homeId); } } - else + + /** + * Construct a value ID from its component parts. + * This method is public only to allow ValueIDs to be saved and recreated by the application. + * Only ValueIDs that have been reported by OpenZWave notifications should ever be used. + * \param _homeId Home ID of the PC Z-Wave Controller that manages the device. + * \param _nodeId Node ID of the device reporting the value. + * \param _genre classification of the value to enable low level system or configuration parameters to be filtered out. + * \param _commandClassId ID of command class that creates and manages this value. + * \param _instance Instance index of the command class. + * \param _valueIndex Index of the value within all the values created by the command class instance. + * \param _type Type of value (bool, byte, string etc). + * \return The ValueID. + * \see ValueID + */ + ValueID(uint32 const _homeId, uint8 const _nodeId, ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex, ValueType const _type) : + m_homeId(_homeId) { - return( m_homeId > _other.m_homeId ); + m_id = (((uint32) _nodeId) << 24) | (((uint32) _genre) << 22) | (((uint32) _commandClassId) << 14) | (((uint32) (_instance & 0xFF)) << 4) | ((uint32) _type); + m_id1 = (((uint32) _valueIndex) << 16); } - } - /** - * Construct a value ID from its component parts. - * This method is public only to allow ValueIDs to be saved and recreated by the application. - * Only ValueIDs that have been reported by OpenZWave notifications should ever be used. - * \param _homeId Home ID of the PC Z-Wave Controller that manages the device. - * \param _nodeId Node ID of the device reporting the value. - * \param _genre classification of the value to enable low level system or configuration parameters to be filtered out. - * \param _commandClassId ID of command class that creates and manages this value. - * \param _instance Instance index of the command class. - * \param _valueIndex Index of the value within all the values created by the command class instance. - * \param _type Type of value (bool, byte, string etc). - * \return The ValueID. - * \see ValueID - */ - ValueID - ( - uint32 const _homeId, - uint8 const _nodeId, - ValueGenre const _genre, - uint8 const _commandClassId, - uint8 const _instance, - uint16 const _valueIndex, - ValueType const _type - ): - m_homeId( _homeId ) - { - m_id = (((uint32)_nodeId)<<24) - | (((uint32)_genre)<<22) - | (((uint32)_commandClassId)<<14) - | (((uint32)(_instance & 0xFF))<<4) - | ((uint32)_type); - m_id1 = (((uint32)_valueIndex)<<16); - } + /* construct a ValueID based on the HomeID and the unit64 returned from GetID + * \param _homeId - The HomeID + * \param id - The ID returned from ValueID::GetID + * \see ValueID::GetId + */ + ValueID(uint32 _homeId, uint64 id) : + m_homeId(_homeId) + { + m_id = ((uint32) (id & 0xFFFFFFFF)); + m_id1 = (uint32) (id >> 32); + } - /* construct a ValueID based on the HomeID and the unit64 returned from GetID - * \param _homeId - The HomeID - * \param id - The ID returned from ValueID::GetID - * \see ValueID::GetId - */ - ValueID - ( - uint32 _homeId, - uint64 id - ): - m_homeId(_homeId) - { - m_id = ((uint32)(id & 0xFFFFFFFF)); - m_id1 = (uint32)(id >> 32); - } - private: - // Construct a value id for use in notifications - ValueID( uint32 const _homeId, uint8 const _nodeId ): - m_id1( 0 ), - m_homeId( _homeId ) + // Construct a value id for use in notifications + ValueID(uint32 const _homeId, uint8 const _nodeId) : + m_id1(0), m_homeId(_homeId) { - m_id = ((uint32)_nodeId)<<24; + m_id = ((uint32) _nodeId) << 24; } - ValueID( uint32 const _homeId, uint8 const _nodeId, uint32 const _instance ): - m_homeId( _homeId ) - { - m_id = (((uint32)_nodeId)<<24) | (((uint32)_instance) << 4); + ValueID(uint32 const _homeId, uint8 const _nodeId, uint32 const _instance) : + m_homeId(_homeId) + { + m_id = (((uint32) _nodeId) << 24) | (((uint32) _instance) << 4); m_id1 = 0; } - // Default constructor - ValueID(): - m_id(0), - m_id1(0), - m_homeId(0) + // Default constructor + ValueID() : + m_id(0), m_id1(0), m_homeId(0) { } - // Not all parts of the ValueID are necessary to uniquely identify the value. In the case of a - // Node's ValueStore, we can ignore the home ID, node ID, genre and type and still be left with - // a unique integer than can be used as a key to look up values. The two GetValueStoreKey methods - // below are helpers to enable command classes to easily access their values from the ValueStore. - - // Get the key from our own m_id - uint32 GetValueStoreKey()const - { - /* 0xIIIICCii - * I = Index - * C = CC - * i = Instance - */ - /* CC Index Instance */ - return ( ( ( m_id & 0x003fc000 ) >> 6) | ( m_id1 & 0xffff0000 ) | ( ( m_id & 0xFF0) >> 4 ) ); - } + // Not all parts of the ValueID are necessary to uniquely identify the value. In the case of a + // Node's ValueStore, we can ignore the home ID, node ID, genre and type and still be left with + // a unique integer than can be used as a key to look up values. The two GetValueStoreKey methods + // below are helpers to enable command classes to easily access their values from the ValueStore. - // Generate a key from its component parts - static uint32 GetValueStoreKey( uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex ) - { + // Get the key from our own m_id + uint32 GetValueStoreKey() const + { + /* 0xIIIICCii + * I = Index + * C = CC + * i = Instance + */ + /* CC Index Instance */ + return (((m_id & 0x003fc000) >> 6) | (m_id1 & 0xffff0000) | ((m_id & 0xFF0) >> 4)); + } - uint32 key = (((uint32)_instance)) - | (((uint32)_commandClassId)<<8) - | (((uint32)(_valueIndex & 0xFFFF))<<16); - - return key; - } + // Generate a key from its component parts + static uint32 GetValueStoreKey(uint8 const _commandClassId, uint8 const _instance, uint16 const _valueIndex) + { + + uint32 key = (((uint32) _instance)) | (((uint32) _commandClassId) << 8) | (((uint32) (_valueIndex & 0xFFFF)) << 16); + + return key; + } + + private: + + // ID Packing: + // Bits + // 24-31: 8 bits. Node ID of device + // 22-23: 2 bits. genre of value (see ValueGenre enum). + // 14-21: 8 bits. ID of command class that created and manages this value. + // 12-13 Unused. + // 04-11: 8 bits. Instance of the Value + // 00-03: 4 bits. Type of value (bool, byte, string etc). + uint32 m_id; + + // ID1 Packing: + // Bits + // 16-31 16 bits. Instance Index of the command class. + uint32 m_id1; - // ID Packing: - // Bits - // 24-31: 8 bits. Node ID of device - // 22-23: 2 bits. genre of value (see ValueGenre enum). - // 14-21: 8 bits. ID of command class that created and manages this value. - // 12-13 Unused. - // 04-11: 8 bits. Instance of the Value - // 00-03: 4 bits. Type of value (bool, byte, string etc). - uint32 m_id; - - // ID1 Packing: - // Bits - // 16-31 16 bits. Instance Index of the command class. - uint32 m_id1; - - // Unique PC interface identifier - uint32 m_homeId; + // Unique PC interface identifier + uint32 m_homeId; }; } // namespace OpenZWave diff --git a/cpp/src/value_classes/ValueInt.cpp b/cpp/src/value_classes/ValueInt.cpp index 64e46c08b6..59e94e560a 100644 --- a/cpp/src/value_classes/ValueInt.cpp +++ b/cpp/src/value_classes/ValueInt.cpp @@ -34,153 +34,120 @@ #include "Manager.h" #include -using namespace OpenZWave; - +namespace OpenZWave +{ + namespace Internal + { + namespace VC + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -ValueInt::ValueInt -( - uint32 const _homeId, - uint8 const _nodeId, - ValueID::ValueGenre const _genre, - uint8 const _commandClassId, - uint8 const _instance, - uint16 const _index, - string const& _label, - string const& _units, - bool const _readOnly, - bool const _writeOnly, - int32 const _value, - uint8 const _pollIntensity -): - Value( _homeId, _nodeId, _genre, _commandClassId, _instance, _index, ValueID::ValueType_Int, _label, _units, _readOnly, _writeOnly, false, _pollIntensity ), - m_value( _value ), - m_valueCheck( 0 ) -{ - m_min = INT_MIN; - m_max = INT_MAX; -} + ValueInt::ValueInt(uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, int32 const _value, uint8 const _pollIntensity) : + Value(_homeId, _nodeId, _genre, _commandClassId, _instance, _index, ValueID::ValueType_Int, _label, _units, _readOnly, _writeOnly, false, _pollIntensity), m_value(_value), m_valueCheck(0) + { + m_min = INT_MIN; + m_max = INT_MAX; + } //----------------------------------------------------------------------------- // // Constructor (from XML) //----------------------------------------------------------------------------- -ValueInt::ValueInt -( -): - Value(), - m_value( 0 ), - m_valueCheck( 0 ) - -{ - m_min = INT_MIN; - m_max = INT_MAX; -} - -string const ValueInt::GetAsString -( -) const -{ - stringstream ss; - ss << GetValue(); - return ss.str(); -} - -bool ValueInt::SetFromString -( - string const& _value -) -{ - int32 val = atoi( _value.c_str() ); - return Set( val ); -} + ValueInt::ValueInt() : + Value(), m_value(0), m_valueCheck(0) + + { + m_min = INT_MIN; + m_max = INT_MAX; + } + + std::string const ValueInt::GetAsString() const + { + stringstream ss; + ss << GetValue(); + return ss.str(); + } + + bool ValueInt::SetFromString(string const& _value) + { + int32 val = atoi(_value.c_str()); + return Set(val); + } //----------------------------------------------------------------------------- // // Apply settings from XML //----------------------------------------------------------------------------- -void ValueInt::ReadXML -( - uint32 const _homeId, - uint8 const _nodeId, - uint8 const _commandClassId, - TiXmlElement const* _valueElement -) -{ - Value::ReadXML( _homeId, _nodeId, _commandClassId, _valueElement ); - - int intVal; - if( TIXML_SUCCESS == _valueElement->QueryIntAttribute( "value", &intVal ) ) - { - m_value = (int32)intVal; - } - else - { - Log::Write( LogLevel_Info, "Missing default integer value from xml configuration: node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex() ); - } -} + void ValueInt::ReadXML(uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement) + { + Value::ReadXML(_homeId, _nodeId, _commandClassId, _valueElement); + + int intVal; + if (TIXML_SUCCESS == _valueElement->QueryIntAttribute("value", &intVal)) + { + m_value = (int32) intVal; + } + else + { + Log::Write(LogLevel_Info, "Missing default integer value from xml configuration: node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex()); + } + } //----------------------------------------------------------------------------- // // Write ourselves to an XML document //----------------------------------------------------------------------------- -void ValueInt::WriteXML -( - TiXmlElement* _valueElement -) -{ - Value::WriteXML( _valueElement ); + void ValueInt::WriteXML(TiXmlElement* _valueElement) + { + Value::WriteXML(_valueElement); - char str[16]; - snprintf( str, sizeof(str), "%d", m_value ); - _valueElement->SetAttribute( "value", str ); -} + char str[16]; + snprintf(str, sizeof(str), "%d", m_value); + _valueElement->SetAttribute("value", str); + } //----------------------------------------------------------------------------- // // Set a new value in the device //----------------------------------------------------------------------------- -bool ValueInt::Set -( - int32 const _value -) -{ - // create a temporary copy of this value to be submitted to the Set() call and set its value to the function param - ValueInt* tempValue = new ValueInt( *this ); - tempValue->m_value = _value; + bool ValueInt::Set(int32 const _value) + { + // create a temporary copy of this value to be submitted to the Set() call and set its value to the function param + ValueInt* tempValue = new ValueInt(*this); + tempValue->m_value = _value; - // Set the value in the device. - bool ret = ((Value*)tempValue)->Set(); + // Set the value in the device. + bool ret = ((Value*) tempValue)->Set(); - // clean up the temporary value - delete tempValue; + // clean up the temporary value + delete tempValue; - return ret; -} + return ret; + } //----------------------------------------------------------------------------- // // A value in a device has been refreshed //----------------------------------------------------------------------------- -void ValueInt::OnValueRefreshed -( - int32 const _value -) -{ - switch( VerifyRefreshedValue( (void*) &m_value, (void*) &m_valueCheck, (void*) &_value, ValueID::ValueType_Int) ) - { - case 0: // value hasn't changed, nothing to do - break; - case 1: // value has changed (not confirmed yet), save _value in m_valueCheck - m_valueCheck = _value; - break; - case 2: // value has changed (confirmed), save _value in m_value - m_value = _value; - break; - case 3: // all three values are different, so wait for next refresh to try again - break; - } -} + void ValueInt::OnValueRefreshed(int32 const _value) + { + switch (VerifyRefreshedValue((void*) &m_value, (void*) &m_valueCheck, (void*) &_value, ValueID::ValueType_Int)) + { + case 0: // value hasn't changed, nothing to do + break; + case 1: // value has changed (not confirmed yet), save _value in m_valueCheck + m_valueCheck = _value; + break; + case 2: // value has changed (confirmed), save _value in m_value + m_value = _value; + break; + case 3: // all three values are different, so wait for next refresh to try again + break; + } + } + } // namespace VC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/value_classes/ValueInt.h b/cpp/src/value_classes/ValueInt.h index 1436492a3d..34f8c0f9aa 100644 --- a/cpp/src/value_classes/ValueInt.h +++ b/cpp/src/value_classes/ValueInt.h @@ -36,35 +36,43 @@ class TiXmlElement; namespace OpenZWave { - class Msg; - class Node; - - /** \brief Integer value sent to/received from a node. - * \ingroup ValueID - */ - class ValueInt: public Value + namespace Internal { - public: - ValueInt( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, int32 const _value, uint8 const _pollIntensity ); - ValueInt(); - virtual ~ValueInt(){} + namespace VC + { - bool Set( int32 const _value ); - void OnValueRefreshed( int32 const _value ); + /** \brief Integer value sent to/received from a node. + * \ingroup ValueID + */ + class ValueInt: public Value + { + public: + ValueInt(uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, int32 const _value, uint8 const _pollIntensity); + ValueInt(); + virtual ~ValueInt() + { + } - // From Value - virtual string const GetAsString() const; - virtual bool SetFromString( string const& _value ); - virtual void ReadXML( uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement ); - virtual void WriteXML( TiXmlElement* _valueElement ); + bool Set(int32 const _value); + void OnValueRefreshed(int32 const _value); - int32 GetValue()const{ return m_value; } + // From Value + virtual string const GetAsString() const; + virtual bool SetFromString(string const& _value); + virtual void ReadXML(uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement); + virtual void WriteXML(TiXmlElement* _valueElement); - private: - int32 m_value; // the current value - int32 m_valueCheck; // the previous value (used for double-checking spurious value reads) - }; + int32 GetValue() const + { + return m_value; + } + private: + int32 m_value; // the current value + int32 m_valueCheck; // the previous value (used for double-checking spurious value reads) + }; + } // namespace VC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/value_classes/ValueList.cpp b/cpp/src/value_classes/ValueList.cpp index 5f9fa03196..5433ba2de8 100644 --- a/cpp/src/value_classes/ValueList.cpp +++ b/cpp/src/value_classes/ValueList.cpp @@ -33,394 +33,346 @@ #include "Localization.h" #include -using namespace OpenZWave; - +namespace OpenZWave +{ + namespace Internal + { + namespace VC + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -ValueList::ValueList -( - uint32 const _homeId, - uint8 const _nodeId, - ValueID::ValueGenre const _genre, - uint8 const _commandClassId, - uint8 const _instance, - uint16 const _index, - string const& _label, - string const& _units, - bool const _readOnly, - bool const _writeOnly, - vector const& _items, - int32 const _valueIdx, - uint8 const _pollIntensity, - uint8 const _size // = 4 -): - Value( _homeId, _nodeId, _genre, _commandClassId, _instance, _index, ValueID::ValueType_List, _label, _units, _readOnly, _writeOnly, false, _pollIntensity ), - m_items( _items ), - m_valueIdx( _valueIdx ), - m_valueIdxCheck( 0 ), - m_size( _size ) -{ - for( vector::iterator it = m_items.begin(); it != m_items.end(); ++it ) - { - /* first what is currently in m_label is the default text for a Item, so set it */ - Localization::Get()->SetValueItemLabel(_commandClassId, _index, -1, it->m_value, it->m_label, ""); - /* now set to the Localized Value */ - it->m_label = Localization::Get()->GetValueItemLabel(_commandClassId, _index, -1, it->m_value); - } -} + ValueList::ValueList(uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, vector const& _items, int32 const _valueIdx, uint8 const _pollIntensity, uint8 const _size // = 4 + ) : + Value(_homeId, _nodeId, _genre, _commandClassId, _instance, _index, ValueID::ValueType_List, _label, _units, _readOnly, _writeOnly, false, _pollIntensity), m_items(_items), m_valueIdx(_valueIdx), m_valueIdxCheck(0), m_size(_size) + { + for (vector::iterator it = m_items.begin(); it != m_items.end(); ++it) + { + /* first what is currently in m_label is the default text for a Item, so set it */ + Localization::Get()->SetValueItemLabel(m_id.GetNodeId(), _commandClassId, _index, -1, it->m_value, it->m_label, ""); + /* now set to the Localized Value */ + it->m_label = Localization::Get()->GetValueItemLabel(m_id.GetNodeId(), _commandClassId, _index, -1, it->m_value); + } + } //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -ValueList::ValueList -( -): - Value(), - m_items( ), - m_valueIdx(), - m_valueIdxCheck( 0 ), - m_size(0) -{ + ValueList::ValueList() : + Value(), m_items(), m_valueIdx(), m_valueIdxCheck(0), m_size(0) + { -} + } //----------------------------------------------------------------------------- // // Apply settings from XML //----------------------------------------------------------------------------- -void ValueList::ReadXML -( - uint32 const _homeId, - uint8 const _nodeId, - uint8 const _commandClassId, - TiXmlElement const* _valueElement -) -{ - Value::ReadXML( _homeId, _nodeId, _commandClassId, _valueElement ); - - // Get size of values - int intSize; - if ( TIXML_SUCCESS == _valueElement->QueryIntAttribute( "size", &intSize ) ) - { - if( intSize == 1 || intSize == 2 || intSize == 4 ) - { - m_size = intSize; - } - else - { - Log::Write( LogLevel_Warning, "Value size is invalid (%d). Only 1, 2 & 4 supported for node %d, class 0x%02x, instance %d, index %d", intSize, _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex() ); - } - } - else - { - Log::Write( LogLevel_Warning, "Value list size is not set, assuming 4 bytes for node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex() ); - } - - TiXmlElement const* itemElement = _valueElement->FirstChildElement(); - - bool shouldclearlist = true; - while( itemElement ) - { - char const* str = itemElement->Value(); - if( str && !strcmp( str, "Item" ) ) - { - /* clear the existing list, if we have Item entries. (static list entries are created in the constructor - * here, we load up any localized labels - */ - if (shouldclearlist) { - m_items.clear(); - shouldclearlist = false; - } - - bool AddItem = true; - char const* labelStr = itemElement->Attribute( "label" ); - char const* lang = ""; - if (itemElement->Attribute( "lang" )) { - lang = itemElement->Attribute( "lang" ); - AddItem = false; - } else { - AddItem = true; - } - int value = 0; - if (itemElement->QueryIntAttribute( "value", &value ) != TIXML_SUCCESS) { - Log::Write( LogLevel_Warning, "Item value %s is wrong type or does not exist in xml configuration for node %d, class 0x%02x, instance %d, index %d", labelStr, _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex() ); - continue; - } - if(( m_size == 1 && value > 255 ) || ( m_size == 2 && value > 65535) ) + void ValueList::ReadXML(uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement) { - Log::Write( LogLevel_Warning, "Item value %s is incorrect size in xml configuration for node %d, class 0x%02x, instance %d, index %d", labelStr, _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex() ); - } - else - { - Localization::Get()->SetValueItemLabel(m_id.GetCommandClassId(), m_id.GetIndex(), -1, value, labelStr, lang); - if (AddItem) { - Item item; - item.m_label = labelStr; - item.m_value = value; - m_items.push_back( item ); + Value::ReadXML(_homeId, _nodeId, _commandClassId, _valueElement); + + // Get size of values + int intSize; + if (TIXML_SUCCESS == _valueElement->QueryIntAttribute("size", &intSize)) + { + if (intSize == 1 || intSize == 2 || intSize == 4) + { + m_size = intSize; + } + else + { + Log::Write(LogLevel_Warning, "Value size is invalid (%d). Only 1, 2 & 4 supported for node %d, class 0x%02x, instance %d, index %d", intSize, _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex()); + } + } + else + { + Log::Write(LogLevel_Warning, "Value list size is not set, assuming 4 bytes for node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex()); } - } - } - - itemElement = itemElement->NextSiblingElement(); - } - /* setup any Localization now as we should have read all available languages already */ - for( vector::iterator it = m_items.begin(); it != m_items.end(); ++it ) - { - it->m_label = Localization::Get()->GetValueItemLabel(m_id.GetCommandClassId(), m_id.GetIndex(), -1, it->m_value); - } - - - // Set the value - bool valSet = false; - int intVal; - m_valueIdx = 0; - if ( TIXML_SUCCESS == _valueElement->QueryIntAttribute( "value", &intVal ) ) - { - valSet = true; - intVal = GetItemIdxByValue( intVal ); - if( intVal != -1 ) - { - m_valueIdx = (int32)intVal; - } - else - { - Log::Write( LogLevel_Warning, "Value is not found in xml configuration for node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex() ); - } - } - - // Set the index - bool indSet = false; - int intInd = 0; - if ( TIXML_SUCCESS == _valueElement->QueryIntAttribute( "vindex", &intInd ) ) - { - indSet = true; - if( intInd >= 0 && intInd < (int32)m_items.size() ) - { - m_valueIdx = (int32)intInd; - } - else - { - Log::Write( LogLevel_Warning, "Vindex is out of range for index in xml configuration for node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex() ); - } - } - if( !valSet && !indSet ) - { - Log::Write( LogLevel_Warning, "Missing default list value or vindex from xml configuration: node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex() ); - } + TiXmlElement const* itemElement = _valueElement->FirstChildElement(); + + bool shouldclearlist = true; + while (itemElement) + { + char const* str = itemElement->Value(); + if (str && !strcmp(str, "Item")) + { + /* clear the existing list, if we have Item entries. (static list entries are created in the constructor + * here, we load up any localized labels + */ + if (shouldclearlist) + { + m_items.clear(); + shouldclearlist = false; + } + + bool AddItem = true; + char const* labelStr = itemElement->Attribute("label"); + char const* lang = ""; + if (itemElement->Attribute("lang")) + { + lang = itemElement->Attribute("lang"); + AddItem = false; + } + else + { + AddItem = true; + } + int value = 0; + if (itemElement->QueryIntAttribute("value", &value) != TIXML_SUCCESS) + { + Log::Write(LogLevel_Warning, "Item value %s is wrong type or does not exist in xml configuration for node %d, class 0x%02x, instance %d, index %d", labelStr, _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex()); + continue; + } + if ((m_size == 1 && value > 255) || (m_size == 2 && value > 65535)) + { + Log::Write(LogLevel_Warning, "Item value %s is incorrect size in xml configuration for node %d, class 0x%02x, instance %d, index %d", labelStr, _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex()); + } + else + { + Localization::Get()->SetValueItemLabel(m_id.GetNodeId(), m_id.GetCommandClassId(), m_id.GetIndex(), -1, value, labelStr, lang); + if (AddItem) + { + Item item; + item.m_label = labelStr; + item.m_value = value; + m_items.push_back(item); + } + } + } + + itemElement = itemElement->NextSiblingElement(); + } + /* setup any Localization now as we should have read all available languages already */ + for (vector::iterator it = m_items.begin(); it != m_items.end(); ++it) + { + it->m_label = Localization::Get()->GetValueItemLabel(m_id.GetNodeId(), m_id.GetCommandClassId(), m_id.GetIndex(), -1, it->m_value); + } + // Set the value + bool valSet = false; + int intVal; + m_valueIdx = 0; + if (TIXML_SUCCESS == _valueElement->QueryIntAttribute("value", &intVal)) + { + valSet = true; + intVal = GetItemIdxByValue(intVal); + if (intVal != -1) + { + m_valueIdx = (int32) intVal; + } + else + { + Log::Write(LogLevel_Warning, "Value is not found in xml configuration for node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex()); + } + } + // Set the index + bool indSet = false; + int intInd = 0; + if (TIXML_SUCCESS == _valueElement->QueryIntAttribute("vindex", &intInd)) + { + indSet = true; + if (intInd >= 0 && intInd < (int32) m_items.size()) + { + m_valueIdx = (int32) intInd; + } + else + { + Log::Write(LogLevel_Warning, "Vindex is out of range for index in xml configuration for node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex()); + } + } + if (!valSet && !indSet) + { + Log::Write(LogLevel_Warning, "Missing default list value or vindex from xml configuration: node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex()); + } -} + } //----------------------------------------------------------------------------- // // Write ourselves to an XML document //----------------------------------------------------------------------------- -void ValueList::WriteXML -( - TiXmlElement* _valueElement -) -{ - Value::WriteXML( _valueElement ); + void ValueList::WriteXML(TiXmlElement* _valueElement) + { + Value::WriteXML(_valueElement); - char str[16]; - snprintf( str, sizeof(str), "%d", m_valueIdx ); - _valueElement->SetAttribute( "vindex", str ); + char str[16]; + snprintf(str, sizeof(str), "%d", m_valueIdx); + _valueElement->SetAttribute("vindex", str); - snprintf( str, sizeof(str), "%d", m_size ); - _valueElement->SetAttribute( "size", str ); + snprintf(str, sizeof(str), "%d", m_size); + _valueElement->SetAttribute("size", str); - for( vector::iterator it = m_items.begin(); it != m_items.end(); ++it ) - { - TiXmlElement* pItemElement = new TiXmlElement( "Item" ); - pItemElement->SetAttribute( "label", (*it).m_label.c_str() ); + for (vector::iterator it = m_items.begin(); it != m_items.end(); ++it) + { + TiXmlElement* pItemElement = new TiXmlElement("Item"); + pItemElement->SetAttribute("label", (*it).m_label.c_str()); - snprintf( str, sizeof(str), "%d", (*it).m_value ); - pItemElement->SetAttribute( "value", str ); + snprintf(str, sizeof(str), "%d", (*it).m_value); + pItemElement->SetAttribute("value", str); - _valueElement->LinkEndChild( pItemElement ); - } -} + _valueElement->LinkEndChild(pItemElement); + } + } //----------------------------------------------------------------------------- // // Set a new value in the device, selected by item index //----------------------------------------------------------------------------- -bool ValueList::SetByValue -( - int32 const _value -) -{ - // create a temporary copy of this value to be submitted to the Set() call and set its value to the function param - ValueList* tempValue = new ValueList( *this ); - tempValue->m_valueIdx = _value; + bool ValueList::SetByValue(int32 const _value) + { + // create a temporary copy of this value to be submitted to the Set() call and set its value to the function param + ValueList* tempValue = new ValueList(*this); + tempValue->m_valueIdx = _value; - // Set the value in the device. - bool ret = ((Value*)tempValue)->Set(); + // Set the value in the device. + bool ret = ((Value*) tempValue)->Set(); - // clean up the temporary value - delete tempValue; + // clean up the temporary value + delete tempValue; - return ret; -} + return ret; + } //----------------------------------------------------------------------------- // // Set a new value in the device, selected by item label //----------------------------------------------------------------------------- -bool ValueList::SetByLabel -( - string const& _label -) -{ - // Ensure the value is one of the options - int index = GetItemIdxByLabel( _label ); - if( index < 0 ) - { - // Item not found - return false; - } + bool ValueList::SetByLabel(string const& _label) + { + // Ensure the value is one of the options + int index = GetItemIdxByLabel(_label); + if (index < 0) + { + // Item not found + return false; + } - return SetByValue( index ); -} + return SetByValue(index); + } //----------------------------------------------------------------------------- // // A value in a device has been refreshed //----------------------------------------------------------------------------- -void ValueList::OnValueRefreshed -( - int32 const _value -) -{ - // Ensure the value is one of the options - int32 index = GetItemIdxByValue( _value ); - if( index < 0 ) - { - // Item not found - return; - } + void ValueList::OnValueRefreshed(int32 const _value) + { + // Ensure the value is one of the options + int32 index = GetItemIdxByValue(_value); + if (index < 0) + { + // Item not found + return; + } - switch( VerifyRefreshedValue( (void*) &m_valueIdx, (void*) &m_valueIdxCheck, (void*) &index, ValueID::ValueType_List) ) - { - case 0: // value hasn't changed, nothing to do - break; - case 1: // value has changed (not confirmed yet), save _value in m_valueCheck - m_valueIdxCheck = index; - break; - case 2: // value has changed (confirmed), save _value in m_value - m_valueIdx = index; - break; - case 3: // all three values are different, so wait for next refresh to try again - break; - } -} + switch (VerifyRefreshedValue((void*) &m_valueIdx, (void*) &m_valueIdxCheck, (void*) &index, ValueID::ValueType_List)) + { + case 0: // value hasn't changed, nothing to do + break; + case 1: // value has changed (not confirmed yet), save _value in m_valueCheck + m_valueIdxCheck = index; + break; + case 2: // value has changed (confirmed), save _value in m_value + m_valueIdx = index; + break; + case 3: // all three values are different, so wait for next refresh to try again + break; + } + } //----------------------------------------------------------------------------- // // Get the index of an item from its label //----------------------------------------------------------------------------- -int32 ValueList::GetItemIdxByLabel -( - string const& _label -) const -{ - for( int32 i=0; i<(int32)m_items.size(); ++i ) - { - if( _label == m_items[i].m_label ) - { - return i; - } - } + int32 ValueList::GetItemIdxByLabel(string const& _label) const + { + for (int32 i = 0; i < (int32) m_items.size(); ++i) + { + if (_label == m_items[i].m_label) + { + return i; + } + } - return -1; -} + return -1; + } //----------------------------------------------------------------------------- // // Get the index of an item from its value //----------------------------------------------------------------------------- -int32 ValueList::GetItemIdxByValue -( - int32 const _value -) const -{ - for( int32 i=0; i<(int32)m_items.size(); ++i ) - { - if( _value == m_items[i].m_value ) - { - return i; - } - } + int32 ValueList::GetItemIdxByValue(int32 const _value) const + { + for (int32 i = 0; i < (int32) m_items.size(); ++i) + { + if (_value == m_items[i].m_value) + { + return i; + } + } - return -1; -} + return -1; + } //----------------------------------------------------------------------------- // // Fill a vector with the item labels //----------------------------------------------------------------------------- -bool ValueList::GetItemLabels -( - vector* o_items -) -{ - if( o_items ) - { - for( vector::iterator it = m_items.begin(); it != m_items.end(); ++it ) - { - o_items->push_back( (*it).m_label ); - } - - return true; - } + bool ValueList::GetItemLabels(vector* o_items) + { + if (o_items) + { + for (vector::iterator it = m_items.begin(); it != m_items.end(); ++it) + { + o_items->push_back((*it).m_label); + } + + return true; + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Fill a vector with the item values //----------------------------------------------------------------------------- -bool ValueList::GetItemValues -( - vector* o_values -) -{ - if( o_values ) - { - for( vector::iterator it = m_items.begin(); it != m_items.end(); ++it ) - { - o_values->push_back( (*it).m_value ); - } - - return true; - } + bool ValueList::GetItemValues(vector* o_values) + { + if (o_values) + { + for (vector::iterator it = m_items.begin(); it != m_items.end(); ++it) + { + o_values->push_back((*it).m_value); + } + + return true; + } - return false; -} + return false; + } //----------------------------------------------------------------------------- // // Get the Item at the Currently selected Index //----------------------------------------------------------------------------- -ValueList::Item const *ValueList::GetItem() const { - try { - return &m_items.at(m_valueIdx); - } catch (const std::out_of_range& oor) { - Log::Write(LogLevel_Warning, "Invalid Index Set on ValueList: %s", oor.what()); - return NULL; - } -} - - - - - - + ValueList::Item const *ValueList::GetItem() const + { + try + { + return &m_items.at(m_valueIdx); + } + catch (const std::out_of_range& oor) + { + Log::Write(LogLevel_Warning, "Invalid Index Set on ValueList: %s", oor.what()); + return NULL; + } + } + } // namespace VC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/value_classes/ValueList.h b/cpp/src/value_classes/ValueList.h index 04114ac4ea..614bf77d43 100644 --- a/cpp/src/value_classes/ValueList.h +++ b/cpp/src/value_classes/ValueList.h @@ -37,58 +37,70 @@ class TiXmlElement; namespace OpenZWave { - class Msg; - class Node; - - /** \brief List of values sent to/received from a node. - * \ingroup ValueID - */ - class ValueList: public Value + namespace Internal { - public: - /** \brief An item (element) in the list of values. - */ - struct Item + namespace VC { - string m_label; - int32 m_value; - }; - - ValueList( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, vector const& _items, int32 const _valueIdx, uint8 const _pollIntensity, uint8 const _size = 4 ); - ValueList(); - virtual ~ValueList(){} - - bool SetByLabel( string const& _label ); - bool SetByValue( int32 const _value ); - - void OnValueRefreshed( int32 const _valueIdx ); - - // From Value - virtual string const GetAsString() const { return GetItem()->m_label; } - virtual bool SetFromString( string const& _value ) { return SetByLabel( _value ); } - virtual void ReadXML( uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement ); - virtual void WriteXML( TiXmlElement* _valueElement ); - - Item const* GetItem() const; - - int32 GetItemIdxByLabel( string const& _label ) const; - int32 GetItemIdxByValue( int32 const _value ) const; - - bool GetItemLabels( vector* o_items ); - bool GetItemValues( vector* o_values ); - - uint8 GetSize()const{ return m_size; } - - private: - vector m_items; - int32 m_valueIdx; // the current index in the m_items vector - int32 m_valueIdxCheck; // the previous index in the m_items vector (used for double-checking spurious value reads) - uint8 m_size; - }; + /** \brief List of values sent to/received from a node. + * \ingroup ValueID + */ + class ValueList: public Value + { + public: + /** \brief An item (element) in the list of values. + */ + struct Item + { + string m_label; + int32 m_value; + }; + + ValueList(uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, vector const& _items, int32 const _valueIdx, uint8 const _pollIntensity, uint8 const _size = 4); + ValueList(); + virtual ~ValueList() + { + } + + bool SetByLabel(string const& _label); + bool SetByValue(int32 const _value); + + void OnValueRefreshed(int32 const _valueIdx); + + // From Value + virtual string const GetAsString() const + { + return GetItem()->m_label; + } + virtual bool SetFromString(string const& _value) + { + return SetByLabel(_value); + } + virtual void ReadXML(uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement); + virtual void WriteXML(TiXmlElement* _valueElement); + + Item const* GetItem() const; + + int32 GetItemIdxByLabel(string const& _label) const; + int32 GetItemIdxByValue(int32 const _value) const; + + bool GetItemLabels(vector* o_items); + bool GetItemValues(vector* o_values); + + uint8 GetSize() const + { + return m_size; + } + + private: + vector m_items; + int32 m_valueIdx; // the current index in the m_items vector + int32 m_valueIdxCheck; // the previous index in the m_items vector (used for double-checking spurious value reads) + uint8 m_size; + }; + } // namespace VC + } // namespace Internal } // namespace OpenZWave #endif - - diff --git a/cpp/src/value_classes/ValueRaw.cpp b/cpp/src/value_classes/ValueRaw.cpp index f919f141ca..8c562a3220 100644 --- a/cpp/src/value_classes/ValueRaw.cpp +++ b/cpp/src/value_classes/ValueRaw.cpp @@ -32,257 +32,217 @@ #include "Manager.h" #include -using namespace OpenZWave; - +namespace OpenZWave +{ + namespace Internal + { + namespace VC + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -ValueRaw::ValueRaw -( - uint32 const _homeId, - uint8 const _nodeId, - ValueID::ValueGenre const _genre, - uint8 const _commandClassId, - uint8 const _instance, - uint16 const _index, - string const& _label, - string const& _units, - bool const _readOnly, - bool const _writeOnly, - uint8 const* _value, - uint8 const _length, - uint8 const _pollIntensity -): - Value( _homeId, _nodeId, _genre, _commandClassId, _instance, _index, ValueID::ValueType_Raw, _label, _units, _readOnly, _writeOnly, false, _pollIntensity ), - m_value( NULL ), - m_valueLength( _length ), - m_valueCheck ( NULL ), - m_valueCheckLength ( 0 ) -{ - m_value = new uint8[_length]; - memcpy( m_value, _value, _length ); - m_min = 0; - m_max = 0; -} + ValueRaw::ValueRaw(uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, uint8 const* _value, uint8 const _length, uint8 const _pollIntensity) : + Value(_homeId, _nodeId, _genre, _commandClassId, _instance, _index, ValueID::ValueType_Raw, _label, _units, _readOnly, _writeOnly, false, _pollIntensity), m_value( NULL), m_valueLength(_length), m_valueCheck( NULL), m_valueCheckLength(0) + { + m_value = new uint8[_length]; + memcpy(m_value, _value, _length); + m_min = 0; + m_max = 0; + } //----------------------------------------------------------------------------- // // Constructor (from XML) //----------------------------------------------------------------------------- -ValueRaw::ValueRaw -( -): - m_value( NULL ), - m_valueLength( 0 ), - m_valueCheck ( NULL ), - m_valueCheckLength ( 0 ) -{ - m_min = 0; - m_max = 0; -} + ValueRaw::ValueRaw() : + m_value( NULL), m_valueLength(0), m_valueCheck( NULL), m_valueCheckLength(0) + { + m_min = 0; + m_max = 0; + } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -ValueRaw::~ValueRaw -( -) -{ - delete [] m_value; - if ( m_valueCheck != NULL ) delete[] m_valueCheck; -} - -string const ValueRaw::GetAsString -( -) const -{ - string str = ""; - char bstr[10]; - - for( uint32 i=0; i= 256 ) - { - break; - } - if( index < m_valueLength ) - { - value[index] = (uint8)val; - } - index++; - if( ep != NULL && *ep == '\0' ) - { - break; - } - p = ep + 1; - } - - bool bRet = false; + ValueRaw::~ValueRaw() + { + delete[] m_value; + if (m_valueCheck != NULL) + delete[] m_valueCheck; + } - if ( index <= m_valueLength ) - { - bRet = Set( value, index ); - } + std::string const ValueRaw::GetAsString() const + { + string str = ""; + char bstr[10]; + + for (uint32 i = 0; i < m_valueLength; ++i) + { + if (i) + { + str += " "; + } + snprintf(bstr, sizeof(bstr), "0x%.2x", m_value[i]); + str += bstr; + } + + return str; + } - delete [] value; - return bRet; -} + bool ValueRaw::SetFromString(string const& _value) + { + char const* p = _value.c_str(); + uint8 index = 0; + uint8* value = new uint8[m_valueLength]; + while (1) + { + char *ep = NULL; + uint32 val = (uint32) strtol(p, &ep, 16); + if (p == ep || val >= 256) + { + break; + } + if (index < m_valueLength) + { + value[index] = (uint8) val; + } + index++; + if (ep != NULL && *ep == '\0') + { + break; + } + p = ep + 1; + } + + bool bRet = false; + + if (index <= m_valueLength) + { + bRet = Set(value, index); + } + + delete[] value; + return bRet; + } //----------------------------------------------------------------------------- // // Apply settings from XML //----------------------------------------------------------------------------- -void ValueRaw::ReadXML -( - uint32 const _homeId, - uint8 const _nodeId, - uint8 const _commandClassId, - TiXmlElement const* _valueElement -) -{ - Value::ReadXML( _homeId, _nodeId, _commandClassId, _valueElement ); - - int intVal; - if( TIXML_SUCCESS == _valueElement->QueryIntAttribute( "length", &intVal ) ) - { - m_valueLength = (uint8)intVal; - } - m_value = new uint8[m_valueLength]; - char const* str = _valueElement->Attribute( "value" ); - if( str ) - { - uint8 index = 0; - while( 1 ) - { - char *ep = NULL; - uint32 val = (uint32)strtol( str, &ep, 16 ); - if( str == ep || val >= 256 ) - { - break; - } - if( index < m_valueLength ) + void ValueRaw::ReadXML(uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement) { - m_value[index] = (uint8)val; + Value::ReadXML(_homeId, _nodeId, _commandClassId, _valueElement); + + int intVal; + if (TIXML_SUCCESS == _valueElement->QueryIntAttribute("length", &intVal)) + { + m_valueLength = (uint8) intVal; + } + m_value = new uint8[m_valueLength]; + char const* str = _valueElement->Attribute("value"); + if (str) + { + uint8 index = 0; + while (1) + { + char *ep = NULL; + uint32 val = (uint32) strtol(str, &ep, 16); + if (str == ep || val >= 256) + { + break; + } + if (index < m_valueLength) + { + m_value[index] = (uint8) val; + } + index++; + if (ep != NULL && *ep == '\0') + { + break; + } + str = ep + 1; + } + if (index > m_valueLength) + { + Log::Write(LogLevel_Info, "Data length mismatch for raw data. Got %d but expected %d.", index, m_valueLength); + } + } + else + { + Log::Write(LogLevel_Info, "Missing default raw value from xml configuration: node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex()); + } } - index++; - if( ep != NULL && *ep == '\0' ) - { - break; - } - str = ep + 1; - } - if( index > m_valueLength ) - { - Log::Write( LogLevel_Info, "Data length mismatch for raw data. Got %d but expected %d.", index, m_valueLength ); - } - } - else - { - Log::Write( LogLevel_Info, "Missing default raw value from xml configuration: node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex() ); - } -} //----------------------------------------------------------------------------- // // Write ourselves to an XML document //----------------------------------------------------------------------------- -void ValueRaw::WriteXML -( - TiXmlElement* _valueElement -) -{ - Value::WriteXML( _valueElement ); + void ValueRaw::WriteXML(TiXmlElement* _valueElement) + { + Value::WriteXML(_valueElement); - _valueElement->SetAttribute( "value", GetAsString().c_str() ); - char str[8]; - snprintf( str, sizeof(str), "%d", GetLength() ); - _valueElement->SetAttribute( "length", str ); -} + _valueElement->SetAttribute("value", GetAsString().c_str()); + char str[8]; + snprintf(str, sizeof(str), "%d", GetLength()); + _valueElement->SetAttribute("length", str); + } //----------------------------------------------------------------------------- // // Set a new value in the device //----------------------------------------------------------------------------- -bool ValueRaw::Set -( - uint8 const* _value, - uint8 const _length -) -{ - // create a temporary copy of this value to be submitted to the Set() call and set its value to the function param - ValueRaw* tempValue = new ValueRaw( *this ); - tempValue->m_value = new uint8[_length]; - memcpy( tempValue->m_value, _value, _length ); - tempValue->m_valueLength = _length; + bool ValueRaw::Set(uint8 const* _value, uint8 const _length) + { + // create a temporary copy of this value to be submitted to the Set() call and set its value to the function param + ValueRaw* tempValue = new ValueRaw(*this); + tempValue->m_value = new uint8[_length]; + memcpy(tempValue->m_value, _value, _length); + tempValue->m_valueLength = _length; - // Set the value in the device. - bool ret = ((Value*)tempValue)->Set(); + // Set the value in the device. + bool ret = ((Value*) tempValue)->Set(); - // clean up the temporary value - delete tempValue; + // clean up the temporary value + delete tempValue; - return ret; -} + return ret; + } //----------------------------------------------------------------------------- // // A value in a device has been refreshed //----------------------------------------------------------------------------- -void ValueRaw::OnValueRefreshed -( - uint8 const* _value, - uint8 const _length -) -{ - switch( VerifyRefreshedValue( (void*)m_value, (void*)m_valueCheck, (void*)_value, ValueID::ValueType_Raw, m_valueLength, m_valueCheckLength, _length ) ) - { - case 0: // value hasn't changed, nothing to do - break; - case 1: // value has changed (not confirmed yet), save _value in m_valueCheck - if( m_valueCheck != NULL ) - { - delete [] m_valueCheck; - } - m_valueCheck = new uint8[_length]; - m_valueCheckLength = _length; - memcpy( m_valueCheck, _value, _length ); - break; - case 2: // value has changed (confirmed), save _value in m_value - if( m_value != NULL ) - { - delete [] m_value; - } - m_value = new uint8[_length]; - m_valueLength = _length; - memcpy( m_value, _value, _length ); - break; - case 3: // all three values are different, so wait for next refresh to try again - break; - } -} + void ValueRaw::OnValueRefreshed(uint8 const* _value, uint8 const _length) + { + switch (VerifyRefreshedValue((void*) m_value, (void*) m_valueCheck, (void*) _value, ValueID::ValueType_Raw, m_valueLength, m_valueCheckLength, _length)) + { + case 0: // value hasn't changed, nothing to do + break; + case 1: // value has changed (not confirmed yet), save _value in m_valueCheck + if (m_valueCheck != NULL) + { + delete[] m_valueCheck; + } + m_valueCheck = new uint8[_length]; + m_valueCheckLength = _length; + memcpy(m_valueCheck, _value, _length); + break; + case 2: // value has changed (confirmed), save _value in m_value + if (m_value != NULL) + { + delete[] m_value; + } + m_value = new uint8[_length]; + m_valueLength = _length; + memcpy(m_value, _value, _length); + break; + case 3: // all three values are different, so wait for next refresh to try again + break; + } + } + } // namespace VC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/value_classes/ValueRaw.h b/cpp/src/value_classes/ValueRaw.h index f21d3be5aa..38e3da445b 100644 --- a/cpp/src/value_classes/ValueRaw.h +++ b/cpp/src/value_classes/ValueRaw.h @@ -36,41 +36,48 @@ class TiXmlElement; namespace OpenZWave { - class Msg; - class Node; - - /** \brief A collection of bytes sent to/received from a node. - * \ingroup ValueID - */ - class ValueRaw: public Value + namespace Internal { - public: - ValueRaw( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, uint8 const* _value, uint8 const _length, uint8 const _pollIntensity ); - ValueRaw(); - virtual ~ValueRaw(); + namespace VC + { - bool Set( uint8 const* _value, uint8 const _length ); - void OnValueRefreshed( uint8 const* _value, uint8 const _length ); + /** \brief A collection of bytes sent to/received from a node. + * \ingroup ValueID + */ + class ValueRaw: public Value + { + public: + ValueRaw(uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, uint8 const* _value, uint8 const _length, uint8 const _pollIntensity); + ValueRaw(); + virtual ~ValueRaw(); - // From Value - virtual string const GetAsString() const; - virtual bool SetFromString( string const& _value ); - virtual void ReadXML( uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement ); - virtual void WriteXML( TiXmlElement* _valueElement ); + bool Set(uint8 const* _value, uint8 const _length); + void OnValueRefreshed(uint8 const* _value, uint8 const _length); - uint8* GetValue()const{ return m_value; } - uint8 GetLength()const{ return m_valueLength; } + // From Value + virtual string const GetAsString() const; + virtual bool SetFromString(string const& _value); + virtual void ReadXML(uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement); + virtual void WriteXML(TiXmlElement* _valueElement); - private: - uint8* m_value; // the current value - uint8 m_valueLength; // fixed length for this instance - uint8* m_valueCheck; // the previous value (used for double-checking spurious value reads) - uint8 m_valueCheckLength; // m_valueCheck array length - }; + uint8* GetValue() const + { + return m_value; + } + uint8 GetLength() const + { + return m_valueLength; + } + private: + uint8* m_value; // the current value + uint8 m_valueLength; // fixed length for this instance + uint8* m_valueCheck; // the previous value (used for double-checking spurious value reads) + uint8 m_valueCheckLength; // m_valueCheck array length + }; + } // namespace VC + } // namespace Internal } // namespace OpenZWave #endif - - diff --git a/cpp/src/value_classes/ValueSchedule.cpp b/cpp/src/value_classes/ValueSchedule.cpp index edf3ff28a7..fb5ed9a0ac 100644 --- a/cpp/src/value_classes/ValueSchedule.cpp +++ b/cpp/src/value_classes/ValueSchedule.cpp @@ -32,334 +32,296 @@ #include "Msg.h" #include "platform/Log.h" -using namespace OpenZWave; +namespace OpenZWave +{ + namespace Internal + { + namespace VC + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -ValueSchedule::ValueSchedule -( - uint32 const _homeId, - uint8 const _nodeId, - ValueID::ValueGenre const _genre, - uint8 const _commandClassId, - uint8 const _instance, - uint16 const _index, - string const& _label, - string const& _units, - bool const _readOnly, - bool const _writeOnly, - uint8 const _pollIntensity -): - Value( _homeId, _nodeId, _genre, _commandClassId, _instance, _index, ValueID::ValueType_Schedule, _label, _units, _readOnly, _writeOnly, false, _pollIntensity ), - m_numSwitchPoints( 0 ) + ValueSchedule::ValueSchedule(uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, uint8 const _pollIntensity) : + Value(_homeId, _nodeId, _genre, _commandClassId, _instance, _index, ValueID::ValueType_Schedule, _label, _units, _readOnly, _writeOnly, false, _pollIntensity), m_numSwitchPoints(0) -{ -} + { + } //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -ValueSchedule::ValueSchedule -( -): - Value(), - m_numSwitchPoints( 0 ) + ValueSchedule::ValueSchedule() : + Value(), m_numSwitchPoints(0) -{ -} + { + } //----------------------------------------------------------------------------- // // Apply settings from XML //----------------------------------------------------------------------------- -void ValueSchedule::ReadXML -( - uint32 const _homeId, - uint8 const _nodeId, - uint8 const _commandClassId, - TiXmlElement const* _valueElement -) -{ - Value::ReadXML( _homeId, _nodeId, _commandClassId, _valueElement ); - - // Read in the switch points - TiXmlElement const* child = _valueElement->FirstChildElement(); - while( child ) - { - char const* str = child->Value(); - if( str ) - { - if( !strcmp( str, "SwitchPoint" ) ) + void ValueSchedule::ReadXML(uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement) { - int intVal; - - uint8 hours = 0; - if( TIXML_SUCCESS == child->QueryIntAttribute( "hours", &intVal ) ) - { - hours = (uint8)intVal; - } + Value::ReadXML(_homeId, _nodeId, _commandClassId, _valueElement); - uint8 minutes = 0; - if( TIXML_SUCCESS == child->QueryIntAttribute( "minutes", &intVal ) ) + // Read in the switch points + TiXmlElement const* child = _valueElement->FirstChildElement(); + while (child) { - minutes = (uint8)intVal; + char const* str = child->Value(); + if (str) + { + if (!strcmp(str, "SwitchPoint")) + { + int intVal; + + uint8 hours = 0; + if (TIXML_SUCCESS == child->QueryIntAttribute("hours", &intVal)) + { + hours = (uint8) intVal; + } + + uint8 minutes = 0; + if (TIXML_SUCCESS == child->QueryIntAttribute("minutes", &intVal)) + { + minutes = (uint8) intVal; + } + + int8 setback = 0; + if (TIXML_SUCCESS == child->QueryIntAttribute("setback", &intVal)) + { + setback = (int8) intVal; + } + + SetSwitchPoint(hours, minutes, setback); + } + } + + child = child->NextSiblingElement(); } - - int8 setback = 0; - if( TIXML_SUCCESS == child->QueryIntAttribute( "setback", &intVal ) ) - { - setback = (int8)intVal; - } - - SetSwitchPoint( hours, minutes, setback ); } - } - - child = child->NextSiblingElement(); - } -} //----------------------------------------------------------------------------- // // Write ourselves to an XML document //----------------------------------------------------------------------------- -void ValueSchedule::WriteXML -( - TiXmlElement* _valueElement -) -{ - Value::WriteXML( _valueElement ); + void ValueSchedule::WriteXML(TiXmlElement* _valueElement) + { + Value::WriteXML(_valueElement); - for( uint8 i=0; iLinkEndChild( switchPointElement ); + TiXmlElement* switchPointElement = new TiXmlElement("SwitchPoint"); + _valueElement->LinkEndChild(switchPointElement); - snprintf( str, sizeof(str), "%d", hours ); - switchPointElement->SetAttribute( "hours", str ); + snprintf(str, sizeof(str), "%d", hours); + switchPointElement->SetAttribute("hours", str); - snprintf( str, sizeof(str), "%d", minutes ); - switchPointElement->SetAttribute( "minutes", str ); + snprintf(str, sizeof(str), "%d", minutes); + switchPointElement->SetAttribute("minutes", str); - snprintf( str, sizeof(str), "%d", setback ); - switchPointElement->SetAttribute( "setback", str ); - } - } -} + snprintf(str, sizeof(str), "%d", setback); + switchPointElement->SetAttribute("setback", str); + } + } + } //----------------------------------------------------------------------------- // // Set a new value in the device //----------------------------------------------------------------------------- -bool ValueSchedule::Set -( -) -{ - // Set the value in the device. - // TODO this needs to be checked to make sure it works as intended - return Value::Set(); -} + bool ValueSchedule::Set() + { + // Set the value in the device. + // TODO this needs to be checked to make sure it works as intended + return Value::Set(); + } //----------------------------------------------------------------------------- // // A value in a device has been refreshed //----------------------------------------------------------------------------- -void ValueSchedule::OnValueRefreshed -( -) -{ - /* Value::VerifyRefreshedValue doesn't handle Schedule Properly yet, but still do this so we can do it eventually */ + void ValueSchedule::OnValueRefreshed() + { + /* Value::VerifyRefreshedValue doesn't handle Schedule Properly yet, but still do this so we can do it eventually */ - switch( VerifyRefreshedValue( (void*) "Schedule", (void*) "Schedule", (void*) "Schedule", ValueID::ValueType_Schedule) ) - { - case 0: // value hasn't changed, nothing to do - break; - case 1: // value has changed (not confirmed yet), save _value in m_valueCheck - break; - case 2: // value has changed (confirmed), save _value in m_value - break; - case 3: // all three values are different, so wait for next refresh to try again - break; - } -} + switch (VerifyRefreshedValue((void*) "Schedule", (void*) "Schedule", (void*) "Schedule", ValueID::ValueType_Schedule)) + { + case 0: // value hasn't changed, nothing to do + break; + case 1: // value has changed (not confirmed yet), save _value in m_valueCheck + break; + case 2: // value has changed (confirmed), save _value in m_value + break; + case 3: // all three values are different, so wait for next refresh to try again + break; + } + } //----------------------------------------------------------------------------- // // A value in a device has changed //----------------------------------------------------------------------------- -bool ValueSchedule::SetSwitchPoint -( - uint8 const _hours, uint8 const _minutes, int8 const _setback -) -{ - // Find where to insert this switch point. They must be sorted by ascending time value. - uint8 i; - uint8 insertAt = 0; - - for( i=0; i _minutes ) - { - break; - } - } - else if( m_switchPoints[i].m_hours > _hours ) - { - break; - } - - ++insertAt; - } + for (i = 0; i < m_numSwitchPoints; ++i) + { + if (m_switchPoints[i].m_hours == _hours) + { + if (m_switchPoints[i].m_minutes == _minutes) + { + // There is already a switch point with this time, so we + // just update its setback value + m_switchPoints[i].m_setback = _setback; + return true; + } + + if (m_switchPoints[i].m_minutes > _minutes) + { + break; + } + } + else if (m_switchPoints[i].m_hours > _hours) + { + break; + } + + ++insertAt; + } - if( m_numSwitchPoints >= 9 ) - { - // The schedule is full - return false; - } + if (m_numSwitchPoints >= 9) + { + // The schedule is full + return false; + } - // Shuffle any later switch points out of the way - for( i=m_numSwitchPoints; i>insertAt; --i ) - { - m_switchPoints[i].m_hours = m_switchPoints[i-1].m_hours; - m_switchPoints[i].m_minutes = m_switchPoints[i-1].m_minutes; - m_switchPoints[i].m_setback = m_switchPoints[i-1].m_setback; - } + // Shuffle any later switch points out of the way + for (i = m_numSwitchPoints; i > insertAt; --i) + { + m_switchPoints[i].m_hours = m_switchPoints[i - 1].m_hours; + m_switchPoints[i].m_minutes = m_switchPoints[i - 1].m_minutes; + m_switchPoints[i].m_setback = m_switchPoints[i - 1].m_setback; + } - // Insert the new switch point - m_switchPoints[insertAt].m_hours = _hours; - m_switchPoints[insertAt].m_minutes = _minutes; - m_switchPoints[insertAt].m_setback = _setback; + // Insert the new switch point + m_switchPoints[insertAt].m_hours = _hours; + m_switchPoints[insertAt].m_minutes = _minutes; + m_switchPoints[insertAt].m_setback = _setback; - ++m_numSwitchPoints; - return true; -} + ++m_numSwitchPoints; + return true; + } //----------------------------------------------------------------------------- // // A value in a device has changed //----------------------------------------------------------------------------- -bool ValueSchedule::RemoveSwitchPoint -( - uint8 const _idx -) -{ - if( _idx >= m_numSwitchPoints ) - { - // _idx is out of range - return false; - } + bool ValueSchedule::RemoveSwitchPoint(uint8 const _idx) + { + if (_idx >= m_numSwitchPoints) + { + // _idx is out of range + return false; + } - // Shuffle any later switch points down to fill the gap - for( uint8 i=_idx; i<(m_numSwitchPoints-1); ++i ) - { - m_switchPoints[i].m_hours = m_switchPoints[i+1].m_hours; - m_switchPoints[i].m_minutes = m_switchPoints[i+1].m_minutes; - m_switchPoints[i].m_setback = m_switchPoints[i+1].m_setback; - } + // Shuffle any later switch points down to fill the gap + for (uint8 i = _idx; i < (m_numSwitchPoints - 1); ++i) + { + m_switchPoints[i].m_hours = m_switchPoints[i + 1].m_hours; + m_switchPoints[i].m_minutes = m_switchPoints[i + 1].m_minutes; + m_switchPoints[i].m_setback = m_switchPoints[i + 1].m_setback; + } - --m_numSwitchPoints; - return true; -} + --m_numSwitchPoints; + return true; + } //----------------------------------------------------------------------------- // // Get the values of a switch point //----------------------------------------------------------------------------- -bool ValueSchedule::GetSwitchPoint -( - uint8 const _idx, - uint8* o_hours, - uint8* o_minutes, - int8* o_setback -)const -{ - if( _idx >= m_numSwitchPoints ) - { - // _idx is out of range - return false; - } + bool ValueSchedule::GetSwitchPoint(uint8 const _idx, uint8* o_hours, uint8* o_minutes, int8* o_setback) const + { + if (_idx >= m_numSwitchPoints) + { + // _idx is out of range + return false; + } - if( o_hours ) - { - *o_hours = m_switchPoints[_idx].m_hours; - } + if (o_hours) + { + *o_hours = m_switchPoints[_idx].m_hours; + } - if( o_minutes ) - { - *o_minutes = m_switchPoints[_idx].m_minutes; - } + if (o_minutes) + { + *o_minutes = m_switchPoints[_idx].m_minutes; + } - if( o_setback ) - { - *o_setback = m_switchPoints[_idx].m_setback; - } + if (o_setback) + { + *o_setback = m_switchPoints[_idx].m_setback; + } - return true; -} + return true; + } //----------------------------------------------------------------------------- // // Get the index of the switch point at the specified time //----------------------------------------------------------------------------- -bool ValueSchedule::FindSwitchPoint -( - uint8 const _hours, - uint8 const _minutes, - uint8* o_idx -)const -{ - for( uint8 i=0; i _minutes) + { + // Gone past any possible match + return false; + } + } + else if (m_switchPoints[i].m_hours > _hours) + { + // Gone past any possible match + return false; + } } - return true; + + // No match found + return false; } - if( m_switchPoints[i].m_minutes > _minutes ) + std::string const ValueSchedule::GetAsString() const { - // Gone past any possible match - return false; + /* we should actuall find a way to return the arrays of switchpoints nicely */ + return "SwitchPoint"; } - } - else if( m_switchPoints[i].m_hours > _hours ) - { - // Gone past any possible match - return false; - } - } - - // No match found - return false; -} - -string const ValueSchedule::GetAsString() const { - /* we should actuall find a way to return the arrays of switchpoints nicely */ - return "SwitchPoint"; -} + } // namespace VC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/value_classes/ValueSchedule.h b/cpp/src/value_classes/ValueSchedule.h index 8c6f0edbcf..81169d6bf3 100644 --- a/cpp/src/value_classes/ValueSchedule.h +++ b/cpp/src/value_classes/ValueSchedule.h @@ -36,47 +36,58 @@ class TiXmlElement; namespace OpenZWave { - class Msg; - class Node; - - /** \brief Schedule sent to/received from a node. - * \ingroup ValueID - */ - class ValueSchedule: public Value + namespace Internal { - public: - ValueSchedule( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, uint8 const _pollIntensity ); - ValueSchedule(); - virtual ~ValueSchedule(){} + namespace VC + { - bool SetSwitchPoint( uint8 const _hours, uint8 const _minutes, int8 const _setback ); - bool RemoveSwitchPoint( uint8 const _idx ); - void ClearSwitchPoints(){ m_numSwitchPoints = 0; } - bool GetSwitchPoint( uint8 const _idx, uint8* o_hours, uint8* o_minutes, int8* o_setback )const; - bool FindSwitchPoint( uint8 const _hours, uint8 const _minutes, uint8* o_idx )const; - uint8 GetNumSwitchPoints()const{ return m_numSwitchPoints; } + /** \brief Schedule sent to/received from a node. + * \ingroup ValueID + */ + class ValueSchedule: public Value + { + public: + ValueSchedule(uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, uint8 const _pollIntensity); + ValueSchedule(); + virtual ~ValueSchedule() + { + } - bool Set(); - void OnValueRefreshed(); + bool SetSwitchPoint(uint8 const _hours, uint8 const _minutes, int8 const _setback); + bool RemoveSwitchPoint(uint8 const _idx); + void ClearSwitchPoints() + { + m_numSwitchPoints = 0; + } + bool GetSwitchPoint(uint8 const _idx, uint8* o_hours, uint8* o_minutes, int8* o_setback) const; + bool FindSwitchPoint(uint8 const _hours, uint8 const _minutes, uint8* o_idx) const; + uint8 GetNumSwitchPoints() const + { + return m_numSwitchPoints; + } - virtual string const GetAsString() const; + bool Set(); + void OnValueRefreshed(); - // From Value - virtual void ReadXML( uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement ); - virtual void WriteXML( TiXmlElement* _valueElement ); + virtual string const GetAsString() const; - private: - struct SwitchPoint - { - uint8 m_hours; - uint8 m_minutes; - int8 m_setback; - }; + // From Value + virtual void ReadXML(uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement); + virtual void WriteXML(TiXmlElement* _valueElement); - SwitchPoint m_switchPoints[9]; - uint8 m_numSwitchPoints; - }; + private: + struct SwitchPoint + { + uint8 m_hours; + uint8 m_minutes; + int8 m_setback; + }; + SwitchPoint m_switchPoints[9]; + uint8 m_numSwitchPoints; + }; + } // namespace VC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/value_classes/ValueShort.cpp b/cpp/src/value_classes/ValueShort.cpp index df7b9c7d71..b0e0bd867a 100644 --- a/cpp/src/value_classes/ValueShort.cpp +++ b/cpp/src/value_classes/ValueShort.cpp @@ -34,156 +34,123 @@ #include "Manager.h" #include -using namespace OpenZWave; - +namespace OpenZWave +{ + namespace Internal + { + namespace VC + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -ValueShort::ValueShort -( - uint32 const _homeId, - uint8 const _nodeId, - ValueID::ValueGenre const _genre, - uint8 const _commandClassId, - uint8 const _instance, - uint16 const _index, - string const& _label, - string const& _units, - bool const _readOnly, - bool const _writeOnly, - int16 const _value, - uint8 const _pollIntensity -): - Value( _homeId, _nodeId, _genre, _commandClassId, _instance, _index, ValueID::ValueType_Short, _label, _units, _readOnly, _writeOnly, false, _pollIntensity ), - m_value( _value ), - m_valueCheck( 0 ) -{ - m_min = SHRT_MIN; - m_max = SHRT_MAX; -} + ValueShort::ValueShort(uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, int16 const _value, uint8 const _pollIntensity) : + Value(_homeId, _nodeId, _genre, _commandClassId, _instance, _index, ValueID::ValueType_Short, _label, _units, _readOnly, _writeOnly, false, _pollIntensity), m_value(_value), m_valueCheck(0) + { + m_min = SHRT_MIN; + m_max = SHRT_MAX; + } //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -ValueShort::ValueShort -( -): - Value(), - m_value( 0 ), - m_valueCheck( 0 ) -{ - m_min = SHRT_MIN; - m_max = SHRT_MAX; -} - -string const ValueShort::GetAsString -( -) const -{ - stringstream ss; - ss << GetValue(); - return ss.str(); -} - -bool ValueShort::SetFromString -( - string const& _value -) -{ - uint32 val = (uint32)atoi( _value.c_str() ); - if( val < 32768 ) - { - return Set( (int16)val ); - } - return false; -} + ValueShort::ValueShort() : + Value(), m_value(0), m_valueCheck(0) + { + m_min = SHRT_MIN; + m_max = SHRT_MAX; + } + + std::string const ValueShort::GetAsString() const + { + stringstream ss; + ss << GetValue(); + return ss.str(); + } + + bool ValueShort::SetFromString(string const& _value) + { + uint32 val = (uint32) atoi(_value.c_str()); + if (val < 32768) + { + return Set((int16) val); + } + return false; + } //----------------------------------------------------------------------------- // // Apply settings from XML //----------------------------------------------------------------------------- -void ValueShort::ReadXML -( - uint32 const _homeId, - uint8 const _nodeId, - uint8 const _commandClassId, - TiXmlElement const* _valueElement -) -{ - Value::ReadXML( _homeId, _nodeId, _commandClassId, _valueElement ); - - int intVal; - if( TIXML_SUCCESS == _valueElement->QueryIntAttribute( "value", &intVal ) ) - { - m_value = (int16)intVal; - } - else - { - Log::Write( LogLevel_Info, "Missing default short value from xml configuration: node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex() ); - } -} + void ValueShort::ReadXML(uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement) + { + Value::ReadXML(_homeId, _nodeId, _commandClassId, _valueElement); + + int intVal; + if (TIXML_SUCCESS == _valueElement->QueryIntAttribute("value", &intVal)) + { + m_value = (int16) intVal; + } + else + { + Log::Write(LogLevel_Info, "Missing default short value from xml configuration: node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex()); + } + } //----------------------------------------------------------------------------- // // Write ourselves to an XML document //----------------------------------------------------------------------------- -void ValueShort::WriteXML -( - TiXmlElement* _valueElement -) -{ - Value::WriteXML( _valueElement ); + void ValueShort::WriteXML(TiXmlElement* _valueElement) + { + Value::WriteXML(_valueElement); - char str[16]; - snprintf( str, sizeof(str), "%d", m_value ); - _valueElement->SetAttribute( "value", str ); -} + char str[16]; + snprintf(str, sizeof(str), "%d", m_value); + _valueElement->SetAttribute("value", str); + } //----------------------------------------------------------------------------- // // Set a new value in the device //----------------------------------------------------------------------------- -bool ValueShort::Set -( - int16 const _value -) -{ - // create a temporary copy of this value to be submitted to the Set() call and set its value to the function param - ValueShort* tempValue = new ValueShort( *this ); - tempValue->m_value = _value; + bool ValueShort::Set(int16 const _value) + { + // create a temporary copy of this value to be submitted to the Set() call and set its value to the function param + ValueShort* tempValue = new ValueShort(*this); + tempValue->m_value = _value; - // Set the value in the device. - bool ret = ((Value*)tempValue)->Set(); + // Set the value in the device. + bool ret = ((Value*) tempValue)->Set(); - // clean up the temporary value - delete tempValue; + // clean up the temporary value + delete tempValue; - return ret; -} + return ret; + } //----------------------------------------------------------------------------- // // A value in a device has been refreshed //----------------------------------------------------------------------------- -void ValueShort::OnValueRefreshed -( - int16 const _value -) -{ - switch( VerifyRefreshedValue( (void*) &m_value, (void*) &m_valueCheck, (void*) &_value, ValueID::ValueType_Short) ) - { - case 0: // value hasn't changed, nothing to do - break; - case 1: // value has changed (not confirmed yet), save _value in m_valueCheck - m_valueCheck = _value; - break; - case 2: // value has changed (confirmed), save _value in m_value - m_value = _value; - break; - case 3: // all three values are different, so wait for next refresh to try again - break; - } -} + void ValueShort::OnValueRefreshed(int16 const _value) + { + switch (VerifyRefreshedValue((void*) &m_value, (void*) &m_valueCheck, (void*) &_value, ValueID::ValueType_Short)) + { + case 0: // value hasn't changed, nothing to do + break; + case 1: // value has changed (not confirmed yet), save _value in m_valueCheck + m_valueCheck = _value; + break; + case 2: // value has changed (confirmed), save _value in m_value + m_value = _value; + break; + case 3: // all three values are different, so wait for next refresh to try again + break; + } + } + } // namespace VC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/value_classes/ValueShort.h b/cpp/src/value_classes/ValueShort.h index 125acba507..db5c13340f 100644 --- a/cpp/src/value_classes/ValueShort.h +++ b/cpp/src/value_classes/ValueShort.h @@ -36,35 +36,43 @@ class TiXmlElement; namespace OpenZWave { - class Msg; - class Node; - - /** \brief Short value sent to/received from a node. - * \ingroup ValueID - */ - class ValueShort: public Value + namespace Internal { - public: - ValueShort( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, int16 const _value, uint8 const _pollIntensity ); - ValueShort(); - virtual ~ValueShort(){} + namespace VC + { - bool Set( int16 const _value ); - void OnValueRefreshed( int16 const _value ); + /** \brief Short value sent to/received from a node. + * \ingroup ValueID + */ + class ValueShort: public Value + { + public: + ValueShort(uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, int16 const _value, uint8 const _pollIntensity); + ValueShort(); + virtual ~ValueShort() + { + } - // From Value - virtual string const GetAsString() const; - virtual bool SetFromString( string const& _value ); - virtual void ReadXML( uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement ); - virtual void WriteXML( TiXmlElement* _valueElement ); + bool Set(int16 const _value); + void OnValueRefreshed(int16 const _value); - int16 GetValue()const{ return m_value; } + // From Value + virtual string const GetAsString() const; + virtual bool SetFromString(string const& _value); + virtual void ReadXML(uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement); + virtual void WriteXML(TiXmlElement* _valueElement); - private: - int16 m_value; // the current value - int16 m_valueCheck; // the previous value (used for double-checking spurious value reads) - }; + int16 GetValue() const + { + return m_value; + } + private: + int16 m_value; // the current value + int16 m_valueCheck; // the previous value (used for double-checking spurious value reads) + }; + } // namespace VC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/src/value_classes/ValueStore.cpp b/cpp/src/value_classes/ValueStore.cpp index d3502180bc..3c99389b1f 100644 --- a/cpp/src/value_classes/ValueStore.cpp +++ b/cpp/src/value_classes/ValueStore.cpp @@ -30,95 +30,107 @@ #include "Manager.h" #include "Notification.h" #include "Localization.h" +#include "platform/Log.h" -using namespace OpenZWave; - +namespace OpenZWave +{ + namespace Internal + { + namespace VC + { //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- -ValueStore::~ValueStore -( -) -{ - map::iterator it = m_values.begin(); - while( !m_values.empty() ) - { - ValueID const& valueId = it->second->GetID(); - RemoveValue( valueId.GetValueStoreKey() ); - it = m_values.begin(); - } -} + ValueStore::~ValueStore() + { + map::iterator it = m_values.begin(); + while (!m_values.empty()) + { + ValueID const& valueId = it->second->GetID(); + RemoveValue(valueId.GetValueStoreKey()); + it = m_values.begin(); + } + } //----------------------------------------------------------------------------- // // Add a value to the store //----------------------------------------------------------------------------- -bool ValueStore::AddValue -( - Value* _value -) -{ - if( !_value ) - { - return false; - } - uint32 key = _value->GetID().GetValueStoreKey(); - map::iterator it = m_values.find( key ); - if( it != m_values.end() ) - { - // There is already a value in the store with this key, so we give up. - return false; - } - - m_values[key] = _value; - _value->AddRef(); - - // Notify the watchers of the new value - if( Driver* driver = Manager::Get()->GetDriver( _value->GetID().GetHomeId() ) ) - { - Notification* notification = new Notification( Notification::Type_ValueAdded ); - notification->SetValueId( _value->GetID() ); - driver->QueueNotification( notification ); - } - - return true; -} + bool ValueStore::AddValue(Value* _value) + { + if (!_value) + { + return false; + } + + uint32 key = _value->GetID().GetValueStoreKey(); + map::iterator it = m_values.find(key); + if (it != m_values.end()) + { + // There is already a value in the store with this key, so we give up. + return false; + } + + m_values[key] = _value; + _value->AddRef(); + + // Notify the watchers of the new value and Check our GetChangeVerified Flag + if (Driver* driver = Manager::Get()->GetDriver(_value->GetID().GetHomeId())) + { + Node *node = driver->GetNodeUnsafe(_value->GetID().GetNodeId()); + if (node) { + Internal::CC::CommandClass *cc = node->GetCommandClass(_value->GetID().GetCommandClassId()); + if (cc) { + if (cc->m_com.GetFlagBool(COMPAT_FLAG_VERIFYCHANGED, _value->GetID().GetIndex())) { + Log::Write(LogLevel_Info, _value->GetID().GetNodeId(), "Setting VerifiedChanged Flag on Value %d for CC %s", _value->GetID().GetIndex(), cc->GetCommandClassName().c_str()); + _value->SetChangeVerified(true); + } + } + } + Notification* notification = new Notification(Notification::Type_ValueAdded); + notification->SetValueId(_value->GetID()); + driver->QueueNotification(notification); + } + + return true; + } //----------------------------------------------------------------------------- // // Remove a value from the store //----------------------------------------------------------------------------- -bool ValueStore::RemoveValue -( - uint32 const& _key -) -{ - map::iterator it = m_values.find( _key ); - if( it != m_values.end() ) - { - Value* value = it->second; - ValueID const& valueId = value->GetID(); - - // First notify the watchers - if( Driver* driver = Manager::Get()->GetDriver( valueId.GetHomeId() ) ) - { - Notification* notification = new Notification( Notification::Type_ValueRemoved ); - notification->SetValueId( valueId ); - driver->QueueNotification( notification ); - } - - // Now release and remove the value from the store - value->Release(); - m_values.erase( it ); - - return true; - } - - // Value not found in the store - return false; -} + bool ValueStore::RemoveValue(uint32 const& _key) + { + map::iterator it = m_values.find(_key); + if (it != m_values.end()) + { + Value* value = it->second; + ValueID const& valueId = value->GetID(); + + // First notify the watchers + if (Driver* driver = Manager::Get()->GetDriver(valueId.GetHomeId())) + { + Notification* notification = new Notification(Notification::Type_ValueRemoved); + notification->SetValueId(valueId); + driver->QueueNotification(notification); + } + + // Now release and remove the value from the store + int32 references = value->Release(); + if (references > 0) + Log::Write(LogLevel_Warning, "Value Not Deleted - Still in use %d times: CC: %d - %s - %s - %d", references, valueId.GetCommandClassId(), valueId.GetTypeAsString().c_str(), value->GetLabel().c_str(), value->GetID()); + else + Log::Write(LogLevel_Debug, "Value Deleted"); + m_values.erase(it); + + return true; + } + + // Value not found in the store + return false; + } ////----------------------------------------------------------------------------- //// @@ -129,76 +141,63 @@ bool ValueStore::RemoveValue // ValueID const& _id //) - //----------------------------------------------------------------------------- // // Remove all the values associated with a command class from the store //----------------------------------------------------------------------------- -void ValueStore::RemoveCommandClassValues -( - uint8 const _commandClassId -) -{ - map::iterator it = m_values.begin(); - while( it != m_values.end() ) - { - Value* value = it->second; - ValueID const& valueId = value->GetID(); - if( _commandClassId == valueId.GetCommandClassId() ) - { - // The value belongs to the specified command class - - // First notify the watchers - if( Driver* driver = Manager::Get()->GetDriver( valueId.GetHomeId() ) ) + void ValueStore::RemoveCommandClassValues(uint8 const _commandClassId) { - Notification* notification = new Notification( Notification::Type_ValueRemoved ); - notification->SetValueId( valueId ); - driver->QueueNotification( notification ); + map::iterator it = m_values.begin(); + while (it != m_values.end()) + { + Value* value = it->second; + ValueID const& valueId = value->GetID(); + if (_commandClassId == valueId.GetCommandClassId()) + { + // The value belongs to the specified command class + + // First notify the watchers + if (Driver* driver = Manager::Get()->GetDriver(valueId.GetHomeId())) + { + Notification* notification = new Notification(Notification::Type_ValueRemoved); + notification->SetValueId(valueId); + driver->QueueNotification(notification); + } + + // Now release and remove the value from the store + value->Release(); + m_values.erase(it++); + } + else + { + ++it; + } + } } - // Now release and remove the value from the store - value->Release(); - m_values.erase( it++ ); - } - else - { - ++it; - } - } -} - //----------------------------------------------------------------------------- // // Get a value from the store //----------------------------------------------------------------------------- -Value* ValueStore::GetValue -( - uint32 const& _key -)const -{ - Value* value = NULL; - - map::const_iterator it = m_values.find( _key ); - if( it != m_values.end() ) - { - value = it->second; - if( value ) - { - // Add a reference to the value. The caller must - // call Release on the value when they are done with it. - value->AddRef(); - } - } - - return value; -} - -////----------------------------------------------------------------------------- -//// -//// Get a value from the store -////----------------------------------------------------------------------------- -//Value* ValueStore::GetValue -//( -// ValueID const& _id -//)const + Value* ValueStore::GetValue(uint32 const& _key) const + { + Value* value = NULL; + + map::const_iterator it = m_values.find(_key); + if (it != m_values.end()) + { + value = it->second; + if (value) + { + // Add a reference to the value. The caller must + // call Release on the value when they are done with it. + value->AddRef(); + } + } + + return value; + } + } // namespace VC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/value_classes/ValueStore.h b/cpp/src/value_classes/ValueStore.h index 69637899cc..1e74a8a1e6 100644 --- a/cpp/src/value_classes/ValueStore.h +++ b/cpp/src/value_classes/ValueStore.h @@ -36,36 +36,48 @@ class TiXmlElement; namespace OpenZWave { - class Value; - - /** \brief Container that holds all of the values associated with a given node. - * \ingroup ValueID - */ - class ValueStore + namespace Internal { - public: - - typedef map::const_iterator Iterator; + namespace VC + { - Iterator Begin(){ return m_values.begin(); } - Iterator End(){ return m_values.end(); } - - ValueStore(){} - ~ValueStore(); + class Value; - bool AddValue( Value* _value ); - bool RemoveValue( uint32 const& _key ); - Value* GetValue( uint32 const& _key )const; + /** \brief Container that holds all of the values associated with a given node. + * \ingroup ValueID + */ + class ValueStore + { + public: - void RemoveCommandClassValues( uint8 const _commandClassId ); // Remove all the values associated with a command class + typedef map::const_iterator Iterator; - private: - map m_values; - }; + Iterator Begin() + { + return m_values.begin(); + } + Iterator End() + { + return m_values.end(); + } -} // namespace OpenZWave + ValueStore() + { + } + ~ValueStore(); -#endif + bool AddValue(Value* _value); + bool RemoveValue(uint32 const& _key); + Value* GetValue(uint32 const& _key) const; + void RemoveCommandClassValues(uint8 const _commandClassId); // Remove all the values associated with a command class + private: + map m_values; + }; + } // namespace VC + } // namespace Internal +} // namespace OpenZWave + +#endif diff --git a/cpp/src/value_classes/ValueString.cpp b/cpp/src/value_classes/ValueString.cpp index 81594c55d1..fad42a8873 100644 --- a/cpp/src/value_classes/ValueString.cpp +++ b/cpp/src/value_classes/ValueString.cpp @@ -31,115 +31,90 @@ #include "platform/Log.h" #include "Manager.h" -using namespace OpenZWave; - +namespace OpenZWave +{ + namespace Internal + { + namespace VC + { //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- -ValueString::ValueString -( - uint32 const _homeId, - uint8 const _nodeId, - ValueID::ValueGenre const _genre, - uint8 const _commandClassId, - uint8 const _instance, - uint16 const _index, - string const& _label, - string const& _units, - bool const _readOnly, - bool const _writeOnly, - string const& _value, - uint8 const _pollIntensity -): - Value( _homeId, _nodeId, _genre, _commandClassId, _instance, _index, ValueID::ValueType_String, _label, _units, _readOnly, _writeOnly, false, _pollIntensity ), - m_value( _value ), - m_valueCheck( "" ), - m_newValue( "" ) -{ -} + ValueString::ValueString(uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, string const& _value, uint8 const _pollIntensity) : + Value(_homeId, _nodeId, _genre, _commandClassId, _instance, _index, ValueID::ValueType_String, _label, _units, _readOnly, _writeOnly, false, _pollIntensity), m_value(_value), m_valueCheck(""), m_newValue("") + { + } //----------------------------------------------------------------------------- // // Apply settings from XML //----------------------------------------------------------------------------- -void ValueString::ReadXML -( - uint32 const _homeId, - uint8 const _nodeId, - uint8 const _commandClassId, - TiXmlElement const* _valueElement -) -{ - Value::ReadXML( _homeId, _nodeId, _commandClassId, _valueElement ); + void ValueString::ReadXML(uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement) + { + Value::ReadXML(_homeId, _nodeId, _commandClassId, _valueElement); - char const* str = _valueElement->Attribute( "value" ); - if( str ) - { - m_value = str; - } - else - { - Log::Write( LogLevel_Alert, "Missing default string value from xml configuration: node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex() ); - } -} + char const* str = _valueElement->Attribute("value"); + if (str) + { + m_value = str; + } + else + { + Log::Write(LogLevel_Alert, "Missing default string value from xml configuration: node %d, class 0x%02x, instance %d, index %d", _nodeId, _commandClassId, GetID().GetInstance(), GetID().GetIndex()); + } + } //----------------------------------------------------------------------------- // // Write ourselves to an XML document //----------------------------------------------------------------------------- -void ValueString::WriteXML -( - TiXmlElement* _valueElement -) -{ - Value::WriteXML( _valueElement ); - _valueElement->SetAttribute( "value", m_value.c_str() ); -} + void ValueString::WriteXML(TiXmlElement* _valueElement) + { + Value::WriteXML(_valueElement); + _valueElement->SetAttribute("value", m_value.c_str()); + } //----------------------------------------------------------------------------- // // Set a new value in the device and queue a "RequestValue" to confirm it worked //----------------------------------------------------------------------------- -bool ValueString::Set -( - string const& _value -) -{ - // create a temporary copy of this value to be submitted to the Set() call and set its value to the function param - ValueString* tempValue = new ValueString( *this ); - tempValue->m_value = _value; + bool ValueString::Set(string const& _value) + { + // create a temporary copy of this value to be submitted to the Set() call and set its value to the function param + ValueString* tempValue = new ValueString(*this); + tempValue->m_value = _value; - // Set the value in the device. - bool ret = ((Value*)tempValue)->Set(); + // Set the value in the device. + bool ret = ((Value*) tempValue)->Set(); - // clean up the temporary value - delete tempValue; + // clean up the temporary value + delete tempValue; - return ret; -} + return ret; + } //----------------------------------------------------------------------------- // // A value in a device has been refreshed //----------------------------------------------------------------------------- -void ValueString::OnValueRefreshed -( - string const& _value -) -{ - switch( VerifyRefreshedValue( (void*) &m_value, (void*) &m_valueCheck, (void*) &_value, ValueID::ValueType_String) ) - { - case 0: // value hasn't changed, nothing to do - break; - case 1: // value has changed (not confirmed yet), save _value in m_valueCheck - m_valueCheck = _value; - break; - case 2: // value has changed (confirmed), save _value in m_value - m_value = _value; - break; - case 3: // all three values are different, so wait for next refresh to try again - break; - } -} + void ValueString::OnValueRefreshed(string const& _value) + { + switch (VerifyRefreshedValue((void*) &m_value, (void*) &m_valueCheck, (void*) &_value, ValueID::ValueType_String)) + { + case 0: // value hasn't changed, nothing to do + break; + case 1: // value has changed (not confirmed yet), save _value in m_valueCheck + m_valueCheck = _value; + break; + case 2: // value has changed (confirmed), save _value in m_value + m_value = _value; + break; + case 3: // all three values are different, so wait for next refresh to try again + break; + } + } + } // namespace VC + } // namespace Internal +} // namespace OpenZWave diff --git a/cpp/src/value_classes/ValueString.h b/cpp/src/value_classes/ValueString.h index e3c4e68480..0b3e7714fb 100644 --- a/cpp/src/value_classes/ValueString.h +++ b/cpp/src/value_classes/ValueString.h @@ -36,36 +36,52 @@ class TiXmlElement; namespace OpenZWave { - class Msg; - class Node; - - /** \brief String value sent to/received from a node. - * \ingroup ValueID - */ - class ValueString: public Value + namespace Internal { - public: - ValueString( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, string const& _value, uint8 const _pollIntensity ); - ValueString(){} - virtual ~ValueString(){} + namespace VC + { - bool Set( string const& _value ); - void OnValueRefreshed( string const& _value ); + /** \brief String value sent to/received from a node. + * \ingroup ValueID + */ + class ValueString: public Value + { + public: + ValueString(uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint16 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, string const& _value, uint8 const _pollIntensity); + ValueString() + { + } + virtual ~ValueString() + { + } - // From Value - virtual string const GetAsString() const { return GetValue(); } - virtual bool SetFromString( string const& _value ) { return Set( _value ); } - virtual void ReadXML( uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement ); - virtual void WriteXML( TiXmlElement* _valueElement ); + bool Set(string const& _value); + void OnValueRefreshed(string const& _value); - string GetValue()const{ return m_value; } + // From Value + virtual string const GetAsString() const + { + return GetValue(); + } + virtual bool SetFromString(string const& _value) + { + return Set(_value); + } + virtual void ReadXML(uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement); + virtual void WriteXML(TiXmlElement* _valueElement); - private: - string m_value; // the current value - string m_valueCheck; // the previous value (used for double-checking spurious value reads) - string m_newValue; // a new value to be set on the appropriate device - }; + string GetValue() const + { + return m_value; + } + private: + string m_value; // the current value + string m_valueCheck; // the previous value (used for double-checking spurious value reads) + string m_newValue; // a new value to be set on the appropriate device + }; + } // namespace VC + } // namespace Internal } // namespace OpenZWave #endif diff --git a/cpp/test/Makefile b/cpp/test/Makefile index e5ba44b530..4dd1ff03d0 100644 --- a/cpp/test/Makefile +++ b/cpp/test/Makefile @@ -9,9 +9,17 @@ .SUFFIXES: .d .cpp .o .a .PHONY: default clean +# 2019-10 added this test because there are path issues, hings go wrong when you try to run +# "make" in the cpp/test subdirectory. One of the offending statements is "top_builddir ?= $(CURDIR)" +# Needs some work to get a proper fix. -DEBUG_CFLAGS := -Wall -ggdb -DDEBUG $(CPPFLAGS) -RELEASE_CFLAGS := -Wall -Wno-unknown-pragmas -O3 $(CPPFLAGS) +ifeq ($(top_builddir),) + $(error Variable top_builddir is undefined, please run "make" from root of OpenzWave repository only.) +endif + +COMMON_FLAGS := -std=c++11 -Wall -Wno-unknown-pragmas -Wsign-compare +DEBUG_CFLAGS := -ggdb -DDEBUG $(CPPFLAGS) $(COMMON_FLAGS) +RELEASE_CFLAGS := -O3 $(CPPFLAGS) $(COMMON_FLAGS) DEBUG_LDFLAGS := -g @@ -21,7 +29,13 @@ top_srcdir := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))../../) LIBDIR ?= $(top_builddir) INCLUDES := -I $(top_srcdir)/cpp/test/ -I $(top_srcdir)/cpp/test/include/ -I $(top_srcdir)/cpp/src -I $(top_srcdir)/cpp/tinyxml/ -I $(top_srcdir)/cpp/hidapi/hidapi/ -LIBS = $(wildcard $(LIBDIR)/*.a ) +OZW_LIB = $(wildcard $(LIBDIR)/*.a ) +LIBS = $(OZW_LIB) + +ifneq ($(UNAME),FreeBSD) +LIBS += -lresolv +endif + #LIBSDIR = $(abspath $(dir $(firstword $(LIBS)))) SOURCES := $(top_srcdir)/cpp/test/src/ $(top_srcdir)/cpp/test/ gtestsrc := $(notdir $(wildcard $(top_srcdir)/cpp/test/src/*.cc)) @@ -69,7 +83,7 @@ $(OBJDIR)/%.o : %.cc @$(CXX) $(CFLAGS) $(TARCH) $(INCLUDES) -o $@ $< $(top_builddir)/gtest-main: $(patsubst %.cc,$(OBJDIR)/%.o,$(gtestsrc)) \ - $(patsubst %.cpp,$(OBJDIR)/%.o,$(testsrc)) + $(patsubst %.cpp,$(OBJDIR)/%.o,$(testsrc)) $(OZW_LIB) @echo "Linking $@" @$(LD) $(LDFLAGS) $(TARCH) -o $@ $+ $(LIBS) -pthread diff --git a/cpp/test/ValueID_test.cpp b/cpp/test/ValueID_test.cpp index 8f2f9ce075..a9e5320952 100644 --- a/cpp/test/ValueID_test.cpp +++ b/cpp/test/ValueID_test.cpp @@ -26,45 +26,99 @@ //----------------------------------------------------------------------------- #include "gtest/gtest.h" - #include "value_classes/ValueID.h" -using namespace OpenZWave; -TEST(ValueID, Constructor) { - ValueID *vid = new ValueID(0xFFFF, 0x1, ValueID::ValueGenre_Basic, 0xCC, 0x02, 0x04, ValueID::ValueType_BitSet); +extern uint16_t ozw_vers_major; +extern uint16_t ozw_vers_minor; +extern uint16_t ozw_vers_revision; +namespace OpenZWave +{ + +namespace Testing +{ +TEST(OpenZWave, Version) +{ + EXPECT_EQ(ozw_vers_major, 1); + EXPECT_EQ(ozw_vers_minor, 6); + // Allow ozw_vers_revision to be zero, to avoid build server failure: + // "ValueID_test.cpp:42: Failure" + // "Expected: (ozw_vers_revision) >= (900), actual: 0 vs 900 [ FAILED ] OpenZWave.Version (0 ms)"" + if (ozw_vers_revision != 0) + { + EXPECT_GE(ozw_vers_revision, 900); + } +} +TEST(ValueID, Constructor) +{ + ValueID *vid = new ValueID(0xFFFFu, 0x1, ValueID::ValueGenre_Basic, 0xCC, 0x02, 0x04, ValueID::ValueType_BitSet); EXPECT_EQ(vid->GetCommandClassId(), 0xCC); EXPECT_EQ(vid->GetGenre(), ValueID::ValueGenre_Basic); - EXPECT_EQ(vid->GetHomeId(), 0xFFFF); + EXPECT_EQ(vid->GetHomeId(), 0xFFFFu); EXPECT_EQ(vid->GetIndex(), 0x04); EXPECT_EQ(vid->GetInstance(), 0x02); EXPECT_EQ(vid->GetNodeId(), 0x01); EXPECT_EQ(vid->GetType(), ValueID::ValueType_BitSet); - EXPECT_EQ(vid->GetId(), 0x400000133002A); + EXPECT_EQ(vid->GetId(), 0x400000133002Au); delete vid; } -TEST(ValueID, KeyConstructor) { - ValueID *vid = new ValueID(0xFFFF, (uint64)0x400000133002A); +TEST(ValueID, KeyConstructor) +{ + // static cast needed to avoid: "call to constructor of 'OpenZWave::ValueID' is ambiguous" + ValueID *vid = new ValueID(0xFFFFu, static_cast(0x400000133002Au)); EXPECT_EQ(vid->GetCommandClassId(), 0xCC); EXPECT_EQ(vid->GetGenre(), ValueID::ValueGenre_Basic); - EXPECT_EQ(vid->GetHomeId(), 0xFFFF); + EXPECT_EQ(vid->GetHomeId(), 0xFFFFu); EXPECT_EQ(vid->GetIndex(), 0x04); EXPECT_EQ(vid->GetInstance(), 0x02); EXPECT_EQ(vid->GetNodeId(), 0x01); EXPECT_EQ(vid->GetType(), ValueID::ValueType_BitSet); delete vid; } -TEST(ValueID, Comparision) { - ValueID *vid1 = new ValueID(0xFFFF, (uint64)0x400000133002A); - ValueID *vid2 = new ValueID(0xFFFF, 0x1, ValueID::ValueGenre_Basic, 0xCC, 0x02, 0x04, ValueID::ValueType_BitSet); - ValueID *vid3 = new ValueID(0xFFFF, (uint64)0x01); -// EXPECT_TRUE(vid1 == vid2); -// EXPECT_TRUE(vid1 != vid3); -// EXPECT_FALSE(vid1 == vid3); - delete vid1; - delete vid2; - delete vid3; +TEST(ValueID, Comparision) +{ + EXPECT_EQ( + ValueID(0xFFFF, (uint64)0x400000133002A), + ValueID(0xFFFF, 0x1, ValueID::ValueGenre_Basic, 0xCC, 0x02, 0x04, ValueID::ValueType_BitSet)); + EXPECT_NE( + ValueID(0xFFFF, (uint64)0x01), + ValueID(0xFFFF, 0x1, ValueID::ValueGenre_Basic, 0xCC, 0x02, 0x04, ValueID::ValueType_BitSet)); } +TEST(ValueID, GetStoreKey) +{ + ValueID *vid1 = new ValueID(0xFFFFu, 0x1, ValueID::ValueGenre_Basic, 0xCC, 0x02, 0x04, ValueID::ValueType_BitSet); + ValueID *vid2 = new ValueID(0xFFFFu, 0x1, ValueID::ValueGenre_Basic, 0x01, 0x01, 0x01, ValueID::ValueType_BitSet); + ValueID *vid3 = new ValueID(0xFFFFu, 0x1, ValueID::ValueGenre_Basic, 0x80, 0x80, 0x80, ValueID::ValueType_BitSet); + EXPECT_EQ(vid1->GetValueStoreKey(), ValueID::GetValueStoreKey(0xCC, 0x02, 0x04)); + EXPECT_EQ(vid2->GetValueStoreKey(), ValueID::GetValueStoreKey(0x01, 0x01, 0x01)); + EXPECT_EQ(vid3->GetValueStoreKey(), ValueID::GetValueStoreKey(0x80, 0x80, 0x80)); + EXPECT_NE(vid1->GetValueStoreKey(), vid2->GetValueStoreKey()); + EXPECT_NE(vid1->GetValueStoreKey(), vid3->GetValueStoreKey()); + EXPECT_NE(vid2->GetValueStoreKey(), vid3->GetValueStoreKey()); + // See if we've all three contributing parts (CC, instance and index) in the mix. + EXPECT_NE(ValueID::GetValueStoreKey(0x80, 0x80, 0x80), ValueID::GetValueStoreKey(0x81, 0x80, 0x80)); + EXPECT_NE(ValueID::GetValueStoreKey(0x80, 0x80, 0x80), ValueID::GetValueStoreKey(0x80, 0x81, 0x80)); + EXPECT_NE(ValueID::GetValueStoreKey(0x80, 0x80, 0x80), ValueID::GetValueStoreKey(0x80, 0x80, 0x81)); + ValueID *vid4 = new ValueID(0xFFFFu, 0x1, ValueID::ValueGenre_Basic, 0x81, 0x80, 0x80, ValueID::ValueType_BitSet); + ValueID *vid5 = new ValueID(0xFFFFu, 0x1, ValueID::ValueGenre_Basic, 0x80, 0x81, 0x80, ValueID::ValueType_BitSet); + ValueID *vid6 = new ValueID(0xFFFFu, 0x1, ValueID::ValueGenre_Basic, 0x80, 0x80, 0x81, ValueID::ValueType_BitSet); + + EXPECT_NE(vid3->GetValueStoreKey(), vid4->GetValueStoreKey()); + EXPECT_NE(vid3->GetValueStoreKey(), vid5->GetValueStoreKey()); + EXPECT_NE(vid3->GetValueStoreKey(), vid6->GetValueStoreKey()); + EXPECT_NE(vid4->GetValueStoreKey(), vid5->GetValueStoreKey()); + EXPECT_NE(vid4->GetValueStoreKey(), vid6->GetValueStoreKey()); + EXPECT_NE(vid5->GetValueStoreKey(), vid6->GetValueStoreKey()); + + delete vid1; + delete vid2; + delete vid3; + delete vid4; + delete vid5; + delete vid6; +} +} // namespace Testing +} // namespace OpenZWave \ No newline at end of file diff --git a/cpp/test/include/gtest/gtest-death-test.h b/cpp/test/include/gtest/gtest-death-test.h index 957a69c6a9..dc878ffbb3 100644 --- a/cpp/test/include/gtest/gtest-death-test.h +++ b/cpp/test/include/gtest/gtest-death-test.h @@ -26,14 +26,14 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + // -// Author: wan@google.com (Zhanyong Wan) -// -// The Google C++ Testing Framework (Google Test) +// The Google C++ Testing and Mocking Framework (Google Test) // // This header file defines the public API for death tests. It is // #included by gtest.h so a user doesn't need to include this // directly. +// GOOGLETEST_CM0001 DO NOT DELETE #ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ #define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ @@ -99,10 +99,11 @@ GTEST_API_ bool InDeathTestChild(); // // On the regular expressions used in death tests: // +// GOOGLETEST_CM0005 DO NOT DELETE // On POSIX-compliant systems (*nix), we use the library, // which uses the POSIX extended regex syntax. // -// On other platforms (e.g. Windows), we only support a simple regex +// On other platforms (e.g. Windows or Mac), we only support a simple regex // syntax implemented as part of Google Test. This limited // implementation should be enough most of the time when writing // death tests; though it lacks many features you can find in PCRE @@ -160,7 +161,6 @@ GTEST_API_ bool InDeathTestChild(); // is rarely a problem as people usually don't put the test binary // directory in PATH. // -// TODO(wan@google.com): make thread-safe death tests search the PATH. // Asserts that a given statement causes the program to exit, with an // integer exit status that satisfies predicate, and emitting error output @@ -169,7 +169,7 @@ GTEST_API_ bool InDeathTestChild(); GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_) // Like ASSERT_EXIT, but continues on to successive tests in the -// test case, if any: +// test suite, if any: # define EXPECT_EXIT(statement, predicate, regex) \ GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_) @@ -180,7 +180,7 @@ GTEST_API_ bool InDeathTestChild(); ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex) // Like ASSERT_DEATH, but continues on to successive tests in the -// test case, if any: +// test suite, if any: # define EXPECT_DEATH(statement, regex) \ EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex) @@ -198,9 +198,10 @@ class GTEST_API_ ExitedWithCode { const int exit_code_; }; -# if !GTEST_OS_WINDOWS +# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA // Tests that an exit code describes an exit due to termination by a // given signal. +// GOOGLETEST_CM0006 DO NOT DELETE class GTEST_API_ KilledBySignal { public: explicit KilledBySignal(int signum); @@ -226,7 +227,7 @@ class GTEST_API_ KilledBySignal { // return 12; // } // -// TEST(TestCase, TestDieOr12WorksInDgbAndOpt) { +// TEST(TestSuite, TestDieOr12WorksInDgbAndOpt) { // int sideeffect = 0; // // Only asserts in dbg. // EXPECT_DEBUG_DEATH(DieInDebugOr12(&sideeffect), "death"); @@ -272,6 +273,54 @@ class GTEST_API_ KilledBySignal { # endif // NDEBUG for EXPECT_DEBUG_DEATH #endif // GTEST_HAS_DEATH_TEST +// This macro is used for implementing macros such as +// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where +// death tests are not supported. Those macros must compile on such systems +// if and only if EXPECT_DEATH and ASSERT_DEATH compile with the same parameters +// on systems that support death tests. This allows one to write such a macro on +// a system that does not support death tests and be sure that it will compile +// on a death-test supporting system. It is exposed publicly so that systems +// that have death-tests with stricter requirements than GTEST_HAS_DEATH_TEST +// can write their own equivalent of EXPECT_DEATH_IF_SUPPORTED and +// ASSERT_DEATH_IF_SUPPORTED. +// +// Parameters: +// statement - A statement that a macro such as EXPECT_DEATH would test +// for program termination. This macro has to make sure this +// statement is compiled but not executed, to ensure that +// EXPECT_DEATH_IF_SUPPORTED compiles with a certain +// parameter if and only if EXPECT_DEATH compiles with it. +// regex - A regex that a macro such as EXPECT_DEATH would use to test +// the output of statement. This parameter has to be +// compiled but not evaluated by this macro, to ensure that +// this macro only accepts expressions that a macro such as +// EXPECT_DEATH would accept. +// terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED +// and a return statement for ASSERT_DEATH_IF_SUPPORTED. +// This ensures that ASSERT_DEATH_IF_SUPPORTED will not +// compile inside functions where ASSERT_DEATH doesn't +// compile. +// +// The branch that has an always false condition is used to ensure that +// statement and regex are compiled (and thus syntactically correct) but +// never executed. The unreachable code macro protects the terminator +// statement from generating an 'unreachable code' warning in case +// statement unconditionally returns or throws. The Message constructor at +// the end allows the syntax of streaming additional messages into the +// macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH. +# define GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, terminator) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + GTEST_LOG_(WARNING) \ + << "Death tests are not supported on this platform.\n" \ + << "Statement '" #statement "' cannot be verified."; \ + } else if (::testing::internal::AlwaysFalse()) { \ + ::testing::internal::RE::PartialMatch(".*", (regex)); \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + terminator; \ + } else \ + ::testing::Message() + // EXPECT_DEATH_IF_SUPPORTED(statement, regex) and // ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if // death tests are supported; otherwise they just issue a warning. This is @@ -284,9 +333,9 @@ class GTEST_API_ KilledBySignal { ASSERT_DEATH(statement, regex) #else # define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \ - GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, ) + GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, ) # define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \ - GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, return) + GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, return) #endif } // namespace testing diff --git a/cpp/test/include/gtest/gtest-matchers.h b/cpp/test/include/gtest/gtest-matchers.h new file mode 100644 index 0000000000..d9b28e08a3 --- /dev/null +++ b/cpp/test/include/gtest/gtest-matchers.h @@ -0,0 +1,750 @@ +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// The Google C++ Testing and Mocking Framework (Google Test) +// +// This file implements just enough of the matcher interface to allow +// EXPECT_DEATH and friends to accept a matcher argument. + +// IWYU pragma: private, include "testing/base/public/gunit.h" +// IWYU pragma: friend third_party/googletest/googlemock/.* +// IWYU pragma: friend third_party/googletest/googletest/.* + +#ifndef GTEST_INCLUDE_GTEST_GTEST_MATCHERS_H_ +#define GTEST_INCLUDE_GTEST_GTEST_MATCHERS_H_ + +#include +#include +#include +#include + +#include "gtest/gtest-printers.h" +#include "gtest/internal/gtest-internal.h" +#include "gtest/internal/gtest-port.h" + +// MSVC warning C5046 is new as of VS2017 version 15.8. +#if defined(_MSC_VER) && _MSC_VER >= 1915 +#define GTEST_MAYBE_5046_ 5046 +#else +#define GTEST_MAYBE_5046_ +#endif + +GTEST_DISABLE_MSC_WARNINGS_PUSH_( + 4251 GTEST_MAYBE_5046_ /* class A needs to have dll-interface to be used by + clients of class B */ + /* Symbol involving type with internal linkage not defined */) + +namespace testing { + +// To implement a matcher Foo for type T, define: +// 1. a class FooMatcherImpl that implements the +// MatcherInterface interface, and +// 2. a factory function that creates a Matcher object from a +// FooMatcherImpl*. +// +// The two-level delegation design makes it possible to allow a user +// to write "v" instead of "Eq(v)" where a Matcher is expected, which +// is impossible if we pass matchers by pointers. It also eases +// ownership management as Matcher objects can now be copied like +// plain values. + +// MatchResultListener is an abstract class. Its << operator can be +// used by a matcher to explain why a value matches or doesn't match. +// +class MatchResultListener { + public: + // Creates a listener object with the given underlying ostream. The + // listener does not own the ostream, and does not dereference it + // in the constructor or destructor. + explicit MatchResultListener(::std::ostream* os) : stream_(os) {} + virtual ~MatchResultListener() = 0; // Makes this class abstract. + + // Streams x to the underlying ostream; does nothing if the ostream + // is NULL. + template + MatchResultListener& operator<<(const T& x) { + if (stream_ != nullptr) *stream_ << x; + return *this; + } + + // Returns the underlying ostream. + ::std::ostream* stream() { return stream_; } + + // Returns true if and only if the listener is interested in an explanation + // of the match result. A matcher's MatchAndExplain() method can use + // this information to avoid generating the explanation when no one + // intends to hear it. + bool IsInterested() const { return stream_ != nullptr; } + + private: + ::std::ostream* const stream_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(MatchResultListener); +}; + +inline MatchResultListener::~MatchResultListener() { +} + +// An instance of a subclass of this knows how to describe itself as a +// matcher. +class MatcherDescriberInterface { + public: + virtual ~MatcherDescriberInterface() {} + + // Describes this matcher to an ostream. The function should print + // a verb phrase that describes the property a value matching this + // matcher should have. The subject of the verb phrase is the value + // being matched. For example, the DescribeTo() method of the Gt(7) + // matcher prints "is greater than 7". + virtual void DescribeTo(::std::ostream* os) const = 0; + + // Describes the negation of this matcher to an ostream. For + // example, if the description of this matcher is "is greater than + // 7", the negated description could be "is not greater than 7". + // You are not required to override this when implementing + // MatcherInterface, but it is highly advised so that your matcher + // can produce good error messages. + virtual void DescribeNegationTo(::std::ostream* os) const { + *os << "not ("; + DescribeTo(os); + *os << ")"; + } +}; + +// The implementation of a matcher. +template +class MatcherInterface : public MatcherDescriberInterface { + public: + // Returns true if and only if the matcher matches x; also explains the + // match result to 'listener' if necessary (see the next paragraph), in + // the form of a non-restrictive relative clause ("which ...", + // "whose ...", etc) that describes x. For example, the + // MatchAndExplain() method of the Pointee(...) matcher should + // generate an explanation like "which points to ...". + // + // Implementations of MatchAndExplain() should add an explanation of + // the match result *if and only if* they can provide additional + // information that's not already present (or not obvious) in the + // print-out of x and the matcher's description. Whether the match + // succeeds is not a factor in deciding whether an explanation is + // needed, as sometimes the caller needs to print a failure message + // when the match succeeds (e.g. when the matcher is used inside + // Not()). + // + // For example, a "has at least 10 elements" matcher should explain + // what the actual element count is, regardless of the match result, + // as it is useful information to the reader; on the other hand, an + // "is empty" matcher probably only needs to explain what the actual + // size is when the match fails, as it's redundant to say that the + // size is 0 when the value is already known to be empty. + // + // You should override this method when defining a new matcher. + // + // It's the responsibility of the caller (Google Test) to guarantee + // that 'listener' is not NULL. This helps to simplify a matcher's + // implementation when it doesn't care about the performance, as it + // can talk to 'listener' without checking its validity first. + // However, in order to implement dummy listeners efficiently, + // listener->stream() may be NULL. + virtual bool MatchAndExplain(T x, MatchResultListener* listener) const = 0; + + // Inherits these methods from MatcherDescriberInterface: + // virtual void DescribeTo(::std::ostream* os) const = 0; + // virtual void DescribeNegationTo(::std::ostream* os) const; +}; + +namespace internal { + +// Converts a MatcherInterface to a MatcherInterface. +template +class MatcherInterfaceAdapter : public MatcherInterface { + public: + explicit MatcherInterfaceAdapter(const MatcherInterface* impl) + : impl_(impl) {} + ~MatcherInterfaceAdapter() override { delete impl_; } + + void DescribeTo(::std::ostream* os) const override { impl_->DescribeTo(os); } + + void DescribeNegationTo(::std::ostream* os) const override { + impl_->DescribeNegationTo(os); + } + + bool MatchAndExplain(const T& x, + MatchResultListener* listener) const override { + return impl_->MatchAndExplain(x, listener); + } + + private: + const MatcherInterface* const impl_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(MatcherInterfaceAdapter); +}; + +struct AnyEq { + template + bool operator()(const A& a, const B& b) const { return a == b; } +}; +struct AnyNe { + template + bool operator()(const A& a, const B& b) const { return a != b; } +}; +struct AnyLt { + template + bool operator()(const A& a, const B& b) const { return a < b; } +}; +struct AnyGt { + template + bool operator()(const A& a, const B& b) const { return a > b; } +}; +struct AnyLe { + template + bool operator()(const A& a, const B& b) const { return a <= b; } +}; +struct AnyGe { + template + bool operator()(const A& a, const B& b) const { return a >= b; } +}; + +// A match result listener that ignores the explanation. +class DummyMatchResultListener : public MatchResultListener { + public: + DummyMatchResultListener() : MatchResultListener(nullptr) {} + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(DummyMatchResultListener); +}; + +// A match result listener that forwards the explanation to a given +// ostream. The difference between this and MatchResultListener is +// that the former is concrete. +class StreamMatchResultListener : public MatchResultListener { + public: + explicit StreamMatchResultListener(::std::ostream* os) + : MatchResultListener(os) {} + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamMatchResultListener); +}; + +// An internal class for implementing Matcher, which will derive +// from it. We put functionalities common to all Matcher +// specializations here to avoid code duplication. +template +class MatcherBase { + public: + // Returns true if and only if the matcher matches x; also explains the + // match result to 'listener'. + bool MatchAndExplain(const T& x, MatchResultListener* listener) const { + return impl_->MatchAndExplain(x, listener); + } + + // Returns true if and only if this matcher matches x. + bool Matches(const T& x) const { + DummyMatchResultListener dummy; + return MatchAndExplain(x, &dummy); + } + + // Describes this matcher to an ostream. + void DescribeTo(::std::ostream* os) const { impl_->DescribeTo(os); } + + // Describes the negation of this matcher to an ostream. + void DescribeNegationTo(::std::ostream* os) const { + impl_->DescribeNegationTo(os); + } + + // Explains why x matches, or doesn't match, the matcher. + void ExplainMatchResultTo(const T& x, ::std::ostream* os) const { + StreamMatchResultListener listener(os); + MatchAndExplain(x, &listener); + } + + // Returns the describer for this matcher object; retains ownership + // of the describer, which is only guaranteed to be alive when + // this matcher object is alive. + const MatcherDescriberInterface* GetDescriber() const { + return impl_.get(); + } + + protected: + MatcherBase() {} + + // Constructs a matcher from its implementation. + explicit MatcherBase(const MatcherInterface* impl) : impl_(impl) {} + + template + explicit MatcherBase( + const MatcherInterface* impl, + typename std::enable_if::value>::type* = + nullptr) + : impl_(new internal::MatcherInterfaceAdapter(impl)) {} + + MatcherBase(const MatcherBase&) = default; + MatcherBase& operator=(const MatcherBase&) = default; + MatcherBase(MatcherBase&&) = default; + MatcherBase& operator=(MatcherBase&&) = default; + + virtual ~MatcherBase() {} + + private: + std::shared_ptr> impl_; +}; + +} // namespace internal + +// A Matcher is a copyable and IMMUTABLE (except by assignment) +// object that can check whether a value of type T matches. The +// implementation of Matcher is just a std::shared_ptr to const +// MatcherInterface. Don't inherit from Matcher! +template +class Matcher : public internal::MatcherBase { + public: + // Constructs a null matcher. Needed for storing Matcher objects in STL + // containers. A default-constructed matcher is not yet initialized. You + // cannot use it until a valid value has been assigned to it. + explicit Matcher() {} // NOLINT + + // Constructs a matcher from its implementation. + explicit Matcher(const MatcherInterface* impl) + : internal::MatcherBase(impl) {} + + template + explicit Matcher( + const MatcherInterface* impl, + typename std::enable_if::value>::type* = + nullptr) + : internal::MatcherBase(impl) {} + + // Implicit constructor here allows people to write + // EXPECT_CALL(foo, Bar(5)) instead of EXPECT_CALL(foo, Bar(Eq(5))) sometimes + Matcher(T value); // NOLINT +}; + +// The following two specializations allow the user to write str +// instead of Eq(str) and "foo" instead of Eq("foo") when a std::string +// matcher is expected. +template <> +class GTEST_API_ Matcher + : public internal::MatcherBase { + public: + Matcher() {} + + explicit Matcher(const MatcherInterface* impl) + : internal::MatcherBase(impl) {} + + // Allows the user to write str instead of Eq(str) sometimes, where + // str is a std::string object. + Matcher(const std::string& s); // NOLINT + + // Allows the user to write "foo" instead of Eq("foo") sometimes. + Matcher(const char* s); // NOLINT +}; + +template <> +class GTEST_API_ Matcher + : public internal::MatcherBase { + public: + Matcher() {} + + explicit Matcher(const MatcherInterface* impl) + : internal::MatcherBase(impl) {} + explicit Matcher(const MatcherInterface* impl) + : internal::MatcherBase(impl) {} + + // Allows the user to write str instead of Eq(str) sometimes, where + // str is a string object. + Matcher(const std::string& s); // NOLINT + + // Allows the user to write "foo" instead of Eq("foo") sometimes. + Matcher(const char* s); // NOLINT +}; + +#if GTEST_HAS_ABSL +// The following two specializations allow the user to write str +// instead of Eq(str) and "foo" instead of Eq("foo") when a absl::string_view +// matcher is expected. +template <> +class GTEST_API_ Matcher + : public internal::MatcherBase { + public: + Matcher() {} + + explicit Matcher(const MatcherInterface* impl) + : internal::MatcherBase(impl) {} + + // Allows the user to write str instead of Eq(str) sometimes, where + // str is a std::string object. + Matcher(const std::string& s); // NOLINT + + // Allows the user to write "foo" instead of Eq("foo") sometimes. + Matcher(const char* s); // NOLINT + + // Allows the user to pass absl::string_views directly. + Matcher(absl::string_view s); // NOLINT +}; + +template <> +class GTEST_API_ Matcher + : public internal::MatcherBase { + public: + Matcher() {} + + explicit Matcher(const MatcherInterface* impl) + : internal::MatcherBase(impl) {} + explicit Matcher(const MatcherInterface* impl) + : internal::MatcherBase(impl) {} + + // Allows the user to write str instead of Eq(str) sometimes, where + // str is a std::string object. + Matcher(const std::string& s); // NOLINT + + // Allows the user to write "foo" instead of Eq("foo") sometimes. + Matcher(const char* s); // NOLINT + + // Allows the user to pass absl::string_views directly. + Matcher(absl::string_view s); // NOLINT +}; +#endif // GTEST_HAS_ABSL + +// Prints a matcher in a human-readable format. +template +std::ostream& operator<<(std::ostream& os, const Matcher& matcher) { + matcher.DescribeTo(&os); + return os; +} + +// The PolymorphicMatcher class template makes it easy to implement a +// polymorphic matcher (i.e. a matcher that can match values of more +// than one type, e.g. Eq(n) and NotNull()). +// +// To define a polymorphic matcher, a user should provide an Impl +// class that has a DescribeTo() method and a DescribeNegationTo() +// method, and define a member function (or member function template) +// +// bool MatchAndExplain(const Value& value, +// MatchResultListener* listener) const; +// +// See the definition of NotNull() for a complete example. +template +class PolymorphicMatcher { + public: + explicit PolymorphicMatcher(const Impl& an_impl) : impl_(an_impl) {} + + // Returns a mutable reference to the underlying matcher + // implementation object. + Impl& mutable_impl() { return impl_; } + + // Returns an immutable reference to the underlying matcher + // implementation object. + const Impl& impl() const { return impl_; } + + template + operator Matcher() const { + return Matcher(new MonomorphicImpl(impl_)); + } + + private: + template + class MonomorphicImpl : public MatcherInterface { + public: + explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {} + + void DescribeTo(::std::ostream* os) const override { impl_.DescribeTo(os); } + + void DescribeNegationTo(::std::ostream* os) const override { + impl_.DescribeNegationTo(os); + } + + bool MatchAndExplain(T x, MatchResultListener* listener) const override { + return impl_.MatchAndExplain(x, listener); + } + + private: + const Impl impl_; + }; + + Impl impl_; +}; + +// Creates a matcher from its implementation. +// DEPRECATED: Especially in the generic code, prefer: +// Matcher(new MyMatcherImpl(...)); +// +// MakeMatcher may create a Matcher that accepts its argument by value, which +// leads to unnecessary copies & lack of support for non-copyable types. +template +inline Matcher MakeMatcher(const MatcherInterface* impl) { + return Matcher(impl); +} + +// Creates a polymorphic matcher from its implementation. This is +// easier to use than the PolymorphicMatcher constructor as it +// doesn't require you to explicitly write the template argument, e.g. +// +// MakePolymorphicMatcher(foo); +// vs +// PolymorphicMatcher(foo); +template +inline PolymorphicMatcher MakePolymorphicMatcher(const Impl& impl) { + return PolymorphicMatcher(impl); +} + +namespace internal { +// Implements a matcher that compares a given value with a +// pre-supplied value using one of the ==, <=, <, etc, operators. The +// two values being compared don't have to have the same type. +// +// The matcher defined here is polymorphic (for example, Eq(5) can be +// used to match an int, a short, a double, etc). Therefore we use +// a template type conversion operator in the implementation. +// +// The following template definition assumes that the Rhs parameter is +// a "bare" type (i.e. neither 'const T' nor 'T&'). +template +class ComparisonBase { + public: + explicit ComparisonBase(const Rhs& rhs) : rhs_(rhs) {} + template + operator Matcher() const { + return Matcher(new Impl(rhs_)); + } + + private: + template + static const T& Unwrap(const T& v) { return v; } + template + static const T& Unwrap(std::reference_wrapper v) { return v; } + + template + class Impl : public MatcherInterface { + public: + explicit Impl(const Rhs& rhs) : rhs_(rhs) {} + bool MatchAndExplain(Lhs lhs, + MatchResultListener* /* listener */) const override { + return Op()(lhs, Unwrap(rhs_)); + } + void DescribeTo(::std::ostream* os) const override { + *os << D::Desc() << " "; + UniversalPrint(Unwrap(rhs_), os); + } + void DescribeNegationTo(::std::ostream* os) const override { + *os << D::NegatedDesc() << " "; + UniversalPrint(Unwrap(rhs_), os); + } + + private: + Rhs rhs_; + }; + Rhs rhs_; +}; + +template +class EqMatcher : public ComparisonBase, Rhs, AnyEq> { + public: + explicit EqMatcher(const Rhs& rhs) + : ComparisonBase, Rhs, AnyEq>(rhs) { } + static const char* Desc() { return "is equal to"; } + static const char* NegatedDesc() { return "isn't equal to"; } +}; +template +class NeMatcher : public ComparisonBase, Rhs, AnyNe> { + public: + explicit NeMatcher(const Rhs& rhs) + : ComparisonBase, Rhs, AnyNe>(rhs) { } + static const char* Desc() { return "isn't equal to"; } + static const char* NegatedDesc() { return "is equal to"; } +}; +template +class LtMatcher : public ComparisonBase, Rhs, AnyLt> { + public: + explicit LtMatcher(const Rhs& rhs) + : ComparisonBase, Rhs, AnyLt>(rhs) { } + static const char* Desc() { return "is <"; } + static const char* NegatedDesc() { return "isn't <"; } +}; +template +class GtMatcher : public ComparisonBase, Rhs, AnyGt> { + public: + explicit GtMatcher(const Rhs& rhs) + : ComparisonBase, Rhs, AnyGt>(rhs) { } + static const char* Desc() { return "is >"; } + static const char* NegatedDesc() { return "isn't >"; } +}; +template +class LeMatcher : public ComparisonBase, Rhs, AnyLe> { + public: + explicit LeMatcher(const Rhs& rhs) + : ComparisonBase, Rhs, AnyLe>(rhs) { } + static const char* Desc() { return "is <="; } + static const char* NegatedDesc() { return "isn't <="; } +}; +template +class GeMatcher : public ComparisonBase, Rhs, AnyGe> { + public: + explicit GeMatcher(const Rhs& rhs) + : ComparisonBase, Rhs, AnyGe>(rhs) { } + static const char* Desc() { return "is >="; } + static const char* NegatedDesc() { return "isn't >="; } +}; + +// Implements polymorphic matchers MatchesRegex(regex) and +// ContainsRegex(regex), which can be used as a Matcher as long as +// T can be converted to a string. +class MatchesRegexMatcher { + public: + MatchesRegexMatcher(const RE* regex, bool full_match) + : regex_(regex), full_match_(full_match) {} + +#if GTEST_HAS_ABSL + bool MatchAndExplain(const absl::string_view& s, + MatchResultListener* listener) const { + return MatchAndExplain(std::string(s), listener); + } +#endif // GTEST_HAS_ABSL + + // Accepts pointer types, particularly: + // const char* + // char* + // const wchar_t* + // wchar_t* + template + bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { + return s != nullptr && MatchAndExplain(std::string(s), listener); + } + + // Matches anything that can convert to std::string. + // + // This is a template, not just a plain function with const std::string&, + // because absl::string_view has some interfering non-explicit constructors. + template + bool MatchAndExplain(const MatcheeStringType& s, + MatchResultListener* /* listener */) const { + const std::string& s2(s); + return full_match_ ? RE::FullMatch(s2, *regex_) + : RE::PartialMatch(s2, *regex_); + } + + void DescribeTo(::std::ostream* os) const { + *os << (full_match_ ? "matches" : "contains") << " regular expression "; + UniversalPrinter::Print(regex_->pattern(), os); + } + + void DescribeNegationTo(::std::ostream* os) const { + *os << "doesn't " << (full_match_ ? "match" : "contain") + << " regular expression "; + UniversalPrinter::Print(regex_->pattern(), os); + } + + private: + const std::shared_ptr regex_; + const bool full_match_; +}; +} // namespace internal + +// Matches a string that fully matches regular expression 'regex'. +// The matcher takes ownership of 'regex'. +inline PolymorphicMatcher MatchesRegex( + const internal::RE* regex) { + return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, true)); +} +inline PolymorphicMatcher MatchesRegex( + const std::string& regex) { + return MatchesRegex(new internal::RE(regex)); +} + +// Matches a string that contains regular expression 'regex'. +// The matcher takes ownership of 'regex'. +inline PolymorphicMatcher ContainsRegex( + const internal::RE* regex) { + return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, false)); +} +inline PolymorphicMatcher ContainsRegex( + const std::string& regex) { + return ContainsRegex(new internal::RE(regex)); +} + +// Creates a polymorphic matcher that matches anything equal to x. +// Note: if the parameter of Eq() were declared as const T&, Eq("foo") +// wouldn't compile. +template +inline internal::EqMatcher Eq(T x) { return internal::EqMatcher(x); } + +// Constructs a Matcher from a 'value' of type T. The constructed +// matcher matches any value that's equal to 'value'. +template +Matcher::Matcher(T value) { *this = Eq(value); } + +// Creates a monomorphic matcher that matches anything with type Lhs +// and equal to rhs. A user may need to use this instead of Eq(...) +// in order to resolve an overloading ambiguity. +// +// TypedEq(x) is just a convenient short-hand for Matcher(Eq(x)) +// or Matcher(x), but more readable than the latter. +// +// We could define similar monomorphic matchers for other comparison +// operations (e.g. TypedLt, TypedGe, and etc), but decided not to do +// it yet as those are used much less than Eq() in practice. A user +// can always write Matcher(Lt(5)) to be explicit about the type, +// for example. +template +inline Matcher TypedEq(const Rhs& rhs) { return Eq(rhs); } + +// Creates a polymorphic matcher that matches anything >= x. +template +inline internal::GeMatcher Ge(Rhs x) { + return internal::GeMatcher(x); +} + +// Creates a polymorphic matcher that matches anything > x. +template +inline internal::GtMatcher Gt(Rhs x) { + return internal::GtMatcher(x); +} + +// Creates a polymorphic matcher that matches anything <= x. +template +inline internal::LeMatcher Le(Rhs x) { + return internal::LeMatcher(x); +} + +// Creates a polymorphic matcher that matches anything < x. +template +inline internal::LtMatcher Lt(Rhs x) { + return internal::LtMatcher(x); +} + +// Creates a polymorphic matcher that matches anything != x. +template +inline internal::NeMatcher Ne(Rhs x) { + return internal::NeMatcher(x); +} +} // namespace testing + +GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 5046 + +#endif // GTEST_INCLUDE_GTEST_GTEST_MATCHERS_H_ diff --git a/cpp/test/include/gtest/gtest-message.h b/cpp/test/include/gtest/gtest-message.h index fe879bca79..21899232a2 100644 --- a/cpp/test/include/gtest/gtest-message.h +++ b/cpp/test/include/gtest/gtest-message.h @@ -26,10 +26,9 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + // -// Author: wan@google.com (Zhanyong Wan) -// -// The Google C++ Testing Framework (Google Test) +// The Google C++ Testing and Mocking Framework (Google Test) // // This header file defines the Message class. // @@ -43,13 +42,20 @@ // to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user // program! +// GOOGLETEST_CM0001 DO NOT DELETE + #ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ #define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ #include +#include +#include #include "gtest/internal/gtest-port.h" +GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ +/* class A needs to have dll-interface to be used by clients of class B */) + // Ensures that there is at least one operator<< in the global namespace. // See Message& operator<<(...) below for why. void operator<<(const testing::internal::Secret&, int); @@ -102,14 +108,6 @@ class GTEST_API_ Message { *ss_ << str; } -#if GTEST_OS_SYMBIAN - // Streams a value (either a pointer or not) to this object. - template - inline Message& operator <<(const T& value) { - StreamHelper(typename internal::is_pointer::type(), value); - return *this; - } -#else // Streams a non-pointer value to this object. template inline Message& operator <<(const T& val) { @@ -147,14 +145,13 @@ class GTEST_API_ Message { // as "(null)". template inline Message& operator <<(T* const& pointer) { // NOLINT - if (pointer == NULL) { + if (pointer == nullptr) { *ss_ << "(null)"; } else { *ss_ << pointer; } return *this; } -#endif // GTEST_OS_SYMBIAN // Since the basic IO manipulators are overloaded for both narrow // and wide streams, we have to provide this specialized definition @@ -183,12 +180,6 @@ class GTEST_API_ Message { Message& operator <<(const ::std::wstring& wstr); #endif // GTEST_HAS_STD_WSTRING -#if GTEST_HAS_GLOBAL_WSTRING - // Converts the given wide string to a narrow string using the UTF-8 - // encoding, and streams the result to this Message object. - Message& operator <<(const ::wstring& wstr); -#endif // GTEST_HAS_GLOBAL_WSTRING - // Gets the text streamed to this object so far as an std::string. // Each '\0' character in the buffer is replaced with "\\0". // @@ -196,32 +187,8 @@ class GTEST_API_ Message { std::string GetString() const; private: - -#if GTEST_OS_SYMBIAN - // These are needed as the Nokia Symbian Compiler cannot decide between - // const T& and const T* in a function template. The Nokia compiler _can_ - // decide between class template specializations for T and T*, so a - // tr1::type_traits-like is_pointer works, and we can overload on that. - template - inline void StreamHelper(internal::true_type /*is_pointer*/, T* pointer) { - if (pointer == NULL) { - *ss_ << "(null)"; - } else { - *ss_ << pointer; - } - } - template - inline void StreamHelper(internal::false_type /*is_pointer*/, - const T& value) { - // See the comments in Message& operator <<(const T&) above for why - // we need this using statement. - using ::operator <<; - *ss_ << value; - } -#endif // GTEST_OS_SYMBIAN - // We'll hold the text streamed to this object here. - const internal::scoped_ptr< ::std::stringstream> ss_; + const std::unique_ptr< ::std::stringstream> ss_; // We declare (but don't implement) this to prevent the compiler // from implementing the assignment operator. @@ -247,4 +214,6 @@ std::string StreamableToString(const T& streamable) { } // namespace internal } // namespace testing +GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 + #endif // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ diff --git a/cpp/test/include/gtest/gtest-param-test.h b/cpp/test/include/gtest/gtest-param-test.h index 038f9ba79e..f61e3c5d88 100644 --- a/cpp/test/include/gtest/gtest-param-test.h +++ b/cpp/test/include/gtest/gtest-param-test.h @@ -1,7 +1,3 @@ -// This file was GENERATED by command: -// pump.py gtest-param-test.h.pump -// DO NOT EDIT BY HAND!!! - // Copyright 2008, Google Inc. // All rights reserved. // @@ -31,13 +27,12 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // -// Authors: vladl@google.com (Vlad Losev) -// // Macros and functions for implementing parameterized tests -// in Google C++ Testing Framework (Google Test) +// in Google C++ Testing and Mocking Framework (Google Test) // // This file is generated by a SCRIPT. DO NOT EDIT BY HAND! // +// GOOGLETEST_CM0001 DO NOT DELETE #ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ #define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ @@ -63,7 +58,9 @@ class FooTest : public ::testing::TestWithParam { // Then, use the TEST_P macro to define as many parameterized tests // for this fixture as you want. The _P suffix is for "parameterized" -// or "pattern", whichever you prefer to think. +// or "pattern", whichever you prefer to think. The arguments to the +// TEST_P macro are the test_suite_name and test_case (both which must be +// non-empty) that will form the test name. TEST_P(FooTest, DoesBlah) { // Inside a test, access the test parameter with the GetParam() method @@ -76,10 +73,10 @@ TEST_P(FooTest, HasBlahBlah) { ... } -// Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test +// Finally, you can use INSTANTIATE_TEST_SUITE_P to instantiate the test // case with any set of parameters you want. Google Test defines a number // of functions for generating test parameters. They return what we call -// (surprise!) parameter generators. Here is a summary of them, which +// (surprise!) parameter generators. Here is a summary of them, which // are all in the testing namespace: // // @@ -97,19 +94,19 @@ TEST_P(FooTest, HasBlahBlah) { // For more details, see comments at the definitions of these functions below // in this file. // -// The following statement will instantiate tests from the FooTest test case +// The following statement will instantiate tests from the FooTest test suite // each with parameter values "meeny", "miny", and "moe". -INSTANTIATE_TEST_CASE_P(InstantiationName, - FooTest, - Values("meeny", "miny", "moe")); +INSTANTIATE_TEST_SUITE_P(InstantiationName, + FooTest, + Values("meeny", "miny", "moe")); // To distinguish different instances of the pattern, (yes, you -// can instantiate it more then once) the first argument to the -// INSTANTIATE_TEST_CASE_P macro is a prefix that will be added to the -// actual test case name. Remember to pick unique prefixes for different -// instantiations. The tests from the instantiation above will have -// these names: +// can instantiate it more than once) the first argument to the +// INSTANTIATE_TEST_SUITE_P macro is a prefix (which must be non-empty) that +// will be added to the actual test suite name. Remember to pick unique prefixes +// for different instantiations. The tests from the instantiation above will +// have these names: // // * InstantiationName/FooTest.DoesBlah/0 for "meeny" // * InstantiationName/FooTest.DoesBlah/1 for "miny" @@ -124,7 +121,7 @@ INSTANTIATE_TEST_CASE_P(InstantiationName, // with parameter values "cat" and "dog": const char* pets[] = {"cat", "dog"}; -INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets)); +INSTANTIATE_TEST_SUITE_P(AnotherInstantiationName, FooTest, ValuesIn(pets)); // The tests from the instantiation above will have these names: // @@ -133,9 +130,9 @@ INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets)); // * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat" // * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog" // -// Please note that INSTANTIATE_TEST_CASE_P will instantiate all tests -// in the given test case, whether their definitions come before or -// AFTER the INSTANTIATE_TEST_CASE_P statement. +// Please note that INSTANTIATE_TEST_SUITE_P will instantiate all tests +// in the given test suite, whether their definitions come before or +// AFTER the INSTANTIATE_TEST_SUITE_P statement. // // Please also note that generator expressions (including parameters to the // generators) are evaluated in InitGoogleTest(), after main() has started. @@ -179,31 +176,23 @@ TEST_P(DerivedTest, DoesBlah) { #endif // 0 -#include "gtest/internal/gtest-port.h" - -#if !GTEST_OS_SYMBIAN -# include -#endif +#include +#include -// scripts/fuse_gtest.py depends on gtest's own header being #included -// *unconditionally*. Therefore these #includes cannot be moved -// inside #if GTEST_HAS_PARAM_TEST. #include "gtest/internal/gtest-internal.h" #include "gtest/internal/gtest-param-util.h" -#include "gtest/internal/gtest-param-util-generated.h" - -#if GTEST_HAS_PARAM_TEST +#include "gtest/internal/gtest-port.h" namespace testing { // Functions producing parameter generators. // // Google Test uses these generators to produce parameters for value- -// parameterized tests. When a parameterized test case is instantiated +// parameterized tests. When a parameterized test suite is instantiated // with a particular generator, Google Test creates and runs tests // for each element in the sequence produced by the generator. // -// In the following sample, tests from test case FooTest are instantiated +// In the following sample, tests from test suite FooTest are instantiated // each three times with parameter values 3, 5, and 8: // // class FooTest : public TestWithParam { ... }; @@ -212,7 +201,7 @@ namespace testing { // } // TEST_P(FooTest, TestThat) { // } -// INSTANTIATE_TEST_CASE_P(TestSequence, FooTest, Values(3, 5, 8)); +// INSTANTIATE_TEST_SUITE_P(TestSequence, FooTest, Values(3, 5, 8)); // // Range() returns generators providing sequences of values in a range. @@ -269,13 +258,13 @@ internal::ParamGenerator Range(T start, T end) { // // Examples: // -// This instantiates tests from test case StringTest +// This instantiates tests from test suite StringTest // each with C-string values of "foo", "bar", and "baz": // // const char* strings[] = {"foo", "bar", "baz"}; -// INSTANTIATE_TEST_CASE_P(StringSequence, SrtingTest, ValuesIn(strings)); +// INSTANTIATE_TEST_SUITE_P(StringSequence, StringTest, ValuesIn(strings)); // -// This instantiates tests from test case StlStringTest +// This instantiates tests from test suite StlStringTest // each with STL strings with values "a" and "b": // // ::std::vector< ::std::string> GetParameterStrings() { @@ -285,9 +274,9 @@ internal::ParamGenerator Range(T start, T end) { // return v; // } // -// INSTANTIATE_TEST_CASE_P(CharSequence, -// StlStringTest, -// ValuesIn(GetParameterStrings())); +// INSTANTIATE_TEST_SUITE_P(CharSequence, +// StlStringTest, +// ValuesIn(GetParameterStrings())); // // // This will also instantiate tests from CharTest @@ -300,16 +289,15 @@ internal::ParamGenerator Range(T start, T end) { // return list; // } // ::std::list l = GetParameterChars(); -// INSTANTIATE_TEST_CASE_P(CharSequence2, -// CharTest, -// ValuesIn(l.begin(), l.end())); +// INSTANTIATE_TEST_SUITE_P(CharSequence2, +// CharTest, +// ValuesIn(l.begin(), l.end())); // template internal::ParamGenerator< - typename ::testing::internal::IteratorTraits::value_type> + typename std::iterator_traits::value_type> ValuesIn(ForwardIterator begin, ForwardIterator end) { - typedef typename ::testing::internal::IteratorTraits - ::value_type ParamType; + typedef typename std::iterator_traits::value_type ParamType; return internal::ParamGenerator( new internal::ValuesInIteratorRangeGenerator(begin, end)); } @@ -332,869 +320,22 @@ internal::ParamGenerator ValuesIn( // Values(T v1, T v2, ..., T vN) // - returns a generator producing sequences with elements v1, v2, ..., vN. // -// For example, this instantiates tests from test case BarTest each +// For example, this instantiates tests from test suite BarTest each // with values "one", "two", and "three": // -// INSTANTIATE_TEST_CASE_P(NumSequence, BarTest, Values("one", "two", "three")); +// INSTANTIATE_TEST_SUITE_P(NumSequence, +// BarTest, +// Values("one", "two", "three")); // -// This instantiates tests from test case BazTest each with values 1, 2, 3.5. +// This instantiates tests from test suite BazTest each with values 1, 2, 3.5. // The exact type of values will depend on the type of parameter in BazTest. // -// INSTANTIATE_TEST_CASE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5)); +// INSTANTIATE_TEST_SUITE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5)); // -// Currently, Values() supports from 1 to 50 parameters. // -template -internal::ValueArray1 Values(T1 v1) { - return internal::ValueArray1(v1); -} - -template -internal::ValueArray2 Values(T1 v1, T2 v2) { - return internal::ValueArray2(v1, v2); -} - -template -internal::ValueArray3 Values(T1 v1, T2 v2, T3 v3) { - return internal::ValueArray3(v1, v2, v3); -} - -template -internal::ValueArray4 Values(T1 v1, T2 v2, T3 v3, T4 v4) { - return internal::ValueArray4(v1, v2, v3, v4); -} - -template -internal::ValueArray5 Values(T1 v1, T2 v2, T3 v3, T4 v4, - T5 v5) { - return internal::ValueArray5(v1, v2, v3, v4, v5); -} - -template -internal::ValueArray6 Values(T1 v1, T2 v2, T3 v3, - T4 v4, T5 v5, T6 v6) { - return internal::ValueArray6(v1, v2, v3, v4, v5, v6); -} - -template -internal::ValueArray7 Values(T1 v1, T2 v2, T3 v3, - T4 v4, T5 v5, T6 v6, T7 v7) { - return internal::ValueArray7(v1, v2, v3, v4, v5, - v6, v7); -} - -template -internal::ValueArray8 Values(T1 v1, T2 v2, - T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8) { - return internal::ValueArray8(v1, v2, v3, v4, - v5, v6, v7, v8); -} - -template -internal::ValueArray9 Values(T1 v1, T2 v2, - T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9) { - return internal::ValueArray9(v1, v2, v3, - v4, v5, v6, v7, v8, v9); -} - -template -internal::ValueArray10 Values(T1 v1, - T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10) { - return internal::ValueArray10(v1, - v2, v3, v4, v5, v6, v7, v8, v9, v10); -} - -template -internal::ValueArray11 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11) { - return internal::ValueArray11(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11); -} - -template -internal::ValueArray12 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12) { - return internal::ValueArray12(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12); -} - -template -internal::ValueArray13 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13) { - return internal::ValueArray13(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13); -} - -template -internal::ValueArray14 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) { - return internal::ValueArray14(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, - v14); -} - -template -internal::ValueArray15 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, - T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) { - return internal::ValueArray15(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, - v13, v14, v15); -} - -template -internal::ValueArray16 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, - T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, - T16 v16) { - return internal::ValueArray16(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, - v12, v13, v14, v15, v16); -} - -template -internal::ValueArray17 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, - T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, - T16 v16, T17 v17) { - return internal::ValueArray17(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, - v11, v12, v13, v14, v15, v16, v17); -} - -template -internal::ValueArray18 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, - T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, - T16 v16, T17 v17, T18 v18) { - return internal::ValueArray18(v1, v2, v3, v4, v5, v6, v7, v8, v9, - v10, v11, v12, v13, v14, v15, v16, v17, v18); -} - -template -internal::ValueArray19 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, - T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, - T15 v15, T16 v16, T17 v17, T18 v18, T19 v19) { - return internal::ValueArray19(v1, v2, v3, v4, v5, v6, v7, v8, - v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19); -} - -template -internal::ValueArray20 Values(T1 v1, T2 v2, T3 v3, T4 v4, - T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, - T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20) { - return internal::ValueArray20(v1, v2, v3, v4, v5, v6, v7, - v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20); -} - -template -internal::ValueArray21 Values(T1 v1, T2 v2, T3 v3, T4 v4, - T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, - T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21) { - return internal::ValueArray21(v1, v2, v3, v4, v5, v6, - v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21); -} - -template -internal::ValueArray22 Values(T1 v1, T2 v2, T3 v3, - T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, - T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, - T21 v21, T22 v22) { - return internal::ValueArray22(v1, v2, v3, v4, - v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, - v20, v21, v22); -} - -template -internal::ValueArray23 Values(T1 v1, T2 v2, - T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, - T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, - T21 v21, T22 v22, T23 v23) { - return internal::ValueArray23(v1, v2, v3, - v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, - v20, v21, v22, v23); -} - -template -internal::ValueArray24 Values(T1 v1, T2 v2, - T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, - T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, - T21 v21, T22 v22, T23 v23, T24 v24) { - return internal::ValueArray24(v1, v2, - v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, - v19, v20, v21, v22, v23, v24); -} - -template -internal::ValueArray25 Values(T1 v1, - T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, - T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, - T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25) { - return internal::ValueArray25(v1, - v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, - v18, v19, v20, v21, v22, v23, v24, v25); -} - -template -internal::ValueArray26 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26) { - return internal::ValueArray26(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, - v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26); -} - -template -internal::ValueArray27 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27) { - return internal::ValueArray27(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, - v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27); -} - -template -internal::ValueArray28 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28) { - return internal::ValueArray28(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, - v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, - v28); -} - -template -internal::ValueArray29 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29) { - return internal::ValueArray29(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, - v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, - v27, v28, v29); -} - -template -internal::ValueArray30 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, - T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, - T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, - T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) { - return internal::ValueArray30(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, - v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, - v26, v27, v28, v29, v30); -} - -template -internal::ValueArray31 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, - T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, - T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, - T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) { - return internal::ValueArray31(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, - v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, - v25, v26, v27, v28, v29, v30, v31); -} - -template -internal::ValueArray32 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, - T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, - T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, - T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, - T32 v32) { - return internal::ValueArray32(v1, v2, v3, v4, v5, v6, v7, v8, v9, - v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, - v24, v25, v26, v27, v28, v29, v30, v31, v32); -} - -template -internal::ValueArray33 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, - T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, - T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, - T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, - T32 v32, T33 v33) { - return internal::ValueArray33(v1, v2, v3, v4, v5, v6, v7, v8, - v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, - v24, v25, v26, v27, v28, v29, v30, v31, v32, v33); -} - -template -internal::ValueArray34 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, - T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, - T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, - T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, - T31 v31, T32 v32, T33 v33, T34 v34) { - return internal::ValueArray34(v1, v2, v3, v4, v5, v6, v7, - v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, - v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34); -} - -template -internal::ValueArray35 Values(T1 v1, T2 v2, T3 v3, T4 v4, - T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, - T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, - T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, - T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35) { - return internal::ValueArray35(v1, v2, v3, v4, v5, v6, - v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, - v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35); -} - -template -internal::ValueArray36 Values(T1 v1, T2 v2, T3 v3, T4 v4, - T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, - T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, - T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, - T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36) { - return internal::ValueArray36(v1, v2, v3, v4, - v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, - v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, - v34, v35, v36); -} - -template -internal::ValueArray37 Values(T1 v1, T2 v2, T3 v3, - T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, - T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, - T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, - T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, - T37 v37) { - return internal::ValueArray37(v1, v2, v3, - v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, - v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, - v34, v35, v36, v37); -} - -template -internal::ValueArray38 Values(T1 v1, T2 v2, - T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, - T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, - T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, - T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, - T37 v37, T38 v38) { - return internal::ValueArray38(v1, v2, - v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, - v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, - v33, v34, v35, v36, v37, v38); -} - -template -internal::ValueArray39 Values(T1 v1, T2 v2, - T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, - T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, - T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, - T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, - T37 v37, T38 v38, T39 v39) { - return internal::ValueArray39(v1, - v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, - v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, - v32, v33, v34, v35, v36, v37, v38, v39); -} - -template -internal::ValueArray40 Values(T1 v1, - T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, - T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, - T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, - T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, - T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) { - return internal::ValueArray40(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, - v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, - v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40); -} - -template -internal::ValueArray41 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41) { - return internal::ValueArray41(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, - v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, - v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41); -} - -template -internal::ValueArray42 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, - T42 v42) { - return internal::ValueArray42(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, - v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, - v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, - v42); -} - -template -internal::ValueArray43 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, - T42 v42, T43 v43) { - return internal::ValueArray43(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, - v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, - v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, - v41, v42, v43); -} - -template -internal::ValueArray44 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, - T42 v42, T43 v43, T44 v44) { - return internal::ValueArray44(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, - v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, - v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, - v40, v41, v42, v43, v44); -} - -template -internal::ValueArray45 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, - T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, - T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, - T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, - T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, - T41 v41, T42 v42, T43 v43, T44 v44, T45 v45) { - return internal::ValueArray45(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, - v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, - v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, - v39, v40, v41, v42, v43, v44, v45); -} - -template -internal::ValueArray46 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, - T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, - T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, - T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, - T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, - T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) { - return internal::ValueArray46(v1, v2, v3, v4, v5, v6, v7, v8, v9, - v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, - v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, - v38, v39, v40, v41, v42, v43, v44, v45, v46); -} - -template -internal::ValueArray47 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, - T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, - T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, - T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, - T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, - T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) { - return internal::ValueArray47(v1, v2, v3, v4, v5, v6, v7, v8, - v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, - v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, - v38, v39, v40, v41, v42, v43, v44, v45, v46, v47); -} - -template -internal::ValueArray48 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, - T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, - T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, - T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, - T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, - T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, - T48 v48) { - return internal::ValueArray48(v1, v2, v3, v4, v5, v6, v7, - v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, - v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, - v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48); -} - -template -internal::ValueArray49 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, - T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, - T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, - T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, - T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, - T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, - T47 v47, T48 v48, T49 v49) { - return internal::ValueArray49(v1, v2, v3, v4, v5, v6, - v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, - v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, - v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49); -} - -template -internal::ValueArray50 Values(T1 v1, T2 v2, T3 v3, T4 v4, - T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, - T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, - T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, - T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, - T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, - T46 v46, T47 v47, T48 v48, T49 v49, T50 v50) { - return internal::ValueArray50(v1, v2, v3, v4, - v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, - v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, - v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, - v48, v49, v50); +template +internal::ValueArray Values(T... v) { + return internal::ValueArray(std::move(v)...); } // Bool() allows generating tests with parameters in a set of (false, true). @@ -1207,7 +348,7 @@ internal::ValueArray50 { @@ -1215,13 +356,12 @@ internal::ValueArray50 Bool() { return Values(false, true); } -# if GTEST_HAS_COMBINE // Combine() allows the user to combine two or more sequences to produce // values of a Cartesian product of those sequences' elements. // @@ -1230,215 +370,145 @@ inline internal::ParamGenerator Bool() { // - returns a generator producing sequences with elements coming from // the Cartesian product of elements from the sequences generated by // gen1, gen2, ..., genN. The sequence elements will have a type of -// tuple where T1, T2, ..., TN are the types +// std::tuple where T1, T2, ..., TN are the types // of elements from sequences produces by gen1, gen2, ..., genN. // -// Combine can have up to 10 arguments. This number is currently limited -// by the maximum number of elements in the tuple implementation used by Google -// Test. +// Combine can have up to 10 arguments. // // Example: // -// This will instantiate tests in test case AnimalTest each one with +// This will instantiate tests in test suite AnimalTest each one with // the parameter values tuple("cat", BLACK), tuple("cat", WHITE), // tuple("dog", BLACK), and tuple("dog", WHITE): // // enum Color { BLACK, GRAY, WHITE }; // class AnimalTest -// : public testing::TestWithParam > {...}; +// : public testing::TestWithParam > {...}; // // TEST_P(AnimalTest, AnimalLooksNice) {...} // -// INSTANTIATE_TEST_CASE_P(AnimalVariations, AnimalTest, -// Combine(Values("cat", "dog"), -// Values(BLACK, WHITE))); +// INSTANTIATE_TEST_SUITE_P(AnimalVariations, AnimalTest, +// Combine(Values("cat", "dog"), +// Values(BLACK, WHITE))); // // This will instantiate tests in FlagDependentTest with all variations of two // Boolean flags: // // class FlagDependentTest -// : public testing::TestWithParam > { +// : public testing::TestWithParam > { // virtual void SetUp() { // // Assigns external_flag_1 and external_flag_2 values from the tuple. -// tie(external_flag_1, external_flag_2) = GetParam(); +// std::tie(external_flag_1, external_flag_2) = GetParam(); // } // }; // // TEST_P(FlagDependentTest, TestFeature1) { // // Test your code using external_flag_1 and external_flag_2 here. // } -// INSTANTIATE_TEST_CASE_P(TwoBoolSequence, FlagDependentTest, -// Combine(Bool(), Bool())); -// -template -internal::CartesianProductHolder2 Combine( - const Generator1& g1, const Generator2& g2) { - return internal::CartesianProductHolder2( - g1, g2); -} - -template -internal::CartesianProductHolder3 Combine( - const Generator1& g1, const Generator2& g2, const Generator3& g3) { - return internal::CartesianProductHolder3( - g1, g2, g3); -} - -template -internal::CartesianProductHolder4 Combine( - const Generator1& g1, const Generator2& g2, const Generator3& g3, - const Generator4& g4) { - return internal::CartesianProductHolder4( - g1, g2, g3, g4); -} - -template -internal::CartesianProductHolder5 Combine( - const Generator1& g1, const Generator2& g2, const Generator3& g3, - const Generator4& g4, const Generator5& g5) { - return internal::CartesianProductHolder5( - g1, g2, g3, g4, g5); -} - -template -internal::CartesianProductHolder6 Combine( - const Generator1& g1, const Generator2& g2, const Generator3& g3, - const Generator4& g4, const Generator5& g5, const Generator6& g6) { - return internal::CartesianProductHolder6( - g1, g2, g3, g4, g5, g6); -} - -template -internal::CartesianProductHolder7 Combine( - const Generator1& g1, const Generator2& g2, const Generator3& g3, - const Generator4& g4, const Generator5& g5, const Generator6& g6, - const Generator7& g7) { - return internal::CartesianProductHolder7( - g1, g2, g3, g4, g5, g6, g7); -} - -template -internal::CartesianProductHolder8 Combine( - const Generator1& g1, const Generator2& g2, const Generator3& g3, - const Generator4& g4, const Generator5& g5, const Generator6& g6, - const Generator7& g7, const Generator8& g8) { - return internal::CartesianProductHolder8( - g1, g2, g3, g4, g5, g6, g7, g8); -} - -template -internal::CartesianProductHolder9 Combine( - const Generator1& g1, const Generator2& g2, const Generator3& g3, - const Generator4& g4, const Generator5& g5, const Generator6& g6, - const Generator7& g7, const Generator8& g8, const Generator9& g9) { - return internal::CartesianProductHolder9( - g1, g2, g3, g4, g5, g6, g7, g8, g9); -} - -template -internal::CartesianProductHolder10 Combine( - const Generator1& g1, const Generator2& g2, const Generator3& g3, - const Generator4& g4, const Generator5& g5, const Generator6& g6, - const Generator7& g7, const Generator8& g8, const Generator9& g9, - const Generator10& g10) { - return internal::CartesianProductHolder10( - g1, g2, g3, g4, g5, g6, g7, g8, g9, g10); -} -# endif // GTEST_HAS_COMBINE - - - -# define TEST_P(test_case_name, test_name) \ - class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \ - : public test_case_name { \ - public: \ - GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {} \ - virtual void TestBody(); \ - private: \ - static int AddToRegistry() { \ - ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ - GetTestCasePatternHolder(\ - #test_case_name, \ - ::testing::internal::CodeLocation(\ - __FILE__, __LINE__))->AddTestPattern(\ - #test_case_name, \ - #test_name, \ - new ::testing::internal::TestMetaFactory< \ - GTEST_TEST_CLASS_NAME_(\ - test_case_name, test_name)>()); \ - return 0; \ - } \ - static int gtest_registering_dummy_ GTEST_ATTRIBUTE_UNUSED_; \ - GTEST_DISALLOW_COPY_AND_ASSIGN_(\ - GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \ - }; \ - int GTEST_TEST_CLASS_NAME_(test_case_name, \ - test_name)::gtest_registering_dummy_ = \ - GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \ - void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody() - -// The optional last argument to INSTANTIATE_TEST_CASE_P allows the user -// to specify a function or functor that generates custom test name suffixes -// based on the test parameters. The function should accept one argument of -// type testing::TestParamInfo, and return std::string. +// INSTANTIATE_TEST_SUITE_P(TwoBoolSequence, FlagDependentTest, +// Combine(Bool(), Bool())); +// +template +internal::CartesianProductHolder Combine(const Generator&... g) { + return internal::CartesianProductHolder(g...); +} + +#define TEST_P(test_suite_name, test_name) \ + static_assert(sizeof(GTEST_STRINGIFY_(test_suite_name)) > 1, \ + "test_suite_name must not be empty"); \ + static_assert(sizeof(GTEST_STRINGIFY_(test_name)) > 1, \ + "test_name must not be empty"); \ + class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \ + : public test_suite_name { \ + public: \ + GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() {} \ + void TestBody() override; \ + \ + private: \ + static int AddToRegistry() { \ + ::testing::UnitTest::GetInstance() \ + ->parameterized_test_registry() \ + .GetTestSuitePatternHolder( \ + GTEST_STRINGIFY_(test_suite_name), \ + ::testing::internal::CodeLocation(__FILE__, __LINE__)) \ + ->AddTestPattern( \ + GTEST_STRINGIFY_(test_suite_name), GTEST_STRINGIFY_(test_name), \ + new ::testing::internal::TestMetaFactory()); \ + return 0; \ + } \ + static int gtest_registering_dummy_ GTEST_ATTRIBUTE_UNUSED_; \ + GTEST_DISALLOW_COPY_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name, \ + test_name)); \ + }; \ + int GTEST_TEST_CLASS_NAME_(test_suite_name, \ + test_name)::gtest_registering_dummy_ = \ + GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::AddToRegistry(); \ + void GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::TestBody() + +// The last argument to INSTANTIATE_TEST_SUITE_P allows the user to specify +// generator and an optional function or functor that generates custom test name +// suffixes based on the test parameters. Such a function or functor should +// accept one argument of type testing::TestParamInfo, and +// return std::string. // // testing::PrintToStringParamName is a builtin test suffix generator that -// returns the value of testing::PrintToString(GetParam()). It does not work -// for std::string or C strings. +// returns the value of testing::PrintToString(GetParam()). // // Note: test names must be non-empty, unique, and may only contain ASCII -// alphanumeric characters or underscore. - -# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator, ...) \ - ::testing::internal::ParamGenerator \ - gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \ - ::std::string gtest_##prefix##test_case_name##_EvalGenerateName_( \ - const ::testing::TestParamInfo& info) { \ - return ::testing::internal::GetParamNameGen \ - (__VA_ARGS__)(info); \ - } \ - int gtest_##prefix##test_case_name##_dummy_ GTEST_ATTRIBUTE_UNUSED_ = \ - ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ - GetTestCasePatternHolder(\ - #test_case_name, \ - ::testing::internal::CodeLocation(\ - __FILE__, __LINE__))->AddTestCaseInstantiation(\ - #prefix, \ - >est_##prefix##test_case_name##_EvalGenerator_, \ - >est_##prefix##test_case_name##_EvalGenerateName_, \ - __FILE__, __LINE__) +// alphanumeric characters or underscore. Because PrintToString adds quotes +// to std::string and C strings, it won't work for these types. + +#define GTEST_EXPAND_(arg) arg +#define GTEST_GET_FIRST_(first, ...) first +#define GTEST_GET_SECOND_(first, second, ...) second + +#define INSTANTIATE_TEST_SUITE_P(prefix, test_suite_name, ...) \ + static_assert(sizeof(GTEST_STRINGIFY_(test_suite_name)) > 1, \ + "test_suite_name must not be empty"); \ + static_assert(sizeof(GTEST_STRINGIFY_(prefix)) > 1, \ + "prefix must not be empty"); \ + static ::testing::internal::ParamGenerator \ + gtest_##prefix##test_suite_name##_EvalGenerator_() { \ + return GTEST_EXPAND_(GTEST_GET_FIRST_(__VA_ARGS__, DUMMY_PARAM_)); \ + } \ + static ::std::string gtest_##prefix##test_suite_name##_EvalGenerateName_( \ + const ::testing::TestParamInfo& info) { \ + if (::testing::internal::AlwaysFalse()) { \ + ::testing::internal::TestNotEmpty(GTEST_EXPAND_(GTEST_GET_SECOND_( \ + __VA_ARGS__, \ + ::testing::internal::DefaultParamName, \ + DUMMY_PARAM_))); \ + auto t = std::make_tuple(__VA_ARGS__); \ + static_assert(std::tuple_size::value <= 2, \ + "Too Many Args!"); \ + } \ + return ((GTEST_EXPAND_(GTEST_GET_SECOND_( \ + __VA_ARGS__, \ + ::testing::internal::DefaultParamName, \ + DUMMY_PARAM_))))(info); \ + } \ + static int gtest_##prefix##test_suite_name##_dummy_ \ + GTEST_ATTRIBUTE_UNUSED_ = \ + ::testing::UnitTest::GetInstance() \ + ->parameterized_test_registry() \ + .GetTestSuitePatternHolder( \ + GTEST_STRINGIFY_(test_suite_name), \ + ::testing::internal::CodeLocation(__FILE__, __LINE__)) \ + ->AddTestSuiteInstantiation( \ + GTEST_STRINGIFY_(prefix), \ + >est_##prefix##test_suite_name##_EvalGenerator_, \ + >est_##prefix##test_suite_name##_EvalGenerateName_, \ + __FILE__, __LINE__) + +// Legacy API is deprecated but still available +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ +#define INSTANTIATE_TEST_CASE_P \ + static_assert(::testing::internal::InstantiateTestCase_P_IsDeprecated(), \ + ""); \ + INSTANTIATE_TEST_SUITE_P +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ } // namespace testing -#endif // GTEST_HAS_PARAM_TEST - #endif // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ diff --git a/cpp/test/include/gtest/gtest-param-test.h.pump b/cpp/test/include/gtest/gtest-param-test.h.pump deleted file mode 100644 index 3078d6d2a1..0000000000 --- a/cpp/test/include/gtest/gtest-param-test.h.pump +++ /dev/null @@ -1,510 +0,0 @@ -$$ -*- mode: c++; -*- -$var n = 50 $$ Maximum length of Values arguments we want to support. -$var maxtuple = 10 $$ Maximum number of Combine arguments we want to support. -// Copyright 2008, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Authors: vladl@google.com (Vlad Losev) -// -// Macros and functions for implementing parameterized tests -// in Google C++ Testing Framework (Google Test) -// -// This file is generated by a SCRIPT. DO NOT EDIT BY HAND! -// -#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ -#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ - - -// Value-parameterized tests allow you to test your code with different -// parameters without writing multiple copies of the same test. -// -// Here is how you use value-parameterized tests: - -#if 0 - -// To write value-parameterized tests, first you should define a fixture -// class. It is usually derived from testing::TestWithParam (see below for -// another inheritance scheme that's sometimes useful in more complicated -// class hierarchies), where the type of your parameter values. -// TestWithParam is itself derived from testing::Test. T can be any -// copyable type. If it's a raw pointer, you are responsible for managing the -// lifespan of the pointed values. - -class FooTest : public ::testing::TestWithParam { - // You can implement all the usual class fixture members here. -}; - -// Then, use the TEST_P macro to define as many parameterized tests -// for this fixture as you want. The _P suffix is for "parameterized" -// or "pattern", whichever you prefer to think. - -TEST_P(FooTest, DoesBlah) { - // Inside a test, access the test parameter with the GetParam() method - // of the TestWithParam class: - EXPECT_TRUE(foo.Blah(GetParam())); - ... -} - -TEST_P(FooTest, HasBlahBlah) { - ... -} - -// Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test -// case with any set of parameters you want. Google Test defines a number -// of functions for generating test parameters. They return what we call -// (surprise!) parameter generators. Here is a summary of them, which -// are all in the testing namespace: -// -// -// Range(begin, end [, step]) - Yields values {begin, begin+step, -// begin+step+step, ...}. The values do not -// include end. step defaults to 1. -// Values(v1, v2, ..., vN) - Yields values {v1, v2, ..., vN}. -// ValuesIn(container) - Yields values from a C-style array, an STL -// ValuesIn(begin,end) container, or an iterator range [begin, end). -// Bool() - Yields sequence {false, true}. -// Combine(g1, g2, ..., gN) - Yields all combinations (the Cartesian product -// for the math savvy) of the values generated -// by the N generators. -// -// For more details, see comments at the definitions of these functions below -// in this file. -// -// The following statement will instantiate tests from the FooTest test case -// each with parameter values "meeny", "miny", and "moe". - -INSTANTIATE_TEST_CASE_P(InstantiationName, - FooTest, - Values("meeny", "miny", "moe")); - -// To distinguish different instances of the pattern, (yes, you -// can instantiate it more then once) the first argument to the -// INSTANTIATE_TEST_CASE_P macro is a prefix that will be added to the -// actual test case name. Remember to pick unique prefixes for different -// instantiations. The tests from the instantiation above will have -// these names: -// -// * InstantiationName/FooTest.DoesBlah/0 for "meeny" -// * InstantiationName/FooTest.DoesBlah/1 for "miny" -// * InstantiationName/FooTest.DoesBlah/2 for "moe" -// * InstantiationName/FooTest.HasBlahBlah/0 for "meeny" -// * InstantiationName/FooTest.HasBlahBlah/1 for "miny" -// * InstantiationName/FooTest.HasBlahBlah/2 for "moe" -// -// You can use these names in --gtest_filter. -// -// This statement will instantiate all tests from FooTest again, each -// with parameter values "cat" and "dog": - -const char* pets[] = {"cat", "dog"}; -INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets)); - -// The tests from the instantiation above will have these names: -// -// * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat" -// * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog" -// * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat" -// * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog" -// -// Please note that INSTANTIATE_TEST_CASE_P will instantiate all tests -// in the given test case, whether their definitions come before or -// AFTER the INSTANTIATE_TEST_CASE_P statement. -// -// Please also note that generator expressions (including parameters to the -// generators) are evaluated in InitGoogleTest(), after main() has started. -// This allows the user on one hand, to adjust generator parameters in order -// to dynamically determine a set of tests to run and on the other hand, -// give the user a chance to inspect the generated tests with Google Test -// reflection API before RUN_ALL_TESTS() is executed. -// -// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc -// for more examples. -// -// In the future, we plan to publish the API for defining new parameter -// generators. But for now this interface remains part of the internal -// implementation and is subject to change. -// -// -// A parameterized test fixture must be derived from testing::Test and from -// testing::WithParamInterface, where T is the type of the parameter -// values. Inheriting from TestWithParam satisfies that requirement because -// TestWithParam inherits from both Test and WithParamInterface. In more -// complicated hierarchies, however, it is occasionally useful to inherit -// separately from Test and WithParamInterface. For example: - -class BaseTest : public ::testing::Test { - // You can inherit all the usual members for a non-parameterized test - // fixture here. -}; - -class DerivedTest : public BaseTest, public ::testing::WithParamInterface { - // The usual test fixture members go here too. -}; - -TEST_F(BaseTest, HasFoo) { - // This is an ordinary non-parameterized test. -} - -TEST_P(DerivedTest, DoesBlah) { - // GetParam works just the same here as if you inherit from TestWithParam. - EXPECT_TRUE(foo.Blah(GetParam())); -} - -#endif // 0 - -#include "gtest/internal/gtest-port.h" - -#if !GTEST_OS_SYMBIAN -# include -#endif - -// scripts/fuse_gtest.py depends on gtest's own header being #included -// *unconditionally*. Therefore these #includes cannot be moved -// inside #if GTEST_HAS_PARAM_TEST. -#include "gtest/internal/gtest-internal.h" -#include "gtest/internal/gtest-param-util.h" -#include "gtest/internal/gtest-param-util-generated.h" - -#if GTEST_HAS_PARAM_TEST - -namespace testing { - -// Functions producing parameter generators. -// -// Google Test uses these generators to produce parameters for value- -// parameterized tests. When a parameterized test case is instantiated -// with a particular generator, Google Test creates and runs tests -// for each element in the sequence produced by the generator. -// -// In the following sample, tests from test case FooTest are instantiated -// each three times with parameter values 3, 5, and 8: -// -// class FooTest : public TestWithParam { ... }; -// -// TEST_P(FooTest, TestThis) { -// } -// TEST_P(FooTest, TestThat) { -// } -// INSTANTIATE_TEST_CASE_P(TestSequence, FooTest, Values(3, 5, 8)); -// - -// Range() returns generators providing sequences of values in a range. -// -// Synopsis: -// Range(start, end) -// - returns a generator producing a sequence of values {start, start+1, -// start+2, ..., }. -// Range(start, end, step) -// - returns a generator producing a sequence of values {start, start+step, -// start+step+step, ..., }. -// Notes: -// * The generated sequences never include end. For example, Range(1, 5) -// returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2) -// returns a generator producing {1, 3, 5, 7}. -// * start and end must have the same type. That type may be any integral or -// floating-point type or a user defined type satisfying these conditions: -// * It must be assignable (have operator=() defined). -// * It must have operator+() (operator+(int-compatible type) for -// two-operand version). -// * It must have operator<() defined. -// Elements in the resulting sequences will also have that type. -// * Condition start < end must be satisfied in order for resulting sequences -// to contain any elements. -// -template -internal::ParamGenerator Range(T start, T end, IncrementT step) { - return internal::ParamGenerator( - new internal::RangeGenerator(start, end, step)); -} - -template -internal::ParamGenerator Range(T start, T end) { - return Range(start, end, 1); -} - -// ValuesIn() function allows generation of tests with parameters coming from -// a container. -// -// Synopsis: -// ValuesIn(const T (&array)[N]) -// - returns a generator producing sequences with elements from -// a C-style array. -// ValuesIn(const Container& container) -// - returns a generator producing sequences with elements from -// an STL-style container. -// ValuesIn(Iterator begin, Iterator end) -// - returns a generator producing sequences with elements from -// a range [begin, end) defined by a pair of STL-style iterators. These -// iterators can also be plain C pointers. -// -// Please note that ValuesIn copies the values from the containers -// passed in and keeps them to generate tests in RUN_ALL_TESTS(). -// -// Examples: -// -// This instantiates tests from test case StringTest -// each with C-string values of "foo", "bar", and "baz": -// -// const char* strings[] = {"foo", "bar", "baz"}; -// INSTANTIATE_TEST_CASE_P(StringSequence, SrtingTest, ValuesIn(strings)); -// -// This instantiates tests from test case StlStringTest -// each with STL strings with values "a" and "b": -// -// ::std::vector< ::std::string> GetParameterStrings() { -// ::std::vector< ::std::string> v; -// v.push_back("a"); -// v.push_back("b"); -// return v; -// } -// -// INSTANTIATE_TEST_CASE_P(CharSequence, -// StlStringTest, -// ValuesIn(GetParameterStrings())); -// -// -// This will also instantiate tests from CharTest -// each with parameter values 'a' and 'b': -// -// ::std::list GetParameterChars() { -// ::std::list list; -// list.push_back('a'); -// list.push_back('b'); -// return list; -// } -// ::std::list l = GetParameterChars(); -// INSTANTIATE_TEST_CASE_P(CharSequence2, -// CharTest, -// ValuesIn(l.begin(), l.end())); -// -template -internal::ParamGenerator< - typename ::testing::internal::IteratorTraits::value_type> -ValuesIn(ForwardIterator begin, ForwardIterator end) { - typedef typename ::testing::internal::IteratorTraits - ::value_type ParamType; - return internal::ParamGenerator( - new internal::ValuesInIteratorRangeGenerator(begin, end)); -} - -template -internal::ParamGenerator ValuesIn(const T (&array)[N]) { - return ValuesIn(array, array + N); -} - -template -internal::ParamGenerator ValuesIn( - const Container& container) { - return ValuesIn(container.begin(), container.end()); -} - -// Values() allows generating tests from explicitly specified list of -// parameters. -// -// Synopsis: -// Values(T v1, T v2, ..., T vN) -// - returns a generator producing sequences with elements v1, v2, ..., vN. -// -// For example, this instantiates tests from test case BarTest each -// with values "one", "two", and "three": -// -// INSTANTIATE_TEST_CASE_P(NumSequence, BarTest, Values("one", "two", "three")); -// -// This instantiates tests from test case BazTest each with values 1, 2, 3.5. -// The exact type of values will depend on the type of parameter in BazTest. -// -// INSTANTIATE_TEST_CASE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5)); -// -// Currently, Values() supports from 1 to $n parameters. -// -$range i 1..n -$for i [[ -$range j 1..i - -template <$for j, [[typename T$j]]> -internal::ValueArray$i<$for j, [[T$j]]> Values($for j, [[T$j v$j]]) { - return internal::ValueArray$i<$for j, [[T$j]]>($for j, [[v$j]]); -} - -]] - -// Bool() allows generating tests with parameters in a set of (false, true). -// -// Synopsis: -// Bool() -// - returns a generator producing sequences with elements {false, true}. -// -// It is useful when testing code that depends on Boolean flags. Combinations -// of multiple flags can be tested when several Bool()'s are combined using -// Combine() function. -// -// In the following example all tests in the test case FlagDependentTest -// will be instantiated twice with parameters false and true. -// -// class FlagDependentTest : public testing::TestWithParam { -// virtual void SetUp() { -// external_flag = GetParam(); -// } -// } -// INSTANTIATE_TEST_CASE_P(BoolSequence, FlagDependentTest, Bool()); -// -inline internal::ParamGenerator Bool() { - return Values(false, true); -} - -# if GTEST_HAS_COMBINE -// Combine() allows the user to combine two or more sequences to produce -// values of a Cartesian product of those sequences' elements. -// -// Synopsis: -// Combine(gen1, gen2, ..., genN) -// - returns a generator producing sequences with elements coming from -// the Cartesian product of elements from the sequences generated by -// gen1, gen2, ..., genN. The sequence elements will have a type of -// tuple where T1, T2, ..., TN are the types -// of elements from sequences produces by gen1, gen2, ..., genN. -// -// Combine can have up to $maxtuple arguments. This number is currently limited -// by the maximum number of elements in the tuple implementation used by Google -// Test. -// -// Example: -// -// This will instantiate tests in test case AnimalTest each one with -// the parameter values tuple("cat", BLACK), tuple("cat", WHITE), -// tuple("dog", BLACK), and tuple("dog", WHITE): -// -// enum Color { BLACK, GRAY, WHITE }; -// class AnimalTest -// : public testing::TestWithParam > {...}; -// -// TEST_P(AnimalTest, AnimalLooksNice) {...} -// -// INSTANTIATE_TEST_CASE_P(AnimalVariations, AnimalTest, -// Combine(Values("cat", "dog"), -// Values(BLACK, WHITE))); -// -// This will instantiate tests in FlagDependentTest with all variations of two -// Boolean flags: -// -// class FlagDependentTest -// : public testing::TestWithParam > { -// virtual void SetUp() { -// // Assigns external_flag_1 and external_flag_2 values from the tuple. -// tie(external_flag_1, external_flag_2) = GetParam(); -// } -// }; -// -// TEST_P(FlagDependentTest, TestFeature1) { -// // Test your code using external_flag_1 and external_flag_2 here. -// } -// INSTANTIATE_TEST_CASE_P(TwoBoolSequence, FlagDependentTest, -// Combine(Bool(), Bool())); -// -$range i 2..maxtuple -$for i [[ -$range j 1..i - -template <$for j, [[typename Generator$j]]> -internal::CartesianProductHolder$i<$for j, [[Generator$j]]> Combine( - $for j, [[const Generator$j& g$j]]) { - return internal::CartesianProductHolder$i<$for j, [[Generator$j]]>( - $for j, [[g$j]]); -} - -]] -# endif // GTEST_HAS_COMBINE - - - -# define TEST_P(test_case_name, test_name) \ - class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \ - : public test_case_name { \ - public: \ - GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {} \ - virtual void TestBody(); \ - private: \ - static int AddToRegistry() { \ - ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ - GetTestCasePatternHolder(\ - #test_case_name, \ - ::testing::internal::CodeLocation(\ - __FILE__, __LINE__))->AddTestPattern(\ - #test_case_name, \ - #test_name, \ - new ::testing::internal::TestMetaFactory< \ - GTEST_TEST_CLASS_NAME_(\ - test_case_name, test_name)>()); \ - return 0; \ - } \ - static int gtest_registering_dummy_ GTEST_ATTRIBUTE_UNUSED_; \ - GTEST_DISALLOW_COPY_AND_ASSIGN_(\ - GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \ - }; \ - int GTEST_TEST_CLASS_NAME_(test_case_name, \ - test_name)::gtest_registering_dummy_ = \ - GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \ - void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody() - -// The optional last argument to INSTANTIATE_TEST_CASE_P allows the user -// to specify a function or functor that generates custom test name suffixes -// based on the test parameters. The function should accept one argument of -// type testing::TestParamInfo, and return std::string. -// -// testing::PrintToStringParamName is a builtin test suffix generator that -// returns the value of testing::PrintToString(GetParam()). -// -// Note: test names must be non-empty, unique, and may only contain ASCII -// alphanumeric characters or underscore. Because PrintToString adds quotes -// to std::string and C strings, it won't work for these types. - -# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator, ...) \ - ::testing::internal::ParamGenerator \ - gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \ - ::std::string gtest_##prefix##test_case_name##_EvalGenerateName_( \ - const ::testing::TestParamInfo& info) { \ - return ::testing::internal::GetParamNameGen \ - (__VA_ARGS__)(info); \ - } \ - int gtest_##prefix##test_case_name##_dummy_ GTEST_ATTRIBUTE_UNUSED_ = \ - ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ - GetTestCasePatternHolder(\ - #test_case_name, \ - ::testing::internal::CodeLocation(\ - __FILE__, __LINE__))->AddTestCaseInstantiation(\ - #prefix, \ - >est_##prefix##test_case_name##_EvalGenerator_, \ - >est_##prefix##test_case_name##_EvalGenerateName_, \ - __FILE__, __LINE__) - -} // namespace testing - -#endif // GTEST_HAS_PARAM_TEST - -#endif // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ diff --git a/cpp/test/include/gtest/gtest-printers.h b/cpp/test/include/gtest/gtest-printers.h index e850d60542..56a05450ef 100644 --- a/cpp/test/include/gtest/gtest-printers.h +++ b/cpp/test/include/gtest/gtest-printers.h @@ -26,10 +26,9 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Author: wan@google.com (Zhanyong Wan) -// Google Test - The Google C++ Testing Framework + +// Google Test - The Google C++ Testing and Mocking Framework // // This file implements a universal value printer that can print a // value of any type T: @@ -46,6 +45,10 @@ // 2. operator<<(ostream&, const T&) defined in either foo or the // global namespace. // +// However if T is an STL-style container then it is printed element-wise +// unless foo::PrintTo(const T&, ostream*) is defined. Note that +// operator<<() is ignored for container types. +// // If none of the above is defined, it will print the debug string of // the value if it is a protocol buffer, or print the raw bytes in the // value otherwise. @@ -92,20 +95,27 @@ // being defined as many user-defined container types don't have // value_type. +// GOOGLETEST_CM0001 DO NOT DELETE + #ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ #define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ +#include #include // NOLINT #include #include +#include +#include #include #include -#include "gtest/internal/gtest-port.h" #include "gtest/internal/gtest-internal.h" +#include "gtest/internal/gtest-port.h" -#if GTEST_HAS_STD_TUPLE_ -# include -#endif +#if GTEST_HAS_ABSL +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "absl/types/variant.h" +#endif // GTEST_HAS_ABSL namespace testing { @@ -125,7 +135,11 @@ enum TypeKind { kProtobuf, // a protobuf type kConvertibleToInteger, // a type implicitly convertible to BiggestInt // (e.g. a named or unnamed enum type) - kOtherType // anything else +#if GTEST_HAS_ABSL + kConvertibleToStringView, // a type implicitly convertible to + // absl::string_view +#endif + kOtherType // anything else }; // TypeWithoutFormatter::PrintValue(value, os) is called @@ -137,8 +151,10 @@ class TypeWithoutFormatter { public: // This default version is called when kTypeKind is kOtherType. static void PrintValue(const T& value, ::std::ostream* os) { - PrintBytesInObjectTo(reinterpret_cast(&value), - sizeof(value), os); + PrintBytesInObjectTo( + static_cast( + reinterpret_cast(std::addressof(value))), + sizeof(value), os); } }; @@ -175,6 +191,19 @@ class TypeWithoutFormatter { } }; +#if GTEST_HAS_ABSL +template +class TypeWithoutFormatter { + public: + // Since T has neither operator<< nor PrintTo() but can be implicitly + // converted to absl::string_view, we print it as a absl::string_view. + // + // Note: the implementation is further below, as it depends on + // internal::PrintTo symbol which is defined later in the file. + static void PrintValue(const T& value, ::std::ostream* os); +}; +#endif + // Prints the given value to the given ostream. If the value is a // protocol message, its debug string is printed; if it's an enum or // of a type implicitly convertible to BiggestInt, it's printed as an @@ -202,10 +231,19 @@ class TypeWithoutFormatter { template ::std::basic_ostream& operator<<( ::std::basic_ostream& os, const T& x) { - TypeWithoutFormatter::value ? kProtobuf : - internal::ImplicitlyConvertible::value ? - kConvertibleToInteger : kOtherType)>::PrintValue(x, &os); + TypeWithoutFormatter::value + ? kProtobuf + : std::is_convertible< + const T&, internal::BiggestInt>::value + ? kConvertibleToInteger + : +#if GTEST_HAS_ABSL + std::is_convertible< + const T&, absl::string_view>::value + ? kConvertibleToStringView + : +#endif + kOtherType)>::PrintValue(x, &os); return os; } @@ -320,16 +358,6 @@ GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const wchar_t); GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::std::string); GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::std::string); -#if GTEST_HAS_GLOBAL_STRING -GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::string); -GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::string); -#endif - -#if GTEST_HAS_GLOBAL_WSTRING -GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::wstring); -GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::wstring); -#endif - #if GTEST_HAS_STD_WSTRING GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::std::wstring); GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::std::wstring); @@ -410,7 +438,7 @@ void DefaultPrintTo(WrapPrinterType /* dummy */, template void DefaultPrintTo(WrapPrinterType /* dummy */, T* p, ::std::ostream* os) { - if (p == NULL) { + if (p == nullptr) { *os << "NULL"; } else { // T is not a function type. We just call << to print p, @@ -422,17 +450,13 @@ void DefaultPrintTo(WrapPrinterType /* dummy */, template void DefaultPrintTo(WrapPrinterType /* dummy */, T* p, ::std::ostream* os) { - if (p == NULL) { + if (p == nullptr) { *os << "NULL"; } else { // T is a function type, so '*os << p' doesn't do what we want // (it just prints p as bool). We want to print p as a const - // void*. However, we cannot cast it to const void* directly, - // even using reinterpret_cast, as earlier versions of gcc - // (e.g. 3.4.5) cannot compile the cast when p is a function - // pointer. Casting to UInt64 first solves the problem. - *os << reinterpret_cast( - reinterpret_cast(p)); + // void*. + *os << reinterpret_cast(p); } } @@ -477,16 +501,15 @@ void PrintTo(const T& value, ::std::ostream* os) { // function pointers so that the `*os << p` in the object pointer overload // doesn't cause that warning either. DefaultPrintTo( - WrapPrinterType(0)) == sizeof(IsContainer) - ? kPrintContainer : !is_pointer::value + WrapPrinterType < + (sizeof(IsContainerTest(0)) == sizeof(IsContainer)) && + !IsRecursiveContainer::value + ? kPrintContainer + : !std::is_pointer::value ? kPrintOther -#if GTEST_LANG_CXX11 : std::is_function::type>::value -#else - : !internal::ImplicitlyConvertible::value -#endif ? kPrintFunctionPointer - : kPrintPointer>(), + : kPrintPointer > (), value, os); } @@ -566,27 +589,13 @@ void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) { } } -// Overloads for ::string and ::std::string. -#if GTEST_HAS_GLOBAL_STRING -GTEST_API_ void PrintStringTo(const ::string&s, ::std::ostream* os); -inline void PrintTo(const ::string& s, ::std::ostream* os) { - PrintStringTo(s, os); -} -#endif // GTEST_HAS_GLOBAL_STRING - +// Overloads for ::std::string. GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os); inline void PrintTo(const ::std::string& s, ::std::ostream* os) { PrintStringTo(s, os); } -// Overloads for ::wstring and ::std::wstring. -#if GTEST_HAS_GLOBAL_WSTRING -GTEST_API_ void PrintWideStringTo(const ::wstring&s, ::std::ostream* os); -inline void PrintTo(const ::wstring& s, ::std::ostream* os) { - PrintWideStringTo(s, os); -} -#endif // GTEST_HAS_GLOBAL_WSTRING - +// Overloads for ::std::wstring. #if GTEST_HAS_STD_WSTRING GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os); inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) { @@ -594,95 +603,45 @@ inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) { } #endif // GTEST_HAS_STD_WSTRING -#if GTEST_HAS_TR1_TUPLE || GTEST_HAS_STD_TUPLE_ -// Helper function for printing a tuple. T must be instantiated with -// a tuple type. -template -void PrintTupleTo(const T& t, ::std::ostream* os); -#endif // GTEST_HAS_TR1_TUPLE || GTEST_HAS_STD_TUPLE_ - -#if GTEST_HAS_TR1_TUPLE -// Overload for ::std::tr1::tuple. Needed for printing function arguments, -// which are packed as tuples. - -// Overloaded PrintTo() for tuples of various arities. We support -// tuples of up-to 10 fields. The following implementation works -// regardless of whether tr1::tuple is implemented using the -// non-standard variadic template feature or not. - -inline void PrintTo(const ::std::tr1::tuple<>& t, ::std::ostream* os) { - PrintTupleTo(t, os); -} - -template -void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { - PrintTupleTo(t, os); -} - -template -void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { - PrintTupleTo(t, os); -} - -template -void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { - PrintTupleTo(t, os); +#if GTEST_HAS_ABSL +// Overload for absl::string_view. +inline void PrintTo(absl::string_view sp, ::std::ostream* os) { + PrintTo(::std::string(sp), os); } +#endif // GTEST_HAS_ABSL -template -void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { - PrintTupleTo(t, os); -} - -template -void PrintTo(const ::std::tr1::tuple& t, - ::std::ostream* os) { - PrintTupleTo(t, os); -} - -template -void PrintTo(const ::std::tr1::tuple& t, - ::std::ostream* os) { - PrintTupleTo(t, os); -} - -template -void PrintTo(const ::std::tr1::tuple& t, - ::std::ostream* os) { - PrintTupleTo(t, os); -} +inline void PrintTo(std::nullptr_t, ::std::ostream* os) { *os << "(nullptr)"; } -template -void PrintTo(const ::std::tr1::tuple& t, - ::std::ostream* os) { - PrintTupleTo(t, os); -} - -template -void PrintTo(const ::std::tr1::tuple& t, - ::std::ostream* os) { - PrintTupleTo(t, os); +template +void PrintTo(std::reference_wrapper ref, ::std::ostream* os) { + UniversalPrinter::Print(ref.get(), os); } -template -void PrintTo( - const ::std::tr1::tuple& t, - ::std::ostream* os) { - PrintTupleTo(t, os); +// Helper function for printing a tuple. T must be instantiated with +// a tuple type. +template +void PrintTupleTo(const T&, std::integral_constant, + ::std::ostream*) {} + +template +void PrintTupleTo(const T& t, std::integral_constant, + ::std::ostream* os) { + PrintTupleTo(t, std::integral_constant(), os); + GTEST_INTENTIONAL_CONST_COND_PUSH_() + if (I > 1) { + GTEST_INTENTIONAL_CONST_COND_POP_() + *os << ", "; + } + UniversalPrinter::type>::Print( + std::get(t), os); } -#endif // GTEST_HAS_TR1_TUPLE -#if GTEST_HAS_STD_TUPLE_ template void PrintTo(const ::std::tuple& t, ::std::ostream* os) { - PrintTupleTo(t, os); + *os << "("; + PrintTupleTo(t, std::integral_constant(), os); + *os << ")"; } -#endif // GTEST_HAS_STD_TUPLE_ // Overload for std::pair. template @@ -723,6 +682,48 @@ class UniversalPrinter { GTEST_DISABLE_MSC_WARNINGS_POP_() }; +#if GTEST_HAS_ABSL + +// Printer for absl::optional + +template +class UniversalPrinter<::absl::optional> { + public: + static void Print(const ::absl::optional& value, ::std::ostream* os) { + *os << '('; + if (!value) { + *os << "nullopt"; + } else { + UniversalPrint(*value, os); + } + *os << ')'; + } +}; + +// Printer for absl::variant + +template +class UniversalPrinter<::absl::variant> { + public: + static void Print(const ::absl::variant& value, ::std::ostream* os) { + *os << '('; + absl::visit(Visitor{os}, value); + *os << ')'; + } + + private: + struct Visitor { + template + void operator()(const U& u) const { + *os << "'" << GetTypeName() << "' with value "; + UniversalPrint(u, os); + } + ::std::ostream* os; + }; +}; + +#endif // GTEST_HAS_ABSL + // UniversalPrintArray(begin, len, os) prints an array of 'len' // elements, starting at address 'begin'. template @@ -736,7 +737,6 @@ void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) { // If the array has more than kThreshold elements, we'll have to // omit some details by printing only the first and the last // kChunkSize elements. - // TODO(wan@google.com): let the user control the threshold using a flag. if (len <= kThreshold) { PrintRawArrayTo(begin, len, os); } else { @@ -815,7 +815,7 @@ template <> class UniversalTersePrinter { public: static void Print(const char* str, ::std::ostream* os) { - if (str == NULL) { + if (str == nullptr) { *os << "NULL"; } else { UniversalPrint(std::string(str), os); @@ -835,7 +835,7 @@ template <> class UniversalTersePrinter { public: static void Print(const wchar_t* str, ::std::ostream* os) { - if (str == NULL) { + if (str == nullptr) { *os << "NULL"; } else { UniversalPrint(::std::wstring(str), os); @@ -869,110 +869,22 @@ void UniversalPrint(const T& value, ::std::ostream* os) { UniversalPrinter::Print(value, os); } -typedef ::std::vector Strings; - -// TuplePolicy must provide: -// - tuple_size -// size of tuple TupleT. -// - get(const TupleT& t) -// static function extracting element I of tuple TupleT. -// - tuple_element::type -// type of element I of tuple TupleT. -template -struct TuplePolicy; - -#if GTEST_HAS_TR1_TUPLE -template -struct TuplePolicy { - typedef TupleT Tuple; - static const size_t tuple_size = ::std::tr1::tuple_size::value; - - template - struct tuple_element : ::std::tr1::tuple_element {}; - - template - static typename AddReference< - const typename ::std::tr1::tuple_element::type>::type get( - const Tuple& tuple) { - return ::std::tr1::get(tuple); - } -}; -template -const size_t TuplePolicy::tuple_size; -#endif // GTEST_HAS_TR1_TUPLE - -#if GTEST_HAS_STD_TUPLE_ -template -struct TuplePolicy< ::std::tuple > { - typedef ::std::tuple Tuple; - static const size_t tuple_size = ::std::tuple_size::value; - - template - struct tuple_element : ::std::tuple_element {}; - - template - static const typename ::std::tuple_element::type& get( - const Tuple& tuple) { - return ::std::get(tuple); - } -}; -template -const size_t TuplePolicy< ::std::tuple >::tuple_size; -#endif // GTEST_HAS_STD_TUPLE_ - -#if GTEST_HAS_TR1_TUPLE || GTEST_HAS_STD_TUPLE_ -// This helper template allows PrintTo() for tuples and -// UniversalTersePrintTupleFieldsToStrings() to be defined by -// induction on the number of tuple fields. The idea is that -// TuplePrefixPrinter::PrintPrefixTo(t, os) prints the first N -// fields in tuple t, and can be defined in terms of -// TuplePrefixPrinter. -// -// The inductive case. -template -struct TuplePrefixPrinter { - // Prints the first N fields of a tuple. - template - static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) { - TuplePrefixPrinter::PrintPrefixTo(t, os); - GTEST_INTENTIONAL_CONST_COND_PUSH_() - if (N > 1) { - GTEST_INTENTIONAL_CONST_COND_POP_() - *os << ", "; - } - UniversalPrinter< - typename TuplePolicy::template tuple_element::type> - ::Print(TuplePolicy::template get(t), os); - } +typedef ::std::vector< ::std::string> Strings; // Tersely prints the first N fields of a tuple to a string vector, // one element for each field. - template - static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) { - TuplePrefixPrinter::TersePrintPrefixToStrings(t, strings); - ::std::stringstream ss; - UniversalTersePrint(TuplePolicy::template get(t), &ss); - strings->push_back(ss.str()); - } -}; - -// Base case. -template <> -struct TuplePrefixPrinter<0> { - template - static void PrintPrefixTo(const Tuple&, ::std::ostream*) {} - - template - static void TersePrintPrefixToStrings(const Tuple&, Strings*) {} -}; - -// Helper function for printing a tuple. -// Tuple must be either std::tr1::tuple or std::tuple type. template -void PrintTupleTo(const Tuple& t, ::std::ostream* os) { - *os << "("; - TuplePrefixPrinter::tuple_size>::PrintPrefixTo(t, os); - *os << ")"; +void TersePrintPrefixToStrings(const Tuple&, std::integral_constant, + Strings*) {} +template +void TersePrintPrefixToStrings(const Tuple& t, + std::integral_constant, + Strings* strings) { + TersePrintPrefixToStrings(t, std::integral_constant(), + strings); + ::std::stringstream ss; + UniversalTersePrint(std::get(t), &ss); + strings->push_back(ss.str()); } // Prints the fields of a tuple tersely to a string vector, one @@ -981,14 +893,24 @@ void PrintTupleTo(const Tuple& t, ::std::ostream* os) { template Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) { Strings result; - TuplePrefixPrinter::tuple_size>:: - TersePrintPrefixToStrings(value, &result); + TersePrintPrefixToStrings( + value, std::integral_constant::value>(), + &result); return result; } -#endif // GTEST_HAS_TR1_TUPLE || GTEST_HAS_STD_TUPLE_ } // namespace internal +#if GTEST_HAS_ABSL +namespace internal2 { +template +void TypeWithoutFormatter::PrintValue( + const T& value, ::std::ostream* os) { + internal::PrintTo(absl::string_view(value), os); +} +} // namespace internal2 +#endif + template ::std::string PrintToString(const T& value) { ::std::stringstream ss; diff --git a/cpp/test/include/gtest/gtest-spi.h b/cpp/test/include/gtest/gtest-spi.h index 0e5c10cf7c..aa38870e8e 100644 --- a/cpp/test/include/gtest/gtest-spi.h +++ b/cpp/test/include/gtest/gtest-spi.h @@ -26,17 +26,21 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Author: wan@google.com (Zhanyong Wan) + // // Utilities for testing Google Test itself and code that uses Google Test // (e.g. frameworks built on top of Google Test). +// GOOGLETEST_CM0004 DO NOT DELETE + #ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_ #define GTEST_INCLUDE_GTEST_GTEST_SPI_H_ #include "gtest/gtest.h" +GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ +/* class A needs to have dll-interface to be used by clients of class B */) + namespace testing { // This helper class can be used to mock out Google Test failure reporting @@ -68,14 +72,15 @@ class GTEST_API_ ScopedFakeTestPartResultReporter TestPartResultArray* result); // The d'tor restores the previous test part result reporter. - virtual ~ScopedFakeTestPartResultReporter(); + ~ScopedFakeTestPartResultReporter() override; // Appends the TestPartResult object to the TestPartResultArray // received in the constructor. // // This method is from the TestPartResultReporterInterface // interface. - virtual void ReportTestPartResult(const TestPartResult& result); + void ReportTestPartResult(const TestPartResult& result) override; + private: void Init(); @@ -111,6 +116,8 @@ class GTEST_API_ SingleFailureChecker { } // namespace testing +GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 + // A set of macros for testing Google Test assertions or code that's expected // to generate Google Test fatal failures. It verifies that the given // statement will cause exactly one fatal Google Test failure with 'substr' diff --git a/cpp/test/include/gtest/gtest-test-part.h b/cpp/test/include/gtest/gtest-test-part.h index 77eb844839..05a7985358 100644 --- a/cpp/test/include/gtest/gtest-test-part.h +++ b/cpp/test/include/gtest/gtest-test-part.h @@ -27,8 +27,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // -// Author: mheule@google.com (Markus Heule) -// +// GOOGLETEST_CM0001 DO NOT DELETE #ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ #define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ @@ -38,6 +37,9 @@ #include "gtest/internal/gtest-internal.h" #include "gtest/internal/gtest-string.h" +GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ +/* class A needs to have dll-interface to be used by clients of class B */) + namespace testing { // A copyable object representing the result of a test part (i.e. an @@ -51,22 +53,20 @@ class GTEST_API_ TestPartResult { enum Type { kSuccess, // Succeeded. kNonFatalFailure, // Failed but the test can continue. - kFatalFailure // Failed and the test should be terminated. + kFatalFailure, // Failed and the test should be terminated. + kSkip // Skipped. }; // C'tor. TestPartResult does NOT have a default constructor. // Always use this constructor (with parameters) to create a // TestPartResult object. - TestPartResult(Type a_type, - const char* a_file_name, - int a_line_number, + TestPartResult(Type a_type, const char* a_file_name, int a_line_number, const char* a_message) : type_(a_type), - file_name_(a_file_name == NULL ? "" : a_file_name), + file_name_(a_file_name == nullptr ? "" : a_file_name), line_number_(a_line_number), summary_(ExtractSummary(a_message)), - message_(a_message) { - } + message_(a_message) {} // Gets the outcome of the test part. Type type() const { return type_; } @@ -74,7 +74,7 @@ class GTEST_API_ TestPartResult { // Gets the name of the source file where the test part took place, or // NULL if it's unknown. const char* file_name() const { - return file_name_.empty() ? NULL : file_name_.c_str(); + return file_name_.empty() ? nullptr : file_name_.c_str(); } // Gets the line in the source file where the test part took place, @@ -87,18 +87,21 @@ class GTEST_API_ TestPartResult { // Gets the message associated with the test part. const char* message() const { return message_.c_str(); } - // Returns true iff the test part passed. - bool passed() const { return type_ == kSuccess; } + // Returns true if and only if the test part was skipped. + bool skipped() const { return type_ == kSkip; } - // Returns true iff the test part failed. - bool failed() const { return type_ != kSuccess; } + // Returns true if and only if the test part passed. + bool passed() const { return type_ == kSuccess; } - // Returns true iff the test part non-fatally failed. + // Returns true if and only if the test part non-fatally failed. bool nonfatally_failed() const { return type_ == kNonFatalFailure; } - // Returns true iff the test part fatally failed. + // Returns true if and only if the test part fatally failed. bool fatally_failed() const { return type_ == kFatalFailure; } + // Returns true if and only if the test part failed. + bool failed() const { return fatally_failed() || nonfatally_failed(); } + private: Type type_; @@ -143,7 +146,7 @@ class GTEST_API_ TestPartResultArray { }; // This interface knows how to report a test part result. -class TestPartResultReporterInterface { +class GTEST_API_ TestPartResultReporterInterface { public: virtual ~TestPartResultReporterInterface() {} @@ -162,8 +165,8 @@ class GTEST_API_ HasNewFatalFailureHelper : public TestPartResultReporterInterface { public: HasNewFatalFailureHelper(); - virtual ~HasNewFatalFailureHelper(); - virtual void ReportTestPartResult(const TestPartResult& result); + ~HasNewFatalFailureHelper() override; + void ReportTestPartResult(const TestPartResult& result) override; bool has_new_fatal_failure() const { return has_new_fatal_failure_; } private: bool has_new_fatal_failure_; @@ -176,4 +179,6 @@ class GTEST_API_ HasNewFatalFailureHelper } // namespace testing +GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 + #endif // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ diff --git a/cpp/test/include/gtest/gtest-typed-test.h b/cpp/test/include/gtest/gtest-typed-test.h index 20726b2cd5..151fc8f769 100644 --- a/cpp/test/include/gtest/gtest-typed-test.h +++ b/cpp/test/include/gtest/gtest-typed-test.h @@ -26,8 +26,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Author: wan@google.com (Zhanyong Wan) + +// GOOGLETEST_CM0001 DO NOT DELETE #ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ #define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ @@ -51,22 +51,22 @@ class FooTest : public testing::Test { T value_; }; -// Next, associate a list of types with the test case, which will be +// Next, associate a list of types with the test suite, which will be // repeated for each type in the list. The typedef is necessary for // the macro to parse correctly. typedef testing::Types MyTypes; -TYPED_TEST_CASE(FooTest, MyTypes); +TYPED_TEST_SUITE(FooTest, MyTypes); // If the type list contains only one type, you can write that type // directly without Types<...>: -// TYPED_TEST_CASE(FooTest, int); +// TYPED_TEST_SUITE(FooTest, int); // Then, use TYPED_TEST() instead of TEST_F() to define as many typed -// tests for this test case as you want. +// tests for this test suite as you want. TYPED_TEST(FooTest, DoesBlah) { - // Inside a test, refer to TypeParam to get the type parameter. - // Since we are inside a derived class template, C++ requires use to - // visit the members of FooTest via 'this'. + // Inside a test, refer to the special name TypeParam to get the type + // parameter. Since we are inside a derived class template, C++ requires + // us to visit the members of FooTest via 'this'. TypeParam n = this->value_; // To visit static members of the fixture, add the TestFixture:: @@ -82,6 +82,24 @@ TYPED_TEST(FooTest, DoesBlah) { TYPED_TEST(FooTest, HasPropertyA) { ... } +// TYPED_TEST_SUITE takes an optional third argument which allows to specify a +// class that generates custom test name suffixes based on the type. This should +// be a class which has a static template function GetName(int index) returning +// a string for each type. The provided integer index equals the index of the +// type in the provided type list. In many cases the index can be ignored. +// +// For example: +// class MyTypeNames { +// public: +// template +// static std::string GetName(int) { +// if (std::is_same()) return "char"; +// if (std::is_same()) return "int"; +// if (std::is_same()) return "unsignedInt"; +// } +// }; +// TYPED_TEST_SUITE(FooTest, MyTypes, MyTypeNames); + #endif // 0 // Type-parameterized tests are abstract test patterns parameterized @@ -107,13 +125,13 @@ class FooTest : public testing::Test { ... }; -// Next, declare that you will define a type-parameterized test case +// Next, declare that you will define a type-parameterized test suite // (the _P suffix is for "parameterized" or "pattern", whichever you // prefer): -TYPED_TEST_CASE_P(FooTest); +TYPED_TEST_SUITE_P(FooTest); // Then, use TYPED_TEST_P() to define as many type-parameterized tests -// for this type-parameterized test case as you want. +// for this type-parameterized test suite as you want. TYPED_TEST_P(FooTest, DoesBlah) { // Inside a test, refer to TypeParam to get the type parameter. TypeParam n = 0; @@ -124,10 +142,10 @@ TYPED_TEST_P(FooTest, HasPropertyA) { ... } // Now the tricky part: you need to register all test patterns before // you can instantiate them. The first argument of the macro is the -// test case name; the rest are the names of the tests in this test +// test suite name; the rest are the names of the tests in this test // case. -REGISTER_TYPED_TEST_CASE_P(FooTest, - DoesBlah, HasPropertyA); +REGISTER_TYPED_TEST_SUITE_P(FooTest, + DoesBlah, HasPropertyA); // Finally, you are free to instantiate the pattern with the types you // want. If you put the above code in a header file, you can #include @@ -135,14 +153,19 @@ REGISTER_TYPED_TEST_CASE_P(FooTest, // // To distinguish different instances of the pattern, the first // argument to the INSTANTIATE_* macro is a prefix that will be added -// to the actual test case name. Remember to pick unique prefixes for +// to the actual test suite name. Remember to pick unique prefixes for // different instances. typedef testing::Types MyTypes; -INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes); +INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes); // If the type list contains only one type, you can write that type // directly without Types<...>: -// INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int); +// INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, int); +// +// Similar to the optional argument of TYPED_TEST_SUITE above, +// INSTANTIATE_TEST_SUITE_P takes an optional fourth argument which allows to +// generate custom names. +// INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes, MyTypeNames); #endif // 0 @@ -156,35 +179,52 @@ INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes); // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // // Expands to the name of the typedef for the type parameters of the -// given test case. -# define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_ - -// The 'Types' template argument below must have spaces around it -// since some compilers may choke on '>>' when passing a template -// instance (e.g. Types) -# define TYPED_TEST_CASE(CaseName, Types) \ - typedef ::testing::internal::TypeList< Types >::type \ - GTEST_TYPE_PARAMS_(CaseName) - -# define TYPED_TEST(CaseName, TestName) \ - template \ - class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \ - : public CaseName { \ - private: \ - typedef CaseName TestFixture; \ - typedef gtest_TypeParam_ TypeParam; \ - virtual void TestBody(); \ - }; \ - bool gtest_##CaseName##_##TestName##_registered_ GTEST_ATTRIBUTE_UNUSED_ = \ - ::testing::internal::TypeParameterizedTest< \ - CaseName, \ - ::testing::internal::TemplateSel< \ - GTEST_TEST_CLASS_NAME_(CaseName, TestName)>, \ - GTEST_TYPE_PARAMS_(CaseName)>::Register(\ - "", ::testing::internal::CodeLocation(__FILE__, __LINE__), \ - #CaseName, #TestName, 0); \ - template \ - void GTEST_TEST_CLASS_NAME_(CaseName, TestName)::TestBody() +// given test suite. +#define GTEST_TYPE_PARAMS_(TestSuiteName) gtest_type_params_##TestSuiteName##_ + +// Expands to the name of the typedef for the NameGenerator, responsible for +// creating the suffixes of the name. +#define GTEST_NAME_GENERATOR_(TestSuiteName) \ + gtest_type_params_##TestSuiteName##_NameGenerator + +#define TYPED_TEST_SUITE(CaseName, Types, ...) \ + typedef ::testing::internal::GenerateTypeList::type \ + GTEST_TYPE_PARAMS_(CaseName); \ + typedef ::testing::internal::NameGeneratorSelector<__VA_ARGS__>::type \ + GTEST_NAME_GENERATOR_(CaseName) + +#define TYPED_TEST(CaseName, TestName) \ + template \ + class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \ + : public CaseName { \ + private: \ + typedef CaseName TestFixture; \ + typedef gtest_TypeParam_ TypeParam; \ + void TestBody() override; \ + }; \ + static bool gtest_##CaseName##_##TestName##_registered_ \ + GTEST_ATTRIBUTE_UNUSED_ = ::testing::internal::TypeParameterizedTest< \ + CaseName, \ + ::testing::internal::TemplateSel, \ + GTEST_TYPE_PARAMS_( \ + CaseName)>::Register("", \ + ::testing::internal::CodeLocation( \ + __FILE__, __LINE__), \ + #CaseName, #TestName, 0, \ + ::testing::internal::GenerateNames< \ + GTEST_NAME_GENERATOR_(CaseName), \ + GTEST_TYPE_PARAMS_(CaseName)>()); \ + template \ + void GTEST_TEST_CLASS_NAME_(CaseName, \ + TestName)::TestBody() + +// Legacy API is deprecated but still available +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ +#define TYPED_TEST_CASE \ + static_assert(::testing::internal::TypedTestCaseIsDeprecated(), ""); \ + TYPED_TEST_SUITE +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ #endif // GTEST_HAS_TYPED_TEST @@ -195,69 +235,93 @@ INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes); // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // // Expands to the namespace name that the type-parameterized tests for -// the given type-parameterized test case are defined in. The exact +// the given type-parameterized test suite are defined in. The exact // name of the namespace is subject to change without notice. -# define GTEST_CASE_NAMESPACE_(TestCaseName) \ - gtest_case_##TestCaseName##_ +#define GTEST_SUITE_NAMESPACE_(TestSuiteName) gtest_suite_##TestSuiteName##_ // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // // Expands to the name of the variable used to remember the names of -// the defined tests in the given test case. -# define GTEST_TYPED_TEST_CASE_P_STATE_(TestCaseName) \ - gtest_typed_test_case_p_state_##TestCaseName##_ +// the defined tests in the given test suite. +#define GTEST_TYPED_TEST_SUITE_P_STATE_(TestSuiteName) \ + gtest_typed_test_suite_p_state_##TestSuiteName##_ // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY. // // Expands to the name of the variable used to remember the names of -// the registered tests in the given test case. -# define GTEST_REGISTERED_TEST_NAMES_(TestCaseName) \ - gtest_registered_test_names_##TestCaseName##_ +// the registered tests in the given test suite. +#define GTEST_REGISTERED_TEST_NAMES_(TestSuiteName) \ + gtest_registered_test_names_##TestSuiteName##_ // The variables defined in the type-parameterized test macros are // static as typically these macros are used in a .h file that can be // #included in multiple translation units linked together. -# define TYPED_TEST_CASE_P(CaseName) \ - static ::testing::internal::TypedTestCasePState \ - GTEST_TYPED_TEST_CASE_P_STATE_(CaseName) - -# define TYPED_TEST_P(CaseName, TestName) \ - namespace GTEST_CASE_NAMESPACE_(CaseName) { \ - template \ - class TestName : public CaseName { \ - private: \ - typedef CaseName TestFixture; \ - typedef gtest_TypeParam_ TypeParam; \ - virtual void TestBody(); \ - }; \ - static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \ - GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).AddTestName(\ - __FILE__, __LINE__, #CaseName, #TestName); \ - } \ - template \ - void GTEST_CASE_NAMESPACE_(CaseName)::TestName::TestBody() - -# define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \ - namespace GTEST_CASE_NAMESPACE_(CaseName) { \ - typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \ - } \ - static const char* const GTEST_REGISTERED_TEST_NAMES_(CaseName) \ - GTEST_ATTRIBUTE_UNUSED_ = \ - GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames(\ - __FILE__, __LINE__, #__VA_ARGS__) - -// The 'Types' template argument below must have spaces around it -// since some compilers may choke on '>>' when passing a template -// instance (e.g. Types) -# define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \ - bool gtest_##Prefix##_##CaseName GTEST_ATTRIBUTE_UNUSED_ = \ - ::testing::internal::TypeParameterizedTestCase::type>::Register(\ - #Prefix, \ - ::testing::internal::CodeLocation(__FILE__, __LINE__), \ - >EST_TYPED_TEST_CASE_P_STATE_(CaseName), \ - #CaseName, GTEST_REGISTERED_TEST_NAMES_(CaseName)) +#define TYPED_TEST_SUITE_P(SuiteName) \ + static ::testing::internal::TypedTestSuitePState \ + GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName) + +// Legacy API is deprecated but still available +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ +#define TYPED_TEST_CASE_P \ + static_assert(::testing::internal::TypedTestCase_P_IsDeprecated(), ""); \ + TYPED_TEST_SUITE_P +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ + +#define TYPED_TEST_P(SuiteName, TestName) \ + namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \ + template \ + class TestName : public SuiteName { \ + private: \ + typedef SuiteName TestFixture; \ + typedef gtest_TypeParam_ TypeParam; \ + void TestBody() override; \ + }; \ + static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \ + GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).AddTestName( \ + __FILE__, __LINE__, #SuiteName, #TestName); \ + } \ + template \ + void GTEST_SUITE_NAMESPACE_( \ + SuiteName)::TestName::TestBody() + +#define REGISTER_TYPED_TEST_SUITE_P(SuiteName, ...) \ + namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \ + typedef ::testing::internal::Templates<__VA_ARGS__> gtest_AllTests_; \ + } \ + static const char* const GTEST_REGISTERED_TEST_NAMES_( \ + SuiteName) GTEST_ATTRIBUTE_UNUSED_ = \ + GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).VerifyRegisteredTestNames( \ + __FILE__, __LINE__, #__VA_ARGS__) + +// Legacy API is deprecated but still available +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ +#define REGISTER_TYPED_TEST_CASE_P \ + static_assert(::testing::internal::RegisterTypedTestCase_P_IsDeprecated(), \ + ""); \ + REGISTER_TYPED_TEST_SUITE_P +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ + +#define INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, SuiteName, Types, ...) \ + static bool gtest_##Prefix##_##SuiteName GTEST_ATTRIBUTE_UNUSED_ = \ + ::testing::internal::TypeParameterizedTestSuite< \ + SuiteName, GTEST_SUITE_NAMESPACE_(SuiteName)::gtest_AllTests_, \ + ::testing::internal::GenerateTypeList::type>:: \ + Register(#Prefix, \ + ::testing::internal::CodeLocation(__FILE__, __LINE__), \ + >EST_TYPED_TEST_SUITE_P_STATE_(SuiteName), #SuiteName, \ + GTEST_REGISTERED_TEST_NAMES_(SuiteName), \ + ::testing::internal::GenerateNames< \ + ::testing::internal::NameGeneratorSelector< \ + __VA_ARGS__>::type, \ + ::testing::internal::GenerateTypeList::type>()) + +// Legacy API is deprecated but still available +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ +#define INSTANTIATE_TYPED_TEST_CASE_P \ + static_assert( \ + ::testing::internal::InstantiateTypedTestCase_P_IsDeprecated(), ""); \ + INSTANTIATE_TYPED_TEST_SUITE_P +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ #endif // GTEST_HAS_TYPED_TEST_P diff --git a/cpp/test/include/gtest/gtest.h b/cpp/test/include/gtest/gtest.h index c1cd69ab46..8eda6eac2b 100644 --- a/cpp/test/include/gtest/gtest.h +++ b/cpp/test/include/gtest/gtest.h @@ -26,10 +26,9 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + // -// Author: wan@google.com (Zhanyong Wan) -// -// The Google C++ Testing Framework (Google Test) +// The Google C++ Testing and Mocking Framework (Google Test) // // This header file defines the public API for Google Test. It should be // included by any test program that uses Google Test. @@ -48,16 +47,22 @@ // registration from Barthelemy Dagenais' (barthelemy@prologique.com) // easyUnit framework. +// GOOGLETEST_CM0001 DO NOT DELETE + #ifndef GTEST_INCLUDE_GTEST_GTEST_H_ #define GTEST_INCLUDE_GTEST_GTEST_H_ +#include #include +#include #include +#include #include #include "gtest/internal/gtest-internal.h" #include "gtest/internal/gtest-string.h" #include "gtest/gtest-death-test.h" +#include "gtest/gtest-matchers.h" #include "gtest/gtest-message.h" #include "gtest/gtest-param-test.h" #include "gtest/gtest-printers.h" @@ -65,23 +70,20 @@ #include "gtest/gtest-test-part.h" #include "gtest/gtest-typed-test.h" -// Depending on the platform, different string classes are available. -// On Linux, in addition to ::std::string, Google also makes use of -// class ::string, which has the same interface as ::std::string, but -// has a different implementation. -// -// You can define GTEST_HAS_GLOBAL_STRING to 1 to indicate that -// ::string is available AND is a distinct type to ::std::string, or -// define it to 0 to indicate otherwise. -// -// If ::std::string and ::string are the same class on your platform -// due to aliasing, you should define GTEST_HAS_GLOBAL_STRING to 0. -// -// If you do not define GTEST_HAS_GLOBAL_STRING, it is defined -// heuristically. +GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ +/* class A needs to have dll-interface to be used by clients of class B */) namespace testing { +// Silence C4100 (unreferenced formal parameter) and 4805 +// unsafe mix of type 'const int' and type 'const bool' +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable:4805) +# pragma warning(disable:4100) +#endif + + // Declares the flags. // This flag temporary enables the disabled tests. @@ -103,6 +105,10 @@ GTEST_DECLARE_string_(color); // the tests to run. If the filter is not given all tests are executed. GTEST_DECLARE_string_(filter); +// This flag controls whether Google Test installs a signal handler that dumps +// debugging information when fatal signals are raised. +GTEST_DECLARE_bool_(install_failure_signal_handler); + // This flag causes the Google Test to list tests. None of the tests listed // are actually run if the flag is provided. GTEST_DECLARE_bool_(list_tests); @@ -115,6 +121,9 @@ GTEST_DECLARE_string_(output); // test. GTEST_DECLARE_bool_(print_time); +// This flags control whether Google Test prints UTF8 characters as text. +GTEST_DECLARE_bool_(print_utf8); + // This flag specifies the random number seed. GTEST_DECLARE_int32_(random_seed); @@ -135,7 +144,7 @@ GTEST_DECLARE_int32_(stack_trace_depth); // When this flag is specified, a failed assertion will throw an // exception if exceptions are enabled, or exit the program with a -// non-zero code otherwise. +// non-zero code otherwise. For use with an external test framework. GTEST_DECLARE_bool_(throw_on_failure); // When this flag is set with a "host:port" string, on supported @@ -143,6 +152,10 @@ GTEST_DECLARE_bool_(throw_on_failure); // the specified host machine. GTEST_DECLARE_string_(stream_result_to); +#if GTEST_USE_OWN_FLAGFILE_FLAG_ +GTEST_DECLARE_string_(flagfile); +#endif // GTEST_USE_OWN_FLAGFILE_FLAG_ + // The upper limit for valid stack trace depths. const int kMaxStackTraceDepth = 100; @@ -160,6 +173,7 @@ class TestEventListenersAccessor; class TestEventRepeater; class UnitTestRecordPropertyTestHelper; class WindowsDeathTest; +class FuchsiaDeathTest; class UnitTestImpl* GetUnitTestImpl(); void ReportFailureInUnknownLocation(TestPartResult::Type result_type, const std::string& message); @@ -170,7 +184,12 @@ void ReportFailureInUnknownLocation(TestPartResult::Type result_type, // If we don't forward declare them the compiler might confuse the classes // in friendship clauses with same named classes on the scope. class Test; -class TestCase; +class TestSuite; + +// Old API is still available but deprecated +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ +using TestCase = TestSuite; +#endif class TestInfo; class UnitTest; @@ -259,7 +278,9 @@ class GTEST_API_ AssertionResult { // Used in EXPECT_TRUE/FALSE(assertion_result). AssertionResult(const AssertionResult& other); +#if defined(_MSC_VER) && _MSC_VER < 1910 GTEST_DISABLE_MSC_WARNINGS_PUSH_(4800 /* forcing value to bool */) +#endif // Used in the EXPECT_TRUE/FALSE(bool_expression). // @@ -271,12 +292,15 @@ class GTEST_API_ AssertionResult { template explicit AssertionResult( const T& success, - typename internal::EnableIf< - !internal::ImplicitlyConvertible::value>::type* - /*enabler*/ = NULL) + typename std::enable_if< + !std::is_convertible::value>::type* + /*enabler*/ + = nullptr) : success_(success) {} +#if defined(_MSC_VER) && _MSC_VER < 1910 GTEST_DISABLE_MSC_WARNINGS_POP_() +#endif // Assignment operator. AssertionResult& operator=(AssertionResult other) { @@ -284,7 +308,7 @@ class GTEST_API_ AssertionResult { return *this; } - // Returns true iff the assertion succeeded. + // Returns true if and only if the assertion succeeded. operator bool() const { return success_; } // NOLINT // Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE. @@ -295,9 +319,8 @@ class GTEST_API_ AssertionResult { // assertion's expectation). When nothing has been streamed into the // object, returns an empty string. const char* message() const { - return message_.get() != NULL ? message_->c_str() : ""; + return message_.get() != nullptr ? message_->c_str() : ""; } - // TODO(vladl@google.com): Remove this after making sure no clients use it. // Deprecated; please use message() instead. const char* failure_message() const { return message(); } @@ -318,8 +341,7 @@ class GTEST_API_ AssertionResult { private: // Appends the contents of message to message_. void AppendMessage(const Message& a_message) { - if (message_.get() == NULL) - message_.reset(new ::std::string); + if (message_.get() == nullptr) message_.reset(new ::std::string); message_->append(a_message.GetString().c_str()); } @@ -332,7 +354,7 @@ class GTEST_API_ AssertionResult { // construct is not satisfied with the predicate's outcome. // Referenced via a pointer to avoid taking too much stack frame space // with test assertions. - internal::scoped_ptr< ::std::string> message_; + std::unique_ptr< ::std::string> message_; }; // Makes a successful assertion result. @@ -345,17 +367,26 @@ GTEST_API_ AssertionResult AssertionFailure(); // Deprecated; use AssertionFailure() << msg. GTEST_API_ AssertionResult AssertionFailure(const Message& msg); +} // namespace testing + +// Includes the auto-generated header that implements a family of generic +// predicate assertion macros. This include comes late because it relies on +// APIs declared above. +#include "gtest/gtest_pred_impl.h" + +namespace testing { + // The abstract class that all tests inherit from. // -// In Google Test, a unit test program contains one or many TestCases, and -// each TestCase contains one or many Tests. +// In Google Test, a unit test program contains one or many TestSuites, and +// each TestSuite contains one or many Tests. // // When you define a test using the TEST macro, you don't need to // explicitly derive from Test - the TEST macro automatically does // this for you. // // The only time you derive from Test is when defining a test fixture -// to be used a TEST_F. For example: +// to be used in a TEST_F. For example: // // class FooTest : public testing::Test { // protected: @@ -372,49 +403,57 @@ class GTEST_API_ Test { public: friend class TestInfo; - // Defines types for pointers to functions that set up and tear down - // a test case. - typedef internal::SetUpTestCaseFunc SetUpTestCaseFunc; - typedef internal::TearDownTestCaseFunc TearDownTestCaseFunc; - // The d'tor is virtual as we intend to inherit from Test. virtual ~Test(); // Sets up the stuff shared by all tests in this test case. // - // Google Test will call Foo::SetUpTestCase() before running the first + // Google Test will call Foo::SetUpTestSuite() before running the first // test in test case Foo. Hence a sub-class can define its own - // SetUpTestCase() method to shadow the one defined in the super + // SetUpTestSuite() method to shadow the one defined in the super // class. - static void SetUpTestCase() {} + // Failures that happen during SetUpTestSuite are logged but otherwise + // ignored. + static void SetUpTestSuite() {} - // Tears down the stuff shared by all tests in this test case. + // Tears down the stuff shared by all tests in this test suite. // - // Google Test will call Foo::TearDownTestCase() after running the last + // Google Test will call Foo::TearDownTestSuite() after running the last // test in test case Foo. Hence a sub-class can define its own - // TearDownTestCase() method to shadow the one defined in the super + // TearDownTestSuite() method to shadow the one defined in the super // class. + // Failures that happen during TearDownTestSuite are logged but otherwise + // ignored. + static void TearDownTestSuite() {} + + // Legacy API is deprecated but still available +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ static void TearDownTestCase() {} + static void SetUpTestCase() {} +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ - // Returns true iff the current test has a fatal failure. + // Returns true if and only if the current test has a fatal failure. static bool HasFatalFailure(); - // Returns true iff the current test has a non-fatal failure. + // Returns true if and only if the current test has a non-fatal failure. static bool HasNonfatalFailure(); - // Returns true iff the current test has a (either fatal or + // Returns true if and only if the current test was skipped. + static bool IsSkipped(); + + // Returns true if and only if the current test has a (either fatal or // non-fatal) failure. static bool HasFailure() { return HasFatalFailure() || HasNonfatalFailure(); } - // Logs a property for the current test, test case, or for the entire + // Logs a property for the current test, test suite, or for the entire // invocation of the test program when used outside of the context of a - // test case. Only the last value for a given key is remembered. These + // test suite. Only the last value for a given key is remembered. These // are public static so they can be called from utility functions that are // not members of the test fixture. Calls to RecordProperty made during // lifespan of the test (from the moment its constructor starts to the // moment its destructor finishes) will be output in XML as attributes of // the element. Properties recorded from fixture's - // SetUpTestCase or TearDownTestCase are logged as attributes of the + // SetUpTestSuite or TearDownTestSuite are logged as attributes of the // corresponding element. Calls to RecordProperty made in the // global context (before or after invocation of RUN_ALL_TESTS and from // SetUp/TearDown method of Environment objects registered with Google @@ -433,8 +472,8 @@ class GTEST_API_ Test { virtual void TearDown(); private: - // Returns true iff the current test has the same fixture class as - // the first test in the current test case. + // Returns true if and only if the current test has the same fixture class + // as the first test in the current test suite. static bool HasSameFixtureClass(); // Runs the test after the test fixture has been set up. @@ -452,7 +491,7 @@ class GTEST_API_ Test { // internal method to avoid clashing with names used in user TESTs. void DeleteSelf_() { delete this; } - const internal::scoped_ptr< GTEST_FLAG_SAVER_ > gtest_flag_saver_; + const std::unique_ptr gtest_flag_saver_; // Often a user misspells SetUp() as Setup() and spends a long time // wondering why it is never called by Google Test. The declaration of @@ -471,7 +510,7 @@ class GTEST_API_ Test { // If you see an error about overriding the following function or // about it being private, you have mis-spelled SetUp() as Setup(). struct Setup_should_be_spelled_SetUp {}; - virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; } + virtual Setup_should_be_spelled_SetUp* Setup() { return nullptr; } // We disallow copying Tests. GTEST_DISALLOW_COPY_AND_ASSIGN_(Test); @@ -535,24 +574,30 @@ class GTEST_API_ TestResult { // Returns the number of the test properties. int test_property_count() const; - // Returns true iff the test passed (i.e. no test part failed). - bool Passed() const { return !Failed(); } + // Returns true if and only if the test passed (i.e. no test part failed). + bool Passed() const { return !Skipped() && !Failed(); } + + // Returns true if and only if the test was skipped. + bool Skipped() const; - // Returns true iff the test failed. + // Returns true if and only if the test failed. bool Failed() const; - // Returns true iff the test fatally failed. + // Returns true if and only if the test fatally failed. bool HasFatalFailure() const; - // Returns true iff the test has a non-fatal failure. + // Returns true if and only if the test has a non-fatal failure. bool HasNonfatalFailure() const; // Returns the elapsed time, in milliseconds. TimeInMillis elapsed_time() const { return elapsed_time_; } - // Returns the i-th test part result among all the results. i can range - // from 0 to test_property_count() - 1. If i is not in that range, aborts - // the program. + // Gets the time of the test case start, in ms from the start of the + // UNIX epoch. + TimeInMillis start_timestamp() const { return start_timestamp_; } + + // Returns the i-th test part result among all the results. i can range from 0 + // to total_part_count() - 1. If i is not in that range, aborts the program. const TestPartResult& GetTestPartResult(int i) const; // Returns the i-th test property. i can range from 0 to @@ -562,13 +607,14 @@ class GTEST_API_ TestResult { private: friend class TestInfo; - friend class TestCase; + friend class TestSuite; friend class UnitTest; friend class internal::DefaultGlobalTestPartResultReporter; friend class internal::ExecDeathTest; friend class internal::TestResultAccessor; friend class internal::UnitTestImpl; friend class internal::WindowsDeathTest; + friend class internal::FuchsiaDeathTest; // Gets the vector of TestPartResults. const std::vector& test_part_results() const { @@ -580,6 +626,9 @@ class GTEST_API_ TestResult { return test_properties_; } + // Sets the start time. + void set_start_timestamp(TimeInMillis start) { start_timestamp_ = start; } + // Sets the elapsed time. void set_elapsed_time(TimeInMillis elapsed) { elapsed_time_ = elapsed; } @@ -593,8 +642,8 @@ class GTEST_API_ TestResult { const TestProperty& test_property); // Adds a failure if the key is a reserved attribute of Google Test - // testcase tags. Returns true if the property is valid. - // TODO(russr): Validate attribute names are legal and human readable. + // testsuite tags. Returns true if the property is valid. + // FIXME: Validate attribute names are legal and human readable. static bool ValidateTestProperty(const std::string& xml_element, const TestProperty& test_property); @@ -623,6 +672,8 @@ class GTEST_API_ TestResult { std::vector test_properties_; // Running count of death tests. int death_test_count_; + // The start time, in milliseconds since UNIX Epoch. + TimeInMillis start_timestamp_; // The elapsed time, in milliseconds. TimeInMillis elapsed_time_; @@ -632,7 +683,7 @@ class GTEST_API_ TestResult { // A TestInfo object stores the following information about a test: // -// Test case name +// Test suite name // Test name // Whether the test should be run // A function pointer that creates the test object when invoked @@ -647,8 +698,13 @@ class GTEST_API_ TestInfo { // don't inherit from TestInfo. ~TestInfo(); - // Returns the test case name. - const char* test_case_name() const { return test_case_name_.c_str(); } + // Returns the test suite name. + const char* test_suite_name() const { return test_suite_name_.c_str(); } + +// Legacy API is deprecated but still available +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ + const char* test_case_name() const { return test_suite_name(); } +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ // Returns the test name. const char* name() const { return name_.c_str(); } @@ -656,17 +712,15 @@ class GTEST_API_ TestInfo { // Returns the name of the parameter type, or NULL if this is not a typed // or a type-parameterized test. const char* type_param() const { - if (type_param_.get() != NULL) - return type_param_->c_str(); - return NULL; + if (type_param_.get() != nullptr) return type_param_->c_str(); + return nullptr; } // Returns the text representation of the value parameter, or NULL if this // is not a value-parameterized test. const char* value_param() const { - if (value_param_.get() != NULL) - return value_param_->c_str(); - return NULL; + if (value_param_.get() != nullptr) return value_param_->c_str(); + return nullptr; } // Returns the file name where this test is defined. @@ -675,12 +729,15 @@ class GTEST_API_ TestInfo { // Returns the line where this test is defined. int line() const { return location_.line; } + // Return true if this test should not be run because it's in another shard. + bool is_in_another_shard() const { return is_in_another_shard_; } + // Returns true if this test should run, that is if the test is not // disabled (or it is disabled but the also_run_disabled_tests flag has // been specified) and its full name matches the user-specified filter. // // Google Test allows the user to filter the tests by their full names. - // The full name of a test Bar in test case Foo is defined as + // The full name of a test Bar in test suite Foo is defined as // "Foo.Bar". Only the tests that match the filter will run. // // A filter is a colon-separated list of glob (not regex) patterns, @@ -693,12 +750,11 @@ class GTEST_API_ TestInfo { // contains the character 'A' or starts with "Foo.". bool should_run() const { return should_run_; } - // Returns true iff this test will appear in the XML report. + // Returns true if and only if this test will appear in the XML report. bool is_reportable() const { - // For now, the XML report includes all tests matching the filter. - // In the future, we may trim tests that are excluded because of - // sharding. - return matches_filter_; + // The XML report includes tests matching the filter, excluding those + // run in other shards. + return matches_filter_ && !is_in_another_shard_; } // Returns the result of the test. @@ -709,24 +765,19 @@ class GTEST_API_ TestInfo { friend class internal::DefaultDeathTestFactory; #endif // GTEST_HAS_DEATH_TEST friend class Test; - friend class TestCase; + friend class TestSuite; friend class internal::UnitTestImpl; friend class internal::StreamingListenerTest; friend TestInfo* internal::MakeAndRegisterTestInfo( - const char* test_case_name, - const char* name, - const char* type_param, - const char* value_param, - internal::CodeLocation code_location, - internal::TypeId fixture_class_id, - Test::SetUpTestCaseFunc set_up_tc, - Test::TearDownTestCaseFunc tear_down_tc, + const char* test_suite_name, const char* name, const char* type_param, + const char* value_param, internal::CodeLocation code_location, + internal::TypeId fixture_class_id, internal::SetUpTestSuiteFunc set_up_tc, + internal::TearDownTestSuiteFunc tear_down_tc, internal::TestFactoryBase* factory); // Constructs a TestInfo object. The newly constructed instance assumes // ownership of the factory object. - TestInfo(const std::string& test_case_name, - const std::string& name, + TestInfo(const std::string& test_suite_name, const std::string& name, const char* a_type_param, // NULL if not a type-parameterized test const char* a_value_param, // NULL if not a value-parameterized test internal::CodeLocation a_code_location, @@ -748,20 +799,21 @@ class GTEST_API_ TestInfo { } // These fields are immutable properties of the test. - const std::string test_case_name_; // Test case name + const std::string test_suite_name_; // test suite name const std::string name_; // Test name // Name of the parameter type, or NULL if this is not a typed or a // type-parameterized test. - const internal::scoped_ptr type_param_; + const std::unique_ptr type_param_; // Text representation of the value parameter, or NULL if this is not a // value-parameterized test. - const internal::scoped_ptr value_param_; + const std::unique_ptr value_param_; internal::CodeLocation location_; - const internal::TypeId fixture_class_id_; // ID of the test fixture class - bool should_run_; // True iff this test should run - bool is_disabled_; // True iff this test is disabled - bool matches_filter_; // True if this test matches the - // user-specified filter. + const internal::TypeId fixture_class_id_; // ID of the test fixture class + bool should_run_; // True if and only if this test should run + bool is_disabled_; // True if and only if this test is disabled + bool matches_filter_; // True if this test matches the + // user-specified filter. + bool is_in_another_shard_; // Will be run in another shard. internal::TestFactoryBase* const factory_; // The factory that creates // the test object @@ -772,90 +824,96 @@ class GTEST_API_ TestInfo { GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfo); }; -// A test case, which consists of a vector of TestInfos. +// A test suite, which consists of a vector of TestInfos. // -// TestCase is not copyable. -class GTEST_API_ TestCase { +// TestSuite is not copyable. +class GTEST_API_ TestSuite { public: - // Creates a TestCase with the given name. + // Creates a TestSuite with the given name. // - // TestCase does NOT have a default constructor. Always use this - // constructor to create a TestCase object. + // TestSuite does NOT have a default constructor. Always use this + // constructor to create a TestSuite object. // // Arguments: // - // name: name of the test case + // name: name of the test suite // a_type_param: the name of the test's type parameter, or NULL if // this is not a type-parameterized test. - // set_up_tc: pointer to the function that sets up the test case - // tear_down_tc: pointer to the function that tears down the test case - TestCase(const char* name, const char* a_type_param, - Test::SetUpTestCaseFunc set_up_tc, - Test::TearDownTestCaseFunc tear_down_tc); + // set_up_tc: pointer to the function that sets up the test suite + // tear_down_tc: pointer to the function that tears down the test suite + TestSuite(const char* name, const char* a_type_param, + internal::SetUpTestSuiteFunc set_up_tc, + internal::TearDownTestSuiteFunc tear_down_tc); - // Destructor of TestCase. - virtual ~TestCase(); + // Destructor of TestSuite. + virtual ~TestSuite(); - // Gets the name of the TestCase. + // Gets the name of the TestSuite. const char* name() const { return name_.c_str(); } // Returns the name of the parameter type, or NULL if this is not a - // type-parameterized test case. + // type-parameterized test suite. const char* type_param() const { - if (type_param_.get() != NULL) - return type_param_->c_str(); - return NULL; + if (type_param_.get() != nullptr) return type_param_->c_str(); + return nullptr; } - // Returns true if any test in this test case should run. + // Returns true if any test in this test suite should run. bool should_run() const { return should_run_; } - // Gets the number of successful tests in this test case. + // Gets the number of successful tests in this test suite. int successful_test_count() const; - // Gets the number of failed tests in this test case. + // Gets the number of skipped tests in this test suite. + int skipped_test_count() const; + + // Gets the number of failed tests in this test suite. int failed_test_count() const; // Gets the number of disabled tests that will be reported in the XML report. int reportable_disabled_test_count() const; - // Gets the number of disabled tests in this test case. + // Gets the number of disabled tests in this test suite. int disabled_test_count() const; // Gets the number of tests to be printed in the XML report. int reportable_test_count() const; - // Get the number of tests in this test case that should run. + // Get the number of tests in this test suite that should run. int test_to_run_count() const; - // Gets the number of all tests in this test case. + // Gets the number of all tests in this test suite. int total_test_count() const; - // Returns true iff the test case passed. + // Returns true if and only if the test suite passed. bool Passed() const { return !Failed(); } - // Returns true iff the test case failed. + // Returns true if and only if the test suite failed. bool Failed() const { return failed_test_count() > 0; } // Returns the elapsed time, in milliseconds. TimeInMillis elapsed_time() const { return elapsed_time_; } + // Gets the time of the test suite start, in ms from the start of the + // UNIX epoch. + TimeInMillis start_timestamp() const { return start_timestamp_; } + // Returns the i-th test among all the tests. i can range from 0 to // total_test_count() - 1. If i is not in that range, returns NULL. const TestInfo* GetTestInfo(int i) const; // Returns the TestResult that holds test properties recorded during - // execution of SetUpTestCase and TearDownTestCase. + // execution of SetUpTestSuite and TearDownTestSuite. const TestResult& ad_hoc_test_result() const { return ad_hoc_test_result_; } private: friend class Test; friend class internal::UnitTestImpl; - // Gets the (mutable) vector of TestInfos in this TestCase. + // Gets the (mutable) vector of TestInfos in this TestSuite. std::vector& test_info_list() { return test_info_list_; } - // Gets the (immutable) vector of TestInfos in this TestCase. + // Gets the (immutable) vector of TestInfos in this TestSuite. const std::vector& test_info_list() const { return test_info_list_; } @@ -867,51 +925,64 @@ class GTEST_API_ TestCase { // Sets the should_run member. void set_should_run(bool should) { should_run_ = should; } - // Adds a TestInfo to this test case. Will delete the TestInfo upon - // destruction of the TestCase object. + // Adds a TestInfo to this test suite. Will delete the TestInfo upon + // destruction of the TestSuite object. void AddTestInfo(TestInfo * test_info); - // Clears the results of all tests in this test case. + // Clears the results of all tests in this test suite. void ClearResult(); - // Clears the results of all tests in the given test case. - static void ClearTestCaseResult(TestCase* test_case) { - test_case->ClearResult(); + // Clears the results of all tests in the given test suite. + static void ClearTestSuiteResult(TestSuite* test_suite) { + test_suite->ClearResult(); } - // Runs every test in this TestCase. + // Runs every test in this TestSuite. void Run(); - // Runs SetUpTestCase() for this TestCase. This wrapper is needed - // for catching exceptions thrown from SetUpTestCase(). - void RunSetUpTestCase() { (*set_up_tc_)(); } + // Runs SetUpTestSuite() for this TestSuite. This wrapper is needed + // for catching exceptions thrown from SetUpTestSuite(). + void RunSetUpTestSuite() { + if (set_up_tc_ != nullptr) { + (*set_up_tc_)(); + } + } - // Runs TearDownTestCase() for this TestCase. This wrapper is - // needed for catching exceptions thrown from TearDownTestCase(). - void RunTearDownTestCase() { (*tear_down_tc_)(); } + // Runs TearDownTestSuite() for this TestSuite. This wrapper is + // needed for catching exceptions thrown from TearDownTestSuite(). + void RunTearDownTestSuite() { + if (tear_down_tc_ != nullptr) { + (*tear_down_tc_)(); + } + } - // Returns true iff test passed. + // Returns true if and only if test passed. static bool TestPassed(const TestInfo* test_info) { return test_info->should_run() && test_info->result()->Passed(); } - // Returns true iff test failed. + // Returns true if and only if test skipped. + static bool TestSkipped(const TestInfo* test_info) { + return test_info->should_run() && test_info->result()->Skipped(); + } + + // Returns true if and only if test failed. static bool TestFailed(const TestInfo* test_info) { return test_info->should_run() && test_info->result()->Failed(); } - // Returns true iff the test is disabled and will be reported in the XML - // report. + // Returns true if and only if the test is disabled and will be reported in + // the XML report. static bool TestReportableDisabled(const TestInfo* test_info) { return test_info->is_reportable() && test_info->is_disabled_; } - // Returns true iff test is disabled. + // Returns true if and only if test is disabled. static bool TestDisabled(const TestInfo* test_info) { return test_info->is_disabled_; } - // Returns true iff this test will appear in the XML report. + // Returns true if and only if this test will appear in the XML report. static bool TestReportable(const TestInfo* test_info) { return test_info->is_reportable(); } @@ -921,17 +992,17 @@ class GTEST_API_ TestCase { return test_info->should_run(); } - // Shuffles the tests in this test case. + // Shuffles the tests in this test suite. void ShuffleTests(internal::Random* random); // Restores the test order to before the first shuffle. void UnshuffleTests(); - // Name of the test case. + // Name of the test suite. std::string name_; // Name of the parameter type, or NULL if this is not a typed or a // type-parameterized test. - const internal::scoped_ptr type_param_; + const std::unique_ptr type_param_; // The vector of TestInfos in their original order. It owns the // elements in the vector. std::vector test_info_list_; @@ -939,20 +1010,22 @@ class GTEST_API_ TestCase { // shuffling and restoring the test order. The i-th element in this // vector is the index of the i-th test in the shuffled test list. std::vector test_indices_; - // Pointer to the function that sets up the test case. - Test::SetUpTestCaseFunc set_up_tc_; - // Pointer to the function that tears down the test case. - Test::TearDownTestCaseFunc tear_down_tc_; - // True iff any test in this test case should run. + // Pointer to the function that sets up the test suite. + internal::SetUpTestSuiteFunc set_up_tc_; + // Pointer to the function that tears down the test suite. + internal::TearDownTestSuiteFunc tear_down_tc_; + // True if and only if any test in this test suite should run. bool should_run_; + // The start time, in milliseconds since UNIX Epoch. + TimeInMillis start_timestamp_; // Elapsed time, in milliseconds. TimeInMillis elapsed_time_; - // Holds test properties recorded during execution of SetUpTestCase and - // TearDownTestCase. + // Holds test properties recorded during execution of SetUpTestSuite and + // TearDownTestSuite. TestResult ad_hoc_test_result_; - // We disallow copying TestCases. - GTEST_DISALLOW_COPY_AND_ASSIGN_(TestCase); + // We disallow copying TestSuites. + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestSuite); }; // An Environment object is capable of setting up and tearing down an @@ -983,9 +1056,21 @@ class Environment { // If you see an error about overriding the following function or // about it being private, you have mis-spelled SetUp() as Setup(). struct Setup_should_be_spelled_SetUp {}; - virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; } + virtual Setup_should_be_spelled_SetUp* Setup() { return nullptr; } }; +#if GTEST_HAS_EXCEPTIONS + +// Exception which can be thrown from TestEventListener::OnTestPartResult. +class GTEST_API_ AssertionException + : public internal::GoogleTestFailureException { + public: + explicit AssertionException(const TestPartResult& result) + : GoogleTestFailureException(result) {} +}; + +#endif // GTEST_HAS_EXCEPTIONS + // The interface for tracing execution of tests. The methods are organized in // the order the corresponding events are fired. class TestEventListener { @@ -1007,20 +1092,32 @@ class TestEventListener { // Fired after environment set-up for each iteration of tests ends. virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) = 0; - // Fired before the test case starts. - virtual void OnTestCaseStart(const TestCase& test_case) = 0; + // Fired before the test suite starts. + virtual void OnTestSuiteStart(const TestSuite& /*test_suite*/) {} + + // Legacy API is deprecated but still available +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ + virtual void OnTestCaseStart(const TestCase& /*test_case*/) {} +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ // Fired before the test starts. virtual void OnTestStart(const TestInfo& test_info) = 0; // Fired after a failed assertion or a SUCCEED() invocation. + // If you want to throw an exception from this function to skip to the next + // TEST, it must be AssertionException defined above, or inherited from it. virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0; // Fired after the test ends. virtual void OnTestEnd(const TestInfo& test_info) = 0; - // Fired after the test case ends. - virtual void OnTestCaseEnd(const TestCase& test_case) = 0; + // Fired after the test suite ends. + virtual void OnTestSuiteEnd(const TestSuite& /*test_suite*/) {} + +// Legacy API is deprecated but still available +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ + virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {} +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ // Fired before environment tear-down for each iteration of tests starts. virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) = 0; @@ -1043,21 +1140,30 @@ class TestEventListener { // above. class EmptyTestEventListener : public TestEventListener { public: - virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {} - virtual void OnTestIterationStart(const UnitTest& /*unit_test*/, - int /*iteration*/) {} - virtual void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) {} - virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {} - virtual void OnTestCaseStart(const TestCase& /*test_case*/) {} - virtual void OnTestStart(const TestInfo& /*test_info*/) {} - virtual void OnTestPartResult(const TestPartResult& /*test_part_result*/) {} - virtual void OnTestEnd(const TestInfo& /*test_info*/) {} - virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {} - virtual void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) {} - virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {} - virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/, - int /*iteration*/) {} - virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {} + void OnTestProgramStart(const UnitTest& /*unit_test*/) override {} + void OnTestIterationStart(const UnitTest& /*unit_test*/, + int /*iteration*/) override {} + void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) override {} + void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) override {} + void OnTestSuiteStart(const TestSuite& /*test_suite*/) override {} +// Legacy API is deprecated but still available +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ + void OnTestCaseStart(const TestCase& /*test_case*/) override {} +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ + + void OnTestStart(const TestInfo& /*test_info*/) override {} + void OnTestPartResult(const TestPartResult& /*test_part_result*/) override {} + void OnTestEnd(const TestInfo& /*test_info*/) override {} + void OnTestSuiteEnd(const TestSuite& /*test_suite*/) override {} +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ + void OnTestCaseEnd(const TestCase& /*test_case*/) override {} +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ + + void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) override {} + void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) override {} + void OnTestIterationEnd(const UnitTest& /*unit_test*/, + int /*iteration*/) override {} + void OnTestProgramEnd(const UnitTest& /*unit_test*/) override {} }; // TestEventListeners lets users add listeners to track events in Google Test. @@ -1097,7 +1203,7 @@ class GTEST_API_ TestEventListeners { } private: - friend class TestCase; + friend class TestSuite; friend class TestInfo; friend class internal::DefaultGlobalTestPartResultReporter; friend class internal::NoExecDeathTest; @@ -1138,7 +1244,7 @@ class GTEST_API_ TestEventListeners { GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventListeners); }; -// A UnitTest consists of a vector of TestCases. +// A UnitTest consists of a vector of TestSuites. // // This is a singleton class. The only instance of UnitTest is // created when UnitTest::GetInstance() is first called. This @@ -1167,10 +1273,14 @@ class GTEST_API_ UnitTest { // was executed. The UnitTest object owns the string. const char* original_working_dir() const; - // Returns the TestCase object for the test that's currently running, + // Returns the TestSuite object for the test that's currently running, // or NULL if no test is running. - const TestCase* current_test_case() const - GTEST_LOCK_EXCLUDED_(mutex_); + const TestSuite* current_test_suite() const GTEST_LOCK_EXCLUDED_(mutex_); + +// Legacy API is still available but deprecated +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ + const TestCase* current_test_case() const GTEST_LOCK_EXCLUDED_(mutex_); +#endif // Returns the TestInfo object for the test that's currently running, // or NULL if no test is running. @@ -1180,31 +1290,40 @@ class GTEST_API_ UnitTest { // Returns the random seed used at the start of the current test run. int random_seed() const; -#if GTEST_HAS_PARAM_TEST - // Returns the ParameterizedTestCaseRegistry object used to keep track of + // Returns the ParameterizedTestSuiteRegistry object used to keep track of // value-parameterized tests and instantiate and register them. // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. - internal::ParameterizedTestCaseRegistry& parameterized_test_registry() + internal::ParameterizedTestSuiteRegistry& parameterized_test_registry() GTEST_LOCK_EXCLUDED_(mutex_); -#endif // GTEST_HAS_PARAM_TEST - // Gets the number of successful test cases. - int successful_test_case_count() const; + // Gets the number of successful test suites. + int successful_test_suite_count() const; - // Gets the number of failed test cases. - int failed_test_case_count() const; + // Gets the number of failed test suites. + int failed_test_suite_count() const; - // Gets the number of all test cases. - int total_test_case_count() const; + // Gets the number of all test suites. + int total_test_suite_count() const; - // Gets the number of all test cases that contain at least one test + // Gets the number of all test suites that contain at least one test // that should run. + int test_suite_to_run_count() const; + + // Legacy API is deprecated but still available +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ + int successful_test_case_count() const; + int failed_test_case_count() const; + int total_test_case_count() const; int test_case_to_run_count() const; +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ // Gets the number of successful tests. int successful_test_count() const; + // Gets the number of skipped tests. + int skipped_test_count() const; + // Gets the number of failed tests. int failed_test_count() const; @@ -1230,19 +1349,25 @@ class GTEST_API_ UnitTest { // Gets the elapsed time, in milliseconds. TimeInMillis elapsed_time() const; - // Returns true iff the unit test passed (i.e. all test cases passed). + // Returns true if and only if the unit test passed (i.e. all test suites + // passed). bool Passed() const; - // Returns true iff the unit test failed (i.e. some test case failed - // or something outside of all tests failed). + // Returns true if and only if the unit test failed (i.e. some test suite + // failed or something outside of all tests failed). bool Failed() const; - // Gets the i-th test case among all the test cases. i can range from 0 to - // total_test_case_count() - 1. If i is not in that range, returns NULL. + // Gets the i-th test suite among all the test suites. i can range from 0 to + // total_test_suite_count() - 1. If i is not in that range, returns NULL. + const TestSuite* GetTestSuite(int i) const; + +// Legacy API is deprecated but still available +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ const TestCase* GetTestCase(int i) const; +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ // Returns the TestResult containing information on test failures and - // properties logged outside of individual test cases. + // properties logged outside of individual test suites. const TestResult& ad_hoc_test_result() const; // Returns the list of event listeners that can be used to track events @@ -1273,15 +1398,15 @@ class GTEST_API_ UnitTest { GTEST_LOCK_EXCLUDED_(mutex_); // Adds a TestProperty to the current TestResult object when invoked from - // inside a test, to current TestCase's ad_hoc_test_result_ when invoked - // from SetUpTestCase or TearDownTestCase, or to the global property set + // inside a test, to current TestSuite's ad_hoc_test_result_ when invoked + // from SetUpTestSuite or TearDownTestSuite, or to the global property set // when invoked elsewhere. If the result already contains a property with // the same key, the value will be updated. void RecordProperty(const std::string& key, const std::string& value); - // Gets the i-th test case among all the test cases. i can range from 0 to - // total_test_case_count() - 1. If i is not in that range, returns NULL. - TestCase* GetMutableTestCase(int i); + // Gets the i-th test suite among all the test suites. i can range from 0 to + // total_test_suite_count() - 1. If i is not in that range, returns NULL. + TestSuite* GetMutableTestSuite(int i); // Accessors for the implementation object. internal::UnitTestImpl* impl() { return impl_; } @@ -1289,9 +1414,9 @@ class GTEST_API_ UnitTest { // These classes and functions are friends as they need to access private // members of UnitTest. + friend class ScopedTrace; friend class Test; friend class internal::AssertHelper; - friend class internal::ScopedTrace; friend class internal::StreamingListenerTest; friend class internal::UnitTestRecordPropertyTestHelper; friend Environment* AddGlobalTestEnvironment(Environment* env); @@ -1366,6 +1491,10 @@ GTEST_API_ void InitGoogleTest(int* argc, char** argv); // UNICODE mode. GTEST_API_ void InitGoogleTest(int* argc, wchar_t** argv); +// This overloaded version can be used on Arduino/embedded platforms where +// there is no argc/argv. +GTEST_API_ void InitGoogleTest(); + namespace internal { // Separate the error generating code from the code path to reduce the stack @@ -1382,17 +1511,22 @@ AssertionResult CmpHelperEQFailure(const char* lhs_expression, false); } +// This block of code defines operator==/!= +// to block lexical scope lookup. +// It prevents using invalid operator==/!= defined at namespace scope. +struct faketype {}; +inline bool operator==(faketype, faketype) { return true; } +inline bool operator!=(faketype, faketype) { return false; } + // The helper function for {ASSERT|EXPECT}_EQ. template AssertionResult CmpHelperEQ(const char* lhs_expression, const char* rhs_expression, const T1& lhs, const T2& rhs) { -GTEST_DISABLE_MSC_WARNINGS_PUSH_(4389 /* signed/unsigned mismatch */) if (lhs == rhs) { return AssertionSuccess(); } -GTEST_DISABLE_MSC_WARNINGS_POP_() return CmpHelperEQFailure(lhs_expression, rhs_expression, lhs, rhs); } @@ -1405,18 +1539,17 @@ GTEST_API_ AssertionResult CmpHelperEQ(const char* lhs_expression, BiggestInt lhs, BiggestInt rhs); -// The helper class for {ASSERT|EXPECT}_EQ. The template argument -// lhs_is_null_literal is true iff the first argument to ASSERT_EQ() -// is a null pointer literal. The following default implementation is -// for lhs_is_null_literal being false. -template class EqHelper { public: // This templatized version is for the general case. - template + template < + typename T1, typename T2, + // Disable this overload for cases where one argument is a pointer + // and the other is the null pointer constant. + typename std::enable_if::value || + !std::is_pointer::value>::type* = nullptr> static AssertionResult Compare(const char* lhs_expression, - const char* rhs_expression, - const T1& lhs, + const char* rhs_expression, const T1& lhs, const T2& rhs) { return CmpHelperEQ(lhs_expression, rhs_expression, lhs, rhs); } @@ -1433,49 +1566,15 @@ class EqHelper { BiggestInt rhs) { return CmpHelperEQ(lhs_expression, rhs_expression, lhs, rhs); } -}; - -// This specialization is used when the first argument to ASSERT_EQ() -// is a null pointer literal, like NULL, false, or 0. -template <> -class EqHelper { - public: - // We define two overloaded versions of Compare(). The first - // version will be picked when the second argument to ASSERT_EQ() is - // NOT a pointer, e.g. ASSERT_EQ(0, AnIntFunction()) or - // EXPECT_EQ(false, a_bool). - template - static AssertionResult Compare( - const char* lhs_expression, - const char* rhs_expression, - const T1& lhs, - const T2& rhs, - // The following line prevents this overload from being considered if T2 - // is not a pointer type. We need this because ASSERT_EQ(NULL, my_ptr) - // expands to Compare("", "", NULL, my_ptr), which requires a conversion - // to match the Secret* in the other overload, which would otherwise make - // this template match better. - typename EnableIf::value>::type* = 0) { - return CmpHelperEQ(lhs_expression, rhs_expression, lhs, rhs); - } - // This version will be picked when the second argument to ASSERT_EQ() is a - // pointer, e.g. ASSERT_EQ(NULL, a_pointer). template static AssertionResult Compare( - const char* lhs_expression, - const char* rhs_expression, - // We used to have a second template parameter instead of Secret*. That - // template parameter would deduce to 'long', making this a better match - // than the first overload even without the first overload's EnableIf. - // Unfortunately, gcc with -Wconversion-null warns when "passing NULL to - // non-pointer argument" (even a deduced integral argument), so the old - // implementation caused warnings in user code. - Secret* /* lhs (NULL) */, - T* rhs) { + const char* lhs_expression, const char* rhs_expression, + // Handle cases where '0' is used as a null pointer literal. + std::nullptr_t /* lhs */, T* rhs) { // We already know that 'lhs' is a null pointer. - return CmpHelperEQ(lhs_expression, rhs_expression, - static_cast(NULL), rhs); + return CmpHelperEQ(lhs_expression, rhs_expression, static_cast(nullptr), + rhs); } }; @@ -1704,9 +1803,14 @@ class GTEST_API_ AssertHelper { GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelper); }; +enum GTestColor { COLOR_DEFAULT, COLOR_RED, COLOR_GREEN, COLOR_YELLOW }; + +GTEST_API_ GTEST_ATTRIBUTE_PRINTF_(2, 3) void ColoredPrintf(GTestColor color, + const char* fmt, + ...); + } // namespace internal -#if GTEST_HAS_PARAM_TEST // The pure interface class that all value-parameterized tests inherit from. // A value-parameterized class must inherit from both ::testing::Test and // ::testing::WithParamInterface. In most cases that just means inheriting @@ -1724,13 +1828,13 @@ class GTEST_API_ AssertHelper { // FooTest() { // // Can use GetParam() here. // } -// virtual ~FooTest() { +// ~FooTest() override { // // Can use GetParam() here. // } -// virtual void SetUp() { +// void SetUp() override { // // Can use GetParam() here. // } -// virtual void TearDown { +// void TearDown override { // // Can use GetParam() here. // } // }; @@ -1739,7 +1843,7 @@ class GTEST_API_ AssertHelper { // Foo foo; // ASSERT_TRUE(foo.DoesBar(GetParam())); // } -// INSTANTIATE_TEST_CASE_P(OneToTenRange, FooTest, ::testing::Range(1, 10)); +// INSTANTIATE_TEST_SUITE_P(OneToTenRange, FooTest, ::testing::Range(1, 10)); template class WithParamInterface { @@ -1748,12 +1852,9 @@ class WithParamInterface { virtual ~WithParamInterface() {} // The current parameter value. Is also available in the test fixture's - // constructor. This member function is non-static, even though it only - // references static data, to reduce the opportunity for incorrect uses - // like writing 'WithParamInterface::GetParam()' for a test that - // uses a fixture whose parameter type is int. - const ParamType& GetParam() const { - GTEST_CHECK_(parameter_ != NULL) + // constructor. + static const ParamType& GetParam() { + GTEST_CHECK_(parameter_ != nullptr) << "GetParam() can only be called inside a value-parameterized test " << "-- did you intend to write TEST_P instead of TEST_F?"; return *parameter_; @@ -1774,7 +1875,7 @@ class WithParamInterface { }; template -const T* WithParamInterface::parameter_ = NULL; +const T* WithParamInterface::parameter_ = nullptr; // Most value-parameterized classes can ignore the existence of // WithParamInterface, and can just inherit from ::testing::TestWithParam. @@ -1783,10 +1884,13 @@ template class TestWithParam : public Test, public WithParamInterface { }; -#endif // GTEST_HAS_PARAM_TEST - // Macros for indicating success/failure in test code. +// Skips test in runtime. +// Skipping test aborts current function. +// Skipped tests are neither successful nor failed. +#define GTEST_SKIP() GTEST_SKIP_("") + // ADD_FAILURE unconditionally adds a failure to the current test. // SUCCEED generates a success - it doesn't automatically make the // current test successful, as a test is only successful when it has @@ -1816,6 +1920,11 @@ class TestWithParam : public Test, public WithParamInterface { // Generates a fatal failure with a generic message. #define GTEST_FAIL() GTEST_FATAL_FAILURE_("Failed") +// Like GTEST_FAIL(), but at the given source file location. +#define GTEST_FAIL_AT(file, line) \ + GTEST_MESSAGE_AT_(file, line, "Failed", \ + ::testing::TestPartResult::kFatalFailure) + // Define this macro to 1 to omit the definition of FAIL(), which is a // generic name and clashes with some other libraries. #if !GTEST_DONT_DEFINE_FAIL @@ -1857,22 +1966,18 @@ class TestWithParam : public Test, public WithParamInterface { // AssertionResult. For more information on how to use AssertionResult with // these macros see comments on that class. #define EXPECT_TRUE(condition) \ - GTEST_TEST_BOOLEAN_((condition), #condition, false, true, \ + GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \ GTEST_NONFATAL_FAILURE_) #define EXPECT_FALSE(condition) \ GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \ GTEST_NONFATAL_FAILURE_) #define ASSERT_TRUE(condition) \ - GTEST_TEST_BOOLEAN_((condition), #condition, false, true, \ + GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \ GTEST_FATAL_FAILURE_) #define ASSERT_FALSE(condition) \ GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \ GTEST_FATAL_FAILURE_) -// Includes the auto-generated header that implements a family of -// generic predicate assertion macros. -#include "gtest/gtest_pred_impl.h" - // Macros for testing equalities and inequalities. // // * {ASSERT|EXPECT}_EQ(v1, v2): Tests that v1 == v2 @@ -1914,15 +2019,13 @@ class TestWithParam : public Test, public WithParamInterface { // // Examples: // -// EXPECT_NE(5, Foo()); -// EXPECT_EQ(NULL, a_pointer); +// EXPECT_NE(Foo(), 5); +// EXPECT_EQ(a_pointer, NULL); // ASSERT_LT(i, array_size); // ASSERT_GT(records.size(), 0) << "There is no record left."; #define EXPECT_EQ(val1, val2) \ - EXPECT_PRED_FORMAT2(::testing::internal:: \ - EqHelper::Compare, \ - val1, val2) + EXPECT_PRED_FORMAT2(::testing::internal::EqHelper::Compare, val1, val2) #define EXPECT_NE(val1, val2) \ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2) #define EXPECT_LE(val1, val2) \ @@ -1935,9 +2038,7 @@ class TestWithParam : public Test, public WithParamInterface { EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2) #define GTEST_ASSERT_EQ(val1, val2) \ - ASSERT_PRED_FORMAT2(::testing::internal:: \ - EqHelper::Compare, \ - val1, val2) + ASSERT_PRED_FORMAT2(::testing::internal::EqHelper::Compare, val1, val2) #define GTEST_ASSERT_NE(val1, val2) \ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2) #define GTEST_ASSERT_LE(val1, val2) \ @@ -2101,6 +2202,51 @@ GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2, #define EXPECT_NO_FATAL_FAILURE(statement) \ GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_NONFATAL_FAILURE_) +// Causes a trace (including the given source file path and line number, +// and the given message) to be included in every test failure message generated +// by code in the scope of the lifetime of an instance of this class. The effect +// is undone with the destruction of the instance. +// +// The message argument can be anything streamable to std::ostream. +// +// Example: +// testing::ScopedTrace trace("file.cc", 123, "message"); +// +class GTEST_API_ ScopedTrace { + public: + // The c'tor pushes the given source file location and message onto + // a trace stack maintained by Google Test. + + // Template version. Uses Message() to convert the values into strings. + // Slow, but flexible. + template + ScopedTrace(const char* file, int line, const T& message) { + PushTrace(file, line, (Message() << message).GetString()); + } + + // Optimize for some known types. + ScopedTrace(const char* file, int line, const char* message) { + PushTrace(file, line, message ? message : "(null)"); + } + + ScopedTrace(const char* file, int line, const std::string& message) { + PushTrace(file, line, message); + } + + // The d'tor pops the info pushed by the c'tor. + // + // Note that the d'tor is not virtual in order to be efficient. + // Don't inherit from ScopedTrace! + ~ScopedTrace(); + + private: + void PushTrace(const char* file, int line, std::string message); + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedTrace); +} GTEST_ATTRIBUTE_UNUSED_; // A ScopedTrace object does its job in its + // c'tor and d'tor. Therefore it doesn't + // need to be used otherwise. + // Causes a trace (including the source file path, the current line // number, and the given message) to be included in every test failure // message generated by code in the current scope. The effect is @@ -2112,13 +2258,17 @@ GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2, // of the dummy variable name, thus allowing multiple SCOPED_TRACE()s // to appear in the same block - as long as they are on different // lines. +// +// Assuming that each thread maintains its own stack of traces. +// Therefore, a SCOPED_TRACE() would (correctly) only affect the +// assertions in its own thread. #define SCOPED_TRACE(message) \ - ::testing::internal::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\ - __FILE__, __LINE__, ::testing::Message() << (message)) + ::testing::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\ + __FILE__, __LINE__, (message)) // Compile-time assertion for type equality. -// StaticAssertTypeEq() compiles iff type1 and type2 are -// the same type. The value it returns is not interesting. +// StaticAssertTypeEq() compiles if and only if type1 and type2 +// are the same type. The value it returns is not interesting. // // Instead of making StaticAssertTypeEq a class template, we make it a // function template that invokes a helper class template. This @@ -2147,18 +2297,18 @@ GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2, // // to cause a compiler error. template -bool StaticAssertTypeEq() { - (void)internal::StaticAssertTypeEqHelper(); +constexpr bool StaticAssertTypeEq() noexcept { + static_assert(std::is_same::value, "T1 and T2 are not the same type"); return true; } // Defines a test. // -// The first parameter is the name of the test case, and the second -// parameter is the name of the test within the test case. +// The first parameter is the name of the test suite, and the second +// parameter is the name of the test within the test suite. // -// The convention is to end the test case name with "Test". For -// example, a test case for the Foo class can be named FooTest. +// The convention is to end the test suite name with "Test". For +// example, a test suite for the Foo class can be named FooTest. // // Test code should appear between braces after an invocation of // this macro. Example: @@ -2177,28 +2327,28 @@ bool StaticAssertTypeEq() { // code. GetTestTypeId() is guaranteed to always return the same // value, as it always calls GetTypeId<>() from the Google Test // framework. -#define GTEST_TEST(test_case_name, test_name)\ - GTEST_TEST_(test_case_name, test_name, \ - ::testing::Test, ::testing::internal::GetTestTypeId()) +#define GTEST_TEST(test_suite_name, test_name) \ + GTEST_TEST_(test_suite_name, test_name, ::testing::Test, \ + ::testing::internal::GetTestTypeId()) // Define this macro to 1 to omit the definition of TEST(), which // is a generic name and clashes with some other libraries. #if !GTEST_DONT_DEFINE_TEST -# define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name) +#define TEST(test_suite_name, test_name) GTEST_TEST(test_suite_name, test_name) #endif // Defines a test that uses a test fixture. // // The first parameter is the name of the test fixture class, which -// also doubles as the test case name. The second parameter is the -// name of the test within the test case. +// also doubles as the test suite name. The second parameter is the +// name of the test within the test suite. // // A test fixture class must be declared earlier. The user should put // the test code between braces after using this macro. Example: // // class FooTest : public testing::Test { // protected: -// virtual void SetUp() { b_.AddElement(3); } +// void SetUp() override { b_.AddElement(3); } // // Foo a_; // Foo b_; @@ -2209,10 +2359,11 @@ bool StaticAssertTypeEq() { // } // // TEST_F(FooTest, ReturnsElementCountCorrectly) { -// EXPECT_EQ(0, a_.size()); -// EXPECT_EQ(1, b_.size()); +// EXPECT_EQ(a_.size(), 0); +// EXPECT_EQ(b_.size(), 1); // } - +// +// GOOGLETEST_CM0011 DO NOT DELETE #define TEST_F(test_fixture, test_name)\ GTEST_TEST_(test_fixture, test_name, test_fixture, \ ::testing::internal::GetTypeId()) @@ -2221,6 +2372,90 @@ bool StaticAssertTypeEq() { // Tries to determine an appropriate directory for the platform. GTEST_API_ std::string TempDir(); +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +// Dynamically registers a test with the framework. +// +// This is an advanced API only to be used when the `TEST` macros are +// insufficient. The macros should be preferred when possible, as they avoid +// most of the complexity of calling this function. +// +// The `factory` argument is a factory callable (move-constructible) object or +// function pointer that creates a new instance of the Test object. It +// handles ownership to the caller. The signature of the callable is +// `Fixture*()`, where `Fixture` is the test fixture class for the test. All +// tests registered with the same `test_suite_name` must return the same +// fixture type. This is checked at runtime. +// +// The framework will infer the fixture class from the factory and will call +// the `SetUpTestSuite` and `TearDownTestSuite` for it. +// +// Must be called before `RUN_ALL_TESTS()` is invoked, otherwise behavior is +// undefined. +// +// Use case example: +// +// class MyFixture : public ::testing::Test { +// public: +// // All of these optional, just like in regular macro usage. +// static void SetUpTestSuite() { ... } +// static void TearDownTestSuite() { ... } +// void SetUp() override { ... } +// void TearDown() override { ... } +// }; +// +// class MyTest : public MyFixture { +// public: +// explicit MyTest(int data) : data_(data) {} +// void TestBody() override { ... } +// +// private: +// int data_; +// }; +// +// void RegisterMyTests(const std::vector& values) { +// for (int v : values) { +// ::testing::RegisterTest( +// "MyFixture", ("Test" + std::to_string(v)).c_str(), nullptr, +// std::to_string(v).c_str(), +// __FILE__, __LINE__, +// // Important to use the fixture type as the return type here. +// [=]() -> MyFixture* { return new MyTest(v); }); +// } +// } +// ... +// int main(int argc, char** argv) { +// std::vector values_to_test = LoadValuesFromConfig(); +// RegisterMyTests(values_to_test); +// ... +// return RUN_ALL_TESTS(); +// } +// +template +TestInfo* RegisterTest(const char* test_suite_name, const char* test_name, + const char* type_param, const char* value_param, + const char* file, int line, Factory factory) { + using TestT = typename std::remove_pointer::type; + + class FactoryImpl : public internal::TestFactoryBase { + public: + explicit FactoryImpl(Factory f) : factory_(std::move(f)) {} + Test* CreateTest() override { return factory_(); } + + private: + Factory factory_; + }; + + return internal::MakeAndRegisterTestInfo( + test_suite_name, test_name, type_param, value_param, + internal::CodeLocation(file, line), internal::GetTypeId(), + internal::SuiteApiResolver::GetSetUpCaseOrSuite(file, line), + internal::SuiteApiResolver::GetTearDownCaseOrSuite(file, line), + new FactoryImpl{std::move(factory)}); +} + } // namespace testing // Use this function in main() to run all tests. It returns 0 if all @@ -2237,4 +2472,6 @@ inline int RUN_ALL_TESTS() { return ::testing::UnitTest::GetInstance()->Run(); } +GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 + #endif // GTEST_INCLUDE_GTEST_GTEST_H_ diff --git a/cpp/test/include/gtest/gtest_pred_impl.h b/cpp/test/include/gtest/gtest_pred_impl.h index 30ae712f50..d514255c73 100644 --- a/cpp/test/include/gtest/gtest_pred_impl.h +++ b/cpp/test/include/gtest/gtest_pred_impl.h @@ -27,18 +27,18 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// This file is AUTOMATICALLY GENERATED on 10/31/2011 by command +// This file is AUTOMATICALLY GENERATED on 01/02/2019 by command // 'gen_gtest_pred_impl.py 5'. DO NOT EDIT BY HAND! // // Implements a family of generic predicate assertion macros. +// GOOGLETEST_CM0001 DO NOT DELETE #ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ #define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ -// Makes sure this header is not included before gtest.h. -#ifndef GTEST_INCLUDE_GTEST_GTEST_H_ -# error Do not include gtest_pred_impl.h directly. Include gtest.h instead. -#endif // GTEST_INCLUDE_GTEST_GTEST_H_ +#include "gtest/gtest.h" + +namespace testing { // This header implements a family of generic predicate assertion // macros: @@ -90,9 +90,10 @@ AssertionResult AssertPred1Helper(const char* pred_text, const T1& v1) { if (pred(v1)) return AssertionSuccess(); - return AssertionFailure() << pred_text << "(" - << e1 << ") evaluates to false, where" - << "\n" << e1 << " evaluates to " << v1; + return AssertionFailure() + << pred_text << "(" << e1 << ") evaluates to false, where" + << "\n" + << e1 << " evaluates to " << ::testing::PrintToString(v1); } // Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1. @@ -134,11 +135,12 @@ AssertionResult AssertPred2Helper(const char* pred_text, const T2& v2) { if (pred(v1, v2)) return AssertionSuccess(); - return AssertionFailure() << pred_text << "(" - << e1 << ", " - << e2 << ") evaluates to false, where" - << "\n" << e1 << " evaluates to " << v1 - << "\n" << e2 << " evaluates to " << v2; + return AssertionFailure() + << pred_text << "(" << e1 << ", " << e2 + << ") evaluates to false, where" + << "\n" + << e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n" + << e2 << " evaluates to " << ::testing::PrintToString(v2); } // Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2. @@ -185,13 +187,13 @@ AssertionResult AssertPred3Helper(const char* pred_text, const T3& v3) { if (pred(v1, v2, v3)) return AssertionSuccess(); - return AssertionFailure() << pred_text << "(" - << e1 << ", " - << e2 << ", " - << e3 << ") evaluates to false, where" - << "\n" << e1 << " evaluates to " << v1 - << "\n" << e2 << " evaluates to " << v2 - << "\n" << e3 << " evaluates to " << v3; + return AssertionFailure() + << pred_text << "(" << e1 << ", " << e2 << ", " << e3 + << ") evaluates to false, where" + << "\n" + << e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n" + << e2 << " evaluates to " << ::testing::PrintToString(v2) << "\n" + << e3 << " evaluates to " << ::testing::PrintToString(v3); } // Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3. @@ -243,15 +245,14 @@ AssertionResult AssertPred4Helper(const char* pred_text, const T4& v4) { if (pred(v1, v2, v3, v4)) return AssertionSuccess(); - return AssertionFailure() << pred_text << "(" - << e1 << ", " - << e2 << ", " - << e3 << ", " - << e4 << ") evaluates to false, where" - << "\n" << e1 << " evaluates to " << v1 - << "\n" << e2 << " evaluates to " << v2 - << "\n" << e3 << " evaluates to " << v3 - << "\n" << e4 << " evaluates to " << v4; + return AssertionFailure() + << pred_text << "(" << e1 << ", " << e2 << ", " << e3 << ", " << e4 + << ") evaluates to false, where" + << "\n" + << e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n" + << e2 << " evaluates to " << ::testing::PrintToString(v2) << "\n" + << e3 << " evaluates to " << ::testing::PrintToString(v3) << "\n" + << e4 << " evaluates to " << ::testing::PrintToString(v4); } // Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4. @@ -308,17 +309,15 @@ AssertionResult AssertPred5Helper(const char* pred_text, const T5& v5) { if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess(); - return AssertionFailure() << pred_text << "(" - << e1 << ", " - << e2 << ", " - << e3 << ", " - << e4 << ", " - << e5 << ") evaluates to false, where" - << "\n" << e1 << " evaluates to " << v1 - << "\n" << e2 << " evaluates to " << v2 - << "\n" << e3 << " evaluates to " << v3 - << "\n" << e4 << " evaluates to " << v4 - << "\n" << e5 << " evaluates to " << v5; + return AssertionFailure() + << pred_text << "(" << e1 << ", " << e2 << ", " << e3 << ", " << e4 + << ", " << e5 << ") evaluates to false, where" + << "\n" + << e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n" + << e2 << " evaluates to " << ::testing::PrintToString(v2) << "\n" + << e3 << " evaluates to " << ::testing::PrintToString(v3) << "\n" + << e4 << " evaluates to " << ::testing::PrintToString(v4) << "\n" + << e5 << " evaluates to " << ::testing::PrintToString(v5); } // Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5. @@ -355,4 +354,6 @@ AssertionResult AssertPred5Helper(const char* pred_text, +} // namespace testing + #endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ diff --git a/cpp/test/include/gtest/gtest_prod.h b/cpp/test/include/gtest/gtest_prod.h index da80ddc6c7..e651671ebd 100644 --- a/cpp/test/include/gtest/gtest_prod.h +++ b/cpp/test/include/gtest/gtest_prod.h @@ -26,10 +26,10 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + // -// Author: wan@google.com (Zhanyong Wan) -// -// Google C++ Testing Framework definitions useful in production code. +// Google C++ Testing and Mocking Framework definitions useful in production code. +// GOOGLETEST_CM0003 DO NOT DELETE #ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_ #define GTEST_INCLUDE_GTEST_GTEST_PROD_H_ @@ -40,17 +40,20 @@ // // class MyClass { // private: -// void MyMethod(); -// FRIEND_TEST(MyClassTest, MyMethod); +// void PrivateMethod(); +// FRIEND_TEST(MyClassTest, PrivateMethodWorks); // }; // // class MyClassTest : public testing::Test { // // ... // }; // -// TEST_F(MyClassTest, MyMethod) { -// // Can call MyClass::MyMethod() here. +// TEST_F(MyClassTest, PrivateMethodWorks) { +// // Can call MyClass::PrivateMethod() here. // } +// +// Note: The test class must be in the same namespace as the class being tested. +// For example, putting MyClassTest in an anonymous namespace will not work. #define FRIEND_TEST(test_case_name, test_name)\ friend class test_case_name##_##test_name##_Test diff --git a/cpp/test/include/gtest/internal/custom/README.md b/cpp/test/include/gtest/internal/custom/README.md new file mode 100644 index 0000000000..ff391fb4e2 --- /dev/null +++ b/cpp/test/include/gtest/internal/custom/README.md @@ -0,0 +1,56 @@ +# Customization Points + +The custom directory is an injection point for custom user configurations. + +## Header `gtest.h` + +### The following macros can be defined: + +* `GTEST_OS_STACK_TRACE_GETTER_` - The name of an implementation of + `OsStackTraceGetterInterface`. +* `GTEST_CUSTOM_TEMPDIR_FUNCTION_` - An override for `testing::TempDir()`. See + `testing::TempDir` for semantics and signature. + +## Header `gtest-port.h` + +The following macros can be defined: + +### Flag related macros: + +* `GTEST_FLAG(flag_name)` +* `GTEST_USE_OWN_FLAGFILE_FLAG_` - Define to 0 when the system provides its + own flagfile flag parsing. +* `GTEST_DECLARE_bool_(name)` +* `GTEST_DECLARE_int32_(name)` +* `GTEST_DECLARE_string_(name)` +* `GTEST_DEFINE_bool_(name, default_val, doc)` +* `GTEST_DEFINE_int32_(name, default_val, doc)` +* `GTEST_DEFINE_string_(name, default_val, doc)` + +### Logging: + +* `GTEST_LOG_(severity)` +* `GTEST_CHECK_(condition)` +* Functions `LogToStderr()` and `FlushInfoLog()` have to be provided too. + +### Threading: + +* `GTEST_HAS_NOTIFICATION_` - Enabled if Notification is already provided. +* `GTEST_HAS_MUTEX_AND_THREAD_LOCAL_` - Enabled if `Mutex` and `ThreadLocal` + are already provided. Must also provide `GTEST_DECLARE_STATIC_MUTEX_(mutex)` + and `GTEST_DEFINE_STATIC_MUTEX_(mutex)` +* `GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks)` +* `GTEST_LOCK_EXCLUDED_(locks)` + +### Underlying library support features + +* `GTEST_HAS_CXXABI_H_` + +### Exporting API symbols: + +* `GTEST_API_` - Specifier for exported symbols. + +## Header `gtest-printers.h` + +* See documentation at `gtest/gtest-printers.h` for details on how to define a + custom printer. diff --git a/cpp/test/include/gtest/internal/custom/gtest-port.h b/cpp/test/include/gtest/internal/custom/gtest-port.h index c85f5d5847..cd85d956d2 100644 --- a/cpp/test/include/gtest/internal/custom/gtest-port.h +++ b/cpp/test/include/gtest/internal/custom/gtest-port.h @@ -27,42 +27,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // -// Injection point for custom user configurations. -// The following macros can be defined: -// -// Flag related macros: -// GTEST_FLAG(flag_name) -// GTEST_USE_OWN_FLAGFILE_FLAG_ - Define to 0 when the system provides its -// own flagfile flag parsing. -// GTEST_DECLARE_bool_(name) -// GTEST_DECLARE_int32_(name) -// GTEST_DECLARE_string_(name) -// GTEST_DEFINE_bool_(name, default_val, doc) -// GTEST_DEFINE_int32_(name, default_val, doc) -// GTEST_DEFINE_string_(name, default_val, doc) -// -// Test filtering: -// GTEST_TEST_FILTER_ENV_VAR_ - The name of an environment variable that -// will be used if --GTEST_FLAG(test_filter) -// is not provided. -// -// Logging: -// GTEST_LOG_(severity) -// GTEST_CHECK_(condition) -// Functions LogToStderr() and FlushInfoLog() have to be provided too. -// -// Threading: -// GTEST_HAS_NOTIFICATION_ - Enabled if Notification is already provided. -// GTEST_HAS_MUTEX_AND_THREAD_LOCAL_ - Enabled if Mutex and ThreadLocal are -// already provided. -// Must also provide GTEST_DECLARE_STATIC_MUTEX_(mutex) and -// GTEST_DEFINE_STATIC_MUTEX_(mutex) -// -// GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks) -// GTEST_LOCK_EXCLUDED_(locks) -// -// Exporting API symbols: -// GTEST_API_ - Specifier for exported symbols. +// Injection point for custom user configurations. See README for details // // ** Custom implementation starts here ** diff --git a/cpp/test/include/gtest/internal/custom/gtest-printers.h b/cpp/test/include/gtest/internal/custom/gtest-printers.h index 60c1ea050b..eb4467abca 100644 --- a/cpp/test/include/gtest/internal/custom/gtest-printers.h +++ b/cpp/test/include/gtest/internal/custom/gtest-printers.h @@ -31,8 +31,8 @@ // installation of gTest. // It will be included from gtest-printers.h and the overrides in this file // will be visible to everyone. -// See documentation at gtest/gtest-printers.h for details on how to define a -// custom printer. +// +// Injection point for custom user configurations. See README for details // // ** Custom implementation starts here ** diff --git a/cpp/test/include/gtest/internal/custom/gtest.h b/cpp/test/include/gtest/internal/custom/gtest.h index a7a1c0b7d9..4c8e07be23 100644 --- a/cpp/test/include/gtest/internal/custom/gtest.h +++ b/cpp/test/include/gtest/internal/custom/gtest.h @@ -27,16 +27,8 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // -// Injection point for custom user configurations. -// The following macros can be defined: +// Injection point for custom user configurations. See README for details // -// GTEST_OS_STACK_TRACE_GETTER_ - The name of an implementation of -// OsStackTraceGetterInterface. -// -// GTEST_CUSTOM_TEMPDIR_FUNCTION_ - An override for testing::TempDir(). -// See testing::TempDir for semantics and -// signature. -// // ** Custom implementation starts here ** #ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ diff --git a/cpp/test/include/gtest/internal/gtest-death-test-internal.h b/cpp/test/include/gtest/internal/gtest-death-test-internal.h index 2b3a78f5bf..68bd353061 100644 --- a/cpp/test/include/gtest/internal/gtest-death-test-internal.h +++ b/cpp/test/include/gtest/internal/gtest-death-test-internal.h @@ -27,19 +27,20 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // -// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) -// -// The Google C++ Testing Framework (Google Test) +// The Google C++ Testing and Mocking Framework (Google Test) // // This header file defines internal utilities needed for implementing // death tests. They are subject to change without notice. +// GOOGLETEST_CM0001 DO NOT DELETE #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ +#include "gtest/gtest-matchers.h" #include "gtest/internal/gtest-internal.h" #include +#include namespace testing { namespace internal { @@ -53,6 +54,9 @@ const char kInternalRunDeathTestFlag[] = "internal_run_death_test"; #if GTEST_HAS_DEATH_TEST +GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ +/* class A needs to have dll-interface to be used by clients of class B */) + // DeathTest is a class that hides much of the complexity of the // GTEST_DEATH_TEST_ macro. It is abstract; its static Create method // returns a concrete class that depends on the prevailing death test @@ -76,7 +80,7 @@ class GTEST_API_ DeathTest { // argument is set. If the death test should be skipped, the pointer // is set to NULL; otherwise, it is set to the address of a new concrete // DeathTest object that controls the execution of the current test. - static bool Create(const char* statement, const RE* regex, + static bool Create(const char* statement, Matcher matcher, const char* file, int line, DeathTest** test); DeathTest(); virtual ~DeathTest() { } @@ -136,25 +140,50 @@ class GTEST_API_ DeathTest { GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest); }; +GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 + // Factory interface for death tests. May be mocked out for testing. class DeathTestFactory { public: virtual ~DeathTestFactory() { } - virtual bool Create(const char* statement, const RE* regex, - const char* file, int line, DeathTest** test) = 0; + virtual bool Create(const char* statement, + Matcher matcher, const char* file, + int line, DeathTest** test) = 0; }; // A concrete DeathTestFactory implementation for normal use. class DefaultDeathTestFactory : public DeathTestFactory { public: - virtual bool Create(const char* statement, const RE* regex, - const char* file, int line, DeathTest** test); + bool Create(const char* statement, Matcher matcher, + const char* file, int line, DeathTest** test) override; }; // Returns true if exit_status describes a process that was terminated // by a signal, or exited normally with a nonzero exit code. GTEST_API_ bool ExitedUnsuccessfully(int exit_status); +// A string passed to EXPECT_DEATH (etc.) is caught by one of these overloads +// and interpreted as a regex (rather than an Eq matcher) for legacy +// compatibility. +inline Matcher MakeDeathTestMatcher( + ::testing::internal::RE regex) { + return ContainsRegex(regex.pattern()); +} +inline Matcher MakeDeathTestMatcher(const char* regex) { + return ContainsRegex(regex); +} +inline Matcher MakeDeathTestMatcher( + const ::std::string& regex) { + return ContainsRegex(regex); +} + +// If a Matcher is passed to EXPECT_DEATH (etc.), it's +// used directly. +inline Matcher MakeDeathTestMatcher( + Matcher matcher) { + return matcher; +} + // Traps C++ exceptions escaping statement and reports them as test // failures. Note that trapping SEH exceptions is not implemented here. # if GTEST_HAS_EXCEPTIONS @@ -182,50 +211,53 @@ GTEST_API_ bool ExitedUnsuccessfully(int exit_status); // This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*, // ASSERT_EXIT*, and EXPECT_EXIT*. -# define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \ - GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ - if (::testing::internal::AlwaysTrue()) { \ - const ::testing::internal::RE& gtest_regex = (regex); \ - ::testing::internal::DeathTest* gtest_dt; \ - if (!::testing::internal::DeathTest::Create(#statement, >est_regex, \ - __FILE__, __LINE__, >est_dt)) { \ - goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \ - } \ - if (gtest_dt != NULL) { \ - ::testing::internal::scoped_ptr< ::testing::internal::DeathTest> \ - gtest_dt_ptr(gtest_dt); \ - switch (gtest_dt->AssumeRole()) { \ - case ::testing::internal::DeathTest::OVERSEE_TEST: \ - if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \ - goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \ - } \ - break; \ - case ::testing::internal::DeathTest::EXECUTE_TEST: { \ - ::testing::internal::DeathTest::ReturnSentinel \ - gtest_sentinel(gtest_dt); \ - GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \ - gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \ - break; \ - } \ - default: \ - break; \ - } \ - } \ - } else \ - GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__): \ - fail(::testing::internal::DeathTest::LastMessage()) +#define GTEST_DEATH_TEST_(statement, predicate, regex_or_matcher, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + ::testing::internal::DeathTest* gtest_dt; \ + if (!::testing::internal::DeathTest::Create( \ + #statement, \ + ::testing::internal::MakeDeathTestMatcher(regex_or_matcher), \ + __FILE__, __LINE__, >est_dt)) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \ + } \ + if (gtest_dt != nullptr) { \ + std::unique_ptr< ::testing::internal::DeathTest> gtest_dt_ptr(gtest_dt); \ + switch (gtest_dt->AssumeRole()) { \ + case ::testing::internal::DeathTest::OVERSEE_TEST: \ + if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \ + } \ + break; \ + case ::testing::internal::DeathTest::EXECUTE_TEST: { \ + ::testing::internal::DeathTest::ReturnSentinel gtest_sentinel( \ + gtest_dt); \ + GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \ + gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \ + break; \ + } \ + default: \ + break; \ + } \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__) \ + : fail(::testing::internal::DeathTest::LastMessage()) // The symbol "fail" here expands to something into which a message // can be streamed. // This macro is for implementing ASSERT/EXPECT_DEBUG_DEATH when compiled in -// NDEBUG mode. In this case we need the statements to be executed, the regex is -// ignored, and the macro must accept a streamed message even though the message -// is never printed. -# define GTEST_EXECUTE_STATEMENT_(statement, regex) \ - GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ - if (::testing::internal::AlwaysTrue()) { \ - GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ - } else \ +// NDEBUG mode. In this case we need the statements to be executed and the macro +// must accept a streamed message even though the message is never printed. +// The regex object is not evaluated, but it is used to prevent "unused" +// warnings and to avoid an expression that doesn't compile in debug mode. +#define GTEST_EXECUTE_STATEMENT_(statement, regex_or_matcher) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } else if (!::testing::internal::AlwaysTrue()) { \ + ::testing::internal::MakeDeathTestMatcher(regex_or_matcher); \ + } else \ ::testing::Message() // A class representing the parsed contents of the @@ -264,53 +296,6 @@ class InternalRunDeathTestFlag { // the flag is specified; otherwise returns NULL. InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag(); -#else // GTEST_HAS_DEATH_TEST - -// This macro is used for implementing macros such as -// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where -// death tests are not supported. Those macros must compile on such systems -// iff EXPECT_DEATH and ASSERT_DEATH compile with the same parameters on -// systems that support death tests. This allows one to write such a macro -// on a system that does not support death tests and be sure that it will -// compile on a death-test supporting system. -// -// Parameters: -// statement - A statement that a macro such as EXPECT_DEATH would test -// for program termination. This macro has to make sure this -// statement is compiled but not executed, to ensure that -// EXPECT_DEATH_IF_SUPPORTED compiles with a certain -// parameter iff EXPECT_DEATH compiles with it. -// regex - A regex that a macro such as EXPECT_DEATH would use to test -// the output of statement. This parameter has to be -// compiled but not evaluated by this macro, to ensure that -// this macro only accepts expressions that a macro such as -// EXPECT_DEATH would accept. -// terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED -// and a return statement for ASSERT_DEATH_IF_SUPPORTED. -// This ensures that ASSERT_DEATH_IF_SUPPORTED will not -// compile inside functions where ASSERT_DEATH doesn't -// compile. -// -// The branch that has an always false condition is used to ensure that -// statement and regex are compiled (and thus syntactically correct) but -// never executed. The unreachable code macro protects the terminator -// statement from generating an 'unreachable code' warning in case -// statement unconditionally returns or throws. The Message constructor at -// the end allows the syntax of streaming additional messages into the -// macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH. -# define GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, terminator) \ - GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ - if (::testing::internal::AlwaysTrue()) { \ - GTEST_LOG_(WARNING) \ - << "Death tests are not supported on this platform.\n" \ - << "Statement '" #statement "' cannot be verified."; \ - } else if (::testing::internal::AlwaysFalse()) { \ - ::testing::internal::RE::PartialMatch(".*", (regex)); \ - GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ - terminator; \ - } else \ - ::testing::Message() - #endif // GTEST_HAS_DEATH_TEST } // namespace internal diff --git a/cpp/test/include/gtest/internal/gtest-filepath.h b/cpp/test/include/gtest/internal/gtest-filepath.h index 7a13b4b0de..c11b101516 100644 --- a/cpp/test/include/gtest/internal/gtest-filepath.h +++ b/cpp/test/include/gtest/internal/gtest-filepath.h @@ -27,21 +27,24 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // -// Author: keith.ray@gmail.com (Keith Ray) -// // Google Test filepath utilities // // This header file declares classes and functions used internally by // Google Test. They are subject to change without notice. // -// This file is #included in . +// This file is #included in gtest/internal/gtest-internal.h. // Do not include this header file separately! +// GOOGLETEST_CM0001 DO NOT DELETE + #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ #include "gtest/internal/gtest-string.h" +GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ +/* class A needs to have dll-interface to be used by clients of class B */) + namespace testing { namespace internal { @@ -107,7 +110,7 @@ class GTEST_API_ FilePath { const FilePath& base_name, const char* extension); - // Returns true iff the path is "". + // Returns true if and only if the path is "". bool IsEmpty() const { return pathname_.empty(); } // If input name has a trailing separator character, removes it and returns @@ -203,4 +206,6 @@ class GTEST_API_ FilePath { } // namespace internal } // namespace testing +GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 + #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ diff --git a/cpp/test/include/gtest/internal/gtest-internal.h b/cpp/test/include/gtest/internal/gtest-internal.h index 72d83f0b13..f9da4899e2 100644 --- a/cpp/test/include/gtest/internal/gtest-internal.h +++ b/cpp/test/include/gtest/internal/gtest-internal.h @@ -27,13 +27,13 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // -// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) -// -// The Google C++ Testing Framework (Google Test) +// The Google C++ Testing and Mocking Framework (Google Test) // // This header file declares functions and macros used internally by // Google Test. They are subject to change without notice. +// GOOGLETEST_CM0001 DO NOT DELETE + #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ @@ -58,11 +58,12 @@ #include #include #include +#include #include #include "gtest/gtest-message.h" -#include "gtest/internal/gtest-string.h" #include "gtest/internal/gtest-filepath.h" +#include "gtest/internal/gtest-string.h" #include "gtest/internal/gtest-type-util.h" // Due to C++ preprocessor weirdness, we need double indirection to @@ -76,7 +77,9 @@ #define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar) #define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar -class ProtocolMessage; +// Stringifies its argument. +#define GTEST_STRINGIFY_(name) #name + namespace proto2 { class Message; } namespace testing { @@ -88,7 +91,7 @@ class Message; // Represents a failure message. class Test; // Represents a test. class TestInfo; // Information about a test. class TestPartResult; // Result of a test part. -class UnitTest; // A collection of test cases. +class UnitTest; // A collection of test suites. template ::std::string PrintToString(const T& value); @@ -96,7 +99,6 @@ ::std::string PrintToString(const T& value); namespace internal { struct TraceInfo; // Information about a trace point. -class ScopedTrace; // Implements scoped trace. class TestInfoImpl; // Opaque implementation of TestInfo class UnitTestImpl; // Opaque implementation of UnitTest @@ -104,34 +106,22 @@ class UnitTestImpl; // Opaque implementation of UnitTest // stack trace. GTEST_API_ extern const char kStackTraceMarker[]; -// Two overloaded helpers for checking at compile time whether an -// expression is a null pointer literal (i.e. NULL or any 0-valued -// compile-time integral constant). Their return values have -// different sizes, so we can use sizeof() to test which version is -// picked by the compiler. These helpers have no implementations, as -// we only need their signatures. -// -// Given IsNullLiteralHelper(x), the compiler will pick the first -// version if x can be implicitly converted to Secret*, and pick the -// second version otherwise. Since Secret is a secret and incomplete -// type, the only expression a user can write that has type Secret* is -// a null pointer literal. Therefore, we know that x is a null -// pointer literal if and only if the first version is picked by the -// compiler. -char IsNullLiteralHelper(Secret* p); -char (&IsNullLiteralHelper(...))[2]; // NOLINT - -// A compile-time bool constant that is true if and only if x is a -// null pointer literal (i.e. NULL or any 0-valued compile-time -// integral constant). -#ifdef GTEST_ELLIPSIS_NEEDS_POD_ -// We lose support for NULL detection where the compiler doesn't like -// passing non-POD classes through ellipsis (...). -# define GTEST_IS_NULL_LITERAL_(x) false -#else -# define GTEST_IS_NULL_LITERAL_(x) \ - (sizeof(::testing::internal::IsNullLiteralHelper(x)) == 1) -#endif // GTEST_ELLIPSIS_NEEDS_POD_ +// An IgnoredValue object can be implicitly constructed from ANY value. +class IgnoredValue { + struct Sink {}; + public: + // This constructor template allows any value to be implicitly + // converted to IgnoredValue. The object has no data member and + // doesn't try to remember anything about the argument. We + // deliberately omit the 'explicit' keyword in order to allow the + // conversion to be implicit. + // Disable the conversion if T already has a magical conversion operator. + // Otherwise we get ambiguity. + template ::value, + int>::type = 0> + IgnoredValue(const T& /* ignored */) {} // NOLINT(runtime/explicit) +}; // Appends the user-supplied message to the Google-Test-generated message. GTEST_API_ std::string AppendUserMessage( @@ -139,6 +129,9 @@ GTEST_API_ std::string AppendUserMessage( #if GTEST_HAS_EXCEPTIONS +GTEST_DISABLE_MSC_WARNINGS_PUSH_(4275 \ +/* an exported class was derived from a class that was not exported */) + // This exception is thrown by (and only by) a failed Google Test // assertion when GTEST_FLAG(throw_on_failure) is true (if exceptions // are enabled). We derive it from std::runtime_error, which is for @@ -150,26 +143,9 @@ class GTEST_API_ GoogleTestFailureException : public ::std::runtime_error { explicit GoogleTestFailureException(const TestPartResult& failure); }; -#endif // GTEST_HAS_EXCEPTIONS - -// A helper class for creating scoped traces in user programs. -class GTEST_API_ ScopedTrace { - public: - // The c'tor pushes the given source file location and message onto - // a trace stack maintained by Google Test. - ScopedTrace(const char* file, int line, const Message& message); - - // The d'tor pops the info pushed by the c'tor. - // - // Note that the d'tor is not virtual in order to be efficient. - // Don't inherit from ScopedTrace! - ~ScopedTrace(); +GTEST_DISABLE_MSC_WARNINGS_POP_() // 4275 - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedTrace); -} GTEST_ATTRIBUTE_UNUSED_; // A ScopedTrace object does its job in its - // c'tor and d'tor. Therefore it doesn't - // need to be used otherwise. +#endif // GTEST_HAS_EXCEPTIONS namespace edit_distance { // Returns the optimal edits to go from 'left' to 'right'. @@ -213,7 +189,7 @@ GTEST_API_ std::string DiffStrings(const std::string& left, // expected_value: "5" // actual_value: "6" // -// The ignoring_case parameter is true iff the assertion is a +// The ignoring_case parameter is true if and only if the assertion is a // *_STRCASEEQ*. When it's true, the string " (ignoring case)" will // be inserted into the message. GTEST_API_ AssertionResult EqFailure(const char* expected_expression, @@ -342,15 +318,15 @@ class FloatingPoint { // Returns the sign bit of this number. Bits sign_bit() const { return kSignBitMask & u_.bits_; } - // Returns true iff this is NAN (not a number). + // Returns true if and only if this is NAN (not a number). bool is_nan() const { // It's a NAN if the exponent bits are all ones and the fraction // bits are not entirely zeros. return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0); } - // Returns true iff this number is at most kMaxUlps ULP's away from - // rhs. In particular, this function: + // Returns true if and only if this number is at most kMaxUlps ULP's away + // from rhs. In particular, this function: // // - returns false if either number is (or both are) NAN. // - treats really large numbers as almost equal to infinity. @@ -421,7 +397,7 @@ typedef FloatingPoint Float; typedef FloatingPoint Double; // In order to catch the mistake of putting tests that use different -// test fixture classes in the same test case, we need to assign +// test fixture classes in the same test suite, we need to assign // unique IDs to fixture classes and compare them. The TypeId type is // used to hold such IDs. The user should treat TypeId as an opaque // type: the only operation allowed on TypeId values is to compare @@ -481,7 +457,7 @@ class TestFactoryBase { template class TestFactoryImpl : public TestFactoryBase { public: - virtual Test* CreateTest() { return new TestClass; } + Test* CreateTest() override { return new TestClass; } }; #if GTEST_OS_WINDOWS @@ -497,9 +473,9 @@ GTEST_API_ AssertionResult IsHRESULTFailure(const char* expr, #endif // GTEST_OS_WINDOWS -// Types of SetUpTestCase() and TearDownTestCase() functions. -typedef void (*SetUpTestCaseFunc)(); -typedef void (*TearDownTestCaseFunc)(); +// Types of SetUpTestSuite() and TearDownTestSuite() functions. +using SetUpTestSuiteFunc = void (*)(); +using TearDownTestSuiteFunc = void (*)(); struct CodeLocation { CodeLocation(const std::string& a_file, int a_line) @@ -509,12 +485,64 @@ struct CodeLocation { int line; }; +// Helper to identify which setup function for TestCase / TestSuite to call. +// Only one function is allowed, either TestCase or TestSute but not both. + +// Utility functions to help SuiteApiResolver +using SetUpTearDownSuiteFuncType = void (*)(); + +inline SetUpTearDownSuiteFuncType GetNotDefaultOrNull( + SetUpTearDownSuiteFuncType a, SetUpTearDownSuiteFuncType def) { + return a == def ? nullptr : a; +} + +template +// Note that SuiteApiResolver inherits from T because +// SetUpTestSuite()/TearDownTestSuite() could be protected. Ths way +// SuiteApiResolver can access them. +struct SuiteApiResolver : T { + // testing::Test is only forward declared at this point. So we make it a + // dependend class for the compiler to be OK with it. + using Test = + typename std::conditional::type; + + static SetUpTearDownSuiteFuncType GetSetUpCaseOrSuite(const char* filename, + int line_num) { + SetUpTearDownSuiteFuncType test_case_fp = + GetNotDefaultOrNull(&T::SetUpTestCase, &Test::SetUpTestCase); + SetUpTearDownSuiteFuncType test_suite_fp = + GetNotDefaultOrNull(&T::SetUpTestSuite, &Test::SetUpTestSuite); + + GTEST_CHECK_(!test_case_fp || !test_suite_fp) + << "Test can not provide both SetUpTestSuite and SetUpTestCase, please " + "make sure there is only one present at " + << filename << ":" << line_num; + + return test_case_fp != nullptr ? test_case_fp : test_suite_fp; + } + + static SetUpTearDownSuiteFuncType GetTearDownCaseOrSuite(const char* filename, + int line_num) { + SetUpTearDownSuiteFuncType test_case_fp = + GetNotDefaultOrNull(&T::TearDownTestCase, &Test::TearDownTestCase); + SetUpTearDownSuiteFuncType test_suite_fp = + GetNotDefaultOrNull(&T::TearDownTestSuite, &Test::TearDownTestSuite); + + GTEST_CHECK_(!test_case_fp || !test_suite_fp) + << "Test can not provide both TearDownTestSuite and TearDownTestCase," + " please make sure there is only one present at" + << filename << ":" << line_num; + + return test_case_fp != nullptr ? test_case_fp : test_suite_fp; + } +}; + // Creates a new TestInfo object and registers it with Google Test; // returns the created object. // // Arguments: // -// test_case_name: name of the test case +// test_suite_name: name of the test suite // name: name of the test // type_param the name of the test's type parameter, or NULL if // this is not a typed or a type-parameterized test. @@ -522,21 +550,16 @@ struct CodeLocation { // or NULL if this is not a type-parameterized test. // code_location: code location where the test is defined // fixture_class_id: ID of the test fixture class -// set_up_tc: pointer to the function that sets up the test case -// tear_down_tc: pointer to the function that tears down the test case +// set_up_tc: pointer to the function that sets up the test suite +// tear_down_tc: pointer to the function that tears down the test suite // factory: pointer to the factory that creates a test object. // The newly created TestInfo instance will assume // ownership of the factory object. GTEST_API_ TestInfo* MakeAndRegisterTestInfo( - const char* test_case_name, - const char* name, - const char* type_param, - const char* value_param, - CodeLocation code_location, - TypeId fixture_class_id, - SetUpTestCaseFunc set_up_tc, - TearDownTestCaseFunc tear_down_tc, - TestFactoryBase* factory); + const char* test_suite_name, const char* name, const char* type_param, + const char* value_param, CodeLocation code_location, + TypeId fixture_class_id, SetUpTestSuiteFunc set_up_tc, + TearDownTestSuiteFunc tear_down_tc, TestFactoryBase* factory); // If *pstr starts with the given prefix, modifies *pstr to be right // past the prefix and returns true; otherwise leaves *pstr unchanged @@ -545,19 +568,23 @@ GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr); #if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P -// State of the definition of a type-parameterized test case. -class GTEST_API_ TypedTestCasePState { +GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ +/* class A needs to have dll-interface to be used by clients of class B */) + +// State of the definition of a type-parameterized test suite. +class GTEST_API_ TypedTestSuitePState { public: - TypedTestCasePState() : registered_(false) {} + TypedTestSuitePState() : registered_(false) {} // Adds the given test name to defined_test_names_ and return true - // if the test case hasn't been registered; otherwise aborts the + // if the test suite hasn't been registered; otherwise aborts the // program. bool AddTestName(const char* file, int line, const char* case_name, const char* test_name) { if (registered_) { - fprintf(stderr, "%s Test %s must be defined before " - "REGISTER_TYPED_TEST_CASE_P(%s, ...).\n", + fprintf(stderr, + "%s Test %s must be defined before " + "REGISTER_TYPED_TEST_SUITE_P(%s, ...).\n", FormatFileLocation(file, line).c_str(), test_name, case_name); fflush(stderr); posix::Abort(); @@ -590,12 +617,19 @@ class GTEST_API_ TypedTestCasePState { RegisteredTestsMap registered_tests_; }; +// Legacy API is deprecated but still available +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ +using TypedTestCasePState = TypedTestSuitePState; +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ + +GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 + // Skips to the first non-space char after the first comma in 'str'; // returns NULL if no comma is found in 'str'. inline const char* SkipComma(const char* str) { const char* comma = strchr(str, ','); - if (comma == NULL) { - return NULL; + if (comma == nullptr) { + return nullptr; } while (IsSpace(*(++comma))) {} return comma; @@ -605,7 +639,7 @@ inline const char* SkipComma(const char* str) { // the entire string if it contains no comma. inline std::string GetPrefixUntilComma(const char* str) { const char* comma = strchr(str, ','); - return comma == NULL ? str : std::string(str, comma); + return comma == nullptr ? str : std::string(str, comma); } // Splits a given string on a given delimiter, populating a given @@ -613,6 +647,37 @@ inline std::string GetPrefixUntilComma(const char* str) { void SplitString(const ::std::string& str, char delimiter, ::std::vector< ::std::string>* dest); +// The default argument to the template below for the case when the user does +// not provide a name generator. +struct DefaultNameGenerator { + template + static std::string GetName(int i) { + return StreamableToString(i); + } +}; + +template +struct NameGeneratorSelector { + typedef Provided type; +}; + +template +void GenerateNamesRecursively(internal::None, std::vector*, int) {} + +template +void GenerateNamesRecursively(Types, std::vector* result, int i) { + result->push_back(NameGenerator::template GetName(i)); + GenerateNamesRecursively(typename Types::Tail(), result, + i + 1); +} + +template +std::vector GenerateNames() { + std::vector result; + GenerateNamesRecursively(Types(), &result, 0); + return result; +} + // TypeParameterizedTest::Register() // registers a list of type-parameterized tests with Google Test. The // return value is insignificant - we just need to return something @@ -624,13 +689,13 @@ template class TypeParameterizedTest { public: // 'index' is the index of the test in the type list 'Types' - // specified in INSTANTIATE_TYPED_TEST_CASE_P(Prefix, TestCase, + // specified in INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, TestSuite, // Types). Valid values for 'index' are [0, N - 1] where N is the // length of Types. - static bool Register(const char* prefix, - CodeLocation code_location, - const char* case_name, const char* test_names, - int index) { + static bool Register(const char* prefix, const CodeLocation& code_location, + const char* case_name, const char* test_names, int index, + const std::vector& type_names = + GenerateNames()) { typedef typename Types::Head Type; typedef Fixture FixtureClass; typedef typename GTEST_BIND_(TestSel, Type) TestClass; @@ -638,44 +703,55 @@ class TypeParameterizedTest { // First, registers the first type-parameterized test in the type // list. MakeAndRegisterTestInfo( - (std::string(prefix) + (prefix[0] == '\0' ? "" : "/") + case_name + "/" - + StreamableToString(index)).c_str(), + (std::string(prefix) + (prefix[0] == '\0' ? "" : "/") + case_name + + "/" + type_names[static_cast(index)]) + .c_str(), StripTrailingSpaces(GetPrefixUntilComma(test_names)).c_str(), GetTypeName().c_str(), - NULL, // No value parameter. - code_location, - GetTypeId(), - TestClass::SetUpTestCase, - TestClass::TearDownTestCase, + nullptr, // No value parameter. + code_location, GetTypeId(), + SuiteApiResolver::GetSetUpCaseOrSuite( + code_location.file.c_str(), code_location.line), + SuiteApiResolver::GetTearDownCaseOrSuite( + code_location.file.c_str(), code_location.line), new TestFactoryImpl); // Next, recurses (at compile time) with the tail of the type list. - return TypeParameterizedTest - ::Register(prefix, code_location, case_name, test_names, index + 1); + return TypeParameterizedTest::Register(prefix, + code_location, + case_name, + test_names, + index + 1, + type_names); } }; // The base case for the compile time recursion. template -class TypeParameterizedTest { +class TypeParameterizedTest { public: - static bool Register(const char* /*prefix*/, CodeLocation, + static bool Register(const char* /*prefix*/, const CodeLocation&, const char* /*case_name*/, const char* /*test_names*/, - int /*index*/) { + int /*index*/, + const std::vector& = + std::vector() /*type_names*/) { return true; } }; -// TypeParameterizedTestCase::Register() +// TypeParameterizedTestSuite::Register() // registers *all combinations* of 'Tests' and 'Types' with Google // Test. The return value is insignificant - we just need to return // something such that we can call this function in a namespace scope. template -class TypeParameterizedTestCase { +class TypeParameterizedTestSuite { public: static bool Register(const char* prefix, CodeLocation code_location, - const TypedTestCasePState* state, - const char* case_name, const char* test_names) { + const TypedTestSuitePState* state, const char* case_name, + const char* test_names, + const std::vector& type_names = + GenerateNames()) { std::string test_name = StripTrailingSpaces( GetPrefixUntilComma(test_names)); if (!state->TestExists(test_name)) { @@ -692,22 +768,26 @@ class TypeParameterizedTestCase { // First, register the first test in 'Test' for each type in 'Types'. TypeParameterizedTest::Register( - prefix, test_location, case_name, test_names, 0); + prefix, test_location, case_name, test_names, 0, type_names); // Next, recurses (at compile time) with the tail of the test list. - return TypeParameterizedTestCase - ::Register(prefix, code_location, state, - case_name, SkipComma(test_names)); + return TypeParameterizedTestSuite::Register(prefix, code_location, + state, case_name, + SkipComma(test_names), + type_names); } }; // The base case for the compile time recursion. template -class TypeParameterizedTestCase { +class TypeParameterizedTestSuite { public: - static bool Register(const char* /*prefix*/, CodeLocation, - const TypedTestCasePState* /*state*/, - const char* /*case_name*/, const char* /*test_names*/) { + static bool Register(const char* /*prefix*/, const CodeLocation&, + const TypedTestSuitePState* /*state*/, + const char* /*case_name*/, const char* /*test_names*/, + const std::vector& = + std::vector() /*type_names*/) { return true; } }; @@ -745,6 +825,16 @@ struct GTEST_API_ ConstCharPtr { const char* value; }; +// Helper for declaring std::string within 'if' statement +// in pre C++17 build environment. +struct GTEST_API_ TrueWithString { + TrueWithString() = default; + explicit TrueWithString(const char* str) : value(str) {} + explicit TrueWithString(const std::string& str) : value(str) {} + explicit operator bool() const { return true; } + std::string value; +}; + // A simple Linear Congruential Generator for generating random // numbers with a uniform distribution. Unlike rand() and srand(), it // doesn't use global state (and therefore can't interfere with user @@ -767,145 +857,15 @@ class GTEST_API_ Random { GTEST_DISALLOW_COPY_AND_ASSIGN_(Random); }; -// Defining a variable of type CompileAssertTypesEqual will cause a -// compiler error iff T1 and T2 are different types. -template -struct CompileAssertTypesEqual; - -template -struct CompileAssertTypesEqual { -}; - -// Removes the reference from a type if it is a reference type, -// otherwise leaves it unchanged. This is the same as -// tr1::remove_reference, which is not widely available yet. -template -struct RemoveReference { typedef T type; }; // NOLINT -template -struct RemoveReference { typedef T type; }; // NOLINT - -// A handy wrapper around RemoveReference that works when the argument -// T depends on template parameters. -#define GTEST_REMOVE_REFERENCE_(T) \ - typename ::testing::internal::RemoveReference::type - -// Removes const from a type if it is a const type, otherwise leaves -// it unchanged. This is the same as tr1::remove_const, which is not -// widely available yet. -template -struct RemoveConst { typedef T type; }; // NOLINT -template -struct RemoveConst { typedef T type; }; // NOLINT - -// MSVC 8.0, Sun C++, and IBM XL C++ have a bug which causes the above -// definition to fail to remove the const in 'const int[3]' and 'const -// char[3][4]'. The following specialization works around the bug. -template -struct RemoveConst { - typedef typename RemoveConst::type type[N]; -}; - -#if defined(_MSC_VER) && _MSC_VER < 1400 -// This is the only specialization that allows VC++ 7.1 to remove const in -// 'const int[3] and 'const int[3][4]'. However, it causes trouble with GCC -// and thus needs to be conditionally compiled. -template -struct RemoveConst { - typedef typename RemoveConst::type type[N]; -}; -#endif - -// A handy wrapper around RemoveConst that works when the argument -// T depends on template parameters. -#define GTEST_REMOVE_CONST_(T) \ - typename ::testing::internal::RemoveConst::type - // Turns const U&, U&, const U, and U all into U. #define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \ - GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(T)) - -// Adds reference to a type if it is not a reference type, -// otherwise leaves it unchanged. This is the same as -// tr1::add_reference, which is not widely available yet. -template -struct AddReference { typedef T& type; }; // NOLINT -template -struct AddReference { typedef T& type; }; // NOLINT - -// A handy wrapper around AddReference that works when the argument T -// depends on template parameters. -#define GTEST_ADD_REFERENCE_(T) \ - typename ::testing::internal::AddReference::type - -// Adds a reference to const on top of T as necessary. For example, -// it transforms -// -// char ==> const char& -// const char ==> const char& -// char& ==> const char& -// const char& ==> const char& -// -// The argument T must depend on some template parameters. -#define GTEST_REFERENCE_TO_CONST_(T) \ - GTEST_ADD_REFERENCE_(const GTEST_REMOVE_REFERENCE_(T)) - -// ImplicitlyConvertible::value is a compile-time bool -// constant that's true iff type From can be implicitly converted to -// type To. -template -class ImplicitlyConvertible { - private: - // We need the following helper functions only for their types. - // They have no implementations. - - // MakeFrom() is an expression whose type is From. We cannot simply - // use From(), as the type From may not have a public default - // constructor. - static typename AddReference::type MakeFrom(); - - // These two functions are overloaded. Given an expression - // Helper(x), the compiler will pick the first version if x can be - // implicitly converted to type To; otherwise it will pick the - // second version. - // - // The first version returns a value of size 1, and the second - // version returns a value of size 2. Therefore, by checking the - // size of Helper(x), which can be done at compile time, we can tell - // which version of Helper() is used, and hence whether x can be - // implicitly converted to type To. - static char Helper(To); - static char (&Helper(...))[2]; // NOLINT - - // We have to put the 'public' section after the 'private' section, - // or MSVC refuses to compile the code. - public: -#if defined(__BORLANDC__) - // C++Builder cannot use member overload resolution during template - // instantiation. The simplest workaround is to use its C++0x type traits - // functions (C++Builder 2009 and above only). - static const bool value = __is_convertible(From, To); -#else - // MSVC warns about implicitly converting from double to int for - // possible loss of data, so we need to temporarily disable the - // warning. - GTEST_DISABLE_MSC_WARNINGS_PUSH_(4244) - static const bool value = - sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1; - GTEST_DISABLE_MSC_WARNINGS_POP_() -#endif // __BORLANDC__ -}; -template -const bool ImplicitlyConvertible::value; + typename std::remove_const::type>::type // IsAProtocolMessage::value is a compile-time bool constant that's -// true iff T is type ProtocolMessage, proto2::Message, or a subclass -// of those. +// true if and only if T is type proto2::Message or a subclass of it. template struct IsAProtocolMessage - : public bool_constant< - ImplicitlyConvertible::value || - ImplicitlyConvertible::value> { -}; + : public std::is_convertible {}; // When the compiler sees expression IsContainerTest(0), if C is an // STL-style container class, the first overload of IsContainerTest @@ -918,8 +878,11 @@ struct IsAProtocolMessage // a container class by checking the type of IsContainerTest(0). // The value of the expression is insignificant. // -// Note that we look for both C::iterator and C::const_iterator. The -// reason is that C++ injects the name of a class as a member of the +// In C++11 mode we check the existence of a const_iterator and that an +// iterator is properly implemented for the container. +// +// For pre-C++11 that we look for both C::iterator and C::const_iterator. +// The reason is that C++ injects the name of a class as a member of the // class itself (e.g. you can refer to class iterator as either // 'iterator' or 'iterator::iterator'). If we look for C::iterator // only, for example, we would mistakenly think that a class named @@ -929,10 +892,13 @@ struct IsAProtocolMessage // IsContainerTest(typename C::const_iterator*) and // IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++. typedef int IsContainer; -template -IsContainer IsContainerTest(int /* dummy */, - typename C::iterator* /* it */ = NULL, - typename C::const_iterator* /* const_it */ = NULL) { +template ().begin()), + class = decltype(::std::declval().end()), + class = decltype(++::std::declval()), + class = decltype(*::std::declval()), + class = typename C::const_iterator> +IsContainer IsContainerTest(int /* dummy */) { return 0; } @@ -940,12 +906,55 @@ typedef char IsNotContainer; template IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; } -// EnableIf::type is void when 'Cond' is true, and -// undefined when 'Cond' is false. To use SFINAE to make a function -// overload only apply when a particular expression is true, add -// "typename EnableIf::type* = 0" as the last parameter. -template struct EnableIf; -template<> struct EnableIf { typedef void type; }; // NOLINT +// Trait to detect whether a type T is a hash table. +// The heuristic used is that the type contains an inner type `hasher` and does +// not contain an inner type `reverse_iterator`. +// If the container is iterable in reverse, then order might actually matter. +template +struct IsHashTable { + private: + template + static char test(typename U::hasher*, typename U::reverse_iterator*); + template + static int test(typename U::hasher*, ...); + template + static char test(...); + + public: + static const bool value = sizeof(test(nullptr, nullptr)) == sizeof(int); +}; + +template +const bool IsHashTable::value; + +template (0)) == sizeof(IsContainer)> +struct IsRecursiveContainerImpl; + +template +struct IsRecursiveContainerImpl : public std::false_type {}; + +// Since the IsRecursiveContainerImpl depends on the IsContainerTest we need to +// obey the same inconsistencies as the IsContainerTest, namely check if +// something is a container is relying on only const_iterator in C++11 and +// is relying on both const_iterator and iterator otherwise +template +struct IsRecursiveContainerImpl { + using value_type = decltype(*std::declval()); + using type = + std::is_same::type>::type, + C>; +}; + +// IsRecursiveContainer is a unary compile-time predicate that +// evaluates whether C is a recursive container type. A recursive container +// type is a container type whose value_type is equal to the container type +// itself. An example for a recursive container type is +// boost::filesystem::path, whose iterator has a value_type that is equal to +// boost::filesystem::path. +template +struct IsRecursiveContainer : public IsRecursiveContainerImpl::type {}; // Utilities for native arrays. @@ -1069,10 +1078,9 @@ class NativeArray { } private: - enum { - kCheckTypeIsNotConstOrAReference = StaticAssertTypeEqHelper< - Element, GTEST_REMOVE_REFERENCE_AND_CONST_(Element)>::value, - }; + static_assert(!std::is_const::value, "Type must not be const"); + static_assert(!std::is_reference::value, + "Type must not be a reference"); // Initializes this object with a copy of the input. void InitCopy(const Element* array, size_t a_size) { @@ -1097,6 +1105,141 @@ class NativeArray { GTEST_DISALLOW_ASSIGN_(NativeArray); }; +// Backport of std::index_sequence. +template +struct IndexSequence { + using type = IndexSequence; +}; + +// Double the IndexSequence, and one if plus_one is true. +template +struct DoubleSequence; +template +struct DoubleSequence, sizeofT> { + using type = IndexSequence; +}; +template +struct DoubleSequence, sizeofT> { + using type = IndexSequence; +}; + +// Backport of std::make_index_sequence. +// It uses O(ln(N)) instantiation depth. +template +struct MakeIndexSequence + : DoubleSequence::type, + N / 2>::type {}; + +template <> +struct MakeIndexSequence<0> : IndexSequence<> {}; + +template +struct Ignore { + Ignore(...); // NOLINT +}; + +template +struct ElemFromListImpl; +template +struct ElemFromListImpl> { + // We make Ignore a template to solve a problem with MSVC. + // A non-template Ignore would work fine with `decltype(Ignore(I))...`, but + // MSVC doesn't understand how to deal with that pack expansion. + // Use `0 * I` to have a single instantiation of Ignore. + template + static R Apply(Ignore<0 * I>..., R (*)(), ...); +}; + +template +struct ElemFromList { + using type = + decltype(ElemFromListImpl::type>::Apply( + static_cast(nullptr)...)); +}; + +template +class FlatTuple; + +template +struct FlatTupleElemBase; + +template +struct FlatTupleElemBase, I> { + using value_type = typename ElemFromList::type; + FlatTupleElemBase() = default; + explicit FlatTupleElemBase(value_type t) : value(std::move(t)) {} + value_type value; +}; + +template +struct FlatTupleBase; + +template +struct FlatTupleBase, IndexSequence> + : FlatTupleElemBase, Idx>... { + using Indices = IndexSequence; + FlatTupleBase() = default; + explicit FlatTupleBase(T... t) + : FlatTupleElemBase, Idx>(std::move(t))... {} +}; + +// Analog to std::tuple but with different tradeoffs. +// This class minimizes the template instantiation depth, thus allowing more +// elements that std::tuple would. std::tuple has been seen to require an +// instantiation depth of more than 10x the number of elements in some +// implementations. +// FlatTuple and ElemFromList are not recursive and have a fixed depth +// regardless of T... +// MakeIndexSequence, on the other hand, it is recursive but with an +// instantiation depth of O(ln(N)). +template +class FlatTuple + : private FlatTupleBase, + typename MakeIndexSequence::type> { + using Indices = typename FlatTuple::FlatTupleBase::Indices; + + public: + FlatTuple() = default; + explicit FlatTuple(T... t) : FlatTuple::FlatTupleBase(std::move(t)...) {} + + template + const typename ElemFromList::type& Get() const { + return static_cast*>(this)->value; + } + + template + typename ElemFromList::type& Get() { + return static_cast*>(this)->value; + } +}; + +// Utility functions to be called with static_assert to induce deprecation +// warnings. +GTEST_INTERNAL_DEPRECATED( + "INSTANTIATE_TEST_CASE_P is deprecated, please use " + "INSTANTIATE_TEST_SUITE_P") +constexpr bool InstantiateTestCase_P_IsDeprecated() { return true; } + +GTEST_INTERNAL_DEPRECATED( + "TYPED_TEST_CASE_P is deprecated, please use " + "TYPED_TEST_SUITE_P") +constexpr bool TypedTestCase_P_IsDeprecated() { return true; } + +GTEST_INTERNAL_DEPRECATED( + "TYPED_TEST_CASE is deprecated, please use " + "TYPED_TEST_SUITE") +constexpr bool TypedTestCaseIsDeprecated() { return true; } + +GTEST_INTERNAL_DEPRECATED( + "REGISTER_TYPED_TEST_CASE_P is deprecated, please use " + "REGISTER_TYPED_TEST_SUITE_P") +constexpr bool RegisterTypedTestCase_P_IsDeprecated() { return true; } + +GTEST_INTERNAL_DEPRECATED( + "INSTANTIATE_TYPED_TEST_CASE_P is deprecated, please use " + "INSTANTIATE_TYPED_TEST_SUITE_P") +constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; } + } // namespace internal } // namespace testing @@ -1116,7 +1259,10 @@ class NativeArray { #define GTEST_SUCCESS_(message) \ GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess) -// Suppresses MSVC warnings 4072 (unreachable code) for the code following +#define GTEST_SKIP_(message) \ + return GTEST_MESSAGE_(message, ::testing::TestPartResult::kSkip) + +// Suppress MSVC warning 4072 (unreachable code) for the code following // statement if it returns or throws (or doesn't return or throw in some // situations). #define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \ @@ -1148,19 +1294,39 @@ class NativeArray { GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \ fail(gtest_msg.value) +#if GTEST_HAS_EXCEPTIONS + +#define GTEST_TEST_NO_THROW_CATCH_STD_EXCEPTION_() \ + catch (std::exception const& e) { \ + gtest_msg.value = ( \ + "it throws std::exception-derived exception with description: \"" \ + ); \ + gtest_msg.value += e.what(); \ + gtest_msg.value += "\"."; \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \ + } + +#else // GTEST_HAS_EXCEPTIONS + +#define GTEST_TEST_NO_THROW_CATCH_STD_EXCEPTION_() + +#endif // GTEST_HAS_EXCEPTIONS + #define GTEST_TEST_NO_THROW_(statement, fail) \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ - if (::testing::internal::AlwaysTrue()) { \ + if (::testing::internal::TrueWithString gtest_msg{}) { \ try { \ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ } \ + GTEST_TEST_NO_THROW_CATCH_STD_EXCEPTION_() \ catch (...) { \ + gtest_msg.value = "it throws."; \ goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \ } \ } else \ GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \ - fail("Expected: " #statement " doesn't throw an exception.\n" \ - " Actual: it throws.") + fail(("Expected: " #statement " doesn't throw an exception.\n" \ + " Actual: " + gtest_msg.value).c_str()) #define GTEST_TEST_ANY_THROW_(statement, fail) \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ @@ -1208,32 +1374,38 @@ class NativeArray { " Actual: it does.") // Expands to the name of the class that implements the given test. -#define GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \ - test_case_name##_##test_name##_Test +#define GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \ + test_suite_name##_##test_name##_Test // Helper macro for defining tests. -#define GTEST_TEST_(test_case_name, test_name, parent_class, parent_id)\ -class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\ - public:\ - GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\ - private:\ - virtual void TestBody();\ - static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;\ - GTEST_DISALLOW_COPY_AND_ASSIGN_(\ - GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\ -};\ -\ -::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\ - ::test_info_ =\ - ::testing::internal::MakeAndRegisterTestInfo(\ - #test_case_name, #test_name, NULL, NULL, \ - ::testing::internal::CodeLocation(__FILE__, __LINE__), \ - (parent_id), \ - parent_class::SetUpTestCase, \ - parent_class::TearDownTestCase, \ - new ::testing::internal::TestFactoryImpl<\ - GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>);\ -void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody() +#define GTEST_TEST_(test_suite_name, test_name, parent_class, parent_id) \ + static_assert(sizeof(GTEST_STRINGIFY_(test_suite_name)) > 1, \ + "test_suite_name must not be empty"); \ + static_assert(sizeof(GTEST_STRINGIFY_(test_name)) > 1, \ + "test_name must not be empty"); \ + class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \ + : public parent_class { \ + public: \ + GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() {} \ + \ + private: \ + void TestBody() override; \ + static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_; \ + GTEST_DISALLOW_COPY_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name, \ + test_name)); \ + }; \ + \ + ::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_suite_name, \ + test_name)::test_info_ = \ + ::testing::internal::MakeAndRegisterTestInfo( \ + #test_suite_name, #test_name, nullptr, nullptr, \ + ::testing::internal::CodeLocation(__FILE__, __LINE__), (parent_id), \ + ::testing::internal::SuiteApiResolver< \ + parent_class>::GetSetUpCaseOrSuite(__FILE__, __LINE__), \ + ::testing::internal::SuiteApiResolver< \ + parent_class>::GetTearDownCaseOrSuite(__FILE__, __LINE__), \ + new ::testing::internal::TestFactoryImpl); \ + void GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::TestBody() #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ - diff --git a/cpp/test/include/gtest/internal/gtest-linked_ptr.h b/cpp/test/include/gtest/internal/gtest-linked_ptr.h deleted file mode 100644 index 3602942217..0000000000 --- a/cpp/test/include/gtest/internal/gtest-linked_ptr.h +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright 2003 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Authors: Dan Egnor (egnor@google.com) -// -// A "smart" pointer type with reference tracking. Every pointer to a -// particular object is kept on a circular linked list. When the last pointer -// to an object is destroyed or reassigned, the object is deleted. -// -// Used properly, this deletes the object when the last reference goes away. -// There are several caveats: -// - Like all reference counting schemes, cycles lead to leaks. -// - Each smart pointer is actually two pointers (8 bytes instead of 4). -// - Every time a pointer is assigned, the entire list of pointers to that -// object is traversed. This class is therefore NOT SUITABLE when there -// will often be more than two or three pointers to a particular object. -// - References are only tracked as long as linked_ptr<> objects are copied. -// If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS -// will happen (double deletion). -// -// A good use of this class is storing object references in STL containers. -// You can safely put linked_ptr<> in a vector<>. -// Other uses may not be as good. -// -// Note: If you use an incomplete type with linked_ptr<>, the class -// *containing* linked_ptr<> must have a constructor and destructor (even -// if they do nothing!). -// -// Bill Gibbons suggested we use something like this. -// -// Thread Safety: -// Unlike other linked_ptr implementations, in this implementation -// a linked_ptr object is thread-safe in the sense that: -// - it's safe to copy linked_ptr objects concurrently, -// - it's safe to copy *from* a linked_ptr and read its underlying -// raw pointer (e.g. via get()) concurrently, and -// - it's safe to write to two linked_ptrs that point to the same -// shared object concurrently. -// TODO(wan@google.com): rename this to safe_linked_ptr to avoid -// confusion with normal linked_ptr. - -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ - -#include -#include - -#include "gtest/internal/gtest-port.h" - -namespace testing { -namespace internal { - -// Protects copying of all linked_ptr objects. -GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex); - -// This is used internally by all instances of linked_ptr<>. It needs to be -// a non-template class because different types of linked_ptr<> can refer to -// the same object (linked_ptr(obj) vs linked_ptr(obj)). -// So, it needs to be possible for different types of linked_ptr to participate -// in the same circular linked list, so we need a single class type here. -// -// DO NOT USE THIS CLASS DIRECTLY YOURSELF. Use linked_ptr. -class linked_ptr_internal { - public: - // Create a new circle that includes only this instance. - void join_new() { - next_ = this; - } - - // Many linked_ptr operations may change p.link_ for some linked_ptr - // variable p in the same circle as this object. Therefore we need - // to prevent two such operations from occurring concurrently. - // - // Note that different types of linked_ptr objects can coexist in a - // circle (e.g. linked_ptr, linked_ptr, and - // linked_ptr). Therefore we must use a single mutex to - // protect all linked_ptr objects. This can create serious - // contention in production code, but is acceptable in a testing - // framework. - - // Join an existing circle. - void join(linked_ptr_internal const* ptr) - GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) { - MutexLock lock(&g_linked_ptr_mutex); - - linked_ptr_internal const* p = ptr; - while (p->next_ != ptr) { - assert(p->next_ != this && - "Trying to join() a linked ring we are already in. " - "Is GMock thread safety enabled?"); - p = p->next_; - } - p->next_ = this; - next_ = ptr; - } - - // Leave whatever circle we're part of. Returns true if we were the - // last member of the circle. Once this is done, you can join() another. - bool depart() - GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) { - MutexLock lock(&g_linked_ptr_mutex); - - if (next_ == this) return true; - linked_ptr_internal const* p = next_; - while (p->next_ != this) { - assert(p->next_ != next_ && - "Trying to depart() a linked ring we are not in. " - "Is GMock thread safety enabled?"); - p = p->next_; - } - p->next_ = next_; - return false; - } - - private: - mutable linked_ptr_internal const* next_; -}; - -template -class linked_ptr { - public: - typedef T element_type; - - // Take over ownership of a raw pointer. This should happen as soon as - // possible after the object is created. - explicit linked_ptr(T* ptr = NULL) { capture(ptr); } - ~linked_ptr() { depart(); } - - // Copy an existing linked_ptr<>, adding ourselves to the list of references. - template linked_ptr(linked_ptr const& ptr) { copy(&ptr); } - linked_ptr(linked_ptr const& ptr) { // NOLINT - assert(&ptr != this); - copy(&ptr); - } - - // Assignment releases the old value and acquires the new. - template linked_ptr& operator=(linked_ptr const& ptr) { - depart(); - copy(&ptr); - return *this; - } - - linked_ptr& operator=(linked_ptr const& ptr) { - if (&ptr != this) { - depart(); - copy(&ptr); - } - return *this; - } - - // Smart pointer members. - void reset(T* ptr = NULL) { - depart(); - capture(ptr); - } - T* get() const { return value_; } - T* operator->() const { return value_; } - T& operator*() const { return *value_; } - - bool operator==(T* p) const { return value_ == p; } - bool operator!=(T* p) const { return value_ != p; } - template - bool operator==(linked_ptr const& ptr) const { - return value_ == ptr.get(); - } - template - bool operator!=(linked_ptr const& ptr) const { - return value_ != ptr.get(); - } - - private: - template - friend class linked_ptr; - - T* value_; - linked_ptr_internal link_; - - void depart() { - if (link_.depart()) delete value_; - } - - void capture(T* ptr) { - value_ = ptr; - link_.join_new(); - } - - template void copy(linked_ptr const* ptr) { - value_ = ptr->get(); - if (value_) - link_.join(&ptr->link_); - else - link_.join_new(); - } -}; - -template inline -bool operator==(T* ptr, const linked_ptr& x) { - return ptr == x.get(); -} - -template inline -bool operator!=(T* ptr, const linked_ptr& x) { - return ptr != x.get(); -} - -// A function to convert T* into linked_ptr -// Doing e.g. make_linked_ptr(new FooBarBaz(arg)) is a shorter notation -// for linked_ptr >(new FooBarBaz(arg)) -template -linked_ptr make_linked_ptr(T* ptr) { - return linked_ptr(ptr); -} - -} // namespace internal -} // namespace testing - -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ diff --git a/cpp/test/include/gtest/internal/gtest-param-util-generated.h b/cpp/test/include/gtest/internal/gtest-param-util-generated.h deleted file mode 100644 index 4d1d81d20f..0000000000 --- a/cpp/test/include/gtest/internal/gtest-param-util-generated.h +++ /dev/null @@ -1,5146 +0,0 @@ -// This file was GENERATED by command: -// pump.py gtest-param-util-generated.h.pump -// DO NOT EDIT BY HAND!!! - -// Copyright 2008 Google Inc. -// All Rights Reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Author: vladl@google.com (Vlad Losev) - -// Type and function utilities for implementing parameterized tests. -// This file is generated by a SCRIPT. DO NOT EDIT BY HAND! -// -// Currently Google Test supports at most 50 arguments in Values, -// and at most 10 arguments in Combine. Please contact -// googletestframework@googlegroups.com if you need more. -// Please note that the number of arguments to Combine is limited -// by the maximum arity of the implementation of tuple which is -// currently set at 10. - -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ - -// scripts/fuse_gtest.py depends on gtest's own header being #included -// *unconditionally*. Therefore these #includes cannot be moved -// inside #if GTEST_HAS_PARAM_TEST. -#include "gtest/internal/gtest-param-util.h" -#include "gtest/internal/gtest-port.h" - -#if GTEST_HAS_PARAM_TEST - -namespace testing { - -// Forward declarations of ValuesIn(), which is implemented in -// include/gtest/gtest-param-test.h. -template -internal::ParamGenerator< - typename ::testing::internal::IteratorTraits::value_type> -ValuesIn(ForwardIterator begin, ForwardIterator end); - -template -internal::ParamGenerator ValuesIn(const T (&array)[N]); - -template -internal::ParamGenerator ValuesIn( - const Container& container); - -namespace internal { - -// Used in the Values() function to provide polymorphic capabilities. -template -class ValueArray1 { - public: - explicit ValueArray1(T1 v1) : v1_(v1) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray1& other); - - const T1 v1_; -}; - -template -class ValueArray2 { - public: - ValueArray2(T1 v1, T2 v2) : v1_(v1), v2_(v2) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray2& other); - - const T1 v1_; - const T2 v2_; -}; - -template -class ValueArray3 { - public: - ValueArray3(T1 v1, T2 v2, T3 v3) : v1_(v1), v2_(v2), v3_(v3) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray3& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; -}; - -template -class ValueArray4 { - public: - ValueArray4(T1 v1, T2 v2, T3 v3, T4 v4) : v1_(v1), v2_(v2), v3_(v3), - v4_(v4) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray4& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; -}; - -template -class ValueArray5 { - public: - ValueArray5(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5) : v1_(v1), v2_(v2), v3_(v3), - v4_(v4), v5_(v5) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray5& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; -}; - -template -class ValueArray6 { - public: - ValueArray6(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6) : v1_(v1), v2_(v2), - v3_(v3), v4_(v4), v5_(v5), v6_(v6) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray6& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; -}; - -template -class ValueArray7 { - public: - ValueArray7(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7) : v1_(v1), - v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray7& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; -}; - -template -class ValueArray8 { - public: - ValueArray8(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, - T8 v8) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), - v8_(v8) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray8& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; -}; - -template -class ValueArray9 { - public: - ValueArray9(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, - T9 v9) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), - v8_(v8), v9_(v9) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray9& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; -}; - -template -class ValueArray10 { - public: - ValueArray10(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), - v8_(v8), v9_(v9), v10_(v10) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray10& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; -}; - -template -class ValueArray11 { - public: - ValueArray11(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), - v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray11& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; -}; - -template -class ValueArray12 { - public: - ValueArray12(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), - v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray12& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; -}; - -template -class ValueArray13 { - public: - ValueArray13(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), - v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), - v12_(v12), v13_(v13) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray13& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; -}; - -template -class ValueArray14 { - public: - ValueArray14(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) : v1_(v1), v2_(v2), v3_(v3), - v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), - v11_(v11), v12_(v12), v13_(v13), v14_(v14) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray14& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; -}; - -template -class ValueArray15 { - public: - ValueArray15(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) : v1_(v1), v2_(v2), - v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), - v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray15& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; -}; - -template -class ValueArray16 { - public: - ValueArray16(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16) : v1_(v1), - v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), - v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), - v16_(v16) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray16& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; -}; - -template -class ValueArray17 { - public: - ValueArray17(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, - T17 v17) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), - v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), - v15_(v15), v16_(v16), v17_(v17) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray17& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; -}; - -template -class ValueArray18 { - public: - ValueArray18(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), - v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), - v15_(v15), v16_(v16), v17_(v17), v18_(v18) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray18& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; -}; - -template -class ValueArray19 { - public: - ValueArray19(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), - v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), - v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray19& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; -}; - -template -class ValueArray20 { - public: - ValueArray20(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), - v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), - v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), - v19_(v19), v20_(v20) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray20& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; -}; - -template -class ValueArray21 { - public: - ValueArray21(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), - v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), - v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), - v18_(v18), v19_(v19), v20_(v20), v21_(v21) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray21& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; -}; - -template -class ValueArray22 { - public: - ValueArray22(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22) : v1_(v1), v2_(v2), v3_(v3), - v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), - v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), - v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray22& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; -}; - -template -class ValueArray23 { - public: - ValueArray23(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23) : v1_(v1), v2_(v2), - v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), - v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), - v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), - v23_(v23) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray23& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; -}; - -template -class ValueArray24 { - public: - ValueArray24(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24) : v1_(v1), - v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), - v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), - v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), - v22_(v22), v23_(v23), v24_(v24) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray24& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; -}; - -template -class ValueArray25 { - public: - ValueArray25(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, - T25 v25) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), - v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), - v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), - v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray25& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; -}; - -template -class ValueArray26 { - public: - ValueArray26(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), - v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), - v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), - v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray26& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; -}; - -template -class ValueArray27 { - public: - ValueArray27(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), - v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), - v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), - v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), - v26_(v26), v27_(v27) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray27& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; -}; - -template -class ValueArray28 { - public: - ValueArray28(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), - v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), - v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), - v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), - v25_(v25), v26_(v26), v27_(v27), v28_(v28) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray28& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; -}; - -template -class ValueArray29 { - public: - ValueArray29(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), - v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), - v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), - v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), - v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray29& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; -}; - -template -class ValueArray30 { - public: - ValueArray30(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) : v1_(v1), v2_(v2), v3_(v3), - v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), - v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), - v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), - v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), - v29_(v29), v30_(v30) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray30& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; -}; - -template -class ValueArray31 { - public: - ValueArray31(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) : v1_(v1), v2_(v2), - v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), - v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), - v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), - v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), - v29_(v29), v30_(v30), v31_(v31) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray31& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; -}; - -template -class ValueArray32 { - public: - ValueArray32(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32) : v1_(v1), - v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), - v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), - v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), - v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), - v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray32& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; -}; - -template -class ValueArray33 { - public: - ValueArray33(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, - T33 v33) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), - v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), - v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), - v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), - v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), - v33_(v33) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray33& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; -}; - -template -class ValueArray34 { - public: - ValueArray34(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), - v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), - v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), - v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), - v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), - v33_(v33), v34_(v34) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray34& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; -}; - -template -class ValueArray35 { - public: - ValueArray35(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), - v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), - v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), - v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), - v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), - v32_(v32), v33_(v33), v34_(v34), v35_(v35) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray35& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; -}; - -template -class ValueArray36 { - public: - ValueArray36(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), - v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), - v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), - v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), - v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), - v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray36& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; -}; - -template -class ValueArray37 { - public: - ValueArray37(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), - v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), - v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), - v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), - v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), - v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), - v36_(v36), v37_(v37) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_), static_cast(v37_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray37& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; - const T37 v37_; -}; - -template -class ValueArray38 { - public: - ValueArray38(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38) : v1_(v1), v2_(v2), v3_(v3), - v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), - v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), - v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), - v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), - v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), - v35_(v35), v36_(v36), v37_(v37), v38_(v38) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_), static_cast(v37_), static_cast(v38_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray38& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; - const T37 v37_; - const T38 v38_; -}; - -template -class ValueArray39 { - public: - ValueArray39(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39) : v1_(v1), v2_(v2), - v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), - v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), - v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), - v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), - v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), - v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_), static_cast(v37_), static_cast(v38_), - static_cast(v39_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray39& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; - const T37 v37_; - const T38 v38_; - const T39 v39_; -}; - -template -class ValueArray40 { - public: - ValueArray40(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) : v1_(v1), - v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), - v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), - v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), - v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), - v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), - v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), - v40_(v40) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_), static_cast(v37_), static_cast(v38_), - static_cast(v39_), static_cast(v40_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray40& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; - const T37 v37_; - const T38 v38_; - const T39 v39_; - const T40 v40_; -}; - -template -class ValueArray41 { - public: - ValueArray41(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, - T41 v41) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), - v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), - v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), - v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), - v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), - v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), - v39_(v39), v40_(v40), v41_(v41) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_), static_cast(v37_), static_cast(v38_), - static_cast(v39_), static_cast(v40_), static_cast(v41_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray41& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; - const T37 v37_; - const T38 v38_; - const T39 v39_; - const T40 v40_; - const T41 v41_; -}; - -template -class ValueArray42 { - public: - ValueArray42(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, - T42 v42) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), - v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), - v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), - v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), - v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), - v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), - v39_(v39), v40_(v40), v41_(v41), v42_(v42) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_), static_cast(v37_), static_cast(v38_), - static_cast(v39_), static_cast(v40_), static_cast(v41_), - static_cast(v42_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray42& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; - const T37 v37_; - const T38 v38_; - const T39 v39_; - const T40 v40_; - const T41 v41_; - const T42 v42_; -}; - -template -class ValueArray43 { - public: - ValueArray43(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, - T42 v42, T43 v43) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), - v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), - v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), - v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), - v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), - v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), - v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_), static_cast(v37_), static_cast(v38_), - static_cast(v39_), static_cast(v40_), static_cast(v41_), - static_cast(v42_), static_cast(v43_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray43& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; - const T37 v37_; - const T38 v38_; - const T39 v39_; - const T40 v40_; - const T41 v41_; - const T42 v42_; - const T43 v43_; -}; - -template -class ValueArray44 { - public: - ValueArray44(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, - T42 v42, T43 v43, T44 v44) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), - v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), - v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), - v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), - v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), - v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), - v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), - v43_(v43), v44_(v44) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_), static_cast(v37_), static_cast(v38_), - static_cast(v39_), static_cast(v40_), static_cast(v41_), - static_cast(v42_), static_cast(v43_), static_cast(v44_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray44& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; - const T37 v37_; - const T38 v38_; - const T39 v39_; - const T40 v40_; - const T41 v41_; - const T42 v42_; - const T43 v43_; - const T44 v44_; -}; - -template -class ValueArray45 { - public: - ValueArray45(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, - T42 v42, T43 v43, T44 v44, T45 v45) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), - v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), - v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), - v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), - v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), - v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), - v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), - v42_(v42), v43_(v43), v44_(v44), v45_(v45) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_), static_cast(v37_), static_cast(v38_), - static_cast(v39_), static_cast(v40_), static_cast(v41_), - static_cast(v42_), static_cast(v43_), static_cast(v44_), - static_cast(v45_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray45& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; - const T37 v37_; - const T38 v38_; - const T39 v39_; - const T40 v40_; - const T41 v41_; - const T42 v42_; - const T43 v43_; - const T44 v44_; - const T45 v45_; -}; - -template -class ValueArray46 { - public: - ValueArray46(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, - T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) : v1_(v1), v2_(v2), v3_(v3), - v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), - v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), - v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), - v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), - v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), - v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), - v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_), static_cast(v37_), static_cast(v38_), - static_cast(v39_), static_cast(v40_), static_cast(v41_), - static_cast(v42_), static_cast(v43_), static_cast(v44_), - static_cast(v45_), static_cast(v46_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray46& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; - const T37 v37_; - const T38 v38_; - const T39 v39_; - const T40 v40_; - const T41 v41_; - const T42 v42_; - const T43 v43_; - const T44 v44_; - const T45 v45_; - const T46 v46_; -}; - -template -class ValueArray47 { - public: - ValueArray47(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, - T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) : v1_(v1), v2_(v2), - v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), - v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), - v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), - v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), - v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), - v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), - v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46), - v47_(v47) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_), static_cast(v37_), static_cast(v38_), - static_cast(v39_), static_cast(v40_), static_cast(v41_), - static_cast(v42_), static_cast(v43_), static_cast(v44_), - static_cast(v45_), static_cast(v46_), static_cast(v47_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray47& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; - const T37 v37_; - const T38 v38_; - const T39 v39_; - const T40 v40_; - const T41 v41_; - const T42 v42_; - const T43 v43_; - const T44 v44_; - const T45 v45_; - const T46 v46_; - const T47 v47_; -}; - -template -class ValueArray48 { - public: - ValueArray48(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, - T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48) : v1_(v1), - v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), - v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), - v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), - v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), - v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), - v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), - v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), - v46_(v46), v47_(v47), v48_(v48) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_), static_cast(v37_), static_cast(v38_), - static_cast(v39_), static_cast(v40_), static_cast(v41_), - static_cast(v42_), static_cast(v43_), static_cast(v44_), - static_cast(v45_), static_cast(v46_), static_cast(v47_), - static_cast(v48_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray48& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; - const T37 v37_; - const T38 v38_; - const T39 v39_; - const T40 v40_; - const T41 v41_; - const T42 v42_; - const T43 v43_; - const T44 v44_; - const T45 v45_; - const T46 v46_; - const T47 v47_; - const T48 v48_; -}; - -template -class ValueArray49 { - public: - ValueArray49(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, - T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, - T49 v49) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), - v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), - v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), - v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), - v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), - v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), - v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), - v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_), static_cast(v37_), static_cast(v38_), - static_cast(v39_), static_cast(v40_), static_cast(v41_), - static_cast(v42_), static_cast(v43_), static_cast(v44_), - static_cast(v45_), static_cast(v46_), static_cast(v47_), - static_cast(v48_), static_cast(v49_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray49& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; - const T37 v37_; - const T38 v38_; - const T39 v39_; - const T40 v40_; - const T41 v41_; - const T42 v42_; - const T43 v43_; - const T44 v44_; - const T45 v45_; - const T46 v46_; - const T47 v47_; - const T48 v48_; - const T49 v49_; -}; - -template -class ValueArray50 { - public: - ValueArray50(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, - T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, - T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, - T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, - T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, - T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, T49 v49, - T50 v50) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), - v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), - v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), - v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), - v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), - v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), - v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), - v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49), v50_(v50) {} - - template - operator ParamGenerator() const { - const T array[] = {static_cast(v1_), static_cast(v2_), - static_cast(v3_), static_cast(v4_), static_cast(v5_), - static_cast(v6_), static_cast(v7_), static_cast(v8_), - static_cast(v9_), static_cast(v10_), static_cast(v11_), - static_cast(v12_), static_cast(v13_), static_cast(v14_), - static_cast(v15_), static_cast(v16_), static_cast(v17_), - static_cast(v18_), static_cast(v19_), static_cast(v20_), - static_cast(v21_), static_cast(v22_), static_cast(v23_), - static_cast(v24_), static_cast(v25_), static_cast(v26_), - static_cast(v27_), static_cast(v28_), static_cast(v29_), - static_cast(v30_), static_cast(v31_), static_cast(v32_), - static_cast(v33_), static_cast(v34_), static_cast(v35_), - static_cast(v36_), static_cast(v37_), static_cast(v38_), - static_cast(v39_), static_cast(v40_), static_cast(v41_), - static_cast(v42_), static_cast(v43_), static_cast(v44_), - static_cast(v45_), static_cast(v46_), static_cast(v47_), - static_cast(v48_), static_cast(v49_), static_cast(v50_)}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray50& other); - - const T1 v1_; - const T2 v2_; - const T3 v3_; - const T4 v4_; - const T5 v5_; - const T6 v6_; - const T7 v7_; - const T8 v8_; - const T9 v9_; - const T10 v10_; - const T11 v11_; - const T12 v12_; - const T13 v13_; - const T14 v14_; - const T15 v15_; - const T16 v16_; - const T17 v17_; - const T18 v18_; - const T19 v19_; - const T20 v20_; - const T21 v21_; - const T22 v22_; - const T23 v23_; - const T24 v24_; - const T25 v25_; - const T26 v26_; - const T27 v27_; - const T28 v28_; - const T29 v29_; - const T30 v30_; - const T31 v31_; - const T32 v32_; - const T33 v33_; - const T34 v34_; - const T35 v35_; - const T36 v36_; - const T37 v37_; - const T38 v38_; - const T39 v39_; - const T40 v40_; - const T41 v41_; - const T42 v42_; - const T43 v43_; - const T44 v44_; - const T45 v45_; - const T46 v46_; - const T47 v47_; - const T48 v48_; - const T49 v49_; - const T50 v50_; -}; - -# if GTEST_HAS_COMBINE -// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. -// -// Generates values from the Cartesian product of values produced -// by the argument generators. -// -template -class CartesianProductGenerator2 - : public ParamGeneratorInterface< ::testing::tuple > { - public: - typedef ::testing::tuple ParamType; - - CartesianProductGenerator2(const ParamGenerator& g1, - const ParamGenerator& g2) - : g1_(g1), g2_(g2) {} - virtual ~CartesianProductGenerator2() {} - - virtual ParamIteratorInterface* Begin() const { - return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin()); - } - virtual ParamIteratorInterface* End() const { - return new Iterator(this, g1_, g1_.end(), g2_, g2_.end()); - } - - private: - class Iterator : public ParamIteratorInterface { - public: - Iterator(const ParamGeneratorInterface* base, - const ParamGenerator& g1, - const typename ParamGenerator::iterator& current1, - const ParamGenerator& g2, - const typename ParamGenerator::iterator& current2) - : base_(base), - begin1_(g1.begin()), end1_(g1.end()), current1_(current1), - begin2_(g2.begin()), end2_(g2.end()), current2_(current2) { - ComputeCurrentValue(); - } - virtual ~Iterator() {} - - virtual const ParamGeneratorInterface* BaseGenerator() const { - return base_; - } - // Advance should not be called on beyond-of-range iterators - // so no component iterators must be beyond end of range, either. - virtual void Advance() { - assert(!AtEnd()); - ++current2_; - if (current2_ == end2_) { - current2_ = begin2_; - ++current1_; - } - ComputeCurrentValue(); - } - virtual ParamIteratorInterface* Clone() const { - return new Iterator(*this); - } - virtual const ParamType* Current() const { return ¤t_value_; } - virtual bool Equals(const ParamIteratorInterface& other) const { - // Having the same base generator guarantees that the other - // iterator is of the same type and we can downcast. - GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) - << "The program attempted to compare iterators " - << "from different generators." << std::endl; - const Iterator* typed_other = - CheckedDowncastToActualType(&other); - // We must report iterators equal if they both point beyond their - // respective ranges. That can happen in a variety of fashions, - // so we have to consult AtEnd(). - return (AtEnd() && typed_other->AtEnd()) || - ( - current1_ == typed_other->current1_ && - current2_ == typed_other->current2_); - } - - private: - Iterator(const Iterator& other) - : base_(other.base_), - begin1_(other.begin1_), - end1_(other.end1_), - current1_(other.current1_), - begin2_(other.begin2_), - end2_(other.end2_), - current2_(other.current2_) { - ComputeCurrentValue(); - } - - void ComputeCurrentValue() { - if (!AtEnd()) - current_value_ = ParamType(*current1_, *current2_); - } - bool AtEnd() const { - // We must report iterator past the end of the range when either of the - // component iterators has reached the end of its range. - return - current1_ == end1_ || - current2_ == end2_; - } - - // No implementation - assignment is unsupported. - void operator=(const Iterator& other); - - const ParamGeneratorInterface* const base_; - // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. - // current[i]_ is the actual traversing iterator. - const typename ParamGenerator::iterator begin1_; - const typename ParamGenerator::iterator end1_; - typename ParamGenerator::iterator current1_; - const typename ParamGenerator::iterator begin2_; - const typename ParamGenerator::iterator end2_; - typename ParamGenerator::iterator current2_; - ParamType current_value_; - }; // class CartesianProductGenerator2::Iterator - - // No implementation - assignment is unsupported. - void operator=(const CartesianProductGenerator2& other); - - const ParamGenerator g1_; - const ParamGenerator g2_; -}; // class CartesianProductGenerator2 - - -template -class CartesianProductGenerator3 - : public ParamGeneratorInterface< ::testing::tuple > { - public: - typedef ::testing::tuple ParamType; - - CartesianProductGenerator3(const ParamGenerator& g1, - const ParamGenerator& g2, const ParamGenerator& g3) - : g1_(g1), g2_(g2), g3_(g3) {} - virtual ~CartesianProductGenerator3() {} - - virtual ParamIteratorInterface* Begin() const { - return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, - g3_.begin()); - } - virtual ParamIteratorInterface* End() const { - return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end()); - } - - private: - class Iterator : public ParamIteratorInterface { - public: - Iterator(const ParamGeneratorInterface* base, - const ParamGenerator& g1, - const typename ParamGenerator::iterator& current1, - const ParamGenerator& g2, - const typename ParamGenerator::iterator& current2, - const ParamGenerator& g3, - const typename ParamGenerator::iterator& current3) - : base_(base), - begin1_(g1.begin()), end1_(g1.end()), current1_(current1), - begin2_(g2.begin()), end2_(g2.end()), current2_(current2), - begin3_(g3.begin()), end3_(g3.end()), current3_(current3) { - ComputeCurrentValue(); - } - virtual ~Iterator() {} - - virtual const ParamGeneratorInterface* BaseGenerator() const { - return base_; - } - // Advance should not be called on beyond-of-range iterators - // so no component iterators must be beyond end of range, either. - virtual void Advance() { - assert(!AtEnd()); - ++current3_; - if (current3_ == end3_) { - current3_ = begin3_; - ++current2_; - } - if (current2_ == end2_) { - current2_ = begin2_; - ++current1_; - } - ComputeCurrentValue(); - } - virtual ParamIteratorInterface* Clone() const { - return new Iterator(*this); - } - virtual const ParamType* Current() const { return ¤t_value_; } - virtual bool Equals(const ParamIteratorInterface& other) const { - // Having the same base generator guarantees that the other - // iterator is of the same type and we can downcast. - GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) - << "The program attempted to compare iterators " - << "from different generators." << std::endl; - const Iterator* typed_other = - CheckedDowncastToActualType(&other); - // We must report iterators equal if they both point beyond their - // respective ranges. That can happen in a variety of fashions, - // so we have to consult AtEnd(). - return (AtEnd() && typed_other->AtEnd()) || - ( - current1_ == typed_other->current1_ && - current2_ == typed_other->current2_ && - current3_ == typed_other->current3_); - } - - private: - Iterator(const Iterator& other) - : base_(other.base_), - begin1_(other.begin1_), - end1_(other.end1_), - current1_(other.current1_), - begin2_(other.begin2_), - end2_(other.end2_), - current2_(other.current2_), - begin3_(other.begin3_), - end3_(other.end3_), - current3_(other.current3_) { - ComputeCurrentValue(); - } - - void ComputeCurrentValue() { - if (!AtEnd()) - current_value_ = ParamType(*current1_, *current2_, *current3_); - } - bool AtEnd() const { - // We must report iterator past the end of the range when either of the - // component iterators has reached the end of its range. - return - current1_ == end1_ || - current2_ == end2_ || - current3_ == end3_; - } - - // No implementation - assignment is unsupported. - void operator=(const Iterator& other); - - const ParamGeneratorInterface* const base_; - // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. - // current[i]_ is the actual traversing iterator. - const typename ParamGenerator::iterator begin1_; - const typename ParamGenerator::iterator end1_; - typename ParamGenerator::iterator current1_; - const typename ParamGenerator::iterator begin2_; - const typename ParamGenerator::iterator end2_; - typename ParamGenerator::iterator current2_; - const typename ParamGenerator::iterator begin3_; - const typename ParamGenerator::iterator end3_; - typename ParamGenerator::iterator current3_; - ParamType current_value_; - }; // class CartesianProductGenerator3::Iterator - - // No implementation - assignment is unsupported. - void operator=(const CartesianProductGenerator3& other); - - const ParamGenerator g1_; - const ParamGenerator g2_; - const ParamGenerator g3_; -}; // class CartesianProductGenerator3 - - -template -class CartesianProductGenerator4 - : public ParamGeneratorInterface< ::testing::tuple > { - public: - typedef ::testing::tuple ParamType; - - CartesianProductGenerator4(const ParamGenerator& g1, - const ParamGenerator& g2, const ParamGenerator& g3, - const ParamGenerator& g4) - : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {} - virtual ~CartesianProductGenerator4() {} - - virtual ParamIteratorInterface* Begin() const { - return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, - g3_.begin(), g4_, g4_.begin()); - } - virtual ParamIteratorInterface* End() const { - return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), - g4_, g4_.end()); - } - - private: - class Iterator : public ParamIteratorInterface { - public: - Iterator(const ParamGeneratorInterface* base, - const ParamGenerator& g1, - const typename ParamGenerator::iterator& current1, - const ParamGenerator& g2, - const typename ParamGenerator::iterator& current2, - const ParamGenerator& g3, - const typename ParamGenerator::iterator& current3, - const ParamGenerator& g4, - const typename ParamGenerator::iterator& current4) - : base_(base), - begin1_(g1.begin()), end1_(g1.end()), current1_(current1), - begin2_(g2.begin()), end2_(g2.end()), current2_(current2), - begin3_(g3.begin()), end3_(g3.end()), current3_(current3), - begin4_(g4.begin()), end4_(g4.end()), current4_(current4) { - ComputeCurrentValue(); - } - virtual ~Iterator() {} - - virtual const ParamGeneratorInterface* BaseGenerator() const { - return base_; - } - // Advance should not be called on beyond-of-range iterators - // so no component iterators must be beyond end of range, either. - virtual void Advance() { - assert(!AtEnd()); - ++current4_; - if (current4_ == end4_) { - current4_ = begin4_; - ++current3_; - } - if (current3_ == end3_) { - current3_ = begin3_; - ++current2_; - } - if (current2_ == end2_) { - current2_ = begin2_; - ++current1_; - } - ComputeCurrentValue(); - } - virtual ParamIteratorInterface* Clone() const { - return new Iterator(*this); - } - virtual const ParamType* Current() const { return ¤t_value_; } - virtual bool Equals(const ParamIteratorInterface& other) const { - // Having the same base generator guarantees that the other - // iterator is of the same type and we can downcast. - GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) - << "The program attempted to compare iterators " - << "from different generators." << std::endl; - const Iterator* typed_other = - CheckedDowncastToActualType(&other); - // We must report iterators equal if they both point beyond their - // respective ranges. That can happen in a variety of fashions, - // so we have to consult AtEnd(). - return (AtEnd() && typed_other->AtEnd()) || - ( - current1_ == typed_other->current1_ && - current2_ == typed_other->current2_ && - current3_ == typed_other->current3_ && - current4_ == typed_other->current4_); - } - - private: - Iterator(const Iterator& other) - : base_(other.base_), - begin1_(other.begin1_), - end1_(other.end1_), - current1_(other.current1_), - begin2_(other.begin2_), - end2_(other.end2_), - current2_(other.current2_), - begin3_(other.begin3_), - end3_(other.end3_), - current3_(other.current3_), - begin4_(other.begin4_), - end4_(other.end4_), - current4_(other.current4_) { - ComputeCurrentValue(); - } - - void ComputeCurrentValue() { - if (!AtEnd()) - current_value_ = ParamType(*current1_, *current2_, *current3_, - *current4_); - } - bool AtEnd() const { - // We must report iterator past the end of the range when either of the - // component iterators has reached the end of its range. - return - current1_ == end1_ || - current2_ == end2_ || - current3_ == end3_ || - current4_ == end4_; - } - - // No implementation - assignment is unsupported. - void operator=(const Iterator& other); - - const ParamGeneratorInterface* const base_; - // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. - // current[i]_ is the actual traversing iterator. - const typename ParamGenerator::iterator begin1_; - const typename ParamGenerator::iterator end1_; - typename ParamGenerator::iterator current1_; - const typename ParamGenerator::iterator begin2_; - const typename ParamGenerator::iterator end2_; - typename ParamGenerator::iterator current2_; - const typename ParamGenerator::iterator begin3_; - const typename ParamGenerator::iterator end3_; - typename ParamGenerator::iterator current3_; - const typename ParamGenerator::iterator begin4_; - const typename ParamGenerator::iterator end4_; - typename ParamGenerator::iterator current4_; - ParamType current_value_; - }; // class CartesianProductGenerator4::Iterator - - // No implementation - assignment is unsupported. - void operator=(const CartesianProductGenerator4& other); - - const ParamGenerator g1_; - const ParamGenerator g2_; - const ParamGenerator g3_; - const ParamGenerator g4_; -}; // class CartesianProductGenerator4 - - -template -class CartesianProductGenerator5 - : public ParamGeneratorInterface< ::testing::tuple > { - public: - typedef ::testing::tuple ParamType; - - CartesianProductGenerator5(const ParamGenerator& g1, - const ParamGenerator& g2, const ParamGenerator& g3, - const ParamGenerator& g4, const ParamGenerator& g5) - : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {} - virtual ~CartesianProductGenerator5() {} - - virtual ParamIteratorInterface* Begin() const { - return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, - g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin()); - } - virtual ParamIteratorInterface* End() const { - return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), - g4_, g4_.end(), g5_, g5_.end()); - } - - private: - class Iterator : public ParamIteratorInterface { - public: - Iterator(const ParamGeneratorInterface* base, - const ParamGenerator& g1, - const typename ParamGenerator::iterator& current1, - const ParamGenerator& g2, - const typename ParamGenerator::iterator& current2, - const ParamGenerator& g3, - const typename ParamGenerator::iterator& current3, - const ParamGenerator& g4, - const typename ParamGenerator::iterator& current4, - const ParamGenerator& g5, - const typename ParamGenerator::iterator& current5) - : base_(base), - begin1_(g1.begin()), end1_(g1.end()), current1_(current1), - begin2_(g2.begin()), end2_(g2.end()), current2_(current2), - begin3_(g3.begin()), end3_(g3.end()), current3_(current3), - begin4_(g4.begin()), end4_(g4.end()), current4_(current4), - begin5_(g5.begin()), end5_(g5.end()), current5_(current5) { - ComputeCurrentValue(); - } - virtual ~Iterator() {} - - virtual const ParamGeneratorInterface* BaseGenerator() const { - return base_; - } - // Advance should not be called on beyond-of-range iterators - // so no component iterators must be beyond end of range, either. - virtual void Advance() { - assert(!AtEnd()); - ++current5_; - if (current5_ == end5_) { - current5_ = begin5_; - ++current4_; - } - if (current4_ == end4_) { - current4_ = begin4_; - ++current3_; - } - if (current3_ == end3_) { - current3_ = begin3_; - ++current2_; - } - if (current2_ == end2_) { - current2_ = begin2_; - ++current1_; - } - ComputeCurrentValue(); - } - virtual ParamIteratorInterface* Clone() const { - return new Iterator(*this); - } - virtual const ParamType* Current() const { return ¤t_value_; } - virtual bool Equals(const ParamIteratorInterface& other) const { - // Having the same base generator guarantees that the other - // iterator is of the same type and we can downcast. - GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) - << "The program attempted to compare iterators " - << "from different generators." << std::endl; - const Iterator* typed_other = - CheckedDowncastToActualType(&other); - // We must report iterators equal if they both point beyond their - // respective ranges. That can happen in a variety of fashions, - // so we have to consult AtEnd(). - return (AtEnd() && typed_other->AtEnd()) || - ( - current1_ == typed_other->current1_ && - current2_ == typed_other->current2_ && - current3_ == typed_other->current3_ && - current4_ == typed_other->current4_ && - current5_ == typed_other->current5_); - } - - private: - Iterator(const Iterator& other) - : base_(other.base_), - begin1_(other.begin1_), - end1_(other.end1_), - current1_(other.current1_), - begin2_(other.begin2_), - end2_(other.end2_), - current2_(other.current2_), - begin3_(other.begin3_), - end3_(other.end3_), - current3_(other.current3_), - begin4_(other.begin4_), - end4_(other.end4_), - current4_(other.current4_), - begin5_(other.begin5_), - end5_(other.end5_), - current5_(other.current5_) { - ComputeCurrentValue(); - } - - void ComputeCurrentValue() { - if (!AtEnd()) - current_value_ = ParamType(*current1_, *current2_, *current3_, - *current4_, *current5_); - } - bool AtEnd() const { - // We must report iterator past the end of the range when either of the - // component iterators has reached the end of its range. - return - current1_ == end1_ || - current2_ == end2_ || - current3_ == end3_ || - current4_ == end4_ || - current5_ == end5_; - } - - // No implementation - assignment is unsupported. - void operator=(const Iterator& other); - - const ParamGeneratorInterface* const base_; - // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. - // current[i]_ is the actual traversing iterator. - const typename ParamGenerator::iterator begin1_; - const typename ParamGenerator::iterator end1_; - typename ParamGenerator::iterator current1_; - const typename ParamGenerator::iterator begin2_; - const typename ParamGenerator::iterator end2_; - typename ParamGenerator::iterator current2_; - const typename ParamGenerator::iterator begin3_; - const typename ParamGenerator::iterator end3_; - typename ParamGenerator::iterator current3_; - const typename ParamGenerator::iterator begin4_; - const typename ParamGenerator::iterator end4_; - typename ParamGenerator::iterator current4_; - const typename ParamGenerator::iterator begin5_; - const typename ParamGenerator::iterator end5_; - typename ParamGenerator::iterator current5_; - ParamType current_value_; - }; // class CartesianProductGenerator5::Iterator - - // No implementation - assignment is unsupported. - void operator=(const CartesianProductGenerator5& other); - - const ParamGenerator g1_; - const ParamGenerator g2_; - const ParamGenerator g3_; - const ParamGenerator g4_; - const ParamGenerator g5_; -}; // class CartesianProductGenerator5 - - -template -class CartesianProductGenerator6 - : public ParamGeneratorInterface< ::testing::tuple > { - public: - typedef ::testing::tuple ParamType; - - CartesianProductGenerator6(const ParamGenerator& g1, - const ParamGenerator& g2, const ParamGenerator& g3, - const ParamGenerator& g4, const ParamGenerator& g5, - const ParamGenerator& g6) - : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {} - virtual ~CartesianProductGenerator6() {} - - virtual ParamIteratorInterface* Begin() const { - return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, - g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin()); - } - virtual ParamIteratorInterface* End() const { - return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), - g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end()); - } - - private: - class Iterator : public ParamIteratorInterface { - public: - Iterator(const ParamGeneratorInterface* base, - const ParamGenerator& g1, - const typename ParamGenerator::iterator& current1, - const ParamGenerator& g2, - const typename ParamGenerator::iterator& current2, - const ParamGenerator& g3, - const typename ParamGenerator::iterator& current3, - const ParamGenerator& g4, - const typename ParamGenerator::iterator& current4, - const ParamGenerator& g5, - const typename ParamGenerator::iterator& current5, - const ParamGenerator& g6, - const typename ParamGenerator::iterator& current6) - : base_(base), - begin1_(g1.begin()), end1_(g1.end()), current1_(current1), - begin2_(g2.begin()), end2_(g2.end()), current2_(current2), - begin3_(g3.begin()), end3_(g3.end()), current3_(current3), - begin4_(g4.begin()), end4_(g4.end()), current4_(current4), - begin5_(g5.begin()), end5_(g5.end()), current5_(current5), - begin6_(g6.begin()), end6_(g6.end()), current6_(current6) { - ComputeCurrentValue(); - } - virtual ~Iterator() {} - - virtual const ParamGeneratorInterface* BaseGenerator() const { - return base_; - } - // Advance should not be called on beyond-of-range iterators - // so no component iterators must be beyond end of range, either. - virtual void Advance() { - assert(!AtEnd()); - ++current6_; - if (current6_ == end6_) { - current6_ = begin6_; - ++current5_; - } - if (current5_ == end5_) { - current5_ = begin5_; - ++current4_; - } - if (current4_ == end4_) { - current4_ = begin4_; - ++current3_; - } - if (current3_ == end3_) { - current3_ = begin3_; - ++current2_; - } - if (current2_ == end2_) { - current2_ = begin2_; - ++current1_; - } - ComputeCurrentValue(); - } - virtual ParamIteratorInterface* Clone() const { - return new Iterator(*this); - } - virtual const ParamType* Current() const { return ¤t_value_; } - virtual bool Equals(const ParamIteratorInterface& other) const { - // Having the same base generator guarantees that the other - // iterator is of the same type and we can downcast. - GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) - << "The program attempted to compare iterators " - << "from different generators." << std::endl; - const Iterator* typed_other = - CheckedDowncastToActualType(&other); - // We must report iterators equal if they both point beyond their - // respective ranges. That can happen in a variety of fashions, - // so we have to consult AtEnd(). - return (AtEnd() && typed_other->AtEnd()) || - ( - current1_ == typed_other->current1_ && - current2_ == typed_other->current2_ && - current3_ == typed_other->current3_ && - current4_ == typed_other->current4_ && - current5_ == typed_other->current5_ && - current6_ == typed_other->current6_); - } - - private: - Iterator(const Iterator& other) - : base_(other.base_), - begin1_(other.begin1_), - end1_(other.end1_), - current1_(other.current1_), - begin2_(other.begin2_), - end2_(other.end2_), - current2_(other.current2_), - begin3_(other.begin3_), - end3_(other.end3_), - current3_(other.current3_), - begin4_(other.begin4_), - end4_(other.end4_), - current4_(other.current4_), - begin5_(other.begin5_), - end5_(other.end5_), - current5_(other.current5_), - begin6_(other.begin6_), - end6_(other.end6_), - current6_(other.current6_) { - ComputeCurrentValue(); - } - - void ComputeCurrentValue() { - if (!AtEnd()) - current_value_ = ParamType(*current1_, *current2_, *current3_, - *current4_, *current5_, *current6_); - } - bool AtEnd() const { - // We must report iterator past the end of the range when either of the - // component iterators has reached the end of its range. - return - current1_ == end1_ || - current2_ == end2_ || - current3_ == end3_ || - current4_ == end4_ || - current5_ == end5_ || - current6_ == end6_; - } - - // No implementation - assignment is unsupported. - void operator=(const Iterator& other); - - const ParamGeneratorInterface* const base_; - // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. - // current[i]_ is the actual traversing iterator. - const typename ParamGenerator::iterator begin1_; - const typename ParamGenerator::iterator end1_; - typename ParamGenerator::iterator current1_; - const typename ParamGenerator::iterator begin2_; - const typename ParamGenerator::iterator end2_; - typename ParamGenerator::iterator current2_; - const typename ParamGenerator::iterator begin3_; - const typename ParamGenerator::iterator end3_; - typename ParamGenerator::iterator current3_; - const typename ParamGenerator::iterator begin4_; - const typename ParamGenerator::iterator end4_; - typename ParamGenerator::iterator current4_; - const typename ParamGenerator::iterator begin5_; - const typename ParamGenerator::iterator end5_; - typename ParamGenerator::iterator current5_; - const typename ParamGenerator::iterator begin6_; - const typename ParamGenerator::iterator end6_; - typename ParamGenerator::iterator current6_; - ParamType current_value_; - }; // class CartesianProductGenerator6::Iterator - - // No implementation - assignment is unsupported. - void operator=(const CartesianProductGenerator6& other); - - const ParamGenerator g1_; - const ParamGenerator g2_; - const ParamGenerator g3_; - const ParamGenerator g4_; - const ParamGenerator g5_; - const ParamGenerator g6_; -}; // class CartesianProductGenerator6 - - -template -class CartesianProductGenerator7 - : public ParamGeneratorInterface< ::testing::tuple > { - public: - typedef ::testing::tuple ParamType; - - CartesianProductGenerator7(const ParamGenerator& g1, - const ParamGenerator& g2, const ParamGenerator& g3, - const ParamGenerator& g4, const ParamGenerator& g5, - const ParamGenerator& g6, const ParamGenerator& g7) - : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {} - virtual ~CartesianProductGenerator7() {} - - virtual ParamIteratorInterface* Begin() const { - return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, - g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, - g7_.begin()); - } - virtual ParamIteratorInterface* End() const { - return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), - g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end()); - } - - private: - class Iterator : public ParamIteratorInterface { - public: - Iterator(const ParamGeneratorInterface* base, - const ParamGenerator& g1, - const typename ParamGenerator::iterator& current1, - const ParamGenerator& g2, - const typename ParamGenerator::iterator& current2, - const ParamGenerator& g3, - const typename ParamGenerator::iterator& current3, - const ParamGenerator& g4, - const typename ParamGenerator::iterator& current4, - const ParamGenerator& g5, - const typename ParamGenerator::iterator& current5, - const ParamGenerator& g6, - const typename ParamGenerator::iterator& current6, - const ParamGenerator& g7, - const typename ParamGenerator::iterator& current7) - : base_(base), - begin1_(g1.begin()), end1_(g1.end()), current1_(current1), - begin2_(g2.begin()), end2_(g2.end()), current2_(current2), - begin3_(g3.begin()), end3_(g3.end()), current3_(current3), - begin4_(g4.begin()), end4_(g4.end()), current4_(current4), - begin5_(g5.begin()), end5_(g5.end()), current5_(current5), - begin6_(g6.begin()), end6_(g6.end()), current6_(current6), - begin7_(g7.begin()), end7_(g7.end()), current7_(current7) { - ComputeCurrentValue(); - } - virtual ~Iterator() {} - - virtual const ParamGeneratorInterface* BaseGenerator() const { - return base_; - } - // Advance should not be called on beyond-of-range iterators - // so no component iterators must be beyond end of range, either. - virtual void Advance() { - assert(!AtEnd()); - ++current7_; - if (current7_ == end7_) { - current7_ = begin7_; - ++current6_; - } - if (current6_ == end6_) { - current6_ = begin6_; - ++current5_; - } - if (current5_ == end5_) { - current5_ = begin5_; - ++current4_; - } - if (current4_ == end4_) { - current4_ = begin4_; - ++current3_; - } - if (current3_ == end3_) { - current3_ = begin3_; - ++current2_; - } - if (current2_ == end2_) { - current2_ = begin2_; - ++current1_; - } - ComputeCurrentValue(); - } - virtual ParamIteratorInterface* Clone() const { - return new Iterator(*this); - } - virtual const ParamType* Current() const { return ¤t_value_; } - virtual bool Equals(const ParamIteratorInterface& other) const { - // Having the same base generator guarantees that the other - // iterator is of the same type and we can downcast. - GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) - << "The program attempted to compare iterators " - << "from different generators." << std::endl; - const Iterator* typed_other = - CheckedDowncastToActualType(&other); - // We must report iterators equal if they both point beyond their - // respective ranges. That can happen in a variety of fashions, - // so we have to consult AtEnd(). - return (AtEnd() && typed_other->AtEnd()) || - ( - current1_ == typed_other->current1_ && - current2_ == typed_other->current2_ && - current3_ == typed_other->current3_ && - current4_ == typed_other->current4_ && - current5_ == typed_other->current5_ && - current6_ == typed_other->current6_ && - current7_ == typed_other->current7_); - } - - private: - Iterator(const Iterator& other) - : base_(other.base_), - begin1_(other.begin1_), - end1_(other.end1_), - current1_(other.current1_), - begin2_(other.begin2_), - end2_(other.end2_), - current2_(other.current2_), - begin3_(other.begin3_), - end3_(other.end3_), - current3_(other.current3_), - begin4_(other.begin4_), - end4_(other.end4_), - current4_(other.current4_), - begin5_(other.begin5_), - end5_(other.end5_), - current5_(other.current5_), - begin6_(other.begin6_), - end6_(other.end6_), - current6_(other.current6_), - begin7_(other.begin7_), - end7_(other.end7_), - current7_(other.current7_) { - ComputeCurrentValue(); - } - - void ComputeCurrentValue() { - if (!AtEnd()) - current_value_ = ParamType(*current1_, *current2_, *current3_, - *current4_, *current5_, *current6_, *current7_); - } - bool AtEnd() const { - // We must report iterator past the end of the range when either of the - // component iterators has reached the end of its range. - return - current1_ == end1_ || - current2_ == end2_ || - current3_ == end3_ || - current4_ == end4_ || - current5_ == end5_ || - current6_ == end6_ || - current7_ == end7_; - } - - // No implementation - assignment is unsupported. - void operator=(const Iterator& other); - - const ParamGeneratorInterface* const base_; - // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. - // current[i]_ is the actual traversing iterator. - const typename ParamGenerator::iterator begin1_; - const typename ParamGenerator::iterator end1_; - typename ParamGenerator::iterator current1_; - const typename ParamGenerator::iterator begin2_; - const typename ParamGenerator::iterator end2_; - typename ParamGenerator::iterator current2_; - const typename ParamGenerator::iterator begin3_; - const typename ParamGenerator::iterator end3_; - typename ParamGenerator::iterator current3_; - const typename ParamGenerator::iterator begin4_; - const typename ParamGenerator::iterator end4_; - typename ParamGenerator::iterator current4_; - const typename ParamGenerator::iterator begin5_; - const typename ParamGenerator::iterator end5_; - typename ParamGenerator::iterator current5_; - const typename ParamGenerator::iterator begin6_; - const typename ParamGenerator::iterator end6_; - typename ParamGenerator::iterator current6_; - const typename ParamGenerator::iterator begin7_; - const typename ParamGenerator::iterator end7_; - typename ParamGenerator::iterator current7_; - ParamType current_value_; - }; // class CartesianProductGenerator7::Iterator - - // No implementation - assignment is unsupported. - void operator=(const CartesianProductGenerator7& other); - - const ParamGenerator g1_; - const ParamGenerator g2_; - const ParamGenerator g3_; - const ParamGenerator g4_; - const ParamGenerator g5_; - const ParamGenerator g6_; - const ParamGenerator g7_; -}; // class CartesianProductGenerator7 - - -template -class CartesianProductGenerator8 - : public ParamGeneratorInterface< ::testing::tuple > { - public: - typedef ::testing::tuple ParamType; - - CartesianProductGenerator8(const ParamGenerator& g1, - const ParamGenerator& g2, const ParamGenerator& g3, - const ParamGenerator& g4, const ParamGenerator& g5, - const ParamGenerator& g6, const ParamGenerator& g7, - const ParamGenerator& g8) - : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), - g8_(g8) {} - virtual ~CartesianProductGenerator8() {} - - virtual ParamIteratorInterface* Begin() const { - return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, - g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, - g7_.begin(), g8_, g8_.begin()); - } - virtual ParamIteratorInterface* End() const { - return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), - g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, - g8_.end()); - } - - private: - class Iterator : public ParamIteratorInterface { - public: - Iterator(const ParamGeneratorInterface* base, - const ParamGenerator& g1, - const typename ParamGenerator::iterator& current1, - const ParamGenerator& g2, - const typename ParamGenerator::iterator& current2, - const ParamGenerator& g3, - const typename ParamGenerator::iterator& current3, - const ParamGenerator& g4, - const typename ParamGenerator::iterator& current4, - const ParamGenerator& g5, - const typename ParamGenerator::iterator& current5, - const ParamGenerator& g6, - const typename ParamGenerator::iterator& current6, - const ParamGenerator& g7, - const typename ParamGenerator::iterator& current7, - const ParamGenerator& g8, - const typename ParamGenerator::iterator& current8) - : base_(base), - begin1_(g1.begin()), end1_(g1.end()), current1_(current1), - begin2_(g2.begin()), end2_(g2.end()), current2_(current2), - begin3_(g3.begin()), end3_(g3.end()), current3_(current3), - begin4_(g4.begin()), end4_(g4.end()), current4_(current4), - begin5_(g5.begin()), end5_(g5.end()), current5_(current5), - begin6_(g6.begin()), end6_(g6.end()), current6_(current6), - begin7_(g7.begin()), end7_(g7.end()), current7_(current7), - begin8_(g8.begin()), end8_(g8.end()), current8_(current8) { - ComputeCurrentValue(); - } - virtual ~Iterator() {} - - virtual const ParamGeneratorInterface* BaseGenerator() const { - return base_; - } - // Advance should not be called on beyond-of-range iterators - // so no component iterators must be beyond end of range, either. - virtual void Advance() { - assert(!AtEnd()); - ++current8_; - if (current8_ == end8_) { - current8_ = begin8_; - ++current7_; - } - if (current7_ == end7_) { - current7_ = begin7_; - ++current6_; - } - if (current6_ == end6_) { - current6_ = begin6_; - ++current5_; - } - if (current5_ == end5_) { - current5_ = begin5_; - ++current4_; - } - if (current4_ == end4_) { - current4_ = begin4_; - ++current3_; - } - if (current3_ == end3_) { - current3_ = begin3_; - ++current2_; - } - if (current2_ == end2_) { - current2_ = begin2_; - ++current1_; - } - ComputeCurrentValue(); - } - virtual ParamIteratorInterface* Clone() const { - return new Iterator(*this); - } - virtual const ParamType* Current() const { return ¤t_value_; } - virtual bool Equals(const ParamIteratorInterface& other) const { - // Having the same base generator guarantees that the other - // iterator is of the same type and we can downcast. - GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) - << "The program attempted to compare iterators " - << "from different generators." << std::endl; - const Iterator* typed_other = - CheckedDowncastToActualType(&other); - // We must report iterators equal if they both point beyond their - // respective ranges. That can happen in a variety of fashions, - // so we have to consult AtEnd(). - return (AtEnd() && typed_other->AtEnd()) || - ( - current1_ == typed_other->current1_ && - current2_ == typed_other->current2_ && - current3_ == typed_other->current3_ && - current4_ == typed_other->current4_ && - current5_ == typed_other->current5_ && - current6_ == typed_other->current6_ && - current7_ == typed_other->current7_ && - current8_ == typed_other->current8_); - } - - private: - Iterator(const Iterator& other) - : base_(other.base_), - begin1_(other.begin1_), - end1_(other.end1_), - current1_(other.current1_), - begin2_(other.begin2_), - end2_(other.end2_), - current2_(other.current2_), - begin3_(other.begin3_), - end3_(other.end3_), - current3_(other.current3_), - begin4_(other.begin4_), - end4_(other.end4_), - current4_(other.current4_), - begin5_(other.begin5_), - end5_(other.end5_), - current5_(other.current5_), - begin6_(other.begin6_), - end6_(other.end6_), - current6_(other.current6_), - begin7_(other.begin7_), - end7_(other.end7_), - current7_(other.current7_), - begin8_(other.begin8_), - end8_(other.end8_), - current8_(other.current8_) { - ComputeCurrentValue(); - } - - void ComputeCurrentValue() { - if (!AtEnd()) - current_value_ = ParamType(*current1_, *current2_, *current3_, - *current4_, *current5_, *current6_, *current7_, *current8_); - } - bool AtEnd() const { - // We must report iterator past the end of the range when either of the - // component iterators has reached the end of its range. - return - current1_ == end1_ || - current2_ == end2_ || - current3_ == end3_ || - current4_ == end4_ || - current5_ == end5_ || - current6_ == end6_ || - current7_ == end7_ || - current8_ == end8_; - } - - // No implementation - assignment is unsupported. - void operator=(const Iterator& other); - - const ParamGeneratorInterface* const base_; - // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. - // current[i]_ is the actual traversing iterator. - const typename ParamGenerator::iterator begin1_; - const typename ParamGenerator::iterator end1_; - typename ParamGenerator::iterator current1_; - const typename ParamGenerator::iterator begin2_; - const typename ParamGenerator::iterator end2_; - typename ParamGenerator::iterator current2_; - const typename ParamGenerator::iterator begin3_; - const typename ParamGenerator::iterator end3_; - typename ParamGenerator::iterator current3_; - const typename ParamGenerator::iterator begin4_; - const typename ParamGenerator::iterator end4_; - typename ParamGenerator::iterator current4_; - const typename ParamGenerator::iterator begin5_; - const typename ParamGenerator::iterator end5_; - typename ParamGenerator::iterator current5_; - const typename ParamGenerator::iterator begin6_; - const typename ParamGenerator::iterator end6_; - typename ParamGenerator::iterator current6_; - const typename ParamGenerator::iterator begin7_; - const typename ParamGenerator::iterator end7_; - typename ParamGenerator::iterator current7_; - const typename ParamGenerator::iterator begin8_; - const typename ParamGenerator::iterator end8_; - typename ParamGenerator::iterator current8_; - ParamType current_value_; - }; // class CartesianProductGenerator8::Iterator - - // No implementation - assignment is unsupported. - void operator=(const CartesianProductGenerator8& other); - - const ParamGenerator g1_; - const ParamGenerator g2_; - const ParamGenerator g3_; - const ParamGenerator g4_; - const ParamGenerator g5_; - const ParamGenerator g6_; - const ParamGenerator g7_; - const ParamGenerator g8_; -}; // class CartesianProductGenerator8 - - -template -class CartesianProductGenerator9 - : public ParamGeneratorInterface< ::testing::tuple > { - public: - typedef ::testing::tuple ParamType; - - CartesianProductGenerator9(const ParamGenerator& g1, - const ParamGenerator& g2, const ParamGenerator& g3, - const ParamGenerator& g4, const ParamGenerator& g5, - const ParamGenerator& g6, const ParamGenerator& g7, - const ParamGenerator& g8, const ParamGenerator& g9) - : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), - g9_(g9) {} - virtual ~CartesianProductGenerator9() {} - - virtual ParamIteratorInterface* Begin() const { - return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, - g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, - g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin()); - } - virtual ParamIteratorInterface* End() const { - return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), - g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, - g8_.end(), g9_, g9_.end()); - } - - private: - class Iterator : public ParamIteratorInterface { - public: - Iterator(const ParamGeneratorInterface* base, - const ParamGenerator& g1, - const typename ParamGenerator::iterator& current1, - const ParamGenerator& g2, - const typename ParamGenerator::iterator& current2, - const ParamGenerator& g3, - const typename ParamGenerator::iterator& current3, - const ParamGenerator& g4, - const typename ParamGenerator::iterator& current4, - const ParamGenerator& g5, - const typename ParamGenerator::iterator& current5, - const ParamGenerator& g6, - const typename ParamGenerator::iterator& current6, - const ParamGenerator& g7, - const typename ParamGenerator::iterator& current7, - const ParamGenerator& g8, - const typename ParamGenerator::iterator& current8, - const ParamGenerator& g9, - const typename ParamGenerator::iterator& current9) - : base_(base), - begin1_(g1.begin()), end1_(g1.end()), current1_(current1), - begin2_(g2.begin()), end2_(g2.end()), current2_(current2), - begin3_(g3.begin()), end3_(g3.end()), current3_(current3), - begin4_(g4.begin()), end4_(g4.end()), current4_(current4), - begin5_(g5.begin()), end5_(g5.end()), current5_(current5), - begin6_(g6.begin()), end6_(g6.end()), current6_(current6), - begin7_(g7.begin()), end7_(g7.end()), current7_(current7), - begin8_(g8.begin()), end8_(g8.end()), current8_(current8), - begin9_(g9.begin()), end9_(g9.end()), current9_(current9) { - ComputeCurrentValue(); - } - virtual ~Iterator() {} - - virtual const ParamGeneratorInterface* BaseGenerator() const { - return base_; - } - // Advance should not be called on beyond-of-range iterators - // so no component iterators must be beyond end of range, either. - virtual void Advance() { - assert(!AtEnd()); - ++current9_; - if (current9_ == end9_) { - current9_ = begin9_; - ++current8_; - } - if (current8_ == end8_) { - current8_ = begin8_; - ++current7_; - } - if (current7_ == end7_) { - current7_ = begin7_; - ++current6_; - } - if (current6_ == end6_) { - current6_ = begin6_; - ++current5_; - } - if (current5_ == end5_) { - current5_ = begin5_; - ++current4_; - } - if (current4_ == end4_) { - current4_ = begin4_; - ++current3_; - } - if (current3_ == end3_) { - current3_ = begin3_; - ++current2_; - } - if (current2_ == end2_) { - current2_ = begin2_; - ++current1_; - } - ComputeCurrentValue(); - } - virtual ParamIteratorInterface* Clone() const { - return new Iterator(*this); - } - virtual const ParamType* Current() const { return ¤t_value_; } - virtual bool Equals(const ParamIteratorInterface& other) const { - // Having the same base generator guarantees that the other - // iterator is of the same type and we can downcast. - GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) - << "The program attempted to compare iterators " - << "from different generators." << std::endl; - const Iterator* typed_other = - CheckedDowncastToActualType(&other); - // We must report iterators equal if they both point beyond their - // respective ranges. That can happen in a variety of fashions, - // so we have to consult AtEnd(). - return (AtEnd() && typed_other->AtEnd()) || - ( - current1_ == typed_other->current1_ && - current2_ == typed_other->current2_ && - current3_ == typed_other->current3_ && - current4_ == typed_other->current4_ && - current5_ == typed_other->current5_ && - current6_ == typed_other->current6_ && - current7_ == typed_other->current7_ && - current8_ == typed_other->current8_ && - current9_ == typed_other->current9_); - } - - private: - Iterator(const Iterator& other) - : base_(other.base_), - begin1_(other.begin1_), - end1_(other.end1_), - current1_(other.current1_), - begin2_(other.begin2_), - end2_(other.end2_), - current2_(other.current2_), - begin3_(other.begin3_), - end3_(other.end3_), - current3_(other.current3_), - begin4_(other.begin4_), - end4_(other.end4_), - current4_(other.current4_), - begin5_(other.begin5_), - end5_(other.end5_), - current5_(other.current5_), - begin6_(other.begin6_), - end6_(other.end6_), - current6_(other.current6_), - begin7_(other.begin7_), - end7_(other.end7_), - current7_(other.current7_), - begin8_(other.begin8_), - end8_(other.end8_), - current8_(other.current8_), - begin9_(other.begin9_), - end9_(other.end9_), - current9_(other.current9_) { - ComputeCurrentValue(); - } - - void ComputeCurrentValue() { - if (!AtEnd()) - current_value_ = ParamType(*current1_, *current2_, *current3_, - *current4_, *current5_, *current6_, *current7_, *current8_, - *current9_); - } - bool AtEnd() const { - // We must report iterator past the end of the range when either of the - // component iterators has reached the end of its range. - return - current1_ == end1_ || - current2_ == end2_ || - current3_ == end3_ || - current4_ == end4_ || - current5_ == end5_ || - current6_ == end6_ || - current7_ == end7_ || - current8_ == end8_ || - current9_ == end9_; - } - - // No implementation - assignment is unsupported. - void operator=(const Iterator& other); - - const ParamGeneratorInterface* const base_; - // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. - // current[i]_ is the actual traversing iterator. - const typename ParamGenerator::iterator begin1_; - const typename ParamGenerator::iterator end1_; - typename ParamGenerator::iterator current1_; - const typename ParamGenerator::iterator begin2_; - const typename ParamGenerator::iterator end2_; - typename ParamGenerator::iterator current2_; - const typename ParamGenerator::iterator begin3_; - const typename ParamGenerator::iterator end3_; - typename ParamGenerator::iterator current3_; - const typename ParamGenerator::iterator begin4_; - const typename ParamGenerator::iterator end4_; - typename ParamGenerator::iterator current4_; - const typename ParamGenerator::iterator begin5_; - const typename ParamGenerator::iterator end5_; - typename ParamGenerator::iterator current5_; - const typename ParamGenerator::iterator begin6_; - const typename ParamGenerator::iterator end6_; - typename ParamGenerator::iterator current6_; - const typename ParamGenerator::iterator begin7_; - const typename ParamGenerator::iterator end7_; - typename ParamGenerator::iterator current7_; - const typename ParamGenerator::iterator begin8_; - const typename ParamGenerator::iterator end8_; - typename ParamGenerator::iterator current8_; - const typename ParamGenerator::iterator begin9_; - const typename ParamGenerator::iterator end9_; - typename ParamGenerator::iterator current9_; - ParamType current_value_; - }; // class CartesianProductGenerator9::Iterator - - // No implementation - assignment is unsupported. - void operator=(const CartesianProductGenerator9& other); - - const ParamGenerator g1_; - const ParamGenerator g2_; - const ParamGenerator g3_; - const ParamGenerator g4_; - const ParamGenerator g5_; - const ParamGenerator g6_; - const ParamGenerator g7_; - const ParamGenerator g8_; - const ParamGenerator g9_; -}; // class CartesianProductGenerator9 - - -template -class CartesianProductGenerator10 - : public ParamGeneratorInterface< ::testing::tuple > { - public: - typedef ::testing::tuple ParamType; - - CartesianProductGenerator10(const ParamGenerator& g1, - const ParamGenerator& g2, const ParamGenerator& g3, - const ParamGenerator& g4, const ParamGenerator& g5, - const ParamGenerator& g6, const ParamGenerator& g7, - const ParamGenerator& g8, const ParamGenerator& g9, - const ParamGenerator& g10) - : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), - g9_(g9), g10_(g10) {} - virtual ~CartesianProductGenerator10() {} - - virtual ParamIteratorInterface* Begin() const { - return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, - g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, - g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin(), g10_, g10_.begin()); - } - virtual ParamIteratorInterface* End() const { - return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), - g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, - g8_.end(), g9_, g9_.end(), g10_, g10_.end()); - } - - private: - class Iterator : public ParamIteratorInterface { - public: - Iterator(const ParamGeneratorInterface* base, - const ParamGenerator& g1, - const typename ParamGenerator::iterator& current1, - const ParamGenerator& g2, - const typename ParamGenerator::iterator& current2, - const ParamGenerator& g3, - const typename ParamGenerator::iterator& current3, - const ParamGenerator& g4, - const typename ParamGenerator::iterator& current4, - const ParamGenerator& g5, - const typename ParamGenerator::iterator& current5, - const ParamGenerator& g6, - const typename ParamGenerator::iterator& current6, - const ParamGenerator& g7, - const typename ParamGenerator::iterator& current7, - const ParamGenerator& g8, - const typename ParamGenerator::iterator& current8, - const ParamGenerator& g9, - const typename ParamGenerator::iterator& current9, - const ParamGenerator& g10, - const typename ParamGenerator::iterator& current10) - : base_(base), - begin1_(g1.begin()), end1_(g1.end()), current1_(current1), - begin2_(g2.begin()), end2_(g2.end()), current2_(current2), - begin3_(g3.begin()), end3_(g3.end()), current3_(current3), - begin4_(g4.begin()), end4_(g4.end()), current4_(current4), - begin5_(g5.begin()), end5_(g5.end()), current5_(current5), - begin6_(g6.begin()), end6_(g6.end()), current6_(current6), - begin7_(g7.begin()), end7_(g7.end()), current7_(current7), - begin8_(g8.begin()), end8_(g8.end()), current8_(current8), - begin9_(g9.begin()), end9_(g9.end()), current9_(current9), - begin10_(g10.begin()), end10_(g10.end()), current10_(current10) { - ComputeCurrentValue(); - } - virtual ~Iterator() {} - - virtual const ParamGeneratorInterface* BaseGenerator() const { - return base_; - } - // Advance should not be called on beyond-of-range iterators - // so no component iterators must be beyond end of range, either. - virtual void Advance() { - assert(!AtEnd()); - ++current10_; - if (current10_ == end10_) { - current10_ = begin10_; - ++current9_; - } - if (current9_ == end9_) { - current9_ = begin9_; - ++current8_; - } - if (current8_ == end8_) { - current8_ = begin8_; - ++current7_; - } - if (current7_ == end7_) { - current7_ = begin7_; - ++current6_; - } - if (current6_ == end6_) { - current6_ = begin6_; - ++current5_; - } - if (current5_ == end5_) { - current5_ = begin5_; - ++current4_; - } - if (current4_ == end4_) { - current4_ = begin4_; - ++current3_; - } - if (current3_ == end3_) { - current3_ = begin3_; - ++current2_; - } - if (current2_ == end2_) { - current2_ = begin2_; - ++current1_; - } - ComputeCurrentValue(); - } - virtual ParamIteratorInterface* Clone() const { - return new Iterator(*this); - } - virtual const ParamType* Current() const { return ¤t_value_; } - virtual bool Equals(const ParamIteratorInterface& other) const { - // Having the same base generator guarantees that the other - // iterator is of the same type and we can downcast. - GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) - << "The program attempted to compare iterators " - << "from different generators." << std::endl; - const Iterator* typed_other = - CheckedDowncastToActualType(&other); - // We must report iterators equal if they both point beyond their - // respective ranges. That can happen in a variety of fashions, - // so we have to consult AtEnd(). - return (AtEnd() && typed_other->AtEnd()) || - ( - current1_ == typed_other->current1_ && - current2_ == typed_other->current2_ && - current3_ == typed_other->current3_ && - current4_ == typed_other->current4_ && - current5_ == typed_other->current5_ && - current6_ == typed_other->current6_ && - current7_ == typed_other->current7_ && - current8_ == typed_other->current8_ && - current9_ == typed_other->current9_ && - current10_ == typed_other->current10_); - } - - private: - Iterator(const Iterator& other) - : base_(other.base_), - begin1_(other.begin1_), - end1_(other.end1_), - current1_(other.current1_), - begin2_(other.begin2_), - end2_(other.end2_), - current2_(other.current2_), - begin3_(other.begin3_), - end3_(other.end3_), - current3_(other.current3_), - begin4_(other.begin4_), - end4_(other.end4_), - current4_(other.current4_), - begin5_(other.begin5_), - end5_(other.end5_), - current5_(other.current5_), - begin6_(other.begin6_), - end6_(other.end6_), - current6_(other.current6_), - begin7_(other.begin7_), - end7_(other.end7_), - current7_(other.current7_), - begin8_(other.begin8_), - end8_(other.end8_), - current8_(other.current8_), - begin9_(other.begin9_), - end9_(other.end9_), - current9_(other.current9_), - begin10_(other.begin10_), - end10_(other.end10_), - current10_(other.current10_) { - ComputeCurrentValue(); - } - - void ComputeCurrentValue() { - if (!AtEnd()) - current_value_ = ParamType(*current1_, *current2_, *current3_, - *current4_, *current5_, *current6_, *current7_, *current8_, - *current9_, *current10_); - } - bool AtEnd() const { - // We must report iterator past the end of the range when either of the - // component iterators has reached the end of its range. - return - current1_ == end1_ || - current2_ == end2_ || - current3_ == end3_ || - current4_ == end4_ || - current5_ == end5_ || - current6_ == end6_ || - current7_ == end7_ || - current8_ == end8_ || - current9_ == end9_ || - current10_ == end10_; - } - - // No implementation - assignment is unsupported. - void operator=(const Iterator& other); - - const ParamGeneratorInterface* const base_; - // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. - // current[i]_ is the actual traversing iterator. - const typename ParamGenerator::iterator begin1_; - const typename ParamGenerator::iterator end1_; - typename ParamGenerator::iterator current1_; - const typename ParamGenerator::iterator begin2_; - const typename ParamGenerator::iterator end2_; - typename ParamGenerator::iterator current2_; - const typename ParamGenerator::iterator begin3_; - const typename ParamGenerator::iterator end3_; - typename ParamGenerator::iterator current3_; - const typename ParamGenerator::iterator begin4_; - const typename ParamGenerator::iterator end4_; - typename ParamGenerator::iterator current4_; - const typename ParamGenerator::iterator begin5_; - const typename ParamGenerator::iterator end5_; - typename ParamGenerator::iterator current5_; - const typename ParamGenerator::iterator begin6_; - const typename ParamGenerator::iterator end6_; - typename ParamGenerator::iterator current6_; - const typename ParamGenerator::iterator begin7_; - const typename ParamGenerator::iterator end7_; - typename ParamGenerator::iterator current7_; - const typename ParamGenerator::iterator begin8_; - const typename ParamGenerator::iterator end8_; - typename ParamGenerator::iterator current8_; - const typename ParamGenerator::iterator begin9_; - const typename ParamGenerator::iterator end9_; - typename ParamGenerator::iterator current9_; - const typename ParamGenerator::iterator begin10_; - const typename ParamGenerator::iterator end10_; - typename ParamGenerator::iterator current10_; - ParamType current_value_; - }; // class CartesianProductGenerator10::Iterator - - // No implementation - assignment is unsupported. - void operator=(const CartesianProductGenerator10& other); - - const ParamGenerator g1_; - const ParamGenerator g2_; - const ParamGenerator g3_; - const ParamGenerator g4_; - const ParamGenerator g5_; - const ParamGenerator g6_; - const ParamGenerator g7_; - const ParamGenerator g8_; - const ParamGenerator g9_; - const ParamGenerator g10_; -}; // class CartesianProductGenerator10 - - -// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. -// -// Helper classes providing Combine() with polymorphic features. They allow -// casting CartesianProductGeneratorN to ParamGenerator if T is -// convertible to U. -// -template -class CartesianProductHolder2 { - public: -CartesianProductHolder2(const Generator1& g1, const Generator2& g2) - : g1_(g1), g2_(g2) {} - template - operator ParamGenerator< ::testing::tuple >() const { - return ParamGenerator< ::testing::tuple >( - new CartesianProductGenerator2( - static_cast >(g1_), - static_cast >(g2_))); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const CartesianProductHolder2& other); - - const Generator1 g1_; - const Generator2 g2_; -}; // class CartesianProductHolder2 - -template -class CartesianProductHolder3 { - public: -CartesianProductHolder3(const Generator1& g1, const Generator2& g2, - const Generator3& g3) - : g1_(g1), g2_(g2), g3_(g3) {} - template - operator ParamGenerator< ::testing::tuple >() const { - return ParamGenerator< ::testing::tuple >( - new CartesianProductGenerator3( - static_cast >(g1_), - static_cast >(g2_), - static_cast >(g3_))); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const CartesianProductHolder3& other); - - const Generator1 g1_; - const Generator2 g2_; - const Generator3 g3_; -}; // class CartesianProductHolder3 - -template -class CartesianProductHolder4 { - public: -CartesianProductHolder4(const Generator1& g1, const Generator2& g2, - const Generator3& g3, const Generator4& g4) - : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {} - template - operator ParamGenerator< ::testing::tuple >() const { - return ParamGenerator< ::testing::tuple >( - new CartesianProductGenerator4( - static_cast >(g1_), - static_cast >(g2_), - static_cast >(g3_), - static_cast >(g4_))); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const CartesianProductHolder4& other); - - const Generator1 g1_; - const Generator2 g2_; - const Generator3 g3_; - const Generator4 g4_; -}; // class CartesianProductHolder4 - -template -class CartesianProductHolder5 { - public: -CartesianProductHolder5(const Generator1& g1, const Generator2& g2, - const Generator3& g3, const Generator4& g4, const Generator5& g5) - : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {} - template - operator ParamGenerator< ::testing::tuple >() const { - return ParamGenerator< ::testing::tuple >( - new CartesianProductGenerator5( - static_cast >(g1_), - static_cast >(g2_), - static_cast >(g3_), - static_cast >(g4_), - static_cast >(g5_))); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const CartesianProductHolder5& other); - - const Generator1 g1_; - const Generator2 g2_; - const Generator3 g3_; - const Generator4 g4_; - const Generator5 g5_; -}; // class CartesianProductHolder5 - -template -class CartesianProductHolder6 { - public: -CartesianProductHolder6(const Generator1& g1, const Generator2& g2, - const Generator3& g3, const Generator4& g4, const Generator5& g5, - const Generator6& g6) - : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {} - template - operator ParamGenerator< ::testing::tuple >() const { - return ParamGenerator< ::testing::tuple >( - new CartesianProductGenerator6( - static_cast >(g1_), - static_cast >(g2_), - static_cast >(g3_), - static_cast >(g4_), - static_cast >(g5_), - static_cast >(g6_))); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const CartesianProductHolder6& other); - - const Generator1 g1_; - const Generator2 g2_; - const Generator3 g3_; - const Generator4 g4_; - const Generator5 g5_; - const Generator6 g6_; -}; // class CartesianProductHolder6 - -template -class CartesianProductHolder7 { - public: -CartesianProductHolder7(const Generator1& g1, const Generator2& g2, - const Generator3& g3, const Generator4& g4, const Generator5& g5, - const Generator6& g6, const Generator7& g7) - : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {} - template - operator ParamGenerator< ::testing::tuple >() const { - return ParamGenerator< ::testing::tuple >( - new CartesianProductGenerator7( - static_cast >(g1_), - static_cast >(g2_), - static_cast >(g3_), - static_cast >(g4_), - static_cast >(g5_), - static_cast >(g6_), - static_cast >(g7_))); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const CartesianProductHolder7& other); - - const Generator1 g1_; - const Generator2 g2_; - const Generator3 g3_; - const Generator4 g4_; - const Generator5 g5_; - const Generator6 g6_; - const Generator7 g7_; -}; // class CartesianProductHolder7 - -template -class CartesianProductHolder8 { - public: -CartesianProductHolder8(const Generator1& g1, const Generator2& g2, - const Generator3& g3, const Generator4& g4, const Generator5& g5, - const Generator6& g6, const Generator7& g7, const Generator8& g8) - : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), - g8_(g8) {} - template - operator ParamGenerator< ::testing::tuple >() const { - return ParamGenerator< ::testing::tuple >( - new CartesianProductGenerator8( - static_cast >(g1_), - static_cast >(g2_), - static_cast >(g3_), - static_cast >(g4_), - static_cast >(g5_), - static_cast >(g6_), - static_cast >(g7_), - static_cast >(g8_))); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const CartesianProductHolder8& other); - - const Generator1 g1_; - const Generator2 g2_; - const Generator3 g3_; - const Generator4 g4_; - const Generator5 g5_; - const Generator6 g6_; - const Generator7 g7_; - const Generator8 g8_; -}; // class CartesianProductHolder8 - -template -class CartesianProductHolder9 { - public: -CartesianProductHolder9(const Generator1& g1, const Generator2& g2, - const Generator3& g3, const Generator4& g4, const Generator5& g5, - const Generator6& g6, const Generator7& g7, const Generator8& g8, - const Generator9& g9) - : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), - g9_(g9) {} - template - operator ParamGenerator< ::testing::tuple >() const { - return ParamGenerator< ::testing::tuple >( - new CartesianProductGenerator9( - static_cast >(g1_), - static_cast >(g2_), - static_cast >(g3_), - static_cast >(g4_), - static_cast >(g5_), - static_cast >(g6_), - static_cast >(g7_), - static_cast >(g8_), - static_cast >(g9_))); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const CartesianProductHolder9& other); - - const Generator1 g1_; - const Generator2 g2_; - const Generator3 g3_; - const Generator4 g4_; - const Generator5 g5_; - const Generator6 g6_; - const Generator7 g7_; - const Generator8 g8_; - const Generator9 g9_; -}; // class CartesianProductHolder9 - -template -class CartesianProductHolder10 { - public: -CartesianProductHolder10(const Generator1& g1, const Generator2& g2, - const Generator3& g3, const Generator4& g4, const Generator5& g5, - const Generator6& g6, const Generator7& g7, const Generator8& g8, - const Generator9& g9, const Generator10& g10) - : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), - g9_(g9), g10_(g10) {} - template - operator ParamGenerator< ::testing::tuple >() const { - return ParamGenerator< ::testing::tuple >( - new CartesianProductGenerator10( - static_cast >(g1_), - static_cast >(g2_), - static_cast >(g3_), - static_cast >(g4_), - static_cast >(g5_), - static_cast >(g6_), - static_cast >(g7_), - static_cast >(g8_), - static_cast >(g9_), - static_cast >(g10_))); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const CartesianProductHolder10& other); - - const Generator1 g1_; - const Generator2 g2_; - const Generator3 g3_; - const Generator4 g4_; - const Generator5 g5_; - const Generator6 g6_; - const Generator7 g7_; - const Generator8 g8_; - const Generator9 g9_; - const Generator10 g10_; -}; // class CartesianProductHolder10 - -# endif // GTEST_HAS_COMBINE - -} // namespace internal -} // namespace testing - -#endif // GTEST_HAS_PARAM_TEST - -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ diff --git a/cpp/test/include/gtest/internal/gtest-param-util-generated.h.pump b/cpp/test/include/gtest/internal/gtest-param-util-generated.h.pump deleted file mode 100644 index 5c7c47af0b..0000000000 --- a/cpp/test/include/gtest/internal/gtest-param-util-generated.h.pump +++ /dev/null @@ -1,286 +0,0 @@ -$$ -*- mode: c++; -*- -$var n = 50 $$ Maximum length of Values arguments we want to support. -$var maxtuple = 10 $$ Maximum number of Combine arguments we want to support. -// Copyright 2008 Google Inc. -// All Rights Reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Author: vladl@google.com (Vlad Losev) - -// Type and function utilities for implementing parameterized tests. -// This file is generated by a SCRIPT. DO NOT EDIT BY HAND! -// -// Currently Google Test supports at most $n arguments in Values, -// and at most $maxtuple arguments in Combine. Please contact -// googletestframework@googlegroups.com if you need more. -// Please note that the number of arguments to Combine is limited -// by the maximum arity of the implementation of tuple which is -// currently set at $maxtuple. - -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ - -// scripts/fuse_gtest.py depends on gtest's own header being #included -// *unconditionally*. Therefore these #includes cannot be moved -// inside #if GTEST_HAS_PARAM_TEST. -#include "gtest/internal/gtest-param-util.h" -#include "gtest/internal/gtest-port.h" - -#if GTEST_HAS_PARAM_TEST - -namespace testing { - -// Forward declarations of ValuesIn(), which is implemented in -// include/gtest/gtest-param-test.h. -template -internal::ParamGenerator< - typename ::testing::internal::IteratorTraits::value_type> -ValuesIn(ForwardIterator begin, ForwardIterator end); - -template -internal::ParamGenerator ValuesIn(const T (&array)[N]); - -template -internal::ParamGenerator ValuesIn( - const Container& container); - -namespace internal { - -// Used in the Values() function to provide polymorphic capabilities. -$range i 1..n -$for i [[ -$range j 1..i - -template <$for j, [[typename T$j]]> -class ValueArray$i { - public: - $if i==1 [[explicit ]]ValueArray$i($for j, [[T$j v$j]]) : $for j, [[v$(j)_(v$j)]] {} - - template - operator ParamGenerator() const { - const T array[] = {$for j, [[static_cast(v$(j)_)]]}; - return ValuesIn(array); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const ValueArray$i& other); - -$for j [[ - - const T$j v$(j)_; -]] - -}; - -]] - -# if GTEST_HAS_COMBINE -// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. -// -// Generates values from the Cartesian product of values produced -// by the argument generators. -// -$range i 2..maxtuple -$for i [[ -$range j 1..i -$range k 2..i - -template <$for j, [[typename T$j]]> -class CartesianProductGenerator$i - : public ParamGeneratorInterface< ::testing::tuple<$for j, [[T$j]]> > { - public: - typedef ::testing::tuple<$for j, [[T$j]]> ParamType; - - CartesianProductGenerator$i($for j, [[const ParamGenerator& g$j]]) - : $for j, [[g$(j)_(g$j)]] {} - virtual ~CartesianProductGenerator$i() {} - - virtual ParamIteratorInterface* Begin() const { - return new Iterator(this, $for j, [[g$(j)_, g$(j)_.begin()]]); - } - virtual ParamIteratorInterface* End() const { - return new Iterator(this, $for j, [[g$(j)_, g$(j)_.end()]]); - } - - private: - class Iterator : public ParamIteratorInterface { - public: - Iterator(const ParamGeneratorInterface* base, $for j, [[ - - const ParamGenerator& g$j, - const typename ParamGenerator::iterator& current$(j)]]) - : base_(base), -$for j, [[ - - begin$(j)_(g$j.begin()), end$(j)_(g$j.end()), current$(j)_(current$j) -]] { - ComputeCurrentValue(); - } - virtual ~Iterator() {} - - virtual const ParamGeneratorInterface* BaseGenerator() const { - return base_; - } - // Advance should not be called on beyond-of-range iterators - // so no component iterators must be beyond end of range, either. - virtual void Advance() { - assert(!AtEnd()); - ++current$(i)_; - -$for k [[ - if (current$(i+2-k)_ == end$(i+2-k)_) { - current$(i+2-k)_ = begin$(i+2-k)_; - ++current$(i+2-k-1)_; - } - -]] - ComputeCurrentValue(); - } - virtual ParamIteratorInterface* Clone() const { - return new Iterator(*this); - } - virtual const ParamType* Current() const { return ¤t_value_; } - virtual bool Equals(const ParamIteratorInterface& other) const { - // Having the same base generator guarantees that the other - // iterator is of the same type and we can downcast. - GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) - << "The program attempted to compare iterators " - << "from different generators." << std::endl; - const Iterator* typed_other = - CheckedDowncastToActualType(&other); - // We must report iterators equal if they both point beyond their - // respective ranges. That can happen in a variety of fashions, - // so we have to consult AtEnd(). - return (AtEnd() && typed_other->AtEnd()) || - ($for j && [[ - - current$(j)_ == typed_other->current$(j)_ -]]); - } - - private: - Iterator(const Iterator& other) - : base_(other.base_), $for j, [[ - - begin$(j)_(other.begin$(j)_), - end$(j)_(other.end$(j)_), - current$(j)_(other.current$(j)_) -]] { - ComputeCurrentValue(); - } - - void ComputeCurrentValue() { - if (!AtEnd()) - current_value_ = ParamType($for j, [[*current$(j)_]]); - } - bool AtEnd() const { - // We must report iterator past the end of the range when either of the - // component iterators has reached the end of its range. - return -$for j || [[ - - current$(j)_ == end$(j)_ -]]; - } - - // No implementation - assignment is unsupported. - void operator=(const Iterator& other); - - const ParamGeneratorInterface* const base_; - // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. - // current[i]_ is the actual traversing iterator. -$for j [[ - - const typename ParamGenerator::iterator begin$(j)_; - const typename ParamGenerator::iterator end$(j)_; - typename ParamGenerator::iterator current$(j)_; -]] - - ParamType current_value_; - }; // class CartesianProductGenerator$i::Iterator - - // No implementation - assignment is unsupported. - void operator=(const CartesianProductGenerator$i& other); - - -$for j [[ - const ParamGenerator g$(j)_; - -]] -}; // class CartesianProductGenerator$i - - -]] - -// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. -// -// Helper classes providing Combine() with polymorphic features. They allow -// casting CartesianProductGeneratorN to ParamGenerator if T is -// convertible to U. -// -$range i 2..maxtuple -$for i [[ -$range j 1..i - -template <$for j, [[class Generator$j]]> -class CartesianProductHolder$i { - public: -CartesianProductHolder$i($for j, [[const Generator$j& g$j]]) - : $for j, [[g$(j)_(g$j)]] {} - template <$for j, [[typename T$j]]> - operator ParamGenerator< ::testing::tuple<$for j, [[T$j]]> >() const { - return ParamGenerator< ::testing::tuple<$for j, [[T$j]]> >( - new CartesianProductGenerator$i<$for j, [[T$j]]>( -$for j,[[ - - static_cast >(g$(j)_) -]])); - } - - private: - // No implementation - assignment is unsupported. - void operator=(const CartesianProductHolder$i& other); - - -$for j [[ - const Generator$j g$(j)_; - -]] -}; // class CartesianProductHolder$i - -]] - -# endif // GTEST_HAS_COMBINE - -} // namespace internal -} // namespace testing - -#endif // GTEST_HAS_PARAM_TEST - -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ diff --git a/cpp/test/include/gtest/internal/gtest-param-util.h b/cpp/test/include/gtest/internal/gtest-param-util.h index 3142f742a0..e900b3ffbf 100644 --- a/cpp/test/include/gtest/internal/gtest-param-util.h +++ b/cpp/test/include/gtest/internal/gtest-param-util.h @@ -26,33 +26,30 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Author: vladl@google.com (Vlad Losev) + // Type and function utilities for implementing parameterized tests. +// GOOGLETEST_CM0001 DO NOT DELETE + #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ #include +#include #include +#include #include +#include #include #include -// scripts/fuse_gtest.py depends on gtest's own header being #included -// *unconditionally*. Therefore these #includes cannot be moved -// inside #if GTEST_HAS_PARAM_TEST. #include "gtest/internal/gtest-internal.h" -#include "gtest/internal/gtest-linked_ptr.h" #include "gtest/internal/gtest-port.h" #include "gtest/gtest-printers.h" -#if GTEST_HAS_PARAM_TEST - namespace testing { - // Input to a parameterized test name generator, describing a test parameter. // Consists of the parameter value and the integer parameter index. template @@ -76,13 +73,14 @@ struct PrintToStringParamName { namespace internal { // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. -// +// Utility Functions + // Outputs a message explaining invalid registration of different -// fixture class for the same test case. This may happen when +// fixture class for the same test suite. This may happen when // TEST_P macro is used to define two tests with the same name // but in different namespaces. -GTEST_API_ void ReportInvalidTestCaseType(const char* test_case_name, - CodeLocation code_location); +GTEST_API_ void ReportInvalidTestSuiteType(const char* test_suite_name, + CodeLocation code_location); template class ParamGeneratorInterface; template class ParamGenerator; @@ -157,7 +155,7 @@ class ParamIterator { private: friend class ParamGenerator; explicit ParamIterator(ParamIteratorInterface* impl) : impl_(impl) {} - scoped_ptr > impl_; + std::unique_ptr > impl_; }; // ParamGeneratorInterface is the binary interface to access generators @@ -196,7 +194,7 @@ class ParamGenerator { iterator end() const { return iterator(impl_->End()); } private: - linked_ptr > impl_; + std::shared_ptr > impl_; }; // Generates values from a range of two comparable values. Can be used to @@ -209,12 +207,12 @@ class RangeGenerator : public ParamGeneratorInterface { RangeGenerator(T begin, T end, IncrementT step) : begin_(begin), end_(end), step_(step), end_index_(CalculateEndIndex(begin, end, step)) {} - virtual ~RangeGenerator() {} + ~RangeGenerator() override {} - virtual ParamIteratorInterface* Begin() const { + ParamIteratorInterface* Begin() const override { return new Iterator(this, begin_, 0, step_); } - virtual ParamIteratorInterface* End() const { + ParamIteratorInterface* End() const override { return new Iterator(this, end_, end_index_, step_); } @@ -224,20 +222,20 @@ class RangeGenerator : public ParamGeneratorInterface { Iterator(const ParamGeneratorInterface* base, T value, int index, IncrementT step) : base_(base), value_(value), index_(index), step_(step) {} - virtual ~Iterator() {} + ~Iterator() override {} - virtual const ParamGeneratorInterface* BaseGenerator() const { + const ParamGeneratorInterface* BaseGenerator() const override { return base_; } - virtual void Advance() { + void Advance() override { value_ = static_cast(value_ + step_); index_++; } - virtual ParamIteratorInterface* Clone() const { + ParamIteratorInterface* Clone() const override { return new Iterator(*this); } - virtual const T* Current() const { return &value_; } - virtual bool Equals(const ParamIteratorInterface& other) const { + const T* Current() const override { return &value_; } + bool Equals(const ParamIteratorInterface& other) const override { // Having the same base generator guarantees that the other // iterator is of the same type and we can downcast. GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) @@ -294,12 +292,12 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface { template ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end) : container_(begin, end) {} - virtual ~ValuesInIteratorRangeGenerator() {} + ~ValuesInIteratorRangeGenerator() override {} - virtual ParamIteratorInterface* Begin() const { + ParamIteratorInterface* Begin() const override { return new Iterator(this, container_.begin()); } - virtual ParamIteratorInterface* End() const { + ParamIteratorInterface* End() const override { return new Iterator(this, container_.end()); } @@ -311,16 +309,16 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface { Iterator(const ParamGeneratorInterface* base, typename ContainerType::const_iterator iterator) : base_(base), iterator_(iterator) {} - virtual ~Iterator() {} + ~Iterator() override {} - virtual const ParamGeneratorInterface* BaseGenerator() const { + const ParamGeneratorInterface* BaseGenerator() const override { return base_; } - virtual void Advance() { + void Advance() override { ++iterator_; value_.reset(); } - virtual ParamIteratorInterface* Clone() const { + ParamIteratorInterface* Clone() const override { return new Iterator(*this); } // We need to use cached value referenced by iterator_ because *iterator_ @@ -330,12 +328,11 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface { // can advance iterator_ beyond the end of the range, and we cannot // detect that fact. The client code, on the other hand, is // responsible for not calling Current() on an out-of-range iterator. - virtual const T* Current() const { - if (value_.get() == NULL) - value_.reset(new T(*iterator_)); + const T* Current() const override { + if (value_.get() == nullptr) value_.reset(new T(*iterator_)); return value_.get(); } - virtual bool Equals(const ParamIteratorInterface& other) const { + bool Equals(const ParamIteratorInterface& other) const override { // Having the same base generator guarantees that the other // iterator is of the same type and we can downcast. GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) @@ -358,9 +355,9 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface { // A cached value of *iterator_. We keep it here to allow access by // pointer in the wrapping iterator's operator->(). // value_ needs to be mutable to be accessed in Current(). - // Use of scoped_ptr helps manage cached value's lifetime, + // Use of std::unique_ptr helps manage cached value's lifetime, // which is bound by the lifespan of the iterator itself. - mutable scoped_ptr value_; + mutable std::unique_ptr value_; }; // class ValuesInIteratorRangeGenerator::Iterator // No implementation - assignment is unsupported. @@ -380,25 +377,12 @@ std::string DefaultParamName(const TestParamInfo& info) { return name_stream.GetString(); } -// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. -// -// Parameterized test name overload helpers, which help the -// INSTANTIATE_TEST_CASE_P macro choose between the default parameterized -// test name generator and user param name generator. -template -ParamNameGenFunctor GetParamNameGen(ParamNameGenFunctor func) { - return func; -} - -template -struct ParamNameGenFunc { - typedef std::string Type(const TestParamInfo&); -}; - -template -typename ParamNameGenFunc::Type *GetParamNameGen() { - return DefaultParamName; +template +void TestNotEmpty() { + static_assert(sizeof(T) == 0, "Empty arguments are not allowed."); } +template +void TestNotEmpty(const T&) {} // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // @@ -410,7 +394,7 @@ class ParameterizedTestFactory : public TestFactoryBase { typedef typename TestClass::ParamType ParamType; explicit ParameterizedTestFactory(ParamType parameter) : parameter_(parameter) {} - virtual Test* CreateTest() { + Test* CreateTest() override { TestClass::SetParam(¶meter_); return new TestClass(); } @@ -438,19 +422,19 @@ class TestMetaFactoryBase { // TestMetaFactory creates test factories for passing into // MakeAndRegisterTestInfo function. Since MakeAndRegisterTestInfo receives // ownership of test factory pointer, same factory object cannot be passed -// into that method twice. But ParameterizedTestCaseInfo is going to call +// into that method twice. But ParameterizedTestSuiteInfo is going to call // it for each Test/Parameter value combination. Thus it needs meta factory // creator class. -template +template class TestMetaFactory - : public TestMetaFactoryBase { + : public TestMetaFactoryBase { public: - typedef typename TestCase::ParamType ParamType; + using ParamType = typename TestSuite::ParamType; TestMetaFactory() {} - virtual TestFactoryBase* CreateTestFactory(ParamType parameter) { - return new ParameterizedTestFactory(parameter); + TestFactoryBase* CreateTestFactory(ParamType parameter) override { + return new ParameterizedTestFactory(parameter); } private: @@ -459,93 +443,93 @@ class TestMetaFactory // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // -// ParameterizedTestCaseInfoBase is a generic interface -// to ParameterizedTestCaseInfo classes. ParameterizedTestCaseInfoBase +// ParameterizedTestSuiteInfoBase is a generic interface +// to ParameterizedTestSuiteInfo classes. ParameterizedTestSuiteInfoBase // accumulates test information provided by TEST_P macro invocations -// and generators provided by INSTANTIATE_TEST_CASE_P macro invocations +// and generators provided by INSTANTIATE_TEST_SUITE_P macro invocations // and uses that information to register all resulting test instances -// in RegisterTests method. The ParameterizeTestCaseRegistry class holds -// a collection of pointers to the ParameterizedTestCaseInfo objects +// in RegisterTests method. The ParameterizeTestSuiteRegistry class holds +// a collection of pointers to the ParameterizedTestSuiteInfo objects // and calls RegisterTests() on each of them when asked. -class ParameterizedTestCaseInfoBase { +class ParameterizedTestSuiteInfoBase { public: - virtual ~ParameterizedTestCaseInfoBase() {} + virtual ~ParameterizedTestSuiteInfoBase() {} - // Base part of test case name for display purposes. - virtual const std::string& GetTestCaseName() const = 0; + // Base part of test suite name for display purposes. + virtual const std::string& GetTestSuiteName() const = 0; // Test case id to verify identity. - virtual TypeId GetTestCaseTypeId() const = 0; + virtual TypeId GetTestSuiteTypeId() const = 0; // UnitTest class invokes this method to register tests in this - // test case right before running them in RUN_ALL_TESTS macro. - // This method should not be called more then once on any single - // instance of a ParameterizedTestCaseInfoBase derived class. + // test suite right before running them in RUN_ALL_TESTS macro. + // This method should not be called more than once on any single + // instance of a ParameterizedTestSuiteInfoBase derived class. virtual void RegisterTests() = 0; protected: - ParameterizedTestCaseInfoBase() {} + ParameterizedTestSuiteInfoBase() {} private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfoBase); + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteInfoBase); }; // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // -// ParameterizedTestCaseInfo accumulates tests obtained from TEST_P -// macro invocations for a particular test case and generators -// obtained from INSTANTIATE_TEST_CASE_P macro invocations for that -// test case. It registers tests with all values generated by all +// ParameterizedTestSuiteInfo accumulates tests obtained from TEST_P +// macro invocations for a particular test suite and generators +// obtained from INSTANTIATE_TEST_SUITE_P macro invocations for that +// test suite. It registers tests with all values generated by all // generators when asked. -template -class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase { +template +class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase { public: // ParamType and GeneratorCreationFunc are private types but are required // for declarations of public methods AddTestPattern() and - // AddTestCaseInstantiation(). - typedef typename TestCase::ParamType ParamType; + // AddTestSuiteInstantiation(). + using ParamType = typename TestSuite::ParamType; // A function that returns an instance of appropriate generator type. typedef ParamGenerator(GeneratorCreationFunc)(); - typedef typename ParamNameGenFunc::Type ParamNameGeneratorFunc; + using ParamNameGeneratorFunc = std::string(const TestParamInfo&); - explicit ParameterizedTestCaseInfo( - const char* name, CodeLocation code_location) - : test_case_name_(name), code_location_(code_location) {} + explicit ParameterizedTestSuiteInfo(const char* name, + CodeLocation code_location) + : test_suite_name_(name), code_location_(code_location) {} // Test case base name for display purposes. - virtual const std::string& GetTestCaseName() const { return test_case_name_; } + const std::string& GetTestSuiteName() const override { + return test_suite_name_; + } // Test case id to verify identity. - virtual TypeId GetTestCaseTypeId() const { return GetTypeId(); } + TypeId GetTestSuiteTypeId() const override { return GetTypeId(); } // TEST_P macro uses AddTestPattern() to record information // about a single test in a LocalTestInfo structure. - // test_case_name is the base name of the test case (without invocation + // test_suite_name is the base name of the test suite (without invocation // prefix). test_base_name is the name of an individual test without // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is - // test case base name and DoBar is test base name. - void AddTestPattern(const char* test_case_name, - const char* test_base_name, + // test suite base name and DoBar is test base name. + void AddTestPattern(const char* test_suite_name, const char* test_base_name, TestMetaFactoryBase* meta_factory) { - tests_.push_back(linked_ptr(new TestInfo(test_case_name, - test_base_name, - meta_factory))); + tests_.push_back(std::shared_ptr( + new TestInfo(test_suite_name, test_base_name, meta_factory))); } - // INSTANTIATE_TEST_CASE_P macro uses AddGenerator() to record information + // INSTANTIATE_TEST_SUITE_P macro uses AddGenerator() to record information // about a generator. - int AddTestCaseInstantiation(const std::string& instantiation_name, - GeneratorCreationFunc* func, - ParamNameGeneratorFunc* name_func, - const char* file, int line) { + int AddTestSuiteInstantiation(const std::string& instantiation_name, + GeneratorCreationFunc* func, + ParamNameGeneratorFunc* name_func, + const char* file, int line) { instantiations_.push_back( InstantiationInfo(instantiation_name, func, name_func, file, line)); return 0; // Return value used only to run this method in namespace scope. } - // UnitTest class invokes this method to register tests in this test case - // test cases right before running tests in RUN_ALL_TESTS macro. - // This method should not be called more then once on any single - // instance of a ParameterizedTestCaseInfoBase derived class. - // UnitTest has a guard to prevent from calling this method more then once. - virtual void RegisterTests() { + // UnitTest class invokes this method to register tests in this test suite + // test suites right before running tests in RUN_ALL_TESTS macro. + // This method should not be called more than once on any single + // instance of a ParameterizedTestSuiteInfoBase derived class. + // UnitTest has a guard to prevent from calling this method more than once. + void RegisterTests() override { for (typename TestInfoContainer::iterator test_it = tests_.begin(); test_it != tests_.end(); ++test_it) { - linked_ptr test_info = *test_it; + std::shared_ptr test_info = *test_it; for (typename InstantiationContainer::iterator gen_it = instantiations_.begin(); gen_it != instantiations_.end(); ++gen_it) { @@ -555,10 +539,10 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase { const char* file = gen_it->file; int line = gen_it->line; - std::string test_case_name; + std::string test_suite_name; if ( !instantiation_name.empty() ) - test_case_name = instantiation_name + "/"; - test_case_name += test_info->test_case_base_name; + test_suite_name = instantiation_name + "/"; + test_suite_name += test_info->test_suite_base_name; size_t i = 0; std::set test_param_names; @@ -583,37 +567,34 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase { test_name_stream << test_info->test_base_name << "/" << param_name; MakeAndRegisterTestInfo( - test_case_name.c_str(), - test_name_stream.GetString().c_str(), - NULL, // No type parameter. - PrintToString(*param_it).c_str(), - code_location_, - GetTestCaseTypeId(), - TestCase::SetUpTestCase, - TestCase::TearDownTestCase, + test_suite_name.c_str(), test_name_stream.GetString().c_str(), + nullptr, // No type parameter. + PrintToString(*param_it).c_str(), code_location_, + GetTestSuiteTypeId(), + SuiteApiResolver::GetSetUpCaseOrSuite(file, line), + SuiteApiResolver::GetTearDownCaseOrSuite(file, line), test_info->test_meta_factory->CreateTestFactory(*param_it)); } // for param_it } // for gen_it } // for test_it - } // RegisterTests + } // RegisterTests private: // LocalTestInfo structure keeps information about a single test registered // with TEST_P macro. struct TestInfo { - TestInfo(const char* a_test_case_base_name, - const char* a_test_base_name, - TestMetaFactoryBase* a_test_meta_factory) : - test_case_base_name(a_test_case_base_name), - test_base_name(a_test_base_name), - test_meta_factory(a_test_meta_factory) {} - - const std::string test_case_base_name; + TestInfo(const char* a_test_suite_base_name, const char* a_test_base_name, + TestMetaFactoryBase* a_test_meta_factory) + : test_suite_base_name(a_test_suite_base_name), + test_base_name(a_test_base_name), + test_meta_factory(a_test_meta_factory) {} + + const std::string test_suite_base_name; const std::string test_base_name; - const scoped_ptr > test_meta_factory; + const std::unique_ptr > test_meta_factory; }; - typedef ::std::vector > TestInfoContainer; - // Records data received from INSTANTIATE_TEST_CASE_P macros: + using TestInfoContainer = ::std::vector >; + // Records data received from INSTANTIATE_TEST_SUITE_P macros: // struct InstantiationInfo { @@ -650,81 +631,250 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase { return true; } - const std::string test_case_name_; + const std::string test_suite_name_; CodeLocation code_location_; TestInfoContainer tests_; InstantiationContainer instantiations_; - GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfo); -}; // class ParameterizedTestCaseInfo + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteInfo); +}; // class ParameterizedTestSuiteInfo + +// Legacy API is deprecated but still available +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ +template +using ParameterizedTestCaseInfo = ParameterizedTestSuiteInfo; +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // -// ParameterizedTestCaseRegistry contains a map of ParameterizedTestCaseInfoBase -// classes accessed by test case names. TEST_P and INSTANTIATE_TEST_CASE_P -// macros use it to locate their corresponding ParameterizedTestCaseInfo -// descriptors. -class ParameterizedTestCaseRegistry { +// ParameterizedTestSuiteRegistry contains a map of +// ParameterizedTestSuiteInfoBase classes accessed by test suite names. TEST_P +// and INSTANTIATE_TEST_SUITE_P macros use it to locate their corresponding +// ParameterizedTestSuiteInfo descriptors. +class ParameterizedTestSuiteRegistry { public: - ParameterizedTestCaseRegistry() {} - ~ParameterizedTestCaseRegistry() { - for (TestCaseInfoContainer::iterator it = test_case_infos_.begin(); - it != test_case_infos_.end(); ++it) { - delete *it; + ParameterizedTestSuiteRegistry() {} + ~ParameterizedTestSuiteRegistry() { + for (auto& test_suite_info : test_suite_infos_) { + delete test_suite_info; } } // Looks up or creates and returns a structure containing information about - // tests and instantiations of a particular test case. - template - ParameterizedTestCaseInfo* GetTestCasePatternHolder( - const char* test_case_name, - CodeLocation code_location) { - ParameterizedTestCaseInfo* typed_test_info = NULL; - for (TestCaseInfoContainer::iterator it = test_case_infos_.begin(); - it != test_case_infos_.end(); ++it) { - if ((*it)->GetTestCaseName() == test_case_name) { - if ((*it)->GetTestCaseTypeId() != GetTypeId()) { + // tests and instantiations of a particular test suite. + template + ParameterizedTestSuiteInfo* GetTestSuitePatternHolder( + const char* test_suite_name, CodeLocation code_location) { + ParameterizedTestSuiteInfo* typed_test_info = nullptr; + for (auto& test_suite_info : test_suite_infos_) { + if (test_suite_info->GetTestSuiteName() == test_suite_name) { + if (test_suite_info->GetTestSuiteTypeId() != GetTypeId()) { // Complain about incorrect usage of Google Test facilities // and terminate the program since we cannot guaranty correct - // test case setup and tear-down in this case. - ReportInvalidTestCaseType(test_case_name, code_location); + // test suite setup and tear-down in this case. + ReportInvalidTestSuiteType(test_suite_name, code_location); posix::Abort(); } else { // At this point we are sure that the object we found is of the same // type we are looking for, so we downcast it to that type // without further checks. typed_test_info = CheckedDowncastToActualType< - ParameterizedTestCaseInfo >(*it); + ParameterizedTestSuiteInfo >(test_suite_info); } break; } } - if (typed_test_info == NULL) { - typed_test_info = new ParameterizedTestCaseInfo( - test_case_name, code_location); - test_case_infos_.push_back(typed_test_info); + if (typed_test_info == nullptr) { + typed_test_info = new ParameterizedTestSuiteInfo( + test_suite_name, code_location); + test_suite_infos_.push_back(typed_test_info); } return typed_test_info; } void RegisterTests() { - for (TestCaseInfoContainer::iterator it = test_case_infos_.begin(); - it != test_case_infos_.end(); ++it) { - (*it)->RegisterTests(); + for (auto& test_suite_info : test_suite_infos_) { + test_suite_info->RegisterTests(); } } +// Legacy API is deprecated but still available +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ + template + ParameterizedTestCaseInfo* GetTestCasePatternHolder( + const char* test_case_name, CodeLocation code_location) { + return GetTestSuitePatternHolder(test_case_name, code_location); + } + +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ private: - typedef ::std::vector TestCaseInfoContainer; + using TestSuiteInfoContainer = ::std::vector; - TestCaseInfoContainer test_case_infos_; + TestSuiteInfoContainer test_suite_infos_; - GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseRegistry); + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteRegistry); }; } // namespace internal -} // namespace testing -#endif // GTEST_HAS_PARAM_TEST +// Forward declarations of ValuesIn(), which is implemented in +// include/gtest/gtest-param-test.h. +template +internal::ParamGenerator ValuesIn( + const Container& container); + +namespace internal { +// Used in the Values() function to provide polymorphic capabilities. + +template +class ValueArray { + public: + ValueArray(Ts... v) : v_{std::move(v)...} {} + + template + operator ParamGenerator() const { // NOLINT + return ValuesIn(MakeVector(MakeIndexSequence())); + } + + private: + template + std::vector MakeVector(IndexSequence) const { + return std::vector{static_cast(v_.template Get())...}; + } + + FlatTuple v_; +}; + +template +class CartesianProductGenerator + : public ParamGeneratorInterface<::std::tuple> { + public: + typedef ::std::tuple ParamType; + + CartesianProductGenerator(const std::tuple...>& g) + : generators_(g) {} + ~CartesianProductGenerator() override {} + + ParamIteratorInterface* Begin() const override { + return new Iterator(this, generators_, false); + } + ParamIteratorInterface* End() const override { + return new Iterator(this, generators_, true); + } + + private: + template + class IteratorImpl; + template + class IteratorImpl> + : public ParamIteratorInterface { + public: + IteratorImpl(const ParamGeneratorInterface* base, + const std::tuple...>& generators, bool is_end) + : base_(base), + begin_(std::get(generators).begin()...), + end_(std::get(generators).end()...), + current_(is_end ? end_ : begin_) { + ComputeCurrentValue(); + } + ~IteratorImpl() override {} + + const ParamGeneratorInterface* BaseGenerator() const override { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + void Advance() override { + assert(!AtEnd()); + // Advance the last iterator. + ++std::get(current_); + // if that reaches end, propagate that up. + AdvanceIfEnd(); + ComputeCurrentValue(); + } + ParamIteratorInterface* Clone() const override { + return new IteratorImpl(*this); + } + + const ParamType* Current() const override { return current_value_.get(); } + + bool Equals(const ParamIteratorInterface& other) const override { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const IteratorImpl* typed_other = + CheckedDowncastToActualType(&other); + + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + if (AtEnd() && typed_other->AtEnd()) return true; + + bool same = true; + bool dummy[] = { + (same = same && std::get(current_) == + std::get(typed_other->current_))...}; + (void)dummy; + return same; + } + + private: + template + void AdvanceIfEnd() { + if (std::get(current_) != std::get(end_)) return; + + bool last = ThisI == 0; + if (last) { + // We are done. Nothing else to propagate. + return; + } + + constexpr size_t NextI = ThisI - (ThisI != 0); + std::get(current_) = std::get(begin_); + ++std::get(current_); + AdvanceIfEnd(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = std::make_shared(*std::get(current_)...); + } + bool AtEnd() const { + bool at_end = false; + bool dummy[] = { + (at_end = at_end || std::get(current_) == std::get(end_))...}; + (void)dummy; + return at_end; + } + + const ParamGeneratorInterface* const base_; + std::tuple::iterator...> begin_; + std::tuple::iterator...> end_; + std::tuple::iterator...> current_; + std::shared_ptr current_value_; + }; + + using Iterator = IteratorImpl::type>; + + std::tuple...> generators_; +}; + +template +class CartesianProductHolder { + public: + CartesianProductHolder(const Gen&... g) : generators_(g...) {} + template + operator ParamGenerator<::std::tuple>() const { + return ParamGenerator<::std::tuple>( + new CartesianProductGenerator(generators_)); + } + + private: + std::tuple generators_; +}; + +} // namespace internal +} // namespace testing #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ diff --git a/cpp/test/include/gtest/internal/gtest-port-arch.h b/cpp/test/include/gtest/internal/gtest-port-arch.h index 74ab949057..d3239b25ba 100644 --- a/cpp/test/include/gtest/internal/gtest-port-arch.h +++ b/cpp/test/include/gtest/internal/gtest-port-arch.h @@ -27,7 +27,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // -// The Google C++ Testing Framework (Google Test) +// The Google C++ Testing and Mocking Framework (Google Test) // // This header file defines the GTEST_OS_* macro. // It is separate from gtest-port.h so that custom/gtest-port.h can include it. @@ -38,14 +38,13 @@ // Determines the platform on which Google Test is compiled. #ifdef __CYGWIN__ # define GTEST_OS_CYGWIN 1 -#elif defined __SYMBIAN32__ -# define GTEST_OS_SYMBIAN 1 +# elif defined(__MINGW__) || defined(__MINGW32__) || defined(__MINGW64__) +# define GTEST_OS_WINDOWS_MINGW 1 +# define GTEST_OS_WINDOWS 1 #elif defined _WIN32 # define GTEST_OS_WINDOWS 1 # ifdef _WIN32_WCE # define GTEST_OS_WINDOWS_MOBILE 1 -# elif defined(__MINGW__) || defined(__MINGW32__) -# define GTEST_OS_WINDOWS_MINGW 1 # elif defined(WINAPI_FAMILY) # include # if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) @@ -54,6 +53,9 @@ # define GTEST_OS_WINDOWS_PHONE 1 # elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) # define GTEST_OS_WINDOWS_RT 1 +# elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE) +# define GTEST_OS_WINDOWS_PHONE 1 +# define GTEST_OS_WINDOWS_TV_TITLE 1 # else // WINAPI_FAMILY defined but no known partition matched. // Default to desktop. @@ -62,13 +64,21 @@ # else # define GTEST_OS_WINDOWS_DESKTOP 1 # endif // _WIN32_WCE +#elif defined __OS2__ +# define GTEST_OS_OS2 1 #elif defined __APPLE__ # define GTEST_OS_MAC 1 # if TARGET_OS_IPHONE # define GTEST_OS_IOS 1 # endif +#elif defined __DragonFly__ +# define GTEST_OS_DRAGONFLY 1 #elif defined __FreeBSD__ # define GTEST_OS_FREEBSD 1 +#elif defined __Fuchsia__ +# define GTEST_OS_FUCHSIA 1 +#elif defined(__GLIBC__) && defined(__FreeBSD_kernel__) +# define GTEST_OS_GNU_KFREEBSD 1 #elif defined __linux__ # define GTEST_OS_LINUX 1 # if defined __ANDROID__ @@ -84,10 +94,18 @@ # define GTEST_OS_HPUX 1 #elif defined __native_client__ # define GTEST_OS_NACL 1 +#elif defined __NetBSD__ +# define GTEST_OS_NETBSD 1 #elif defined __OpenBSD__ # define GTEST_OS_OPENBSD 1 #elif defined __QNX__ # define GTEST_OS_QNX 1 +#elif defined(__HAIKU__) +#define GTEST_OS_HAIKU 1 +#elif defined ESP8266 +#define GTEST_OS_ESP8266 1 +#elif defined ESP32 +#define GTEST_OS_ESP32 1 #endif // __CYGWIN__ #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ diff --git a/cpp/test/include/gtest/internal/gtest-port.h b/cpp/test/include/gtest/internal/gtest-port.h index 5e4f8ba82a..90be25e27e 100644 --- a/cpp/test/include/gtest/internal/gtest-port.h +++ b/cpp/test/include/gtest/internal/gtest-port.h @@ -27,8 +27,6 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // -// Authors: wan@google.com (Zhanyong Wan) -// // Low-level types and utilities for porting Google Test to various // platforms. All macros ending with _ and symbols defined in an // internal namespace are subject to change without notice. Code @@ -40,6 +38,8 @@ // files are expected to #include this. Therefore, it cannot #include // any other Google Test header. +// GOOGLETEST_CM0001 DO NOT DELETE + #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ @@ -72,12 +72,6 @@ // is/isn't available. // GTEST_HAS_EXCEPTIONS - Define it to 1/0 to indicate that exceptions // are enabled. -// GTEST_HAS_GLOBAL_STRING - Define it to 1/0 to indicate that ::string -// is/isn't available (some systems define -// ::string, which is different to std::string). -// GTEST_HAS_GLOBAL_WSTRING - Define it to 1/0 to indicate that ::string -// is/isn't available (some systems define -// ::wstring, which is different to std::wstring). // GTEST_HAS_POSIX_RE - Define it to 1/0 to indicate that POSIX regular // expressions are/aren't available. // GTEST_HAS_PTHREAD - Define it to 1/0 to indicate that @@ -87,8 +81,6 @@ // GTEST_HAS_STD_WSTRING - Define it to 1/0 to indicate that // std::wstring does/doesn't work (Google Test can // be used where std::wstring is unavailable). -// GTEST_HAS_TR1_TUPLE - Define it to 1/0 to indicate tr1::tuple -// is/isn't available. // GTEST_HAS_SEH - Define it to 1/0 to indicate whether the // compiler supports Microsoft's "Structured // Exception Handling". @@ -96,12 +88,6 @@ // - Define it to 1/0 to indicate whether the // platform supports I/O stream redirection using // dup() and dup2(). -// GTEST_USE_OWN_TR1_TUPLE - Define it to 1/0 to indicate whether Google -// Test's own tr1 tuple implementation should be -// used. Unused when the user sets -// GTEST_HAS_TR1_TUPLE to 0. -// GTEST_LANG_CXX11 - Define it to 1/0 to indicate that Google Test -// is building in C++11/C++98 mode. // GTEST_LINKED_AS_SHARED_LIBRARY // - Define to 1 when compiling tests that use // Google Test as a shared library (known as @@ -109,6 +95,12 @@ // GTEST_CREATE_SHARED_LIBRARY // - Define to 1 when compiling Google Test itself // as a shared library. +// GTEST_DEFAULT_DEATH_TEST_STYLE +// - The default value of --gtest_death_test_style. +// The legacy default has been "fast" in the open +// source version since 2008. The recommended value +// is "threadsafe", and can be set in +// custom/gtest-port.h. // Platform-indicating macros // -------------------------- @@ -121,17 +113,22 @@ // // GTEST_OS_AIX - IBM AIX // GTEST_OS_CYGWIN - Cygwin +// GTEST_OS_DRAGONFLY - DragonFlyBSD // GTEST_OS_FREEBSD - FreeBSD +// GTEST_OS_FUCHSIA - Fuchsia +// GTEST_OS_GNU_KFREEBSD - GNU/kFreeBSD +// GTEST_OS_HAIKU - Haiku // GTEST_OS_HPUX - HP-UX // GTEST_OS_LINUX - Linux // GTEST_OS_LINUX_ANDROID - Google Android // GTEST_OS_MAC - Mac OS X // GTEST_OS_IOS - iOS // GTEST_OS_NACL - Google Native Client (NaCl) +// GTEST_OS_NETBSD - NetBSD // GTEST_OS_OPENBSD - OpenBSD +// GTEST_OS_OS2 - OS/2 // GTEST_OS_QNX - QNX // GTEST_OS_SOLARIS - Sun Solaris -// GTEST_OS_SYMBIAN - Symbian // GTEST_OS_WINDOWS - Windows (Desktop, MinGW, or Mobile) // GTEST_OS_WINDOWS_DESKTOP - Windows Desktop // GTEST_OS_WINDOWS_MINGW - MinGW @@ -140,7 +137,7 @@ // GTEST_OS_WINDOWS_RT - Windows Store App/WinRT // GTEST_OS_ZOS - z/OS // -// Among the platforms, Cygwin, Linux, Max OS X, and Windows have the +// Among the platforms, Cygwin, Linux, Mac OS X, and Windows have the // most stable support. Since core members of the Google Test project // don't have access to other platforms, support for them may be less // stable. If you notice any problems on your platform, please notify @@ -166,19 +163,16 @@ // EXPECT_DEATH(DoSomethingDeadly()); // #endif // -// GTEST_HAS_COMBINE - the Combine() function (for value-parameterized -// tests) // GTEST_HAS_DEATH_TEST - death tests -// GTEST_HAS_PARAM_TEST - value-parameterized tests // GTEST_HAS_TYPED_TEST - typed tests // GTEST_HAS_TYPED_TEST_P - type-parameterized tests // GTEST_IS_THREADSAFE - Google Test is thread-safe. +// GOOGLETEST_CM0007 DO NOT DELETE // GTEST_USES_POSIX_RE - enhanced POSIX regex is used. Do not confuse with // GTEST_HAS_POSIX_RE (see above) which users can // define themselves. // GTEST_USES_SIMPLE_RE - our own simple regex is used; -// the above two are mutually exclusive. -// GTEST_CAN_COMPARE_NULL - accepts untyped NULL in EXPECT_EQ(). +// the above RE\b(s) are mutually exclusive. // Misc public macros // ------------------ @@ -204,28 +198,16 @@ // GTEST_INTENTIONAL_CONST_COND_POP_ - finish code section where MSVC C4127 // is suppressed. // -// C++11 feature wrappers: -// -// testing::internal::move - portability wrapper for std::move. -// // Synchronization: // Mutex, MutexLock, ThreadLocal, GetThreadCount() // - synchronization primitives. // -// Template meta programming: -// is_pointer - as in TR1; needed on Symbian and IBM XL C/C++ only. -// IteratorTraits - partial implementation of std::iterator_traits, which -// is not available in libCstd when compiled with Sun C++. -// -// Smart pointers: -// scoped_ptr - as in TR2. -// // Regular expressions: // RE - a simple regular expression class using the POSIX -// Extended Regular Expression syntax on UNIX-like -// platforms, or a reduced regular exception syntax on -// other platforms, including Windows. -// +// Extended Regular Expression syntax on UNIX-like platforms +// GOOGLETEST_CM0008 DO NOT DELETE +// or a reduced regular exception syntax on other +// platforms, including Windows. // Logging: // GTEST_LOG_() - logs messages at the specified severity level. // LogToStderr() - directs all log messages to stderr. @@ -255,12 +237,19 @@ // BoolFromGTestEnv() - parses a bool environment variable. // Int32FromGTestEnv() - parses an Int32 environment variable. // StringFromGTestEnv() - parses a string environment variable. +// +// Deprecation warnings: +// GTEST_INTERNAL_DEPRECATED(message) - attribute marking a function as +// deprecated; calling a marked function +// should generate a compiler warning #include // for isspace, etc #include // for ptrdiff_t -#include #include +#include #include +#include + #ifndef _WIN32_WCE # include # include @@ -271,15 +260,14 @@ # include #endif -#include // NOLINT #include // NOLINT -#include // NOLINT +#include #include // NOLINT -#include +#include #include // NOLINT -#include "gtest/internal/gtest-port-arch.h" #include "gtest/internal/custom/gtest-port.h" +#include "gtest/internal/gtest-port-arch.h" #if !defined(GTEST_DEV_EMAIL_) # define GTEST_DEV_EMAIL_ "googletestframework@@googlegroups.com" @@ -306,85 +294,32 @@ // GTEST_DISABLE_MSC_WARNINGS_PUSH_(4800 4385) // /* code that triggers warnings C4800 and C4385 */ // GTEST_DISABLE_MSC_WARNINGS_POP_() -#if _MSC_VER >= 1500 +#if defined(_MSC_VER) # define GTEST_DISABLE_MSC_WARNINGS_PUSH_(warnings) \ __pragma(warning(push)) \ __pragma(warning(disable: warnings)) # define GTEST_DISABLE_MSC_WARNINGS_POP_() \ __pragma(warning(pop)) #else -// Older versions of MSVC don't have __pragma. +// Not all compilers are MSVC # define GTEST_DISABLE_MSC_WARNINGS_PUSH_(warnings) # define GTEST_DISABLE_MSC_WARNINGS_POP_() #endif -#ifndef GTEST_LANG_CXX11 -// gcc and clang define __GXX_EXPERIMENTAL_CXX0X__ when -// -std={c,gnu}++{0x,11} is passed. The C++11 standard specifies a -// value for __cplusplus, and recent versions of clang, gcc, and -// probably other compilers set that too in C++11 mode. -# if __GXX_EXPERIMENTAL_CXX0X__ || __cplusplus >= 201103L -// Compiling in at least C++11 mode. -# define GTEST_LANG_CXX11 1 -# else -# define GTEST_LANG_CXX11 0 -# endif -#endif - -// Distinct from C++11 language support, some environments don't provide -// proper C++11 library support. Notably, it's possible to build in -// C++11 mode when targeting Mac OS X 10.6, which has an old libstdc++ -// with no C++11 support. -// -// libstdc++ has sufficient C++11 support as of GCC 4.6.0, __GLIBCXX__ -// 20110325, but maintenance releases in the 4.4 and 4.5 series followed -// this date, so check for those versions by their date stamps. -// https://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html#abi.versioning -#if GTEST_LANG_CXX11 && \ - (!defined(__GLIBCXX__) || ( \ - __GLIBCXX__ >= 20110325ul && /* GCC >= 4.6.0 */ \ - /* Blacklist of patch releases of older branches: */ \ - __GLIBCXX__ != 20110416ul && /* GCC 4.4.6 */ \ - __GLIBCXX__ != 20120313ul && /* GCC 4.4.7 */ \ - __GLIBCXX__ != 20110428ul && /* GCC 4.5.3 */ \ - __GLIBCXX__ != 20120702ul)) /* GCC 4.5.4 */ -# define GTEST_STDLIB_CXX11 1 -#endif - -// Only use C++11 library features if the library provides them. -#if GTEST_STDLIB_CXX11 -# define GTEST_HAS_STD_BEGIN_AND_END_ 1 -# define GTEST_HAS_STD_FORWARD_LIST_ 1 -# define GTEST_HAS_STD_FUNCTION_ 1 -# define GTEST_HAS_STD_INITIALIZER_LIST_ 1 -# define GTEST_HAS_STD_MOVE_ 1 -# define GTEST_HAS_STD_SHARED_PTR_ 1 -# define GTEST_HAS_STD_TYPE_TRAITS_ 1 -# define GTEST_HAS_STD_UNIQUE_PTR_ 1 -#endif - -// C++11 specifies that provides std::tuple. -// Some platforms still might not have it, however. -#if GTEST_LANG_CXX11 -# define GTEST_HAS_STD_TUPLE_ 1 -# if defined(__clang__) -// Inspired by http://clang.llvm.org/docs/LanguageExtensions.html#__has_include -# if defined(__has_include) && !__has_include() -# undef GTEST_HAS_STD_TUPLE_ -# endif -# elif defined(_MSC_VER) -// Inspired by boost/config/stdlib/dinkumware.hpp -# if defined(_CPPLIB_VER) && _CPPLIB_VER < 520 -# undef GTEST_HAS_STD_TUPLE_ -# endif -# elif defined(__GLIBCXX__) -// Inspired by boost/config/stdlib/libstdcpp3.hpp, -// http://gcc.gnu.org/gcc-4.2/changes.html and -// http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt01ch01.html#manual.intro.status.standard.200x -# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2) -# undef GTEST_HAS_STD_TUPLE_ -# endif -# endif +// Clang on Windows does not understand MSVC's pragma warning. +// We need clang-specific way to disable function deprecation warning. +#ifdef __clang__ +# define GTEST_DISABLE_MSC_DEPRECATED_PUSH_() \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") \ + _Pragma("clang diagnostic ignored \"-Wdeprecated-implementations\"") +#define GTEST_DISABLE_MSC_DEPRECATED_POP_() \ + _Pragma("clang diagnostic pop") +#else +# define GTEST_DISABLE_MSC_DEPRECATED_PUSH_() \ + GTEST_DISABLE_MSC_WARNINGS_PUSH_(4996) +# define GTEST_DISABLE_MSC_DEPRECATED_POP_() \ + GTEST_DISABLE_MSC_WARNINGS_POP_() #endif // Brings in definitions for functions used in the testing::internal::posix @@ -419,7 +354,8 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION; # include // NOLINT #endif -// Defines this to true iff Google Test can use POSIX regular expressions. +// Defines this to true if and only if Google Test can use POSIX regular +// expressions. #ifndef GTEST_HAS_POSIX_RE # if GTEST_OS_LINUX_ANDROID // On Android, is only available starting with Gingerbread. @@ -459,8 +395,11 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION; #ifndef GTEST_HAS_EXCEPTIONS // The user didn't tell us whether exceptions are enabled, so we need // to figure it out. -# if defined(_MSC_VER) || defined(__BORLANDC__) -// MSVC's and C++Builder's implementations of the STL use the _HAS_EXCEPTIONS +# if defined(_MSC_VER) && defined(_CPPUNWIND) +// MSVC defines _CPPUNWIND to 1 if and only if exceptions are enabled. +# define GTEST_HAS_EXCEPTIONS 1 +# elif defined(__BORLANDC__) +// C++Builder's implementation of the STL uses the _HAS_EXCEPTIONS // macro to enable exceptions, so we'll do the same. // Assumes that exceptions are enabled by default. # ifndef _HAS_EXCEPTIONS @@ -468,16 +407,17 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION; # endif // _HAS_EXCEPTIONS # define GTEST_HAS_EXCEPTIONS _HAS_EXCEPTIONS # elif defined(__clang__) -// clang defines __EXCEPTIONS iff exceptions are enabled before clang 220714, -// but iff cleanups are enabled after that. In Obj-C++ files, there can be -// cleanups for ObjC exceptions which also need cleanups, even if C++ exceptions -// are disabled. clang has __has_feature(cxx_exceptions) which checks for C++ -// exceptions starting at clang r206352, but which checked for cleanups prior to -// that. To reliably check for C++ exception availability with clang, check for +// clang defines __EXCEPTIONS if and only if exceptions are enabled before clang +// 220714, but if and only if cleanups are enabled after that. In Obj-C++ files, +// there can be cleanups for ObjC exceptions which also need cleanups, even if +// C++ exceptions are disabled. clang has __has_feature(cxx_exceptions) which +// checks for C++ exceptions starting at clang r206352, but which checked for +// cleanups prior to that. To reliably check for C++ exception availability with +// clang, check for // __EXCEPTIONS && __has_feature(cxx_exceptions). # define GTEST_HAS_EXCEPTIONS (__EXCEPTIONS && __has_feature(cxx_exceptions)) # elif defined(__GNUC__) && __EXCEPTIONS -// gcc defines __EXCEPTIONS to 1 iff exceptions are enabled. +// gcc defines __EXCEPTIONS to 1 if and only if exceptions are enabled. # define GTEST_HAS_EXCEPTIONS 1 # elif defined(__SUNPRO_CC) // Sun Pro CC supports exceptions. However, there is no compile-time way of @@ -485,7 +425,7 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION; // they are enabled unless the user tells us otherwise. # define GTEST_HAS_EXCEPTIONS 1 # elif defined(__IBMCPP__) && __EXCEPTIONS -// xlC defines __EXCEPTIONS to 1 iff exceptions are enabled. +// xlC defines __EXCEPTIONS to 1 if and only if exceptions are enabled. # define GTEST_HAS_EXCEPTIONS 1 # elif defined(__HP_aCC) // Exception handling is in effect by default in HP aCC compiler. It has to @@ -498,44 +438,18 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION; # endif // defined(_MSC_VER) || defined(__BORLANDC__) #endif // GTEST_HAS_EXCEPTIONS -#if !defined(GTEST_HAS_STD_STRING) -// Even though we don't use this macro any longer, we keep it in case -// some clients still depend on it. -# define GTEST_HAS_STD_STRING 1 -#elif !GTEST_HAS_STD_STRING -// The user told us that ::std::string isn't available. -# error "Google Test cannot be used where ::std::string isn't available." -#endif // !defined(GTEST_HAS_STD_STRING) - -#ifndef GTEST_HAS_GLOBAL_STRING -// The user didn't tell us whether ::string is available, so we need -// to figure it out. - -# define GTEST_HAS_GLOBAL_STRING 0 - -#endif // GTEST_HAS_GLOBAL_STRING - #ifndef GTEST_HAS_STD_WSTRING // The user didn't tell us whether ::std::wstring is available, so we need // to figure it out. -// TODO(wan@google.com): uses autoconf to detect whether ::std::wstring -// is available. - // Cygwin 1.7 and below doesn't support ::std::wstring. // Solaris' libc++ doesn't support it either. Android has // no support for it at least as recent as Froyo (2.2). -# define GTEST_HAS_STD_WSTRING \ - (!(GTEST_OS_LINUX_ANDROID || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS)) +#define GTEST_HAS_STD_WSTRING \ + (!(GTEST_OS_LINUX_ANDROID || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \ + GTEST_OS_HAIKU || GTEST_OS_ESP32 || GTEST_OS_ESP8266)) #endif // GTEST_HAS_STD_WSTRING -#ifndef GTEST_HAS_GLOBAL_WSTRING -// The user didn't tell us whether ::wstring is available, so we need -// to figure it out. -# define GTEST_HAS_GLOBAL_WSTRING \ - (GTEST_HAS_STD_WSTRING && GTEST_HAS_GLOBAL_STRING) -#endif // GTEST_HAS_GLOBAL_WSTRING - // Determines whether RTTI is available. #ifndef GTEST_HAS_RTTI // The user didn't tell us whether RTTI is enabled, so we need to @@ -543,14 +457,15 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION; # ifdef _MSC_VER -# ifdef _CPPRTTI // MSVC defines this macro iff RTTI is enabled. +#ifdef _CPPRTTI // MSVC defines this macro if and only if RTTI is enabled. # define GTEST_HAS_RTTI 1 # else # define GTEST_HAS_RTTI 0 # endif -// Starting with version 4.3.2, gcc defines __GXX_RTTI iff RTTI is enabled. -# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40302) +// Starting with version 4.3.2, gcc defines __GXX_RTTI if and only if RTTI is +// enabled. +# elif defined(__GNUC__) # ifdef __GXX_RTTI // When building against STLport with the Android NDK and with @@ -606,8 +521,11 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION; // // To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0 // to your compiler flags. -# define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX \ - || GTEST_OS_QNX || GTEST_OS_FREEBSD || GTEST_OS_NACL) +#define GTEST_HAS_PTHREAD \ + (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX || GTEST_OS_QNX || \ + GTEST_OS_FREEBSD || GTEST_OS_NACL || GTEST_OS_NETBSD || GTEST_OS_FUCHSIA || \ + GTEST_OS_DRAGONFLY || GTEST_OS_GNU_KFREEBSD || GTEST_OS_OPENBSD || \ + GTEST_OS_HAIKU) #endif // GTEST_HAS_PTHREAD #if GTEST_HAS_PTHREAD @@ -619,138 +537,6 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION; # include // NOLINT #endif -// Determines if hash_map/hash_set are available. -// Only used for testing against those containers. -#if !defined(GTEST_HAS_HASH_MAP_) -# if defined(_MSC_VER) && (_MSC_VER < 1900) -# define GTEST_HAS_HASH_MAP_ 1 // Indicates that hash_map is available. -# define GTEST_HAS_HASH_SET_ 1 // Indicates that hash_set is available. -# endif // _MSC_VER -#endif // !defined(GTEST_HAS_HASH_MAP_) - -// Determines whether Google Test can use tr1/tuple. You can define -// this macro to 0 to prevent Google Test from using tuple (any -// feature depending on tuple with be disabled in this mode). -#ifndef GTEST_HAS_TR1_TUPLE -# if GTEST_OS_LINUX_ANDROID && defined(_STLPORT_MAJOR) -// STLport, provided with the Android NDK, has neither or . -# define GTEST_HAS_TR1_TUPLE 0 -# else -// The user didn't tell us not to do it, so we assume it's OK. -# define GTEST_HAS_TR1_TUPLE 1 -# endif -#endif // GTEST_HAS_TR1_TUPLE - -// Determines whether Google Test's own tr1 tuple implementation -// should be used. -#ifndef GTEST_USE_OWN_TR1_TUPLE -// The user didn't tell us, so we need to figure it out. - -// We use our own TR1 tuple if we aren't sure the user has an -// implementation of it already. At this time, libstdc++ 4.0.0+ and -// MSVC 2010 are the only mainstream standard libraries that come -// with a TR1 tuple implementation. NVIDIA's CUDA NVCC compiler -// pretends to be GCC by defining __GNUC__ and friends, but cannot -// compile GCC's tuple implementation. MSVC 2008 (9.0) provides TR1 -// tuple in a 323 MB Feature Pack download, which we cannot assume the -// user has. QNX's QCC compiler is a modified GCC but it doesn't -// support TR1 tuple. libc++ only provides std::tuple, in C++11 mode, -// and it can be used with some compilers that define __GNUC__. -# if (defined(__GNUC__) && !defined(__CUDACC__) && (GTEST_GCC_VER_ >= 40000) \ - && !GTEST_OS_QNX && !defined(_LIBCPP_VERSION)) || _MSC_VER >= 1600 -# define GTEST_ENV_HAS_TR1_TUPLE_ 1 -# endif - -// C++11 specifies that provides std::tuple. Use that if gtest is used -// in C++11 mode and libstdc++ isn't very old (binaries targeting OS X 10.6 -// can build with clang but need to use gcc4.2's libstdc++). -# if GTEST_LANG_CXX11 && (!defined(__GLIBCXX__) || __GLIBCXX__ > 20110325) -# define GTEST_ENV_HAS_STD_TUPLE_ 1 -# endif - -# if GTEST_ENV_HAS_TR1_TUPLE_ || GTEST_ENV_HAS_STD_TUPLE_ -# define GTEST_USE_OWN_TR1_TUPLE 0 -# else -# define GTEST_USE_OWN_TR1_TUPLE 1 -# endif - -#endif // GTEST_USE_OWN_TR1_TUPLE - -// To avoid conditional compilation everywhere, we make it -// gtest-port.h's responsibility to #include the header implementing -// tuple. -#if GTEST_HAS_STD_TUPLE_ -# include // IWYU pragma: export -# define GTEST_TUPLE_NAMESPACE_ ::std -#endif // GTEST_HAS_STD_TUPLE_ - -// We include tr1::tuple even if std::tuple is available to define printers for -// them. -#if GTEST_HAS_TR1_TUPLE -# ifndef GTEST_TUPLE_NAMESPACE_ -# define GTEST_TUPLE_NAMESPACE_ ::std::tr1 -# endif // GTEST_TUPLE_NAMESPACE_ - -# if GTEST_USE_OWN_TR1_TUPLE -# include "gtest/internal/gtest-tuple.h" // IWYU pragma: export // NOLINT -# elif GTEST_ENV_HAS_STD_TUPLE_ -# include -// C++11 puts its tuple into the ::std namespace rather than -// ::std::tr1. gtest expects tuple to live in ::std::tr1, so put it there. -// This causes undefined behavior, but supported compilers react in -// the way we intend. -namespace std { -namespace tr1 { -using ::std::get; -using ::std::make_tuple; -using ::std::tuple; -using ::std::tuple_element; -using ::std::tuple_size; -} -} - -# elif GTEST_OS_SYMBIAN - -// On Symbian, BOOST_HAS_TR1_TUPLE causes Boost's TR1 tuple library to -// use STLport's tuple implementation, which unfortunately doesn't -// work as the copy of STLport distributed with Symbian is incomplete. -// By making sure BOOST_HAS_TR1_TUPLE is undefined, we force Boost to -// use its own tuple implementation. -# ifdef BOOST_HAS_TR1_TUPLE -# undef BOOST_HAS_TR1_TUPLE -# endif // BOOST_HAS_TR1_TUPLE - -// This prevents , which defines -// BOOST_HAS_TR1_TUPLE, from being #included by Boost's . -# define BOOST_TR1_DETAIL_CONFIG_HPP_INCLUDED -# include // IWYU pragma: export // NOLINT - -# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40000) -// GCC 4.0+ implements tr1/tuple in the header. This does -// not conform to the TR1 spec, which requires the header to be . - -# if !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302 -// Until version 4.3.2, gcc has a bug that causes , -// which is #included by , to not compile when RTTI is -// disabled. _TR1_FUNCTIONAL is the header guard for -// . Hence the following #define is a hack to prevent -// from being included. -# define _TR1_FUNCTIONAL 1 -# include -# undef _TR1_FUNCTIONAL // Allows the user to #include - // if he chooses to. -# else -# include // NOLINT -# endif // !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302 - -# else -// If the compiler is not GCC 4.0+, we assume the user is using a -// spec-conforming TR1 implementation. -# include // IWYU pragma: export // NOLINT -# endif // GTEST_USE_OWN_TR1_TUPLE - -#endif // GTEST_HAS_TR1_TUPLE - // Determines whether clone(2) is supported. // Usually it will only be available on Linux, excluding // Linux on the Itanium architecture. @@ -784,55 +570,42 @@ using ::std::tuple_size; #ifndef GTEST_HAS_STREAM_REDIRECTION // By default, we assume that stream redirection is supported on all // platforms except known mobile ones. -# if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || \ - GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT +#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || \ + GTEST_OS_WINDOWS_RT || GTEST_OS_ESP8266 # define GTEST_HAS_STREAM_REDIRECTION 0 # else # define GTEST_HAS_STREAM_REDIRECTION 1 -# endif // !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_SYMBIAN +# endif // !GTEST_OS_WINDOWS_MOBILE #endif // GTEST_HAS_STREAM_REDIRECTION // Determines whether to support death tests. -// Google Test does not support death tests for VC 7.1 and earlier as -// abort() in a VC 7.1 application compiled as GUI in debug config // pops up a dialog window that cannot be suppressed programmatically. -#if (GTEST_OS_LINUX || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \ - (GTEST_OS_MAC && !GTEST_OS_IOS) || \ - (GTEST_OS_WINDOWS_DESKTOP && _MSC_VER >= 1400) || \ - GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX || GTEST_OS_HPUX || \ - GTEST_OS_OPENBSD || GTEST_OS_QNX || GTEST_OS_FREEBSD) +#if (GTEST_OS_LINUX || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \ + (GTEST_OS_MAC && !GTEST_OS_IOS) || \ + (GTEST_OS_WINDOWS_DESKTOP && _MSC_VER) || GTEST_OS_WINDOWS_MINGW || \ + GTEST_OS_AIX || GTEST_OS_HPUX || GTEST_OS_OPENBSD || GTEST_OS_QNX || \ + GTEST_OS_FREEBSD || GTEST_OS_NETBSD || GTEST_OS_FUCHSIA || \ + GTEST_OS_DRAGONFLY || GTEST_OS_GNU_KFREEBSD || GTEST_OS_HAIKU) # define GTEST_HAS_DEATH_TEST 1 #endif -// We don't support MSVC 7.1 with exceptions disabled now. Therefore -// all the compilers we care about are adequate for supporting -// value-parameterized tests. -#define GTEST_HAS_PARAM_TEST 1 - // Determines whether to support type-driven tests. // Typed tests need and variadic macros, which GCC, VC++ 8.0, // Sun Pro CC, IBM Visual Age, and HP aCC support. -#if defined(__GNUC__) || (_MSC_VER >= 1400) || defined(__SUNPRO_CC) || \ +#if defined(__GNUC__) || defined(_MSC_VER) || defined(__SUNPRO_CC) || \ defined(__IBMCPP__) || defined(__HP_aCC) # define GTEST_HAS_TYPED_TEST 1 # define GTEST_HAS_TYPED_TEST_P 1 #endif -// Determines whether to support Combine(). This only makes sense when -// value-parameterized tests are enabled. The implementation doesn't -// work on Sun Studio since it doesn't understand templated conversion -// operators. -#if GTEST_HAS_PARAM_TEST && GTEST_HAS_TR1_TUPLE && !defined(__SUNPRO_CC) -# define GTEST_HAS_COMBINE 1 -#endif - // Determines whether the system compiler uses UTF-16 for encoding wide strings. #define GTEST_WIDE_STRING_USES_UTF16_ \ - (GTEST_OS_WINDOWS || GTEST_OS_CYGWIN || GTEST_OS_SYMBIAN || GTEST_OS_AIX) + (GTEST_OS_WINDOWS || GTEST_OS_CYGWIN || GTEST_OS_AIX || GTEST_OS_OS2) // Determines whether test results can be streamed to a socket. -#if GTEST_OS_LINUX +#if GTEST_OS_LINUX || GTEST_OS_GNU_KFREEBSD || GTEST_OS_DRAGONFLY || \ + GTEST_OS_FREEBSD || GTEST_OS_NETBSD || GTEST_OS_OPENBSD # define GTEST_CAN_STREAM_RESULTS_ 1 #endif @@ -875,7 +648,7 @@ using ::std::tuple_size; #endif // Use this annotation before a function that takes a printf format string. -#if defined(__GNUC__) && !defined(COMPILER_ICC) +#if (defined(__GNUC__) || defined(__clang__)) && !defined(COMPILER_ICC) # if defined(__MINGW_PRINTF_FORMAT) // MinGW has two different printf implementations. Ensure the format macro // matches the selected implementation. See @@ -891,15 +664,16 @@ using ::std::tuple_size; # define GTEST_ATTRIBUTE_PRINTF_(string_index, first_to_check) #endif + // A macro to disallow operator= // This should be used in the private: declarations for a class. -#define GTEST_DISALLOW_ASSIGN_(type)\ - void operator=(type const &) +#define GTEST_DISALLOW_ASSIGN_(type) \ + void operator=(type const &) = delete // A macro to disallow copy constructor and operator= // This should be used in the private: declarations for a class. -#define GTEST_DISALLOW_COPY_AND_ASSIGN_(type)\ - type(type const &);\ +#define GTEST_DISALLOW_COPY_AND_ASSIGN_(type) \ + type(type const &) = delete; \ GTEST_DISALLOW_ASSIGN_(type) // Tell the compiler to warn about unused return values for functions declared @@ -907,11 +681,11 @@ using ::std::tuple_size; // following the argument list: // // Sprocket* AllocateSprocket() GTEST_MUST_USE_RESULT_; -#if defined(__GNUC__) && (GTEST_GCC_VER_ >= 30400) && !defined(COMPILER_ICC) +#if defined(__GNUC__) && !defined(COMPILER_ICC) # define GTEST_MUST_USE_RESULT_ __attribute__ ((warn_unused_result)) #else # define GTEST_MUST_USE_RESULT_ -#endif // __GNUC__ && (GTEST_GCC_VER_ >= 30400) && !COMPILER_ICC +#endif // __GNUC__ && !COMPILER_ICC // MS C++ compiler emits warning when a conditional expression is compile time // constant. In some contexts this warning is false positive and needs to be @@ -940,13 +714,17 @@ using ::std::tuple_size; # define GTEST_HAS_SEH 0 # endif -#define GTEST_IS_THREADSAFE \ - (GTEST_HAS_MUTEX_AND_THREAD_LOCAL_ \ - || (GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT) \ - || GTEST_HAS_PTHREAD) - #endif // GTEST_HAS_SEH +#ifndef GTEST_IS_THREADSAFE + +#define GTEST_IS_THREADSAFE \ + (GTEST_HAS_MUTEX_AND_THREAD_LOCAL_ || \ + (GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT) || \ + GTEST_HAS_PTHREAD) + +#endif // GTEST_IS_THREADSAFE + // GTEST_API_ qualifies all symbols that must be exported. The definitions below // are guarded by #ifndef to give embedders a chance to define GTEST_API_ in // gtest/internal/custom/gtest-port.h @@ -960,13 +738,17 @@ using ::std::tuple_size; # endif #elif __GNUC__ >= 4 || defined(__clang__) # define GTEST_API_ __attribute__((visibility ("default"))) -#endif // _MSC_VER +#endif // _MSC_VER -#endif // GTEST_API_ +#endif // GTEST_API_ #ifndef GTEST_API_ # define GTEST_API_ -#endif // GTEST_API_ +#endif // GTEST_API_ + +#ifndef GTEST_DEFAULT_DEATH_TEST_STYLE +# define GTEST_DEFAULT_DEATH_TEST_STYLE "fast" +#endif // GTEST_DEFAULT_DEATH_TEST_STYLE #ifdef __GNUC__ // Ask the compiler to never inline a given function. @@ -976,10 +758,12 @@ using ::std::tuple_size; #endif // _LIBCPP_VERSION is defined by the libc++ library from the LLVM project. -#if defined(__GLIBCXX__) || defined(_LIBCPP_VERSION) -# define GTEST_HAS_CXXABI_H_ 1 -#else -# define GTEST_HAS_CXXABI_H_ 0 +#if !defined(GTEST_HAS_CXXABI_H_) +# if defined(__GLIBCXX__) || (defined(_LIBCPP_VERSION) && !defined(_MSC_VER)) +# define GTEST_HAS_CXXABI_H_ 1 +# else +# define GTEST_HAS_CXXABI_H_ 0 +# endif #endif // A function level attribute to disable checking for use of uninitialized @@ -1007,6 +791,18 @@ using ::std::tuple_size; # define GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ #endif // __clang__ +// A function level attribute to disable HWAddressSanitizer instrumentation. +#if defined(__clang__) +# if __has_feature(hwaddress_sanitizer) +# define GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_ \ + __attribute__((no_sanitize("hwaddress"))) +# else +# define GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_ +# endif // __has_feature(hwaddress_sanitizer) +#else +# define GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_ +#endif // __clang__ + // A function level attribute to disable ThreadSanitizer instrumentation. #if defined(__clang__) # if __has_feature(thread_sanitizer) @@ -1023,16 +819,13 @@ namespace testing { class Message; -#if defined(GTEST_TUPLE_NAMESPACE_) -// Import tuple and friends into the ::testing namespace. -// It is part of our interface, having them in ::testing allows us to change -// their types as needed. -using GTEST_TUPLE_NAMESPACE_::get; -using GTEST_TUPLE_NAMESPACE_::make_tuple; -using GTEST_TUPLE_NAMESPACE_::tuple; -using GTEST_TUPLE_NAMESPACE_::tuple_size; -using GTEST_TUPLE_NAMESPACE_::tuple_element; -#endif // defined(GTEST_TUPLE_NAMESPACE_) +// Legacy imports for backwards compatibility. +// New code should use std:: names directly. +using std::get; +using std::make_tuple; +using std::tuple; +using std::tuple_element; +using std::tuple_size; namespace internal { @@ -1041,150 +834,27 @@ namespace internal { // Secret object, which is what we want. class Secret; -// The GTEST_COMPILE_ASSERT_ macro can be used to verify that a compile time -// expression is true. For example, you could use it to verify the -// size of a static array: +// The GTEST_COMPILE_ASSERT_ is a legacy macro used to verify that a compile +// time expression is true (in new code, use static_assert instead). For +// example, you could use it to verify the size of a static array: // // GTEST_COMPILE_ASSERT_(GTEST_ARRAY_SIZE_(names) == NUM_NAMES, // names_incorrect_size); // -// or to make sure a struct is smaller than a certain size: -// -// GTEST_COMPILE_ASSERT_(sizeof(foo) < 128, foo_too_large); -// -// The second argument to the macro is the name of the variable. If -// the expression is false, most compilers will issue a warning/error -// containing the name of the variable. - -#if GTEST_LANG_CXX11 -# define GTEST_COMPILE_ASSERT_(expr, msg) static_assert(expr, #msg) -#else // !GTEST_LANG_CXX11 -template - struct CompileAssert { -}; - -# define GTEST_COMPILE_ASSERT_(expr, msg) \ - typedef ::testing::internal::CompileAssert<(static_cast(expr))> \ - msg[static_cast(expr) ? 1 : -1] GTEST_ATTRIBUTE_UNUSED_ -#endif // !GTEST_LANG_CXX11 - -// Implementation details of GTEST_COMPILE_ASSERT_: -// -// (In C++11, we simply use static_assert instead of the following) -// -// - GTEST_COMPILE_ASSERT_ works by defining an array type that has -1 -// elements (and thus is invalid) when the expression is false. -// -// - The simpler definition -// -// #define GTEST_COMPILE_ASSERT_(expr, msg) typedef char msg[(expr) ? 1 : -1] -// -// does not work, as gcc supports variable-length arrays whose sizes -// are determined at run-time (this is gcc's extension and not part -// of the C++ standard). As a result, gcc fails to reject the -// following code with the simple definition: -// -// int foo; -// GTEST_COMPILE_ASSERT_(foo, msg); // not supposed to compile as foo is -// // not a compile-time constant. -// -// - By using the type CompileAssert<(bool(expr))>, we ensures that -// expr is a compile-time constant. (Template arguments must be -// determined at compile-time.) -// -// - The outter parentheses in CompileAssert<(bool(expr))> are necessary -// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written -// -// CompileAssert -// -// instead, these compilers will refuse to compile -// -// GTEST_COMPILE_ASSERT_(5 > 0, some_message); -// -// (They seem to think the ">" in "5 > 0" marks the end of the -// template argument list.) -// -// - The array size is (bool(expr) ? 1 : -1), instead of simply -// -// ((expr) ? 1 : -1). -// -// This is to avoid running into a bug in MS VC 7.1, which -// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1. - -// StaticAssertTypeEqHelper is used by StaticAssertTypeEq defined in gtest.h. -// -// This template is declared, but intentionally undefined. -template -struct StaticAssertTypeEqHelper; - -template -struct StaticAssertTypeEqHelper { - enum { value = true }; -}; - -// Evaluates to the number of elements in 'array'. -#define GTEST_ARRAY_SIZE_(array) (sizeof(array) / sizeof(array[0])) - -#if GTEST_HAS_GLOBAL_STRING -typedef ::string string; -#else -typedef ::std::string string; -#endif // GTEST_HAS_GLOBAL_STRING - -#if GTEST_HAS_GLOBAL_WSTRING -typedef ::wstring wstring; -#elif GTEST_HAS_STD_WSTRING -typedef ::std::wstring wstring; -#endif // GTEST_HAS_GLOBAL_WSTRING +// The second argument to the macro must be a valid C++ identifier. If the +// expression is false, compiler will issue an error containing this identifier. +#define GTEST_COMPILE_ASSERT_(expr, msg) static_assert(expr, #msg) // A helper for suppressing warnings on constant condition. It just // returns 'condition'. GTEST_API_ bool IsTrue(bool condition); -// Defines scoped_ptr. - -// This implementation of scoped_ptr is PARTIAL - it only contains -// enough stuff to satisfy Google Test's need. -template -class scoped_ptr { - public: - typedef T element_type; - - explicit scoped_ptr(T* p = NULL) : ptr_(p) {} - ~scoped_ptr() { reset(); } - - T& operator*() const { return *ptr_; } - T* operator->() const { return ptr_; } - T* get() const { return ptr_; } - - T* release() { - T* const ptr = ptr_; - ptr_ = NULL; - return ptr; - } - - void reset(T* p = NULL) { - if (p != ptr_) { - if (IsTrue(sizeof(T) > 0)) { // Makes sure T is a complete type. - delete ptr_; - } - ptr_ = p; - } - } - - friend void swap(scoped_ptr& a, scoped_ptr& b) { - using std::swap; - swap(a.ptr_, b.ptr_); - } - - private: - T* ptr_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(scoped_ptr); -}; - // Defines RE. +#if GTEST_USES_PCRE +// if used, PCRE is injected by custom/gtest-port.h +#elif GTEST_USES_POSIX_RE || GTEST_USES_SIMPLE_RE + // A simple C++ wrapper for . It uses the POSIX Extended // Regular Expression syntax. class GTEST_API_ RE { @@ -1196,25 +866,16 @@ class GTEST_API_ RE { // Constructs an RE from a string. RE(const ::std::string& regex) { Init(regex.c_str()); } // NOLINT -#if GTEST_HAS_GLOBAL_STRING - - RE(const ::string& regex) { Init(regex.c_str()); } // NOLINT - -#endif // GTEST_HAS_GLOBAL_STRING - RE(const char* regex) { Init(regex); } // NOLINT ~RE(); // Returns the string representation of the regex. const char* pattern() const { return pattern_; } - // FullMatch(str, re) returns true iff regular expression re matches - // the entire str. - // PartialMatch(str, re) returns true iff regular expression re + // FullMatch(str, re) returns true if and only if regular expression re + // matches the entire str. + // PartialMatch(str, re) returns true if and only if regular expression re // matches a substring of str (including str itself). - // - // TODO(wan@google.com): make FullMatch() and PartialMatch() work - // when str contains NUL characters. static bool FullMatch(const ::std::string& str, const RE& re) { return FullMatch(str.c_str(), re); } @@ -1222,43 +883,30 @@ class GTEST_API_ RE { return PartialMatch(str.c_str(), re); } -#if GTEST_HAS_GLOBAL_STRING - - static bool FullMatch(const ::string& str, const RE& re) { - return FullMatch(str.c_str(), re); - } - static bool PartialMatch(const ::string& str, const RE& re) { - return PartialMatch(str.c_str(), re); - } - -#endif // GTEST_HAS_GLOBAL_STRING - static bool FullMatch(const char* str, const RE& re); static bool PartialMatch(const char* str, const RE& re); private: void Init(const char* regex); - - // We use a const char* instead of an std::string, as Google Test used to be - // used where std::string is not available. TODO(wan@google.com): change to - // std::string. const char* pattern_; bool is_valid_; -#if GTEST_USES_POSIX_RE +# if GTEST_USES_POSIX_RE regex_t full_regex_; // For FullMatch(). regex_t partial_regex_; // For PartialMatch(). -#else // GTEST_USES_SIMPLE_RE +# else // GTEST_USES_SIMPLE_RE const char* full_pattern_; // For FullMatch(); -#endif +# endif GTEST_DISALLOW_ASSIGN_(RE); }; +#endif // GTEST_USES_PCRE + // Formats a source file path and a line number as they would appear // in an error message from the compiler used to compile this code. GTEST_API_ ::std::string FormatFileLocation(const char* file, int line); @@ -1307,7 +955,7 @@ class GTEST_API_ GTestLog { __FILE__, __LINE__).GetStream() inline void LogToStderr() {} -inline void FlushInfoLog() { fflush(NULL); } +inline void FlushInfoLog() { fflush(nullptr); } #endif // !defined(GTEST_LOG_) @@ -1344,14 +992,25 @@ inline void FlushInfoLog() { fflush(NULL); } GTEST_LOG_(FATAL) << #posix_call << "failed with error " \ << gtest_error -#if GTEST_HAS_STD_MOVE_ -using std::move; -#else // GTEST_HAS_STD_MOVE_ +// Transforms "T" into "const T&" according to standard reference collapsing +// rules (this is only needed as a backport for C++98 compilers that do not +// support reference collapsing). Specifically, it transforms: +// +// char ==> const char& +// const char ==> const char& +// char& ==> char& +// const char& ==> const char& +// +// Note that the non-const reference will not have "const" added. This is +// standard, and necessary so that "T" can always bind to "const T&". template -const T& move(const T& t) { - return t; -} -#endif // GTEST_HAS_STD_MOVE_ +struct ConstRef { typedef const T& type; }; +template +struct ConstRef { typedef T& type; }; + +// The argument T must depend on some template parameters. +#define GTEST_REFERENCE_TO_CONST_(T) \ + typename ::testing::internal::ConstRef::type // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // @@ -1406,13 +1065,13 @@ inline To DownCast_(From* f) { // so we only accept pointers GTEST_INTENTIONAL_CONST_COND_PUSH_() if (false) { GTEST_INTENTIONAL_CONST_COND_POP_() - const To to = NULL; - ::testing::internal::ImplicitCast_(to); + const To to = nullptr; + ::testing::internal::ImplicitCast_(to); } #if GTEST_HAS_RTTI // RTTI: debug mode only! - GTEST_CHECK_(f == NULL || dynamic_cast(f) != NULL); + GTEST_CHECK_(f == nullptr || dynamic_cast(f) != nullptr); #endif return static_cast(f); } @@ -1451,7 +1110,6 @@ GTEST_API_ void CaptureStderr(); GTEST_API_ std::string GetCapturedStderr(); #endif // GTEST_HAS_STREAM_REDIRECTION - // Returns the size (in bytes) of a file. GTEST_API_ size_t GetFileSize(FILE* file); @@ -1459,14 +1117,15 @@ GTEST_API_ size_t GetFileSize(FILE* file); GTEST_API_ std::string ReadEntireFile(FILE* file); // All command line arguments. -GTEST_API_ const ::std::vector& GetArgvs(); +GTEST_API_ std::vector GetArgvs(); #if GTEST_HAS_DEATH_TEST -const ::std::vector& GetInjectableArgvs(); -void SetInjectableArgvs(const ::std::vector* - new_argvs); - +std::vector GetInjectableArgvs(); +// Deprecated: pass the args vector by value instead. +void SetInjectableArgvs(const std::vector* new_argvs); +void SetInjectableArgvs(const std::vector& new_argvs); +void ClearInjectableArgvs(); #endif // GTEST_HAS_DEATH_TEST @@ -1481,7 +1140,7 @@ inline void SleepMilliseconds(int n) { 0, // 0 seconds. n * 1000L * 1000L, // And n ms. }; - nanosleep(&time, NULL); + nanosleep(&time, nullptr); } # endif // GTEST_HAS_PTHREAD @@ -1499,7 +1158,7 @@ inline void SleepMilliseconds(int n) { class Notification { public: Notification() : notified_(false) { - GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL)); + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, nullptr)); } ~Notification() { pthread_mutex_destroy(&mutex_); @@ -1557,7 +1216,8 @@ class GTEST_API_ AutoHandle { void Reset(Handle handle); private: - // Returns true iff the handle is a valid handle object that can be closed. + // Returns true if and only if the handle is a valid handle object that can be + // closed. bool IsCloseable() const; Handle handle_; @@ -1608,7 +1268,7 @@ class ThreadWithParamBase { // pass into pthread_create(). extern "C" inline void* ThreadFuncWithCLinkage(void* thread) { static_cast(thread)->Run(); - return NULL; + return nullptr; } // Helper class for testing Google Test's multi-threading constructs. @@ -1637,20 +1297,19 @@ class ThreadWithParam : public ThreadWithParamBase { // The thread can be created only after all fields except thread_ // have been initialized. GTEST_CHECK_POSIX_SUCCESS_( - pthread_create(&thread_, 0, &ThreadFuncWithCLinkage, base)); + pthread_create(&thread_, nullptr, &ThreadFuncWithCLinkage, base)); } - ~ThreadWithParam() { Join(); } + ~ThreadWithParam() override { Join(); } void Join() { if (!finished_) { - GTEST_CHECK_POSIX_SUCCESS_(pthread_join(thread_, 0)); + GTEST_CHECK_POSIX_SUCCESS_(pthread_join(thread_, nullptr)); finished_ = true; } } - virtual void Run() { - if (thread_can_start_ != NULL) - thread_can_start_->WaitForNotification(); + void Run() override { + if (thread_can_start_ != nullptr) thread_can_start_->WaitForNotification(); func_(param_); } @@ -1660,7 +1319,8 @@ class ThreadWithParam : public ThreadWithParamBase { // When non-NULL, used to block execution until the controller thread // notifies. Notification* const thread_can_start_; - bool finished_; // true iff we know that the thread function has finished. + bool finished_; // true if and only if we know that the thread function has + // finished. pthread_t thread_; // The native thread object. GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam); @@ -1716,7 +1376,7 @@ class GTEST_API_ Mutex { // Initializes owner_thread_id_ and critical_section_ in static mutexes. void ThreadSafeLazyInit(); - // Per http://blogs.msdn.com/b/oldnewthing/archive/2004/02/23/78395.aspx, + // Per https://blogs.msdn.microsoft.com/oldnewthing/20040223-00/?p=40503, // we assume that 0 is an invalid value for thread IDs. unsigned int owner_thread_id_; @@ -1925,7 +1585,7 @@ class ThreadLocal : public ThreadLocalBase { class DefaultValueHolderFactory : public ValueHolderFactory { public: DefaultValueHolderFactory() {} - virtual ValueHolder* MakeNewHolder() const { return new ValueHolder(); } + ValueHolder* MakeNewHolder() const override { return new ValueHolder(); } private: GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultValueHolderFactory); @@ -1934,7 +1594,7 @@ class ThreadLocal : public ThreadLocalBase { class InstanceValueHolderFactory : public ValueHolderFactory { public: explicit InstanceValueHolderFactory(const T& value) : value_(value) {} - virtual ValueHolder* MakeNewHolder() const { + ValueHolder* MakeNewHolder() const override { return new ValueHolder(value_); } @@ -1944,7 +1604,7 @@ class ThreadLocal : public ThreadLocalBase { GTEST_DISALLOW_COPY_AND_ASSIGN_(InstanceValueHolderFactory); }; - scoped_ptr default_factory_; + std::unique_ptr default_factory_; GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal); }; @@ -2000,15 +1660,20 @@ class MutexBase { extern ::testing::internal::MutexBase mutex // Defines and statically (i.e. at link time) initializes a static mutex. -# define GTEST_DEFINE_STATIC_MUTEX_(mutex) \ - ::testing::internal::MutexBase mutex = { PTHREAD_MUTEX_INITIALIZER, false, pthread_t() } +// The initialization list here does not explicitly initialize each field, +// instead relying on default initialization for the unspecified fields. In +// particular, the owner_ field (a pthread_t) is not explicitly initialized. +// This allows initialization to work whether pthread_t is a scalar or struct. +// The flag -Wmissing-field-initializers must not be specified for this to work. +#define GTEST_DEFINE_STATIC_MUTEX_(mutex) \ + ::testing::internal::MutexBase mutex = {PTHREAD_MUTEX_INITIALIZER, false, 0} // The Mutex class can only be used for mutexes created at runtime. It // shares its API with MutexBase otherwise. class Mutex : public MutexBase { public: Mutex() { - GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL)); + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, nullptr)); has_owner_ = false; } ~Mutex() { @@ -2058,7 +1723,7 @@ extern "C" inline void DeleteThreadLocalValue(void* value_holder) { // Implements thread-local storage on pthreads-based systems. template -class ThreadLocal { +class GTEST_API_ ThreadLocal { public: ThreadLocal() : key_(CreateKey()), default_factory_(new DefaultValueHolderFactory()) {} @@ -2106,7 +1771,7 @@ class ThreadLocal { T* GetOrCreateValue() const { ThreadLocalValueHolderBase* const holder = static_cast(pthread_getspecific(key_)); - if (holder != NULL) { + if (holder != nullptr) { return CheckedDowncastToActualType(holder)->pointer(); } @@ -2129,7 +1794,7 @@ class ThreadLocal { class DefaultValueHolderFactory : public ValueHolderFactory { public: DefaultValueHolderFactory() {} - virtual ValueHolder* MakeNewHolder() const { return new ValueHolder(); } + ValueHolder* MakeNewHolder() const override { return new ValueHolder(); } private: GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultValueHolderFactory); @@ -2138,7 +1803,7 @@ class ThreadLocal { class InstanceValueHolderFactory : public ValueHolderFactory { public: explicit InstanceValueHolderFactory(const T& value) : value_(value) {} - virtual ValueHolder* MakeNewHolder() const { + ValueHolder* MakeNewHolder() const override { return new ValueHolder(value_); } @@ -2150,7 +1815,7 @@ class ThreadLocal { // A key pthreads uses for looking up per-thread values. const pthread_key_t key_; - scoped_ptr default_factory_; + std::unique_ptr default_factory_; GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal); }; @@ -2190,7 +1855,7 @@ class GTestMutexLock { typedef GTestMutexLock MutexLock; template -class ThreadLocal { +class GTEST_API_ ThreadLocal { public: ThreadLocal() : value_() {} explicit ThreadLocal(const T& value) : value_(value) {} @@ -2208,59 +1873,6 @@ class ThreadLocal { // we cannot detect it. GTEST_API_ size_t GetThreadCount(); -// Passing non-POD classes through ellipsis (...) crashes the ARM -// compiler and generates a warning in Sun Studio. The Nokia Symbian -// and the IBM XL C/C++ compiler try to instantiate a copy constructor -// for objects passed through ellipsis (...), failing for uncopyable -// objects. We define this to ensure that only POD is passed through -// ellipsis on these systems. -#if defined(__SYMBIAN32__) || defined(__IBMCPP__) || defined(__SUNPRO_CC) -// We lose support for NULL detection where the compiler doesn't like -// passing non-POD classes through ellipsis (...). -# define GTEST_ELLIPSIS_NEEDS_POD_ 1 -#else -# define GTEST_CAN_COMPARE_NULL 1 -#endif - -// The Nokia Symbian and IBM XL C/C++ compilers cannot decide between -// const T& and const T* in a function template. These compilers -// _can_ decide between class template specializations for T and T*, -// so a tr1::type_traits-like is_pointer works. -#if defined(__SYMBIAN32__) || defined(__IBMCPP__) -# define GTEST_NEEDS_IS_POINTER_ 1 -#endif - -template -struct bool_constant { - typedef bool_constant type; - static const bool value = bool_value; -}; -template const bool bool_constant::value; - -typedef bool_constant false_type; -typedef bool_constant true_type; - -template -struct is_pointer : public false_type {}; - -template -struct is_pointer : public true_type {}; - -template -struct IteratorTraits { - typedef typename Iterator::value_type value_type; -}; - -template -struct IteratorTraits { - typedef T value_type; -}; - -template -struct IteratorTraits { - typedef T value_type; -}; - #if GTEST_OS_WINDOWS # define GTEST_PATH_SEP_ "\\" # define GTEST_HAS_ALT_PATH_SEP_ 1 @@ -2364,6 +1976,22 @@ inline bool IsDir(const StatStruct& st) { } # endif // GTEST_OS_WINDOWS_MOBILE +#elif GTEST_OS_ESP8266 +typedef struct stat StatStruct; + +inline int FileNo(FILE* file) { return fileno(file); } +inline int IsATTY(int fd) { return isatty(fd); } +inline int Stat(const char* path, StatStruct* buf) { + // stat function not implemented on ESP8266 + return 0; +} +inline int StrCaseCmp(const char* s1, const char* s2) { + return strcasecmp(s1, s2); +} +inline char* StrDup(const char* src) { return strdup(src); } +inline int RmDir(const char* dir) { return rmdir(dir); } +inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); } + #else typedef struct stat StatStruct; @@ -2382,11 +2010,7 @@ inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); } // Functions deprecated by MSVC 8.0. -GTEST_DISABLE_MSC_WARNINGS_PUSH_(4996 /* deprecated function */) - -inline const char* StrNCpy(char* dest, const char* src, size_t n) { - return strncpy(dest, src, n); -} +GTEST_DISABLE_MSC_DEPRECATED_PUSH_() // ChDir(), FReopen(), FDOpen(), Read(), Write(), Close(), and // StrError() aren't needed on Windows CE at this time and thus not @@ -2416,29 +2040,30 @@ inline int Close(int fd) { return close(fd); } inline const char* StrError(int errnum) { return strerror(errnum); } #endif inline const char* GetEnv(const char* name) { -#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE | GTEST_OS_WINDOWS_RT - // We are on Windows CE, which has no environment variables. +#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || \ + GTEST_OS_WINDOWS_RT || GTEST_OS_ESP8266 + // We are on an embedded platform, which has no environment variables. static_cast(name); // To prevent 'unused argument' warning. - return NULL; + return nullptr; #elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9) // Environment variables which we programmatically clear will be set to the // empty string rather than unset (NULL). Handle that case. const char* const env = getenv(name); - return (env != NULL && env[0] != '\0') ? env : NULL; + return (env != nullptr && env[0] != '\0') ? env : nullptr; #else return getenv(name); #endif } -GTEST_DISABLE_MSC_WARNINGS_POP_() +GTEST_DISABLE_MSC_DEPRECATED_POP_() #if GTEST_OS_WINDOWS_MOBILE // Windows CE has no C library. The abort() function is used in // several places in Google Test. This implementation provides a reasonable // imitation of standard behaviour. -void Abort(); +[[noreturn]] void Abort(); #else -inline void Abort() { abort(); } +[[noreturn]] inline void Abort() { abort(); } #endif // GTEST_OS_WINDOWS_MOBILE } // namespace posix @@ -2448,13 +2073,12 @@ inline void Abort() { abort(); } // MSVC-based platforms. We map the GTEST_SNPRINTF_ macro to the appropriate // function in order to achieve that. We use macro definition here because // snprintf is a variadic function. -#if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE +#if _MSC_VER && !GTEST_OS_WINDOWS_MOBILE // MSVC 2005 and above support variadic macros. # define GTEST_SNPRINTF_(buffer, size, format, ...) \ _snprintf_s(buffer, size, size, format, __VA_ARGS__) #elif defined(_MSC_VER) -// Windows CE does not define _snprintf_s and MSVC prior to 2005 doesn't -// complain about _snprintf. +// Windows CE does not define _snprintf_s # define GTEST_SNPRINTF_ _snprintf #else # define GTEST_SNPRINTF_ snprintf @@ -2546,15 +2170,15 @@ typedef TypeWithSize<8>::Int TimeInMillis; // Represents time in milliseconds. # define GTEST_DECLARE_bool_(name) GTEST_API_ extern bool GTEST_FLAG(name) # define GTEST_DECLARE_int32_(name) \ GTEST_API_ extern ::testing::internal::Int32 GTEST_FLAG(name) -#define GTEST_DECLARE_string_(name) \ +# define GTEST_DECLARE_string_(name) \ GTEST_API_ extern ::std::string GTEST_FLAG(name) // Macros for defining flags. -#define GTEST_DEFINE_bool_(name, default_val, doc) \ +# define GTEST_DEFINE_bool_(name, default_val, doc) \ GTEST_API_ bool GTEST_FLAG(name) = (default_val) -#define GTEST_DEFINE_int32_(name, default_val, doc) \ +# define GTEST_DEFINE_int32_(name, default_val, doc) \ GTEST_API_ ::testing::internal::Int32 GTEST_FLAG(name) = (default_val) -#define GTEST_DEFINE_string_(name, default_val, doc) \ +# define GTEST_DEFINE_string_(name, default_val, doc) \ GTEST_API_ ::std::string GTEST_FLAG(name) = (default_val) #endif // !defined(GTEST_DECLARE_bool_) @@ -2568,23 +2192,36 @@ typedef TypeWithSize<8>::Int TimeInMillis; // Represents time in milliseconds. // Parses 'str' for a 32-bit signed integer. If successful, writes the result // to *value and returns true; otherwise leaves *value unchanged and returns // false. -// TODO(chandlerc): Find a better way to refactor flag and environment parsing -// out of both gtest-port.cc and gtest.cc to avoid exporting this utility -// function. bool ParseInt32(const Message& src_text, const char* str, Int32* value); // Parses a bool/Int32/string from the environment variable // corresponding to the given Google Test flag. bool BoolFromGTestEnv(const char* flag, bool default_val); GTEST_API_ Int32 Int32FromGTestEnv(const char* flag, Int32 default_val); -std::string StringFromGTestEnv(const char* flag, const char* default_val); +std::string OutputFlagAlsoCheckEnvVar(); +const char* StringFromGTestEnv(const char* flag, const char* default_val); } // namespace internal +} // namespace testing -// Returns a path to temporary directory. -// Tries to determine an appropriate directory for the platform. -GTEST_API_ std::string TempDir(); +#if !defined(GTEST_INTERNAL_DEPRECATED) + +// Internal Macro to mark an API deprecated, for googletest usage only +// Usage: class GTEST_INTERNAL_DEPRECATED(message) MyClass or +// GTEST_INTERNAL_DEPRECATED(message) myFunction(); Every usage of +// a deprecated entity will trigger a warning when compiled with +// `-Wdeprecated-declarations` option (clang, gcc, any __GNUC__ compiler). +// For msvc /W3 option will need to be used +// Note that for 'other' compilers this macro evaluates to nothing to prevent +// compilations errors. +#if defined(_MSC_VER) +#define GTEST_INTERNAL_DEPRECATED(message) __declspec(deprecated(message)) +#elif defined(__GNUC__) +#define GTEST_INTERNAL_DEPRECATED(message) __attribute__((deprecated(message))) +#else +#define GTEST_INTERNAL_DEPRECATED(message) +#endif -} // namespace testing +#endif // !defined(GTEST_INTERNAL_DEPRECATED) #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ diff --git a/cpp/test/include/gtest/internal/gtest-string.h b/cpp/test/include/gtest/internal/gtest-string.h index 97f1a7fdd2..82aaa63bf4 100644 --- a/cpp/test/include/gtest/internal/gtest-string.h +++ b/cpp/test/include/gtest/internal/gtest-string.h @@ -27,17 +27,17 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // -// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) -// -// The Google C++ Testing Framework (Google Test) +// The Google C++ Testing and Mocking Framework (Google Test) // // This header file declares the String class and functions used internally by // Google Test. They are subject to change without notice. They should not used // by code external to Google Test. // -// This header file is #included by . +// This header file is #included by gtest-internal.h. // It should not be #included by other files. +// GOOGLETEST_CM0001 DO NOT DELETE + #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ @@ -94,7 +94,8 @@ class GTEST_API_ String { static const char* Utf16ToAnsi(LPCWSTR utf16_str); #endif - // Compares two C strings. Returns true iff they have the same content. + // Compares two C strings. Returns true if and only if they have the same + // content. // // Unlike strcmp(), this function can handle NULL argument(s). A // NULL C string is considered different to any non-NULL C string, @@ -107,16 +108,16 @@ class GTEST_API_ String { // returned. static std::string ShowWideCString(const wchar_t* wide_c_str); - // Compares two wide C strings. Returns true iff they have the same - // content. + // Compares two wide C strings. Returns true if and only if they have the + // same content. // // Unlike wcscmp(), this function can handle NULL argument(s). A // NULL C string is considered different to any non-NULL C string, // including the empty string. static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs); - // Compares two C strings, ignoring case. Returns true iff they - // have the same content. + // Compares two C strings, ignoring case. Returns true if and only if + // they have the same content. // // Unlike strcasecmp(), this function can handle NULL argument(s). // A NULL C string is considered different to any non-NULL C string, @@ -124,8 +125,8 @@ class GTEST_API_ String { static bool CaseInsensitiveCStringEquals(const char* lhs, const char* rhs); - // Compares two wide C strings, ignoring case. Returns true iff they - // have the same content. + // Compares two wide C strings, ignoring case. Returns true if and only if + // they have the same content. // // Unlike wcscasecmp(), this function can handle NULL argument(s). // A NULL C string is considered different to any non-NULL wide C string, @@ -139,8 +140,8 @@ class GTEST_API_ String { static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs, const wchar_t* rhs); - // Returns true iff the given string ends with the given suffix, ignoring - // case. Any string is considered to end with an empty suffix. + // Returns true if and only if the given string ends with the given suffix, + // ignoring case. Any string is considered to end with an empty suffix. static bool EndsWithCaseInsensitive( const std::string& str, const std::string& suffix); @@ -150,6 +151,9 @@ class GTEST_API_ String { // Formats an int value as "%X". static std::string FormatHexInt(int value); + // Formats an int value as "%X". + static std::string FormatHexUInt32(UInt32 value); + // Formats a byte as "%02X". static std::string FormatByte(unsigned char value); diff --git a/cpp/test/include/gtest/internal/gtest-tuple.h b/cpp/test/include/gtest/internal/gtest-tuple.h deleted file mode 100644 index e9b405340a..0000000000 --- a/cpp/test/include/gtest/internal/gtest-tuple.h +++ /dev/null @@ -1,1020 +0,0 @@ -// This file was GENERATED by command: -// pump.py gtest-tuple.h.pump -// DO NOT EDIT BY HAND!!! - -// Copyright 2009 Google Inc. -// All Rights Reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Author: wan@google.com (Zhanyong Wan) - -// Implements a subset of TR1 tuple needed by Google Test and Google Mock. - -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ - -#include // For ::std::pair. - -// The compiler used in Symbian has a bug that prevents us from declaring the -// tuple template as a friend (it complains that tuple is redefined). This -// hack bypasses the bug by declaring the members that should otherwise be -// private as public. -// Sun Studio versions < 12 also have the above bug. -#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590) -# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public: -#else -# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \ - template friend class tuple; \ - private: -#endif - -// Visual Studio 2010, 2012, and 2013 define symbols in std::tr1 that conflict -// with our own definitions. Therefore using our own tuple does not work on -// those compilers. -#if defined(_MSC_VER) && _MSC_VER >= 1600 /* 1600 is Visual Studio 2010 */ -# error "gtest's tuple doesn't compile on Visual Studio 2010 or later. \ -GTEST_USE_OWN_TR1_TUPLE must be set to 0 on those compilers." -#endif - -// GTEST_n_TUPLE_(T) is the type of an n-tuple. -#define GTEST_0_TUPLE_(T) tuple<> -#define GTEST_1_TUPLE_(T) tuple -#define GTEST_2_TUPLE_(T) tuple -#define GTEST_3_TUPLE_(T) tuple -#define GTEST_4_TUPLE_(T) tuple -#define GTEST_5_TUPLE_(T) tuple -#define GTEST_6_TUPLE_(T) tuple -#define GTEST_7_TUPLE_(T) tuple -#define GTEST_8_TUPLE_(T) tuple -#define GTEST_9_TUPLE_(T) tuple -#define GTEST_10_TUPLE_(T) tuple - -// GTEST_n_TYPENAMES_(T) declares a list of n typenames. -#define GTEST_0_TYPENAMES_(T) -#define GTEST_1_TYPENAMES_(T) typename T##0 -#define GTEST_2_TYPENAMES_(T) typename T##0, typename T##1 -#define GTEST_3_TYPENAMES_(T) typename T##0, typename T##1, typename T##2 -#define GTEST_4_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ - typename T##3 -#define GTEST_5_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ - typename T##3, typename T##4 -#define GTEST_6_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ - typename T##3, typename T##4, typename T##5 -#define GTEST_7_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ - typename T##3, typename T##4, typename T##5, typename T##6 -#define GTEST_8_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ - typename T##3, typename T##4, typename T##5, typename T##6, typename T##7 -#define GTEST_9_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ - typename T##3, typename T##4, typename T##5, typename T##6, \ - typename T##7, typename T##8 -#define GTEST_10_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ - typename T##3, typename T##4, typename T##5, typename T##6, \ - typename T##7, typename T##8, typename T##9 - -// In theory, defining stuff in the ::std namespace is undefined -// behavior. We can do this as we are playing the role of a standard -// library vendor. -namespace std { -namespace tr1 { - -template -class tuple; - -// Anything in namespace gtest_internal is Google Test's INTERNAL -// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code. -namespace gtest_internal { - -// ByRef::type is T if T is a reference; otherwise it's const T&. -template -struct ByRef { typedef const T& type; }; // NOLINT -template -struct ByRef { typedef T& type; }; // NOLINT - -// A handy wrapper for ByRef. -#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef::type - -// AddRef::type is T if T is a reference; otherwise it's T&. This -// is the same as tr1::add_reference::type. -template -struct AddRef { typedef T& type; }; // NOLINT -template -struct AddRef { typedef T& type; }; // NOLINT - -// A handy wrapper for AddRef. -#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef::type - -// A helper for implementing get(). -template class Get; - -// A helper for implementing tuple_element. kIndexValid is true -// iff k < the number of fields in tuple type T. -template -struct TupleElement; - -template -struct TupleElement { - typedef T0 type; -}; - -template -struct TupleElement { - typedef T1 type; -}; - -template -struct TupleElement { - typedef T2 type; -}; - -template -struct TupleElement { - typedef T3 type; -}; - -template -struct TupleElement { - typedef T4 type; -}; - -template -struct TupleElement { - typedef T5 type; -}; - -template -struct TupleElement { - typedef T6 type; -}; - -template -struct TupleElement { - typedef T7 type; -}; - -template -struct TupleElement { - typedef T8 type; -}; - -template -struct TupleElement { - typedef T9 type; -}; - -} // namespace gtest_internal - -template <> -class tuple<> { - public: - tuple() {} - tuple(const tuple& /* t */) {} - tuple& operator=(const tuple& /* t */) { return *this; } -}; - -template -class GTEST_1_TUPLE_(T) { - public: - template friend class gtest_internal::Get; - - tuple() : f0_() {} - - explicit tuple(GTEST_BY_REF_(T0) f0) : f0_(f0) {} - - tuple(const tuple& t) : f0_(t.f0_) {} - - template - tuple(const GTEST_1_TUPLE_(U)& t) : f0_(t.f0_) {} - - tuple& operator=(const tuple& t) { return CopyFrom(t); } - - template - tuple& operator=(const GTEST_1_TUPLE_(U)& t) { - return CopyFrom(t); - } - - GTEST_DECLARE_TUPLE_AS_FRIEND_ - - template - tuple& CopyFrom(const GTEST_1_TUPLE_(U)& t) { - f0_ = t.f0_; - return *this; - } - - T0 f0_; -}; - -template -class GTEST_2_TUPLE_(T) { - public: - template friend class gtest_internal::Get; - - tuple() : f0_(), f1_() {} - - explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1) : f0_(f0), - f1_(f1) {} - - tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_) {} - - template - tuple(const GTEST_2_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_) {} - template - tuple(const ::std::pair& p) : f0_(p.first), f1_(p.second) {} - - tuple& operator=(const tuple& t) { return CopyFrom(t); } - - template - tuple& operator=(const GTEST_2_TUPLE_(U)& t) { - return CopyFrom(t); - } - template - tuple& operator=(const ::std::pair& p) { - f0_ = p.first; - f1_ = p.second; - return *this; - } - - GTEST_DECLARE_TUPLE_AS_FRIEND_ - - template - tuple& CopyFrom(const GTEST_2_TUPLE_(U)& t) { - f0_ = t.f0_; - f1_ = t.f1_; - return *this; - } - - T0 f0_; - T1 f1_; -}; - -template -class GTEST_3_TUPLE_(T) { - public: - template friend class gtest_internal::Get; - - tuple() : f0_(), f1_(), f2_() {} - - explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, - GTEST_BY_REF_(T2) f2) : f0_(f0), f1_(f1), f2_(f2) {} - - tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {} - - template - tuple(const GTEST_3_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {} - - tuple& operator=(const tuple& t) { return CopyFrom(t); } - - template - tuple& operator=(const GTEST_3_TUPLE_(U)& t) { - return CopyFrom(t); - } - - GTEST_DECLARE_TUPLE_AS_FRIEND_ - - template - tuple& CopyFrom(const GTEST_3_TUPLE_(U)& t) { - f0_ = t.f0_; - f1_ = t.f1_; - f2_ = t.f2_; - return *this; - } - - T0 f0_; - T1 f1_; - T2 f2_; -}; - -template -class GTEST_4_TUPLE_(T) { - public: - template friend class gtest_internal::Get; - - tuple() : f0_(), f1_(), f2_(), f3_() {} - - explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, - GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3) : f0_(f0), f1_(f1), f2_(f2), - f3_(f3) {} - - tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_) {} - - template - tuple(const GTEST_4_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), - f3_(t.f3_) {} - - tuple& operator=(const tuple& t) { return CopyFrom(t); } - - template - tuple& operator=(const GTEST_4_TUPLE_(U)& t) { - return CopyFrom(t); - } - - GTEST_DECLARE_TUPLE_AS_FRIEND_ - - template - tuple& CopyFrom(const GTEST_4_TUPLE_(U)& t) { - f0_ = t.f0_; - f1_ = t.f1_; - f2_ = t.f2_; - f3_ = t.f3_; - return *this; - } - - T0 f0_; - T1 f1_; - T2 f2_; - T3 f3_; -}; - -template -class GTEST_5_TUPLE_(T) { - public: - template friend class gtest_internal::Get; - - tuple() : f0_(), f1_(), f2_(), f3_(), f4_() {} - - explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, - GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, - GTEST_BY_REF_(T4) f4) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4) {} - - tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), - f4_(t.f4_) {} - - template - tuple(const GTEST_5_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), - f3_(t.f3_), f4_(t.f4_) {} - - tuple& operator=(const tuple& t) { return CopyFrom(t); } - - template - tuple& operator=(const GTEST_5_TUPLE_(U)& t) { - return CopyFrom(t); - } - - GTEST_DECLARE_TUPLE_AS_FRIEND_ - - template - tuple& CopyFrom(const GTEST_5_TUPLE_(U)& t) { - f0_ = t.f0_; - f1_ = t.f1_; - f2_ = t.f2_; - f3_ = t.f3_; - f4_ = t.f4_; - return *this; - } - - T0 f0_; - T1 f1_; - T2 f2_; - T3 f3_; - T4 f4_; -}; - -template -class GTEST_6_TUPLE_(T) { - public: - template friend class gtest_internal::Get; - - tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_() {} - - explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, - GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, - GTEST_BY_REF_(T5) f5) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4), - f5_(f5) {} - - tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), - f4_(t.f4_), f5_(t.f5_) {} - - template - tuple(const GTEST_6_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), - f3_(t.f3_), f4_(t.f4_), f5_(t.f5_) {} - - tuple& operator=(const tuple& t) { return CopyFrom(t); } - - template - tuple& operator=(const GTEST_6_TUPLE_(U)& t) { - return CopyFrom(t); - } - - GTEST_DECLARE_TUPLE_AS_FRIEND_ - - template - tuple& CopyFrom(const GTEST_6_TUPLE_(U)& t) { - f0_ = t.f0_; - f1_ = t.f1_; - f2_ = t.f2_; - f3_ = t.f3_; - f4_ = t.f4_; - f5_ = t.f5_; - return *this; - } - - T0 f0_; - T1 f1_; - T2 f2_; - T3 f3_; - T4 f4_; - T5 f5_; -}; - -template -class GTEST_7_TUPLE_(T) { - public: - template friend class gtest_internal::Get; - - tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_() {} - - explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, - GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, - GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6) : f0_(f0), f1_(f1), f2_(f2), - f3_(f3), f4_(f4), f5_(f5), f6_(f6) {} - - tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), - f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {} - - template - tuple(const GTEST_7_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), - f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {} - - tuple& operator=(const tuple& t) { return CopyFrom(t); } - - template - tuple& operator=(const GTEST_7_TUPLE_(U)& t) { - return CopyFrom(t); - } - - GTEST_DECLARE_TUPLE_AS_FRIEND_ - - template - tuple& CopyFrom(const GTEST_7_TUPLE_(U)& t) { - f0_ = t.f0_; - f1_ = t.f1_; - f2_ = t.f2_; - f3_ = t.f3_; - f4_ = t.f4_; - f5_ = t.f5_; - f6_ = t.f6_; - return *this; - } - - T0 f0_; - T1 f1_; - T2 f2_; - T3 f3_; - T4 f4_; - T5 f5_; - T6 f6_; -}; - -template -class GTEST_8_TUPLE_(T) { - public: - template friend class gtest_internal::Get; - - tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_() {} - - explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, - GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, - GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, - GTEST_BY_REF_(T7) f7) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4), - f5_(f5), f6_(f6), f7_(f7) {} - - tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), - f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {} - - template - tuple(const GTEST_8_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), - f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {} - - tuple& operator=(const tuple& t) { return CopyFrom(t); } - - template - tuple& operator=(const GTEST_8_TUPLE_(U)& t) { - return CopyFrom(t); - } - - GTEST_DECLARE_TUPLE_AS_FRIEND_ - - template - tuple& CopyFrom(const GTEST_8_TUPLE_(U)& t) { - f0_ = t.f0_; - f1_ = t.f1_; - f2_ = t.f2_; - f3_ = t.f3_; - f4_ = t.f4_; - f5_ = t.f5_; - f6_ = t.f6_; - f7_ = t.f7_; - return *this; - } - - T0 f0_; - T1 f1_; - T2 f2_; - T3 f3_; - T4 f4_; - T5 f5_; - T6 f6_; - T7 f7_; -}; - -template -class GTEST_9_TUPLE_(T) { - public: - template friend class gtest_internal::Get; - - tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_() {} - - explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, - GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, - GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7, - GTEST_BY_REF_(T8) f8) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4), - f5_(f5), f6_(f6), f7_(f7), f8_(f8) {} - - tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), - f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {} - - template - tuple(const GTEST_9_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), - f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {} - - tuple& operator=(const tuple& t) { return CopyFrom(t); } - - template - tuple& operator=(const GTEST_9_TUPLE_(U)& t) { - return CopyFrom(t); - } - - GTEST_DECLARE_TUPLE_AS_FRIEND_ - - template - tuple& CopyFrom(const GTEST_9_TUPLE_(U)& t) { - f0_ = t.f0_; - f1_ = t.f1_; - f2_ = t.f2_; - f3_ = t.f3_; - f4_ = t.f4_; - f5_ = t.f5_; - f6_ = t.f6_; - f7_ = t.f7_; - f8_ = t.f8_; - return *this; - } - - T0 f0_; - T1 f1_; - T2 f2_; - T3 f3_; - T4 f4_; - T5 f5_; - T6 f6_; - T7 f7_; - T8 f8_; -}; - -template -class tuple { - public: - template friend class gtest_internal::Get; - - tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_(), - f9_() {} - - explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, - GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, - GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7, - GTEST_BY_REF_(T8) f8, GTEST_BY_REF_(T9) f9) : f0_(f0), f1_(f1), f2_(f2), - f3_(f3), f4_(f4), f5_(f5), f6_(f6), f7_(f7), f8_(f8), f9_(f9) {} - - tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), - f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_), f9_(t.f9_) {} - - template - tuple(const GTEST_10_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), - f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_), - f9_(t.f9_) {} - - tuple& operator=(const tuple& t) { return CopyFrom(t); } - - template - tuple& operator=(const GTEST_10_TUPLE_(U)& t) { - return CopyFrom(t); - } - - GTEST_DECLARE_TUPLE_AS_FRIEND_ - - template - tuple& CopyFrom(const GTEST_10_TUPLE_(U)& t) { - f0_ = t.f0_; - f1_ = t.f1_; - f2_ = t.f2_; - f3_ = t.f3_; - f4_ = t.f4_; - f5_ = t.f5_; - f6_ = t.f6_; - f7_ = t.f7_; - f8_ = t.f8_; - f9_ = t.f9_; - return *this; - } - - T0 f0_; - T1 f1_; - T2 f2_; - T3 f3_; - T4 f4_; - T5 f5_; - T6 f6_; - T7 f7_; - T8 f8_; - T9 f9_; -}; - -// 6.1.3.2 Tuple creation functions. - -// Known limitations: we don't support passing an -// std::tr1::reference_wrapper to make_tuple(). And we don't -// implement tie(). - -inline tuple<> make_tuple() { return tuple<>(); } - -template -inline GTEST_1_TUPLE_(T) make_tuple(const T0& f0) { - return GTEST_1_TUPLE_(T)(f0); -} - -template -inline GTEST_2_TUPLE_(T) make_tuple(const T0& f0, const T1& f1) { - return GTEST_2_TUPLE_(T)(f0, f1); -} - -template -inline GTEST_3_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2) { - return GTEST_3_TUPLE_(T)(f0, f1, f2); -} - -template -inline GTEST_4_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, - const T3& f3) { - return GTEST_4_TUPLE_(T)(f0, f1, f2, f3); -} - -template -inline GTEST_5_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, - const T3& f3, const T4& f4) { - return GTEST_5_TUPLE_(T)(f0, f1, f2, f3, f4); -} - -template -inline GTEST_6_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, - const T3& f3, const T4& f4, const T5& f5) { - return GTEST_6_TUPLE_(T)(f0, f1, f2, f3, f4, f5); -} - -template -inline GTEST_7_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, - const T3& f3, const T4& f4, const T5& f5, const T6& f6) { - return GTEST_7_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6); -} - -template -inline GTEST_8_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, - const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7) { - return GTEST_8_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7); -} - -template -inline GTEST_9_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, - const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7, - const T8& f8) { - return GTEST_9_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8); -} - -template -inline GTEST_10_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, - const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7, - const T8& f8, const T9& f9) { - return GTEST_10_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9); -} - -// 6.1.3.3 Tuple helper classes. - -template struct tuple_size; - -template -struct tuple_size { - static const int value = 0; -}; - -template -struct tuple_size { - static const int value = 1; -}; - -template -struct tuple_size { - static const int value = 2; -}; - -template -struct tuple_size { - static const int value = 3; -}; - -template -struct tuple_size { - static const int value = 4; -}; - -template -struct tuple_size { - static const int value = 5; -}; - -template -struct tuple_size { - static const int value = 6; -}; - -template -struct tuple_size { - static const int value = 7; -}; - -template -struct tuple_size { - static const int value = 8; -}; - -template -struct tuple_size { - static const int value = 9; -}; - -template -struct tuple_size { - static const int value = 10; -}; - -template -struct tuple_element { - typedef typename gtest_internal::TupleElement< - k < (tuple_size::value), k, Tuple>::type type; -}; - -#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element::type - -// 6.1.3.4 Element access. - -namespace gtest_internal { - -template <> -class Get<0> { - public: - template - static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple)) - Field(Tuple& t) { return t.f0_; } // NOLINT - - template - static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple)) - ConstField(const Tuple& t) { return t.f0_; } -}; - -template <> -class Get<1> { - public: - template - static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple)) - Field(Tuple& t) { return t.f1_; } // NOLINT - - template - static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple)) - ConstField(const Tuple& t) { return t.f1_; } -}; - -template <> -class Get<2> { - public: - template - static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple)) - Field(Tuple& t) { return t.f2_; } // NOLINT - - template - static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple)) - ConstField(const Tuple& t) { return t.f2_; } -}; - -template <> -class Get<3> { - public: - template - static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple)) - Field(Tuple& t) { return t.f3_; } // NOLINT - - template - static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple)) - ConstField(const Tuple& t) { return t.f3_; } -}; - -template <> -class Get<4> { - public: - template - static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple)) - Field(Tuple& t) { return t.f4_; } // NOLINT - - template - static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple)) - ConstField(const Tuple& t) { return t.f4_; } -}; - -template <> -class Get<5> { - public: - template - static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple)) - Field(Tuple& t) { return t.f5_; } // NOLINT - - template - static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple)) - ConstField(const Tuple& t) { return t.f5_; } -}; - -template <> -class Get<6> { - public: - template - static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple)) - Field(Tuple& t) { return t.f6_; } // NOLINT - - template - static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple)) - ConstField(const Tuple& t) { return t.f6_; } -}; - -template <> -class Get<7> { - public: - template - static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple)) - Field(Tuple& t) { return t.f7_; } // NOLINT - - template - static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple)) - ConstField(const Tuple& t) { return t.f7_; } -}; - -template <> -class Get<8> { - public: - template - static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple)) - Field(Tuple& t) { return t.f8_; } // NOLINT - - template - static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple)) - ConstField(const Tuple& t) { return t.f8_; } -}; - -template <> -class Get<9> { - public: - template - static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple)) - Field(Tuple& t) { return t.f9_; } // NOLINT - - template - static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple)) - ConstField(const Tuple& t) { return t.f9_; } -}; - -} // namespace gtest_internal - -template -GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T))) -get(GTEST_10_TUPLE_(T)& t) { - return gtest_internal::Get::Field(t); -} - -template -GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T))) -get(const GTEST_10_TUPLE_(T)& t) { - return gtest_internal::Get::ConstField(t); -} - -// 6.1.3.5 Relational operators - -// We only implement == and !=, as we don't have a need for the rest yet. - -namespace gtest_internal { - -// SameSizeTuplePrefixComparator::Eq(t1, t2) returns true if the -// first k fields of t1 equals the first k fields of t2. -// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if -// k1 != k2. -template -struct SameSizeTuplePrefixComparator; - -template <> -struct SameSizeTuplePrefixComparator<0, 0> { - template - static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) { - return true; - } -}; - -template -struct SameSizeTuplePrefixComparator { - template - static bool Eq(const Tuple1& t1, const Tuple2& t2) { - return SameSizeTuplePrefixComparator::Eq(t1, t2) && - ::std::tr1::get(t1) == ::std::tr1::get(t2); - } -}; - -} // namespace gtest_internal - -template -inline bool operator==(const GTEST_10_TUPLE_(T)& t, - const GTEST_10_TUPLE_(U)& u) { - return gtest_internal::SameSizeTuplePrefixComparator< - tuple_size::value, - tuple_size::value>::Eq(t, u); -} - -template -inline bool operator!=(const GTEST_10_TUPLE_(T)& t, - const GTEST_10_TUPLE_(U)& u) { return !(t == u); } - -// 6.1.4 Pairs. -// Unimplemented. - -} // namespace tr1 -} // namespace std - -#undef GTEST_0_TUPLE_ -#undef GTEST_1_TUPLE_ -#undef GTEST_2_TUPLE_ -#undef GTEST_3_TUPLE_ -#undef GTEST_4_TUPLE_ -#undef GTEST_5_TUPLE_ -#undef GTEST_6_TUPLE_ -#undef GTEST_7_TUPLE_ -#undef GTEST_8_TUPLE_ -#undef GTEST_9_TUPLE_ -#undef GTEST_10_TUPLE_ - -#undef GTEST_0_TYPENAMES_ -#undef GTEST_1_TYPENAMES_ -#undef GTEST_2_TYPENAMES_ -#undef GTEST_3_TYPENAMES_ -#undef GTEST_4_TYPENAMES_ -#undef GTEST_5_TYPENAMES_ -#undef GTEST_6_TYPENAMES_ -#undef GTEST_7_TYPENAMES_ -#undef GTEST_8_TYPENAMES_ -#undef GTEST_9_TYPENAMES_ -#undef GTEST_10_TYPENAMES_ - -#undef GTEST_DECLARE_TUPLE_AS_FRIEND_ -#undef GTEST_BY_REF_ -#undef GTEST_ADD_REF_ -#undef GTEST_TUPLE_ELEMENT_ - -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ diff --git a/cpp/test/include/gtest/internal/gtest-tuple.h.pump b/cpp/test/include/gtest/internal/gtest-tuple.h.pump deleted file mode 100644 index 429ddfeeca..0000000000 --- a/cpp/test/include/gtest/internal/gtest-tuple.h.pump +++ /dev/null @@ -1,347 +0,0 @@ -$$ -*- mode: c++; -*- -$var n = 10 $$ Maximum number of tuple fields we want to support. -$$ This meta comment fixes auto-indentation in Emacs. }} -// Copyright 2009 Google Inc. -// All Rights Reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Author: wan@google.com (Zhanyong Wan) - -// Implements a subset of TR1 tuple needed by Google Test and Google Mock. - -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ - -#include // For ::std::pair. - -// The compiler used in Symbian has a bug that prevents us from declaring the -// tuple template as a friend (it complains that tuple is redefined). This -// hack bypasses the bug by declaring the members that should otherwise be -// private as public. -// Sun Studio versions < 12 also have the above bug. -#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590) -# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public: -#else -# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \ - template friend class tuple; \ - private: -#endif - -// Visual Studio 2010, 2012, and 2013 define symbols in std::tr1 that conflict -// with our own definitions. Therefore using our own tuple does not work on -// those compilers. -#if defined(_MSC_VER) && _MSC_VER >= 1600 /* 1600 is Visual Studio 2010 */ -# error "gtest's tuple doesn't compile on Visual Studio 2010 or later. \ -GTEST_USE_OWN_TR1_TUPLE must be set to 0 on those compilers." -#endif - - -$range i 0..n-1 -$range j 0..n -$range k 1..n -// GTEST_n_TUPLE_(T) is the type of an n-tuple. -#define GTEST_0_TUPLE_(T) tuple<> - -$for k [[ -$range m 0..k-1 -$range m2 k..n-1 -#define GTEST_$(k)_TUPLE_(T) tuple<$for m, [[T##$m]]$for m2 [[, void]]> - -]] - -// GTEST_n_TYPENAMES_(T) declares a list of n typenames. - -$for j [[ -$range m 0..j-1 -#define GTEST_$(j)_TYPENAMES_(T) $for m, [[typename T##$m]] - - -]] - -// In theory, defining stuff in the ::std namespace is undefined -// behavior. We can do this as we are playing the role of a standard -// library vendor. -namespace std { -namespace tr1 { - -template <$for i, [[typename T$i = void]]> -class tuple; - -// Anything in namespace gtest_internal is Google Test's INTERNAL -// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code. -namespace gtest_internal { - -// ByRef::type is T if T is a reference; otherwise it's const T&. -template -struct ByRef { typedef const T& type; }; // NOLINT -template -struct ByRef { typedef T& type; }; // NOLINT - -// A handy wrapper for ByRef. -#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef::type - -// AddRef::type is T if T is a reference; otherwise it's T&. This -// is the same as tr1::add_reference::type. -template -struct AddRef { typedef T& type; }; // NOLINT -template -struct AddRef { typedef T& type; }; // NOLINT - -// A handy wrapper for AddRef. -#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef::type - -// A helper for implementing get(). -template class Get; - -// A helper for implementing tuple_element. kIndexValid is true -// iff k < the number of fields in tuple type T. -template -struct TupleElement; - - -$for i [[ -template -struct TupleElement { - typedef T$i type; -}; - - -]] -} // namespace gtest_internal - -template <> -class tuple<> { - public: - tuple() {} - tuple(const tuple& /* t */) {} - tuple& operator=(const tuple& /* t */) { return *this; } -}; - - -$for k [[ -$range m 0..k-1 -template -class $if k < n [[GTEST_$(k)_TUPLE_(T)]] $else [[tuple]] { - public: - template friend class gtest_internal::Get; - - tuple() : $for m, [[f$(m)_()]] {} - - explicit tuple($for m, [[GTEST_BY_REF_(T$m) f$m]]) : [[]] -$for m, [[f$(m)_(f$m)]] {} - - tuple(const tuple& t) : $for m, [[f$(m)_(t.f$(m)_)]] {} - - template - tuple(const GTEST_$(k)_TUPLE_(U)& t) : $for m, [[f$(m)_(t.f$(m)_)]] {} - -$if k == 2 [[ - template - tuple(const ::std::pair& p) : f0_(p.first), f1_(p.second) {} - -]] - - tuple& operator=(const tuple& t) { return CopyFrom(t); } - - template - tuple& operator=(const GTEST_$(k)_TUPLE_(U)& t) { - return CopyFrom(t); - } - -$if k == 2 [[ - template - tuple& operator=(const ::std::pair& p) { - f0_ = p.first; - f1_ = p.second; - return *this; - } - -]] - - GTEST_DECLARE_TUPLE_AS_FRIEND_ - - template - tuple& CopyFrom(const GTEST_$(k)_TUPLE_(U)& t) { - -$for m [[ - f$(m)_ = t.f$(m)_; - -]] - return *this; - } - - -$for m [[ - T$m f$(m)_; - -]] -}; - - -]] -// 6.1.3.2 Tuple creation functions. - -// Known limitations: we don't support passing an -// std::tr1::reference_wrapper to make_tuple(). And we don't -// implement tie(). - -inline tuple<> make_tuple() { return tuple<>(); } - -$for k [[ -$range m 0..k-1 - -template -inline GTEST_$(k)_TUPLE_(T) make_tuple($for m, [[const T$m& f$m]]) { - return GTEST_$(k)_TUPLE_(T)($for m, [[f$m]]); -} - -]] - -// 6.1.3.3 Tuple helper classes. - -template struct tuple_size; - - -$for j [[ -template -struct tuple_size { - static const int value = $j; -}; - - -]] -template -struct tuple_element { - typedef typename gtest_internal::TupleElement< - k < (tuple_size::value), k, Tuple>::type type; -}; - -#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element::type - -// 6.1.3.4 Element access. - -namespace gtest_internal { - - -$for i [[ -template <> -class Get<$i> { - public: - template - static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple)) - Field(Tuple& t) { return t.f$(i)_; } // NOLINT - - template - static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple)) - ConstField(const Tuple& t) { return t.f$(i)_; } -}; - - -]] -} // namespace gtest_internal - -template -GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T))) -get(GTEST_$(n)_TUPLE_(T)& t) { - return gtest_internal::Get::Field(t); -} - -template -GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T))) -get(const GTEST_$(n)_TUPLE_(T)& t) { - return gtest_internal::Get::ConstField(t); -} - -// 6.1.3.5 Relational operators - -// We only implement == and !=, as we don't have a need for the rest yet. - -namespace gtest_internal { - -// SameSizeTuplePrefixComparator::Eq(t1, t2) returns true if the -// first k fields of t1 equals the first k fields of t2. -// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if -// k1 != k2. -template -struct SameSizeTuplePrefixComparator; - -template <> -struct SameSizeTuplePrefixComparator<0, 0> { - template - static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) { - return true; - } -}; - -template -struct SameSizeTuplePrefixComparator { - template - static bool Eq(const Tuple1& t1, const Tuple2& t2) { - return SameSizeTuplePrefixComparator::Eq(t1, t2) && - ::std::tr1::get(t1) == ::std::tr1::get(t2); - } -}; - -} // namespace gtest_internal - -template -inline bool operator==(const GTEST_$(n)_TUPLE_(T)& t, - const GTEST_$(n)_TUPLE_(U)& u) { - return gtest_internal::SameSizeTuplePrefixComparator< - tuple_size::value, - tuple_size::value>::Eq(t, u); -} - -template -inline bool operator!=(const GTEST_$(n)_TUPLE_(T)& t, - const GTEST_$(n)_TUPLE_(U)& u) { return !(t == u); } - -// 6.1.4 Pairs. -// Unimplemented. - -} // namespace tr1 -} // namespace std - - -$for j [[ -#undef GTEST_$(j)_TUPLE_ - -]] - - -$for j [[ -#undef GTEST_$(j)_TYPENAMES_ - -]] - -#undef GTEST_DECLARE_TUPLE_AS_FRIEND_ -#undef GTEST_BY_REF_ -#undef GTEST_ADD_REF_ -#undef GTEST_TUPLE_ELEMENT_ - -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ diff --git a/cpp/test/include/gtest/internal/gtest-type-util.h b/cpp/test/include/gtest/internal/gtest-type-util.h index e46f7cfcb4..082fdad12c 100644 --- a/cpp/test/include/gtest/internal/gtest-type-util.h +++ b/cpp/test/include/gtest/internal/gtest-type-util.h @@ -1,7 +1,3 @@ -// This file was GENERATED by command: -// pump.py gtest-type-util.h.pump -// DO NOT EDIT BY HAND!!! - // Copyright 2008 Google Inc. // All Rights Reserved. // @@ -30,16 +26,11 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Author: wan@google.com (Zhanyong Wan) // Type utilities needed for implementing typed and type-parameterized -// tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND! -// -// Currently we support at most 50 types in a list, and at most 50 -// type-parameterized tests in one type-parameterized test case. -// Please contact googletestframework@googlegroups.com if you need -// more. +// tests. + +// GOOGLETEST_CM0001 DO NOT DELETE #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ @@ -57,6 +48,22 @@ namespace testing { namespace internal { +// Canonicalizes a given name with respect to the Standard C++ Library. +// This handles removing the inline namespace within `std` that is +// used by various standard libraries (e.g., `std::__1`). Names outside +// of namespace std are returned unmodified. +inline std::string CanonicalizeForStdLibVersioning(std::string s) { + static const char prefix[] = "std::__"; + if (s.compare(0, strlen(prefix), prefix) == 0) { + std::string::size_type end = s.find("::", strlen(prefix)); + if (end != s.npos) { + // Erase everything between the initial `std` and the second `::`. + s.erase(strlen("std"), end - strlen("std")); + } + } + return s; +} + // GetTypeName() returns a human-readable name of type T. // NB: This function is also used in Google Mock, so don't move it inside of // the typed-test-only section below. @@ -72,10 +79,10 @@ std::string GetTypeName() { # if GTEST_HAS_CXXABI_H_ using abi::__cxa_demangle; # endif // GTEST_HAS_CXXABI_H_ - char* const readable_name = __cxa_demangle(name, 0, 0, &status); + char* const readable_name = __cxa_demangle(name, nullptr, nullptr, &status); const std::string name_str(status == 0 ? readable_name : name); free(readable_name); - return name_str; + return CanonicalizeForStdLibVersioning(name_str); # else return name; # endif // GTEST_HAS_CXXABI_H_ || __HP_aCC @@ -89,1536 +96,9 @@ std::string GetTypeName() { #if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P -// AssertyTypeEq::type is defined iff T1 and T2 are the same -// type. This can be used as a compile-time assertion to ensure that -// two types are equal. - -template -struct AssertTypeEq; - -template -struct AssertTypeEq { - typedef bool type; -}; - -// A unique type used as the default value for the arguments of class -// template Types. This allows us to simulate variadic templates -// (e.g. Types, Type, and etc), which C++ doesn't -// support directly. +// A unique type indicating an empty node struct None {}; -// The following family of struct and struct templates are used to -// represent type lists. In particular, TypesN -// represents a type list with N types (T1, T2, ..., and TN) in it. -// Except for Types0, every struct in the family has two member types: -// Head for the first type in the list, and Tail for the rest of the -// list. - -// The empty type list. -struct Types0 {}; - -// Type lists of length 1, 2, 3, and so on. - -template -struct Types1 { - typedef T1 Head; - typedef Types0 Tail; -}; -template -struct Types2 { - typedef T1 Head; - typedef Types1 Tail; -}; - -template -struct Types3 { - typedef T1 Head; - typedef Types2 Tail; -}; - -template -struct Types4 { - typedef T1 Head; - typedef Types3 Tail; -}; - -template -struct Types5 { - typedef T1 Head; - typedef Types4 Tail; -}; - -template -struct Types6 { - typedef T1 Head; - typedef Types5 Tail; -}; - -template -struct Types7 { - typedef T1 Head; - typedef Types6 Tail; -}; - -template -struct Types8 { - typedef T1 Head; - typedef Types7 Tail; -}; - -template -struct Types9 { - typedef T1 Head; - typedef Types8 Tail; -}; - -template -struct Types10 { - typedef T1 Head; - typedef Types9 Tail; -}; - -template -struct Types11 { - typedef T1 Head; - typedef Types10 Tail; -}; - -template -struct Types12 { - typedef T1 Head; - typedef Types11 Tail; -}; - -template -struct Types13 { - typedef T1 Head; - typedef Types12 Tail; -}; - -template -struct Types14 { - typedef T1 Head; - typedef Types13 Tail; -}; - -template -struct Types15 { - typedef T1 Head; - typedef Types14 Tail; -}; - -template -struct Types16 { - typedef T1 Head; - typedef Types15 Tail; -}; - -template -struct Types17 { - typedef T1 Head; - typedef Types16 Tail; -}; - -template -struct Types18 { - typedef T1 Head; - typedef Types17 Tail; -}; - -template -struct Types19 { - typedef T1 Head; - typedef Types18 Tail; -}; - -template -struct Types20 { - typedef T1 Head; - typedef Types19 Tail; -}; - -template -struct Types21 { - typedef T1 Head; - typedef Types20 Tail; -}; - -template -struct Types22 { - typedef T1 Head; - typedef Types21 Tail; -}; - -template -struct Types23 { - typedef T1 Head; - typedef Types22 Tail; -}; - -template -struct Types24 { - typedef T1 Head; - typedef Types23 Tail; -}; - -template -struct Types25 { - typedef T1 Head; - typedef Types24 Tail; -}; - -template -struct Types26 { - typedef T1 Head; - typedef Types25 Tail; -}; - -template -struct Types27 { - typedef T1 Head; - typedef Types26 Tail; -}; - -template -struct Types28 { - typedef T1 Head; - typedef Types27 Tail; -}; - -template -struct Types29 { - typedef T1 Head; - typedef Types28 Tail; -}; - -template -struct Types30 { - typedef T1 Head; - typedef Types29 Tail; -}; - -template -struct Types31 { - typedef T1 Head; - typedef Types30 Tail; -}; - -template -struct Types32 { - typedef T1 Head; - typedef Types31 Tail; -}; - -template -struct Types33 { - typedef T1 Head; - typedef Types32 Tail; -}; - -template -struct Types34 { - typedef T1 Head; - typedef Types33 Tail; -}; - -template -struct Types35 { - typedef T1 Head; - typedef Types34 Tail; -}; - -template -struct Types36 { - typedef T1 Head; - typedef Types35 Tail; -}; - -template -struct Types37 { - typedef T1 Head; - typedef Types36 Tail; -}; - -template -struct Types38 { - typedef T1 Head; - typedef Types37 Tail; -}; - -template -struct Types39 { - typedef T1 Head; - typedef Types38 Tail; -}; - -template -struct Types40 { - typedef T1 Head; - typedef Types39 Tail; -}; - -template -struct Types41 { - typedef T1 Head; - typedef Types40 Tail; -}; - -template -struct Types42 { - typedef T1 Head; - typedef Types41 Tail; -}; - -template -struct Types43 { - typedef T1 Head; - typedef Types42 Tail; -}; - -template -struct Types44 { - typedef T1 Head; - typedef Types43 Tail; -}; - -template -struct Types45 { - typedef T1 Head; - typedef Types44 Tail; -}; - -template -struct Types46 { - typedef T1 Head; - typedef Types45 Tail; -}; - -template -struct Types47 { - typedef T1 Head; - typedef Types46 Tail; -}; - -template -struct Types48 { - typedef T1 Head; - typedef Types47 Tail; -}; - -template -struct Types49 { - typedef T1 Head; - typedef Types48 Tail; -}; - -template -struct Types50 { - typedef T1 Head; - typedef Types49 Tail; -}; - - -} // namespace internal - -// We don't want to require the users to write TypesN<...> directly, -// as that would require them to count the length. Types<...> is much -// easier to write, but generates horrible messages when there is a -// compiler error, as gcc insists on printing out each template -// argument, even if it has the default value (this means Types -// will appear as Types in the compiler -// errors). -// -// Our solution is to combine the best part of the two approaches: a -// user would write Types, and Google Test will translate -// that to TypesN internally to make error messages -// readable. The translation is done by the 'type' member of the -// Types template. -template -struct Types { - typedef internal::Types50 type; -}; - -template <> -struct Types { - typedef internal::Types0 type; -}; -template -struct Types { - typedef internal::Types1 type; -}; -template -struct Types { - typedef internal::Types2 type; -}; -template -struct Types { - typedef internal::Types3 type; -}; -template -struct Types { - typedef internal::Types4 type; -}; -template -struct Types { - typedef internal::Types5 type; -}; -template -struct Types { - typedef internal::Types6 type; -}; -template -struct Types { - typedef internal::Types7 type; -}; -template -struct Types { - typedef internal::Types8 type; -}; -template -struct Types { - typedef internal::Types9 type; -}; -template -struct Types { - typedef internal::Types10 type; -}; -template -struct Types { - typedef internal::Types11 type; -}; -template -struct Types { - typedef internal::Types12 type; -}; -template -struct Types { - typedef internal::Types13 type; -}; -template -struct Types { - typedef internal::Types14 type; -}; -template -struct Types { - typedef internal::Types15 type; -}; -template -struct Types { - typedef internal::Types16 type; -}; -template -struct Types { - typedef internal::Types17 type; -}; -template -struct Types { - typedef internal::Types18 type; -}; -template -struct Types { - typedef internal::Types19 type; -}; -template -struct Types { - typedef internal::Types20 type; -}; -template -struct Types { - typedef internal::Types21 type; -}; -template -struct Types { - typedef internal::Types22 type; -}; -template -struct Types { - typedef internal::Types23 type; -}; -template -struct Types { - typedef internal::Types24 type; -}; -template -struct Types { - typedef internal::Types25 type; -}; -template -struct Types { - typedef internal::Types26 type; -}; -template -struct Types { - typedef internal::Types27 type; -}; -template -struct Types { - typedef internal::Types28 type; -}; -template -struct Types { - typedef internal::Types29 type; -}; -template -struct Types { - typedef internal::Types30 type; -}; -template -struct Types { - typedef internal::Types31 type; -}; -template -struct Types { - typedef internal::Types32 type; -}; -template -struct Types { - typedef internal::Types33 type; -}; -template -struct Types { - typedef internal::Types34 type; -}; -template -struct Types { - typedef internal::Types35 type; -}; -template -struct Types { - typedef internal::Types36 type; -}; -template -struct Types { - typedef internal::Types37 type; -}; -template -struct Types { - typedef internal::Types38 type; -}; -template -struct Types { - typedef internal::Types39 type; -}; -template -struct Types { - typedef internal::Types40 type; -}; -template -struct Types { - typedef internal::Types41 type; -}; -template -struct Types { - typedef internal::Types42 type; -}; -template -struct Types { - typedef internal::Types43 type; -}; -template -struct Types { - typedef internal::Types44 type; -}; -template -struct Types { - typedef internal::Types45 type; -}; -template -struct Types { - typedef internal::Types46 type; -}; -template -struct Types { - typedef internal::Types47 type; -}; -template -struct Types { - typedef internal::Types48 type; -}; -template -struct Types { - typedef internal::Types49 type; -}; - -namespace internal { - # define GTEST_TEMPLATE_ template class // The template "selector" struct TemplateSel is used to @@ -1640,1692 +120,64 @@ struct TemplateSel { # define GTEST_BIND_(TmplSel, T) \ TmplSel::template Bind::type -// A unique struct template used as the default value for the -// arguments of class template Templates. This allows us to simulate -// variadic templates (e.g. Templates, Templates, -// and etc), which C++ doesn't support directly. -template -struct NoneT {}; - -// The following family of struct and struct templates are used to -// represent template lists. In particular, TemplatesN represents a list of N templates (T1, T2, ..., and TN). Except -// for Templates0, every struct in the family has two member types: -// Head for the selector of the first template in the list, and Tail -// for the rest of the list. - -// The empty template list. -struct Templates0 {}; - -// Template lists of length 1, 2, 3, and so on. - -template -struct Templates1 { - typedef TemplateSel Head; - typedef Templates0 Tail; -}; -template -struct Templates2 { - typedef TemplateSel Head; - typedef Templates1 Tail; -}; - -template -struct Templates3 { - typedef TemplateSel Head; - typedef Templates2 Tail; -}; - -template -struct Templates4 { - typedef TemplateSel Head; - typedef Templates3 Tail; -}; - -template -struct Templates5 { - typedef TemplateSel Head; - typedef Templates4 Tail; -}; - -template -struct Templates6 { - typedef TemplateSel Head; - typedef Templates5 Tail; -}; - -template -struct Templates7 { - typedef TemplateSel Head; - typedef Templates6 Tail; -}; - -template -struct Templates8 { - typedef TemplateSel Head; - typedef Templates7 Tail; -}; - -template -struct Templates9 { - typedef TemplateSel Head; - typedef Templates8 Tail; -}; - -template -struct Templates10 { - typedef TemplateSel Head; - typedef Templates9 Tail; -}; - -template -struct Templates11 { - typedef TemplateSel Head; - typedef Templates10 Tail; -}; - -template -struct Templates12 { - typedef TemplateSel Head; - typedef Templates11 Tail; -}; - -template -struct Templates13 { - typedef TemplateSel Head; - typedef Templates12 Tail; -}; - -template -struct Templates14 { - typedef TemplateSel Head; - typedef Templates13 Tail; -}; - -template -struct Templates15 { - typedef TemplateSel Head; - typedef Templates14 Tail; -}; - -template -struct Templates16 { - typedef TemplateSel Head; - typedef Templates15 Tail; -}; - -template -struct Templates17 { - typedef TemplateSel Head; - typedef Templates16 Tail; -}; - -template -struct Templates18 { - typedef TemplateSel Head; - typedef Templates17 Tail; -}; - -template -struct Templates19 { - typedef TemplateSel Head; - typedef Templates18 Tail; -}; - -template -struct Templates20 { - typedef TemplateSel Head; - typedef Templates19 Tail; -}; - -template -struct Templates21 { - typedef TemplateSel Head; - typedef Templates20 Tail; -}; - -template -struct Templates22 { - typedef TemplateSel Head; - typedef Templates21 Tail; -}; - -template -struct Templates23 { - typedef TemplateSel Head; - typedef Templates22 Tail; -}; - -template -struct Templates24 { - typedef TemplateSel Head; - typedef Templates23 Tail; -}; - -template -struct Templates25 { - typedef TemplateSel Head; - typedef Templates24 Tail; -}; - -template -struct Templates26 { - typedef TemplateSel Head; - typedef Templates25 Tail; -}; - -template -struct Templates27 { - typedef TemplateSel Head; - typedef Templates26 Tail; -}; - -template -struct Templates28 { - typedef TemplateSel Head; - typedef Templates27 Tail; -}; - -template -struct Templates29 { - typedef TemplateSel Head; - typedef Templates28 Tail; -}; - -template -struct Templates30 { - typedef TemplateSel Head; - typedef Templates29 Tail; -}; - -template -struct Templates31 { - typedef TemplateSel Head; - typedef Templates30 Tail; -}; - -template -struct Templates32 { - typedef TemplateSel Head; - typedef Templates31 Tail; -}; - -template -struct Templates33 { - typedef TemplateSel Head; - typedef Templates32 Tail; -}; - -template -struct Templates34 { - typedef TemplateSel Head; - typedef Templates33 Tail; -}; - -template -struct Templates35 { - typedef TemplateSel Head; - typedef Templates34 Tail; -}; - -template -struct Templates36 { - typedef TemplateSel Head; - typedef Templates35 Tail; -}; - -template -struct Templates37 { - typedef TemplateSel Head; - typedef Templates36 Tail; -}; - -template -struct Templates38 { - typedef TemplateSel Head; - typedef Templates37 Tail; -}; - -template -struct Templates39 { - typedef TemplateSel Head; - typedef Templates38 Tail; -}; - -template -struct Templates40 { - typedef TemplateSel Head; - typedef Templates39 Tail; -}; - -template -struct Templates41 { - typedef TemplateSel Head; - typedef Templates40 Tail; -}; - -template -struct Templates42 { - typedef TemplateSel Head; - typedef Templates41 Tail; -}; - -template -struct Templates43 { - typedef TemplateSel Head; - typedef Templates42 Tail; -}; - -template -struct Templates44 { - typedef TemplateSel Head; - typedef Templates43 Tail; -}; - -template -struct Templates45 { - typedef TemplateSel Head; - typedef Templates44 Tail; -}; - -template -struct Templates46 { - typedef TemplateSel Head; - typedef Templates45 Tail; +template +struct Templates { + using Head = TemplateSel; + using Tail = Templates; }; -template -struct Templates47 { - typedef TemplateSel Head; - typedef Templates46 Tail; +template +struct Templates { + using Head = TemplateSel; + using Tail = None; }; -template -struct Templates48 { - typedef TemplateSel Head; - typedef Templates47 Tail; +// Tuple-like type lists +template +struct Types { + using Head = Head_; + using Tail = Types; }; -template -struct Templates49 { - typedef TemplateSel Head; - typedef Templates48 Tail; +template +struct Types { + using Head = Head_; + using Tail = None; }; -template -struct Templates50 { - typedef TemplateSel Head; - typedef Templates49 Tail; +// Helper metafunctions to tell apart a single type from types +// generated by ::testing::Types +template +struct ProxyTypeList { + using type = Types; }; +template +struct is_proxy_type_list : std::false_type {}; -// We don't want to require the users to write TemplatesN<...> directly, -// as that would require them to count the length. Templates<...> is much -// easier to write, but generates horrible messages when there is a -// compiler error, as gcc insists on printing out each template -// argument, even if it has the default value (this means Templates -// will appear as Templates in the compiler -// errors). -// -// Our solution is to combine the best part of the two approaches: a -// user would write Templates, and Google Test will translate -// that to TemplatesN internally to make error messages -// readable. The translation is done by the 'type' member of the -// Templates template. -template -struct Templates { - typedef Templates50 type; -}; - -template <> -struct Templates { - typedef Templates0 type; -}; -template -struct Templates { - typedef Templates1 type; -}; -template -struct Templates { - typedef Templates2 type; -}; -template -struct Templates { - typedef Templates3 type; -}; -template -struct Templates { - typedef Templates4 type; -}; -template -struct Templates { - typedef Templates5 type; -}; -template -struct Templates { - typedef Templates6 type; -}; -template -struct Templates { - typedef Templates7 type; -}; -template -struct Templates { - typedef Templates8 type; -}; -template -struct Templates { - typedef Templates9 type; -}; -template -struct Templates { - typedef Templates10 type; -}; -template -struct Templates { - typedef Templates11 type; -}; -template -struct Templates { - typedef Templates12 type; -}; -template -struct Templates { - typedef Templates13 type; -}; -template -struct Templates { - typedef Templates14 type; -}; -template -struct Templates { - typedef Templates15 type; -}; -template -struct Templates { - typedef Templates16 type; -}; -template -struct Templates { - typedef Templates17 type; -}; -template -struct Templates { - typedef Templates18 type; -}; -template -struct Templates { - typedef Templates19 type; -}; -template -struct Templates { - typedef Templates20 type; -}; -template -struct Templates { - typedef Templates21 type; -}; -template -struct Templates { - typedef Templates22 type; -}; -template -struct Templates { - typedef Templates23 type; -}; -template -struct Templates { - typedef Templates24 type; -}; -template -struct Templates { - typedef Templates25 type; -}; -template -struct Templates { - typedef Templates26 type; -}; -template -struct Templates { - typedef Templates27 type; -}; -template -struct Templates { - typedef Templates28 type; -}; -template -struct Templates { - typedef Templates29 type; -}; -template -struct Templates { - typedef Templates30 type; -}; -template -struct Templates { - typedef Templates31 type; -}; -template -struct Templates { - typedef Templates32 type; -}; -template -struct Templates { - typedef Templates33 type; -}; -template -struct Templates { - typedef Templates34 type; -}; -template -struct Templates { - typedef Templates35 type; -}; -template -struct Templates { - typedef Templates36 type; -}; -template -struct Templates { - typedef Templates37 type; -}; -template -struct Templates { - typedef Templates38 type; -}; -template -struct Templates { - typedef Templates39 type; -}; -template -struct Templates { - typedef Templates40 type; -}; -template -struct Templates { - typedef Templates41 type; -}; -template -struct Templates { - typedef Templates42 type; -}; -template -struct Templates { - typedef Templates43 type; -}; -template -struct Templates { - typedef Templates44 type; -}; -template -struct Templates { - typedef Templates45 type; -}; -template -struct Templates { - typedef Templates46 type; -}; -template -struct Templates { - typedef Templates47 type; -}; -template -struct Templates { - typedef Templates48 type; -}; -template -struct Templates { - typedef Templates49 type; -}; - -// The TypeList template makes it possible to use either a single type -// or a Types<...> list in TYPED_TEST_CASE() and -// INSTANTIATE_TYPED_TEST_CASE_P(). +template +struct is_proxy_type_list> : std::true_type {}; +// Generator which conditionally creates type lists. +// It recognizes if a requested type list should be created +// and prevents creating a new type list nested within another one. template -struct TypeList { - typedef Types1 type; -}; +struct GenerateTypeList { + private: + using proxy = typename std::conditional::value, T, + ProxyTypeList>::type; -template -struct TypeList > { - typedef typename Types::type type; + public: + using type = typename proxy::type; }; #endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P } // namespace internal + +template +using Types = internal::ProxyTypeList; + } // namespace testing #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ diff --git a/cpp/test/include/gtest/internal/gtest-type-util.h.pump b/cpp/test/include/gtest/internal/gtest-type-util.h.pump deleted file mode 100644 index 251fdf025b..0000000000 --- a/cpp/test/include/gtest/internal/gtest-type-util.h.pump +++ /dev/null @@ -1,297 +0,0 @@ -$$ -*- mode: c++; -*- -$var n = 50 $$ Maximum length of type lists we want to support. -// Copyright 2008 Google Inc. -// All Rights Reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Author: wan@google.com (Zhanyong Wan) - -// Type utilities needed for implementing typed and type-parameterized -// tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND! -// -// Currently we support at most $n types in a list, and at most $n -// type-parameterized tests in one type-parameterized test case. -// Please contact googletestframework@googlegroups.com if you need -// more. - -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ - -#include "gtest/internal/gtest-port.h" - -// #ifdef __GNUC__ is too general here. It is possible to use gcc without using -// libstdc++ (which is where cxxabi.h comes from). -# if GTEST_HAS_CXXABI_H_ -# include -# elif defined(__HP_aCC) -# include -# endif // GTEST_HASH_CXXABI_H_ - -namespace testing { -namespace internal { - -// GetTypeName() returns a human-readable name of type T. -// NB: This function is also used in Google Mock, so don't move it inside of -// the typed-test-only section below. -template -std::string GetTypeName() { -# if GTEST_HAS_RTTI - - const char* const name = typeid(T).name(); -# if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC) - int status = 0; - // gcc's implementation of typeid(T).name() mangles the type name, - // so we have to demangle it. -# if GTEST_HAS_CXXABI_H_ - using abi::__cxa_demangle; -# endif // GTEST_HAS_CXXABI_H_ - char* const readable_name = __cxa_demangle(name, 0, 0, &status); - const std::string name_str(status == 0 ? readable_name : name); - free(readable_name); - return name_str; -# else - return name; -# endif // GTEST_HAS_CXXABI_H_ || __HP_aCC - -# else - - return ""; - -# endif // GTEST_HAS_RTTI -} - -#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P - -// AssertyTypeEq::type is defined iff T1 and T2 are the same -// type. This can be used as a compile-time assertion to ensure that -// two types are equal. - -template -struct AssertTypeEq; - -template -struct AssertTypeEq { - typedef bool type; -}; - -// A unique type used as the default value for the arguments of class -// template Types. This allows us to simulate variadic templates -// (e.g. Types, Type, and etc), which C++ doesn't -// support directly. -struct None {}; - -// The following family of struct and struct templates are used to -// represent type lists. In particular, TypesN -// represents a type list with N types (T1, T2, ..., and TN) in it. -// Except for Types0, every struct in the family has two member types: -// Head for the first type in the list, and Tail for the rest of the -// list. - -// The empty type list. -struct Types0 {}; - -// Type lists of length 1, 2, 3, and so on. - -template -struct Types1 { - typedef T1 Head; - typedef Types0 Tail; -}; - -$range i 2..n - -$for i [[ -$range j 1..i -$range k 2..i -template <$for j, [[typename T$j]]> -struct Types$i { - typedef T1 Head; - typedef Types$(i-1)<$for k, [[T$k]]> Tail; -}; - - -]] - -} // namespace internal - -// We don't want to require the users to write TypesN<...> directly, -// as that would require them to count the length. Types<...> is much -// easier to write, but generates horrible messages when there is a -// compiler error, as gcc insists on printing out each template -// argument, even if it has the default value (this means Types -// will appear as Types in the compiler -// errors). -// -// Our solution is to combine the best part of the two approaches: a -// user would write Types, and Google Test will translate -// that to TypesN internally to make error messages -// readable. The translation is done by the 'type' member of the -// Types template. - -$range i 1..n -template <$for i, [[typename T$i = internal::None]]> -struct Types { - typedef internal::Types$n<$for i, [[T$i]]> type; -}; - -template <> -struct Types<$for i, [[internal::None]]> { - typedef internal::Types0 type; -}; - -$range i 1..n-1 -$for i [[ -$range j 1..i -$range k i+1..n -template <$for j, [[typename T$j]]> -struct Types<$for j, [[T$j]]$for k[[, internal::None]]> { - typedef internal::Types$i<$for j, [[T$j]]> type; -}; - -]] - -namespace internal { - -# define GTEST_TEMPLATE_ template class - -// The template "selector" struct TemplateSel is used to -// represent Tmpl, which must be a class template with one type -// parameter, as a type. TemplateSel::Bind::type is defined -// as the type Tmpl. This allows us to actually instantiate the -// template "selected" by TemplateSel. -// -// This trick is necessary for simulating typedef for class templates, -// which C++ doesn't support directly. -template -struct TemplateSel { - template - struct Bind { - typedef Tmpl type; - }; -}; - -# define GTEST_BIND_(TmplSel, T) \ - TmplSel::template Bind::type - -// A unique struct template used as the default value for the -// arguments of class template Templates. This allows us to simulate -// variadic templates (e.g. Templates, Templates, -// and etc), which C++ doesn't support directly. -template -struct NoneT {}; - -// The following family of struct and struct templates are used to -// represent template lists. In particular, TemplatesN represents a list of N templates (T1, T2, ..., and TN). Except -// for Templates0, every struct in the family has two member types: -// Head for the selector of the first template in the list, and Tail -// for the rest of the list. - -// The empty template list. -struct Templates0 {}; - -// Template lists of length 1, 2, 3, and so on. - -template -struct Templates1 { - typedef TemplateSel Head; - typedef Templates0 Tail; -}; - -$range i 2..n - -$for i [[ -$range j 1..i -$range k 2..i -template <$for j, [[GTEST_TEMPLATE_ T$j]]> -struct Templates$i { - typedef TemplateSel Head; - typedef Templates$(i-1)<$for k, [[T$k]]> Tail; -}; - - -]] - -// We don't want to require the users to write TemplatesN<...> directly, -// as that would require them to count the length. Templates<...> is much -// easier to write, but generates horrible messages when there is a -// compiler error, as gcc insists on printing out each template -// argument, even if it has the default value (this means Templates -// will appear as Templates in the compiler -// errors). -// -// Our solution is to combine the best part of the two approaches: a -// user would write Templates, and Google Test will translate -// that to TemplatesN internally to make error messages -// readable. The translation is done by the 'type' member of the -// Templates template. - -$range i 1..n -template <$for i, [[GTEST_TEMPLATE_ T$i = NoneT]]> -struct Templates { - typedef Templates$n<$for i, [[T$i]]> type; -}; - -template <> -struct Templates<$for i, [[NoneT]]> { - typedef Templates0 type; -}; - -$range i 1..n-1 -$for i [[ -$range j 1..i -$range k i+1..n -template <$for j, [[GTEST_TEMPLATE_ T$j]]> -struct Templates<$for j, [[T$j]]$for k[[, NoneT]]> { - typedef Templates$i<$for j, [[T$j]]> type; -}; - -]] - -// The TypeList template makes it possible to use either a single type -// or a Types<...> list in TYPED_TEST_CASE() and -// INSTANTIATE_TYPED_TEST_CASE_P(). - -template -struct TypeList { - typedef Types1 type; -}; - - -$range i 1..n -template <$for i, [[typename T$i]]> -struct TypeList > { - typedef typename Types<$for i, [[T$i]]>::type type; -}; - -#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P - -} // namespace internal -} // namespace testing - -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ diff --git a/cpp/test/src/gtest-death-test.cc b/cpp/test/src/gtest-death-test.cc index fd1cc3fcbf..da09a1cfc2 100644 --- a/cpp/test/src/gtest-death-test.cc +++ b/cpp/test/src/gtest-death-test.cc @@ -26,12 +26,14 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Author: wan@google.com (Zhanyong Wan), vladl@google.com (Vlad Losev) + // // This file implements death tests. #include "gtest/gtest-death-test.h" + +#include + #include "gtest/internal/gtest-port.h" #include "gtest/internal/custom/gtest.h" @@ -62,26 +64,36 @@ # include # endif // GTEST_OS_QNX +# if GTEST_OS_FUCHSIA +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# endif // GTEST_OS_FUCHSIA + #endif // GTEST_HAS_DEATH_TEST #include "gtest/gtest-message.h" #include "gtest/internal/gtest-string.h" - -// Indicates that this translation unit is part of Google Test's -// implementation. It must come before gtest-internal-inl.h is -// included, or there will be a compiler error. This trick exists to -// prevent the accidental inclusion of gtest-internal-inl.h in the -// user's code. -#define GTEST_IMPLEMENTATION_ 1 #include "src/gtest-internal-inl.h" -#undef GTEST_IMPLEMENTATION_ namespace testing { // Constants. // The default death test style. -static const char kDefaultDeathTestStyle[] = "fast"; +// +// This is defined in internal/gtest-port.h as "fast", but can be overridden by +// a definition in internal/custom/gtest-port.h. The recommended value, which is +// used internally at Google, is "threadsafe". +static const char kDefaultDeathTestStyle[] = GTEST_DEFAULT_DEATH_TEST_STYLE; GTEST_DEFINE_string_( death_test_style, @@ -110,8 +122,8 @@ GTEST_DEFINE_string_( "Indicates the file, line number, temporal index of " "the single death test to run, and a file descriptor to " "which a success code may be sent, all separated by " - "the '|' characters. This flag is specified if and only if the current " - "process is a sub-process launched for running a thread-safe " + "the '|' characters. This flag is specified if and only if the " + "current process is a sub-process launched for running a thread-safe " "death test. FOR INTERNAL USE ONLY."); } // namespace internal @@ -121,7 +133,7 @@ namespace internal { // Valid only for fast death tests. Indicates the code is running in the // child process of a fast style death test. -# if !GTEST_OS_WINDOWS +# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA static bool g_in_fast_death_test_child = false; # endif @@ -131,10 +143,10 @@ static bool g_in_fast_death_test_child = false; // tests. IMPORTANT: This is an internal utility. Using it may break the // implementation of death tests. User code MUST NOT use it. bool InDeathTestChild() { -# if GTEST_OS_WINDOWS +# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA - // On Windows, death tests are thread-safe regardless of the value of the - // death_test_style flag. + // On Windows and Fuchsia, death tests are thread-safe regardless of the value + // of the death_test_style flag. return !GTEST_FLAG(internal_run_death_test).empty(); # else @@ -154,7 +166,7 @@ ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) { // ExitedWithCode function-call operator. bool ExitedWithCode::operator()(int exit_status) const { -# if GTEST_OS_WINDOWS +# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA return exit_status == exit_code_; @@ -162,10 +174,10 @@ bool ExitedWithCode::operator()(int exit_status) const { return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_; -# endif // GTEST_OS_WINDOWS +# endif // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA } -# if !GTEST_OS_WINDOWS +# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA // KilledBySignal constructor. KilledBySignal::KilledBySignal(int signum) : signum_(signum) { } @@ -182,7 +194,7 @@ bool KilledBySignal::operator()(int exit_status) const { # endif // defined(GTEST_KILLED_BY_SIGNAL_OVERRIDE_) return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_; } -# endif // !GTEST_OS_WINDOWS +# endif // !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA namespace internal { @@ -193,7 +205,7 @@ namespace internal { static std::string ExitSummary(int exit_code) { Message m; -# if GTEST_OS_WINDOWS +# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA m << "Exited with exit status " << exit_code; @@ -209,7 +221,7 @@ static std::string ExitSummary(int exit_code) { m << " (core dumped)"; } # endif -# endif // GTEST_OS_WINDOWS +# endif // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA return m.GetString(); } @@ -220,7 +232,7 @@ bool ExitedUnsuccessfully(int exit_status) { return !ExitedWithCode(0)(exit_status); } -# if !GTEST_OS_WINDOWS +# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA // Generates a textual failure message when a death test finds more than // one thread running, or cannot determine the number of threads, prior // to executing the given statement. It is the responsibility of the @@ -229,13 +241,19 @@ static std::string DeathTestThreadWarning(size_t thread_count) { Message msg; msg << "Death tests use fork(), which is unsafe particularly" << " in a threaded context. For this test, " << GTEST_NAME_ << " "; - if (thread_count == 0) + if (thread_count == 0) { msg << "couldn't detect the number of threads."; - else + } else { msg << "detected " << thread_count << " threads."; + } + msg << " See " + "https://github.com/google/googletest/blob/master/googletest/docs/" + "advanced.md#death-tests-and-threads" + << " for more explanation and suggested solutions, especially if" + << " this is the last message you see before your test times out."; return msg.GetString(); } -# endif // !GTEST_OS_WINDOWS +# endif // !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA // Flag characters for reporting a death test that did not die. static const char kDeathTestLived = 'L'; @@ -243,6 +261,13 @@ static const char kDeathTestReturned = 'R'; static const char kDeathTestThrew = 'T'; static const char kDeathTestInternalError = 'I'; +#if GTEST_OS_FUCHSIA + +// File descriptor used for the pipe in the child process. +static const int kFuchsiaReadPipeFd = 3; + +#endif + // An enumeration describing all of the possible ways that a death test can // conclude. DIED means that the process died while executing the test // code; LIVED means that process lived beyond the end of the test code; @@ -250,8 +275,6 @@ static const char kDeathTestInternalError = 'I'; // statement, which is not allowed; THREW means that the test statement // returned control by throwing an exception. IN_PROGRESS means the test // has not yet concluded. -// TODO(vladl@google.com): Unify names and possibly values for -// AbortReason, DeathTestOutcome, and flag characters above. enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW }; // Routine for aborting the program which is safe to call from an @@ -259,13 +282,13 @@ enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW }; // message is propagated back to the parent process. Otherwise, the // message is simply printed to stderr. In either case, the program // then exits with status 1. -void DeathTestAbort(const std::string& message) { +static void DeathTestAbort(const std::string& message) { // On a POSIX system, this function may be called from a threadsafe-style // death test child process, which operates on a very small stack. Use // the heap for any additional non-minuscule memory requirements. const InternalRunDeathTestFlag* const flag = GetUnitTestImpl()->internal_run_death_test_flag(); - if (flag != NULL) { + if (flag != nullptr) { FILE* parent = posix::FDOpen(flag->write_fd(), "w"); fputc(kDeathTestInternalError, parent); fprintf(parent, "%s", message.c_str()); @@ -345,7 +368,7 @@ static void FailFromInternalError(int fd) { // for the current test. DeathTest::DeathTest() { TestInfo* const info = GetUnitTestImpl()->current_test_info(); - if (info == NULL) { + if (info == nullptr) { DeathTestAbort("Cannot run a death test outside of a TEST or " "TEST_F construct"); } @@ -353,10 +376,11 @@ DeathTest::DeathTest() { // Creates and returns a death test by dispatching to the current // death test factory. -bool DeathTest::Create(const char* statement, const RE* regex, - const char* file, int line, DeathTest** test) { +bool DeathTest::Create(const char* statement, + Matcher matcher, const char* file, + int line, DeathTest** test) { return GetUnitTestImpl()->death_test_factory()->Create( - statement, regex, file, line, test); + statement, std::move(matcher), file, line, test); } const char* DeathTest::LastMessage() { @@ -372,9 +396,9 @@ std::string DeathTest::last_death_test_message_; // Provides cross platform implementation for some death functionality. class DeathTestImpl : public DeathTest { protected: - DeathTestImpl(const char* a_statement, const RE* a_regex) + DeathTestImpl(const char* a_statement, Matcher matcher) : statement_(a_statement), - regex_(a_regex), + matcher_(std::move(matcher)), spawned_(false), status_(-1), outcome_(IN_PROGRESS), @@ -382,13 +406,12 @@ class DeathTestImpl : public DeathTest { write_fd_(-1) {} // read_fd_ is expected to be closed and cleared by a derived class. - ~DeathTestImpl() { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); } + ~DeathTestImpl() override { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); } - void Abort(AbortReason reason); - virtual bool Passed(bool status_ok); + void Abort(AbortReason reason) override; + bool Passed(bool status_ok) override; const char* statement() const { return statement_; } - const RE* regex() const { return regex_; } bool spawned() const { return spawned_; } void set_spawned(bool is_spawned) { spawned_ = is_spawned; } int status() const { return status_; } @@ -406,13 +429,15 @@ class DeathTestImpl : public DeathTest { // case of unexpected codes. void ReadAndInterpretStatusByte(); + // Returns stderr output from the child process. + virtual std::string GetErrorLogs(); + private: // The textual content of the code this object is testing. This class // doesn't own this string and should not attempt to delete it. const char* const statement_; - // The regular expression which test output must match. DeathTestImpl - // doesn't own this object and should not attempt to delete it. - const RE* const regex_; + // A matcher that's expected to match the stderr output by the child process. + Matcher matcher_; // True if the death test child process has been successfully spawned. bool spawned_; // The exit status of the child process. @@ -474,6 +499,10 @@ void DeathTestImpl::ReadAndInterpretStatusByte() { set_read_fd(-1); } +std::string DeathTestImpl::GetErrorLogs() { + return GetCapturedStderr(); +} + // Signals that the death test code which should have exited, didn't. // Should be called only in a death test child process. // Writes a status byte to the child's status file descriptor, then @@ -527,22 +556,21 @@ static ::std::string FormatDeathTestOutput(const ::std::string& output) { // in the format specified by wait(2). On Windows, this is the // value supplied to the ExitProcess() API or a numeric code // of the exception that terminated the program. -// regex: A regular expression object to be applied to -// the test's captured standard error output; the death test -// fails if it does not match. +// matcher_: A matcher that's expected to match the stderr output by the child +// process. // // Argument: // status_ok: true if exit_status is acceptable in the context of // this particular death test, which fails if it is false // -// Returns true iff all of the above conditions are met. Otherwise, the -// first failing condition, in the order given above, is the one that is +// Returns true if and only if all of the above conditions are met. Otherwise, +// the first failing condition, in the order given above, is the one that is // reported. Also sets the last death test message string. bool DeathTestImpl::Passed(bool status_ok) { if (!spawned()) return false; - const std::string error_message = GetCapturedStderr(); + const std::string error_message = GetErrorLogs(); bool success = false; Message buffer; @@ -563,13 +591,15 @@ bool DeathTestImpl::Passed(bool status_ok) { break; case DIED: if (status_ok) { - const bool matched = RE::PartialMatch(error_message.c_str(), *regex()); - if (matched) { + if (matcher_.Matches(error_message)) { success = true; } else { + std::ostringstream stream; + matcher_.DescribeTo(&stream); buffer << " Result: died but not with expected error.\n" - << " Expected: " << regex()->pattern() << "\n" - << "Actual msg:\n" << FormatDeathTestOutput(error_message); + << " Expected: " << stream.str() << "\n" + << "Actual msg:\n" + << FormatDeathTestOutput(error_message); } } else { buffer << " Result: died but not with expected exit code:\n" @@ -618,11 +648,11 @@ bool DeathTestImpl::Passed(bool status_ok) { // class WindowsDeathTest : public DeathTestImpl { public: - WindowsDeathTest(const char* a_statement, - const RE* a_regex, - const char* file, - int line) - : DeathTestImpl(a_statement, a_regex), file_(file), line_(line) {} + WindowsDeathTest(const char* a_statement, Matcher matcher, + const char* file, int line) + : DeathTestImpl(a_statement, std::move(matcher)), + file_(file), + line_(line) {} // All of these virtual functions are inherited from DeathTest. virtual int Wait(); @@ -699,7 +729,7 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() { const TestInfo* const info = impl->current_test_info(); const int death_test_index = info->result()->death_test_count(); - if (flag != NULL) { + if (flag != nullptr) { // ParseInternalRunDeathTestFlag() has performed all the necessary // processing. set_write_fd(flag->write_fd()); @@ -708,8 +738,8 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() { // WindowsDeathTest uses an anonymous pipe to communicate results of // a death test. - SECURITY_ATTRIBUTES handles_are_inheritable = { - sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; + SECURITY_ATTRIBUTES handles_are_inheritable = {sizeof(SECURITY_ATTRIBUTES), + nullptr, TRUE}; HANDLE read_handle, write_handle; GTEST_DEATH_TEST_CHECK_( ::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable, @@ -720,13 +750,13 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() { write_handle_.Reset(write_handle); event_handle_.Reset(::CreateEvent( &handles_are_inheritable, - TRUE, // The event will automatically reset to non-signaled state. - FALSE, // The initial state is non-signalled. - NULL)); // The even is unnamed. - GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != NULL); - const std::string filter_flag = - std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "=" + - info->test_case_name() + "." + info->name(); + TRUE, // The event will automatically reset to non-signaled state. + FALSE, // The initial state is non-signalled. + nullptr)); // The even is unnamed. + GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != nullptr); + const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ + + kFilterFlag + "=" + info->test_suite_name() + + "." + info->name(); const std::string internal_flag = std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "=" + file_ + "|" + StreamableToString(line_) + "|" + @@ -739,10 +769,9 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() { "|" + StreamableToString(reinterpret_cast(event_handle_.Get())); char executable_path[_MAX_PATH + 1]; // NOLINT - GTEST_DEATH_TEST_CHECK_( - _MAX_PATH + 1 != ::GetModuleFileNameA(NULL, - executable_path, - _MAX_PATH)); + GTEST_DEATH_TEST_CHECK_(_MAX_PATH + 1 != ::GetModuleFileNameA(nullptr, + executable_path, + _MAX_PATH)); std::string command_line = std::string(::GetCommandLineA()) + " " + filter_flag + " \"" + @@ -763,33 +792,290 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() { startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE); PROCESS_INFORMATION process_info; - GTEST_DEATH_TEST_CHECK_(::CreateProcessA( - executable_path, - const_cast(command_line.c_str()), - NULL, // Retuned process handle is not inheritable. - NULL, // Retuned thread handle is not inheritable. - TRUE, // Child inherits all inheritable handles (for write_handle_). - 0x0, // Default creation flags. - NULL, // Inherit the parent's environment. - UnitTest::GetInstance()->original_working_dir(), - &startup_info, - &process_info) != FALSE); + GTEST_DEATH_TEST_CHECK_( + ::CreateProcessA( + executable_path, const_cast(command_line.c_str()), + nullptr, // Retuned process handle is not inheritable. + nullptr, // Retuned thread handle is not inheritable. + TRUE, // Child inherits all inheritable handles (for write_handle_). + 0x0, // Default creation flags. + nullptr, // Inherit the parent's environment. + UnitTest::GetInstance()->original_working_dir(), &startup_info, + &process_info) != FALSE); child_handle_.Reset(process_info.hProcess); ::CloseHandle(process_info.hThread); set_spawned(true); return OVERSEE_TEST; } -# else // We are not on Windows. + +# elif GTEST_OS_FUCHSIA + +class FuchsiaDeathTest : public DeathTestImpl { + public: + FuchsiaDeathTest(const char* a_statement, Matcher matcher, + const char* file, int line) + : DeathTestImpl(a_statement, std::move(matcher)), + file_(file), + line_(line) {} + + // All of these virtual functions are inherited from DeathTest. + int Wait() override; + TestRole AssumeRole() override; + std::string GetErrorLogs() override; + + private: + // The name of the file in which the death test is located. + const char* const file_; + // The line number on which the death test is located. + const int line_; + // The stderr data captured by the child process. + std::string captured_stderr_; + + zx::process child_process_; + zx::channel exception_channel_; + zx::socket stderr_socket_; +}; + +// Utility class for accumulating command-line arguments. +class Arguments { + public: + Arguments() { args_.push_back(nullptr); } + + ~Arguments() { + for (std::vector::iterator i = args_.begin(); i != args_.end(); + ++i) { + free(*i); + } + } + void AddArgument(const char* argument) { + args_.insert(args_.end() - 1, posix::StrDup(argument)); + } + + template + void AddArguments(const ::std::vector& arguments) { + for (typename ::std::vector::const_iterator i = arguments.begin(); + i != arguments.end(); + ++i) { + args_.insert(args_.end() - 1, posix::StrDup(i->c_str())); + } + } + char* const* Argv() { + return &args_[0]; + } + + int size() { + return args_.size() - 1; + } + + private: + std::vector args_; +}; + +// Waits for the child in a death test to exit, returning its exit +// status, or 0 if no child process exists. As a side effect, sets the +// outcome data member. +int FuchsiaDeathTest::Wait() { + const int kProcessKey = 0; + const int kSocketKey = 1; + const int kExceptionKey = 2; + + if (!spawned()) + return 0; + + // Create a port to wait for socket/task/exception events. + zx_status_t status_zx; + zx::port port; + status_zx = zx::port::create(0, &port); + GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); + + // Register to wait for the child process to terminate. + status_zx = child_process_.wait_async( + port, kProcessKey, ZX_PROCESS_TERMINATED, ZX_WAIT_ASYNC_ONCE); + GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); + + // Register to wait for the socket to be readable or closed. + status_zx = stderr_socket_.wait_async( + port, kSocketKey, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED, + ZX_WAIT_ASYNC_ONCE); + GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); + + // Register to wait for an exception. + status_zx = exception_channel_.wait_async( + port, kExceptionKey, ZX_CHANNEL_READABLE, ZX_WAIT_ASYNC_ONCE); + GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); + + bool process_terminated = false; + bool socket_closed = false; + do { + zx_port_packet_t packet = {}; + status_zx = port.wait(zx::time::infinite(), &packet); + GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); + + if (packet.key == kExceptionKey) { + // Process encountered an exception. Kill it directly rather than + // letting other handlers process the event. We will get a kProcessKey + // event when the process actually terminates. + status_zx = child_process_.kill(); + GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); + } else if (packet.key == kProcessKey) { + // Process terminated. + GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_ONE(packet.type)); + GTEST_DEATH_TEST_CHECK_(packet.signal.observed & ZX_PROCESS_TERMINATED); + process_terminated = true; + } else if (packet.key == kSocketKey) { + GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_ONE(packet.type)); + if (packet.signal.observed & ZX_SOCKET_READABLE) { + // Read data from the socket. + constexpr size_t kBufferSize = 1024; + do { + size_t old_length = captured_stderr_.length(); + size_t bytes_read = 0; + captured_stderr_.resize(old_length + kBufferSize); + status_zx = stderr_socket_.read( + 0, &captured_stderr_.front() + old_length, kBufferSize, + &bytes_read); + captured_stderr_.resize(old_length + bytes_read); + } while (status_zx == ZX_OK); + if (status_zx == ZX_ERR_PEER_CLOSED) { + socket_closed = true; + } else { + GTEST_DEATH_TEST_CHECK_(status_zx == ZX_ERR_SHOULD_WAIT); + status_zx = stderr_socket_.wait_async( + port, kSocketKey, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED, + ZX_WAIT_ASYNC_ONCE); + GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); + } + } else { + GTEST_DEATH_TEST_CHECK_(packet.signal.observed & ZX_SOCKET_PEER_CLOSED); + socket_closed = true; + } + } + } while (!process_terminated && !socket_closed); + + ReadAndInterpretStatusByte(); + + zx_info_process_t buffer; + status_zx = child_process_.get_info( + ZX_INFO_PROCESS, &buffer, sizeof(buffer), nullptr, nullptr); + GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK); + + GTEST_DEATH_TEST_CHECK_(buffer.exited); + set_status(buffer.return_code); + return status(); +} + +// The AssumeRole process for a Fuchsia death test. It creates a child +// process with the same executable as the current process to run the +// death test. The child process is given the --gtest_filter and +// --gtest_internal_run_death_test flags such that it knows to run the +// current death test only. +DeathTest::TestRole FuchsiaDeathTest::AssumeRole() { + const UnitTestImpl* const impl = GetUnitTestImpl(); + const InternalRunDeathTestFlag* const flag = + impl->internal_run_death_test_flag(); + const TestInfo* const info = impl->current_test_info(); + const int death_test_index = info->result()->death_test_count(); + + if (flag != nullptr) { + // ParseInternalRunDeathTestFlag() has performed all the necessary + // processing. + set_write_fd(kFuchsiaReadPipeFd); + return EXECUTE_TEST; + } + + // Flush the log buffers since the log streams are shared with the child. + FlushInfoLog(); + + // Build the child process command line. + const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ + + kFilterFlag + "=" + info->test_suite_name() + + "." + info->name(); + const std::string internal_flag = + std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "=" + + file_ + "|" + + StreamableToString(line_) + "|" + + StreamableToString(death_test_index); + Arguments args; + args.AddArguments(GetInjectableArgvs()); + args.AddArgument(filter_flag.c_str()); + args.AddArgument(internal_flag.c_str()); + + // Build the pipe for communication with the child. + zx_status_t status; + zx_handle_t child_pipe_handle; + int child_pipe_fd; + status = fdio_pipe_half(&child_pipe_fd, &child_pipe_handle); + GTEST_DEATH_TEST_CHECK_(status == ZX_OK); + set_read_fd(child_pipe_fd); + + // Set the pipe handle for the child. + fdio_spawn_action_t spawn_actions[2] = {}; + fdio_spawn_action_t* add_handle_action = &spawn_actions[0]; + add_handle_action->action = FDIO_SPAWN_ACTION_ADD_HANDLE; + add_handle_action->h.id = PA_HND(PA_FD, kFuchsiaReadPipeFd); + add_handle_action->h.handle = child_pipe_handle; + + // Create a socket pair will be used to receive the child process' stderr. + zx::socket stderr_producer_socket; + status = + zx::socket::create(0, &stderr_producer_socket, &stderr_socket_); + GTEST_DEATH_TEST_CHECK_(status >= 0); + int stderr_producer_fd = -1; + status = + fdio_fd_create(stderr_producer_socket.release(), &stderr_producer_fd); + GTEST_DEATH_TEST_CHECK_(status >= 0); + + // Make the stderr socket nonblocking. + GTEST_DEATH_TEST_CHECK_(fcntl(stderr_producer_fd, F_SETFL, 0) == 0); + + fdio_spawn_action_t* add_stderr_action = &spawn_actions[1]; + add_stderr_action->action = FDIO_SPAWN_ACTION_CLONE_FD; + add_stderr_action->fd.local_fd = stderr_producer_fd; + add_stderr_action->fd.target_fd = STDERR_FILENO; + + // Create a child job. + zx_handle_t child_job = ZX_HANDLE_INVALID; + status = zx_job_create(zx_job_default(), 0, & child_job); + GTEST_DEATH_TEST_CHECK_(status == ZX_OK); + zx_policy_basic_t policy; + policy.condition = ZX_POL_NEW_ANY; + policy.policy = ZX_POL_ACTION_ALLOW; + status = zx_job_set_policy( + child_job, ZX_JOB_POL_RELATIVE, ZX_JOB_POL_BASIC, &policy, 1); + GTEST_DEATH_TEST_CHECK_(status == ZX_OK); + + // Create an exception channel attached to the |child_job|, to allow + // us to suppress the system default exception handler from firing. + status = + zx_task_create_exception_channel( + child_job, 0, exception_channel_.reset_and_get_address()); + GTEST_DEATH_TEST_CHECK_(status == ZX_OK); + + // Spawn the child process. + status = fdio_spawn_etc( + child_job, FDIO_SPAWN_CLONE_ALL, args.Argv()[0], args.Argv(), nullptr, + 2, spawn_actions, child_process_.reset_and_get_address(), nullptr); + GTEST_DEATH_TEST_CHECK_(status == ZX_OK); + + set_spawned(true); + return OVERSEE_TEST; +} + +std::string FuchsiaDeathTest::GetErrorLogs() { + return captured_stderr_; +} + +#else // We are neither on Windows, nor on Fuchsia. // ForkingDeathTest provides implementations for most of the abstract // methods of the DeathTest interface. Only the AssumeRole method is // left undefined. class ForkingDeathTest : public DeathTestImpl { public: - ForkingDeathTest(const char* statement, const RE* regex); + ForkingDeathTest(const char* statement, Matcher matcher); // All of these virtual functions are inherited from DeathTest. - virtual int Wait(); + int Wait() override; protected: void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; } @@ -800,9 +1086,9 @@ class ForkingDeathTest : public DeathTestImpl { }; // Constructs a ForkingDeathTest. -ForkingDeathTest::ForkingDeathTest(const char* a_statement, const RE* a_regex) - : DeathTestImpl(a_statement, a_regex), - child_pid_(-1) {} +ForkingDeathTest::ForkingDeathTest(const char* a_statement, + Matcher matcher) + : DeathTestImpl(a_statement, std::move(matcher)), child_pid_(-1) {} // Waits for the child in a death test to exit, returning its exit // status, or 0 if no child process exists. As a side effect, sets the @@ -823,9 +1109,9 @@ int ForkingDeathTest::Wait() { // in the child process. class NoExecDeathTest : public ForkingDeathTest { public: - NoExecDeathTest(const char* a_statement, const RE* a_regex) : - ForkingDeathTest(a_statement, a_regex) { } - virtual TestRole AssumeRole(); + NoExecDeathTest(const char* a_statement, Matcher matcher) + : ForkingDeathTest(a_statement, std::move(matcher)) {} + TestRole AssumeRole() override; }; // The AssumeRole process for a fork-and-run death test. It implements a @@ -878,10 +1164,13 @@ DeathTest::TestRole NoExecDeathTest::AssumeRole() { // only this specific death test to be run. class ExecDeathTest : public ForkingDeathTest { public: - ExecDeathTest(const char* a_statement, const RE* a_regex, - const char* file, int line) : - ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { } - virtual TestRole AssumeRole(); + ExecDeathTest(const char* a_statement, Matcher matcher, + const char* file, int line) + : ForkingDeathTest(a_statement, std::move(matcher)), + file_(file), + line_(line) {} + TestRole AssumeRole() override; + private: static ::std::vector GetArgvsForDeathTestChildProcess() { ::std::vector args = GetInjectableArgvs(); @@ -901,9 +1190,7 @@ class ExecDeathTest : public ForkingDeathTest { // Utility class for accumulating command-line arguments. class Arguments { public: - Arguments() { - args_.push_back(NULL); - } + Arguments() { args_.push_back(nullptr); } ~Arguments() { for (std::vector::iterator i = args_.begin(); i != args_.end(); @@ -985,6 +1272,7 @@ static int ExecDeathTestChildMain(void* child_arg) { } # endif // !GTEST_OS_QNX +# if GTEST_HAS_CLONE // Two utility routines that together determine the direction the stack // grows. // This could be accomplished more elegantly by a single recursive @@ -994,20 +1282,26 @@ static int ExecDeathTestChildMain(void* child_arg) { // GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining // StackLowerThanAddress into StackGrowsDown, which then doesn't give // correct answer. -void StackLowerThanAddress(const void* ptr, bool* result) GTEST_NO_INLINE_; -void StackLowerThanAddress(const void* ptr, bool* result) { +static void StackLowerThanAddress(const void* ptr, + bool* result) GTEST_NO_INLINE_; +// HWAddressSanitizer add a random tag to the MSB of the local variable address, +// making comparison result unpredictable. +GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_ +static void StackLowerThanAddress(const void* ptr, bool* result) { int dummy; *result = (&dummy < ptr); } // Make sure AddressSanitizer does not tamper with the stack here. GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ -bool StackGrowsDown() { +GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_ +static bool StackGrowsDown() { int dummy; bool result; StackLowerThanAddress(&dummy, &result); return result; } +# endif // GTEST_HAS_CLONE // Spawns a child process with the same executable as the current process in // a thread-safe manner and instructs it to run the death test. The @@ -1045,7 +1339,8 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) { fd_flags | FD_CLOEXEC)); struct inheritance inherit = {0}; // spawn is a system call. - child_pid = spawn(args.argv[0], 0, NULL, &inherit, args.argv, GetEnviron()); + child_pid = + spawn(args.argv[0], 0, nullptr, &inherit, args.argv, GetEnviron()); // Restores the current working directory. GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1); GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd)); @@ -1069,9 +1364,9 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) { if (!use_fork) { static const bool stack_grows_down = StackGrowsDown(); - const size_t stack_size = getpagesize(); + const auto stack_size = static_cast(getpagesize()); // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead. - void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, + void* const stack = mmap(nullptr, stack_size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED); @@ -1085,8 +1380,9 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) { void* const stack_top = static_cast(stack) + (stack_grows_down ? stack_size - kMaxStackAlignment : 0); - GTEST_DEATH_TEST_CHECK_(stack_size > kMaxStackAlignment && - reinterpret_cast(stack_top) % kMaxStackAlignment == 0); + GTEST_DEATH_TEST_CHECK_( + static_cast(stack_size) > kMaxStackAlignment && + reinterpret_cast(stack_top) % kMaxStackAlignment == 0); child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args); @@ -1103,7 +1399,7 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) { # endif // GTEST_OS_QNX # if GTEST_OS_LINUX GTEST_DEATH_TEST_CHECK_SYSCALL_( - sigaction(SIGPROF, &saved_sigprof_action, NULL)); + sigaction(SIGPROF, &saved_sigprof_action, nullptr)); # endif // GTEST_OS_LINUX GTEST_DEATH_TEST_CHECK_(child_pid != -1); @@ -1121,7 +1417,7 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() { const TestInfo* const info = impl->current_test_info(); const int death_test_index = info->result()->death_test_count(); - if (flag != NULL) { + if (flag != nullptr) { set_write_fd(flag->write_fd()); return EXECUTE_TEST; } @@ -1132,9 +1428,9 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() { // it be closed when the child process does an exec: GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1); - const std::string filter_flag = - std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "=" - + info->test_case_name() + "." + info->name(); + const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ + + kFilterFlag + "=" + info->test_suite_name() + + "." + info->name(); const std::string internal_flag = std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "=" + file_ + "|" + StreamableToString(line_) + "|" @@ -1167,7 +1463,8 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() { // by the "test" argument to its address. If the test should be // skipped, sets that pointer to NULL. Returns true, unless the // flag is set to an invalid value. -bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex, +bool DefaultDeathTestFactory::Create(const char* statement, + Matcher matcher, const char* file, int line, DeathTest** test) { UnitTestImpl* const impl = GetUnitTestImpl(); @@ -1176,7 +1473,7 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex, const int death_test_index = impl->current_test_info() ->increment_death_test_count(); - if (flag != NULL) { + if (flag != nullptr) { if (death_test_index > flag->index()) { DeathTest::set_last_death_test_message( "Death test count (" + StreamableToString(death_test_index) @@ -1187,7 +1484,7 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex, if (!(flag->file() == file && flag->line() == line && flag->index() == death_test_index)) { - *test = NULL; + *test = nullptr; return true; } } @@ -1196,15 +1493,22 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex, if (GTEST_FLAG(death_test_style) == "threadsafe" || GTEST_FLAG(death_test_style) == "fast") { - *test = new WindowsDeathTest(statement, regex, file, line); + *test = new WindowsDeathTest(statement, std::move(matcher), file, line); + } + +# elif GTEST_OS_FUCHSIA + + if (GTEST_FLAG(death_test_style) == "threadsafe" || + GTEST_FLAG(death_test_style) == "fast") { + *test = new FuchsiaDeathTest(statement, std::move(matcher), file, line); } # else if (GTEST_FLAG(death_test_style) == "threadsafe") { - *test = new ExecDeathTest(statement, regex, file, line); + *test = new ExecDeathTest(statement, std::move(matcher), file, line); } else if (GTEST_FLAG(death_test_style) == "fast") { - *test = new NoExecDeathTest(statement, regex); + *test = new NoExecDeathTest(statement, std::move(matcher)); } # endif // GTEST_OS_WINDOWS @@ -1223,7 +1527,7 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex, // Recreates the pipe and event handles from the provided parameters, // signals the event, and returns a file descriptor wrapped around the pipe // handle. This function is called in the child process only. -int GetStatusFileDescriptor(unsigned int parent_process_id, +static int GetStatusFileDescriptor(unsigned int parent_process_id, size_t write_handle_as_size_t, size_t event_handle_as_size_t) { AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE, @@ -1234,15 +1538,13 @@ int GetStatusFileDescriptor(unsigned int parent_process_id, StreamableToString(parent_process_id)); } - // TODO(vladl@google.com): Replace the following check with a - // compile-time assertion when available. GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t)); const HANDLE write_handle = reinterpret_cast(write_handle_as_size_t); HANDLE dup_write_handle; - // The newly initialized handle is accessible only in in the parent + // The newly initialized handle is accessible only in the parent // process. To obtain one accessible within the child, we need to use // DuplicateHandle. if (!::DuplicateHandle(parent_process_handle.Get(), write_handle, @@ -1291,7 +1593,7 @@ int GetStatusFileDescriptor(unsigned int parent_process_id, // initialized from the GTEST_FLAG(internal_run_death_test) flag if // the flag is specified; otherwise returns NULL. InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() { - if (GTEST_FLAG(internal_run_death_test) == "") return NULL; + if (GTEST_FLAG(internal_run_death_test) == "") return nullptr; // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we // can use it here. @@ -1319,6 +1621,16 @@ InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() { write_fd = GetStatusFileDescriptor(parent_process_id, write_handle_as_size_t, event_handle_as_size_t); + +# elif GTEST_OS_FUCHSIA + + if (fields.size() != 3 + || !ParseNaturalNumber(fields[1], &line) + || !ParseNaturalNumber(fields[2], &index)) { + DeathTestAbort("Bad --gtest_internal_run_death_test flag: " + + GTEST_FLAG(internal_run_death_test)); + } + # else if (fields.size() != 4 diff --git a/cpp/test/src/gtest-filepath.cc b/cpp/test/src/gtest-filepath.cc index 0292dc1195..9aad12fbd1 100644 --- a/cpp/test/src/gtest-filepath.cc +++ b/cpp/test/src/gtest-filepath.cc @@ -26,28 +26,25 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Authors: keith.ray@gmail.com (Keith Ray) -#include "gtest/gtest-message.h" #include "gtest/internal/gtest-filepath.h" -#include "gtest/internal/gtest-port.h" #include +#include "gtest/internal/gtest-port.h" +#include "gtest/gtest-message.h" #if GTEST_OS_WINDOWS_MOBILE # include #elif GTEST_OS_WINDOWS # include # include -#elif GTEST_OS_SYMBIAN -// Symbian OpenC has PATH_MAX in sys/syslimits.h -# include #else # include # include // Some Linux distributions define PATH_MAX here. #endif // GTEST_OS_WINDOWS_MOBILE +#include "gtest/internal/gtest-string.h" + #if GTEST_OS_WINDOWS # define GTEST_PATH_MAX_ _MAX_PATH #elif defined(PATH_MAX) @@ -58,8 +55,6 @@ # define GTEST_PATH_MAX_ _POSIX_PATH_MAX #endif // GTEST_OS_WINDOWS -#include "gtest/internal/gtest-string.h" - namespace testing { namespace internal { @@ -97,13 +92,14 @@ static bool IsPathSeparator(char c) { // Returns the current working directory, or "" if unsuccessful. FilePath FilePath::GetCurrentDir() { -#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT - // Windows CE doesn't have a current directory, so we just return +#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || \ + GTEST_OS_WINDOWS_RT || GTEST_OS_ESP8266 || GTEST_OS_ESP32 + // These platforms do not have a current directory, so we just return // something reasonable. return FilePath(kCurrentDirectoryString); #elif GTEST_OS_WINDOWS char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; - return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd); + return FilePath(_getcwd(cwd, sizeof(cwd)) == nullptr ? "" : cwd); #else char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; char* result = getcwd(cwd, sizeof(cwd)); @@ -111,9 +107,9 @@ FilePath FilePath::GetCurrentDir() { // getcwd will likely fail in NaCl due to the sandbox, so return something // reasonable. The user may have provided a shim implementation for getcwd, // however, so fallback only when failure is detected. - return FilePath(result == NULL ? kCurrentDirectoryString : cwd); + return FilePath(result == nullptr ? kCurrentDirectoryString : cwd); # endif // GTEST_OS_NACL - return FilePath(result == NULL ? "" : cwd); + return FilePath(result == nullptr ? "" : cwd); #endif // GTEST_OS_WINDOWS_MOBILE } @@ -130,7 +126,7 @@ FilePath FilePath::RemoveExtension(const char* extension) const { return *this; } -// Returns a pointer to the last occurence of a valid path separator in +// Returns a pointer to the last occurrence of a valid path separator in // the FilePath. On Windows, for example, both '/' and '\' are valid path // separators. Returns NULL if no path separator was found. const char* FilePath::FindLastPathSeparator() const { @@ -138,8 +134,8 @@ const char* FilePath::FindLastPathSeparator() const { #if GTEST_HAS_ALT_PATH_SEP_ const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator); // Comparing two pointers of which only one is NULL is undefined. - if (last_alt_sep != NULL && - (last_sep == NULL || last_alt_sep > last_sep)) { + if (last_alt_sep != nullptr && + (last_sep == nullptr || last_alt_sep > last_sep)) { return last_alt_sep; } #endif @@ -167,7 +163,7 @@ FilePath FilePath::RemoveFileName() const { const char* const last_sep = FindLastPathSeparator(); std::string dir; if (last_sep) { - dir = std::string(c_str(), last_sep + 1 - c_str()); + dir = std::string(c_str(), static_cast(last_sep + 1 - c_str())); } else { dir = kCurrentDirectoryString; } @@ -252,9 +248,6 @@ bool FilePath::DirectoryExists() const { // root directory per disk drive.) bool FilePath::IsRootDirectory() const { #if GTEST_OS_WINDOWS - // TODO(wan@google.com): on Windows a network share like - // \\server\share can be a root directory, although it cannot be the - // current directory. Handle this properly. return pathname_.length() == 3 && IsAbsolutePath(); #else return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]); @@ -326,10 +319,13 @@ bool FilePath::CreateFolder() const { #if GTEST_OS_WINDOWS_MOBILE FilePath removed_sep(this->RemoveTrailingPathSeparator()); LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str()); - int result = CreateDirectory(unicode, NULL) ? 0 : -1; + int result = CreateDirectory(unicode, nullptr) ? 0 : -1; delete [] unicode; #elif GTEST_OS_WINDOWS int result = _mkdir(pathname_.c_str()); +#elif GTEST_OS_ESP8266 + // do nothing + int result = 0; #else int result = mkdir(pathname_.c_str(), 0777); #endif // GTEST_OS_WINDOWS_MOBILE @@ -352,9 +348,8 @@ FilePath FilePath::RemoveTrailingPathSeparator() const { // Removes any redundant separators that might be in the pathname. // For example, "bar///foo" becomes "bar/foo". Does not eliminate other // redundancies that might be in a pathname involving "." or "..". -// TODO(wan@google.com): handle Windows network shares (e.g. \\server\share). void FilePath::Normalize() { - if (pathname_.c_str() == NULL) { + if (pathname_.c_str() == nullptr) { pathname_ = ""; return; } diff --git a/cpp/test/src/gtest-internal-inl.h b/cpp/test/src/gtest-internal-inl.h index 021feb16f9..8ed70daab0 100644 --- a/cpp/test/src/gtest-internal-inl.h +++ b/cpp/test/src/gtest-internal-inl.h @@ -27,24 +27,13 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Utility functions and classes used by the Google C++ testing framework. -// -// Author: wan@google.com (Zhanyong Wan) -// +// Utility functions and classes used by the Google C++ testing framework.// // This file contains purely Google Test's internal implementation. Please // DO NOT #INCLUDE IT IN A USER PROGRAM. #ifndef GTEST_SRC_GTEST_INTERNAL_INL_H_ #define GTEST_SRC_GTEST_INTERNAL_INL_H_ -// GTEST_IMPLEMENTATION_ is defined to 1 iff the current translation unit is -// part of Google Test's implementation; otherwise it's undefined. -#if !GTEST_IMPLEMENTATION_ -// If this file is included from the user's code, just say no. -# error "gtest-internal-inl.h is part of Google Test's internal implementation." -# error "It must not be included except by Google Test itself." -#endif // GTEST_IMPLEMENTATION_ - #ifndef _WIN32_WCE # include #endif // !_WIN32_WCE @@ -53,6 +42,7 @@ #include // For memmove. #include +#include #include #include @@ -67,9 +57,12 @@ # include // NOLINT #endif // GTEST_OS_WINDOWS -#include "gtest/gtest.h" // NOLINT +#include "gtest/gtest.h" #include "gtest/gtest-spi.h" +GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ +/* class A needs to have dll-interface to be used by clients of class B */) + namespace testing { // Declares the flags. @@ -94,6 +87,7 @@ const char kFilterFlag[] = "filter"; const char kListTestsFlag[] = "list_tests"; const char kOutputFlag[] = "output"; const char kPrintTimeFlag[] = "print_time"; +const char kPrintUTF8Flag[] = "print_utf8"; const char kRandomSeedFlag[] = "random_seed"; const char kRepeatFlag[] = "repeat"; const char kShuffleFlag[] = "shuffle"; @@ -105,14 +99,14 @@ const char kFlagfileFlag[] = "flagfile"; // A valid random seed must be in [1, kMaxRandomSeed]. const int kMaxRandomSeed = 99999; -// g_help_flag is true iff the --help flag or an equivalent form is -// specified on the command line. +// g_help_flag is true if and only if the --help flag or an equivalent form +// is specified on the command line. GTEST_API_ extern bool g_help_flag; // Returns the current time in milliseconds. GTEST_API_ TimeInMillis GetTimeInMillis(); -// Returns true iff Google Test should use colors in the output. +// Returns true if and only if Google Test should use colors in the output. GTEST_API_ bool ShouldUseColor(bool stdout_is_tty); // Formats the given time in milliseconds as seconds. @@ -174,6 +168,7 @@ class GTestFlagSaver { list_tests_ = GTEST_FLAG(list_tests); output_ = GTEST_FLAG(output); print_time_ = GTEST_FLAG(print_time); + print_utf8_ = GTEST_FLAG(print_utf8); random_seed_ = GTEST_FLAG(random_seed); repeat_ = GTEST_FLAG(repeat); shuffle_ = GTEST_FLAG(shuffle); @@ -195,6 +190,7 @@ class GTestFlagSaver { GTEST_FLAG(list_tests) = list_tests_; GTEST_FLAG(output) = output_; GTEST_FLAG(print_time) = print_time_; + GTEST_FLAG(print_utf8) = print_utf8_; GTEST_FLAG(random_seed) = random_seed_; GTEST_FLAG(repeat) = repeat_; GTEST_FLAG(shuffle) = shuffle_; @@ -216,6 +212,7 @@ class GTestFlagSaver { bool list_tests_; std::string output_; bool print_time_; + bool print_utf8_; internal::Int32 random_seed_; internal::Int32 repeat_; bool shuffle_; @@ -234,7 +231,7 @@ GTEST_API_ std::string CodePointToUtf8(UInt32 code_point); // Converts a wide string to a narrow string in UTF-8 encoding. // The wide string is assumed to have the following encoding: -// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS) +// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin) // UTF-32 if sizeof(wchar_t) == 4 (on Linux) // Parameter str points to a null-terminated wide string. // Parameter num_chars may additionally limit the number @@ -269,8 +266,8 @@ GTEST_API_ bool ShouldShard(const char* total_shards_str, GTEST_API_ Int32 Int32FromEnvOrDie(const char* env_var, Int32 default_val); // Given the total number of shards, the shard index, and the test id, -// returns true iff the test should be run on this shard. The test id is -// some arbitrary but unique non-negative integer assigned to each test +// returns true if and only if the test should be run on this shard. The test id +// is some arbitrary but unique non-negative integer assigned to each test // method. Assumes that 0 <= shard_index < total_shards. GTEST_API_ bool ShouldRunTestOnShard( int total_shards, int shard_index, int test_id); @@ -301,7 +298,8 @@ void ForEach(const Container& c, Functor functor) { // in range [0, v.size()). template inline E GetElementOr(const std::vector& v, int i, E default_value) { - return (i < 0 || i >= static_cast(v.size())) ? default_value : v[i]; + return (i < 0 || i >= static_cast(v.size())) ? default_value + : v[static_cast(i)]; } // Performs an in-place shuffle of a range of the vector's elements. @@ -323,8 +321,11 @@ void ShuffleRange(internal::Random* random, int begin, int end, // http://en.wikipedia.org/wiki/Fisher-Yates_shuffle for (int range_width = end - begin; range_width >= 2; range_width--) { const int last_in_range = begin + range_width - 1; - const int selected = begin + random->Generate(range_width); - std::swap((*v)[selected], (*v)[last_in_range]); + const int selected = + begin + + static_cast(random->Generate(static_cast(range_width))); + std::swap((*v)[static_cast(selected)], + (*v)[static_cast(last_in_range)]); } } @@ -351,7 +352,7 @@ class TestPropertyKeyIs { // TestPropertyKeyIs has NO default constructor. explicit TestPropertyKeyIs(const std::string& key) : key_(key) {} - // Returns true iff the test name of test property matches on key_. + // Returns true if and only if the test name of test property matches on key_. bool operator()(const TestProperty& test_property) const { return test_property.key() == key_; } @@ -384,17 +385,17 @@ class GTEST_API_ UnitTestOptions { // Functions for processing the gtest_filter flag. - // Returns true iff the wildcard pattern matches the string. The - // first ':' or '\0' character in pattern marks the end of it. + // Returns true if and only if the wildcard pattern matches the string. + // The first ':' or '\0' character in pattern marks the end of it. // // This recursive algorithm isn't very efficient, but is clear and // works well enough for matching test names, which are short. static bool PatternMatchesString(const char *pattern, const char *str); - // Returns true iff the user-specified filter matches the test case - // name and the test name. - static bool FilterMatchesTest(const std::string &test_case_name, - const std::string &test_name); + // Returns true if and only if the user-specified filter matches the test + // suite name and the test name. + static bool FilterMatchesTest(const std::string& test_suite_name, + const std::string& test_name); #if GTEST_OS_WINDOWS // Function for supporting the gtest_catch_exception flag. @@ -446,10 +447,20 @@ class OsStackTraceGetter : public OsStackTraceGetterInterface { public: OsStackTraceGetter() {} - virtual std::string CurrentStackTrace(int max_depth, int skip_count); - virtual void UponLeavingGTest(); + std::string CurrentStackTrace(int max_depth, int skip_count) override; + void UponLeavingGTest() override; private: +#if GTEST_HAS_ABSL + Mutex mutex_; // Protects all internal state. + + // We save the stack frame below the frame that calls user code. + // We do this because the address of the frame immediately below + // the user code changes between the call to UponLeavingGTest() + // and any calls to the stack trace code from within the user code. + void* caller_frame_ = nullptr; +#endif // GTEST_HAS_ABSL + GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetter); }; @@ -468,7 +479,7 @@ class DefaultGlobalTestPartResultReporter explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test); // Implements the TestPartResultReporterInterface. Reports the test part // result in the current test. - virtual void ReportTestPartResult(const TestPartResult& result); + void ReportTestPartResult(const TestPartResult& result) override; private: UnitTestImpl* const unit_test_; @@ -484,7 +495,7 @@ class DefaultPerThreadTestPartResultReporter explicit DefaultPerThreadTestPartResultReporter(UnitTestImpl* unit_test); // Implements the TestPartResultReporterInterface. The implementation just // delegates to the current global test part result reporter of *unit_test_. - virtual void ReportTestPartResult(const TestPartResult& result); + void ReportTestPartResult(const TestPartResult& result) override; private: UnitTestImpl* const unit_test_; @@ -522,22 +533,25 @@ class GTEST_API_ UnitTestImpl { void SetTestPartResultReporterForCurrentThread( TestPartResultReporterInterface* reporter); - // Gets the number of successful test cases. - int successful_test_case_count() const; + // Gets the number of successful test suites. + int successful_test_suite_count() const; - // Gets the number of failed test cases. - int failed_test_case_count() const; + // Gets the number of failed test suites. + int failed_test_suite_count() const; - // Gets the number of all test cases. - int total_test_case_count() const; + // Gets the number of all test suites. + int total_test_suite_count() const; - // Gets the number of all test cases that contain at least one test + // Gets the number of all test suites that contain at least one test // that should run. - int test_case_to_run_count() const; + int test_suite_to_run_count() const; // Gets the number of successful tests. int successful_test_count() const; + // Gets the number of skipped tests. + int skipped_test_count() const; + // Gets the number of failed tests. int failed_test_count() const; @@ -563,27 +577,33 @@ class GTEST_API_ UnitTestImpl { // Gets the elapsed time, in milliseconds. TimeInMillis elapsed_time() const { return elapsed_time_; } - // Returns true iff the unit test passed (i.e. all test cases passed). + // Returns true if and only if the unit test passed (i.e. all test suites + // passed). bool Passed() const { return !Failed(); } - // Returns true iff the unit test failed (i.e. some test case failed - // or something outside of all tests failed). + // Returns true if and only if the unit test failed (i.e. some test suite + // failed or something outside of all tests failed). bool Failed() const { - return failed_test_case_count() > 0 || ad_hoc_test_result()->Failed(); + return failed_test_suite_count() > 0 || ad_hoc_test_result()->Failed(); } - // Gets the i-th test case among all the test cases. i can range from 0 to - // total_test_case_count() - 1. If i is not in that range, returns NULL. - const TestCase* GetTestCase(int i) const { - const int index = GetElementOr(test_case_indices_, i, -1); - return index < 0 ? NULL : test_cases_[i]; + // Gets the i-th test suite among all the test suites. i can range from 0 to + // total_test_suite_count() - 1. If i is not in that range, returns NULL. + const TestSuite* GetTestSuite(int i) const { + const int index = GetElementOr(test_suite_indices_, i, -1); + return index < 0 ? nullptr : test_suites_[static_cast(i)]; } - // Gets the i-th test case among all the test cases. i can range from 0 to - // total_test_case_count() - 1. If i is not in that range, returns NULL. - TestCase* GetMutableTestCase(int i) { - const int index = GetElementOr(test_case_indices_, i, -1); - return index < 0 ? NULL : test_cases_[index]; + // Legacy API is deprecated but still available +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ + const TestCase* GetTestCase(int i) const { return GetTestSuite(i); } +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ + + // Gets the i-th test suite among all the test suites. i can range from 0 to + // total_test_suite_count() - 1. If i is not in that range, returns NULL. + TestSuite* GetMutableSuiteCase(int i) { + const int index = GetElementOr(test_suite_indices_, i, -1); + return index < 0 ? nullptr : test_suites_[static_cast(index)]; } // Provides access to the event listener list. @@ -620,30 +640,38 @@ class GTEST_API_ UnitTestImpl { // trace but Bar() and CurrentOsStackTraceExceptTop() won't. std::string CurrentOsStackTraceExceptTop(int skip_count) GTEST_NO_INLINE_; - // Finds and returns a TestCase with the given name. If one doesn't + // Finds and returns a TestSuite with the given name. If one doesn't // exist, creates one and returns it. // // Arguments: // - // test_case_name: name of the test case + // test_suite_name: name of the test suite // type_param: the name of the test's type parameter, or NULL if // this is not a typed or a type-parameterized test. - // set_up_tc: pointer to the function that sets up the test case - // tear_down_tc: pointer to the function that tears down the test case - TestCase* GetTestCase(const char* test_case_name, - const char* type_param, - Test::SetUpTestCaseFunc set_up_tc, - Test::TearDownTestCaseFunc tear_down_tc); + // set_up_tc: pointer to the function that sets up the test suite + // tear_down_tc: pointer to the function that tears down the test suite + TestSuite* GetTestSuite(const char* test_suite_name, const char* type_param, + internal::SetUpTestSuiteFunc set_up_tc, + internal::TearDownTestSuiteFunc tear_down_tc); + +// Legacy API is deprecated but still available +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ + TestCase* GetTestCase(const char* test_case_name, const char* type_param, + internal::SetUpTestSuiteFunc set_up_tc, + internal::TearDownTestSuiteFunc tear_down_tc) { + return GetTestSuite(test_case_name, type_param, set_up_tc, tear_down_tc); + } +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ // Adds a TestInfo to the unit test. // // Arguments: // - // set_up_tc: pointer to the function that sets up the test case - // tear_down_tc: pointer to the function that tears down the test case + // set_up_tc: pointer to the function that sets up the test suite + // tear_down_tc: pointer to the function that tears down the test suite // test_info: the TestInfo object - void AddTestInfo(Test::SetUpTestCaseFunc set_up_tc, - Test::TearDownTestCaseFunc tear_down_tc, + void AddTestInfo(internal::SetUpTestSuiteFunc set_up_tc, + internal::TearDownTestSuiteFunc tear_down_tc, TestInfo* test_info) { // In order to support thread-safe death tests, we need to // remember the original working directory when the test program @@ -658,23 +686,20 @@ class GTEST_API_ UnitTestImpl { << "Failed to get the current working directory."; } - GetTestCase(test_info->test_case_name(), - test_info->type_param(), - set_up_tc, - tear_down_tc)->AddTestInfo(test_info); + GetTestSuite(test_info->test_suite_name(), test_info->type_param(), + set_up_tc, tear_down_tc) + ->AddTestInfo(test_info); } -#if GTEST_HAS_PARAM_TEST - // Returns ParameterizedTestCaseRegistry object used to keep track of + // Returns ParameterizedTestSuiteRegistry object used to keep track of // value-parameterized tests and instantiate and register them. - internal::ParameterizedTestCaseRegistry& parameterized_test_registry() { + internal::ParameterizedTestSuiteRegistry& parameterized_test_registry() { return parameterized_test_registry_; } -#endif // GTEST_HAS_PARAM_TEST - // Sets the TestCase object for the test that's currently running. - void set_current_test_case(TestCase* a_current_test_case) { - current_test_case_ = a_current_test_case; + // Sets the TestSuite object for the test that's currently running. + void set_current_test_suite(TestSuite* a_current_test_suite) { + current_test_suite_ = a_current_test_suite; } // Sets the TestInfo object for the test that's currently running. If @@ -685,7 +710,7 @@ class GTEST_API_ UnitTestImpl { } // Registers all parameterized tests defined using TEST_P and - // INSTANTIATE_TEST_CASE_P, creating regular tests for each test/parameter + // INSTANTIATE_TEST_SUITE_P, creating regular tests for each test/parameter // combination. This method can be called more then once; it has guards // protecting from registering the tests more then once. If // value-parameterized tests are disabled, RegisterParameterizedTests is @@ -700,7 +725,7 @@ class GTEST_API_ UnitTestImpl { // Clears the results of all tests, except the ad hoc tests. void ClearNonAdHocTestResult() { - ForEach(test_cases_, TestCase::ClearTestCaseResult); + ForEach(test_suites_, TestSuite::ClearTestSuiteResult); } // Clears the results of ad-hoc test assertions. @@ -709,7 +734,7 @@ class GTEST_API_ UnitTestImpl { } // Adds a TestProperty to the current TestResult object when invoked in a - // context of a test or a test case, or to the global property set. If the + // context of a test or a test suite, or to the global property set. If the // result already contains a property with the same key, the value will be // updated. void RecordProperty(const TestProperty& test_property); @@ -721,7 +746,7 @@ class GTEST_API_ UnitTestImpl { // Matches the full name of each test against the user-specified // filter to decide whether the test should run, then records the - // result in each TestCase and TestInfo object. + // result in each TestSuite and TestInfo object. // If shard_tests == HONOR_SHARDING_PROTOCOL, further filters tests // based on sharding variables in the environment. // Returns the number of tests that should run. @@ -730,7 +755,7 @@ class GTEST_API_ UnitTestImpl { // Prints the names of the tests matching the user-specified filter flag. void ListTestsMatchingFilter(); - const TestCase* current_test_case() const { return current_test_case_; } + const TestSuite* current_test_suite() const { return current_test_suite_; } TestInfo* current_test_info() { return current_test_info_; } const TestInfo* current_test_info() const { return current_test_info_; } @@ -791,11 +816,11 @@ class GTEST_API_ UnitTestImpl { // Gets the random number generator. internal::Random* random() { return &random_; } - // Shuffles all test cases, and the tests within each test case, + // Shuffles all test suites, and the tests within each test suite, // making sure that death tests are still run first. void ShuffleTests(); - // Restores the test cases and tests to their order before the first shuffle. + // Restores the test suites and tests to their order before the first shuffle. void UnshuffleTests(); // Returns the value of GTEST_FLAG(catch_exceptions) at the moment @@ -835,33 +860,31 @@ class GTEST_API_ UnitTestImpl { // before/after the tests are run. std::vector environments_; - // The vector of TestCases in their original order. It owns the + // The vector of TestSuites in their original order. It owns the // elements in the vector. - std::vector test_cases_; + std::vector test_suites_; - // Provides a level of indirection for the test case list to allow - // easy shuffling and restoring the test case order. The i-th - // element of this vector is the index of the i-th test case in the + // Provides a level of indirection for the test suite list to allow + // easy shuffling and restoring the test suite order. The i-th + // element of this vector is the index of the i-th test suite in the // shuffled order. - std::vector test_case_indices_; + std::vector test_suite_indices_; -#if GTEST_HAS_PARAM_TEST // ParameterizedTestRegistry object used to register value-parameterized // tests. - internal::ParameterizedTestCaseRegistry parameterized_test_registry_; + internal::ParameterizedTestSuiteRegistry parameterized_test_registry_; // Indicates whether RegisterParameterizedTests() has been called already. bool parameterized_tests_registered_; -#endif // GTEST_HAS_PARAM_TEST - // Index of the last death test case registered. Initially -1. - int last_death_test_case_; + // Index of the last death test suite registered. Initially -1. + int last_death_test_suite_; - // This points to the TestCase for the currently running test. It - // changes as Google Test goes through one test case after another. + // This points to the TestSuite for the currently running test. It + // changes as Google Test goes through one test suite after another. // When no test is running, this is set to NULL and Google Test // stores assertion results in ad_hoc_test_result_. Initially NULL. - TestCase* current_test_case_; + TestSuite* current_test_suite_; // This points to the TestInfo for the currently running test. It // changes as Google Test goes through one test after another. When @@ -889,7 +912,7 @@ class GTEST_API_ UnitTestImpl { // desired. OsStackTraceGetterInterface* os_stack_trace_getter_; - // True iff PostFlagParsingInit() has been called. + // True if and only if PostFlagParsingInit() has been called. bool post_flag_parse_init_performed_; // The random number seed used at the beginning of the test run. @@ -908,8 +931,8 @@ class GTEST_API_ UnitTestImpl { #if GTEST_HAS_DEATH_TEST // The decomposed components of the gtest_internal_run_death_test flag, // parsed when RUN_ALL_TESTS is called. - internal::scoped_ptr internal_run_death_test_flag_; - internal::scoped_ptr death_test_factory_; + std::unique_ptr internal_run_death_test_flag_; + std::unique_ptr death_test_factory_; #endif // GTEST_HAS_DEATH_TEST // A per-thread stack of traces created by the SCOPED_TRACE() macro. @@ -992,8 +1015,6 @@ bool ParseNaturalNumber(const ::std::string& str, Integer* number) { const bool parse_success = *end == '\0' && errno == 0; - // TODO(vladl@google.com): Convert this to compile time assertion when it is - // available. GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed)); const Integer result = static_cast(parsed); @@ -1032,7 +1053,7 @@ class TestResultAccessor { #if GTEST_CAN_STREAM_RESULTS_ // Streams test results to the given port on the given host machine. -class GTEST_API_ StreamingListener : public EmptyTestEventListener { +class StreamingListener : public EmptyTestEventListener { public: // Abstract base class for writing strings to a socket. class AbstractSocketWriter { @@ -1057,18 +1078,18 @@ class GTEST_API_ StreamingListener : public EmptyTestEventListener { MakeConnection(); } - virtual ~SocketWriter() { + ~SocketWriter() override { if (sockfd_ != -1) CloseConnection(); } // Sends a string to the socket. - virtual void Send(const std::string& message) { + void Send(const std::string& message) override { GTEST_CHECK_(sockfd_ != -1) << "Send() can be called only when there is a connection."; - const int len = static_cast(message.length()); - if (write(sockfd_, message.c_str(), len) != len) { + const auto len = static_cast(message.length()); + if (write(sockfd_, message.c_str(), len) != static_cast(len)) { GTEST_LOG_(WARNING) << "stream_result_to: failed to stream to " << host_name_ << ":" << port_num_; @@ -1080,7 +1101,7 @@ class GTEST_API_ StreamingListener : public EmptyTestEventListener { void MakeConnection(); // Closes the socket. - void CloseConnection() { + void CloseConnection() override { GTEST_CHECK_(sockfd_ != -1) << "CloseConnection() can be called only when there is a connection."; @@ -1106,11 +1127,11 @@ class GTEST_API_ StreamingListener : public EmptyTestEventListener { explicit StreamingListener(AbstractSocketWriter* socket_writer) : socket_writer_(socket_writer) { Start(); } - void OnTestProgramStart(const UnitTest& /* unit_test */) { + void OnTestProgramStart(const UnitTest& /* unit_test */) override { SendLn("event=TestProgramStart"); } - void OnTestProgramEnd(const UnitTest& unit_test) { + void OnTestProgramEnd(const UnitTest& unit_test) override { // Note that Google Test current only report elapsed time for each // test iteration, not for the entire test program. SendLn("event=TestProgramEnd&passed=" + FormatBool(unit_test.Passed())); @@ -1119,42 +1140,47 @@ class GTEST_API_ StreamingListener : public EmptyTestEventListener { socket_writer_->CloseConnection(); } - void OnTestIterationStart(const UnitTest& /* unit_test */, int iteration) { + void OnTestIterationStart(const UnitTest& /* unit_test */, + int iteration) override { SendLn("event=TestIterationStart&iteration=" + StreamableToString(iteration)); } - void OnTestIterationEnd(const UnitTest& unit_test, int /* iteration */) { + void OnTestIterationEnd(const UnitTest& unit_test, + int /* iteration */) override { SendLn("event=TestIterationEnd&passed=" + FormatBool(unit_test.Passed()) + "&elapsed_time=" + StreamableToString(unit_test.elapsed_time()) + "ms"); } - void OnTestCaseStart(const TestCase& test_case) { + // Note that "event=TestCaseStart" is a wire format and has to remain + // "case" for compatibilty + void OnTestCaseStart(const TestCase& test_case) override { SendLn(std::string("event=TestCaseStart&name=") + test_case.name()); } - void OnTestCaseEnd(const TestCase& test_case) { - SendLn("event=TestCaseEnd&passed=" + FormatBool(test_case.Passed()) - + "&elapsed_time=" + StreamableToString(test_case.elapsed_time()) - + "ms"); + // Note that "event=TestCaseEnd" is a wire format and has to remain + // "case" for compatibilty + void OnTestCaseEnd(const TestCase& test_case) override { + SendLn("event=TestCaseEnd&passed=" + FormatBool(test_case.Passed()) + + "&elapsed_time=" + StreamableToString(test_case.elapsed_time()) + + "ms"); } - void OnTestStart(const TestInfo& test_info) { + void OnTestStart(const TestInfo& test_info) override { SendLn(std::string("event=TestStart&name=") + test_info.name()); } - void OnTestEnd(const TestInfo& test_info) { + void OnTestEnd(const TestInfo& test_info) override { SendLn("event=TestEnd&passed=" + FormatBool((test_info.result())->Passed()) + "&elapsed_time=" + StreamableToString((test_info.result())->elapsed_time()) + "ms"); } - void OnTestPartResult(const TestPartResult& test_part_result) { + void OnTestPartResult(const TestPartResult& test_part_result) override { const char* file_name = test_part_result.file_name(); - if (file_name == NULL) - file_name = ""; + if (file_name == nullptr) file_name = ""; SendLn("event=TestPartResult&file=" + UrlEncode(file_name) + "&line=" + StreamableToString(test_part_result.line_number()) + "&message=" + UrlEncode(test_part_result.message())); @@ -1170,7 +1196,7 @@ class GTEST_API_ StreamingListener : public EmptyTestEventListener { std::string FormatBool(bool value) { return value ? "1" : "0"; } - const scoped_ptr socket_writer_; + const std::unique_ptr socket_writer_; GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamingListener); }; // class StreamingListener @@ -1180,4 +1206,6 @@ class GTEST_API_ StreamingListener : public EmptyTestEventListener { } // namespace internal } // namespace testing +GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 + #endif // GTEST_SRC_GTEST_INTERNAL_INL_H_ diff --git a/cpp/test/src/gtest-matchers.cc b/cpp/test/src/gtest-matchers.cc new file mode 100644 index 0000000000..7d2fb6851e --- /dev/null +++ b/cpp/test/src/gtest-matchers.cc @@ -0,0 +1,97 @@ +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// The Google C++ Testing and Mocking Framework (Google Test) +// +// This file implements just enough of the matcher interface to allow +// EXPECT_DEATH and friends to accept a matcher argument. + +#include "gtest/internal/gtest-internal.h" +#include "gtest/internal/gtest-port.h" +#include "gtest/gtest-matchers.h" + +#include + +namespace testing { + +// Constructs a matcher that matches a const std::string& whose value is +// equal to s. +Matcher::Matcher(const std::string& s) { *this = Eq(s); } + +// Constructs a matcher that matches a const std::string& whose value is +// equal to s. +Matcher::Matcher(const char* s) { + *this = Eq(std::string(s)); +} + +// Constructs a matcher that matches a std::string whose value is equal to +// s. +Matcher::Matcher(const std::string& s) { *this = Eq(s); } + +// Constructs a matcher that matches a std::string whose value is equal to +// s. +Matcher::Matcher(const char* s) { *this = Eq(std::string(s)); } + +#if GTEST_HAS_ABSL +// Constructs a matcher that matches a const absl::string_view& whose value is +// equal to s. +Matcher::Matcher(const std::string& s) { + *this = Eq(s); +} + +// Constructs a matcher that matches a const absl::string_view& whose value is +// equal to s. +Matcher::Matcher(const char* s) { + *this = Eq(std::string(s)); +} + +// Constructs a matcher that matches a const absl::string_view& whose value is +// equal to s. +Matcher::Matcher(absl::string_view s) { + *this = Eq(std::string(s)); +} + +// Constructs a matcher that matches a absl::string_view whose value is equal to +// s. +Matcher::Matcher(const std::string& s) { *this = Eq(s); } + +// Constructs a matcher that matches a absl::string_view whose value is equal to +// s. +Matcher::Matcher(const char* s) { + *this = Eq(std::string(s)); +} + +// Constructs a matcher that matches a absl::string_view whose value is equal to +// s. +Matcher::Matcher(absl::string_view s) { + *this = Eq(std::string(s)); +} +#endif // GTEST_HAS_ABSL + +} // namespace testing diff --git a/cpp/test/src/gtest-port.cc b/cpp/test/src/gtest-port.cc index d80bd80c48..fc5ba6becc 100644 --- a/cpp/test/src/gtest-port.cc +++ b/cpp/test/src/gtest-port.cc @@ -26,22 +26,25 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Author: wan@google.com (Zhanyong Wan) + #include "gtest/internal/gtest-port.h" #include -#include #include +#include #include #include +#include #if GTEST_OS_WINDOWS # include # include # include # include // Used in ThreadLocal. +# ifdef _MSC_VER +# include +# endif // _MSC_VER #else # include #endif // GTEST_OS_WINDOWS @@ -52,6 +55,14 @@ # include #endif // GTEST_OS_MAC +#if GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD || \ + GTEST_OS_NETBSD || GTEST_OS_OPENBSD +# include +# if GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD +# include +# endif +#endif + #if GTEST_OS_QNX # include # include @@ -63,19 +74,16 @@ # include #endif // GTEST_OS_AIX +#if GTEST_OS_FUCHSIA +# include +# include +#endif // GTEST_OS_FUCHSIA + #include "gtest/gtest-spi.h" #include "gtest/gtest-message.h" #include "gtest/internal/gtest-internal.h" #include "gtest/internal/gtest-string.h" - -// Indicates that this translation unit is part of Google Test's -// implementation. It must come before gtest-internal-inl.h is -// included, or there will be a compiler error. This trick exists to -// prevent the accidental inclusion of gtest-internal-inl.h in the -// user's code. -#define GTEST_IMPLEMENTATION_ 1 #include "src/gtest-internal-inl.h" -#undef GTEST_IMPLEMENTATION_ namespace testing { namespace internal { @@ -109,7 +117,7 @@ T ReadProcFileField(const std::string& filename, int field) { size_t GetThreadCount() { const std::string filename = (Message() << "/proc/" << getpid() << "/stat").GetString(); - return ReadProcFileField(filename, 19); + return ReadProcFileField(filename, 19); } #elif GTEST_OS_MAC @@ -131,6 +139,81 @@ size_t GetThreadCount() { } } +#elif GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD || \ + GTEST_OS_NETBSD + +#if GTEST_OS_NETBSD +#undef KERN_PROC +#define KERN_PROC KERN_PROC2 +#define kinfo_proc kinfo_proc2 +#endif + +#if GTEST_OS_DRAGONFLY +#define KP_NLWP(kp) (kp.kp_nthreads) +#elif GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD +#define KP_NLWP(kp) (kp.ki_numthreads) +#elif GTEST_OS_NETBSD +#define KP_NLWP(kp) (kp.p_nlwps) +#endif + +// Returns the number of threads running in the process, or 0 to indicate that +// we cannot detect it. +size_t GetThreadCount() { + int mib[] = { + CTL_KERN, + KERN_PROC, + KERN_PROC_PID, + getpid(), +#if GTEST_OS_NETBSD + sizeof(struct kinfo_proc), + 1, +#endif + }; + u_int miblen = sizeof(mib) / sizeof(mib[0]); + struct kinfo_proc info; + size_t size = sizeof(info); + if (sysctl(mib, miblen, &info, &size, NULL, 0)) { + return 0; + } + return static_cast(KP_NLWP(info)); +} +#elif GTEST_OS_OPENBSD + +// Returns the number of threads running in the process, or 0 to indicate that +// we cannot detect it. +size_t GetThreadCount() { + int mib[] = { + CTL_KERN, + KERN_PROC, + KERN_PROC_PID | KERN_PROC_SHOW_THREADS, + getpid(), + sizeof(struct kinfo_proc), + 0, + }; + u_int miblen = sizeof(mib) / sizeof(mib[0]); + + // get number of structs + size_t size; + if (sysctl(mib, miblen, NULL, &size, NULL, 0)) { + return 0; + } + mib[5] = size / mib[4]; + + // populate array of structs + struct kinfo_proc info[mib[5]]; + if (sysctl(mib, miblen, &info, &size, NULL, 0)) { + return 0; + } + + // exclude empty members + int nthreads = 0; + for (int i = 0; i < size / mib[4]; i++) { + if (info[i].p_tid != -1) + nthreads++; + } + return nthreads; +} + #elif GTEST_OS_QNX // Returns the number of threads running in the process, or 0 to indicate that @@ -142,7 +225,7 @@ size_t GetThreadCount() { } procfs_info process_info; const int status = - devctl(fd, DCMD_PROC_INFO, &process_info, sizeof(process_info), NULL); + devctl(fd, DCMD_PROC_INFO, &process_info, sizeof(process_info), nullptr); close(fd); if (status == EOK) { return static_cast(process_info.num_threads); @@ -156,7 +239,7 @@ size_t GetThreadCount() { size_t GetThreadCount() { struct procentry64 entry; pid_t pid = getpid(); - int status = getprocs64(&entry, sizeof(entry), NULL, 0, &pid, 1); + int status = getprocs64(&entry, sizeof(entry), nullptr, 0, &pid, 1); if (status == 1) { return entry.pi_thcount; } else { @@ -164,6 +247,25 @@ size_t GetThreadCount() { } } +#elif GTEST_OS_FUCHSIA + +size_t GetThreadCount() { + int dummy_buffer; + size_t avail; + zx_status_t status = zx_object_get_info( + zx_process_self(), + ZX_INFO_PROCESS_THREADS, + &dummy_buffer, + 0, + nullptr, + &avail); + if (status == ZX_OK) { + return avail; + } else { + return 0; + } +} + #else size_t GetThreadCount() { @@ -177,7 +279,7 @@ size_t GetThreadCount() { #if GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS void SleepMilliseconds(int n) { - ::Sleep(n); + ::Sleep(static_cast(n)); } AutoHandle::AutoHandle() @@ -215,15 +317,15 @@ void AutoHandle::Reset(HANDLE handle) { bool AutoHandle::IsCloseable() const { // Different Windows APIs may use either of these values to represent an // invalid handle. - return handle_ != NULL && handle_ != INVALID_HANDLE_VALUE; + return handle_ != nullptr && handle_ != INVALID_HANDLE_VALUE; } Notification::Notification() - : event_(::CreateEvent(NULL, // Default security attributes. - TRUE, // Do not reset automatically. - FALSE, // Initially unset. - NULL)) { // Anonymous event. - GTEST_CHECK_(event_.Get() != NULL); + : event_(::CreateEvent(nullptr, // Default security attributes. + TRUE, // Do not reset automatically. + FALSE, // Initially unset. + nullptr)) { // Anonymous event. + GTEST_CHECK_(event_.Get() != nullptr); } void Notification::Notify() { @@ -246,13 +348,10 @@ Mutex::Mutex() Mutex::~Mutex() { // Static mutexes are leaked intentionally. It is not thread-safe to try // to clean them up. - // TODO(yukawa): Switch to Slim Reader/Writer (SRW) Locks, which requires - // nothing to clean it up but is available only on Vista and later. - // http://msdn.microsoft.com/en-us/library/windows/desktop/aa904937.aspx if (type_ == kDynamic) { ::DeleteCriticalSection(critical_section_); delete critical_section_; - critical_section_ = NULL; + critical_section_ = nullptr; } } @@ -279,6 +378,41 @@ void Mutex::AssertHeld() { << "The current thread is not holding the mutex @" << this; } +namespace { + +#ifdef _MSC_VER +// Use the RAII idiom to flag mem allocs that are intentionally never +// deallocated. The motivation is to silence the false positive mem leaks +// that are reported by the debug version of MS's CRT which can only detect +// if an alloc is missing a matching deallocation. +// Example: +// MemoryIsNotDeallocated memory_is_not_deallocated; +// critical_section_ = new CRITICAL_SECTION; +// +class MemoryIsNotDeallocated +{ + public: + MemoryIsNotDeallocated() : old_crtdbg_flag_(0) { + old_crtdbg_flag_ = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); + // Set heap allocation block type to _IGNORE_BLOCK so that MS debug CRT + // doesn't report mem leak if there's no matching deallocation. + _CrtSetDbgFlag(old_crtdbg_flag_ & ~_CRTDBG_ALLOC_MEM_DF); + } + + ~MemoryIsNotDeallocated() { + // Restore the original _CRTDBG_ALLOC_MEM_DF flag + _CrtSetDbgFlag(old_crtdbg_flag_); + } + + private: + int old_crtdbg_flag_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(MemoryIsNotDeallocated); +}; +#endif // _MSC_VER + +} // namespace + // Initializes owner_thread_id_ and critical_section_ in static mutexes. void Mutex::ThreadSafeLazyInit() { // Dynamic mutexes are initialized in the constructor. @@ -289,7 +423,13 @@ void Mutex::ThreadSafeLazyInit() { // If critical_section_init_phase_ was 0 before the exchange, we // are the first to test it and need to perform the initialization. owner_thread_id_ = 0; - critical_section_ = new CRITICAL_SECTION; + { + // Use RAII to flag that following mem alloc is never deallocated. +#ifdef _MSC_VER + MemoryIsNotDeallocated memory_is_not_deallocated; +#endif // _MSC_VER + critical_section_ = new CRITICAL_SECTION; + } ::InitializeCriticalSection(critical_section_); // Updates the critical_section_init_phase_ to 2 to signal // initialization complete. @@ -328,17 +468,16 @@ class ThreadWithParamSupport : public ThreadWithParamBase { Notification* thread_can_start) { ThreadMainParam* param = new ThreadMainParam(runnable, thread_can_start); DWORD thread_id; - // TODO(yukawa): Consider to use _beginthreadex instead. HANDLE thread_handle = ::CreateThread( - NULL, // Default security. - 0, // Default stack size. + nullptr, // Default security. + 0, // Default stack size. &ThreadWithParamSupport::ThreadMain, - param, // Parameter to ThreadMainStatic - 0x0, // Default creation flags. + param, // Parameter to ThreadMainStatic + 0x0, // Default creation flags. &thread_id); // Need a valid pointer for the call to work under Win98. - GTEST_CHECK_(thread_handle != NULL) << "CreateThread failed with error " - << ::GetLastError() << "."; - if (thread_handle == NULL) { + GTEST_CHECK_(thread_handle != nullptr) + << "CreateThread failed with error " << ::GetLastError() << "."; + if (thread_handle == nullptr) { delete param; } return thread_handle; @@ -350,15 +489,15 @@ class ThreadWithParamSupport : public ThreadWithParamBase { : runnable_(runnable), thread_can_start_(thread_can_start) { } - scoped_ptr runnable_; + std::unique_ptr runnable_; // Does not own. Notification* thread_can_start_; }; static DWORD WINAPI ThreadMain(void* ptr) { // Transfers ownership. - scoped_ptr param(static_cast(ptr)); - if (param->thread_can_start_ != NULL) + std::unique_ptr param(static_cast(ptr)); + if (param->thread_can_start_ != nullptr) param->thread_can_start_->WaitForNotification(); param->runnable_->Run(); return 0; @@ -416,7 +555,7 @@ class ThreadLocalRegistryImpl { thread_local_values .insert(std::make_pair( thread_local_instance, - linked_ptr( + std::shared_ptr( thread_local_instance->NewValueForCurrentThread()))) .first; } @@ -425,7 +564,7 @@ class ThreadLocalRegistryImpl { static void OnThreadLocalDestroyed( const ThreadLocalBase* thread_local_instance) { - std::vector > value_holders; + std::vector > value_holders; // Clean up the ThreadLocalValues data structure while holding the lock, but // defer the destruction of the ThreadLocalValueHolderBases. { @@ -453,7 +592,7 @@ class ThreadLocalRegistryImpl { static void OnThreadExit(DWORD thread_id) { GTEST_CHECK_(thread_id != 0) << ::GetLastError(); - std::vector > value_holders; + std::vector > value_holders; // Clean up the ThreadIdToThreadLocals data structure while holding the // lock, but defer the destruction of the ThreadLocalValueHolderBases. { @@ -480,7 +619,8 @@ class ThreadLocalRegistryImpl { private: // In a particular thread, maps a ThreadLocal object to its value. typedef std::map > ThreadLocalValues; + std::shared_ptr > + ThreadLocalValues; // Stores all ThreadIdToThreadLocals having values in a thread, indexed by // thread's ID. typedef std::map ThreadIdToThreadLocals; @@ -495,18 +635,17 @@ class ThreadLocalRegistryImpl { HANDLE thread = ::OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION, FALSE, thread_id); - GTEST_CHECK_(thread != NULL); - // We need to to pass a valid thread ID pointer into CreateThread for it + GTEST_CHECK_(thread != nullptr); + // We need to pass a valid thread ID pointer into CreateThread for it // to work correctly under Win98. DWORD watcher_thread_id; HANDLE watcher_thread = ::CreateThread( - NULL, // Default security. - 0, // Default stack size + nullptr, // Default security. + 0, // Default stack size &ThreadLocalRegistryImpl::WatcherThreadFunc, reinterpret_cast(new ThreadIdAndHandle(thread_id, thread)), - CREATE_SUSPENDED, - &watcher_thread_id); - GTEST_CHECK_(watcher_thread != NULL); + CREATE_SUSPENDED, &watcher_thread_id); + GTEST_CHECK_(watcher_thread != nullptr); // Give the watcher thread the same priority as ours to avoid being // blocked by it. ::SetThreadPriority(watcher_thread, @@ -531,7 +670,10 @@ class ThreadLocalRegistryImpl { // Returns map of thread local instances. static ThreadIdToThreadLocals* GetThreadLocalsMapLocked() { mutex_.AssertHeld(); - static ThreadIdToThreadLocals* map = new ThreadIdToThreadLocals; +#ifdef _MSC_VER + MemoryIsNotDeallocated memory_is_not_deallocated; +#endif // _MSC_VER + static ThreadIdToThreadLocals* map = new ThreadIdToThreadLocals(); return map; } @@ -573,7 +715,7 @@ RE::~RE() { free(const_cast(pattern_)); } -// Returns true iff regular expression re matches the entire str. +// Returns true if and only if regular expression re matches the entire str. bool RE::FullMatch(const char* str, const RE& re) { if (!re.is_valid_) return false; @@ -581,8 +723,8 @@ bool RE::FullMatch(const char* str, const RE& re) { return regexec(&re.full_regex_, str, 1, &match, 0) == 0; } -// Returns true iff regular expression re matches a substring of str -// (including str itself). +// Returns true if and only if regular expression re matches a substring of +// str (including str itself). bool RE::PartialMatch(const char* str, const RE& re) { if (!re.is_valid_) return false; @@ -622,14 +764,14 @@ void RE::Init(const char* regex) { #elif GTEST_USES_SIMPLE_RE -// Returns true iff ch appears anywhere in str (excluding the +// Returns true if and only if ch appears anywhere in str (excluding the // terminating '\0' character). bool IsInSet(char ch, const char* str) { - return ch != '\0' && strchr(str, ch) != NULL; + return ch != '\0' && strchr(str, ch) != nullptr; } -// Returns true iff ch belongs to the given classification. Unlike -// similar functions in , these aren't affected by the +// Returns true if and only if ch belongs to the given classification. +// Unlike similar functions in , these aren't affected by the // current locale. bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; } bool IsAsciiPunct(char ch) { @@ -642,13 +784,13 @@ bool IsAsciiWordChar(char ch) { ('0' <= ch && ch <= '9') || ch == '_'; } -// Returns true iff "\\c" is a supported escape sequence. +// Returns true if and only if "\\c" is a supported escape sequence. bool IsValidEscape(char c) { return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW")); } -// Returns true iff the given atom (specified by escaped and pattern) -// matches ch. The result is undefined if the atom is invalid. +// Returns true if and only if the given atom (specified by escaped and +// pattern) matches ch. The result is undefined if the atom is invalid. bool AtomMatchesChar(bool escaped, char pattern_char, char ch) { if (escaped) { // "\\p" where p is pattern_char. switch (pattern_char) { @@ -671,7 +813,7 @@ bool AtomMatchesChar(bool escaped, char pattern_char, char ch) { } // Helper function used by ValidateRegex() to format error messages. -std::string FormatRegexSyntaxError(const char* regex, int index) { +static std::string FormatRegexSyntaxError(const char* regex, int index) { return (Message() << "Syntax error at index " << index << " in simple regular expression \"" << regex << "\": ").GetString(); } @@ -679,17 +821,14 @@ std::string FormatRegexSyntaxError(const char* regex, int index) { // Generates non-fatal failures and returns false if regex is invalid; // otherwise returns true. bool ValidateRegex(const char* regex) { - if (regex == NULL) { - // TODO(wan@google.com): fix the source file location in the - // assertion failures to match where the regex is used in user - // code. + if (regex == nullptr) { ADD_FAILURE() << "NULL is not a valid simple regular expression."; return false; } bool is_valid = true; - // True iff ?, *, or + can follow the previous atom. + // True if and only if ?, *, or + can follow the previous atom. bool prev_repeatable = false; for (int i = 0; regex[i]; i++) { if (regex[i] == '\\') { // An escape sequence @@ -765,8 +904,8 @@ bool MatchRepetitionAndRegexAtHead( return false; } -// Returns true iff regex matches a prefix of str. regex must be a -// valid simple regular expression and not start with "^", or the +// Returns true if and only if regex matches a prefix of str. regex must +// be a valid simple regular expression and not start with "^", or the // result is undefined. bool MatchRegexAtHead(const char* regex, const char* str) { if (*regex == '\0') // An empty regex matches a prefix of anything. @@ -796,8 +935,8 @@ bool MatchRegexAtHead(const char* regex, const char* str) { } } -// Returns true iff regex matches any substring of str. regex must be -// a valid simple regular expression, or the result is undefined. +// Returns true if and only if regex matches any substring of str. regex must +// be a valid simple regular expression, or the result is undefined. // // The algorithm is recursive, but the recursion depth doesn't exceed // the regex length, so we won't need to worry about running out of @@ -805,8 +944,7 @@ bool MatchRegexAtHead(const char* regex, const char* str) { // exponential with respect to the regex length + the string length, // but usually it's must faster (often close to linear). bool MatchRegexAnywhere(const char* regex, const char* str) { - if (regex == NULL || str == NULL) - return false; + if (regex == nullptr || str == nullptr) return false; if (*regex == '^') return MatchRegexAtHead(regex + 1, str); @@ -826,21 +964,21 @@ RE::~RE() { free(const_cast(full_pattern_)); } -// Returns true iff regular expression re matches the entire str. +// Returns true if and only if regular expression re matches the entire str. bool RE::FullMatch(const char* str, const RE& re) { return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str); } -// Returns true iff regular expression re matches a substring of str -// (including str itself). +// Returns true if and only if regular expression re matches a substring of +// str (including str itself). bool RE::PartialMatch(const char* str, const RE& re) { return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str); } // Initializes an RE from its string representation. void RE::Init(const char* regex) { - pattern_ = full_pattern_ = NULL; - if (regex != NULL) { + pattern_ = full_pattern_ = nullptr; + if (regex != nullptr) { pattern_ = posix::StrDup(regex); } @@ -878,7 +1016,7 @@ const char kUnknownFile[] = "unknown file"; // Formats a source file path and a line number as they would appear // in an error message from the compiler used to compile this code. GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) { - const std::string file_name(file == NULL ? kUnknownFile : file); + const std::string file_name(file == nullptr ? kUnknownFile : file); if (line < 0) { return file_name + ":"; @@ -897,7 +1035,7 @@ GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) { // to the file location it produces, unlike FormatFileLocation(). GTEST_API_ ::std::string FormatCompilerIndependentFileLocation( const char* file, int line) { - const std::string file_name(file == NULL ? kUnknownFile : file); + const std::string file_name(file == nullptr ? kUnknownFile : file); if (line < 0) return file_name; @@ -923,9 +1061,10 @@ GTestLog::~GTestLog() { posix::Abort(); } } + // Disable Microsoft deprecation warnings for POSIX functions called from // this class (creat, dup, dup2, and close) -GTEST_DISABLE_MSC_WARNINGS_PUSH_(4996) +GTEST_DISABLE_MSC_DEPRECATED_PUSH_() #if GTEST_HAS_STREAM_REDIRECTION @@ -963,20 +1102,22 @@ class CapturedStream { // code as part of a regular standalone executable, which doesn't // run in a Dalvik process (e.g. when running it through 'adb shell'). // - // The location /sdcard is directly accessible from native code - // and is the only location (unofficially) supported by the Android - // team. It's generally a symlink to the real SD Card mount point - // which can be /mnt/sdcard, /mnt/sdcard0, /system/media/sdcard, or - // other OEM-customized locations. Never rely on these, and always - // use /sdcard. - char name_template[] = "/sdcard/gtest_captured_stream.XXXXXX"; + // The location /data/local/tmp is directly accessible from native code. + // '/sdcard' and other variants cannot be relied on, as they are not + // guaranteed to be mounted, or may have a delay in mounting. + char name_template[] = "/data/local/tmp/gtest_captured_stream.XXXXXX"; # else char name_template[] = "/tmp/captured_stream.XXXXXX"; # endif // GTEST_OS_LINUX_ANDROID const int captured_fd = mkstemp(name_template); + if (captured_fd == -1) { + GTEST_LOG_(WARNING) + << "Failed to create tmp file " << name_template + << " for test; does the test have access to the /tmp directory?"; + } filename_ = name_template; # endif // GTEST_OS_WINDOWS - fflush(NULL); + fflush(nullptr); dup2(captured_fd, fd_); close(captured_fd); } @@ -988,13 +1129,17 @@ class CapturedStream { std::string GetCapturedString() { if (uncaptured_fd_ != -1) { // Restores the original stream. - fflush(NULL); + fflush(nullptr); dup2(uncaptured_fd_, fd_); close(uncaptured_fd_); uncaptured_fd_ = -1; } FILE* const file = posix::FOpen(filename_.c_str(), "r"); + if (file == nullptr) { + GTEST_LOG_(FATAL) << "Failed to open tmp file " << filename_ + << " for capturing stream."; + } const std::string content = ReadEntireFile(file); posix::FClose(file); return content; @@ -1009,14 +1154,15 @@ class CapturedStream { GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream); }; -GTEST_DISABLE_MSC_WARNINGS_POP_() +GTEST_DISABLE_MSC_DEPRECATED_POP_() -static CapturedStream* g_captured_stderr = NULL; -static CapturedStream* g_captured_stdout = NULL; +static CapturedStream* g_captured_stderr = nullptr; +static CapturedStream* g_captured_stdout = nullptr; // Starts capturing an output stream (stdout/stderr). -void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) { - if (*stream != NULL) { +static void CaptureStream(int fd, const char* stream_name, + CapturedStream** stream) { + if (*stream != nullptr) { GTEST_LOG_(FATAL) << "Only one " << stream_name << " capturer can exist at a time."; } @@ -1024,11 +1170,11 @@ void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) { } // Stops capturing the output stream and returns the captured string. -std::string GetCapturedStream(CapturedStream** captured_stream) { +static std::string GetCapturedStream(CapturedStream** captured_stream) { const std::string content = (*captured_stream)->GetCapturedString(); delete *captured_stream; - *captured_stream = NULL; + *captured_stream = nullptr; return content; } @@ -1055,6 +1201,10 @@ std::string GetCapturedStderr() { #endif // GTEST_HAS_STREAM_REDIRECTION + + + + size_t GetFileSize(FILE* file) { fseek(file, 0, SEEK_END); return static_cast(ftell(file)); @@ -1083,22 +1233,30 @@ std::string ReadEntireFile(FILE* file) { } #if GTEST_HAS_DEATH_TEST +static const std::vector* g_injected_test_argvs = + nullptr; // Owned. -static const ::std::vector* g_injected_test_argvs = - NULL; // Owned. - -void SetInjectableArgvs(const ::std::vector* argvs) { - if (g_injected_test_argvs != argvs) - delete g_injected_test_argvs; - g_injected_test_argvs = argvs; -} - -const ::std::vector& GetInjectableArgvs() { - if (g_injected_test_argvs != NULL) { +std::vector GetInjectableArgvs() { + if (g_injected_test_argvs != nullptr) { return *g_injected_test_argvs; } return GetArgvs(); } + +void SetInjectableArgvs(const std::vector* new_argvs) { + if (g_injected_test_argvs != new_argvs) delete g_injected_test_argvs; + g_injected_test_argvs = new_argvs; +} + +void SetInjectableArgvs(const std::vector& new_argvs) { + SetInjectableArgvs( + new std::vector(new_argvs.begin(), new_argvs.end())); +} + +void ClearInjectableArgvs() { + delete g_injected_test_argvs; + g_injected_test_argvs = nullptr; +} #endif // GTEST_HAS_DEATH_TEST #if GTEST_OS_WINDOWS_MOBILE @@ -1130,7 +1288,7 @@ static std::string FlagToEnvVar(const char* flag) { // unchanged and returns false. bool ParseInt32(const Message& src_text, const char* str, Int32* value) { // Parses the environment variable as a decimal integer. - char* end = NULL; + char* end = nullptr; const long long_value = strtol(str, &end, 10); // NOLINT // Has strtol() consumed all characters in the string? @@ -1169,15 +1327,16 @@ bool ParseInt32(const Message& src_text, const char* str, Int32* value) { // Reads and returns the Boolean environment variable corresponding to // the given flag; if it's not set, returns default_value. // -// The value is considered true iff it's not "0". +// The value is considered true if and only if it's not "0". bool BoolFromGTestEnv(const char* flag, bool default_value) { #if defined(GTEST_GET_BOOL_FROM_ENV_) return GTEST_GET_BOOL_FROM_ENV_(flag, default_value); -#endif // defined(GTEST_GET_BOOL_FROM_ENV_) +#else const std::string env_var = FlagToEnvVar(flag); const char* const string_value = posix::GetEnv(env_var.c_str()); - return string_value == NULL ? - default_value : strcmp(string_value, "0") != 0; + return string_value == nullptr ? default_value + : strcmp(string_value, "0") != 0; +#endif // defined(GTEST_GET_BOOL_FROM_ENV_) } // Reads and returns a 32-bit integer stored in the environment @@ -1186,10 +1345,10 @@ bool BoolFromGTestEnv(const char* flag, bool default_value) { Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) { #if defined(GTEST_GET_INT32_FROM_ENV_) return GTEST_GET_INT32_FROM_ENV_(flag, default_value); -#endif // defined(GTEST_GET_INT32_FROM_ENV_) +#else const std::string env_var = FlagToEnvVar(flag); const char* const string_value = posix::GetEnv(env_var.c_str()); - if (string_value == NULL) { + if (string_value == nullptr) { // The environment variable is not set. return default_value; } @@ -1204,37 +1363,36 @@ Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) { } return result; +#endif // defined(GTEST_GET_INT32_FROM_ENV_) +} + +// As a special case for the 'output' flag, if GTEST_OUTPUT is not +// set, we look for XML_OUTPUT_FILE, which is set by the Bazel build +// system. The value of XML_OUTPUT_FILE is a filename without the +// "xml:" prefix of GTEST_OUTPUT. +// Note that this is meant to be called at the call site so it does +// not check that the flag is 'output' +// In essence this checks an env variable called XML_OUTPUT_FILE +// and if it is set we prepend "xml:" to its value, if it not set we return "" +std::string OutputFlagAlsoCheckEnvVar(){ + std::string default_value_for_output_flag = ""; + const char* xml_output_file_env = posix::GetEnv("XML_OUTPUT_FILE"); + if (nullptr != xml_output_file_env) { + default_value_for_output_flag = std::string("xml:") + xml_output_file_env; + } + return default_value_for_output_flag; } // Reads and returns the string environment variable corresponding to // the given flag; if it's not set, returns default_value. -std::string StringFromGTestEnv(const char* flag, const char* default_value) { +const char* StringFromGTestEnv(const char* flag, const char* default_value) { #if defined(GTEST_GET_STRING_FROM_ENV_) return GTEST_GET_STRING_FROM_ENV_(flag, default_value); -#endif // defined(GTEST_GET_STRING_FROM_ENV_) +#else const std::string env_var = FlagToEnvVar(flag); - const char* value = posix::GetEnv(env_var.c_str()); - if (value != NULL) { - return value; - } - - // As a special case for the 'output' flag, if GTEST_OUTPUT is not - // set, we look for XML_OUTPUT_FILE, which is set by the Bazel build - // system. The value of XML_OUTPUT_FILE is a filename without the - // "xml:" prefix of GTEST_OUTPUT. - // - // The net priority order after flag processing is thus: - // --gtest_output command line flag - // GTEST_OUTPUT environment variable - // XML_OUTPUT_FILE environment variable - // 'default_value' - if (strcmp(flag, "output") == 0) { - value = posix::GetEnv("XML_OUTPUT_FILE"); - if (value != NULL) { - return std::string("xml:") + value; - } - } - return default_value; + const char* const value = posix::GetEnv(env_var.c_str()); + return value == nullptr ? default_value : value; +#endif // defined(GTEST_GET_STRING_FROM_ENV_) } } // namespace internal diff --git a/cpp/test/src/gtest-printers.cc b/cpp/test/src/gtest-printers.cc index a2df412f8a..3337be312e 100644 --- a/cpp/test/src/gtest-printers.cc +++ b/cpp/test/src/gtest-printers.cc @@ -26,10 +26,9 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Author: wan@google.com (Zhanyong Wan) -// Google Test - The Google C++ Testing Framework + +// Google Test - The Google C++ Testing and Mocking Framework // // This file implements a universal value printer that can print a // value of any type T: @@ -43,12 +42,13 @@ // defines Foo. #include "gtest/gtest-printers.h" -#include #include +#include #include #include // NOLINT #include #include "gtest/internal/gtest-port.h" +#include "src/gtest-internal-inl.h" namespace testing { @@ -59,6 +59,7 @@ using ::std::ostream; // Prints a segment of bytes in the given object. GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ +GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_ GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start, size_t count, ostream* os) { @@ -89,7 +90,6 @@ void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count, // If the object size is bigger than kThreshold, we'll have to omit // some details by printing only the first and the last kChunkSize // bytes. - // TODO(wan): let the user control the threshold using a flag. if (count < kThreshold) { PrintByteSegmentInObjectTo(obj_bytes, 0, count, os); } else { @@ -123,7 +123,7 @@ namespace internal { // Depending on the value of a char (or wchar_t), we print it in one // of three formats: // - as is if it's a printable ASCII (e.g. 'a', '2', ' '), -// - as a hexidecimal escape sequence (e.g. '\x7F'), or +// - as a hexadecimal escape sequence (e.g. '\x7F'), or // - as a special escape sequence (e.g. '\r', '\n'). enum CharFormat { kAsIs, @@ -144,7 +144,8 @@ inline bool IsPrintableAscii(wchar_t c) { // which is the type of c. template static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) { - switch (static_cast(c)) { + wchar_t w_c = static_cast(c); + switch (w_c) { case L'\0': *os << "\\0"; break; @@ -176,11 +177,14 @@ static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) { *os << "\\v"; break; default: - if (IsPrintableAscii(c)) { + if (IsPrintableAscii(w_c)) { *os << static_cast(c); return kAsIs; } else { - *os << "\\x" + String::FormatHexInt(static_cast(c)); + ostream::fmtflags flags = os->flags(); + *os << "\\x" << std::hex << std::uppercase + << static_cast(static_cast(c)); + os->flags(flags); return kHexEscape; } } @@ -227,13 +231,13 @@ void PrintCharAndCodeTo(Char c, ostream* os) { return; *os << " (" << static_cast(c); - // For more convenience, we print c's code again in hexidecimal, + // For more convenience, we print c's code again in hexadecimal, // unless c was already printed in the form '\x##' or the code is in // [1, 9]. if (format == kHexEscape || (1 <= c && c <= 9)) { // Do nothing. } else { - *os << ", 0x" << String::FormatHexInt(static_cast(c)); + *os << ", 0x" << String::FormatHexInt(static_cast(c)); } *os << ")"; } @@ -258,12 +262,14 @@ void PrintTo(wchar_t wc, ostream* os) { template GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ +GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_ GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ -static void PrintCharsAsStringTo( +static CharFormat PrintCharsAsStringTo( const CharType* begin, size_t len, ostream* os) { const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\""; *os << kQuoteBegin; bool is_previous_hex = false; + CharFormat print_format = kAsIs; for (size_t index = 0; index < len; ++index) { const CharType cur = begin[index]; if (is_previous_hex && IsXDigit(cur)) { @@ -273,8 +279,13 @@ static void PrintCharsAsStringTo( *os << "\" " << kQuoteBegin; } is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape; + // Remember if any characters required hex escaping. + if (is_previous_hex) { + print_format = kHexEscape; + } } *os << "\""; + return print_format; } // Prints a (const) char/wchar_t array of 'len' elements, starting at address @@ -282,6 +293,7 @@ static void PrintCharsAsStringTo( template GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ +GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_ GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ static void UniversalPrintCharArray( const CharType* begin, size_t len, ostream* os) { @@ -318,7 +330,7 @@ void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) { // Prints the given C string to the ostream. void PrintTo(const char* s, ostream* os) { - if (s == NULL) { + if (s == nullptr) { *os << "NULL"; } else { *os << ImplicitCast_(s) << " pointing to "; @@ -335,32 +347,89 @@ void PrintTo(const char* s, ostream* os) { #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) // Prints the given wide C string to the ostream. void PrintTo(const wchar_t* s, ostream* os) { - if (s == NULL) { + if (s == nullptr) { *os << "NULL"; } else { *os << ImplicitCast_(s) << " pointing to "; - PrintCharsAsStringTo(s, std::wcslen(s), os); + PrintCharsAsStringTo(s, wcslen(s), os); } } #endif // wchar_t is native -// Prints a ::string object. -#if GTEST_HAS_GLOBAL_STRING -void PrintStringTo(const ::string& s, ostream* os) { - PrintCharsAsStringTo(s.data(), s.size(), os); +namespace { + +bool ContainsUnprintableControlCodes(const char* str, size_t length) { + const unsigned char *s = reinterpret_cast(str); + + for (size_t i = 0; i < length; i++) { + unsigned char ch = *s++; + if (std::iscntrl(ch)) { + switch (ch) { + case '\t': + case '\n': + case '\r': + break; + default: + return true; + } + } + } + return false; } -#endif // GTEST_HAS_GLOBAL_STRING -void PrintStringTo(const ::std::string& s, ostream* os) { - PrintCharsAsStringTo(s.data(), s.size(), os); +bool IsUTF8TrailByte(unsigned char t) { return 0x80 <= t && t<= 0xbf; } + +bool IsValidUTF8(const char* str, size_t length) { + const unsigned char *s = reinterpret_cast(str); + + for (size_t i = 0; i < length;) { + unsigned char lead = s[i++]; + + if (lead <= 0x7f) { + continue; // single-byte character (ASCII) 0..7F + } + if (lead < 0xc2) { + return false; // trail byte or non-shortest form + } else if (lead <= 0xdf && (i + 1) <= length && IsUTF8TrailByte(s[i])) { + ++i; // 2-byte character + } else if (0xe0 <= lead && lead <= 0xef && (i + 2) <= length && + IsUTF8TrailByte(s[i]) && + IsUTF8TrailByte(s[i + 1]) && + // check for non-shortest form and surrogate + (lead != 0xe0 || s[i] >= 0xa0) && + (lead != 0xed || s[i] < 0xa0)) { + i += 2; // 3-byte character + } else if (0xf0 <= lead && lead <= 0xf4 && (i + 3) <= length && + IsUTF8TrailByte(s[i]) && + IsUTF8TrailByte(s[i + 1]) && + IsUTF8TrailByte(s[i + 2]) && + // check for non-shortest form + (lead != 0xf0 || s[i] >= 0x90) && + (lead != 0xf4 || s[i] < 0x90)) { + i += 3; // 4-byte character + } else { + return false; + } + } + return true; } -// Prints a ::wstring object. -#if GTEST_HAS_GLOBAL_WSTRING -void PrintWideStringTo(const ::wstring& s, ostream* os) { - PrintCharsAsStringTo(s.data(), s.size(), os); +void ConditionalPrintAsText(const char* str, size_t length, ostream* os) { + if (!ContainsUnprintableControlCodes(str, length) && + IsValidUTF8(str, length)) { + *os << "\n As Text: \"" << str << "\""; + } +} + +} // anonymous namespace + +void PrintStringTo(const ::std::string& s, ostream* os) { + if (PrintCharsAsStringTo(s.data(), s.size(), os) == kHexEscape) { + if (GTEST_FLAG(print_utf8)) { + ConditionalPrintAsText(s.data(), s.size(), os); + } + } } -#endif // GTEST_HAS_GLOBAL_WSTRING #if GTEST_HAS_STD_WSTRING void PrintWideStringTo(const ::std::wstring& s, ostream* os) { diff --git a/cpp/test/src/gtest-test-part.cc b/cpp/test/src/gtest-test-part.cc index fb0e35425e..a938683ced 100644 --- a/cpp/test/src/gtest-test-part.cc +++ b/cpp/test/src/gtest-test-part.cc @@ -26,21 +26,14 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + // -// Author: mheule@google.com (Markus Heule) -// -// The Google C++ Testing Framework (Google Test) +// The Google C++ Testing and Mocking Framework (Google Test) #include "gtest/gtest-test-part.h" -// Indicates that this translation unit is part of Google Test's -// implementation. It must come before gtest-internal-inl.h is -// included, or there will be a compiler error. This trick exists to -// prevent the accidental inclusion of gtest-internal-inl.h in the -// user's code. -#define GTEST_IMPLEMENTATION_ 1 +#include "gtest/internal/gtest-port.h" #include "src/gtest-internal-inl.h" -#undef GTEST_IMPLEMENTATION_ namespace testing { @@ -50,18 +43,23 @@ using internal::GetUnitTestImpl; // in it. std::string TestPartResult::ExtractSummary(const char* message) { const char* const stack_trace = strstr(message, internal::kStackTraceMarker); - return stack_trace == NULL ? message : - std::string(message, stack_trace); + return stack_trace == nullptr ? message : std::string(message, stack_trace); } // Prints a TestPartResult object. std::ostream& operator<<(std::ostream& os, const TestPartResult& result) { - return os - << result.file_name() << ":" << result.line_number() << ": " - << (result.type() == TestPartResult::kSuccess ? "Success" : - result.type() == TestPartResult::kFatalFailure ? "Fatal failure" : - "Non-fatal failure") << ":\n" - << result.message() << std::endl; + return os << internal::FormatFileLocation(result.file_name(), + result.line_number()) + << " " + << (result.type() == TestPartResult::kSuccess + ? "Success" + : result.type() == TestPartResult::kSkip + ? "Skipped" + : result.type() == TestPartResult::kFatalFailure + ? "Fatal failure" + : "Non-fatal failure") + << ":\n" + << result.message() << std::endl; } // Appends a TestPartResult to the array. @@ -76,7 +74,7 @@ const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const { internal::posix::Abort(); } - return array_[index]; + return array_[static_cast(index)]; } // Returns the number of TestPartResult objects in the array. diff --git a/cpp/test/src/gtest-typed-test.cc b/cpp/test/src/gtest-typed-test.cc index df1eef4754..8677caf732 100644 --- a/cpp/test/src/gtest-typed-test.cc +++ b/cpp/test/src/gtest-typed-test.cc @@ -26,10 +26,10 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Author: wan@google.com (Zhanyong Wan) + #include "gtest/gtest-typed-test.h" + #include "gtest/gtest.h" namespace testing { @@ -48,7 +48,7 @@ static const char* SkipSpaces(const char* str) { static std::vector SplitIntoTestNames(const char* src) { std::vector name_vec; src = SkipSpaces(src); - for (; src != NULL; src = SkipComma(src)) { + for (; src != nullptr; src = SkipComma(src)) { name_vec.push_back(StripTrailingSpaces(GetPrefixUntilComma(src))); } return name_vec; @@ -57,7 +57,7 @@ static std::vector SplitIntoTestNames(const char* src) { // Verifies that registered_tests match the test names in // registered_tests_; returns registered_tests if successful, or // aborts the program otherwise. -const char* TypedTestCasePState::VerifyRegisteredTestNames( +const char* TypedTestSuitePState::VerifyRegisteredTestNames( const char* file, int line, const char* registered_tests) { typedef RegisteredTestsMap::const_iterator RegisteredTestIter; registered_ = true; @@ -89,7 +89,7 @@ const char* TypedTestCasePState::VerifyRegisteredTestNames( tests.insert(name); } else { errors << "No test named " << name - << " can be found in this test case.\n"; + << " can be found in this test suite.\n"; } } diff --git a/cpp/test/src/gtest.cc b/cpp/test/src/gtest.cc index 3a18f25d1b..8afb070d2a 100644 --- a/cpp/test/src/gtest.cc +++ b/cpp/test/src/gtest.cc @@ -26,10 +26,9 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + // -// Author: wan@google.com (Zhanyong Wan) -// -// The Google C++ Testing Framework (Google Test) +// The Google C++ Testing and Mocking Framework (Google Test) #include "gtest/gtest.h" #include "gtest/internal/custom/gtest.h" @@ -55,8 +54,6 @@ #if GTEST_OS_LINUX -// TODO(kenton@google.com): Use autoconf to detect availability of -// gettimeofday(). # define GTEST_HAS_GETTIMEOFDAY_ 1 # include // NOLINT @@ -69,10 +66,6 @@ # include // NOLINT # include -#elif GTEST_OS_SYMBIAN -# define GTEST_HAS_GETTIMEOFDAY_ 1 -# include // NOLINT - #elif GTEST_OS_ZOS # define GTEST_HAS_GETTIMEOFDAY_ 1 # include // NOLINT @@ -87,6 +80,11 @@ #elif GTEST_OS_WINDOWS // We are on Windows proper. +# include // NOLINT +# undef min + +# include // NOLINT +# include // NOLINT # include // NOLINT # include // NOLINT # include // NOLINT @@ -94,25 +92,13 @@ # if GTEST_OS_WINDOWS_MINGW // MinGW has gettimeofday() but not _ftime64(). -// TODO(kenton@google.com): Use autoconf to detect availability of -// gettimeofday(). -// TODO(kenton@google.com): There are other ways to get the time on -// Windows, like GetTickCount() or GetSystemTimeAsFileTime(). MinGW -// supports these. consider using them instead. # define GTEST_HAS_GETTIMEOFDAY_ 1 # include // NOLINT # endif // GTEST_OS_WINDOWS_MINGW -// cpplint thinks that the header is already included, so we want to -// silence it. -# include // NOLINT -# undef min - #else // Assume other platforms have gettimeofday(). -// TODO(kenton@google.com): Use autoconf to detect availability of -// gettimeofday(). # define GTEST_HAS_GETTIMEOFDAY_ 1 // cpplint thinks that the header is already included, so we want to @@ -133,19 +119,25 @@ # include // NOLINT #endif -// Indicates that this translation unit is part of Google Test's -// implementation. It must come before gtest-internal-inl.h is -// included, or there will be a compiler error. This trick is to -// prevent a user from accidentally including gtest-internal-inl.h in -// his code. -#define GTEST_IMPLEMENTATION_ 1 #include "src/gtest-internal-inl.h" -#undef GTEST_IMPLEMENTATION_ #if GTEST_OS_WINDOWS # define vsnprintf _vsnprintf #endif // GTEST_OS_WINDOWS +#if GTEST_OS_MAC +#ifndef GTEST_OS_IOS +#include +#endif +#endif + +#if GTEST_HAS_ABSL +#include "absl/debugging/failure_signal_handler.h" +#include "absl/debugging/stacktrace.h" +#include "absl/debugging/symbolize.h" +#include "absl/strings/str_cat.h" +#endif // GTEST_HAS_ABSL + namespace testing { using internal::CountIf; @@ -155,20 +147,22 @@ using internal::Shuffle; // Constants. -// A test whose test case name or test name matches this filter is +// A test whose test suite name or test name matches this filter is // disabled and not run. static const char kDisableTestFilter[] = "DISABLED_*:*/DISABLED_*"; -// A test case whose name matches this filter is considered a death -// test case and will be run before test cases whose name doesn't +// A test suite whose name matches this filter is considered a death +// test suite and will be run before test suites whose name doesn't // match this filter. -static const char kDeathTestCaseFilter[] = "*DeathTest:*DeathTest/*"; +static const char kDeathTestSuiteFilter[] = "*DeathTest:*DeathTest/*"; // A test filter that matches everything. static const char kUniversalFilter[] = "*"; -// The default output file for XML output. -static const char kDefaultOutputFile[] = "test_detail.xml"; +// The default output format. +static const char kDefaultOutputFormat[] = "xml"; +// The default output file. +static const char kDefaultOutputFile[] = "test_detail"; // The environment variable name for the test shard index. static const char kTestShardIndex[] = "GTEST_SHARD_INDEX"; @@ -183,19 +177,35 @@ namespace internal { // stack trace. const char kStackTraceMarker[] = "\nStack trace:\n"; -// g_help_flag is true iff the --help flag or an equivalent form is -// specified on the command line. +// g_help_flag is true if and only if the --help flag or an equivalent form +// is specified on the command line. bool g_help_flag = false; +// Utilty function to Open File for Writing +static FILE* OpenFileForWriting(const std::string& output_file) { + FILE* fileout = nullptr; + FilePath output_file_path(output_file); + FilePath output_dir(output_file_path.RemoveFileName()); + + if (output_dir.CreateDirectoriesRecursively()) { + fileout = posix::FOpen(output_file.c_str(), "w"); + } + if (fileout == nullptr) { + GTEST_LOG_(FATAL) << "Unable to open file \"" << output_file << "\""; + } + return fileout; +} + } // namespace internal +// Bazel passes in the argument to '--test_filter' via the TESTBRIDGE_TEST_ONLY +// environment variable. static const char* GetDefaultFilter() { -#ifdef GTEST_TEST_FILTER_ENV_VAR_ - const char* const testbridge_test_only = getenv(GTEST_TEST_FILTER_ENV_VAR_); - if (testbridge_test_only != NULL) { + const char* const testbridge_test_only = + internal::posix::GetEnv("TESTBRIDGE_TEST_ONLY"); + if (testbridge_test_only != nullptr) { return testbridge_test_only; } -#endif // GTEST_TEST_FILTER_ENV_VAR_ return kUniversalFilter; } @@ -205,15 +215,14 @@ GTEST_DEFINE_bool_( "Run disabled tests too, in addition to the tests normally being run."); GTEST_DEFINE_bool_( - break_on_failure, - internal::BoolFromGTestEnv("break_on_failure", false), - "True iff a failed assertion should be a debugger break-point."); + break_on_failure, internal::BoolFromGTestEnv("break_on_failure", false), + "True if and only if a failed assertion should be a debugger " + "break-point."); -GTEST_DEFINE_bool_( - catch_exceptions, - internal::BoolFromGTestEnv("catch_exceptions", true), - "True iff " GTEST_NAME_ - " should catch exceptions and treat them as test failures."); +GTEST_DEFINE_bool_(catch_exceptions, + internal::BoolFromGTestEnv("catch_exceptions", true), + "True if and only if " GTEST_NAME_ + " should catch exceptions and treat them as test failures."); GTEST_DEFINE_string_( color, @@ -232,26 +241,41 @@ GTEST_DEFINE_string_( "exclude). A test is run if it matches one of the positive " "patterns and does not match any of the negative patterns."); +GTEST_DEFINE_bool_( + install_failure_signal_handler, + internal::BoolFromGTestEnv("install_failure_signal_handler", false), + "If true and supported on the current platform, " GTEST_NAME_ " should " + "install a signal handler that dumps debugging information when fatal " + "signals are raised."); + GTEST_DEFINE_bool_(list_tests, false, "List all tests without running them."); +// The net priority order after flag processing is thus: +// --gtest_output command line flag +// GTEST_OUTPUT environment variable +// XML_OUTPUT_FILE environment variable +// '' GTEST_DEFINE_string_( output, - internal::StringFromGTestEnv("output", ""), - "A format (currently must be \"xml\"), optionally followed " - "by a colon and an output file name or directory. A directory " - "is indicated by a trailing pathname separator. " + internal::StringFromGTestEnv("output", + internal::OutputFlagAlsoCheckEnvVar().c_str()), + "A format (defaults to \"xml\" but can be specified to be \"json\"), " + "optionally followed by a colon and an output file name or directory. " + "A directory is indicated by a trailing pathname separator. " "Examples: \"xml:filename.xml\", \"xml::directoryname/\". " "If a directory is specified, output files will be created " "within that directory, with file-names based on the test " "executable's name and, if necessary, made unique by adding " "digits."); -GTEST_DEFINE_bool_( - print_time, - internal::BoolFromGTestEnv("print_time", true), - "True iff " GTEST_NAME_ - " should display elapsed time in text output."); +GTEST_DEFINE_bool_(print_time, internal::BoolFromGTestEnv("print_time", true), + "True if and only if " GTEST_NAME_ + " should display elapsed time in text output."); + +GTEST_DEFINE_bool_(print_utf8, internal::BoolFromGTestEnv("print_utf8", true), + "True if and only if " GTEST_NAME_ + " prints UTF8 characters as text."); GTEST_DEFINE_int32_( random_seed, @@ -265,16 +289,14 @@ GTEST_DEFINE_int32_( "How many times to repeat each test. Specify a negative number " "for repeating forever. Useful for shaking out flaky tests."); -GTEST_DEFINE_bool_( - show_internal_stack_frames, false, - "True iff " GTEST_NAME_ " should include internal stack frames when " - "printing test failure stack traces."); +GTEST_DEFINE_bool_(show_internal_stack_frames, false, + "True if and only if " GTEST_NAME_ + " should include internal stack frames when " + "printing test failure stack traces."); -GTEST_DEFINE_bool_( - shuffle, - internal::BoolFromGTestEnv("shuffle", false), - "True iff " GTEST_NAME_ - " should randomize tests' order on every run."); +GTEST_DEFINE_bool_(shuffle, internal::BoolFromGTestEnv("shuffle", false), + "True if and only if " GTEST_NAME_ + " should randomize tests' order on every run."); GTEST_DEFINE_int32_( stack_trace_depth, @@ -294,7 +316,7 @@ GTEST_DEFINE_bool_( internal::BoolFromGTestEnv("throw_on_failure", false), "When this flag is specified, a failed assertion will throw an exception " "if exceptions are enabled or exit the program with a non-zero code " - "otherwise."); + "otherwise. For use with an external test framework."); #if GTEST_USE_OWN_FLAGFILE_FLAG_ GTEST_DEFINE_string_( @@ -310,7 +332,8 @@ namespace internal { // than kMaxRange. UInt32 Random::Generate(UInt32 range) { // These constants are the same as are used in glibc's rand(3). - state_ = (1103515245U*state_ + 12345U) % kMaxRange; + // Use wider types than necessary to prevent unsigned overflow diagnostics. + state_ = static_cast(1103515245ULL*state_ + 12345U) % kMaxRange; GTEST_CHECK_(range > 0) << "Cannot generate a number in the range [0, 0)."; @@ -324,16 +347,16 @@ UInt32 Random::Generate(UInt32 range) { return state_ % range; } -// GTestIsInitialized() returns true iff the user has initialized +// GTestIsInitialized() returns true if and only if the user has initialized // Google Test. Useful for catching the user mistake of not initializing // Google Test before calling RUN_ALL_TESTS(). static bool GTestIsInitialized() { return GetArgvs().size() > 0; } -// Iterates over a vector of TestCases, keeping a running sum of the +// Iterates over a vector of TestSuites, keeping a running sum of the // results of calling a given int-returning method on each. // Returns the sum. -static int SumOverTestCaseList(const std::vector& case_list, - int (TestCase::*method)() const) { +static int SumOverTestSuiteList(const std::vector& case_list, + int (TestSuite::*method)() const) { int sum = 0; for (size_t i = 0; i < case_list.size(); i++) { sum += (case_list[i]->*method)(); @@ -341,20 +364,20 @@ static int SumOverTestCaseList(const std::vector& case_list, return sum; } -// Returns true iff the test case passed. -static bool TestCasePassed(const TestCase* test_case) { - return test_case->should_run() && test_case->Passed(); +// Returns true if and only if the test suite passed. +static bool TestSuitePassed(const TestSuite* test_suite) { + return test_suite->should_run() && test_suite->Passed(); } -// Returns true iff the test case failed. -static bool TestCaseFailed(const TestCase* test_case) { - return test_case->should_run() && test_case->Failed(); +// Returns true if and only if the test suite failed. +static bool TestSuiteFailed(const TestSuite* test_suite) { + return test_suite->should_run() && test_suite->Failed(); } -// Returns true iff test_case contains at least one test that should -// run. -static bool ShouldRunTestCase(const TestCase* test_case) { - return test_case->should_run(); +// Returns true if and only if test_suite contains at least one test that +// should run. +static bool ShouldRunTestSuite(const TestSuite* test_suite) { + return test_suite->should_run(); } // AssertHelper constructor. @@ -380,16 +403,16 @@ void AssertHelper::operator=(const Message& message) const { ); // NOLINT } -// Mutex for linked pointers. -GTEST_API_ GTEST_DEFINE_STATIC_MUTEX_(g_linked_ptr_mutex); - // A copy of all command line arguments. Set by InitGoogleTest(). -::std::vector g_argvs; +static ::std::vector g_argvs; -const ::std::vector& GetArgvs() { +::std::vector GetArgvs() { #if defined(GTEST_CUSTOM_GET_ARGVS_) - return GTEST_CUSTOM_GET_ARGVS_(); -#else // defined(GTEST_CUSTOM_GET_ARGVS_) + // GTEST_CUSTOM_GET_ARGVS_() may return a container of std::string or + // ::string. This code converts it to the appropriate type. + const auto& custom = GTEST_CUSTOM_GET_ARGVS_(); + return ::std::vector(custom.begin(), custom.end()); +#else // defined(GTEST_CUSTOM_GET_ARGVS_) return g_argvs; #endif // defined(GTEST_CUSTOM_GET_ARGVS_) } @@ -399,7 +422,7 @@ const ::std::vector& GetArgvs() { FilePath GetCurrentExecutableName() { FilePath result; -#if GTEST_OS_WINDOWS +#if GTEST_OS_WINDOWS || GTEST_OS_OS2 result.Set(FilePath(GetArgvs()[0]).RemoveExtension("exe")); #else result.Set(FilePath(GetArgvs()[0])); @@ -413,34 +436,32 @@ FilePath GetCurrentExecutableName() { // Returns the output format, or "" for normal printed output. std::string UnitTestOptions::GetOutputFormat() { const char* const gtest_output_flag = GTEST_FLAG(output).c_str(); - if (gtest_output_flag == NULL) return std::string(""); - const char* const colon = strchr(gtest_output_flag, ':'); - return (colon == NULL) ? - std::string(gtest_output_flag) : - std::string(gtest_output_flag, colon - gtest_output_flag); + return (colon == nullptr) + ? std::string(gtest_output_flag) + : std::string(gtest_output_flag, + static_cast(colon - gtest_output_flag)); } // Returns the name of the requested output file, or the default if none // was explicitly specified. std::string UnitTestOptions::GetAbsolutePathToOutputFile() { const char* const gtest_output_flag = GTEST_FLAG(output).c_str(); - if (gtest_output_flag == NULL) - return ""; + + std::string format = GetOutputFormat(); + if (format.empty()) + format = std::string(kDefaultOutputFormat); const char* const colon = strchr(gtest_output_flag, ':'); - if (colon == NULL) - return internal::FilePath::ConcatPaths( + if (colon == nullptr) + return internal::FilePath::MakeFileName( internal::FilePath( UnitTest::GetInstance()->original_working_dir()), - internal::FilePath(kDefaultOutputFile)).string(); + internal::FilePath(kDefaultOutputFile), 0, + format.c_str()).string(); internal::FilePath output_name(colon + 1); if (!output_name.IsAbsolutePath()) - // TODO(wan@google.com): on Windows \some\path is not an absolute - // path (as its meaning depends on the current drive), yet the - // following logic for turning it into an absolute path is wrong. - // Fix it. output_name = internal::FilePath::ConcatPaths( internal::FilePath(UnitTest::GetInstance()->original_working_dir()), internal::FilePath(colon + 1)); @@ -454,8 +475,8 @@ std::string UnitTestOptions::GetAbsolutePathToOutputFile() { return result.string(); } -// Returns true iff the wildcard pattern matches the string. The -// first ':' or '\0' character in pattern marks the end of it. +// Returns true if and only if the wildcard pattern matches the string. +// The first ':' or '\0' character in pattern marks the end of it. // // This recursive algorithm isn't very efficient, but is clear and // works well enough for matching test names, which are short. @@ -488,7 +509,7 @@ bool UnitTestOptions::MatchesFilter( cur_pattern = strchr(cur_pattern, ':'); // Returns if no more pattern can be found. - if (cur_pattern == NULL) { + if (cur_pattern == nullptr) { return false; } @@ -497,11 +518,11 @@ bool UnitTestOptions::MatchesFilter( } } -// Returns true iff the user-specified filter matches the test case -// name and the test name. -bool UnitTestOptions::FilterMatchesTest(const std::string &test_case_name, - const std::string &test_name) { - const std::string& full_name = test_case_name + "." + test_name.c_str(); +// Returns true if and only if the user-specified filter matches the test +// suite name and the test name. +bool UnitTestOptions::FilterMatchesTest(const std::string& test_suite_name, + const std::string& test_name) { + const std::string& full_name = test_suite_name + "." + test_name.c_str(); // Split --gtest_filter at '-', if there is one, to separate into // positive filter and negative filter portions @@ -509,7 +530,7 @@ bool UnitTestOptions::FilterMatchesTest(const std::string &test_case_name, const char* const dash = strchr(p, '-'); std::string positive; std::string negative; - if (dash == NULL) { + if (dash == nullptr) { positive = GTEST_FLAG(filter).c_str(); // Whole string is a positive filter negative = ""; } else { @@ -628,12 +649,12 @@ extern const TypeId kTestTypeIdInGoogleTest = GetTestTypeId(); // This predicate-formatter checks that 'results' contains a test part // failure of the given type and that the failure message contains the // given substring. -AssertionResult HasOneFailure(const char* /* results_expr */, - const char* /* type_expr */, - const char* /* substr_expr */, - const TestPartResultArray& results, - TestPartResult::Type type, - const std::string& substr) { +static AssertionResult HasOneFailure(const char* /* results_expr */, + const char* /* type_expr */, + const char* /* substr_expr */, + const TestPartResultArray& results, + TestPartResult::Type type, + const std::string& substr) { const std::string expected(type == TestPartResult::kFatalFailure ? "1 fatal failure" : "1 non-fatal failure"); @@ -654,7 +675,7 @@ AssertionResult HasOneFailure(const char* /* results_expr */, << r; } - if (strstr(r.message(), substr.c_str()) == NULL) { + if (strstr(r.message(), substr.c_str()) == nullptr) { return AssertionFailure() << "Expected: " << expected << " containing \"" << substr << "\"\n" << " Actual:\n" @@ -723,61 +744,66 @@ void UnitTestImpl::SetTestPartResultReporterForCurrentThread( per_thread_test_part_result_reporter_.set(reporter); } -// Gets the number of successful test cases. -int UnitTestImpl::successful_test_case_count() const { - return CountIf(test_cases_, TestCasePassed); +// Gets the number of successful test suites. +int UnitTestImpl::successful_test_suite_count() const { + return CountIf(test_suites_, TestSuitePassed); } -// Gets the number of failed test cases. -int UnitTestImpl::failed_test_case_count() const { - return CountIf(test_cases_, TestCaseFailed); +// Gets the number of failed test suites. +int UnitTestImpl::failed_test_suite_count() const { + return CountIf(test_suites_, TestSuiteFailed); } -// Gets the number of all test cases. -int UnitTestImpl::total_test_case_count() const { - return static_cast(test_cases_.size()); +// Gets the number of all test suites. +int UnitTestImpl::total_test_suite_count() const { + return static_cast(test_suites_.size()); } -// Gets the number of all test cases that contain at least one test +// Gets the number of all test suites that contain at least one test // that should run. -int UnitTestImpl::test_case_to_run_count() const { - return CountIf(test_cases_, ShouldRunTestCase); +int UnitTestImpl::test_suite_to_run_count() const { + return CountIf(test_suites_, ShouldRunTestSuite); } // Gets the number of successful tests. int UnitTestImpl::successful_test_count() const { - return SumOverTestCaseList(test_cases_, &TestCase::successful_test_count); + return SumOverTestSuiteList(test_suites_, &TestSuite::successful_test_count); +} + +// Gets the number of skipped tests. +int UnitTestImpl::skipped_test_count() const { + return SumOverTestSuiteList(test_suites_, &TestSuite::skipped_test_count); } // Gets the number of failed tests. int UnitTestImpl::failed_test_count() const { - return SumOverTestCaseList(test_cases_, &TestCase::failed_test_count); + return SumOverTestSuiteList(test_suites_, &TestSuite::failed_test_count); } // Gets the number of disabled tests that will be reported in the XML report. int UnitTestImpl::reportable_disabled_test_count() const { - return SumOverTestCaseList(test_cases_, - &TestCase::reportable_disabled_test_count); + return SumOverTestSuiteList(test_suites_, + &TestSuite::reportable_disabled_test_count); } // Gets the number of disabled tests. int UnitTestImpl::disabled_test_count() const { - return SumOverTestCaseList(test_cases_, &TestCase::disabled_test_count); + return SumOverTestSuiteList(test_suites_, &TestSuite::disabled_test_count); } // Gets the number of tests to be printed in the XML report. int UnitTestImpl::reportable_test_count() const { - return SumOverTestCaseList(test_cases_, &TestCase::reportable_test_count); + return SumOverTestSuiteList(test_suites_, &TestSuite::reportable_test_count); } // Gets the number of all tests. int UnitTestImpl::total_test_count() const { - return SumOverTestCaseList(test_cases_, &TestCase::total_test_count); + return SumOverTestSuiteList(test_suites_, &TestSuite::total_test_count); } // Gets the number of tests that should run. int UnitTestImpl::test_to_run_count() const { - return SumOverTestCaseList(test_cases_, &TestCase::test_to_run_count); + return SumOverTestSuiteList(test_suites_, &TestSuite::test_to_run_count); } // Returns the current OS stack trace as an std::string. @@ -811,8 +837,6 @@ TimeInMillis GetTimeInMillis() { SYSTEMTIME now_systime; FILETIME now_filetime; ULARGE_INTEGER now_int64; - // TODO(kenton@google.com): Shouldn't this just use - // GetSystemTimeAsFileTime()? GetSystemTime(&now_systime); if (SystemTimeToFileTime(&now_systime, &now_filetime)) { now_int64.LowPart = now_filetime.dwLowDateTime; @@ -827,16 +851,14 @@ TimeInMillis GetTimeInMillis() { // MSVC 8 deprecates _ftime64(), so we want to suppress warning 4996 // (deprecated function) there. - // TODO(kenton@google.com): Use GetTickCount()? Or use - // SystemTimeToFileTime() - GTEST_DISABLE_MSC_WARNINGS_PUSH_(4996) + GTEST_DISABLE_MSC_DEPRECATED_PUSH_() _ftime64(&now); - GTEST_DISABLE_MSC_WARNINGS_POP_() + GTEST_DISABLE_MSC_DEPRECATED_POP_() return static_cast(now.time) * 1000 + now.millitm; #elif GTEST_HAS_GETTIMEOFDAY_ struct timeval now; - gettimeofday(&now, NULL); + gettimeofday(&now, nullptr); return static_cast(now.tv_sec) * 1000 + now.tv_usec / 1000; #else # error "Don't know how to get the current time on your system." @@ -853,11 +875,10 @@ TimeInMillis GetTimeInMillis() { // value using delete[]. Returns the wide string, or NULL if the // input is NULL. LPCWSTR String::AnsiToUtf16(const char* ansi) { - if (!ansi) return NULL; + if (!ansi) return nullptr; const int length = strlen(ansi); const int unicode_length = - MultiByteToWideChar(CP_ACP, 0, ansi, length, - NULL, 0); + MultiByteToWideChar(CP_ACP, 0, ansi, length, nullptr, 0); WCHAR* unicode = new WCHAR[unicode_length + 1]; MultiByteToWideChar(CP_ACP, 0, ansi, length, unicode, unicode_length); @@ -870,33 +891,33 @@ LPCWSTR String::AnsiToUtf16(const char* ansi) { // value using delete[]. Returns the ANSI string, or NULL if the // input is NULL. const char* String::Utf16ToAnsi(LPCWSTR utf16_str) { - if (!utf16_str) return NULL; - const int ansi_length = - WideCharToMultiByte(CP_ACP, 0, utf16_str, -1, - NULL, 0, NULL, NULL); + if (!utf16_str) return nullptr; + const int ansi_length = WideCharToMultiByte(CP_ACP, 0, utf16_str, -1, nullptr, + 0, nullptr, nullptr); char* ansi = new char[ansi_length + 1]; - WideCharToMultiByte(CP_ACP, 0, utf16_str, -1, - ansi, ansi_length, NULL, NULL); + WideCharToMultiByte(CP_ACP, 0, utf16_str, -1, ansi, ansi_length, nullptr, + nullptr); ansi[ansi_length] = 0; return ansi; } #endif // GTEST_OS_WINDOWS_MOBILE -// Compares two C strings. Returns true iff they have the same content. +// Compares two C strings. Returns true if and only if they have the same +// content. // // Unlike strcmp(), this function can handle NULL argument(s). A NULL // C string is considered different to any non-NULL C string, // including the empty string. bool String::CStringEquals(const char * lhs, const char * rhs) { - if ( lhs == NULL ) return rhs == NULL; + if (lhs == nullptr) return rhs == nullptr; - if ( rhs == NULL ) return false; + if (rhs == nullptr) return false; return strcmp(lhs, rhs) == 0; } -#if GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING +#if GTEST_HAS_STD_WSTRING // Converts an array of wide chars to a narrow string using the UTF-8 // encoding, and streams the result to the given Message object. @@ -914,7 +935,7 @@ static void StreamWideCharsToMessage(const wchar_t* wstr, size_t length, } } -#endif // GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING +#endif // GTEST_HAS_STD_WSTRING void SplitString(const ::std::string& str, char delimiter, ::std::vector< ::std::string>* dest) { @@ -964,15 +985,6 @@ Message& Message::operator <<(const ::std::wstring& wstr) { } #endif // GTEST_HAS_STD_WSTRING -#if GTEST_HAS_GLOBAL_WSTRING -// Converts the given wide string to a narrow string using the UTF-8 -// encoding, and streams the result to this Message object. -Message& Message::operator <<(const ::wstring& wstr) { - internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this); - return *this; -} -#endif // GTEST_HAS_GLOBAL_WSTRING - // Gets the text streamed to this object so far as an std::string. // Each '\0' character in the buffer is replaced with "\\0". std::string Message::GetString() const { @@ -983,10 +995,9 @@ std::string Message::GetString() const { // Used in EXPECT_TRUE/FALSE(assertion_result). AssertionResult::AssertionResult(const AssertionResult& other) : success_(other.success_), - message_(other.message_.get() != NULL ? - new ::std::string(*other.message_) : - static_cast< ::std::string*>(NULL)) { -} + message_(other.message_.get() != nullptr + ? new ::std::string(*other.message_) + : static_cast< ::std::string*>(nullptr)) {} // Swaps two AssertionResults. void AssertionResult::swap(AssertionResult& other) { @@ -998,8 +1009,7 @@ void AssertionResult::swap(AssertionResult& other) { // Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE. AssertionResult AssertionResult::operator!() const { AssertionResult negation(!success_); - if (message_.get() != NULL) - negation << *message_; + if (message_.get() != nullptr) negation << *message_; return negation; } @@ -1168,7 +1178,7 @@ class Hunk { // Print a unified diff header for one hunk. // The format is // "@@ -, +, @@" - // where the left/right parts are ommitted if unnecessary. + // where the left/right parts are omitted if unnecessary. void PrintHeader(std::ostream* ss) const { *ss << "@@ "; if (removes_) { @@ -1225,9 +1235,10 @@ std::string CreateUnifiedDiff(const std::vector& left, for (; edit_i < edits.size(); ++edit_i) { if (n_suffix >= context) { // Continue only if the next hunk is very close. - std::vector::const_iterator it = edits.begin() + edit_i; + auto it = edits.begin() + static_cast(edit_i); while (it != edits.end() && *it == kMatch) ++it; - if (it == edits.end() || (it - edits.begin()) - edit_i >= context) { + if (it == edits.end() || + static_cast(it - edits.begin()) - edit_i >= context) { // There is no next edit or it is too far away. break; } @@ -1303,7 +1314,7 @@ std::vector SplitEscapedString(const std::string& str) { // lhs_value: "5" // rhs_value: "6" // -// The ignoring_case parameter is true iff the assertion is a +// The ignoring_case parameter is true if and only if the assertion is a // *_STRCASEEQ*. When it's true, the string "Ignoring case" will // be inserted into the message. AssertionResult EqFailure(const char* lhs_expression, @@ -1312,13 +1323,14 @@ AssertionResult EqFailure(const char* lhs_expression, const std::string& rhs_value, bool ignoring_case) { Message msg; - msg << " Expected: " << lhs_expression; + msg << "Expected equality of these values:"; + msg << "\n " << lhs_expression; if (lhs_value != lhs_expression) { - msg << "\n Which is: " << lhs_value; + msg << "\n Which is: " << lhs_value; } - msg << "\nTo be equal to: " << rhs_expression; + msg << "\n " << rhs_expression; if (rhs_value != rhs_expression) { - msg << "\n Which is: " << rhs_value; + msg << "\n Which is: " << rhs_value; } if (ignoring_case) { @@ -1365,8 +1377,6 @@ AssertionResult DoubleNearPredFormat(const char* expr1, const double diff = fabs(val1 - val2); if (diff <= abs_error) return AssertionSuccess(); - // TODO(wan): do not print the value of an expression if it's - // already a literal. return AssertionFailure() << "The difference between " << expr1 << " and " << expr2 << " is " << diff << ", which exceeds " << abs_error_expr << ", where\n" @@ -1547,22 +1557,20 @@ namespace { // Helper functions for implementing IsSubString() and IsNotSubstring(). -// This group of overloaded functions return true iff needle is a -// substring of haystack. NULL is considered a substring of itself -// only. +// This group of overloaded functions return true if and only if needle +// is a substring of haystack. NULL is considered a substring of +// itself only. bool IsSubstringPred(const char* needle, const char* haystack) { - if (needle == NULL || haystack == NULL) - return needle == haystack; + if (needle == nullptr || haystack == nullptr) return needle == haystack; - return strstr(haystack, needle) != NULL; + return strstr(haystack, needle) != nullptr; } bool IsSubstringPred(const wchar_t* needle, const wchar_t* haystack) { - if (needle == NULL || haystack == NULL) - return needle == haystack; + if (needle == nullptr || haystack == nullptr) return needle == haystack; - return wcsstr(haystack, needle) != NULL; + return wcsstr(haystack, needle) != nullptr; } // StringType here can be either ::std::string or ::std::wstring. @@ -1660,7 +1668,7 @@ namespace { AssertionResult HRESULTFailureHelper(const char* expr, const char* expected, long hr) { // NOLINT -# if GTEST_OS_WINDOWS_MOBILE +# if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_TV_TITLE // Windows CE doesn't support FormatMessage. const char error_text[] = ""; @@ -1676,12 +1684,12 @@ AssertionResult HRESULTFailureHelper(const char* expr, // Gets the system's human readable message string for this HRESULT. char error_text[kBufSize] = { '\0' }; DWORD message_length = ::FormatMessageA(kFlags, - 0, // no source, we're asking system - hr, // the error - 0, // no line width restrictions + 0, // no source, we're asking system + static_cast(hr), // the error + 0, // no line width restrictions error_text, // output buffer - kBufSize, // buf size - NULL); // no arguments for inserts + kBufSize, // buf size + nullptr); // no arguments for inserts // Trims tailing white space (FormatMessage leaves a trailing CR-LF) for (; message_length && IsSpace(error_text[message_length - 1]); --message_length) { @@ -1717,7 +1725,7 @@ AssertionResult IsHRESULTFailure(const char* expr, long hr) { // NOLINT // Utility functions for encoding Unicode text (wide strings) in // UTF-8. -// A Unicode code-point can have upto 21 bits, and is encoded in UTF-8 +// A Unicode code-point can have up to 21 bits, and is encoded in UTF-8 // like this: // // Code-point length Encoding @@ -1755,7 +1763,7 @@ inline UInt32 ChopLowBits(UInt32* bits, int n) { // to "(Invalid Unicode 0xXXXXXXXX)". std::string CodePointToUtf8(UInt32 code_point) { if (code_point > kMaxCodePoint4) { - return "(Invalid Unicode 0x" + String::FormatHexInt(code_point) + ")"; + return "(Invalid Unicode 0x" + String::FormatHexUInt32(code_point) + ")"; } char str[5]; // Big enough for the largest valid code point. @@ -1781,9 +1789,9 @@ std::string CodePointToUtf8(UInt32 code_point) { return str; } -// The following two functions only make sense if the the system +// The following two functions only make sense if the system // uses UTF-16 for wide string encoding. All supported systems -// with 16 bit wchar_t (Windows, Cygwin, Symbian OS) do use UTF-16. +// with 16 bit wchar_t (Windows, Cygwin) do use UTF-16. // Determines if the arguments constitute UTF-16 surrogate pair // and thus should be combined into a single Unicode code point @@ -1796,17 +1804,20 @@ inline bool IsUtf16SurrogatePair(wchar_t first, wchar_t second) { // Creates a Unicode code point from UTF16 surrogate pair. inline UInt32 CreateCodePointFromUtf16SurrogatePair(wchar_t first, wchar_t second) { + const auto first_u = static_cast(first); + const auto second_u = static_cast(second); const UInt32 mask = (1 << 10) - 1; - return (sizeof(wchar_t) == 2) ? - (((first & mask) << 10) | (second & mask)) + 0x10000 : - // This function should not be called when the condition is - // false, but we provide a sensible default in case it is. - static_cast(first); + return (sizeof(wchar_t) == 2) + ? (((first_u & mask) << 10) | (second_u & mask)) + 0x10000 + : + // This function should not be called when the condition is + // false, but we provide a sensible default in case it is. + first_u; } // Converts a wide string to a narrow string in UTF-8 encoding. // The wide string is assumed to have the following encoding: -// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS) +// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin) // UTF-32 if sizeof(wchar_t) == 4 (on Linux) // Parameter str points to a null-terminated wide string. // Parameter num_chars may additionally limit the number @@ -1843,21 +1854,21 @@ std::string WideStringToUtf8(const wchar_t* str, int num_chars) { // Converts a wide C string to an std::string using the UTF-8 encoding. // NULL will be converted to "(null)". std::string String::ShowWideCString(const wchar_t * wide_c_str) { - if (wide_c_str == NULL) return "(null)"; + if (wide_c_str == nullptr) return "(null)"; return internal::WideStringToUtf8(wide_c_str, -1); } -// Compares two wide C strings. Returns true iff they have the same -// content. +// Compares two wide C strings. Returns true if and only if they have the +// same content. // // Unlike wcscmp(), this function can handle NULL argument(s). A NULL // C string is considered different to any non-NULL C string, // including the empty string. bool String::WideCStringEquals(const wchar_t * lhs, const wchar_t * rhs) { - if (lhs == NULL) return rhs == NULL; + if (lhs == nullptr) return rhs == nullptr; - if (rhs == NULL) return false; + if (rhs == nullptr) return false; return wcscmp(lhs, rhs) == 0; } @@ -1893,37 +1904,35 @@ AssertionResult CmpHelperSTRNE(const char* s1_expression, << " vs " << PrintToString(s2); } -// Compares two C strings, ignoring case. Returns true iff they have +// Compares two C strings, ignoring case. Returns true if and only if they have // the same content. // // Unlike strcasecmp(), this function can handle NULL argument(s). A // NULL C string is considered different to any non-NULL C string, // including the empty string. bool String::CaseInsensitiveCStringEquals(const char * lhs, const char * rhs) { - if (lhs == NULL) - return rhs == NULL; - if (rhs == NULL) - return false; + if (lhs == nullptr) return rhs == nullptr; + if (rhs == nullptr) return false; return posix::StrCaseCmp(lhs, rhs) == 0; } - // Compares two wide C strings, ignoring case. Returns true iff they - // have the same content. - // - // Unlike wcscasecmp(), this function can handle NULL argument(s). - // A NULL C string is considered different to any non-NULL wide C string, - // including the empty string. - // NB: The implementations on different platforms slightly differ. - // On windows, this method uses _wcsicmp which compares according to LC_CTYPE - // environment variable. On GNU platform this method uses wcscasecmp - // which compares according to LC_CTYPE category of the current locale. - // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the - // current locale. +// Compares two wide C strings, ignoring case. Returns true if and only if they +// have the same content. +// +// Unlike wcscasecmp(), this function can handle NULL argument(s). +// A NULL C string is considered different to any non-NULL wide C string, +// including the empty string. +// NB: The implementations on different platforms slightly differ. +// On windows, this method uses _wcsicmp which compares according to LC_CTYPE +// environment variable. On GNU platform this method uses wcscasecmp +// which compares according to LC_CTYPE category of the current locale. +// On MacOS X, it uses towlower, which also uses LC_CTYPE category of the +// current locale. bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs, const wchar_t* rhs) { - if (lhs == NULL) return rhs == NULL; + if (lhs == nullptr) return rhs == nullptr; - if (rhs == NULL) return false; + if (rhs == nullptr) return false; #if GTEST_OS_WINDOWS return _wcsicmp(lhs, rhs) == 0; @@ -1934,14 +1943,14 @@ bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs, // Other unknown OSes may not define it either. wint_t left, right; do { - left = towlower(*lhs++); - right = towlower(*rhs++); + left = towlower(static_cast(*lhs++)); + right = towlower(static_cast(*rhs++)); } while (left && left == right); return left == right; #endif // OS selector } -// Returns true iff str ends with the given suffix, ignoring case. +// Returns true if and only if str ends with the given suffix, ignoring case. // Any string is considered to end with an empty suffix. bool String::EndsWithCaseInsensitive( const std::string& str, const std::string& suffix) { @@ -1960,12 +1969,17 @@ std::string String::FormatIntWidth2(int value) { } // Formats an int value as "%X". -std::string String::FormatHexInt(int value) { +std::string String::FormatHexUInt32(UInt32 value) { std::stringstream ss; ss << std::hex << std::uppercase << value; return ss.str(); } +// Formats an int value as "%X". +std::string String::FormatHexInt(int value) { + return FormatHexUInt32(static_cast(value)); +} + // Formats a byte as "%02X". std::string String::FormatByte(unsigned char value) { std::stringstream ss; @@ -1982,7 +1996,7 @@ std::string StringStreamToString(::std::stringstream* ss) { const char* const end = start + str.length(); std::string result; - result.reserve(2 * (end - start)); + result.reserve(static_cast(2 * (end - start))); for (const char* ch = start; ch != end; ++ch) { if (*ch == '\0') { result += "\\0"; // Replaces NUL with "\\0"; @@ -2012,9 +2026,7 @@ std::string AppendUserMessage(const std::string& gtest_msg, // Creates an empty TestResult. TestResult::TestResult() - : death_test_count_(0), - elapsed_time_(0) { -} + : death_test_count_(0), start_timestamp_(0), elapsed_time_(0) {} // D'tor. TestResult::~TestResult() { @@ -2026,7 +2038,7 @@ TestResult::~TestResult() { const TestPartResult& TestResult::GetTestPartResult(int i) const { if (i < 0 || i >= total_part_count()) internal::posix::Abort(); - return test_part_results_.at(i); + return test_part_results_.at(static_cast(i)); } // Returns the i-th test property. i can range from 0 to @@ -2035,7 +2047,7 @@ const TestPartResult& TestResult::GetTestPartResult(int i) const { const TestProperty& TestResult::GetTestProperty(int i) const { if (i < 0 || i >= test_property_count()) internal::posix::Abort(); - return test_properties_.at(i); + return test_properties_.at(static_cast(i)); } // Clears the test part results. @@ -2083,23 +2095,18 @@ static const char* const kReservedTestSuitesAttributes[] = { // The list of reserved attributes used in the element of XML // output. static const char* const kReservedTestSuiteAttributes[] = { - "disabled", - "errors", - "failures", - "name", - "tests", - "time" -}; + "disabled", "errors", "failures", "name", "tests", "time", "timestamp"}; // The list of reserved attributes used in the element of XML output. static const char* const kReservedTestCaseAttributes[] = { - "classname", - "name", - "status", - "time", - "type_param", - "value_param" -}; + "classname", "name", "status", "time", "type_param", + "value_param", "file", "line"}; + +// Use a slightly different set for allowed output to ensure existing tests can +// still RecordProperty("result") or "RecordProperty(timestamp") +static const char* const kReservedOutputTestCaseAttributes[] = { + "classname", "name", "status", "time", "type_param", + "value_param", "file", "line", "result", "timestamp"}; template std::vector ArrayAsVector(const char* const (&array)[kSize]) { @@ -2121,6 +2128,22 @@ static std::vector GetReservedAttributesForElement( return std::vector(); } +// TODO(jdesprez): Merge the two getReserved attributes once skip is improved +static std::vector GetReservedOutputAttributesForElement( + const std::string& xml_element) { + if (xml_element == "testsuites") { + return ArrayAsVector(kReservedTestSuitesAttributes); + } else if (xml_element == "testsuite") { + return ArrayAsVector(kReservedTestSuiteAttributes); + } else if (xml_element == "testcase") { + return ArrayAsVector(kReservedOutputTestCaseAttributes); + } else { + GTEST_CHECK_(false) << "Unrecognized xml_element provided: " << xml_element; + } + // This code is unreachable but some compilers may not realizes that. + return std::vector(); +} + static std::string FormatWordList(const std::vector& words) { Message word_list; for (size_t i = 0; i < words.size(); ++i) { @@ -2135,8 +2158,9 @@ static std::string FormatWordList(const std::vector& words) { return word_list.GetString(); } -bool ValidateTestPropertyName(const std::string& property_name, - const std::vector& reserved_names) { +static bool ValidateTestPropertyName( + const std::string& property_name, + const std::vector& reserved_names) { if (std::find(reserved_names.begin(), reserved_names.end(), property_name) != reserved_names.end()) { ADD_FAILURE() << "Reserved key used in RecordProperty(): " << property_name @@ -2163,7 +2187,17 @@ void TestResult::Clear() { elapsed_time_ = 0; } -// Returns true iff the test failed. +// Returns true off the test part was skipped. +static bool TestPartSkipped(const TestPartResult& result) { + return result.skipped(); +} + +// Returns true if and only if the test was skipped. +bool TestResult::Skipped() const { + return !Failed() && CountIf(test_part_results_, TestPartSkipped) > 0; +} + +// Returns true if and only if the test failed. bool TestResult::Failed() const { for (int i = 0; i < total_part_count(); ++i) { if (GetTestPartResult(i).failed()) @@ -2172,22 +2206,22 @@ bool TestResult::Failed() const { return false; } -// Returns true iff the test part fatally failed. +// Returns true if and only if the test part fatally failed. static bool TestPartFatallyFailed(const TestPartResult& result) { return result.fatally_failed(); } -// Returns true iff the test fatally failed. +// Returns true if and only if the test fatally failed. bool TestResult::HasFatalFailure() const { return CountIf(test_part_results_, TestPartFatallyFailed) > 0; } -// Returns true iff the test part non-fatally failed. +// Returns true if and only if the test part non-fatally failed. static bool TestPartNonfatallyFailed(const TestPartResult& result) { return result.nonfatally_failed(); } -// Returns true iff the test has a non-fatal failure. +// Returns true if and only if the test has a non-fatal failure. bool TestResult::HasNonfatalFailure() const { return CountIf(test_part_results_, TestPartNonfatallyFailed) > 0; } @@ -2250,25 +2284,25 @@ void ReportFailureInUnknownLocation(TestPartResult::Type result_type, // AddTestPartResult. UnitTest::GetInstance()->AddTestPartResult( result_type, - NULL, // No info about the source file where the exception occurred. - -1, // We have no info on which line caused the exception. + nullptr, // No info about the source file where the exception occurred. + -1, // We have no info on which line caused the exception. message, - ""); // No stack trace, either. + ""); // No stack trace, either. } } // namespace internal -// Google Test requires all tests in the same test case to use the same test +// Google Test requires all tests in the same test suite to use the same test // fixture class. This function checks if the current test has the -// same fixture class as the first test in the current test case. If +// same fixture class as the first test in the current test suite. If // yes, it returns true; otherwise it generates a Google Test failure and // returns false. bool Test::HasSameFixtureClass() { internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); - const TestCase* const test_case = impl->current_test_case(); + const TestSuite* const test_suite = impl->current_test_suite(); - // Info about the first test in the current test case. - const TestInfo* const first_test_info = test_case->test_info_list()[0]; + // Info about the first test in the current test suite. + const TestInfo* const first_test_info = test_suite->test_info_list()[0]; const internal::TypeId first_fixture_id = first_test_info->fixture_class_id_; const char* const first_test_name = first_test_info->name(); @@ -2284,7 +2318,7 @@ bool Test::HasSameFixtureClass() { const bool this_is_TEST = this_fixture_id == internal::GetTestTypeId(); if (first_is_TEST || this_is_TEST) { - // Both TEST and TEST_F appear in same test case, which is incorrect. + // Both TEST and TEST_F appear in same test suite, which is incorrect. // Tell the user how to fix this. // Gets the name of the TEST and the name of the TEST_F. Note @@ -2296,9 +2330,9 @@ bool Test::HasSameFixtureClass() { first_is_TEST ? this_test_name : first_test_name; ADD_FAILURE() - << "All tests in the same test case must use the same test fixture\n" - << "class, so mixing TEST_F and TEST in the same test case is\n" - << "illegal. In test case " << this_test_info->test_case_name() + << "All tests in the same test suite must use the same test fixture\n" + << "class, so mixing TEST_F and TEST in the same test suite is\n" + << "illegal. In test suite " << this_test_info->test_suite_name() << ",\n" << "test " << TEST_F_name << " is defined using TEST_F but\n" << "test " << TEST_name << " is defined using TEST. You probably\n" @@ -2308,15 +2342,15 @@ bool Test::HasSameFixtureClass() { // Two fixture classes with the same name appear in two different // namespaces, which is not allowed. Tell the user how to fix this. ADD_FAILURE() - << "All tests in the same test case must use the same test fixture\n" - << "class. However, in test case " - << this_test_info->test_case_name() << ",\n" - << "you defined test " << first_test_name - << " and test " << this_test_name << "\n" + << "All tests in the same test suite must use the same test fixture\n" + << "class. However, in test suite " + << this_test_info->test_suite_name() << ",\n" + << "you defined test " << first_test_name << " and test " + << this_test_name << "\n" << "using two different test fixture classes. This can happen if\n" << "the two classes are from different namespaces or translation\n" << "units and have the same name. You should probably rename one\n" - << "of the classes to put the tests into different test cases."; + << "of the classes to put the tests into different test suites."; } return false; } @@ -2349,7 +2383,7 @@ namespace internal { static std::string FormatCxxExceptionMessage(const char* description, const char* location) { Message message; - if (description != NULL) { + if (description != nullptr) { message << "C++ exception with description \"" << description << "\""; } else { message << "Unknown C++ exception"; @@ -2433,6 +2467,8 @@ Result HandleExceptionsInMethodIfSupported( #if GTEST_HAS_EXCEPTIONS try { return HandleSehExceptionsInMethodIfSupported(object, method, location); + } catch (const AssertionException&) { // NOLINT + // This failure was reported already. } catch (const internal::GoogleTestFailureException&) { // NOLINT // This exception type can only be thrown by a failed Google // Test assertion with the intention of letting another testing @@ -2445,7 +2481,7 @@ Result HandleExceptionsInMethodIfSupported( } catch (...) { // NOLINT internal::ReportFailureInUnknownLocation( TestPartResult::kFatalFailure, - FormatCxxExceptionMessage(NULL, location)); + FormatCxxExceptionMessage(nullptr, location)); } return static_cast(0); #else @@ -2465,8 +2501,9 @@ void Test::Run() { internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); impl->os_stack_trace_getter()->UponLeavingGTest(); internal::HandleExceptionsInMethodIfSupported(this, &Test::SetUp, "SetUp()"); - // We will run the test only if SetUp() was successful. - if (!HasFatalFailure()) { + // We will run the test only if SetUp() was successful and didn't call + // GTEST_SKIP(). + if (!HasFatalFailure() && !IsSkipped()) { impl->os_stack_trace_getter()->UponLeavingGTest(); internal::HandleExceptionsInMethodIfSupported( this, &Test::TestBody, "the test body"); @@ -2480,32 +2517,36 @@ void Test::Run() { this, &Test::TearDown, "TearDown()"); } -// Returns true iff the current test has a fatal failure. +// Returns true if and only if the current test has a fatal failure. bool Test::HasFatalFailure() { return internal::GetUnitTestImpl()->current_test_result()->HasFatalFailure(); } -// Returns true iff the current test has a non-fatal failure. +// Returns true if and only if the current test has a non-fatal failure. bool Test::HasNonfatalFailure() { return internal::GetUnitTestImpl()->current_test_result()-> HasNonfatalFailure(); } +// Returns true if and only if the current test was skipped. +bool Test::IsSkipped() { + return internal::GetUnitTestImpl()->current_test_result()->Skipped(); +} + // class TestInfo // Constructs a TestInfo object. It assumes ownership of the test factory // object. -TestInfo::TestInfo(const std::string& a_test_case_name, - const std::string& a_name, - const char* a_type_param, +TestInfo::TestInfo(const std::string& a_test_suite_name, + const std::string& a_name, const char* a_type_param, const char* a_value_param, internal::CodeLocation a_code_location, internal::TypeId fixture_class_id, internal::TestFactoryBase* factory) - : test_case_name_(a_test_case_name), + : test_suite_name_(a_test_suite_name), name_(a_name), - type_param_(a_type_param ? new std::string(a_type_param) : NULL), - value_param_(a_value_param ? new std::string(a_value_param) : NULL), + type_param_(a_type_param ? new std::string(a_type_param) : nullptr), + value_param_(a_value_param ? new std::string(a_value_param) : nullptr), location_(a_code_location), fixture_class_id_(fixture_class_id), should_run_(false), @@ -2524,7 +2565,7 @@ namespace internal { // // Arguments: // -// test_case_name: name of the test case +// test_suite_name: name of the test suite // name: name of the test // type_param: the name of the test's type parameter, or NULL if // this is not a typed or a type-parameterized test. @@ -2532,49 +2573,40 @@ namespace internal { // or NULL if this is not a value-parameterized test. // code_location: code location where the test is defined // fixture_class_id: ID of the test fixture class -// set_up_tc: pointer to the function that sets up the test case -// tear_down_tc: pointer to the function that tears down the test case +// set_up_tc: pointer to the function that sets up the test suite +// tear_down_tc: pointer to the function that tears down the test suite // factory: pointer to the factory that creates a test object. // The newly created TestInfo instance will assume // ownership of the factory object. TestInfo* MakeAndRegisterTestInfo( - const char* test_case_name, - const char* name, - const char* type_param, - const char* value_param, - CodeLocation code_location, - TypeId fixture_class_id, - SetUpTestCaseFunc set_up_tc, - TearDownTestCaseFunc tear_down_tc, - TestFactoryBase* factory) { + const char* test_suite_name, const char* name, const char* type_param, + const char* value_param, CodeLocation code_location, + TypeId fixture_class_id, SetUpTestSuiteFunc set_up_tc, + TearDownTestSuiteFunc tear_down_tc, TestFactoryBase* factory) { TestInfo* const test_info = - new TestInfo(test_case_name, name, type_param, value_param, + new TestInfo(test_suite_name, name, type_param, value_param, code_location, fixture_class_id, factory); GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info); return test_info; } -#if GTEST_HAS_PARAM_TEST -void ReportInvalidTestCaseType(const char* test_case_name, - CodeLocation code_location) { +void ReportInvalidTestSuiteType(const char* test_suite_name, + CodeLocation code_location) { Message errors; errors - << "Attempted redefinition of test case " << test_case_name << ".\n" - << "All tests in the same test case must use the same test fixture\n" - << "class. However, in test case " << test_case_name << ", you tried\n" + << "Attempted redefinition of test suite " << test_suite_name << ".\n" + << "All tests in the same test suite must use the same test fixture\n" + << "class. However, in test suite " << test_suite_name << ", you tried\n" << "to define a test using a fixture class different from the one\n" << "used earlier. This can happen if the two fixture classes are\n" << "from different namespaces and have the same name. You should\n" << "probably rename one of the classes to put the tests into different\n" - << "test cases."; + << "test suites."; - fprintf(stderr, "%s %s", - FormatFileLocation(code_location.file.c_str(), - code_location.line).c_str(), - errors.GetString().c_str()); + GTEST_LOG_(ERROR) << FormatFileLocation(code_location.file.c_str(), + code_location.line) + << " " << errors.GetString(); } -#endif // GTEST_HAS_PARAM_TEST - } // namespace internal namespace { @@ -2582,7 +2614,7 @@ namespace { // A predicate that checks the test name of a TestInfo against a known // value. // -// This is used for implementation of the TestCase class only. We put +// This is used for implementation of the TestSuite class only. We put // it in the anonymous namespace to prevent polluting the outer // namespace. // @@ -2595,7 +2627,7 @@ class TestNameIs { explicit TestNameIs(const char* name) : name_(name) {} - // Returns true iff the test name of test_info matches name_. + // Returns true if and only if the test name of test_info matches name_. bool operator()(const TestInfo * test_info) const { return test_info && test_info->name() == name_; } @@ -2609,15 +2641,13 @@ class TestNameIs { namespace internal { // This method expands all parameterized tests registered with macros TEST_P -// and INSTANTIATE_TEST_CASE_P into regular tests and registers those. +// and INSTANTIATE_TEST_SUITE_P into regular tests and registers those. // This will be done just once during the program runtime. void UnitTestImpl::RegisterParameterizedTests() { -#if GTEST_HAS_PARAM_TEST if (!parameterized_tests_registered_) { parameterized_test_registry_.RegisterTests(); parameterized_tests_registered_ = true; } -#endif } } // namespace internal @@ -2645,19 +2675,23 @@ void TestInfo::Run() { factory_, &internal::TestFactoryBase::CreateTest, "the test fixture's constructor"); - // Runs the test only if the test object was created and its - // constructor didn't generate a fatal failure. - if ((test != NULL) && !Test::HasFatalFailure()) { + // Runs the test if the constructor didn't generate a fatal failure or invoke + // GTEST_SKIP(). + // Note that the object will not be null + if (!Test::HasFatalFailure() && !Test::IsSkipped()) { // This doesn't throw as all user code that can throw are wrapped into // exception handling code. test->Run(); } - // Deletes the test object. - impl->os_stack_trace_getter()->UponLeavingGTest(); - internal::HandleExceptionsInMethodIfSupported( - test, &Test::DeleteSelf_, "the test fixture's destructor"); + if (test != nullptr) { + // Deletes the test object. + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + test, &Test::DeleteSelf_, "the test fixture's destructor"); + } + result_.set_start_timestamp(start); result_.set_elapsed_time(internal::GetTimeInMillis() - start); // Notifies the unit test event listener that a test has just finished. @@ -2665,134 +2699,151 @@ void TestInfo::Run() { // Tells UnitTest to stop associating assertion results to this // test. - impl->set_current_test_info(NULL); + impl->set_current_test_info(nullptr); } -// class TestCase +// class TestSuite -// Gets the number of successful tests in this test case. -int TestCase::successful_test_count() const { +// Gets the number of successful tests in this test suite. +int TestSuite::successful_test_count() const { return CountIf(test_info_list_, TestPassed); } -// Gets the number of failed tests in this test case. -int TestCase::failed_test_count() const { +// Gets the number of successful tests in this test suite. +int TestSuite::skipped_test_count() const { + return CountIf(test_info_list_, TestSkipped); +} + +// Gets the number of failed tests in this test suite. +int TestSuite::failed_test_count() const { return CountIf(test_info_list_, TestFailed); } // Gets the number of disabled tests that will be reported in the XML report. -int TestCase::reportable_disabled_test_count() const { +int TestSuite::reportable_disabled_test_count() const { return CountIf(test_info_list_, TestReportableDisabled); } -// Gets the number of disabled tests in this test case. -int TestCase::disabled_test_count() const { +// Gets the number of disabled tests in this test suite. +int TestSuite::disabled_test_count() const { return CountIf(test_info_list_, TestDisabled); } // Gets the number of tests to be printed in the XML report. -int TestCase::reportable_test_count() const { +int TestSuite::reportable_test_count() const { return CountIf(test_info_list_, TestReportable); } -// Get the number of tests in this test case that should run. -int TestCase::test_to_run_count() const { +// Get the number of tests in this test suite that should run. +int TestSuite::test_to_run_count() const { return CountIf(test_info_list_, ShouldRunTest); } // Gets the number of all tests. -int TestCase::total_test_count() const { +int TestSuite::total_test_count() const { return static_cast(test_info_list_.size()); } -// Creates a TestCase with the given name. +// Creates a TestSuite with the given name. // // Arguments: // -// name: name of the test case -// a_type_param: the name of the test case's type parameter, or NULL if -// this is not a typed or a type-parameterized test case. -// set_up_tc: pointer to the function that sets up the test case -// tear_down_tc: pointer to the function that tears down the test case -TestCase::TestCase(const char* a_name, const char* a_type_param, - Test::SetUpTestCaseFunc set_up_tc, - Test::TearDownTestCaseFunc tear_down_tc) +// name: name of the test suite +// a_type_param: the name of the test suite's type parameter, or NULL if +// this is not a typed or a type-parameterized test suite. +// set_up_tc: pointer to the function that sets up the test suite +// tear_down_tc: pointer to the function that tears down the test suite +TestSuite::TestSuite(const char* a_name, const char* a_type_param, + internal::SetUpTestSuiteFunc set_up_tc, + internal::TearDownTestSuiteFunc tear_down_tc) : name_(a_name), - type_param_(a_type_param ? new std::string(a_type_param) : NULL), + type_param_(a_type_param ? new std::string(a_type_param) : nullptr), set_up_tc_(set_up_tc), tear_down_tc_(tear_down_tc), should_run_(false), - elapsed_time_(0) { -} + start_timestamp_(0), + elapsed_time_(0) {} -// Destructor of TestCase. -TestCase::~TestCase() { +// Destructor of TestSuite. +TestSuite::~TestSuite() { // Deletes every Test in the collection. ForEach(test_info_list_, internal::Delete); } // Returns the i-th test among all the tests. i can range from 0 to // total_test_count() - 1. If i is not in that range, returns NULL. -const TestInfo* TestCase::GetTestInfo(int i) const { +const TestInfo* TestSuite::GetTestInfo(int i) const { const int index = GetElementOr(test_indices_, i, -1); - return index < 0 ? NULL : test_info_list_[index]; + return index < 0 ? nullptr : test_info_list_[static_cast(index)]; } // Returns the i-th test among all the tests. i can range from 0 to // total_test_count() - 1. If i is not in that range, returns NULL. -TestInfo* TestCase::GetMutableTestInfo(int i) { +TestInfo* TestSuite::GetMutableTestInfo(int i) { const int index = GetElementOr(test_indices_, i, -1); - return index < 0 ? NULL : test_info_list_[index]; + return index < 0 ? nullptr : test_info_list_[static_cast(index)]; } -// Adds a test to this test case. Will delete the test upon -// destruction of the TestCase object. -void TestCase::AddTestInfo(TestInfo * test_info) { +// Adds a test to this test suite. Will delete the test upon +// destruction of the TestSuite object. +void TestSuite::AddTestInfo(TestInfo* test_info) { test_info_list_.push_back(test_info); test_indices_.push_back(static_cast(test_indices_.size())); } -// Runs every test in this TestCase. -void TestCase::Run() { +// Runs every test in this TestSuite. +void TestSuite::Run() { if (!should_run_) return; internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); - impl->set_current_test_case(this); + impl->set_current_test_suite(this); TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater(); + // Call both legacy and the new API + repeater->OnTestSuiteStart(*this); +// Legacy API is deprecated but still available +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI repeater->OnTestCaseStart(*this); +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI + impl->os_stack_trace_getter()->UponLeavingGTest(); internal::HandleExceptionsInMethodIfSupported( - this, &TestCase::RunSetUpTestCase, "SetUpTestCase()"); + this, &TestSuite::RunSetUpTestSuite, "SetUpTestSuite()"); - const internal::TimeInMillis start = internal::GetTimeInMillis(); + start_timestamp_ = internal::GetTimeInMillis(); for (int i = 0; i < total_test_count(); i++) { GetMutableTestInfo(i)->Run(); } - elapsed_time_ = internal::GetTimeInMillis() - start; + elapsed_time_ = internal::GetTimeInMillis() - start_timestamp_; impl->os_stack_trace_getter()->UponLeavingGTest(); internal::HandleExceptionsInMethodIfSupported( - this, &TestCase::RunTearDownTestCase, "TearDownTestCase()"); + this, &TestSuite::RunTearDownTestSuite, "TearDownTestSuite()"); + // Call both legacy and the new API + repeater->OnTestSuiteEnd(*this); +// Legacy API is deprecated but still available +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI repeater->OnTestCaseEnd(*this); - impl->set_current_test_case(NULL); +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI + + impl->set_current_test_suite(nullptr); } -// Clears the results of all tests in this test case. -void TestCase::ClearResult() { +// Clears the results of all tests in this test suite. +void TestSuite::ClearResult() { ad_hoc_test_result_.Clear(); ForEach(test_info_list_, TestInfo::ClearTestResult); } -// Shuffles the tests in this test case. -void TestCase::ShuffleTests(internal::Random* random) { +// Shuffles the tests in this test suite. +void TestSuite::ShuffleTests(internal::Random* random) { Shuffle(random, &test_indices_); } // Restores the test order to before the first shuffle. -void TestCase::UnshuffleTests() { +void TestSuite::UnshuffleTests() { for (size_t i = 0; i < test_indices_.size(); i++) { test_indices_[i] = static_cast(i); } @@ -2815,9 +2866,9 @@ static std::string FormatTestCount(int test_count) { return FormatCountableNoun(test_count, "test", "tests"); } -// Formats the count of test cases. -static std::string FormatTestCaseCount(int test_case_count) { - return FormatCountableNoun(test_case_count, "test case", "test cases"); +// Formats the count of test suites. +static std::string FormatTestSuiteCount(int test_suite_count) { + return FormatCountableNoun(test_suite_count, "test suite", "test suites"); } // Converts a TestPartResult::Type enum to human-friendly string @@ -2826,6 +2877,8 @@ static std::string FormatTestCaseCount(int test_case_count) { // between the two when viewing the test result. static const char * TestPartResultTypeToString(TestPartResult::Type type) { switch (type) { + case TestPartResult::kSkip: + return "Skipped"; case TestPartResult::kSuccess: return "Success"; @@ -2873,19 +2926,11 @@ static void PrintTestPartResult(const TestPartResult& test_part_result) { } // class PrettyUnitTestResultPrinter - -enum GTestColor { - COLOR_DEFAULT, - COLOR_RED, - COLOR_GREEN, - COLOR_YELLOW -}; - #if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE && \ - !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT + !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT && !GTEST_OS_WINDOWS_MINGW // Returns the character attribute for the given color. -WORD GetColorAttribute(GTestColor color) { +static WORD GetColorAttribute(GTestColor color) { switch (color) { case COLOR_RED: return FOREGROUND_RED; case COLOR_GREEN: return FOREGROUND_GREEN; @@ -2894,27 +2939,59 @@ WORD GetColorAttribute(GTestColor color) { } } +static int GetBitOffset(WORD color_mask) { + if (color_mask == 0) return 0; + + int bitOffset = 0; + while ((color_mask & 1) == 0) { + color_mask >>= 1; + ++bitOffset; + } + return bitOffset; +} + +static WORD GetNewColor(GTestColor color, WORD old_color_attrs) { + // Let's reuse the BG + static const WORD background_mask = BACKGROUND_BLUE | BACKGROUND_GREEN | + BACKGROUND_RED | BACKGROUND_INTENSITY; + static const WORD foreground_mask = FOREGROUND_BLUE | FOREGROUND_GREEN | + FOREGROUND_RED | FOREGROUND_INTENSITY; + const WORD existing_bg = old_color_attrs & background_mask; + + WORD new_color = + GetColorAttribute(color) | existing_bg | FOREGROUND_INTENSITY; + static const int bg_bitOffset = GetBitOffset(background_mask); + static const int fg_bitOffset = GetBitOffset(foreground_mask); + + if (((new_color & background_mask) >> bg_bitOffset) == + ((new_color & foreground_mask) >> fg_bitOffset)) { + new_color ^= FOREGROUND_INTENSITY; // invert intensity + } + return new_color; +} + #else // Returns the ANSI color code for the given color. COLOR_DEFAULT is // an invalid input. -const char* GetAnsiColorCode(GTestColor color) { +static const char* GetAnsiColorCode(GTestColor color) { switch (color) { case COLOR_RED: return "1"; case COLOR_GREEN: return "2"; case COLOR_YELLOW: return "3"; - default: return NULL; - }; + default: + return nullptr; + } } #endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE -// Returns true iff Google Test should use colors in the output. +// Returns true if and only if Google Test should use colors in the output. bool ShouldUseColor(bool stdout_is_tty) { const char* const gtest_color = GTEST_FLAG(color).c_str(); if (String::CaseInsensitiveCStringEquals(gtest_color, "auto")) { -#if GTEST_OS_WINDOWS +#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MINGW // On Windows the TERM variable is usually not set, but the // console there does support colors. return stdout_is_tty; @@ -2950,20 +3027,18 @@ bool ShouldUseColor(bool stdout_is_tty) { // cannot simply emit special characters and have the terminal change colors. // This routine must actually emit the characters rather than return a string // that would be colored when printed, as can be done on Linux. -GTEST_ATTRIBUTE_PRINTF_(2, 3) void ColoredPrintf(GTestColor color, const char* fmt, ...) { va_list args; va_start(args, fmt); -#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS || \ - GTEST_OS_IOS || GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT +#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_ZOS || GTEST_OS_IOS || \ + GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT || defined(ESP_PLATFORM) const bool use_color = AlwaysFalse(); #else static const bool in_color_mode = ShouldUseColor(posix::IsATTY(posix::FileNo(stdout)) != 0); const bool use_color = in_color_mode && (color != COLOR_DEFAULT); -#endif // GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS - // The '!= 0' comparison is necessary to satisfy MSVC 7.1. +#endif // GTEST_OS_WINDOWS_MOBILE || GTEST_OS_ZOS if (!use_color) { vprintf(fmt, args); @@ -2972,20 +3047,21 @@ void ColoredPrintf(GTestColor color, const char* fmt, ...) { } #if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE && \ - !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT + !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT && !GTEST_OS_WINDOWS_MINGW const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE); // Gets the current text color. CONSOLE_SCREEN_BUFFER_INFO buffer_info; GetConsoleScreenBufferInfo(stdout_handle, &buffer_info); const WORD old_color_attrs = buffer_info.wAttributes; + const WORD new_color = GetNewColor(color, old_color_attrs); // We need to flush the stream buffers into the console before each // SetConsoleTextAttribute call lest it affect the text that is already // printed but has not yet reached the console. fflush(stdout); - SetConsoleTextAttribute(stdout_handle, - GetColorAttribute(color) | FOREGROUND_INTENSITY); + SetConsoleTextAttribute(stdout_handle, new_color); + vprintf(fmt, args); fflush(stdout); @@ -2999,23 +3075,22 @@ void ColoredPrintf(GTestColor color, const char* fmt, ...) { va_end(args); } -// Text printed in Google Test's text output and --gunit_list_tests +// Text printed in Google Test's text output and --gtest_list_tests // output to label the type parameter and value parameter for a test. static const char kTypeParamLabel[] = "TypeParam"; static const char kValueParamLabel[] = "GetParam()"; -void PrintFullTestCommentIfPresent(const TestInfo& test_info) { +static void PrintFullTestCommentIfPresent(const TestInfo& test_info) { const char* const type_param = test_info.type_param(); const char* const value_param = test_info.value_param(); - if (type_param != NULL || value_param != NULL) { + if (type_param != nullptr || value_param != nullptr) { printf(", where "); - if (type_param != NULL) { + if (type_param != nullptr) { printf("%s = %s", kTypeParamLabel, type_param); - if (value_param != NULL) - printf(" and "); + if (value_param != nullptr) printf(" and "); } - if (value_param != NULL) { + if (value_param != nullptr) { printf("%s = %s", kValueParamLabel, value_param); } } @@ -3027,27 +3102,39 @@ void PrintFullTestCommentIfPresent(const TestInfo& test_info) { class PrettyUnitTestResultPrinter : public TestEventListener { public: PrettyUnitTestResultPrinter() {} - static void PrintTestName(const char * test_case, const char * test) { - printf("%s.%s", test_case, test); + static void PrintTestName(const char* test_suite, const char* test) { + printf("%s.%s", test_suite, test); } // The following methods override what's in the TestEventListener class. - virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {} - virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration); - virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test); - virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {} - virtual void OnTestCaseStart(const TestCase& test_case); - virtual void OnTestStart(const TestInfo& test_info); - virtual void OnTestPartResult(const TestPartResult& result); - virtual void OnTestEnd(const TestInfo& test_info); - virtual void OnTestCaseEnd(const TestCase& test_case); - virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test); - virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {} - virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); - virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {} + void OnTestProgramStart(const UnitTest& /*unit_test*/) override {} + void OnTestIterationStart(const UnitTest& unit_test, int iteration) override; + void OnEnvironmentsSetUpStart(const UnitTest& unit_test) override; + void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) override {} +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ + void OnTestCaseStart(const TestCase& test_case) override; +#else + void OnTestSuiteStart(const TestSuite& test_suite) override; +#endif // OnTestCaseStart + + void OnTestStart(const TestInfo& test_info) override; + + void OnTestPartResult(const TestPartResult& result) override; + void OnTestEnd(const TestInfo& test_info) override; +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ + void OnTestCaseEnd(const TestCase& test_case) override; +#else + void OnTestSuiteEnd(const TestSuite& test_suite) override; +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ + + void OnEnvironmentsTearDownStart(const UnitTest& unit_test) override; + void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) override {} + void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override; + void OnTestProgramEnd(const UnitTest& /*unit_test*/) override {} private: static void PrintFailedTests(const UnitTest& unit_test); + static void PrintSkippedTests(const UnitTest& unit_test); }; // Fired before each iteration of tests starts. @@ -3082,7 +3169,7 @@ void PrettyUnitTestResultPrinter::OnTestIterationStart( ColoredPrintf(COLOR_GREEN, "[==========] "); printf("Running %s from %s.\n", FormatTestCount(unit_test.test_to_run_count()).c_str(), - FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str()); + FormatTestSuiteCount(unit_test.test_suite_to_run_count()).c_str()); fflush(stdout); } @@ -3093,22 +3180,38 @@ void PrettyUnitTestResultPrinter::OnEnvironmentsSetUpStart( fflush(stdout); } +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ void PrettyUnitTestResultPrinter::OnTestCaseStart(const TestCase& test_case) { const std::string counts = FormatCountableNoun(test_case.test_to_run_count(), "test", "tests"); ColoredPrintf(COLOR_GREEN, "[----------] "); printf("%s from %s", counts.c_str(), test_case.name()); - if (test_case.type_param() == NULL) { + if (test_case.type_param() == nullptr) { printf("\n"); } else { printf(", where %s = %s\n", kTypeParamLabel, test_case.type_param()); } fflush(stdout); } +#else +void PrettyUnitTestResultPrinter::OnTestSuiteStart( + const TestSuite& test_suite) { + const std::string counts = + FormatCountableNoun(test_suite.test_to_run_count(), "test", "tests"); + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("%s from %s", counts.c_str(), test_suite.name()); + if (test_suite.type_param() == nullptr) { + printf("\n"); + } else { + printf(", where %s = %s\n", kTypeParamLabel, test_suite.type_param()); + } + fflush(stdout); +} +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ void PrettyUnitTestResultPrinter::OnTestStart(const TestInfo& test_info) { ColoredPrintf(COLOR_GREEN, "[ RUN ] "); - PrintTestName(test_info.test_case_name(), test_info.name()); + PrintTestName(test_info.test_suite_name(), test_info.name()); printf("\n"); fflush(stdout); } @@ -3116,22 +3219,27 @@ void PrettyUnitTestResultPrinter::OnTestStart(const TestInfo& test_info) { // Called after an assertion failure. void PrettyUnitTestResultPrinter::OnTestPartResult( const TestPartResult& result) { - // If the test part succeeded, we don't need to do anything. - if (result.type() == TestPartResult::kSuccess) - return; - - // Print failure message from the assertion (e.g. expected this and got that). - PrintTestPartResult(result); - fflush(stdout); + switch (result.type()) { + // If the test part succeeded, we don't need to do anything. + case TestPartResult::kSuccess: + return; + default: + // Print failure message from the assertion + // (e.g. expected this and got that). + PrintTestPartResult(result); + fflush(stdout); + } } void PrettyUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) { if (test_info.result()->Passed()) { ColoredPrintf(COLOR_GREEN, "[ OK ] "); + } else if (test_info.result()->Skipped()) { + ColoredPrintf(COLOR_GREEN, "[ SKIPPED ] "); } else { ColoredPrintf(COLOR_RED, "[ FAILED ] "); } - PrintTestName(test_info.test_case_name(), test_info.name()); + PrintTestName(test_info.test_suite_name(), test_info.name()); if (test_info.result()->Failed()) PrintFullTestCommentIfPresent(test_info); @@ -3144,17 +3252,29 @@ void PrettyUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) { fflush(stdout); } +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ void PrettyUnitTestResultPrinter::OnTestCaseEnd(const TestCase& test_case) { if (!GTEST_FLAG(print_time)) return; const std::string counts = FormatCountableNoun(test_case.test_to_run_count(), "test", "tests"); ColoredPrintf(COLOR_GREEN, "[----------] "); - printf("%s from %s (%s ms total)\n\n", - counts.c_str(), test_case.name(), + printf("%s from %s (%s ms total)\n\n", counts.c_str(), test_case.name(), internal::StreamableToString(test_case.elapsed_time()).c_str()); fflush(stdout); } +#else +void PrettyUnitTestResultPrinter::OnTestSuiteEnd(const TestSuite& test_suite) { + if (!GTEST_FLAG(print_time)) return; + + const std::string counts = + FormatCountableNoun(test_suite.test_to_run_count(), "test", "tests"); + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("%s from %s (%s ms total)\n\n", counts.c_str(), test_suite.name(), + internal::StreamableToString(test_suite.elapsed_time()).c_str()); + fflush(stdout); +} +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ void PrettyUnitTestResultPrinter::OnEnvironmentsTearDownStart( const UnitTest& /*unit_test*/) { @@ -3170,30 +3290,54 @@ void PrettyUnitTestResultPrinter::PrintFailedTests(const UnitTest& unit_test) { return; } - for (int i = 0; i < unit_test.total_test_case_count(); ++i) { - const TestCase& test_case = *unit_test.GetTestCase(i); - if (!test_case.should_run() || (test_case.failed_test_count() == 0)) { + for (int i = 0; i < unit_test.total_test_suite_count(); ++i) { + const TestSuite& test_suite = *unit_test.GetTestSuite(i); + if (!test_suite.should_run() || (test_suite.failed_test_count() == 0)) { continue; } - for (int j = 0; j < test_case.total_test_count(); ++j) { - const TestInfo& test_info = *test_case.GetTestInfo(j); - if (!test_info.should_run() || test_info.result()->Passed()) { + for (int j = 0; j < test_suite.total_test_count(); ++j) { + const TestInfo& test_info = *test_suite.GetTestInfo(j); + if (!test_info.should_run() || !test_info.result()->Failed()) { continue; } ColoredPrintf(COLOR_RED, "[ FAILED ] "); - printf("%s.%s", test_case.name(), test_info.name()); + printf("%s.%s", test_suite.name(), test_info.name()); PrintFullTestCommentIfPresent(test_info); printf("\n"); } } } +// Internal helper for printing the list of skipped tests. +void PrettyUnitTestResultPrinter::PrintSkippedTests(const UnitTest& unit_test) { + const int skipped_test_count = unit_test.skipped_test_count(); + if (skipped_test_count == 0) { + return; + } + + for (int i = 0; i < unit_test.total_test_suite_count(); ++i) { + const TestSuite& test_suite = *unit_test.GetTestSuite(i); + if (!test_suite.should_run() || (test_suite.skipped_test_count() == 0)) { + continue; + } + for (int j = 0; j < test_suite.total_test_count(); ++j) { + const TestInfo& test_info = *test_suite.GetTestInfo(j); + if (!test_info.should_run() || !test_info.result()->Skipped()) { + continue; + } + ColoredPrintf(COLOR_GREEN, "[ SKIPPED ] "); + printf("%s.%s", test_suite.name(), test_info.name()); + printf("\n"); + } + } +} + void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, int /*iteration*/) { ColoredPrintf(COLOR_GREEN, "[==========] "); printf("%s from %s ran.", FormatTestCount(unit_test.test_to_run_count()).c_str(), - FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str()); + FormatTestSuiteCount(unit_test.test_suite_to_run_count()).c_str()); if (GTEST_FLAG(print_time)) { printf(" (%s ms total)", internal::StreamableToString(unit_test.elapsed_time()).c_str()); @@ -3202,6 +3346,13 @@ void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, ColoredPrintf(COLOR_GREEN, "[ PASSED ] "); printf("%s.\n", FormatTestCount(unit_test.successful_test_count()).c_str()); + const int skipped_test_count = unit_test.skipped_test_count(); + if (skipped_test_count > 0) { + ColoredPrintf(COLOR_GREEN, "[ SKIPPED ] "); + printf("%s, listed below:\n", FormatTestCount(skipped_test_count).c_str()); + PrintSkippedTests(unit_test); + } + int num_failures = unit_test.failed_test_count(); if (!unit_test.Passed()) { const int failed_test_count = unit_test.failed_test_count(); @@ -3234,7 +3385,7 @@ void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, class TestEventRepeater : public TestEventListener { public: TestEventRepeater() : forwarding_enabled_(true) {} - virtual ~TestEventRepeater(); + ~TestEventRepeater() override; void Append(TestEventListener *listener); TestEventListener* Release(TestEventListener* listener); @@ -3243,19 +3394,27 @@ class TestEventRepeater : public TestEventListener { bool forwarding_enabled() const { return forwarding_enabled_; } void set_forwarding_enabled(bool enable) { forwarding_enabled_ = enable; } - virtual void OnTestProgramStart(const UnitTest& unit_test); - virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration); - virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test); - virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test); - virtual void OnTestCaseStart(const TestCase& test_case); - virtual void OnTestStart(const TestInfo& test_info); - virtual void OnTestPartResult(const TestPartResult& result); - virtual void OnTestEnd(const TestInfo& test_info); - virtual void OnTestCaseEnd(const TestCase& test_case); - virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test); - virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test); - virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); - virtual void OnTestProgramEnd(const UnitTest& unit_test); + void OnTestProgramStart(const UnitTest& unit_test) override; + void OnTestIterationStart(const UnitTest& unit_test, int iteration) override; + void OnEnvironmentsSetUpStart(const UnitTest& unit_test) override; + void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) override; +// Legacy API is deprecated but still available +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ + void OnTestCaseStart(const TestSuite& parameter) override; +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ + void OnTestSuiteStart(const TestSuite& parameter) override; + void OnTestStart(const TestInfo& test_info) override; + void OnTestPartResult(const TestPartResult& result) override; + void OnTestEnd(const TestInfo& test_info) override; +// Legacy API is deprecated but still available +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ + void OnTestCaseEnd(const TestCase& parameter) override; +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ + void OnTestSuiteEnd(const TestSuite& parameter) override; + void OnEnvironmentsTearDownStart(const UnitTest& unit_test) override; + void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) override; + void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override; + void OnTestProgramEnd(const UnitTest& unit_test) override; private: // Controls whether events will be forwarded to listeners_. Set to false @@ -3275,16 +3434,15 @@ void TestEventRepeater::Append(TestEventListener *listener) { listeners_.push_back(listener); } -// TODO(vladl@google.com): Factor the search functionality into Vector::Find. TestEventListener* TestEventRepeater::Release(TestEventListener *listener) { for (size_t i = 0; i < listeners_.size(); ++i) { if (listeners_[i] == listener) { - listeners_.erase(listeners_.begin() + i); + listeners_.erase(listeners_.begin() + static_cast(i)); return listener; } } - return NULL; + return nullptr; } // Since most methods are very similar, use macros to reduce boilerplate. @@ -3299,25 +3457,33 @@ void TestEventRepeater::Name(const Type& parameter) { \ } // This defines a member that forwards the call to all listeners in reverse // order. -#define GTEST_REVERSE_REPEATER_METHOD_(Name, Type) \ -void TestEventRepeater::Name(const Type& parameter) { \ - if (forwarding_enabled_) { \ - for (int i = static_cast(listeners_.size()) - 1; i >= 0; i--) { \ - listeners_[i]->Name(parameter); \ - } \ - } \ -} +#define GTEST_REVERSE_REPEATER_METHOD_(Name, Type) \ + void TestEventRepeater::Name(const Type& parameter) { \ + if (forwarding_enabled_) { \ + for (size_t i = listeners_.size(); i != 0; i--) { \ + listeners_[i - 1]->Name(parameter); \ + } \ + } \ + } GTEST_REPEATER_METHOD_(OnTestProgramStart, UnitTest) GTEST_REPEATER_METHOD_(OnEnvironmentsSetUpStart, UnitTest) -GTEST_REPEATER_METHOD_(OnTestCaseStart, TestCase) +// Legacy API is deprecated but still available +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ +GTEST_REPEATER_METHOD_(OnTestCaseStart, TestSuite) +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ +GTEST_REPEATER_METHOD_(OnTestSuiteStart, TestSuite) GTEST_REPEATER_METHOD_(OnTestStart, TestInfo) GTEST_REPEATER_METHOD_(OnTestPartResult, TestPartResult) GTEST_REPEATER_METHOD_(OnEnvironmentsTearDownStart, UnitTest) GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsSetUpEnd, UnitTest) GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsTearDownEnd, UnitTest) GTEST_REVERSE_REPEATER_METHOD_(OnTestEnd, TestInfo) -GTEST_REVERSE_REPEATER_METHOD_(OnTestCaseEnd, TestCase) +// Legacy API is deprecated but still available +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ +GTEST_REVERSE_REPEATER_METHOD_(OnTestCaseEnd, TestSuite) +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ +GTEST_REVERSE_REPEATER_METHOD_(OnTestSuiteEnd, TestSuite) GTEST_REVERSE_REPEATER_METHOD_(OnTestProgramEnd, UnitTest) #undef GTEST_REPEATER_METHOD_ @@ -3335,8 +3501,8 @@ void TestEventRepeater::OnTestIterationStart(const UnitTest& unit_test, void TestEventRepeater::OnTestIterationEnd(const UnitTest& unit_test, int iteration) { if (forwarding_enabled_) { - for (int i = static_cast(listeners_.size()) - 1; i >= 0; i--) { - listeners_[i]->OnTestIterationEnd(unit_test, iteration); + for (size_t i = listeners_.size(); i > 0; i--) { + listeners_[i - 1]->OnTestIterationEnd(unit_test, iteration); } } } @@ -3348,7 +3514,12 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener { public: explicit XmlUnitTestResultPrinter(const char* output_file); - virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); + void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override; + void ListTestsMatchingFilter(const std::vector& test_suites); + + // Prints an XML summary of all unit tests. + static void PrintXmlTestsList(std::ostream* stream, + const std::vector& test_suites); private: // Is c a whitespace character that is normalized to a space character @@ -3393,12 +3564,12 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener { // Streams an XML representation of a TestInfo object. static void OutputXmlTestInfo(::std::ostream* stream, - const char* test_case_name, + const char* test_suite_name, const TestInfo& test_info); - // Prints an XML representation of a TestCase object - static void PrintXmlTestCase(::std::ostream* stream, - const TestCase& test_case); + // Prints an XML representation of a TestSuite object + static void PrintXmlTestSuite(::std::ostream* stream, + const TestSuite& test_suite); // Prints an XML summary of unit_test to output stream out. static void PrintXmlUnitTest(::std::ostream* stream, @@ -3410,6 +3581,11 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener { // to delimit this attribute from prior attributes. static std::string TestPropertiesAsXmlAttributes(const TestResult& result); + // Streams an XML representation of the test properties of a TestResult + // object. + static void OutputXmlTestProperties(std::ostream* stream, + const TestResult& result); + // The output file. const std::string output_file_; @@ -3419,46 +3595,30 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener { // Creates a new XmlUnitTestResultPrinter. XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file) : output_file_(output_file) { - if (output_file_.c_str() == NULL || output_file_.empty()) { - fprintf(stderr, "XML output file may not be null\n"); - fflush(stderr); - exit(EXIT_FAILURE); + if (output_file_.empty()) { + GTEST_LOG_(FATAL) << "XML output file may not be null"; } } // Called after the unit test ends. void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, int /*iteration*/) { - FILE* xmlout = NULL; - FilePath output_file(output_file_); - FilePath output_dir(output_file.RemoveFileName()); - - if (output_dir.CreateDirectoriesRecursively()) { - xmlout = posix::FOpen(output_file_.c_str(), "w"); - } - if (xmlout == NULL) { - // TODO(wan): report the reason of the failure. - // - // We don't do it for now as: - // - // 1. There is no urgent need for it. - // 2. It's a bit involved to make the errno variable thread-safe on - // all three operating systems (Linux, Windows, and Mac OS). - // 3. To interpret the meaning of errno in a thread-safe way, - // we need the strerror_r() function, which is not available on - // Windows. - fprintf(stderr, - "Unable to open file \"%s\"\n", - output_file_.c_str()); - fflush(stderr); - exit(EXIT_FAILURE); - } + FILE* xmlout = OpenFileForWriting(output_file_); std::stringstream stream; PrintXmlUnitTest(&stream, unit_test); fprintf(xmlout, "%s", StringStreamToString(&stream).c_str()); fclose(xmlout); } +void XmlUnitTestResultPrinter::ListTestsMatchingFilter( + const std::vector& test_suites) { + FILE* xmlout = OpenFileForWriting(output_file_); + std::stringstream stream; + PrintXmlTestsList(&stream, test_suites); + fprintf(xmlout, "%s", StringStreamToString(&stream).c_str()); + fclose(xmlout); +} + // Returns an XML-escaped copy of the input string str. If is_attribute // is true, the text is meant to appear as an attribute value, and // normalizable whitespace is preserved by replacing it with character @@ -3469,8 +3629,6 @@ void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, // module will consist of ordinary English text. // If this module is ever modified to produce version 1.1 XML output, // most invalid characters can be retained using character references. -// TODO(wan): It might be nice to have a minimally invasive, human-readable -// escaping scheme for invalid characters, rather than dropping them. std::string XmlUnitTestResultPrinter::EscapeXml( const std::string& str, bool is_attribute) { Message m; @@ -3530,11 +3688,12 @@ std::string XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters( // The following routines generate an XML representation of a UnitTest // object. +// GOOGLETEST_CM0009 DO NOT DELETE // // This is how Google Test concepts map to the DTD: // // <-- corresponds to a UnitTest object -// <-- corresponds to a TestCase object +// <-- corresponds to a TestSuite object // <-- corresponds to a TestInfo object // ... // ... @@ -3558,12 +3717,11 @@ static bool PortableLocaltime(time_t seconds, struct tm* out) { // MINGW provides neither localtime_r nor localtime_s, but uses // Windows' localtime(), which has a thread-local tm buffer. struct tm* tm_ptr = localtime(&seconds); // NOLINT - if (tm_ptr == NULL) - return false; + if (tm_ptr == nullptr) return false; *out = *tm_ptr; return true; #else - return localtime_r(&seconds, out) != NULL; + return localtime_r(&seconds, out) != nullptr; #endif } @@ -3589,7 +3747,7 @@ void XmlUnitTestResultPrinter::OutputXmlCDataSection(::std::ostream* stream, *stream << ""); - if (next_segment != NULL) { + if (next_segment != nullptr) { stream->write( segment, static_cast(next_segment - segment)); *stream << "]]>]]>& allowed_names = - GetReservedAttributesForElement(element_name); + GetReservedOutputAttributesForElement(element_name); GTEST_CHECK_(std::find(allowed_names.begin(), allowed_names.end(), name) != allowed_names.end()) @@ -3619,30 +3777,47 @@ void XmlUnitTestResultPrinter::OutputXmlAttribute( } // Prints an XML representation of a TestInfo object. -// TODO(wan): There is also value in printing properties with the plain printer. void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream, - const char* test_case_name, + const char* test_suite_name, const TestInfo& test_info) { const TestResult& result = *test_info.result(); - const std::string kTestcase = "testcase"; + const std::string kTestsuite = "testcase"; + + if (test_info.is_in_another_shard()) { + return; + } *stream << " \n"; + return; } - OutputXmlAttribute(stream, kTestcase, "status", + OutputXmlAttribute(stream, kTestsuite, "status", test_info.should_run() ? "run" : "notrun"); - OutputXmlAttribute(stream, kTestcase, "time", + OutputXmlAttribute(stream, kTestsuite, "result", + test_info.should_run() + ? (result.Skipped() ? "skipped" : "completed") + : "suppressed"); + OutputXmlAttribute(stream, kTestsuite, "time", FormatTimeInMillisAsSeconds(result.elapsed_time())); - OutputXmlAttribute(stream, kTestcase, "classname", test_case_name); - *stream << TestPropertiesAsXmlAttributes(result); + OutputXmlAttribute( + stream, kTestsuite, "timestamp", + FormatEpochTimeInMillisAsIso8601(result.start_timestamp())); + OutputXmlAttribute(stream, kTestsuite, "classname", test_suite_name); int failures = 0; for (int i = 0; i < result.total_part_count(); ++i) { @@ -3664,34 +3839,43 @@ void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream, } } - if (failures == 0) + if (failures == 0 && result.test_property_count() == 0) { *stream << " />\n"; - else + } else { + if (failures == 0) { + *stream << ">\n"; + } + OutputXmlTestProperties(stream, result); *stream << " \n"; + } } -// Prints an XML representation of a TestCase object -void XmlUnitTestResultPrinter::PrintXmlTestCase(std::ostream* stream, - const TestCase& test_case) { +// Prints an XML representation of a TestSuite object +void XmlUnitTestResultPrinter::PrintXmlTestSuite(std::ostream* stream, + const TestSuite& test_suite) { const std::string kTestsuite = "testsuite"; *stream << " <" << kTestsuite; - OutputXmlAttribute(stream, kTestsuite, "name", test_case.name()); + OutputXmlAttribute(stream, kTestsuite, "name", test_suite.name()); OutputXmlAttribute(stream, kTestsuite, "tests", - StreamableToString(test_case.reportable_test_count())); - OutputXmlAttribute(stream, kTestsuite, "failures", - StreamableToString(test_case.failed_test_count())); - OutputXmlAttribute( - stream, kTestsuite, "disabled", - StreamableToString(test_case.reportable_disabled_test_count())); - OutputXmlAttribute(stream, kTestsuite, "errors", "0"); - OutputXmlAttribute(stream, kTestsuite, "time", - FormatTimeInMillisAsSeconds(test_case.elapsed_time())); - *stream << TestPropertiesAsXmlAttributes(test_case.ad_hoc_test_result()) - << ">\n"; - - for (int i = 0; i < test_case.total_test_count(); ++i) { - if (test_case.GetTestInfo(i)->is_reportable()) - OutputXmlTestInfo(stream, test_case.name(), *test_case.GetTestInfo(i)); + StreamableToString(test_suite.reportable_test_count())); + if (!GTEST_FLAG(list_tests)) { + OutputXmlAttribute(stream, kTestsuite, "failures", + StreamableToString(test_suite.failed_test_count())); + OutputXmlAttribute( + stream, kTestsuite, "disabled", + StreamableToString(test_suite.reportable_disabled_test_count())); + OutputXmlAttribute(stream, kTestsuite, "errors", "0"); + OutputXmlAttribute(stream, kTestsuite, "time", + FormatTimeInMillisAsSeconds(test_suite.elapsed_time())); + OutputXmlAttribute( + stream, kTestsuite, "timestamp", + FormatEpochTimeInMillisAsIso8601(test_suite.start_timestamp())); + *stream << TestPropertiesAsXmlAttributes(test_suite.ad_hoc_test_result()); + } + *stream << ">\n"; + for (int i = 0; i < test_suite.total_test_count(); ++i) { + if (test_suite.GetTestInfo(i)->is_reportable()) + OutputXmlTestInfo(stream, test_suite.name(), *test_suite.GetTestInfo(i)); } *stream << " \n"; } @@ -3712,25 +3896,46 @@ void XmlUnitTestResultPrinter::PrintXmlUnitTest(std::ostream* stream, stream, kTestsuites, "disabled", StreamableToString(unit_test.reportable_disabled_test_count())); OutputXmlAttribute(stream, kTestsuites, "errors", "0"); + OutputXmlAttribute(stream, kTestsuites, "time", + FormatTimeInMillisAsSeconds(unit_test.elapsed_time())); OutputXmlAttribute( stream, kTestsuites, "timestamp", FormatEpochTimeInMillisAsIso8601(unit_test.start_timestamp())); - OutputXmlAttribute(stream, kTestsuites, "time", - FormatTimeInMillisAsSeconds(unit_test.elapsed_time())); if (GTEST_FLAG(shuffle)) { OutputXmlAttribute(stream, kTestsuites, "random_seed", StreamableToString(unit_test.random_seed())); } - *stream << TestPropertiesAsXmlAttributes(unit_test.ad_hoc_test_result()); OutputXmlAttribute(stream, kTestsuites, "name", "AllTests"); *stream << ">\n"; - for (int i = 0; i < unit_test.total_test_case_count(); ++i) { - if (unit_test.GetTestCase(i)->reportable_test_count() > 0) - PrintXmlTestCase(stream, *unit_test.GetTestCase(i)); + for (int i = 0; i < unit_test.total_test_suite_count(); ++i) { + if (unit_test.GetTestSuite(i)->reportable_test_count() > 0) + PrintXmlTestSuite(stream, *unit_test.GetTestSuite(i)); + } + *stream << "\n"; +} + +void XmlUnitTestResultPrinter::PrintXmlTestsList( + std::ostream* stream, const std::vector& test_suites) { + const std::string kTestsuites = "testsuites"; + + *stream << "\n"; + *stream << "<" << kTestsuites; + + int total_tests = 0; + for (auto test_suite : test_suites) { + total_tests += test_suite->total_test_count(); + } + OutputXmlAttribute(stream, kTestsuites, "tests", + StreamableToString(total_tests)); + OutputXmlAttribute(stream, kTestsuites, "name", "AllTests"); + *stream << ">\n"; + + for (auto test_suite : test_suites) { + PrintXmlTestSuite(stream, *test_suite); } *stream << "\n"; } @@ -3748,8 +3953,403 @@ std::string XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes( return attributes.GetString(); } +void XmlUnitTestResultPrinter::OutputXmlTestProperties( + std::ostream* stream, const TestResult& result) { + const std::string kProperties = "properties"; + const std::string kProperty = "property"; + + if (result.test_property_count() <= 0) { + return; + } + + *stream << "<" << kProperties << ">\n"; + for (int i = 0; i < result.test_property_count(); ++i) { + const TestProperty& property = result.GetTestProperty(i); + *stream << "<" << kProperty; + *stream << " name=\"" << EscapeXmlAttribute(property.key()) << "\""; + *stream << " value=\"" << EscapeXmlAttribute(property.value()) << "\""; + *stream << "/>\n"; + } + *stream << "\n"; +} + // End XmlUnitTestResultPrinter +// This class generates an JSON output file. +class JsonUnitTestResultPrinter : public EmptyTestEventListener { + public: + explicit JsonUnitTestResultPrinter(const char* output_file); + + void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override; + + // Prints an JSON summary of all unit tests. + static void PrintJsonTestList(::std::ostream* stream, + const std::vector& test_suites); + + private: + // Returns an JSON-escaped copy of the input string str. + static std::string EscapeJson(const std::string& str); + + //// Verifies that the given attribute belongs to the given element and + //// streams the attribute as JSON. + static void OutputJsonKey(std::ostream* stream, + const std::string& element_name, + const std::string& name, + const std::string& value, + const std::string& indent, + bool comma = true); + static void OutputJsonKey(std::ostream* stream, + const std::string& element_name, + const std::string& name, + int value, + const std::string& indent, + bool comma = true); + + // Streams a JSON representation of a TestInfo object. + static void OutputJsonTestInfo(::std::ostream* stream, + const char* test_suite_name, + const TestInfo& test_info); + + // Prints a JSON representation of a TestSuite object + static void PrintJsonTestSuite(::std::ostream* stream, + const TestSuite& test_suite); + + // Prints a JSON summary of unit_test to output stream out. + static void PrintJsonUnitTest(::std::ostream* stream, + const UnitTest& unit_test); + + // Produces a string representing the test properties in a result as + // a JSON dictionary. + static std::string TestPropertiesAsJson(const TestResult& result, + const std::string& indent); + + // The output file. + const std::string output_file_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(JsonUnitTestResultPrinter); +}; + +// Creates a new JsonUnitTestResultPrinter. +JsonUnitTestResultPrinter::JsonUnitTestResultPrinter(const char* output_file) + : output_file_(output_file) { + if (output_file_.empty()) { + GTEST_LOG_(FATAL) << "JSON output file may not be null"; + } +} + +void JsonUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, + int /*iteration*/) { + FILE* jsonout = OpenFileForWriting(output_file_); + std::stringstream stream; + PrintJsonUnitTest(&stream, unit_test); + fprintf(jsonout, "%s", StringStreamToString(&stream).c_str()); + fclose(jsonout); +} + +// Returns an JSON-escaped copy of the input string str. +std::string JsonUnitTestResultPrinter::EscapeJson(const std::string& str) { + Message m; + + for (size_t i = 0; i < str.size(); ++i) { + const char ch = str[i]; + switch (ch) { + case '\\': + case '"': + case '/': + m << '\\' << ch; + break; + case '\b': + m << "\\b"; + break; + case '\t': + m << "\\t"; + break; + case '\n': + m << "\\n"; + break; + case '\f': + m << "\\f"; + break; + case '\r': + m << "\\r"; + break; + default: + if (ch < ' ') { + m << "\\u00" << String::FormatByte(static_cast(ch)); + } else { + m << ch; + } + break; + } + } + + return m.GetString(); +} + +// The following routines generate an JSON representation of a UnitTest +// object. + +// Formats the given time in milliseconds as seconds. +static std::string FormatTimeInMillisAsDuration(TimeInMillis ms) { + ::std::stringstream ss; + ss << (static_cast(ms) * 1e-3) << "s"; + return ss.str(); +} + +// Converts the given epoch time in milliseconds to a date string in the +// RFC3339 format, without the timezone information. +static std::string FormatEpochTimeInMillisAsRFC3339(TimeInMillis ms) { + struct tm time_struct; + if (!PortableLocaltime(static_cast(ms / 1000), &time_struct)) + return ""; + // YYYY-MM-DDThh:mm:ss + return StreamableToString(time_struct.tm_year + 1900) + "-" + + String::FormatIntWidth2(time_struct.tm_mon + 1) + "-" + + String::FormatIntWidth2(time_struct.tm_mday) + "T" + + String::FormatIntWidth2(time_struct.tm_hour) + ":" + + String::FormatIntWidth2(time_struct.tm_min) + ":" + + String::FormatIntWidth2(time_struct.tm_sec) + "Z"; +} + +static inline std::string Indent(size_t width) { + return std::string(width, ' '); +} + +void JsonUnitTestResultPrinter::OutputJsonKey( + std::ostream* stream, + const std::string& element_name, + const std::string& name, + const std::string& value, + const std::string& indent, + bool comma) { + const std::vector& allowed_names = + GetReservedOutputAttributesForElement(element_name); + + GTEST_CHECK_(std::find(allowed_names.begin(), allowed_names.end(), name) != + allowed_names.end()) + << "Key \"" << name << "\" is not allowed for value \"" << element_name + << "\"."; + + *stream << indent << "\"" << name << "\": \"" << EscapeJson(value) << "\""; + if (comma) + *stream << ",\n"; +} + +void JsonUnitTestResultPrinter::OutputJsonKey( + std::ostream* stream, + const std::string& element_name, + const std::string& name, + int value, + const std::string& indent, + bool comma) { + const std::vector& allowed_names = + GetReservedOutputAttributesForElement(element_name); + + GTEST_CHECK_(std::find(allowed_names.begin(), allowed_names.end(), name) != + allowed_names.end()) + << "Key \"" << name << "\" is not allowed for value \"" << element_name + << "\"."; + + *stream << indent << "\"" << name << "\": " << StreamableToString(value); + if (comma) + *stream << ",\n"; +} + +// Prints a JSON representation of a TestInfo object. +void JsonUnitTestResultPrinter::OutputJsonTestInfo(::std::ostream* stream, + const char* test_suite_name, + const TestInfo& test_info) { + const TestResult& result = *test_info.result(); + const std::string kTestsuite = "testcase"; + const std::string kIndent = Indent(10); + + *stream << Indent(8) << "{\n"; + OutputJsonKey(stream, kTestsuite, "name", test_info.name(), kIndent); + + if (test_info.value_param() != nullptr) { + OutputJsonKey(stream, kTestsuite, "value_param", test_info.value_param(), + kIndent); + } + if (test_info.type_param() != nullptr) { + OutputJsonKey(stream, kTestsuite, "type_param", test_info.type_param(), + kIndent); + } + if (GTEST_FLAG(list_tests)) { + OutputJsonKey(stream, kTestsuite, "file", test_info.file(), kIndent); + OutputJsonKey(stream, kTestsuite, "line", test_info.line(), kIndent, false); + *stream << "\n" << Indent(8) << "}"; + return; + } + + OutputJsonKey(stream, kTestsuite, "status", + test_info.should_run() ? "RUN" : "NOTRUN", kIndent); + OutputJsonKey(stream, kTestsuite, "result", + test_info.should_run() + ? (result.Skipped() ? "SKIPPED" : "COMPLETED") + : "SUPPRESSED", + kIndent); + OutputJsonKey(stream, kTestsuite, "timestamp", + FormatEpochTimeInMillisAsRFC3339(result.start_timestamp()), + kIndent); + OutputJsonKey(stream, kTestsuite, "time", + FormatTimeInMillisAsDuration(result.elapsed_time()), kIndent); + OutputJsonKey(stream, kTestsuite, "classname", test_suite_name, kIndent, + false); + *stream << TestPropertiesAsJson(result, kIndent); + + int failures = 0; + for (int i = 0; i < result.total_part_count(); ++i) { + const TestPartResult& part = result.GetTestPartResult(i); + if (part.failed()) { + *stream << ",\n"; + if (++failures == 1) { + *stream << kIndent << "\"" << "failures" << "\": [\n"; + } + const std::string location = + internal::FormatCompilerIndependentFileLocation(part.file_name(), + part.line_number()); + const std::string message = EscapeJson(location + "\n" + part.message()); + *stream << kIndent << " {\n" + << kIndent << " \"failure\": \"" << message << "\",\n" + << kIndent << " \"type\": \"\"\n" + << kIndent << " }"; + } + } + + if (failures > 0) + *stream << "\n" << kIndent << "]"; + *stream << "\n" << Indent(8) << "}"; +} + +// Prints an JSON representation of a TestSuite object +void JsonUnitTestResultPrinter::PrintJsonTestSuite( + std::ostream* stream, const TestSuite& test_suite) { + const std::string kTestsuite = "testsuite"; + const std::string kIndent = Indent(6); + + *stream << Indent(4) << "{\n"; + OutputJsonKey(stream, kTestsuite, "name", test_suite.name(), kIndent); + OutputJsonKey(stream, kTestsuite, "tests", test_suite.reportable_test_count(), + kIndent); + if (!GTEST_FLAG(list_tests)) { + OutputJsonKey(stream, kTestsuite, "failures", + test_suite.failed_test_count(), kIndent); + OutputJsonKey(stream, kTestsuite, "disabled", + test_suite.reportable_disabled_test_count(), kIndent); + OutputJsonKey(stream, kTestsuite, "errors", 0, kIndent); + OutputJsonKey( + stream, kTestsuite, "timestamp", + FormatEpochTimeInMillisAsRFC3339(test_suite.start_timestamp()), + kIndent); + OutputJsonKey(stream, kTestsuite, "time", + FormatTimeInMillisAsDuration(test_suite.elapsed_time()), + kIndent, false); + *stream << TestPropertiesAsJson(test_suite.ad_hoc_test_result(), kIndent) + << ",\n"; + } + + *stream << kIndent << "\"" << kTestsuite << "\": [\n"; + + bool comma = false; + for (int i = 0; i < test_suite.total_test_count(); ++i) { + if (test_suite.GetTestInfo(i)->is_reportable()) { + if (comma) { + *stream << ",\n"; + } else { + comma = true; + } + OutputJsonTestInfo(stream, test_suite.name(), *test_suite.GetTestInfo(i)); + } + } + *stream << "\n" << kIndent << "]\n" << Indent(4) << "}"; +} + +// Prints a JSON summary of unit_test to output stream out. +void JsonUnitTestResultPrinter::PrintJsonUnitTest(std::ostream* stream, + const UnitTest& unit_test) { + const std::string kTestsuites = "testsuites"; + const std::string kIndent = Indent(2); + *stream << "{\n"; + + OutputJsonKey(stream, kTestsuites, "tests", unit_test.reportable_test_count(), + kIndent); + OutputJsonKey(stream, kTestsuites, "failures", unit_test.failed_test_count(), + kIndent); + OutputJsonKey(stream, kTestsuites, "disabled", + unit_test.reportable_disabled_test_count(), kIndent); + OutputJsonKey(stream, kTestsuites, "errors", 0, kIndent); + if (GTEST_FLAG(shuffle)) { + OutputJsonKey(stream, kTestsuites, "random_seed", unit_test.random_seed(), + kIndent); + } + OutputJsonKey(stream, kTestsuites, "timestamp", + FormatEpochTimeInMillisAsRFC3339(unit_test.start_timestamp()), + kIndent); + OutputJsonKey(stream, kTestsuites, "time", + FormatTimeInMillisAsDuration(unit_test.elapsed_time()), kIndent, + false); + + *stream << TestPropertiesAsJson(unit_test.ad_hoc_test_result(), kIndent) + << ",\n"; + + OutputJsonKey(stream, kTestsuites, "name", "AllTests", kIndent); + *stream << kIndent << "\"" << kTestsuites << "\": [\n"; + + bool comma = false; + for (int i = 0; i < unit_test.total_test_suite_count(); ++i) { + if (unit_test.GetTestSuite(i)->reportable_test_count() > 0) { + if (comma) { + *stream << ",\n"; + } else { + comma = true; + } + PrintJsonTestSuite(stream, *unit_test.GetTestSuite(i)); + } + } + + *stream << "\n" << kIndent << "]\n" << "}\n"; +} + +void JsonUnitTestResultPrinter::PrintJsonTestList( + std::ostream* stream, const std::vector& test_suites) { + const std::string kTestsuites = "testsuites"; + const std::string kIndent = Indent(2); + *stream << "{\n"; + int total_tests = 0; + for (auto test_suite : test_suites) { + total_tests += test_suite->total_test_count(); + } + OutputJsonKey(stream, kTestsuites, "tests", total_tests, kIndent); + + OutputJsonKey(stream, kTestsuites, "name", "AllTests", kIndent); + *stream << kIndent << "\"" << kTestsuites << "\": [\n"; + + for (size_t i = 0; i < test_suites.size(); ++i) { + if (i != 0) { + *stream << ",\n"; + } + PrintJsonTestSuite(stream, *test_suites[i]); + } + + *stream << "\n" + << kIndent << "]\n" + << "}\n"; +} +// Produces a string representing the test properties in a result as +// a JSON dictionary. +std::string JsonUnitTestResultPrinter::TestPropertiesAsJson( + const TestResult& result, const std::string& indent) { + Message attributes; + for (int i = 0; i < result.test_property_count(); ++i) { + const TestProperty& property = result.GetTestProperty(i); + attributes << ",\n" << indent << "\"" << property.key() << "\": " + << "\"" << EscapeJson(property.value()) << "\""; + } + return attributes.GetString(); +} + +// End JsonUnitTestResultPrinter + #if GTEST_CAN_STREAM_RESULTS_ // Checks if str contains '=', '&', '%' or '\n' characters. If yes, @@ -3784,7 +4384,7 @@ void StreamingListener::SocketWriter::MakeConnection() { memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; // To allow both IPv4 and IPv6 addresses. hints.ai_socktype = SOCK_STREAM; - addrinfo* servinfo = NULL; + addrinfo* servinfo = nullptr; // Use the getaddrinfo() to get a linked list of IP addresses for // the given host name. @@ -3796,7 +4396,7 @@ void StreamingListener::SocketWriter::MakeConnection() { } // Loop through all the results and connect to the first we can. - for (addrinfo* cur_addr = servinfo; sockfd_ == -1 && cur_addr != NULL; + for (addrinfo* cur_addr = servinfo; sockfd_ == -1 && cur_addr != nullptr; cur_addr = cur_addr->ai_next) { sockfd_ = socket( cur_addr->ai_family, cur_addr->ai_socktype, cur_addr->ai_protocol); @@ -3820,47 +4420,82 @@ void StreamingListener::SocketWriter::MakeConnection() { // End of class Streaming Listener #endif // GTEST_CAN_STREAM_RESULTS__ -// Class ScopedTrace +// class OsStackTraceGetter -// Pushes the given source file location and message onto a per-thread -// trace stack maintained by Google Test. -ScopedTrace::ScopedTrace(const char* file, int line, const Message& message) - GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) { - TraceInfo trace; - trace.file = file; - trace.line = line; - trace.message = message.GetString(); +const char* const OsStackTraceGetterInterface::kElidedFramesMarker = + "... " GTEST_NAME_ " internal frames ..."; - UnitTest::GetInstance()->PushGTestTrace(trace); -} +std::string OsStackTraceGetter::CurrentStackTrace(int max_depth, int skip_count) + GTEST_LOCK_EXCLUDED_(mutex_) { +#if GTEST_HAS_ABSL + std::string result; -// Pops the info pushed by the c'tor. -ScopedTrace::~ScopedTrace() - GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) { - UnitTest::GetInstance()->PopGTestTrace(); -} + if (max_depth <= 0) { + return result; + } + max_depth = std::min(max_depth, kMaxStackTraceDepth); -// class OsStackTraceGetter + std::vector raw_stack(max_depth); + // Skips the frames requested by the caller, plus this function. + const int raw_stack_size = + absl::GetStackTrace(&raw_stack[0], max_depth, skip_count + 1); -const char* const OsStackTraceGetterInterface::kElidedFramesMarker = - "... " GTEST_NAME_ " internal frames ..."; + void* caller_frame = nullptr; + { + MutexLock lock(&mutex_); + caller_frame = caller_frame_; + } -std::string OsStackTraceGetter::CurrentStackTrace(int /*max_depth*/, - int /*skip_count*/) { + for (int i = 0; i < raw_stack_size; ++i) { + if (raw_stack[i] == caller_frame && + !GTEST_FLAG(show_internal_stack_frames)) { + // Add a marker to the trace and stop adding frames. + absl::StrAppend(&result, kElidedFramesMarker, "\n"); + break; + } + + char tmp[1024]; + const char* symbol = "(unknown)"; + if (absl::Symbolize(raw_stack[i], tmp, sizeof(tmp))) { + symbol = tmp; + } + + char line[1024]; + snprintf(line, sizeof(line), " %p: %s\n", raw_stack[i], symbol); + result += line; + } + + return result; + +#else // !GTEST_HAS_ABSL + static_cast(max_depth); + static_cast(skip_count); return ""; +#endif // GTEST_HAS_ABSL } -void OsStackTraceGetter::UponLeavingGTest() {} +void OsStackTraceGetter::UponLeavingGTest() GTEST_LOCK_EXCLUDED_(mutex_) { +#if GTEST_HAS_ABSL + void* caller_frame = nullptr; + if (absl::GetStackTrace(&caller_frame, 1, 3) <= 0) { + caller_frame = nullptr; + } + + MutexLock lock(&mutex_); + caller_frame_ = caller_frame; +#endif // GTEST_HAS_ABSL +} // A helper class that creates the premature-exit file in its // constructor and deletes the file in its destructor. class ScopedPrematureExitFile { public: explicit ScopedPrematureExitFile(const char* premature_exit_filepath) - : premature_exit_filepath_(premature_exit_filepath) { + : premature_exit_filepath_(premature_exit_filepath ? + premature_exit_filepath : "") { // If a path to the premature-exit file is specified... - if (premature_exit_filepath != NULL && *premature_exit_filepath != '\0') { + if (!premature_exit_filepath_.empty()) { // create the file with a single "0" character in it. I/O // errors are ignored as there's nothing better we can do and we // don't want to fail the test because of this. @@ -3871,13 +4506,20 @@ class ScopedPrematureExitFile { } ~ScopedPrematureExitFile() { - if (premature_exit_filepath_ != NULL && *premature_exit_filepath_ != '\0') { - remove(premature_exit_filepath_); +#if !defined GTEST_OS_ESP8266 + if (!premature_exit_filepath_.empty()) { + int retval = remove(premature_exit_filepath_.c_str()); + if (retval) { + GTEST_LOG_(ERROR) << "Failed to remove premature exit filepath \"" + << premature_exit_filepath_ << "\" with error " + << retval; + } } +#endif } private: - const char* const premature_exit_filepath_; + const std::string premature_exit_filepath_; GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedPrematureExitFile); }; @@ -3888,9 +4530,8 @@ class ScopedPrematureExitFile { TestEventListeners::TestEventListeners() : repeater_(new internal::TestEventRepeater()), - default_result_printer_(NULL), - default_xml_generator_(NULL) { -} + default_result_printer_(nullptr), + default_xml_generator_(nullptr) {} TestEventListeners::~TestEventListeners() { delete repeater_; } @@ -3907,9 +4548,9 @@ void TestEventListeners::Append(TestEventListener* listener) { // NULL if the listener is not found in the list. TestEventListener* TestEventListeners::Release(TestEventListener* listener) { if (listener == default_result_printer_) - default_result_printer_ = NULL; + default_result_printer_ = nullptr; else if (listener == default_xml_generator_) - default_xml_generator_ = NULL; + default_xml_generator_ = nullptr; return repeater_->Release(listener); } @@ -3928,8 +4569,7 @@ void TestEventListeners::SetDefaultResultPrinter(TestEventListener* listener) { // list. delete Release(default_result_printer_); default_result_printer_ = listener; - if (listener != NULL) - Append(listener); + if (listener != nullptr) Append(listener); } } @@ -3944,8 +4584,7 @@ void TestEventListeners::SetDefaultXmlGenerator(TestEventListener* listener) { // list. delete Release(default_xml_generator_); default_xml_generator_ = listener; - if (listener != NULL) - Append(listener); + if (listener != nullptr) Append(listener); } } @@ -3969,52 +4608,66 @@ void TestEventListeners::SuppressEventForwarding() { // call this before main() starts, from which point on the return // value will never change. UnitTest* UnitTest::GetInstance() { - // When compiled with MSVC 7.1 in optimized mode, destroying the - // UnitTest object upon exiting the program messes up the exit code, - // causing successful tests to appear failed. We have to use a - // different implementation in this case to bypass the compiler bug. - // This implementation makes the compiler happy, at the cost of - // leaking the UnitTest object. - // CodeGear C++Builder insists on a public destructor for the // default implementation. Use this implementation to keep good OO // design with private destructor. -#if (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__) +#if defined(__BORLANDC__) static UnitTest* const instance = new UnitTest; return instance; #else static UnitTest instance; return &instance; -#endif // (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__) +#endif // defined(__BORLANDC__) } -// Gets the number of successful test cases. -int UnitTest::successful_test_case_count() const { - return impl()->successful_test_case_count(); +// Gets the number of successful test suites. +int UnitTest::successful_test_suite_count() const { + return impl()->successful_test_suite_count(); } -// Gets the number of failed test cases. -int UnitTest::failed_test_case_count() const { - return impl()->failed_test_case_count(); +// Gets the number of failed test suites. +int UnitTest::failed_test_suite_count() const { + return impl()->failed_test_suite_count(); } -// Gets the number of all test cases. -int UnitTest::total_test_case_count() const { - return impl()->total_test_case_count(); +// Gets the number of all test suites. +int UnitTest::total_test_suite_count() const { + return impl()->total_test_suite_count(); } -// Gets the number of all test cases that contain at least one test +// Gets the number of all test suites that contain at least one test // that should run. +int UnitTest::test_suite_to_run_count() const { + return impl()->test_suite_to_run_count(); +} + +// Legacy API is deprecated but still available +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ +int UnitTest::successful_test_case_count() const { + return impl()->successful_test_suite_count(); +} +int UnitTest::failed_test_case_count() const { + return impl()->failed_test_suite_count(); +} +int UnitTest::total_test_case_count() const { + return impl()->total_test_suite_count(); +} int UnitTest::test_case_to_run_count() const { - return impl()->test_case_to_run_count(); + return impl()->test_suite_to_run_count(); } +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ // Gets the number of successful tests. int UnitTest::successful_test_count() const { return impl()->successful_test_count(); } +// Gets the number of skipped tests. +int UnitTest::skipped_test_count() const { + return impl()->skipped_test_count(); +} + // Gets the number of failed tests. int UnitTest::failed_test_count() const { return impl()->failed_test_count(); } @@ -4050,29 +4703,37 @@ internal::TimeInMillis UnitTest::elapsed_time() const { return impl()->elapsed_time(); } -// Returns true iff the unit test passed (i.e. all test cases passed). +// Returns true if and only if the unit test passed (i.e. all test suites +// passed). bool UnitTest::Passed() const { return impl()->Passed(); } -// Returns true iff the unit test failed (i.e. some test case failed -// or something outside of all tests failed). +// Returns true if and only if the unit test failed (i.e. some test suite +// failed or something outside of all tests failed). bool UnitTest::Failed() const { return impl()->Failed(); } -// Gets the i-th test case among all the test cases. i can range from 0 to -// total_test_case_count() - 1. If i is not in that range, returns NULL. +// Gets the i-th test suite among all the test suites. i can range from 0 to +// total_test_suite_count() - 1. If i is not in that range, returns NULL. +const TestSuite* UnitTest::GetTestSuite(int i) const { + return impl()->GetTestSuite(i); +} + +// Legacy API is deprecated but still available +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ const TestCase* UnitTest::GetTestCase(int i) const { return impl()->GetTestCase(i); } +#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ // Returns the TestResult containing information on test failures and -// properties logged outside of individual test cases. +// properties logged outside of individual test suites. const TestResult& UnitTest::ad_hoc_test_result() const { return *impl()->ad_hoc_test_result(); } -// Gets the i-th test case among all the test cases. i can range from 0 to -// total_test_case_count() - 1. If i is not in that range, returns NULL. -TestCase* UnitTest::GetMutableTestCase(int i) { - return impl()->GetMutableTestCase(i); +// Gets the i-th test suite among all the test suites. i can range from 0 to +// total_test_suite_count() - 1. If i is not in that range, returns NULL. +TestSuite* UnitTest::GetMutableTestSuite(int i) { + return impl()->GetMutableSuiteCase(i); } // Returns the list of event listeners that can be used to track events @@ -4092,8 +4753,8 @@ TestEventListeners& UnitTest::listeners() { // We don't protect this under mutex_, as we only support calling it // from the main thread. Environment* UnitTest::AddEnvironment(Environment* env) { - if (env == NULL) { - return NULL; + if (env == nullptr) { + return nullptr; } impl_->environments().push_back(env); @@ -4117,25 +4778,24 @@ void UnitTest::AddTestPartResult( if (impl_->gtest_trace_stack().size() > 0) { msg << "\n" << GTEST_NAME_ << " trace:"; - for (int i = static_cast(impl_->gtest_trace_stack().size()); - i > 0; --i) { + for (size_t i = impl_->gtest_trace_stack().size(); i > 0; --i) { const internal::TraceInfo& trace = impl_->gtest_trace_stack()[i - 1]; msg << "\n" << internal::FormatFileLocation(trace.file, trace.line) << " " << trace.message; } } - if (os_stack_trace.c_str() != NULL && !os_stack_trace.empty()) { + if (os_stack_trace.c_str() != nullptr && !os_stack_trace.empty()) { msg << internal::kStackTraceMarker << os_stack_trace; } - const TestPartResult result = - TestPartResult(result_type, file_name, line_number, - msg.GetString().c_str()); + const TestPartResult result = TestPartResult( + result_type, file_name, line_number, msg.GetString().c_str()); impl_->GetTestPartResultReporterForCurrentThread()-> ReportTestPartResult(result); - if (result_type != TestPartResult::kSuccess) { + if (result_type != TestPartResult::kSuccess && + result_type != TestPartResult::kSkip) { // gtest_break_on_failure takes precedence over // gtest_throw_on_failure. This allows a user to set the latter // in the code (perhaps in order to use Google Test assertions @@ -4147,12 +4807,16 @@ void UnitTest::AddTestPartResult( // when a failure happens and both the --gtest_break_on_failure and // the --gtest_catch_exceptions flags are specified. DebugBreak(); +#elif (!defined(__native_client__)) && \ + ((defined(__clang__) || defined(__GNUC__)) && \ + (defined(__x86_64__) || defined(__i386__))) + // with clang/gcc we can achieve the same effect on x86 by invoking int3 + asm("int3"); #else - // Dereference NULL through a volatile pointer to prevent the compiler + // Dereference nullptr through a volatile pointer to prevent the compiler // from removing. We use this rather than abort() or __builtin_trap() for - // portability: Symbian doesn't implement abort() well, and some debuggers - // don't correctly trap abort(). - *static_cast(NULL) = 1; + // portability: some debuggers don't correctly trap abort(). + *static_cast(nullptr) = 1; #endif // GTEST_OS_WINDOWS } else if (GTEST_FLAG(throw_on_failure)) { #if GTEST_HAS_EXCEPTIONS @@ -4167,8 +4831,8 @@ void UnitTest::AddTestPartResult( } // Adds a TestProperty to the current TestResult object when invoked from -// inside a test, to current TestCase's ad_hoc_test_result_ when invoked -// from SetUpTestCase or TearDownTestCase, or to the global property set +// inside a test, to current TestSuite's ad_hoc_test_result_ when invoked +// from SetUpTestSuite or TearDownTestSuite, or to the global property set // when invoked elsewhere. If the result already contains a property with // the same key, the value will be updated. void UnitTest::RecordProperty(const std::string& key, @@ -4207,14 +4871,15 @@ int UnitTest::Run() { // that understands the premature-exit-file protocol to report the // test as having failed. const internal::ScopedPrematureExitFile premature_exit_file( - in_death_test_child_process ? - NULL : internal::posix::GetEnv("TEST_PREMATURE_EXIT_FILE")); + in_death_test_child_process + ? nullptr + : internal::posix::GetEnv("TEST_PREMATURE_EXIT_FILE")); // Captures the value of GTEST_FLAG(catch_exceptions). This value will be // used for the duration of the program. impl()->set_catch_exceptions(GTEST_FLAG(catch_exceptions)); -#if GTEST_HAS_SEH +#if GTEST_OS_WINDOWS // Either the user wants Google Test to catch exceptions thrown by the // tests or this is executing in the context of death test child // process. In either case the user does not want to see pop-up dialogs @@ -4233,25 +4898,29 @@ int UnitTest::Run() { _set_error_mode(_OUT_TO_STDERR); # endif -# if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE +# if defined(_MSC_VER) && !GTEST_OS_WINDOWS_MOBILE // In the debug version, Visual Studio pops up a separate dialog // offering a choice to debug the aborted program. We need to suppress // this dialog or it will pop up for every EXPECT/ASSERT_DEATH statement // executed. Google Test will notify the user of any unexpected // failure via stderr. - // - // VC++ doesn't define _set_abort_behavior() prior to the version 8.0. - // Users of prior VC versions shall suffer the agony and pain of - // clicking through the countless debug dialogs. - // TODO(vladl@google.com): find a way to suppress the abort dialog() in the - // debug mode when compiled with VC 7.1 or lower. if (!GTEST_FLAG(break_on_failure)) _set_abort_behavior( 0x0, // Clear the following flags: _WRITE_ABORT_MSG | _CALL_REPORTFAULT); // pop-up window, core dump. # endif + + // In debug mode, the Windows CRT can crash with an assertion over invalid + // input (e.g. passing an invalid file descriptor). The default handling + // for these assertions is to pop up a dialog and wait for user input. + // Instead ask the CRT to dump such assertions to stderr non-interactively. + if (!IsDebuggerPresent()) { + (void)_CrtSetReportMode(_CRT_ASSERT, + _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); + (void)_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + } } -#endif // GTEST_HAS_SEH +#endif // GTEST_OS_WINDOWS return internal::HandleExceptionsInMethodIfSupported( impl(), @@ -4265,13 +4934,22 @@ const char* UnitTest::original_working_dir() const { return impl_->original_working_dir_.c_str(); } -// Returns the TestCase object for the test that's currently running, +// Returns the TestSuite object for the test that's currently running, // or NULL if no test is running. +const TestSuite* UnitTest::current_test_suite() const + GTEST_LOCK_EXCLUDED_(mutex_) { + internal::MutexLock lock(&mutex_); + return impl_->current_test_suite(); +} + +// Legacy API is still available but deprecated +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ const TestCase* UnitTest::current_test_case() const GTEST_LOCK_EXCLUDED_(mutex_) { internal::MutexLock lock(&mutex_); - return impl_->current_test_case(); + return impl_->current_test_suite(); } +#endif // Returns the TestInfo object for the test that's currently running, // or NULL if no test is running. @@ -4284,15 +4962,12 @@ const TestInfo* UnitTest::current_test_info() const // Returns the random seed used at the start of the current test run. int UnitTest::random_seed() const { return impl_->random_seed(); } -#if GTEST_HAS_PARAM_TEST -// Returns ParameterizedTestCaseRegistry object used to keep track of +// Returns ParameterizedTestSuiteRegistry object used to keep track of // value-parameterized tests and instantiate and register them. -internal::ParameterizedTestCaseRegistry& - UnitTest::parameterized_test_registry() - GTEST_LOCK_EXCLUDED_(mutex_) { +internal::ParameterizedTestSuiteRegistry& +UnitTest::parameterized_test_registry() GTEST_LOCK_EXCLUDED_(mutex_) { return impl_->parameterized_test_registry(); } -#endif // GTEST_HAS_PARAM_TEST // Creates an empty UnitTest. UnitTest::UnitTest() { @@ -4324,25 +4999,22 @@ namespace internal { UnitTestImpl::UnitTestImpl(UnitTest* parent) : parent_(parent), GTEST_DISABLE_MSC_WARNINGS_PUSH_(4355 /* using this in initializer */) - default_global_test_part_result_reporter_(this), + default_global_test_part_result_reporter_(this), default_per_thread_test_part_result_reporter_(this), - GTEST_DISABLE_MSC_WARNINGS_POP_() - global_test_part_result_repoter_( + GTEST_DISABLE_MSC_WARNINGS_POP_() global_test_part_result_repoter_( &default_global_test_part_result_reporter_), per_thread_test_part_result_reporter_( &default_per_thread_test_part_result_reporter_), -#if GTEST_HAS_PARAM_TEST parameterized_test_registry_(), parameterized_tests_registered_(false), -#endif // GTEST_HAS_PARAM_TEST - last_death_test_case_(-1), - current_test_case_(NULL), - current_test_info_(NULL), + last_death_test_suite_(-1), + current_test_suite_(nullptr), + current_test_info_(nullptr), ad_hoc_test_result_(), - os_stack_trace_getter_(NULL), + os_stack_trace_getter_(nullptr), post_flag_parse_init_performed_(false), random_seed_(0), // Will be overridden by the flag before first use. - random_(0), // Will be reseeded before first use. + random_(0), // Will be reseeded before first use. start_timestamp_(0), elapsed_time_(0), #if GTEST_HAS_DEATH_TEST @@ -4354,8 +5026,8 @@ UnitTestImpl::UnitTestImpl(UnitTest* parent) } UnitTestImpl::~UnitTestImpl() { - // Deletes every TestCase. - ForEach(test_cases_, internal::Delete); + // Deletes every TestSuite. + ForEach(test_suites_, internal::Delete); // Deletes every Environment. ForEach(environments_, internal::Delete); @@ -4364,20 +5036,20 @@ UnitTestImpl::~UnitTestImpl() { } // Adds a TestProperty to the current TestResult object when invoked in a -// context of a test, to current test case's ad_hoc_test_result when invoke -// from SetUpTestCase/TearDownTestCase, or to the global property set +// context of a test, to current test suite's ad_hoc_test_result when invoke +// from SetUpTestSuite/TearDownTestSuite, or to the global property set // otherwise. If the result already contains a property with the same key, // the value will be updated. void UnitTestImpl::RecordProperty(const TestProperty& test_property) { std::string xml_element; TestResult* test_result; // TestResult appropriate for property recording. - if (current_test_info_ != NULL) { + if (current_test_info_ != nullptr) { xml_element = "testcase"; test_result = &(current_test_info_->result_); - } else if (current_test_case_ != NULL) { + } else if (current_test_suite_ != nullptr) { xml_element = "testsuite"; - test_result = &(current_test_case_->ad_hoc_test_result_); + test_result = &(current_test_suite_->ad_hoc_test_result_); } else { xml_element = "testsuites"; test_result = &ad_hoc_test_result_; @@ -4389,7 +5061,7 @@ void UnitTestImpl::RecordProperty(const TestProperty& test_property) { // Disables event forwarding if the control is currently in a death test // subprocess. Must not be called before InitGoogleTest. void UnitTestImpl::SuppressTestEventsIfInSubprocess() { - if (internal_run_death_test_flag_.get() != NULL) + if (internal_run_death_test_flag_.get() != nullptr) listeners()->SuppressEventForwarding(); } #endif // GTEST_HAS_DEATH_TEST @@ -4401,10 +5073,12 @@ void UnitTestImpl::ConfigureXmlOutput() { if (output_format == "xml") { listeners()->SetDefaultXmlGenerator(new XmlUnitTestResultPrinter( UnitTestOptions::GetAbsolutePathToOutputFile().c_str())); + } else if (output_format == "json") { + listeners()->SetDefaultXmlGenerator(new JsonUnitTestResultPrinter( + UnitTestOptions::GetAbsolutePathToOutputFile().c_str())); } else if (output_format != "") { - printf("WARNING: unrecognized output format \"%s\" ignored.\n", - output_format.c_str()); - fflush(stdout); + GTEST_LOG_(WARNING) << "WARNING: unrecognized output format \"" + << output_format << "\" ignored."; } } @@ -4419,9 +5093,8 @@ void UnitTestImpl::ConfigureStreamingOutput() { listeners()->Append(new StreamingListener(target.substr(0, pos), target.substr(pos+1))); } else { - printf("WARNING: unrecognized streaming target \"%s\" ignored.\n", - target.c_str()); - fflush(stdout); + GTEST_LOG_(WARNING) << "unrecognized streaming target \"" << target + << "\" ignored."; } } } @@ -4460,77 +5133,83 @@ void UnitTestImpl::PostFlagParsingInit() { // Configures listeners for streaming test results to the specified server. ConfigureStreamingOutput(); #endif // GTEST_CAN_STREAM_RESULTS_ + +#if GTEST_HAS_ABSL + if (GTEST_FLAG(install_failure_signal_handler)) { + absl::FailureSignalHandlerOptions options; + absl::InstallFailureSignalHandler(options); + } +#endif // GTEST_HAS_ABSL } } -// A predicate that checks the name of a TestCase against a known +// A predicate that checks the name of a TestSuite against a known // value. // // This is used for implementation of the UnitTest class only. We put // it in the anonymous namespace to prevent polluting the outer // namespace. // -// TestCaseNameIs is copyable. -class TestCaseNameIs { +// TestSuiteNameIs is copyable. +class TestSuiteNameIs { public: // Constructor. - explicit TestCaseNameIs(const std::string& name) - : name_(name) {} + explicit TestSuiteNameIs(const std::string& name) : name_(name) {} - // Returns true iff the name of test_case matches name_. - bool operator()(const TestCase* test_case) const { - return test_case != NULL && strcmp(test_case->name(), name_.c_str()) == 0; + // Returns true if and only if the name of test_suite matches name_. + bool operator()(const TestSuite* test_suite) const { + return test_suite != nullptr && + strcmp(test_suite->name(), name_.c_str()) == 0; } private: std::string name_; }; -// Finds and returns a TestCase with the given name. If one doesn't +// Finds and returns a TestSuite with the given name. If one doesn't // exist, creates one and returns it. It's the CALLER'S // RESPONSIBILITY to ensure that this function is only called WHEN THE // TESTS ARE NOT SHUFFLED. // // Arguments: // -// test_case_name: name of the test case -// type_param: the name of the test case's type parameter, or NULL if -// this is not a typed or a type-parameterized test case. -// set_up_tc: pointer to the function that sets up the test case -// tear_down_tc: pointer to the function that tears down the test case -TestCase* UnitTestImpl::GetTestCase(const char* test_case_name, - const char* type_param, - Test::SetUpTestCaseFunc set_up_tc, - Test::TearDownTestCaseFunc tear_down_tc) { - // Can we find a TestCase with the given name? - const std::vector::const_iterator test_case = - std::find_if(test_cases_.begin(), test_cases_.end(), - TestCaseNameIs(test_case_name)); - - if (test_case != test_cases_.end()) - return *test_case; +// test_suite_name: name of the test suite +// type_param: the name of the test suite's type parameter, or NULL if +// this is not a typed or a type-parameterized test suite. +// set_up_tc: pointer to the function that sets up the test suite +// tear_down_tc: pointer to the function that tears down the test suite +TestSuite* UnitTestImpl::GetTestSuite( + const char* test_suite_name, const char* type_param, + internal::SetUpTestSuiteFunc set_up_tc, + internal::TearDownTestSuiteFunc tear_down_tc) { + // Can we find a TestSuite with the given name? + const auto test_suite = + std::find_if(test_suites_.rbegin(), test_suites_.rend(), + TestSuiteNameIs(test_suite_name)); + + if (test_suite != test_suites_.rend()) return *test_suite; // No. Let's create one. - TestCase* const new_test_case = - new TestCase(test_case_name, type_param, set_up_tc, tear_down_tc); - - // Is this a death test case? - if (internal::UnitTestOptions::MatchesFilter(test_case_name, - kDeathTestCaseFilter)) { - // Yes. Inserts the test case after the last death test case - // defined so far. This only works when the test cases haven't + auto* const new_test_suite = + new TestSuite(test_suite_name, type_param, set_up_tc, tear_down_tc); + + // Is this a death test suite? + if (internal::UnitTestOptions::MatchesFilter(test_suite_name, + kDeathTestSuiteFilter)) { + // Yes. Inserts the test suite after the last death test suite + // defined so far. This only works when the test suites haven't // been shuffled. Otherwise we may end up running a death test // after a non-death test. - ++last_death_test_case_; - test_cases_.insert(test_cases_.begin() + last_death_test_case_, - new_test_case); + ++last_death_test_suite_; + test_suites_.insert(test_suites_.begin() + last_death_test_suite_, + new_test_suite); } else { // No. Appends to the end of the list. - test_cases_.push_back(new_test_case); + test_suites_.push_back(new_test_suite); } - test_case_indices_.push_back(static_cast(test_case_indices_.size())); - return new_test_case; + test_suite_indices_.push_back(static_cast(test_suite_indices_.size())); + return new_test_suite; } // Helpers for setting up / tearing down the given environment. They @@ -4548,13 +5227,9 @@ static void TearDownEnvironment(Environment* env) { env->TearDown(); } // All other functions called from RunAllTests() may safely assume that // parameterized tests are ready to be counted and run. bool UnitTestImpl::RunAllTests() { - // Makes sure InitGoogleTest() was called. - if (!GTestIsInitialized()) { - printf("%s", - "\nThis test program did NOT call ::testing::InitGoogleTest " - "before calling RUN_ALL_TESTS(). Please fix it.\n"); - return false; - } + // True if and only if Google Test is initialized before RUN_ALL_TESTS() is + // called. + const bool gtest_is_initialized_before_run_all_tests = GTestIsInitialized(); // Do not run any test if the --help flag was specified. if (g_help_flag) @@ -4569,12 +5244,13 @@ bool UnitTestImpl::RunAllTests() { // protocol. internal::WriteToShardStatusFileIfNeeded(); - // True iff we are in a subprocess for running a thread-safe-style + // True if and only if we are in a subprocess for running a thread-safe-style // death test. bool in_subprocess_for_death_test = false; #if GTEST_HAS_DEATH_TEST - in_subprocess_for_death_test = (internal_run_death_test_flag_.get() != NULL); + in_subprocess_for_death_test = + (internal_run_death_test_flag_.get() != nullptr); # if defined(GTEST_EXTRA_DEATH_TEST_CHILD_SETUP_) if (in_subprocess_for_death_test) { GTEST_EXTRA_DEATH_TEST_CHILD_SETUP_(); @@ -4601,7 +5277,7 @@ bool UnitTestImpl::RunAllTests() { random_seed_ = GTEST_FLAG(shuffle) ? GetRandomSeedFromFlag(GTEST_FLAG(random_seed)) : 0; - // True iff at least one test has failed. + // True if and only if at least one test has failed. bool failed = false; TestEventListener* repeater = listeners()->repeater(); @@ -4613,17 +5289,17 @@ bool UnitTestImpl::RunAllTests() { // when we are inside the subprocess of a death test. const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG(repeat); // Repeats forever if the repeat count is negative. - const bool forever = repeat < 0; - for (int i = 0; forever || i != repeat; i++) { + const bool gtest_repeat_forever = repeat < 0; + for (int i = 0; gtest_repeat_forever || i != repeat; i++) { // We want to preserve failures generated by ad-hoc test // assertions executed before RUN_ALL_TESTS(). ClearNonAdHocTestResult(); const TimeInMillis start = GetTimeInMillis(); - // Shuffles test cases and tests if requested. + // Shuffles test suites and tests if requested. if (has_tests_to_run && GTEST_FLAG(shuffle)) { - random()->Reseed(random_seed_); + random()->Reseed(static_cast(random_seed_)); // This should be done before calling OnTestIterationStart(), // such that a test event listener can see the actual test order // in the event. @@ -4633,19 +5309,33 @@ bool UnitTestImpl::RunAllTests() { // Tells the unit test event listeners that the tests are about to start. repeater->OnTestIterationStart(*parent_, i); - // Runs each test case if there is at least one test to run. + // Runs each test suite if there is at least one test to run. if (has_tests_to_run) { // Sets up all environments beforehand. repeater->OnEnvironmentsSetUpStart(*parent_); ForEach(environments_, SetUpEnvironment); repeater->OnEnvironmentsSetUpEnd(*parent_); - // Runs the tests only if there was no fatal failure during global - // set-up. - if (!Test::HasFatalFailure()) { - for (int test_index = 0; test_index < total_test_case_count(); + // Runs the tests only if there was no fatal failure or skip triggered + // during global set-up. + if (Test::IsSkipped()) { + // Emit diagnostics when global set-up calls skip, as it will not be + // emitted by default. + TestResult& test_result = + *internal::GetUnitTestImpl()->current_test_result(); + for (int j = 0; j < test_result.total_part_count(); ++j) { + const TestPartResult& test_part_result = + test_result.GetTestPartResult(j); + if (test_part_result.type() == TestPartResult::kSkip) { + const std::string& result = test_part_result.message(); + printf("%s\n", result.c_str()); + } + } + fflush(stdout); + } else if (!Test::HasFatalFailure()) { + for (int test_index = 0; test_index < total_test_suite_count(); test_index++) { - GetMutableTestCase(test_index)->Run(); + GetMutableSuiteCase(test_index)->Run(); } } @@ -4682,6 +5372,20 @@ bool UnitTestImpl::RunAllTests() { repeater->OnTestProgramEnd(*parent_); + if (!gtest_is_initialized_before_run_all_tests) { + ColoredPrintf( + COLOR_RED, + "\nIMPORTANT NOTICE - DO NOT IGNORE:\n" + "This test program did NOT call " GTEST_INIT_GOOGLE_TEST_NAME_ + "() before calling RUN_ALL_TESTS(). This is INVALID. Soon " GTEST_NAME_ + " will start to enforce the valid usage. " + "Please fix it ASAP, or IT WILL START TO FAIL.\n"); // NOLINT +#if GTEST_FOR_GOOGLE_ + ColoredPrintf(COLOR_RED, + "For more details, see http://wiki/Main/ValidGUnitMain.\n"); +#endif // GTEST_FOR_GOOGLE_ + } + return !failed; } @@ -4691,9 +5395,9 @@ bool UnitTestImpl::RunAllTests() { // be created, prints an error and exits. void WriteToShardStatusFileIfNeeded() { const char* const test_shard_file = posix::GetEnv(kTestShardStatusFile); - if (test_shard_file != NULL) { + if (test_shard_file != nullptr) { FILE* const file = posix::FOpen(test_shard_file, "w"); - if (file == NULL) { + if (file == nullptr) { ColoredPrintf(COLOR_RED, "Could not write to the test shard status file \"%s\" " "specified by the %s environment variable.\n", @@ -4758,7 +5462,7 @@ bool ShouldShard(const char* total_shards_env, // and aborts. Int32 Int32FromEnvOrDie(const char* var, Int32 default_val) { const char* str_val = posix::GetEnv(var); - if (str_val == NULL) { + if (str_val == nullptr) { return default_val; } @@ -4771,8 +5475,8 @@ Int32 Int32FromEnvOrDie(const char* var, Int32 default_val) { } // Given the total number of shards, the shard index, and the test id, -// returns true iff the test should be run on this shard. The test id is -// some arbitrary but unique non-negative integer assigned to each test +// returns true if and only if the test should be run on this shard. The test id +// is some arbitrary but unique non-negative integer assigned to each test // method. Assumes that 0 <= shard_index < total_shards. bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id) { return (test_id % total_shards) == shard_index; @@ -4780,11 +5484,11 @@ bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id) { // Compares the name of each test with the user-specified filter to // decide whether the test should be run, then records the result in -// each TestCase and TestInfo object. +// each TestSuite and TestInfo object. // If shard_tests == true, further filters tests based on sharding // variables in the environment - see -// http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide. -// Returns the number of tests that should run. +// https://github.com/google/googletest/blob/master/googletest/docs/advanced.md +// . Returns the number of tests that should run. int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) { const Int32 total_shards = shard_tests == HONOR_SHARDING_PROTOCOL ? Int32FromEnvOrDie(kTestTotalShards, -1) : -1; @@ -4797,42 +5501,40 @@ int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) { // this shard. int num_runnable_tests = 0; int num_selected_tests = 0; - for (size_t i = 0; i < test_cases_.size(); i++) { - TestCase* const test_case = test_cases_[i]; - const std::string &test_case_name = test_case->name(); - test_case->set_should_run(false); + for (auto* test_suite : test_suites_) { + const std::string& test_suite_name = test_suite->name(); + test_suite->set_should_run(false); - for (size_t j = 0; j < test_case->test_info_list().size(); j++) { - TestInfo* const test_info = test_case->test_info_list()[j]; + for (size_t j = 0; j < test_suite->test_info_list().size(); j++) { + TestInfo* const test_info = test_suite->test_info_list()[j]; const std::string test_name(test_info->name()); - // A test is disabled if test case name or test name matches + // A test is disabled if test suite name or test name matches // kDisableTestFilter. - const bool is_disabled = - internal::UnitTestOptions::MatchesFilter(test_case_name, - kDisableTestFilter) || - internal::UnitTestOptions::MatchesFilter(test_name, - kDisableTestFilter); + const bool is_disabled = internal::UnitTestOptions::MatchesFilter( + test_suite_name, kDisableTestFilter) || + internal::UnitTestOptions::MatchesFilter( + test_name, kDisableTestFilter); test_info->is_disabled_ = is_disabled; - const bool matches_filter = - internal::UnitTestOptions::FilterMatchesTest(test_case_name, - test_name); + const bool matches_filter = internal::UnitTestOptions::FilterMatchesTest( + test_suite_name, test_name); test_info->matches_filter_ = matches_filter; const bool is_runnable = (GTEST_FLAG(also_run_disabled_tests) || !is_disabled) && matches_filter; - const bool is_selected = is_runnable && - (shard_tests == IGNORE_SHARDING_PROTOCOL || - ShouldRunTestOnShard(total_shards, shard_index, - num_runnable_tests)); + const bool is_in_another_shard = + shard_tests != IGNORE_SHARDING_PROTOCOL && + !ShouldRunTestOnShard(total_shards, shard_index, num_runnable_tests); + test_info->is_in_another_shard_ = is_in_another_shard; + const bool is_selected = is_runnable && !is_in_another_shard; num_runnable_tests += is_runnable; num_selected_tests += is_selected; test_info->should_run_ = is_selected; - test_case->set_should_run(test_case->should_run() || is_selected); + test_suite->set_should_run(test_suite->should_run() || is_selected); } } return num_selected_tests; @@ -4843,7 +5545,7 @@ int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) { // max_length characters, only prints the first max_length characters // and "...". static void PrintOnOneLine(const char* str, int max_length) { - if (str != NULL) { + if (str != nullptr) { for (int i = 0; *str != '\0'; ++str) { if (i >= max_length) { printf("..."); @@ -4865,27 +5567,25 @@ void UnitTestImpl::ListTestsMatchingFilter() { // Print at most this many characters for each type/value parameter. const int kMaxParamLength = 250; - for (size_t i = 0; i < test_cases_.size(); i++) { - const TestCase* const test_case = test_cases_[i]; - bool printed_test_case_name = false; + for (auto* test_suite : test_suites_) { + bool printed_test_suite_name = false; - for (size_t j = 0; j < test_case->test_info_list().size(); j++) { - const TestInfo* const test_info = - test_case->test_info_list()[j]; + for (size_t j = 0; j < test_suite->test_info_list().size(); j++) { + const TestInfo* const test_info = test_suite->test_info_list()[j]; if (test_info->matches_filter_) { - if (!printed_test_case_name) { - printed_test_case_name = true; - printf("%s.", test_case->name()); - if (test_case->type_param() != NULL) { + if (!printed_test_suite_name) { + printed_test_suite_name = true; + printf("%s.", test_suite->name()); + if (test_suite->type_param() != nullptr) { printf(" # %s = ", kTypeParamLabel); // We print the type parameter on a single line to make // the output easy to parse by a program. - PrintOnOneLine(test_case->type_param(), kMaxParamLength); + PrintOnOneLine(test_suite->type_param(), kMaxParamLength); } printf("\n"); } printf(" %s", test_info->name()); - if (test_info->value_param() != NULL) { + if (test_info->value_param() != nullptr) { printf(" # %s = ", kValueParamLabel); // We print the value parameter on a single line to make the // output easy to parse by a program. @@ -4896,6 +5596,23 @@ void UnitTestImpl::ListTestsMatchingFilter() { } } fflush(stdout); + const std::string& output_format = UnitTestOptions::GetOutputFormat(); + if (output_format == "xml" || output_format == "json") { + FILE* fileout = OpenFileForWriting( + UnitTestOptions::GetAbsolutePathToOutputFile().c_str()); + std::stringstream stream; + if (output_format == "xml") { + XmlUnitTestResultPrinter( + UnitTestOptions::GetAbsolutePathToOutputFile().c_str()) + .PrintXmlTestsList(&stream, test_suites_); + } else if (output_format == "json") { + JsonUnitTestResultPrinter( + UnitTestOptions::GetAbsolutePathToOutputFile().c_str()) + .PrintJsonTestList(&stream, test_suites_); + } + fprintf(fileout, "%s", StringStreamToString(&stream).c_str()); + fclose(fileout); + } } // Sets the OS stack trace getter. @@ -4915,7 +5632,7 @@ void UnitTestImpl::set_os_stack_trace_getter( // otherwise, creates an OsStackTraceGetter, makes it the current // getter, and returns it. OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() { - if (os_stack_trace_getter_ == NULL) { + if (os_stack_trace_getter_ == nullptr) { #ifdef GTEST_OS_STACK_TRACE_GETTER_ os_stack_trace_getter_ = new GTEST_OS_STACK_TRACE_GETTER_; #else @@ -4926,36 +5643,40 @@ OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() { return os_stack_trace_getter_; } -// Returns the TestResult for the test that's currently running, or -// the TestResult for the ad hoc test if no test is running. +// Returns the most specific TestResult currently running. TestResult* UnitTestImpl::current_test_result() { - return current_test_info_ ? - &(current_test_info_->result_) : &ad_hoc_test_result_; + if (current_test_info_ != nullptr) { + return ¤t_test_info_->result_; + } + if (current_test_suite_ != nullptr) { + return ¤t_test_suite_->ad_hoc_test_result_; + } + return &ad_hoc_test_result_; } -// Shuffles all test cases, and the tests within each test case, +// Shuffles all test suites, and the tests within each test suite, // making sure that death tests are still run first. void UnitTestImpl::ShuffleTests() { - // Shuffles the death test cases. - ShuffleRange(random(), 0, last_death_test_case_ + 1, &test_case_indices_); + // Shuffles the death test suites. + ShuffleRange(random(), 0, last_death_test_suite_ + 1, &test_suite_indices_); - // Shuffles the non-death test cases. - ShuffleRange(random(), last_death_test_case_ + 1, - static_cast(test_cases_.size()), &test_case_indices_); + // Shuffles the non-death test suites. + ShuffleRange(random(), last_death_test_suite_ + 1, + static_cast(test_suites_.size()), &test_suite_indices_); - // Shuffles the tests inside each test case. - for (size_t i = 0; i < test_cases_.size(); i++) { - test_cases_[i]->ShuffleTests(random()); + // Shuffles the tests inside each test suite. + for (auto& test_suite : test_suites_) { + test_suite->ShuffleTests(random()); } } -// Restores the test cases and tests to their order before the first shuffle. +// Restores the test suites and tests to their order before the first shuffle. void UnitTestImpl::UnshuffleTests() { - for (size_t i = 0; i < test_cases_.size(); i++) { - // Unshuffles the tests in each test case. - test_cases_[i]->UnshuffleTests(); - // Resets the index of each test case. - test_case_indices_[i] = static_cast(i); + for (size_t i = 0; i < test_suites_.size(); i++) { + // Unshuffles the tests in each test suite. + test_suites_[i]->UnshuffleTests(); + // Resets the index of each test suite. + test_suite_indices_[i] = static_cast(i); } } @@ -5011,16 +5732,15 @@ bool SkipPrefix(const char* prefix, const char** pstr) { // part can be omitted. // // Returns the value of the flag, or NULL if the parsing failed. -const char* ParseFlagValue(const char* str, - const char* flag, - bool def_optional) { +static const char* ParseFlagValue(const char* str, const char* flag, + bool def_optional) { // str and flag must not be NULL. - if (str == NULL || flag == NULL) return NULL; + if (str == nullptr || flag == nullptr) return nullptr; // The flag must start with "--" followed by GTEST_FLAG_PREFIX_. const std::string flag_str = std::string("--") + GTEST_FLAG_PREFIX_ + flag; const size_t flag_len = flag_str.length(); - if (strncmp(str, flag_str.c_str(), flag_len) != 0) return NULL; + if (strncmp(str, flag_str.c_str(), flag_len) != 0) return nullptr; // Skips the flag name. const char* flag_end = str + flag_len; @@ -5033,7 +5753,7 @@ const char* ParseFlagValue(const char* str, // If def_optional is true and there are more characters after the // flag name, or if def_optional is false, there must be a '=' after // the flag name. - if (flag_end[0] != '=') return NULL; + if (flag_end[0] != '=') return nullptr; // Returns the string after "=". return flag_end + 1; @@ -5049,12 +5769,12 @@ const char* ParseFlagValue(const char* str, // // On success, stores the value of the flag in *value, and returns // true. On failure, returns false without changing *value. -bool ParseBoolFlag(const char* str, const char* flag, bool* value) { +static bool ParseBoolFlag(const char* str, const char* flag, bool* value) { // Gets the value of the flag as a string. const char* const value_str = ParseFlagValue(str, flag, true); // Aborts if the parsing failed. - if (value_str == NULL) return false; + if (value_str == nullptr) return false; // Converts the string value to a bool. *value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F'); @@ -5071,7 +5791,7 @@ bool ParseInt32Flag(const char* str, const char* flag, Int32* value) { const char* const value_str = ParseFlagValue(str, flag, false); // Aborts if the parsing failed. - if (value_str == NULL) return false; + if (value_str == nullptr) return false; // Sets *value to the value of the flag. return ParseInt32(Message() << "The value of flag --" << flag, @@ -5083,12 +5803,13 @@ bool ParseInt32Flag(const char* str, const char* flag, Int32* value) { // // On success, stores the value of the flag in *value, and returns // true. On failure, returns false without changing *value. -bool ParseStringFlag(const char* str, const char* flag, std::string* value) { +template +static bool ParseStringFlag(const char* str, const char* flag, String* value) { // Gets the value of the flag as a string. const char* const value_str = ParseFlagValue(str, flag, false); // Aborts if the parsing failed. - if (value_str == NULL) return false; + if (value_str == nullptr) return false; // Sets *value to the value of the flag. *value = value_str; @@ -5119,8 +5840,6 @@ static bool HasGoogleTestFlagPrefix(const char* str) { // @Y changes the color to yellow. // @D changes to the default terminal text color. // -// TODO(wan@google.com): Write tests for this once we add stdout -// capturing to Google Test. static void PrintColorEncoded(const char* str) { GTestColor color = COLOR_DEFAULT; // The current color. @@ -5130,7 +5849,7 @@ static void PrintColorEncoded(const char* str) { // next segment. for (;;) { const char* p = strchr(str, '@'); - if (p == NULL) { + if (p == nullptr) { ColoredPrintf(color, "%s", str); return; } @@ -5185,24 +5904,25 @@ static const char kColorEncodedHelpMessage[] = " Enable/disable colored output. The default is @Gauto@D.\n" " -@G-" GTEST_FLAG_PREFIX_ "print_time=0@D\n" " Don't print the elapsed time of each test.\n" -" @G--" GTEST_FLAG_PREFIX_ "output=xml@Y[@G:@YDIRECTORY_PATH@G" +" @G--" GTEST_FLAG_PREFIX_ "output=@Y(@Gjson@Y|@Gxml@Y)[@G:@YDIRECTORY_PATH@G" GTEST_PATH_SEP_ "@Y|@G:@YFILE_PATH]@D\n" -" Generate an XML report in the given directory or with the given file\n" -" name. @YFILE_PATH@D defaults to @Gtest_details.xml@D.\n" -#if GTEST_CAN_STREAM_RESULTS_ +" Generate a JSON or XML report in the given directory or with the given\n" +" file name. @YFILE_PATH@D defaults to @Gtest_detail.xml@D.\n" +# if GTEST_CAN_STREAM_RESULTS_ " @G--" GTEST_FLAG_PREFIX_ "stream_result_to=@YHOST@G:@YPORT@D\n" " Stream test results to the given server.\n" -#endif // GTEST_CAN_STREAM_RESULTS_ +# endif // GTEST_CAN_STREAM_RESULTS_ "\n" "Assertion Behavior:\n" -#if GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS +# if GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS " @G--" GTEST_FLAG_PREFIX_ "death_test_style=@Y(@Gfast@Y|@Gthreadsafe@Y)@D\n" " Set the default death test style.\n" -#endif // GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS +# endif // GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS " @G--" GTEST_FLAG_PREFIX_ "break_on_failure@D\n" " Turn assertion failures into debugger break-points.\n" " @G--" GTEST_FLAG_PREFIX_ "throw_on_failure@D\n" -" Turn assertion failures into C++ exceptions.\n" +" Turn assertion failures into C++ exceptions for use by an external\n" +" test framework.\n" " @G--" GTEST_FLAG_PREFIX_ "catch_exceptions=0@D\n" " Do not report exceptions as test failures. Instead, allow them\n" " to crash the program or throw a pop-up (on Windows).\n" @@ -5219,7 +5939,7 @@ static const char kColorEncodedHelpMessage[] = "(not one in your own code or tests), please report it to\n" "@G<" GTEST_DEV_EMAIL_ ">@D.\n"; -bool ParseGoogleTestFlag(const char* const arg) { +static bool ParseGoogleTestFlag(const char* const arg) { return ParseBoolFlag(arg, kAlsoRunDisabledTestsFlag, >EST_FLAG(also_run_disabled_tests)) || ParseBoolFlag(arg, kBreakOnFailureFlag, @@ -5237,6 +5957,7 @@ bool ParseGoogleTestFlag(const char* const arg) { ParseBoolFlag(arg, kListTestsFlag, >EST_FLAG(list_tests)) || ParseStringFlag(arg, kOutputFlag, >EST_FLAG(output)) || ParseBoolFlag(arg, kPrintTimeFlag, >EST_FLAG(print_time)) || + ParseBoolFlag(arg, kPrintUTF8Flag, >EST_FLAG(print_utf8)) || ParseInt32Flag(arg, kRandomSeedFlag, >EST_FLAG(random_seed)) || ParseInt32Flag(arg, kRepeatFlag, >EST_FLAG(repeat)) || ParseBoolFlag(arg, kShuffleFlag, >EST_FLAG(shuffle)) || @@ -5249,14 +5970,11 @@ bool ParseGoogleTestFlag(const char* const arg) { } #if GTEST_USE_OWN_FLAGFILE_FLAG_ -void LoadFlagsFromFile(const std::string& path) { +static void LoadFlagsFromFile(const std::string& path) { FILE* flagfile = posix::FOpen(path.c_str(), "r"); if (!flagfile) { - fprintf(stderr, - "Unable to open file \"%s\"\n", - GTEST_FLAG(flagfile).c_str()); - fflush(stderr); - exit(EXIT_FAILURE); + GTEST_LOG_(FATAL) << "Unable to open file \"" << GTEST_FLAG(flagfile) + << "\""; } std::string contents(ReadEntireFile(flagfile)); posix::FClose(flagfile); @@ -5330,6 +6048,17 @@ void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) { // other parts of Google Test. void ParseGoogleTestFlagsOnly(int* argc, char** argv) { ParseGoogleTestFlagsOnlyImpl(argc, argv); + + // Fix the value of *_NSGetArgc() on macOS, but if and only if + // *_NSGetArgv() == argv + // Only applicable to char** version of argv +#if GTEST_OS_MAC +#ifndef GTEST_OS_IOS + if (*_NSGetArgv() == argv) { + *_NSGetArgc() = *argc; + } +#endif +#endif } void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv) { ParseGoogleTestFlagsOnlyImpl(argc, argv); @@ -5351,6 +6080,10 @@ void InitGoogleTestImpl(int* argc, CharType** argv) { g_argvs.push_back(StreamableToString(argv[i])); } +#if GTEST_HAS_ABSL + absl::InitializeSymbolizer(g_argvs[0].c_str()); +#endif // GTEST_HAS_ABSL + ParseGoogleTestFlagsOnly(argc, argv); GetUnitTestImpl()->PostFlagParsingInit(); } @@ -5384,15 +6117,32 @@ void InitGoogleTest(int* argc, wchar_t** argv) { #endif // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_) } +// This overloaded version can be used on Arduino/embedded platforms where +// there is no argc/argv. +void InitGoogleTest() { + // Since Arduino doesn't have a command line, fake out the argc/argv arguments + int argc = 1; + const auto arg0 = "dummy"; + char* argv0 = const_cast(arg0); + char** argv = &argv0; + +#if defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_) + GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_(&argc, argv); +#else // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_) + internal::InitGoogleTestImpl(&argc, argv); +#endif // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_) +} + std::string TempDir() { #if defined(GTEST_CUSTOM_TEMPDIR_FUNCTION_) - return GTEST_CUSTOM_TEMPDIR_FUNCTION_(); + return GTEST_CUSTOM_TEMPDIR_FUNCTION_(); #endif + #if GTEST_OS_WINDOWS_MOBILE return "\\temp\\"; #elif GTEST_OS_WINDOWS const char* temp_dir = internal::posix::GetEnv("TEMP"); - if (temp_dir == NULL || temp_dir[0] == '\0') + if (temp_dir == nullptr || temp_dir[0] == '\0') return "\\temp\\"; else if (temp_dir[strlen(temp_dir) - 1] == '\\') return temp_dir; @@ -5405,4 +6155,23 @@ std::string TempDir() { #endif // GTEST_OS_WINDOWS_MOBILE } +// Class ScopedTrace + +// Pushes the given source file location and message onto a per-thread +// trace stack maintained by Google Test. +void ScopedTrace::PushTrace(const char* file, int line, std::string message) { + internal::TraceInfo trace; + trace.file = file; + trace.line = line; + trace.message.swap(message); + + UnitTest::GetInstance()->PushGTestTrace(trace); +} + +// Pops the info pushed by the c'tor. +ScopedTrace::~ScopedTrace() + GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) { + UnitTest::GetInstance()->PopGTestTrace(); +} + } // namespace testing diff --git a/cpp/test/src/gtest_main.cc b/cpp/test/src/gtest_main.cc index 4cf03e59ba..46b27c3d7d 100644 --- a/cpp/test/src/gtest_main.cc +++ b/cpp/test/src/gtest_main.cc @@ -27,11 +27,28 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include - +#include #include "gtest/gtest.h" +#if GTEST_OS_ESP8266 || GTEST_OS_ESP32 +#if GTEST_OS_ESP8266 +extern "C" { +#endif +void setup() { + testing::InitGoogleTest(); +} + +void loop() { RUN_ALL_TESTS(); } + +#if GTEST_OS_ESP8266 +} +#endif + +#else + GTEST_API_ int main(int argc, char **argv) { + printf("Running main() from %s\n", __FILE__); testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } +#endif diff --git a/dist/openzwave.spec b/dist/openzwave.spec index 1c169bf5dc..d08afb77e5 100644 --- a/dist/openzwave.spec +++ b/dist/openzwave.spec @@ -3,7 +3,7 @@ %endif Name: openzwave -Version: 1.6.160 +Version: 1.6.969 Release: 1.0%{?dist} Summary: Sample Executables for OpenZWave URL: http://www.openzwave.net @@ -74,7 +74,7 @@ applications using openzwave major_ver=$(echo %{version} | awk -F \. {'print $1'}) minor_ver=$(echo %{version} | awk -F \. {'print $2'}) revision=$(echo %{version} | awk -F \. {'print $3'}) -CPPFLAGS="%{optflags} -Wformat -DOPENZWAVE_ENABLE_EXCEPTIONS" LDFLAGS="%{__global_ldflags}" USE_HID=0 USE_BI_TXML=0 VERSION_MAJ=$major_ver VERSION_MIN=$minor_ver VERSION_REV=$revision PREFIX=/usr sysconfdir=%{_sysconfdir}/openzwave/ includedir=%{_includedir} docdir=%{_defaultdocdir}/openzwave-%{version} instlibdir=%{_libdir} make %{?_smp_mflags} +CPPFLAGS="%{optflags} -Wformat" LDFLAGS="%{__global_ldflags}" USE_HID=0 USE_BI_TXML=0 VERSION_MAJ=$major_ver VERSION_MIN=$minor_ver VERSION_REV=$revision PREFIX=/usr sysconfdir=%{_sysconfdir}/openzwave/ includedir=%{_includedir} docdir=%{_defaultdocdir}/openzwave-%{version} instlibdir=%{_libdir} make %{?_smp_mflags} %install @@ -89,6 +89,7 @@ mkdir -p %{buildroot}/%{_sysconfdir}/ mkdir -p %{buildroot}/%{_includedir}/openzwave/ DESTDIR=%{buildroot} USE_HID=0 USE_BI_TXML=0 VERSION_MAJ=$major_ver VERSION_MIN=$minor_ver VERSION_REV=$revision PREFIX=/usr sysconfdir=%{_sysconfdir}/openzwave/ includedir=%{_includedir}/openzwave/ docdir=%{_defaultdocdir}/openzwave-%{version} instlibdir=%{_libdir} make install rm %{buildroot}%{_defaultdocdir}/openzwave-%{version}/Doxyfile.in +rm -rf %{buildroot}%{_defaultdocdir}/openzwave-%{version}/ChangeLog.old rm -rf %{buildroot}%{_defaultdocdir}/openzwave-%{version}/html/ rm -rf %{buildroot}%{_defaultdocdir}/openzwave-%{version}/default.htm rm -rf %{buildroot}%{_defaultdocdir}/openzwave-%{version}/general/ @@ -101,7 +102,7 @@ rm -rf %{buildroot}%{_defaultdocdir}/openzwave-%{version}/api/ %files -n libopenzwave -%license license/*.txt +%license LICENSE %doc docs/default.htm docs/general/ docs/images+css/ %{_libdir}/libopenzwave.so.* %defattr(664, root, zwave, 775) @@ -134,7 +135,7 @@ getent group zwave >/dev/null || groupadd -f -r zwave %changelog -* Wed May 08 2019 Justin Hammond - 1.6.160 +* Wed May 08 2019 Justin Hammond - 1.6.969 - Update to new release of OpenZwave - 1.6 * Fri Feb 01 2019 Fedora Release Engineering - 1.5.0-0.20180624git1e36dcc.0 diff --git a/dist/openzwave.spec.in b/dist/openzwave.spec.in index a980cbd1bd..d5ec624216 100644 --- a/dist/openzwave.spec.in +++ b/dist/openzwave.spec.in @@ -74,7 +74,7 @@ applications using openzwave major_ver=$(echo %{version} | awk -F \. {'print $1'}) minor_ver=$(echo %{version} | awk -F \. {'print $2'}) revision=$(echo %{version} | awk -F \. {'print $3'}) -CPPFLAGS="%{optflags} -Wformat -DOPENZWAVE_ENABLE_EXCEPTIONS" LDFLAGS="%{__global_ldflags}" USE_HID=0 USE_BI_TXML=0 VERSION_MAJ=$major_ver VERSION_MIN=$minor_ver VERSION_REV=$revision PREFIX=/usr sysconfdir=%{_sysconfdir}/openzwave/ includedir=%{_includedir} docdir=%{_defaultdocdir}/openzwave-%{version} instlibdir=%{_libdir} make %{?_smp_mflags} +CPPFLAGS="%{optflags} -Wformat" LDFLAGS="%{__global_ldflags}" USE_HID=0 USE_BI_TXML=0 VERSION_MAJ=$major_ver VERSION_MIN=$minor_ver VERSION_REV=$revision PREFIX=/usr sysconfdir=%{_sysconfdir}/openzwave/ includedir=%{_includedir} docdir=%{_defaultdocdir}/openzwave-%{version} instlibdir=%{_libdir} make %{?_smp_mflags} %install @@ -89,6 +89,7 @@ mkdir -p %{buildroot}/%{_sysconfdir}/ mkdir -p %{buildroot}/%{_includedir}/openzwave/ DESTDIR=%{buildroot} USE_HID=0 USE_BI_TXML=0 VERSION_MAJ=$major_ver VERSION_MIN=$minor_ver VERSION_REV=$revision PREFIX=/usr sysconfdir=%{_sysconfdir}/openzwave/ includedir=%{_includedir}/openzwave/ docdir=%{_defaultdocdir}/openzwave-%{version} instlibdir=%{_libdir} make install rm %{buildroot}%{_defaultdocdir}/openzwave-%{version}/Doxyfile.in +rm -rf %{buildroot}%{_defaultdocdir}/openzwave-%{version}/ChangeLog.old rm -rf %{buildroot}%{_defaultdocdir}/openzwave-%{version}/html/ rm -rf %{buildroot}%{_defaultdocdir}/openzwave-%{version}/default.htm rm -rf %{buildroot}%{_defaultdocdir}/openzwave-%{version}/general/ @@ -101,7 +102,7 @@ rm -rf %{buildroot}%{_defaultdocdir}/openzwave-%{version}/api/ %files -n libopenzwave -%license license/*.txt +%license LICENSE %doc docs/default.htm docs/general/ docs/images+css/ %{_libdir}/libopenzwave.so.* %defattr(664, root, zwave, 775) diff --git a/distfiles.mk b/distfiles.mk index 48185af02b..825baeac4d 100644 --- a/distfiles.mk +++ b/distfiles.mk @@ -3,8 +3,8 @@ DISTFILES = .gitignore \ BSDmakefile \ - ChangeLog \ INSTALL \ + LICENSE \ Makefile \ README.md \ config/2gig/ct100.xml \ @@ -34,6 +34,8 @@ DISTFILES = .gitignore \ config/Localization.xsd \ config/NotificationCCTypes.xml \ config/NotificationCCTypes.xsd \ + config/SensorMultiLevelCCTypes.xml \ + config/SensorMultiLevelCCTypes.xsd \ config/act/lfm20.xml \ config/act/zdm230.xml \ config/act/zdp100.xml \ @@ -99,6 +101,10 @@ DISTFILES = .gitignore \ config/aeotec/zw140.xml \ config/aeotec/zw141.xml \ config/aeotec/zw162.xml \ + config/aeotec/zw164.xml \ + config/aeotec/zw175.xml \ + config/aeotec/zw187.xml \ + config/aeotec/zw189.xml \ config/aeotec/zwa001.xml \ config/aeotec/zwa002.xml \ config/aeotec/zwa003.xml \ @@ -107,6 +113,7 @@ DISTFILES = .gitignore \ config/aeotec/zwa006.xml \ config/aeotec/zwa008.xml \ config/airlinemechanical/zds-ud10.xml \ + config/alfred/DB2.xml \ config/assa_abloy/ConexisL1.xml \ config/assa_abloy/KeyfreeConnected-plus.xml \ config/assa_abloy/KeyfreeConnected.xml \ @@ -118,6 +125,7 @@ DISTFILES = .gitignore \ config/august/asl-03.xml \ config/buffalo/hw-100v15a-zw.xml \ config/comfort/ucm.xml \ + config/config-template.xml \ config/cooper/RF9501.xml \ config/cooper/RF9505-T.xml \ config/cooper/RF9505-T.xml.zip \ @@ -176,6 +184,7 @@ DISTFILES = .gitignore \ config/duwi/zwws.xml \ config/ecolink/doorwindow.xml \ config/ecolink/firefighter.xml \ + config/ecolink/floodfreeze.xml \ config/ecolink/motion.xml \ config/ecolink/sensor.xml \ config/ecolink/tiltsensor.xml \ @@ -256,9 +265,13 @@ DISTFILES = .gitignore \ config/fibaro/fgsd002.xml \ config/fibaro/fgss101.xml \ config/fibaro/fgt001.xml \ + config/fibaro/fgwd111.xml \ + config/fibaro/fgwds221.xml \ + config/fibaro/fgwoe.xml \ config/fibaro/fgwpe.xml \ config/fibaro/fgwpfzw5.xml \ config/fibaro/fgwpg111.xml \ + config/fibaro/fgwr111.xml \ config/firstalert/zcombo.xml \ config/followgood/swz-1002.xml \ config/forest/fs2z5232000002.xml \ @@ -277,6 +290,7 @@ DISTFILES = .gitignore \ config/ge/12724-dimmer.xml \ config/ge/12727.xml \ config/ge/14282-plugin-switch.xml \ + config/ge/14284.xml \ config/ge/14288-outlet.xml \ config/ge/14291-switch.xml \ config/ge/14292-toggle-switch.xml \ @@ -287,6 +301,7 @@ DISTFILES = .gitignore \ config/ge/28167-plugin-dimmer.xml \ config/ge/28169-plugin-switch.xml \ config/ge/45604.xml \ + config/ge/46201-switch.xml \ config/ge/dimmer.xml \ config/ge/dimmer_module.xml \ config/ge/hinge-pin.xml \ @@ -296,14 +311,18 @@ DISTFILES = .gitignore \ config/ge/zw4001-switch.xml \ config/ge/zw6302.xml \ config/gocontrol/GC-TBZ48L.xml \ + config/gr/gr-302n.xml \ config/gr/gr105.xml \ config/gr/gr105n.xml \ config/gr/grb3.xml \ config/graber/brz1.xml \ + config/graber/csz1.xml \ + config/graber/rsz1.xml \ config/graber/vcz1.xml \ config/greenwave/gs1110-1-gr-1.xml \ config/greenwave/powernode1.xml \ config/greenwave/powernode6.xml \ + config/guardtec/gkw2000d.xml \ config/hank/hkzw-dws01.xml \ config/hank/hkzw-fld01.xml \ config/hank/hkzw-ms01.xml \ @@ -324,8 +343,11 @@ DISTFILES = .gitignore \ config/heiman/HS1WL-Z.xml \ config/heiman/HS2SK-Z.xml \ config/heiman/HS2WD-Z.xml \ + config/heltun/he-zw-sw-5a-1.xml \ + config/heltun/he-zw-therm-fc1.xml \ config/heltun/he-zw-therm-fl2.xml \ config/homeseer/ezmotionplus.xml \ + config/homeseer/hs-ds100plus.xml \ config/homeseer/hs-fc200plus.xml \ config/homeseer/hs-fls100plus.xml \ config/homeseer/hs-fs100plus.xml \ @@ -358,9 +380,11 @@ DISTFILES = .gitignore \ config/idlock/idlock150.xml \ config/images/2gig/ct100.png \ config/images/2gig/ct32.png \ + config/images/BeNext/AlarmSound.png \ config/images/BeNext/DoorSensor.png \ config/images/BeNext/Molite.png \ config/images/BeNext/TagReader.png \ + config/images/BeNext/TagReader500.png \ config/images/BeNext/mydisplay.png \ config/images/BeNext/mygate.png \ config/images/act/lfm20.png \ @@ -382,11 +406,13 @@ DISTFILES = .gitignore \ config/images/aeotec/dsc06106.png \ config/images/aeotec/dsc10.png \ config/images/aeotec/dsc11.png \ + config/images/aeotec/dsc14104.png \ config/images/aeotec/dsc18103.png \ config/images/aeotec/dsc19103.png \ config/images/aeotec/dsc24.png \ config/images/aeotec/dsc26103.png \ config/images/aeotec/dsc27103.png \ + config/images/aeotec/dsc35103.png \ config/images/aeotec/dsd37.png \ config/images/aeotec/zw056.png \ config/images/aeotec/zw062.png \ @@ -401,12 +427,42 @@ DISTFILES = .gitignore \ config/images/aeotec/zw096.png \ config/images/aeotec/zw097.png \ config/images/aeotec/zw098.png \ + config/images/aeotec/zw099.png \ config/images/aeotec/zw100.png \ + config/images/aeotec/zw111.png \ + config/images/aeotec/zw112.png \ + config/images/aeotec/zw116.png \ + config/images/aeotec/zw117.png \ + config/images/aeotec/zw120.png \ + config/images/aeotec/zw121.png \ + config/images/aeotec/zw122.png \ + config/images/aeotec/zw129.png \ + config/images/aeotec/zw130.png \ + config/images/aeotec/zw132.png \ + config/images/aeotec/zw139.png \ + config/images/aeotec/zw140.png \ + config/images/aeotec/zw141.png \ + config/images/aeotec/zw162.png \ + config/images/aeotec/zw164.png \ + config/images/aeotec/zw187.png \ + config/images/aeotec/zw189.png \ + config/images/aeotec/zw195.png \ + config/images/aeotec/zwa001.png \ + config/images/aeotec/zwa002.png \ + config/images/aeotec/zwa003.png \ + config/images/aeotec/zwa004.png \ + config/images/aeotec/zwa005.png \ + config/images/aeotec/zwa006.png \ config/images/airlinemechanical/zds-ud10.png \ + config/images/alfred/DB2.png \ + config/images/assa_abloy/ConexisL1.png \ + config/images/assa_abloy/KeyfreeConnected-plus.png \ config/images/assa_abloy/KeyfreeConnected.png \ config/images/assa_abloy/PushButtonDeadbolt.png \ config/images/assa_abloy/TouchDeadbolt.png \ config/images/assa_abloy/TouchLever.png \ + config/images/assa_abloy/nexTouch.png \ + config/images/august/asl-03.png \ config/images/buffalo/hw-100v15a-zw.png \ config/images/comfort/ucm.png \ config/images/cooper/RF9501.png \ @@ -419,25 +475,43 @@ DISTFILES = .gitignore \ config/images/danfoss/rsroom.png \ config/images/danfoss/z.png \ config/images/devolo/mt02648.png \ + config/images/devolo/mt02755.png \ + config/images/devolo/mt02758.png \ config/images/devolo/mt2646.png \ config/images/devolo/mt2647.png \ config/images/devolo/mt2652.png \ + config/images/devolo/mt2756.png \ config/images/diehlcontrols/766366.png \ config/images/dlink/dch-z110.png \ config/images/dlink/dch-z120.png \ config/images/dlink/dch-z510.png \ + config/images/dome/0002.png \ + config/images/dome/0085.png \ + config/images/dome/0086.png \ + config/images/dome/0088.png \ + config/images/dome/0201.png \ + config/images/domitech/zb22uk.png \ + config/images/domitech/ze27eu.png \ config/images/dragontech/wd-100.png \ config/images/duwi/ZWES1000.png \ config/images/duwi/zw-edan-300.png \ config/images/duwi/zw-zdan-300.png \ config/images/duwi/zwws.png \ config/images/ecolink/doorwindow.png \ + config/images/ecolink/firefighter.png \ + config/images/ecolink/floodfreeze.png \ config/images/ecolink/motion.png \ config/images/ecolink/sensor.png \ config/images/ecolink/tiltsensor.png \ config/images/electronicsolutions/dbmz.png \ config/images/enblink/ss201-us-w_1308.png \ + config/images/enerwave/zw15rmplus.png \ config/images/enerwave/zw20r.png \ + config/images/enerwave/zw20rm.png \ + config/images/enerwave/zwn-bpc.png \ + config/images/enerwave/zwnrsm1plus.png \ + config/images/eurotronic/eur_cometz.png \ + config/images/eurotronic/eur_spiritz.png \ config/images/eurotronic/eur_stellaz.png \ config/images/everspring/ad146.png \ config/images/everspring/ad147.png \ @@ -458,6 +532,8 @@ DISTFILES = .gitignore \ config/images/everspring/sm103.png \ config/images/everspring/sp103.png \ config/images/everspring/sp814.png \ + config/images/everspring/sp815.png \ + config/images/everspring/sp816.png \ config/images/everspring/st812.png \ config/images/everspring/st814.png \ config/images/everspring/st815.png \ @@ -466,18 +542,37 @@ DISTFILES = .gitignore \ config/images/evolve/ltm-5.png \ config/images/fakro/arz.png \ config/images/fakro/zws12.png \ + config/images/fibaro/fgbs222.png \ + config/images/fibaro/fgcd001.png \ config/images/fibaro/fgd212.png \ + config/images/fibaro/fgdw2.png \ config/images/fibaro/fgfs101zw5.png \ + config/images/fibaro/fggc001.png \ config/images/fibaro/fgk001.png \ + config/images/fibaro/fgk10x.png \ + config/images/fibaro/fgkf601.png \ config/images/fibaro/fgms.png \ config/images/fibaro/fgmszw5.png \ + config/images/fibaro/fgpb101.png \ + config/images/fibaro/fgr223.png \ config/images/fibaro/fgrgbwm441.png \ + config/images/fibaro/fgs213.png \ + config/images/fibaro/fgs223.png \ config/images/fibaro/fgsd002.png \ + config/images/fibaro/fgt001.png \ + config/images/fibaro/fgwd111.png \ + config/images/fibaro/fgwoe.png \ config/images/fibaro/fgwpe.png \ + config/images/fibaro/fgwpfzw5.png \ + config/images/fibaro/fgwpg111.png \ + config/images/fibaro/fgwr111.png \ config/images/firstalert/zcombo.png \ config/images/followgood/swz-1002.png \ config/images/forest/fs2z5232000002.png \ + config/images/fortrezz/fmi.png \ config/images/fortrezz/gdc1_fortrezz_1501.png \ + config/images/fortrezz/mimo2plus.png \ + config/images/fortrezz/mimolite.png \ config/images/fortrezz/ssa2.png \ config/images/fortrezz/ssa3.png \ config/images/fortrezz/wv01.png \ @@ -488,21 +583,67 @@ DISTFILES = .gitignore \ config/images/ge/12724-dimmer.png \ config/images/ge/12727.png \ config/images/ge/14282-plugin-switch.png \ + config/images/ge/14284.png \ + config/images/ge/14288-outlet.png \ config/images/ge/14291-switch.png \ + config/images/ge/14292-toggle-switch.png \ config/images/ge/14294-dimmer.png \ + config/images/ge/14295-dimmer-toggle.png \ + config/images/ge/26931-motion-switch.png \ + config/images/ge/26933-motion-dimmer.png \ config/images/ge/28167-plugin-dimmer.png \ config/images/ge/28169-plugin-switch.png \ config/images/ge/45604.png \ + config/images/ge/46201-switch.png \ config/images/ge/dimmer.png \ config/images/ge/dimmer_module.png \ + config/images/ge/hinge-pin.png \ config/images/ge/receptacle.png \ config/images/ge/relay.png \ + config/images/ge/ze26i.png \ + config/images/ge/zw6302.png \ + config/images/gr/gr-302n.png \ config/images/gr/gr105.png \ + config/images/gr/gr105n.png \ + config/images/graber/brz1.png \ + config/images/graber/csz1.png \ + config/images/graber/rsz1.png \ + config/images/graber/vcz1.png \ config/images/greenwave/gs1110-1-gr-1.png \ config/images/greenwave/powernode1.png \ config/images/greenwave/powernode6.png \ + config/images/guardtec/gkw2000d.png \ + config/images/hank/hkzw-dws01.png \ + config/images/hank/hkzw-fld01.png \ + config/images/hank/hkzw-ms01.png \ + config/images/hank/hkzw-ms02-200.png \ + config/images/hank/hkzw-rgb01.png \ + config/images/hank/hkzw-so01-smartplug.png \ + config/images/hank/hkzw-so03.png \ + config/images/hank/hkzw-so05-smartplug.png \ + config/images/hank/scenecontroller1.png \ + config/images/hank/scenecontroller4.png \ + config/images/heiman/HS1CA-Z.png \ + config/images/heiman/HS1CG-Z.png \ + config/images/heiman/HS1DS-Z.png \ + config/images/heiman/HS1HT-Z.png \ + config/images/heiman/HS1MS-Z.png \ + config/images/heiman/HS1SA-Z.png \ + config/images/heiman/HS1WL-Z.png \ + config/images/heiman/HS2SK-Z.png \ + config/images/homeseer/hs-ds100plus.png \ + config/images/homeseer/hs-fc200plus.png \ + config/images/homeseer/hs-fls100plus.png \ + config/images/homeseer/hs-ls100plus.png \ + config/images/homeseer/hs-ms100plus.png \ + config/images/homeseer/hs-wd100plus.png \ + config/images/homeseer/hs-wd200plus.png \ + config/images/homeseer/hs-ws100plus.png \ + config/images/homeseer/hs-ws200plus.png \ config/images/homeseer/hsm200.png \ + config/images/honeywell/39351-ZW3005.png \ config/images/honeywell/lynx-touch-l5100.png \ + config/images/honeywell/th6320zw2003.png \ config/images/honeywell/th8320zw1000.png \ config/images/horstmann/asrzw.png \ config/images/horstmann/hrt4zw.png \ @@ -511,20 +652,37 @@ DISTFILES = .gitignore \ config/images/horstmann/ses302.png \ config/images/horstmann/ses303.png \ config/images/horstmann/sir321.png \ + config/images/horstmann/srt321.png \ config/images/horstmann/srt323.png \ config/images/horstmann/ssr302.png \ + config/images/horstmann/ssr303.png \ config/images/icare/zw-66.png \ + config/images/idlock/idlock101.png \ + config/images/idlock/idlock150.png \ config/images/ingersoll/dwzwave1.png \ + config/images/inovelli/lzw30-sn.png \ + config/images/inovelli/lzw30.png \ + config/images/inovelli/simple_module.png \ config/images/iwatsu/ne-4ct-2p.png \ config/images/iwatsu/ne-4ct.png \ config/images/jasco/45601.png \ + config/images/kaipule/im20.png \ config/images/kwikset/smartcode.png \ + config/images/leviton/dz15s.png \ + config/images/leviton/dz6hd.png \ + config/images/leviton/dzpd3.png \ config/images/leviton/vrcs2.png \ config/images/leviton/vrf01.png \ config/images/leviton/vri10.png \ config/images/leviton/vrs15.png \ config/images/linear/LB60Z-1.png \ + config/images/linear/WD500Z5-1.png \ + config/images/linear/gd00z-7.png \ config/images/linear/ngd00z.png \ + config/images/logicsoft/ZHC5010.png \ + config/images/mcohome/mh7h.png \ + config/images/mcohome/mhp220.png \ + config/images/mcohome/mhp511.png \ config/images/merten/5044xx.png \ config/images/merten/5046xx.png \ config/images/merten/506004.png \ @@ -535,45 +693,107 @@ DISTFILES = .gitignore \ config/images/nodon/crc3100OctanRemote.png \ config/images/nodon/crc360xSofremote.png \ config/images/nodon/cws3101wallswitch.png \ + config/images/nodon/msp31xxMicroSmartPlug.png \ config/images/northq/nq92021.png \ + config/images/oomi/ft100.png \ + config/images/oomi/ft111.png \ + config/images/permundo/psc132zw.png \ + config/images/permundo/psc234zw.png \ + config/images/philio/pad02.png \ config/images/philio/pan04.png \ config/images/philio/pan05.png \ config/images/philio/pan06.png \ config/images/philio/pan08.png \ config/images/philio/pan11-1.png \ config/images/philio/pan11.png \ + config/images/philio/pan16.png \ + config/images/philio/phpab01.png \ config/images/philio/phpat02.png \ config/images/philio/phpsg01.png \ + config/images/philio/pse02.png \ config/images/philio/psm02.png \ + config/images/philio/psp05.png \ config/images/philio/psr03-1b.png \ config/images/philio/psr04.png \ config/images/philio/pst02-1c.png \ config/images/philio/pst02-b.png \ config/images/philio/pst02.png \ config/images/polycontrol/doorlock.png \ + config/images/polycontrol/doorlockv3.png \ + config/images/popp/004407.png \ + config/images/popp/009303.png \ + config/images/popp/009402.png \ + config/images/popp/012501.png \ + config/images/popp/700045.png \ + config/images/popp/700168.png \ + config/images/popp/700397.png \ + config/images/popp/dwt.png \ + config/images/popp/smoke-detector.png \ + config/images/popp/solar-siren.png \ + config/images/popp/zweather.png \ config/images/prowell/zw-702.png \ config/images/qees/reto-dimmer-plus.png \ config/images/qees/reto-plugin-switch.png \ + config/images/qubino/ZMNHADx.png \ + config/images/qubino/ZMNHBDx.png \ + config/images/qubino/ZMNHCDx.png \ config/images/qubino/ZMNHDA2.png \ + config/images/qubino/ZMNHDDx.png \ + config/images/qubino/ZMNHIDx.png \ config/images/qubino/ZMNHNDx.png \ + config/images/qubino/ZMNHODx.png \ + config/images/qubino/ZMNHSDx.png \ + config/images/qubino/ZMNHTDx.png \ + config/images/qubino/ZMNHVDx.png \ + config/images/qubino/ZMNHWD1.png \ + config/images/qubino/ZMNHYDx.png \ + config/images/qubino/zmnhxdx.png \ config/images/quby/qb2.png \ config/images/rcs/em52-zw.png \ config/images/rcs/therm0009.png \ config/images/remotec/bw8120eu.png \ config/images/remotec/zfm-80.png \ + config/images/remotec/zrc-100eu.png \ + config/images/remotec/zrc-90.png \ config/images/remotec/zts-110.png \ + config/images/remotec/zts-500.png \ config/images/remotec/zurc.png \ config/images/remotec/zxt-120.png \ + config/images/remotec/zxt-310.png \ + config/images/remotec/zxt-600.png \ + config/images/schlage/BE468ZP.png \ config/images/schlage/BE469.png \ + config/images/schlage/BE469ZP.png \ config/images/schlage/fe599.png \ config/images/schlagelink/41.png \ + config/images/sensative/strips.png \ + config/images/sensative/stripscomfort.png \ config/images/sercomm/sw-clp01-eu.png \ + config/images/shenzen_neo/nas-ab01z.png \ + config/images/shenzen_neo/nas-ds01z.png \ + config/images/shenzen_neo/nas-pd01z.png \ + config/images/shenzen_neo/nas-wr01z.png \ + config/images/shenzen_neo/nas-ws02z.png \ + config/images/simon/10002034-13X.png \ config/images/smartthings/pgc401m.png \ config/images/smartthings/sth-eth200.png \ + config/images/steinel/is140-2.png \ + config/images/steinel/l810-led-ihf.png \ + config/images/steinel/rs-led-d2.png \ + config/images/steinel/xled-home-2.png \ + config/images/stelpro/stzw402.png \ + config/images/sunricher/srzv9001k8.png \ + config/images/sunricher/srzv9001t4dimeu.png \ + config/images/sunricher/srzv9003t4rgbweu.png \ + config/images/sunricher/srzv9101sachpeu.png \ + config/images/sunricher/zv9101.png \ config/images/swiid/swiidinter.png \ config/images/telldus/tzdw100.png \ + config/images/telldus/tzwp100.png \ + config/images/telldus/tzwp102.png \ config/images/there/800z.png \ config/images/thermofloor/heatit021.png \ + config/images/thermofloor/heatit056.png \ config/images/trane/TZEMT400AB32MAA.png \ config/images/trane/TZEMT400BB32MAA.png \ config/images/trane/TZEMT524AA21MA.png \ @@ -581,12 +801,18 @@ DISTFILES = .gitignore \ config/images/vision/1701.png \ config/images/vision/brg1-433.png \ config/images/vision/zd2102.png \ + config/images/vision/zd2105us5.png \ + config/images/vision/zd2201.png \ config/images/vision/zd2301.png \ config/images/vision/zl7101us.png \ config/images/vision/zl7201us.png \ + config/images/vision/zl7431.png \ + config/images/vision/zl7432us.png \ config/images/vision/zm1601eu.png \ config/images/vision/zm1601eu5.png \ + config/images/vision/zm1602eu5.png \ config/images/vision/zp3102.png \ + config/images/vision/zp3111.png \ config/images/vision/zr1202us.png \ config/images/vision/zs610eu.png \ config/images/vision/zu1401jp.png \ @@ -597,23 +823,55 @@ DISTFILES = .gitignore \ config/images/vitrum/vitrumII-Switch.png \ config/images/wenzhou/tsp01.png \ config/images/wenzhou/tz55.png \ + config/images/wenzhou/tz56.png \ config/images/wenzhou/tz65d.png \ config/images/wenzhou/tz66d.png \ config/images/wenzhou/tz67.png \ config/images/wenzhou/tz68.png \ + config/images/wenzhou/tz69.png \ config/images/wenzhou/tz88.png \ config/images/widom/UBS104.png \ config/images/widom/UME304C_S.png \ + config/images/widom/WDS.png \ + config/images/zipato/HS1CA-Z.png \ + config/images/zipato/HS1CG-Z.png \ + config/images/zipato/HS1SA-Z.png \ + config/images/zipato/HS1WL-Z.png \ config/images/zipato/RGBBulb.png \ + config/images/zipato/pan04.png \ + config/images/zipato/phpab01.png \ + config/images/zipato/pse02.png \ + config/images/zipato/pst02.png \ + config/images/zipato/vszd2102.png \ + config/images/zipato/zd2301.png \ + config/images/zipato/zp3102.png \ + config/images/zooz/zen06.png \ + config/images/zooz/zen15.png \ + config/images/zooz/zen20.png \ + config/images/zooz/zen20v2.png \ + config/images/zooz/zen21.png \ + config/images/zooz/zen22.png \ + config/images/zooz/zen26.png \ + config/images/zooz/zen27.png \ + config/images/zooz/zse09.png \ + config/images/zooz/zse19.png \ + config/images/zooz/zse29.png \ + config/images/zooz/zse30.png \ + config/images/zooz/zse33.png \ + config/images/zooz/zse40.png \ config/images/zwave.me/004001.png \ config/images/zwave.me/ZME_05431.png \ config/images/zwave.me/ZME_06433.png \ config/images/zwave.me/ZME_06436.png \ + config/images/zwave.me/ZUno.png \ config/images/zwave.me/kfob.png \ config/images/zwave.me/popp_kfob-c.png \ config/images/zwave.me/zme_raz5.png \ config/images/zwave.me/zweather.png \ + config/images/zwp/WD-100.png \ config/ingersoll/dwzwave1.xml \ + config/inovelli/lzw30-sn.xml \ + config/inovelli/lzw30.xml \ config/inovelli/nzw1201.xml \ config/inovelli/nzw30.xml \ config/inovelli/nzw31.xml \ @@ -654,6 +912,7 @@ DISTFILES = .gitignore \ config/linear/WD500Z5-1.xml \ config/linear/WS15Z-1.xml \ config/linear/WT00Z-1.xml \ + config/linear/gd00z-7.xml \ config/linear/ngd00z.xml \ config/logicsoft/ZHC5002.xml \ config/logicsoft/ZHC5010.xml \ @@ -664,6 +923,8 @@ DISTFILES = .gitignore \ config/mcohome/mh8fceu.xml \ config/mcohome/mh9co2.xml \ config/mcohome/mhp210.xml \ + config/mcohome/mhp220.xml \ + config/mcohome/mhp511.xml \ config/mcohome/mhs311.xml \ config/mcohome/mhs312.xml \ config/mcohome/mhs314.xml \ @@ -690,6 +951,8 @@ DISTFILES = .gitignore \ config/oomi/ft111.xml \ config/options.xml \ config/options.xsd \ + config/permundo/psc132zw.xml \ + config/permundo/psc234zw.xml \ config/philio/pad02.xml \ config/philio/pan03.xml \ config/philio/pan04.xml \ @@ -728,6 +991,7 @@ DISTFILES = .gitignore \ config/popp/700168.xml \ config/popp/700397.xml \ config/popp/700793.xml \ + config/popp/dwt.xml \ config/popp/smoke-detector.xml \ config/popp/solar-siren.xml \ config/popp/zweather.xml \ @@ -742,6 +1006,7 @@ DISTFILES = .gitignore \ config/qubino/ZMNHCDx.xml \ config/qubino/ZMNHDA2.xml \ config/qubino/ZMNHDDx.xml \ + config/qubino/ZMNHHDx.xml \ config/qubino/ZMNHIA2.xml \ config/qubino/ZMNHIDxS1.xml \ config/qubino/ZMNHIDxS2.xml \ @@ -752,6 +1017,7 @@ DISTFILES = .gitignore \ config/qubino/ZMNHLDx.xml \ config/qubino/ZMNHNDx.xml \ config/qubino/ZMNHODx.xml \ + config/qubino/ZMNHQDx.xml \ config/qubino/ZMNHSDx.xml \ config/qubino/ZMNHTDx.xml \ config/qubino/ZMNHTDxS3.xml \ @@ -770,6 +1036,7 @@ DISTFILES = .gitignore \ config/rcs/therm0009.xml \ config/remotec/bw8120eu.xml \ config/remotec/zfm-80.xml \ + config/remotec/zrc-100eu.xml \ config/remotec/zrc-90.xml \ config/remotec/zts-110.xml \ config/remotec/zts-500.xml \ @@ -778,6 +1045,7 @@ DISTFILES = .gitignore \ config/remotec/zxt-310.xml \ config/remotec/zxt-600.xml \ config/schlage/BE468.xml \ + config/schlage/BE468ZP.xml \ config/schlage/BE469.xml \ config/schlage/BE469ZP.xml \ config/schlage/fe599.xml \ @@ -807,7 +1075,9 @@ DISTFILES = .gitignore \ config/steinel/rs-led-d2.xml \ config/steinel/xled-home-2.xml \ config/stelpro/stzw402.xml \ + config/sunricher/srzv9001k8.xml \ config/sunricher/srzv9001t4dimeu.xml \ + config/sunricher/srzv9003t4rgbweu.xml \ config/sunricher/srzv9101sachpeu.xml \ config/sunricher/zv9101.xml \ config/swiid/swiidinter.xml \ @@ -834,6 +1104,7 @@ DISTFILES = .gitignore \ config/vision/zl7201us.xml \ config/vision/zl7261.xml \ config/vision/zl7431.xml \ + config/vision/zl7432us.xml \ config/vision/zm1601eu.xml \ config/vision/zm1601eu5.xml \ config/vision/zm1602eu.xml \ @@ -846,8 +1117,8 @@ DISTFILES = .gitignore \ config/vision/zu1401jp.xml \ config/vitrum/vitrumI-Dimmer.xml \ config/vitrum/vitrumI-Switch.xml \ - config/vitrum/vitrumII-Blind.xml \ config/vitrum/vitrumII-Dimmer.xml \ + config/vitrum/vitrumII-RollerBlind.xml \ config/vitrum/vitrumII-Switch.xml \ config/vitrum/vitrumIII-Dimmer.xml \ config/vitrum/vitrumIII-Switch.xml \ @@ -868,6 +1139,7 @@ DISTFILES = .gitignore \ config/wenzhou/tz74.xml \ config/wenzhou/tz79.xml \ config/wenzhou/tz88.xml \ + config/widom/DRY.xml \ config/widom/UBS104.xml \ config/widom/UME304C_S.xml \ config/widom/WDS.xml \ @@ -895,6 +1167,7 @@ DISTFILES = .gitignore \ config/zooz/zse09.xml \ config/zooz/zse18.xml \ config/zooz/zse19.xml \ + config/zooz/zse29.xml \ config/zooz/zse30.xml \ config/zooz/zse33.xml \ config/zooz/zse40.xml \ @@ -919,6 +1192,7 @@ DISTFILES = .gitignore \ config/zwp/PA-100.xml \ config/zwp/WD-100.xml \ config/zwscene.xsd \ + cpp/build/LeakSanitizer-Suppressions.txt \ cpp/build/Makefile \ cpp/build/OZW_RunTests.sh \ cpp/build/libopenzwave.pc.in \ @@ -936,8 +1210,6 @@ DISTFILES = .gitignore \ cpp/build/windows/installer/openzwave.nsi \ cpp/build/windows/mingw-w64/Makefile \ cpp/build/windows/mingw32/Makefile \ - cpp/build/windows/vs2008/OpenZWave.sln \ - cpp/build/windows/vs2008/OpenZWave.vcproj \ cpp/build/windows/vs2010/OpenZWave.sln \ cpp/build/windows/vs2010/OpenZWave.vcxproj \ cpp/build/windows/vs2010/OpenZWave.vcxproj.filters \ @@ -946,8 +1218,6 @@ DISTFILES = .gitignore \ cpp/examples/MinOZW/Makefile \ cpp/examples/MinOZW/MinOZW.in \ cpp/examples/windows/MinOZW/Main.cpp \ - cpp/examples/windows/MinOZW/vs2008/MinOZW.sln \ - cpp/examples/windows/MinOZW/vs2008/MinOZW.vcproj \ cpp/examples/windows/MinOZW/vs2010/MinOZW.sln \ cpp/examples/windows/MinOZW/vs2010/MinOZW.vcxproj \ cpp/examples/windows/MinOZW/vs2010/MinOZW.vcxproj.filters \ @@ -1028,10 +1298,15 @@ DISTFILES = .gitignore \ cpp/src/Options.h \ cpp/src/Scene.cpp \ cpp/src/Scene.h \ + cpp/src/SensorMultiLevelCCTypes.cpp \ + cpp/src/SensorMultiLevelCCTypes.h \ cpp/src/TimerThread.cpp \ cpp/src/TimerThread.h \ cpp/src/Utils.cpp \ cpp/src/Utils.h \ + cpp/src/ValueIDIndexes.h \ + cpp/src/ValueIDIndexesDefines.def \ + cpp/src/ValueIDIndexesDefines.h \ cpp/src/ZWSecurity.cpp \ cpp/src/ZWSecurity.h \ cpp/src/aes/aes.h \ @@ -1260,6 +1535,7 @@ DISTFILES = .gitignore \ cpp/src/value_classes/ValueByte.h \ cpp/src/value_classes/ValueDecimal.cpp \ cpp/src/value_classes/ValueDecimal.h \ + cpp/src/value_classes/ValueID.cpp \ cpp/src/value_classes/ValueID.h \ cpp/src/value_classes/ValueInt.cpp \ cpp/src/value_classes/ValueInt.h \ @@ -1278,9 +1554,9 @@ DISTFILES = .gitignore \ cpp/test/Makefile \ cpp/test/ValueID_test.cpp \ cpp/test/include/gtest/gtest-death-test.h \ + cpp/test/include/gtest/gtest-matchers.h \ cpp/test/include/gtest/gtest-message.h \ cpp/test/include/gtest/gtest-param-test.h \ - cpp/test/include/gtest/gtest-param-test.h.pump \ cpp/test/include/gtest/gtest-printers.h \ cpp/test/include/gtest/gtest-spi.h \ cpp/test/include/gtest/gtest-test-part.h \ @@ -1288,26 +1564,22 @@ DISTFILES = .gitignore \ cpp/test/include/gtest/gtest.h \ cpp/test/include/gtest/gtest_pred_impl.h \ cpp/test/include/gtest/gtest_prod.h \ + cpp/test/include/gtest/internal/custom/README.md \ cpp/test/include/gtest/internal/custom/gtest-port.h \ cpp/test/include/gtest/internal/custom/gtest-printers.h \ cpp/test/include/gtest/internal/custom/gtest.h \ cpp/test/include/gtest/internal/gtest-death-test-internal.h \ cpp/test/include/gtest/internal/gtest-filepath.h \ cpp/test/include/gtest/internal/gtest-internal.h \ - cpp/test/include/gtest/internal/gtest-linked_ptr.h \ - cpp/test/include/gtest/internal/gtest-param-util-generated.h \ - cpp/test/include/gtest/internal/gtest-param-util-generated.h.pump \ cpp/test/include/gtest/internal/gtest-param-util.h \ cpp/test/include/gtest/internal/gtest-port-arch.h \ cpp/test/include/gtest/internal/gtest-port.h \ cpp/test/include/gtest/internal/gtest-string.h \ - cpp/test/include/gtest/internal/gtest-tuple.h \ - cpp/test/include/gtest/internal/gtest-tuple.h.pump \ cpp/test/include/gtest/internal/gtest-type-util.h \ - cpp/test/include/gtest/internal/gtest-type-util.h.pump \ cpp/test/src/gtest-death-test.cc \ cpp/test/src/gtest-filepath.cc \ cpp/test/src/gtest-internal-inl.h \ + cpp/test/src/gtest-matchers.cc \ cpp/test/src/gtest-port.cc \ cpp/test/src/gtest-printers.cc \ cpp/test/src/gtest-test-part.cc \ @@ -1350,6 +1622,7 @@ DISTFILES = .gitignore \ dist/openzwave.spec \ dist/openzwave.spec.in \ distfiles.mk \ + docs/ChangeLog.old \ docs/Doxyfile.in \ docs/default.htm \ docs/general/DoxygenStepByStep.html \ @@ -1365,9 +1638,10 @@ DISTFILES = .gitignore \ docs/images+css/OpenZWave.css \ docs/images+css/image003.gif \ docs/images+css/zwalliance_250x100.jpg \ - license/Apache-License-2.0.txt \ - license/gpl.txt \ - license/lgpl.txt \ - license/license.txt \ + licenses/Apache-License-2.0.txt \ + licenses/gpl.txt \ + licenses/lgpl.txt \ + licenses/license.txt \ makedist \ + tools/imagedownload.pl \ cpp/src/vers.cpp diff --git a/ChangeLog b/docs/ChangeLog.old similarity index 100% rename from ChangeLog rename to docs/ChangeLog.old diff --git a/license/Apache-License-2.0.txt b/licenses/Apache-License-2.0.txt similarity index 100% rename from license/Apache-License-2.0.txt rename to licenses/Apache-License-2.0.txt diff --git a/license/gpl.txt b/licenses/gpl.txt similarity index 100% rename from license/gpl.txt rename to licenses/gpl.txt diff --git a/license/lgpl.txt b/licenses/lgpl.txt similarity index 100% rename from license/lgpl.txt rename to licenses/lgpl.txt diff --git a/license/license.txt b/licenses/license.txt similarity index 100% rename from license/license.txt rename to licenses/license.txt diff --git a/tools/imagedownload.pl b/tools/imagedownload.pl new file mode 100755 index 0000000000..51d73006d2 --- /dev/null +++ b/tools/imagedownload.pl @@ -0,0 +1,19 @@ +#!/usr/bin/perl -w + +use Image::Resize; +use File::Fetch; +use POSIX; +use open qw/ :std :encoding(utf-8) /; + +BEGIN { $| = 1; } + +my $imgurl = $ARGV[0]; +print "Downloading $imgurl...."; +my $download = File::Fetch->new(uri => $imgurl); +my $file = $download->fetch() or die $download->error; +File::Copy::move($file, 'productimage.png'); +print "Done\n\nResizing...."; +my $img = Image::Resize->new('productimage.png'); +my $gd = $img->resize(200,200); +$gd->_file('productimage.png'); +print "Done\n\nSaved as productimage.png\n";